aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoen Kooi <k-kooi@ti.com>2009-09-30 10:26:42 +0200
committerKoen Kooi <koen@openembedded.org>2009-10-01 19:48:39 +0200
commit02b1862a3b96784cd8caeb5d86c331fa5bbc2b84 (patch)
tree5590c4f4da9f9923ab5b6a626a719ac662f4bc24
parent6e779f0d529fa60a4a322868766b3bba3832a622 (diff)
downloadopenembedded-02b1862a3b96784cd8caeb5d86c331fa5bbc2b84.tar.gz
omap kernels: sync with .dev
Omap kernels in .dev have seen a big number of improvements, the most notable change being the mem-hole issue being resolved. Like the u-boot change this also adds support for new machines Signed-off-by: Koen Kooi <k-kooi@ti.com> Acked-by: Marcin Juszkiewicz <marcin@juszkiewicz.com.pl> Acked-by: Philip Balister <philip@balister.org>
-rw-r--r--recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch429
-rw-r--r--recipes/linux/files/linux-2.6-limits.patch10
-rw-r--r--recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch287
-rw-r--r--recipes/linux/linux-omap-2.6.29/arch-has-holes.diff235
-rw-r--r--recipes/linux/linux-omap-2.6.29/beagleboard/defconfig361
-rw-r--r--recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-puppy.diff66
-rw-r--r--recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-zippy.diff103
-rw-r--r--recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch35774
-rw-r--r--recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch169
-rw-r--r--recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch115
-rw-r--r--recipes/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch153
-rw-r--r--recipes/linux/linux-omap-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch (renamed from recipes/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch)1163
-rw-r--r--recipes/linux/linux-omap-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch (renamed from recipes/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch)35
-rw-r--r--recipes/linux/linux-omap-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch36
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch677
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch64
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-1.patch35
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-2.patch285
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-3.patch23604
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch40
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch221
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch246
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch53
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch39
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/beagle-asoc.patch35
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/board-omap3beagle.c739
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/boot-no-power-message.patch11
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig2720
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig.orig2701
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch66715
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch20
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-export-status.patch44
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch177
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch52
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/ehci.patch131
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/logo_linux_clut224.ppm773
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/memory-move-malloc-end.patch9
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch11
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight.patch10
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/sound-headphone-detection.patch93
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/tincantools-puppy.diff66
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch87
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch108
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch30
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch36
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3evm/defconfig313
-rw-r--r--recipes/linux/linux-omap-2.6.29/vfp/01-vfp-pm.patch128
-rw-r--r--recipes/linux/linux-omap-2.6.29/vfp/02-vfp-ptrace.patch231
-rw-r--r--recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch136
-rw-r--r--recipes/linux/linux-omap-2.6.29/vfp/04-vfp-threads.patch98
-rw-r--r--recipes/linux/linux-omap-2.6.29/vfp/05-vfp-signal-handlers.patch148
-rwxr-xr-xrecipes/linux/linux-omap-2.6.31/arch-has-holes.diff145
-rw-r--r--recipes/linux/linux-omap-2.6.31/beagleboard/defconfig2806
-rw-r--r--recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch22
-rw-r--r--recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm73147
-rw-r--r--recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch169
-rw-r--r--recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch115
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch69
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch385
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch1151
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch152
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch136
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch40
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch840
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch3248
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch378
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch337
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch2341
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch2856
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch3204
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch410
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch821
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch1332
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch284
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch3531
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch3801
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch471
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch947
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch327
-rw-r--r--recipes/linux/linux-omap-2.6.31/dss2/beagle-dss2-support.patch326
-rw-r--r--recipes/linux/linux-omap-2.6.31/echi.patch0
-rw-r--r--recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch122
-rw-r--r--recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch708
-rw-r--r--recipes/linux/linux-omap-2.6.31/madc/madc.patch56
-rw-r--r--recipes/linux/linux-omap-2.6.31/modedb-hd720.patch13
-rw-r--r--recipes/linux/linux-omap-2.6.31/omapzoom2/defconfig1366
-rw-r--r--recipes/linux/linux-omap-2.6.31/overo/ehci.patch47
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch37
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0001-musb-fix-put_device-call-sequence.patch45
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch41
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch31
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0012-musb-Add-back-old-musb-procfs-file.patch947
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch29
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch34
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch422
-rw-r--r--recipes/linux/linux-omap-2.6.31/usb/0016-usb-update-defconfig.patch618
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/0001-ASoC-Add-support-for-OMAP3-EVM.patch206
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/0001-This-merges-Steve-Kipisz-USB-EHCI-support.-He-star.patch146
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/0001-board-ldp-add-regulator-info-to-get-the-microSD-slo.patch90
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/0124-leds-gpio-broken-with-current-git.patch79
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/ads7846-detection.patch41
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/arch-has-holes.diff235
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig2748
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/beagleboard/ehci.patch131
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/beagleboard/logo_linux_clut224.ppm73147
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-puppy.diff66
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-zippy.diff103
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/cache-display-fix.patch238
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch169
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch115
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch (renamed from recipes/linux/linux-omap-pm/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch (renamed from recipes/linux/linux-omap-pm/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch)0
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch (renamed from recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0004-DSS2-OMAP-framebuffer-driver.patch (renamed from recipes/linux/linux-omap-pm/dss2/0004-DSS2-OMAP-framebuffer-driver.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0005-DSS2-Add-panel-drivers.patch (renamed from recipes/linux/linux-omap-pm/dss2/0005-DSS2-Add-panel-drivers.patch)6
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch (renamed from recipes/linux/linux-omap-pm/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch (renamed from recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch)0
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch (renamed from recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch (renamed from recipes/linux/linux-omap-pm/dss2/0009-DSS2-Add-acx565akm-panel.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch (renamed from recipes/linux/linux-omap-pm/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch (renamed from recipes/linux/linux-omap-pm/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0012-DSS2-Fix-DMA-rotation.patch (renamed from recipes/linux/linux-omap-pm/dss2/0012-DSS2-Fix-DMA-rotation.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch (renamed from recipes/linux/linux-omap-pm/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch (renamed from recipes/linux/linux-omap-pm/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch (renamed from recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch (renamed from recipes/linux/linux-omap-pm/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch (renamed from recipes/linux/linux-omap-pm/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch (renamed from recipes/linux/linux-omap-pm/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch (renamed from recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch (renamed from recipes/linux/linux-omap-pm/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0021-DSS2-Add-venc-register-dump.patch (renamed from recipes/linux/linux-omap-pm/dss2/0021-DSS2-Add-venc-register-dump.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0022-DSS2-FB-remove-unused-var-warning.patch (renamed from recipes/linux/linux-omap-pm/dss2/0022-DSS2-FB-remove-unused-var-warning.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch (renamed from recipes/linux/linux-omap-pm/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch (renamed from recipes/linux/linux-omap-pm/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch (renamed from recipes/linux/linux-omap-pm/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch (renamed from recipes/linux/linux-omap-pm/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch (renamed from recipes/linux/linux-omap-pm/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch (renamed from recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch (renamed from recipes/linux/linux-omap-pm/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch (renamed from recipes/linux/linux-omap-pm/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch (renamed from recipes/linux/linux-omap-pm/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch (renamed from recipes/linux/linux-omap-pm/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0033-DSS2-Prefer-3-tap-filter.patch (renamed from recipes/linux/linux-omap-pm/dss2/0033-DSS2-Prefer-3-tap-filter.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch (renamed from recipes/linux/linux-omap-pm/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch (renamed from recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch (renamed from recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch (renamed from recipes/linux/linux-omap-pm/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch (renamed from recipes/linux/linux-omap-pm/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch (renamed from recipes/linux/linux-omap-pm/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch (renamed from recipes/linux/linux-omap-pm/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch (renamed from recipes/linux/linux-omap-pm/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch (renamed from recipes/linux/linux-omap-pm/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch (renamed from recipes/linux/linux-omap-pm/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch (renamed from recipes/linux/linux-omap-pm/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0045-DSS2-Fixed-line-endings-from-to.patch (renamed from recipes/linux/linux-omap-pm/dss2/0045-DSS2-Fixed-line-endings-from-to.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch (renamed from recipes/linux/linux-omap-pm/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch (renamed from recipes/linux/linux-omap-pm/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch (renamed from recipes/linux/linux-omap-pm/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch (renamed from recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch (renamed from recipes/linux/linux-omap-pm/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch (renamed from recipes/linux/linux-omap-pm/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch (renamed from recipes/linux/linux-omap-pm/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch (renamed from recipes/linux/linux-omap-pm/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch)4
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0054-DSS2-DSI-more-error-handling.patch85
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0055-DSS2-Added-global-alpha-support.patch230
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0056-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0057-DSS2-Documentation-update-for-new-sysfs-entries-in.patch32
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0058-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch56
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0059-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch97
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0060-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch34
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0061-DSS2-VRFB-save-restore-context.patch106
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0062-DSS2-VRAM-Fix-indentation.patch65
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0063-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch82
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0064-VRFB-fix-debug-messages.patch35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0065-VRFB-add-suspend-resume-functionality.patch216
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0066-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch92
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0067-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch29
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0068-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch65
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0069-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch125
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0070-DSS2-fix-irq1.diff221
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/0071-DSS2-fix-irq2.diff35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/dss2/merge-fixups.diff49
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/ehci.patch0
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/evm-mcspi-ts.diff132
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/fix-audio-capture.patch16
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/fix-install.patch23
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/fix-unaligned-access.diff41
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch1226
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch453
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch124
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch1083
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch45
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch26
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch24
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch29
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch4625
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch209
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch696
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch1875
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch3413
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch2741
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch2384
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch4018
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch2249
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch1890
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch729
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch36
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch44
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch50
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch61
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch33
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/make-alignment-visible.diff26
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/mmctiming.patch16
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/modedb-hd720.patch13
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch43
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch76
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch218
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch106
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch181
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch84
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch47
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch60
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch93
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch361
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch417
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch56
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch91
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch32
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch202
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch146
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch132
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch167
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch158
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch58
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch70
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch38
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch187
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch259
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch90
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch1109
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch198
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch133
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch145
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/no-cortex-deadlock.patch77
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/no-empty-flash-warnings.patch15
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/no-harry-potter.diff11
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap-2430-lcd.patch11
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap1710h3/defconfig1224
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap2420h4/defconfig1119
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap2430sdp/defconfig1303
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-pandora/defconfig2186
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch677
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch64
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch285
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch23604
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch40
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch221
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch246
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch53
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch39
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch35
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c744
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch11
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig2747
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig2701
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch66715
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch20
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch44
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch177
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch52
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch131
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm773
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch9
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch11
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch10
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch93
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff66
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch87
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch108
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch30
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch36
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3evm/defconfig2217
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-dss2.diff443
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-lcd-redtint.diff66
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/omap5912osk/defconfig1098
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/overo-cpufreq.diff25
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/overo/defconfig2250
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/overo/ehci.patch113
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/read_die_ids.patch23
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/register-all-OPPs.diff12
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/timer-suppression.patch43
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/touchscreen.patch22
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/usbttyfix.patch29
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/01-vfp-pm.patch128
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/02-vfp-ptrace.patch231
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/03-vfp-corruption.patch136
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch98
-rw-r--r--recipes/linux/linux-omap-pm-2.6.29/vfp/05-vfp-signal-handlers.patch148
-rw-r--r--recipes/linux/linux-omap-pm-2.6.31/beagleboard/defconfig2765
-rw-r--r--recipes/linux/linux-omap-pm/beagle-writable-uboot.diff10
-rw-r--r--recipes/linux/linux-omap-pm/beagleboard/defconfig921
-rw-r--r--recipes/linux/linux-omap-pm/beagleboard/ehci.patch155
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0001-OMAPFB-move-omapfb.h-to-include-linux.patch1297
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0002-DSS2-OMAP2-3-Display-Subsystem-driver.patch14450
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP-framebuffer-driver.patch3403
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0004-DSS2-Add-panel-drivers.patch396
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0005-DSS2-HACK-Add-DSS2-support-for-N800.patch1079
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0006-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch5703
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-function-to-display-object-to-get-the-back.patch39
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-acx565akm-panel.patch778
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0009-DSS2-Small-VRFB-context-allocation-bug-fixed.patch28
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0010-DSS2-Allocated-memory-for-Color-Look-up-table.patch37
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0011-DSS2-Fix-DMA-rotation.patch65
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0012-DSS2-Verify-that-overlay-paddr-0.patch41
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0013-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch51
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0014-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch68
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-improve-packet-len-calculation.patch58
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0016-DSS2-Disable-video-planes-on-sync-lost-error.patch103
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0017-DSS2-check-for-ovl-paddr-only-when-enabling.patch40
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0018-DSS2-Check-fclk-limits-when-configuring-video-plane.patch183
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-scaling-limits-against-proper-values.patch79
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0020-DSS2-Add-venc-register-dump.patch96
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0021-DSS2-FB-remove-unused-var-warning.patch27
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0022-DSS2-pass-the-default-FB-color-format-through-board.patch214
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0023-DSS2-Beagle-Use-gpio_set_value.patch48
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0024-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch28
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0025-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch78
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0026-DSS2-VRFB-rotation-and-mirroring-implemented.patch324
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0027-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch236
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch61
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0029-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch29
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0030-DSS2-do-bootmem-reserve-for-exclusive-access.patch33
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0031-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch35
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0032-DSS2-Prefer-3-tap-filter.patch82
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0033-DSS2-VRAM-improve-omap_vram_add_region.patch135
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0034-DSS2-Added-the-function-pointer-for-getting-default.patch66
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-support-for-setting-and-querying-alpha-b.patch118
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-querying-color-keying.patch150
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0037-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch56
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0038-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch59
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0039-DSS2-Provided-proper-exclusion-for-destination-colo.patch97
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0040-DSS2-Disable-vertical-offset-with-fieldmode.patch71
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0041-DSS2-Don-t-enable-fieldmode-automatically.patch34
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0042-DSS2-Swap-field-0-and-field-1-registers.patch170
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0043-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch76
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0044-DSS2-Fixed-line-endings-from-to.patch48
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0045-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0046-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch44
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0047-DSS2-VRAM-clear-allocated-area-with-DMA.patch101
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0048-DSS2-OMAPFB-remove-fb-clearing-code.patch53
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-use-debugfs-not-procfs.patch170
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0050-DSS2-VRAM-fix-section-mismatch-warning.patch34
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0051-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch41
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0052-DSS2-DSI-more-error-handling.patch85
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0053-DSS2-Added-global-alpha-support.patch230
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0054-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch35
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0055-DSS2-Documentation-update-for-new-sysfs-entries-in.patch32
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0056-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch56
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0057-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch97
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0058-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch34
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0059-DSS2-VRFB-save-restore-context.patch106
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0060-DSS2-VRAM-Fix-indentation.patch65
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0061-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch82
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0062-VRFB-fix-debug-messages.patch35
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0063-VRFB-add-suspend-resume-functionality.patch216
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0064-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch92
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0065-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch29
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0066-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch65
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0067-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch125
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0068-DSS2-DSI-Improve-perf-measurement-output.patch127
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0069-DSS2-DSI-Add-support-for-external-TE-signal.patch110
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0070-DSS2-DSI-Fix-LP-clock.patch78
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0071-DSS2-Do-not-swap-xres-yres-or-change-rotation-in-ch.patch68
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0072-DSS2-Allow-independent-rotation-for-each-plane.patch277
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0073-DSS2-DISPC-fix-irq-handling-locking.patch225
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0074-DSS2-DISPC-clear-irqstatus-for-newly-enabled-irqs.patch39
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0075-DSS2-Add-WSS-support.patch172
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0076-DSS2-Fix-PAL-NTSC-timings.patch68
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0077-DSS2-Add-venc-debugfs-file.patch34
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0078-DSS2-Enable-replication-logic-feature.patch138
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0079-DSS2-support-for-querying-the-supported-overlay-col.patch180
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0080-DSS2-fix-uninitialized-var-in-OMAPFB_GET_CAPS-IOCTL.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0081-DSS2-Reset-WSS-data-only-when-changing-TV-standard.patch54
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0082-DSS2-DSI-implement-timeout-for-DSI-transfer.patch78
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0083-DSS2-DSI-reset-perf-frame-counter-when-starting-au.patch32
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0084-DSS2-DSI-Implement-DSI-bus-lock.patch265
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0085-DSS2-OMAPFB-omapfb_get_ovl_colormode-to-static.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0086-DSS2-VRFB-make-vrfb_hw_context-static.patch25
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0087-DSS2-new-device-driver-model.patch5336
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0088-DSS2-Board-file-changes-for-new-device-model.patch496
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0089-DSS2-Panel-driver-changes-for-new-device-model.patch400
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0090-DSS2-VENC-venc-uses-regulator-framework.patch74
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0091-DSS2-DSI-Use-regulator-framework.patch134
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0092-DSS2-SDP-regulators-for-VDAC-DSI.patch225
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0093-DSS2-Sharp-panel-use-regulator-fw.patch100
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0094-DSS2-Beagle-regulators-for-VDAC-DSI.patch52
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0095-DSS2-Fix-checkpatch-complaints.patch740
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0096-DSS2-Overo-add-vdac-dsi-regulators-fix-panel-name.patch278
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0097-DSS2-implement-overlay_manager_info.patch649
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0098-DSS2-use-sysfs_streq-to-compare-display-names.patch43
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0099-DSS2-Implement-function-to-verify-lcd-timings.patch144
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0100-DSS2-Remove-non-existing-dsi-power-funcs-from-dss.h.patch25
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0101-DSS2-move-to_dss_driver-and-to_dss_device-to-pu.patch40
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0102-DSS2-CLK-change-omapfb-omapdss-in-clock-framewo.patch53
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0103-DSS2-Use-clkdev.patch122
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0104-DSS2-Fix-documentation.patch38
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0105-DSS2-OMAPFB-first-set-TE-then-update-mode.patch38
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0106-DSS2-OMAPFB-Disable-forced-display-update-on-fb-cl.patch48
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0107-DSS2-DSI-use-INIT_COMPLETION-not-init_completion.patch25
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0108-DSS2-DSI-Rewrite-of-the-DSI-update-and-cmd-queue.patch1860
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0109-DSS2-let-init_display-return-an-error-code.patch235
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch209
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0111-DSS2-Fix-bottom-field-initial-starting-line.patch210
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0112-DSS2-Correctly-determine-if-an-interlaced-display-i.patch50
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0113-DSS2-Fix-omapfb-framebuffer-name.patch115
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0114-DSS2-Overo-update-defconfig-to-lighter-one.patch1217
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0115-DSS2-SDI-make-sdi_pads-static.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0116-DSS2-Fix-default_color-sysfs-output.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0117-DSS2-Locking-for-VRFB.patch125
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0118-DSS2-DISPC-fix-locking-issue-with-irq-handling.patch54
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0119-DSS2-OMAPFB-remove-unneeded-locks.patch391
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0120-DSS2-DISPC-configuration-management.patch2006
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0121-DSS2-VRFB-clean-up-BUG-calls.patch70
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0122-DSS2-OMAPFB-don-t-fail-even-if-default-display-doe.patch139
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0123-DSS2-DSI-Fix-external-TE-wait.patch41
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0124-DSS2-DSI-Increase-framedone-timeout-to-1s.patch28
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0125-DSS2-VRAM-Add-function-to-get-free-vram-info.patch76
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0126-DSS2-OMAPFB-implement-OMAPFB_GET_VRAM_INFO-ioctl.patch86
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0127-DSS2-DSI-increase-dsi-thread-priority.patch37
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0128-DSS2-DSI-check-bus_lock-in-send_bta.patch28
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0129-DSS2-DSI-export-dsi_vc_send_bta_sync.patch47
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0130-DSS2-DSI-clear-BTA-irq-before-enabling-it.patch26
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0131-DSS2-DSI-check-dsi_set_te-return-value.patch62
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch406
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0133-DSS2-VRAM-Remove-unused-defines.patch41
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0134-DSS2-VENC-Add-invert_polarity-flag.patch65
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0135-DSS2-VRAM-Add-defines-for-VRAM-types.patch89
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0136-DSS2-VRAM-separate-VRAM-setup-from-the-old-fb-vram.patch311
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0137-DSS2-VRFB-Update-license-information.patch77
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0138-DSS2-VRAM-Update-license-information.patch86
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0139-DSS2-VRFB-use-pr_-instead-of-printk.patch43
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0140-DSS2-VRAM-Change-CONFIG_OMAP2_DSS_VRAM_SIZE-name.patch49
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0141-DSS2-VRAM-add-CONFIG_OMAP2_VRAM-flag.patch141
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0142-DSS2-VRFB-Add-CONFIG_OMAP2_VRFB-flag.patch61
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0143-DSS2-VRFB-VRAM-fix-checkpatch-warnings.patch41
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0144-DSS2-fixes-to-dss_omap_3430sdp_defconfig-to-make-it.patch1675
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0145-DSS2-BEAGLE-get-DSS2-working-again-on-beagle.patch724
-rw-r--r--recipes/linux/linux-omap-pm/dss2/0146-DSS2-change-include-asm-.-to-linux-.-in-oma.patch29
-rw-r--r--recipes/linux/linux-omap-pm/fix-mtd.diff51
-rw-r--r--recipes/linux/linux-omap-pm/fix-musb-oops.diff60
-rw-r--r--recipes/linux/linux-omap-pm_2.6.29.bb210
-rw-r--r--recipes/linux/linux-omap-pm_git.bb216
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/fix-section-mismatch.diff11
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/fix-twl-merge-damage.diff19
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/no-3517-hack.diff16
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/omap3517-evm/defconfig1498
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/omap3evm/defconfig2297
-rw-r--r--recipes/linux/linux-omap-psp-2.6.29/shiva-bits.diff11
-rwxr-xr-xrecipes/linux/linux-omap-psp-2.6.29/shiva-ehci.diff60
-rw-r--r--recipes/linux/linux-omap-psp/omap3517-evm/defconfig1646
-rw-r--r--recipes/linux/linux-omap-psp/omap3evm/defconfig2202
-rw-r--r--recipes/linux/linux-omap-psp_2.6.29.bb40
-rw-r--r--recipes/linux/linux-omap-psp_2.6.31.bb28
-rwxr-xr-xrecipes/linux/linux-omap-zoomsync/omapzoom2/defconfig1900
-rw-r--r--recipes/linux/linux-omap-zoomsync_2.6.31.bb28
-rw-r--r--recipes/linux/linux-omap/ehci.patch0
-rw-r--r--recipes/linux/linux-omap/fix-omap4.diff63
-rw-r--r--recipes/linux/linux-omap/fix-serial.eml95
-rw-r--r--recipes/linux/linux-omap/omap4430-sdp/defconfig866
-rw-r--r--recipes/linux/linux-omap_2.6.29.bb60
-rw-r--r--recipes/linux/linux-omap_2.6.31.bb69
-rw-r--r--recipes/linux/linux-omap_git.bb66
-rw-r--r--recipes/linux/linux-omapandroid/omapzoom2/defconfig1854
-rw-r--r--recipes/linux/linux-omapandroid_2.6.29.bb24
-rw-r--r--recipes/linux/linux-palm-omap1_2.6.22-omap1.bb2
-rw-r--r--recipes/linux/linux-tornado-omap2_2.6.16.16.bb2
478 files changed, 542709 insertions, 2494 deletions
diff --git a/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch b/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch
new file mode 100644
index 0000000000..1dee314700
--- /dev/null
+++ b/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch
@@ -0,0 +1,429 @@
+Path: news.gmane.org!not-for-mail
+From: Mikael Pettersson <mikpe@it.uu.se>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH][v3] ARM support for
+ TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
+Date: Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
+Lines: 362
+Approved: news@gmane.org
+Message-ID: <200908151109.n7FB9Sbs000150@pilspetsen.it.uu.se>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1250334940 22899 80.91.229.12 (15 Aug 2009 11:15:40 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Sat, 15 Aug 2009 11:15:40 +0000 (UTC)
+To: linux-arm-kernel@lists.arm.linux.org.uk
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk Sat Aug 15 13:15:33 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from zeniv.linux.org.uk ([195.92.253.2])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1McHER-0000U2-PG
+ for linux-arm-kernel@m.gmane.org; Sat, 15 Aug 2009 13:15:31 +0200
+Original-Received: from [2002:4e20:1eda:1:201:3dff:fe00:156] (helo=lists.arm.linux.org.uk)
+ by ZenIV.linux.org.uk with esmtpsa (Exim 4.69 #1 (Red Hat Linux))
+ id 1McH9u-0005LV-3W; Sat, 15 Aug 2009 11:10:57 +0000
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=arm.linux.org.uk; s=lists; h=Date:Message-Id:From:To:Subject:
+ List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:
+ List-Subscribe:MIME-Version:Content-Type:
+ Content-Transfer-Encoding; bh=RVq9hPAexlUcptd3h6j5nomOyoEIjcDWAP
+ VeJtlhsa4=; b=HAoqRMC9svNzKlR0f938E0cRlLoJZvG2aSun171woWZAClu/Ud
+ IYN0iD2vm4eF+kYQkTYD6PGFCMbNnugmZe6gCpS0QhijoKyOzRBdykQHJuOLQtLE
+ q9KJzp24cQ/vwsV2+O1OqcmIFboIg2L5JQaUuv0djS7OkdspH0ysmi1lg=
+Original-Received: from [::1] (helo=lists.arm.linux.org.uk)
+ by lists.arm.linux.org.uk with esmtp (Exim 4.69)
+ (envelope-from <linux-arm-kernel-bounces@lists.arm.linux.org.uk>)
+ id 1McH9o-0002us-34; Sat, 15 Aug 2009 12:10:44 +0100
+Original-Received: from aun.it.uu.se ([130.238.12.36] ident=root)
+ by lists.arm.linux.org.uk with esmtps (TLSv1:AES256-SHA:256)
+ (Exim 4.69) (envelope-from <mikpe@user.it.uu.se>) id 1McH8h-0002uj-Ck
+ for linux-arm-kernel@lists.arm.linux.org.uk;
+ Sat, 15 Aug 2009 12:09:35 +0100
+Original-Received: from pilspetsen.it.uu.se (daemon@pilspetsen.it.uu.se [130.238.18.39])
+ by aun.it.uu.se (8.13.6/8.13.6) with ESMTP id n7FB9S04005839
+ for <linux-arm-kernel@lists.arm.linux.org.uk>;
+ Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
+Original-Received: (from mikpe@localhost)
+ by pilspetsen.it.uu.se (8.13.8+Sun/8.13.7) id n7FB9Sbs000150
+ for linux-arm-kernel@lists.arm.linux.org.uk;
+ Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
+X-BeenThere: linux-arm-kernel@lists.arm.linux.org.uk
+X-Mailman-Version: 2.1.9
+Precedence: list
+List-Id: ARM Linux kernel discussions <linux-arm-kernel.lists.arm.linux.org.uk>
+List-Unsubscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=unsubscribe>
+List-Archive: <http://lists.arm.linux.org.uk/lurker/list/linux-arm-kernel.html>
+List-Post: <mailto:linux-arm-kernel@lists.arm.linux.org.uk>
+List-Help: <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=help>
+List-Subscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=subscribe>
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:64340
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/64340>
+
+This patch adds support for TIF_RESTORE_SIGMASK to ARM's signal handling,
+which allows to hook up the pselect6, ppoll, and epoll_pwait syscalls on ARM.
+
+Tested here with eabi userspace and a test program with a deliberate race
+between a child's exit and the parent's sigprocmask/select sequence.
+Using sys_pselect6() instead of sigprocmask/select reliably prevents the race.
+
+The other arch's support for TIF_RESTORE_SIGMASK has evolved over time:
+
+In 2.6.16:
+- add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING
+- test both when checking for pending signal [bad, changed later]
+- reimplement sys_sigsuspend() to use current->saved_sigmask,
+ TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND;
+ ditto for sys_rt_sigsuspend(), but drop private code and
+ use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND;
+- there are now no "extra" calls to do_signal() so its oldset
+ parameter is always &current->blocked so need not be passed,
+ also its return value is changed to void
+- change handle_signal() to return 0/-errno
+- change do_signal() to honor TIF_RESTORE_SIGMASK:
+ + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set
+ + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
+ + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
+ clear it and restore the sigmask
+- hook up sys_pselect6() and sys_ppoll()
+
+In 2.6.19:
+- hook up sys_epoll_pwait()
+
+In 2.6.26:
+- allow archs to override how TIF_RESTORE_SIGMASK is implemented;
+ default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and
+ TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again
+ when checking for pending signal work; some archs now implement
+ TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit
+- call set_restore_sigmask() in sys_sigsuspend() instead of setting
+ TIF_RESTORE_SIGMASK
+
+In 2.6.29-rc:
+- kill sys_pselect7() which no arch wanted
+
+So for 2.6.31-rc6/ARM this patch does the following:
+- Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask()
+ which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so
+ TIF_RESTORE_SIGMASK need not claim one of the scarce low thread
+ flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need
+ not be extended for TIF_RESTORE_SIGMASK.
+- sys_sigsuspend() is reimplemented to use current->saved_sigmask and
+ set_restore_sigmask(), making it identical to most other archs.
+- The private code for sys_rt_sigsuspend() is removed, instead generic
+ code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND.
+- sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs
+ parameter, so their assembly code wrappers are removed.
+- handle_signal() is changed to return 0 on success or -errno.
+- The oldset parameter to do_signal() is now redundant and removed,
+ and the return value is now also redundant so it's changed to void.
+- do_signal() is changed to honor TIF_RESTORE_SIGMASK:
+ + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set
+ + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
+ + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
+ clear it and restore the sigmask
+- Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait.
+
+Signed-off-by: Mikael Pettersson
+---
+Changes from previous versions:
+
+v2 (only posted as incremental diff against v1):
+- moved sigmask restoration in no-signal-delivered case into
+ "if (syscall)" block for extra protection against exception
+ path also invoking do_signal()
+v3 (this version):
+- moved oldset initialisation into "if (signr > 0)" block,
+ as requested by Russell
+
+ arch/arm/include/asm/thread_info.h | 2
+ arch/arm/include/asm/unistd.h | 7 +--
+ arch/arm/kernel/calls.S | 10 ++--
+ arch/arm/kernel/entry-common.S | 10 ----
+ arch/arm/kernel/signal.c | 86 +++++++++++++++----------------------
+ 5 files changed, 48 insertions(+), 67 deletions(-)
+
+diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h
+--- linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h 2009-08-14 11:11:10.000000000 +0200
++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h 2009-08-14 11:26:44.000000000 +0200
+@@ -140,6 +140,7 @@ extern void vfp_sync_state(struct thread
+ #define TIF_USING_IWMMXT 17
+ #define TIF_MEMDIE 18
+ #define TIF_FREEZE 19
++#define TIF_RESTORE_SIGMASK 20
+
+ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+@@ -147,6 +148,7 @@ extern void vfp_sync_state(struct thread
+ #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+ #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
+ #define _TIF_FREEZE (1 << TIF_FREEZE)
++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+
+ /*
+ * Change these and you break ASM code in entry-common.S
+diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/unistd.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h
+--- linux-2.6.31-rc6/arch/arm/include/asm/unistd.h 2009-08-14 11:11:10.000000000 +0200
++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h 2009-08-14 11:26:44.000000000 +0200
+@@ -360,8 +360,8 @@
+ #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
+ #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
+ #define __NR_faccessat (__NR_SYSCALL_BASE+334)
+- /* 335 for pselect6 */
+- /* 336 for ppoll */
++#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
++#define __NR_ppoll (__NR_SYSCALL_BASE+336)
+ #define __NR_unshare (__NR_SYSCALL_BASE+337)
+ #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
+ #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
+@@ -372,7 +372,7 @@
+ #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
+ #define __NR_move_pages (__NR_SYSCALL_BASE+344)
+ #define __NR_getcpu (__NR_SYSCALL_BASE+345)
+- /* 346 for epoll_pwait */
++#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
+ #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
+ #define __NR_utimensat (__NR_SYSCALL_BASE+348)
+ #define __NR_signalfd (__NR_SYSCALL_BASE+349)
+@@ -432,6 +432,7 @@
+ #define __ARCH_WANT_SYS_SIGPENDING
+ #define __ARCH_WANT_SYS_SIGPROCMASK
+ #define __ARCH_WANT_SYS_RT_SIGACTION
++#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+
+ #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
+ #define __ARCH_WANT_SYS_TIME
+diff -rupN linux-2.6.31-rc6/arch/arm/kernel/calls.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S
+--- linux-2.6.31-rc6/arch/arm/kernel/calls.S 2009-08-14 11:11:10.000000000 +0200
++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S 2009-08-14 11:26:44.000000000 +0200
+@@ -81,7 +81,7 @@
+ CALL(sys_ni_syscall) /* was sys_ssetmask */
+ /* 70 */ CALL(sys_setreuid16)
+ CALL(sys_setregid16)
+- CALL(sys_sigsuspend_wrapper)
++ CALL(sys_sigsuspend)
+ CALL(sys_sigpending)
+ CALL(sys_sethostname)
+ /* 75 */ CALL(sys_setrlimit)
+@@ -188,7 +188,7 @@
+ CALL(sys_rt_sigpending)
+ CALL(sys_rt_sigtimedwait)
+ CALL(sys_rt_sigqueueinfo)
+- CALL(sys_rt_sigsuspend_wrapper)
++ CALL(sys_rt_sigsuspend)
+ /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
+ CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
+ CALL(sys_chown16)
+@@ -344,8 +344,8 @@
+ CALL(sys_readlinkat)
+ CALL(sys_fchmodat)
+ CALL(sys_faccessat)
+-/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
+- CALL(sys_ni_syscall) /* eventually ppoll */
++/* 335 */ CALL(sys_pselect6)
++ CALL(sys_ppoll)
+ CALL(sys_unshare)
+ CALL(sys_set_robust_list)
+ CALL(sys_get_robust_list)
+@@ -355,7 +355,7 @@
+ CALL(sys_vmsplice)
+ CALL(sys_move_pages)
+ /* 345 */ CALL(sys_getcpu)
+- CALL(sys_ni_syscall) /* eventually epoll_pwait */
++ CALL(sys_epoll_pwait)
+ CALL(sys_kexec_load)
+ CALL(sys_utimensat)
+ CALL(sys_signalfd)
+diff -rupN linux-2.6.31-rc6/arch/arm/kernel/entry-common.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S
+--- linux-2.6.31-rc6/arch/arm/kernel/entry-common.S 2009-08-14 11:11:10.000000000 +0200
++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S 2009-08-14 11:26:44.000000000 +0200
+@@ -373,16 +373,6 @@ sys_clone_wrapper:
+ b sys_clone
+ ENDPROC(sys_clone_wrapper)
+
+-sys_sigsuspend_wrapper:
+- add r3, sp, #S_OFF
+- b sys_sigsuspend
+-ENDPROC(sys_sigsuspend_wrapper)
+-
+-sys_rt_sigsuspend_wrapper:
+- add r2, sp, #S_OFF
+- b sys_rt_sigsuspend
+-ENDPROC(sys_rt_sigsuspend_wrapper)
+-
+ sys_sigreturn_wrapper:
+ add r0, sp, #S_OFF
+ b sys_sigreturn
+diff -rupN linux-2.6.31-rc6/arch/arm/kernel/signal.c linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c
+--- linux-2.6.31-rc6/arch/arm/kernel/signal.c 2009-08-14 11:11:10.000000000 +0200
++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c 2009-08-14 11:26:44.000000000 +0200
+@@ -47,57 +47,22 @@ const unsigned long sigreturn_codes[7] =
+ MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
+ };
+
+-static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
+-
+ /*
+ * atomically swap in the new signal mask, and wait for a signal.
+ */
+-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
+ {
+- sigset_t saveset;
+-
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+- saveset = current->blocked;
++ current->saved_sigmask = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+- regs->ARM_r0 = -EINTR;
+-
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs, 0))
+- return regs->ARM_r0;
+- }
+-}
+-
+-asmlinkage int
+-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
+-{
+- sigset_t saveset, newset;
+-
+- /* XXX: Don't preclude handling different sized sigset_t's. */
+- if (sigsetsize != sizeof(sigset_t))
+- return -EINVAL;
+-
+- if (copy_from_user(&newset, unewset, sizeof(newset)))
+- return -EFAULT;
+- sigdelsetmask(&newset, ~_BLOCKABLE);
+-
+- spin_lock_irq(&current->sighand->siglock);
+- saveset = current->blocked;
+- current->blocked = newset;
+- recalc_sigpending();
+- spin_unlock_irq(&current->sighand->siglock);
+- regs->ARM_r0 = -EINTR;
+
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs, 0))
+- return regs->ARM_r0;
+- }
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ set_restore_sigmask();
++ return -ERESTARTNOHAND;
+ }
+
+ asmlinkage int
+@@ -545,7 +510,7 @@ static inline void setup_syscall_restart
+ /*
+ * OK, we're invoking a handler
+ */
+-static void
++static int
+ handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs * regs, int syscall)
+@@ -596,7 +561,7 @@ handle_signal(unsigned long sig, struct
+
+ if (ret != 0) {
+ force_sigsegv(sig, tsk);
+- return;
++ return ret;
+ }
+
+ /*
+@@ -610,6 +575,7 @@ handle_signal(unsigned long sig, struct
+ recalc_sigpending();
+ spin_unlock_irq(&tsk->sighand->siglock);
+
++ return 0;
+ }
+
+ /*
+@@ -621,7 +587,7 @@ handle_signal(unsigned long sig, struct
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+-static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
++static void do_signal(struct pt_regs *regs, int syscall)
+ {
+ struct k_sigaction ka;
+ siginfo_t info;
+@@ -634,7 +600,7 @@ static int do_signal(sigset_t *oldset, s
+ * if so.
+ */
+ if (!user_mode(regs))
+- return 0;
++ return;
+
+ if (try_to_freeze())
+ goto no_signal;
+@@ -643,9 +609,24 @@ static int do_signal(sigset_t *oldset, s
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+- handle_signal(signr, &ka, &info, oldset, regs, syscall);
++ sigset_t *oldset;
++
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ oldset = &current->saved_sigmask;
++ else
++ oldset = &current->blocked;
++ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
++ /*
++ * A signal was successfully delivered; the saved
++ * sigmask will have been stored in the signal frame,
++ * and will be restored by sigreturn, so we can simply
++ * clear the TIF_RESTORE_SIGMASK flag.
++ */
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ }
+ single_step_set(current);
+- return 1;
++ return;
+ }
+
+ no_signal:
+@@ -697,14 +678,21 @@ static int do_signal(sigset_t *oldset, s
+ regs->ARM_r0 == -ERESTARTNOINTR) {
+ setup_syscall_restart(regs);
+ }
++
++ /* If there's no signal to deliver, we just put the saved sigmask
++ * back.
++ */
++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
++ }
+ }
+ single_step_set(current);
+- return 0;
+ }
+
+ asmlinkage void
+ do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+ {
+ if (thread_flags & _TIF_SIGPENDING)
+- do_signal(&current->blocked, regs, syscall);
++ do_signal(regs, syscall);
+ }
+
+-------------------------------------------------------------------
+List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
+FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php
+Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php
+
diff --git a/recipes/linux/files/linux-2.6-limits.patch b/recipes/linux/files/linux-2.6-limits.patch
new file mode 100644
index 0000000000..777a2fa671
--- /dev/null
+++ b/recipes/linux/files/linux-2.6-limits.patch
@@ -0,0 +1,10 @@
+--- linux/scripts/mod/sumversion.c.orig 2009-03-15 21:44:58.000000000 +0100
++++ linux/scripts/mod/sumversion.c 2009-03-15 21:44:58.000000000 +0100
+@@ -8,6 +8,7 @@
+ #include <errno.h>
+ #include <string.h>
+ #include "modpost.h"
++#include <linux/limits.h>
+
+ /*
+ * Stolen form Cryptographic API.
diff --git a/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch b/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch
deleted file mode 100644
index 7852f0afdb..0000000000
--- a/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch
+++ /dev/null
@@ -1,287 +0,0 @@
-From 8a7643b09856f4f661403dcedbe0455b3cbeeea9 Mon Sep 17 00:00:00 2001
-From: Steven Newbury <s_j_newbury@yahoo.co.uk>
-Date: Fri, 22 May 2009 14:25:40 +0200
-Subject: [PATCH] implement TIF_RESTORE_SIGMASK support and enable the related
- syscalls:
-
-pselect6
-ppoll
-epoll_pwait
-
-Based on http://www.spinics.net/lists/arm-kernel/msg38114.html
----
- arch/arm/include/asm/thread_info.h | 2 +
- arch/arm/include/asm/unistd.h | 7 ++-
- arch/arm/kernel/calls.S | 6 +-
- arch/arm/kernel/signal.c | 90 +++++++++++++++---------------------
- 4 files changed, 46 insertions(+), 59 deletions(-)
-
-diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
-index 4f88482..2cf0917 100644
---- a/arch/arm/include/asm/thread_info.h
-+++ b/arch/arm/include/asm/thread_info.h
-@@ -136,6 +136,7 @@ extern void vfp_sync_state(struct thread_info *thread);
- #define TIF_SIGPENDING 0
- #define TIF_NEED_RESCHED 1
- #define TIF_SYSCALL_TRACE 8
-+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal */
- #define TIF_POLLING_NRFLAG 16
- #define TIF_USING_IWMMXT 17
- #define TIF_MEMDIE 18
-@@ -144,6 +145,7 @@ extern void vfp_sync_state(struct thread_info *thread);
- #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
- #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
- #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
-+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
- #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
- #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
- #define _TIF_FREEZE (1 << TIF_FREEZE)
-diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
-index 94cc58e..cd1eaa0 100644
---- a/arch/arm/include/asm/unistd.h
-+++ b/arch/arm/include/asm/unistd.h
-@@ -360,8 +360,8 @@
- #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
- #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
- #define __NR_faccessat (__NR_SYSCALL_BASE+334)
-- /* 335 for pselect6 */
-- /* 336 for ppoll */
-+#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
-+#define __NR_ppoll (__NR_SYSCALL_BASE+336)
- #define __NR_unshare (__NR_SYSCALL_BASE+337)
- #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
- #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
-@@ -372,7 +372,7 @@
- #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
- #define __NR_move_pages (__NR_SYSCALL_BASE+344)
- #define __NR_getcpu (__NR_SYSCALL_BASE+345)
-- /* 346 for epoll_pwait */
-+#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
- #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
- #define __NR_utimensat (__NR_SYSCALL_BASE+348)
- #define __NR_signalfd (__NR_SYSCALL_BASE+349)
-@@ -430,6 +430,7 @@
- #define __ARCH_WANT_SYS_SIGPENDING
- #define __ARCH_WANT_SYS_SIGPROCMASK
- #define __ARCH_WANT_SYS_RT_SIGACTION
-+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-
- #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
- #define __ARCH_WANT_SYS_TIME
-diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
-index 1680e9e..534000d 100644
---- a/arch/arm/kernel/calls.S
-+++ b/arch/arm/kernel/calls.S
-@@ -344,8 +344,8 @@
- CALL(sys_readlinkat)
- CALL(sys_fchmodat)
- CALL(sys_faccessat)
--/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
-- CALL(sys_ni_syscall) /* eventually ppoll */
-+/* 335 */ CALL(sys_pselect6)
-+ CALL(sys_ppoll)
- CALL(sys_unshare)
- CALL(sys_set_robust_list)
- CALL(sys_get_robust_list)
-@@ -355,7 +355,7 @@
- CALL(sys_vmsplice)
- CALL(sys_move_pages)
- /* 345 */ CALL(sys_getcpu)
-- CALL(sys_ni_syscall) /* eventually epoll_pwait */
-+ CALL(sys_epoll_pwait)
- CALL(sys_kexec_load)
- CALL(sys_utimensat)
- CALL(sys_signalfd)
-diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
-index 80b8b5c..7645048 100644
---- a/arch/arm/kernel/signal.c
-+++ b/arch/arm/kernel/signal.c
-@@ -47,57 +47,23 @@ const unsigned long sigreturn_codes[7] = {
- MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
- };
-
--static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
-+static void do_signal(struct pt_regs * regs, int syscall);
-
- /*
- * atomically swap in the new signal mask, and wait for a signal.
- */
--asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
-+asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
- {
-- sigset_t saveset;
--
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
-- saveset = current->blocked;
-+ current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-- regs->ARM_r0 = -EINTR;
--
-- while (1) {
-- current->state = TASK_INTERRUPTIBLE;
-- schedule();
-- if (do_signal(&saveset, regs, 0))
-- return regs->ARM_r0;
-- }
--}
--
--asmlinkage int
--sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
--{
-- sigset_t saveset, newset;
--
-- /* XXX: Don't preclude handling different sized sigset_t's. */
-- if (sigsetsize != sizeof(sigset_t))
-- return -EINVAL;
--
-- if (copy_from_user(&newset, unewset, sizeof(newset)))
-- return -EFAULT;
-- sigdelsetmask(&newset, ~_BLOCKABLE);
--
-- spin_lock_irq(&current->sighand->siglock);
-- saveset = current->blocked;
-- current->blocked = newset;
-- recalc_sigpending();
-- spin_unlock_irq(&current->sighand->siglock);
-- regs->ARM_r0 = -EINTR;
--
-- while (1) {
-- current->state = TASK_INTERRUPTIBLE;
-- schedule();
-- if (do_signal(&saveset, regs, 0))
-- return regs->ARM_r0;
-- }
-+ current->state = TASK_INTERRUPTIBLE;
-+ schedule();
-+ set_thread_flag(TIF_RESTORE_SIGMASK);
-+ return -ERESTARTNOHAND;
- }
-
- asmlinkage int
-@@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
-
- badframe:
- force_sig(SIGSEGV, current);
-- return 0;
-+ return -EFAULT;
- }
-
- asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
-@@ -325,7 +291,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
-
- badframe:
- force_sig(SIGSEGV, current);
-- return 0;
-+ return -EFAULT;
- }
-
- static int
-@@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs)
- /*
- * OK, we're invoking a handler
- */
--static void
-+static int
- handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
- struct pt_regs * regs, int syscall)
-@@ -592,7 +558,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
-
- if (ret != 0) {
- force_sigsegv(sig, tsk);
-- return;
-+ return ret;
- }
-
- /*
-@@ -606,6 +572,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
- recalc_sigpending();
- spin_unlock_irq(&tsk->sighand->siglock);
-
-+ return ret;
- }
-
- /*
-@@ -617,11 +584,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
- * the kernel can handle, and then we build all the user-level signal handling
- * stack-frames in one go after that.
- */
--static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
-+static void do_signal(struct pt_regs *regs, int syscall)
- {
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
-+ sigset_t *oldset;
-
- /*
- * We want the common case to go fast, which
-@@ -630,18 +598,29 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
- * if so.
- */
- if (!user_mode(regs))
-- return 0;
-+ return;
-
- if (try_to_freeze())
- goto no_signal;
-
- single_step_clear(current);
-
-+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
-+ oldset = &current->saved_sigmask;
-+ else
-+ oldset = &current->blocked;
-+
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
-- handle_signal(signr, &ka, &info, oldset, regs, syscall);
-+ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
-+ /* a signal was successfully delivered; the saved
-+ * sigmask will have been stored in the signal frame,
-+ * and will be restored by sigreturn, so we can simply
-+ * clear the TIF_RESTORE_SIGMASK flag */
-+ clear_thread_flag(TIF_RESTORE_SIGMASK);
-+ }
- single_step_set(current);
-- return 1;
-+ return;
- }
-
- no_signal:
-@@ -665,7 +644,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
- usp = (u32 __user *)regs->ARM_sp;
-
- /*
-- * Either we supports OABI only, or we have
-+ * Either we support OABI only, or we have
- * EABI with the OABI compat layer enabled.
- * In the later case we don't know if user
- * space is EABI or not, and if not we must
-@@ -695,12 +674,17 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
- }
- }
- single_step_set(current);
-- return 0;
-+ /* if there's no signal to deliver, we just put the saved sigmask
-+ back. */
-+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-+ clear_thread_flag(TIF_RESTORE_SIGMASK);
-+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-+ }
- }
-
- asmlinkage void
- do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
- {
-- if (thread_flags & _TIF_SIGPENDING)
-- do_signal(&current->blocked, regs, syscall);
-+ if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
-+ do_signal(regs, syscall);
- }
---
-1.6.2.4
-
diff --git a/recipes/linux/linux-omap-2.6.29/arch-has-holes.diff b/recipes/linux/linux-omap-2.6.29/arch-has-holes.diff
new file mode 100644
index 0000000000..f3935eb90a
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/arch-has-holes.diff
@@ -0,0 +1,235 @@
+diff -purN git2/arch/arm/include/asm/memory.h git/arch/arm/include/asm/memory.h
+--- git2/arch/arm/include/asm/memory.h 2009-06-08 06:42:26.000000000 +0530
++++ git/arch/arm/include/asm/memory.h 2009-08-17 11:58:07.000000000 +0530
+@@ -204,7 +204,6 @@ static inline __deprecated void *bus_to_
+ *
+ * page_to_pfn(page) convert a struct page * to a PFN number
+ * pfn_to_page(pfn) convert a _valid_ PFN number to struct page *
+- * pfn_valid(pfn) indicates whether a PFN number is valid
+ *
+ * virt_to_page(k) convert a _valid_ virtual address to struct page *
+ * virt_addr_valid(k) indicates whether a virtual address is valid
+@@ -213,10 +212,6 @@ static inline __deprecated void *bus_to_
+
+ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
+
+-#ifndef CONFIG_SPARSEMEM
+-#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
+-#endif
+-
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+
+@@ -233,18 +228,6 @@ static inline __deprecated void *bus_to_
+ #define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
+ #define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
+
+-#define pfn_valid(pfn) \
+- ({ \
+- unsigned int nid = PFN_TO_NID(pfn); \
+- int valid = nid < MAX_NUMNODES; \
+- if (valid) { \
+- pg_data_t *node = NODE_DATA(nid); \
+- valid = (pfn - node->node_start_pfn) < \
+- node->node_spanned_pages; \
+- } \
+- valid; \
+- })
+-
+ #define virt_to_page(kaddr) \
+ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
+diff -purN git2/arch/arm/include/asm/page.h git/arch/arm/include/asm/page.h
+--- git2/arch/arm/include/asm/page.h 2009-06-08 06:42:26.000000000 +0530
++++ git/arch/arm/include/asm/page.h 2009-08-17 11:58:07.000000000 +0530
+@@ -186,6 +186,10 @@ typedef unsigned long pgprot_t;
+
+ typedef struct page *pgtable_t;
+
++#ifndef CONFIG_SPARSEMEM
++extern int pfn_valid(unsigned long);
++#endif
++
+ #include <asm/memory.h>
+
+ #endif /* !__ASSEMBLY__ */
+diff -purN git2/arch/arm/Kconfig git/arch/arm/Kconfig
+--- git2/arch/arm/Kconfig 2009-07-20 05:07:12.000000000 +0530
++++ git/arch/arm/Kconfig 2009-08-17 12:08:37.000000000 +0530
+@@ -272,6 +272,7 @@ config ARCH_EP93XX
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_HAS_HOLES_MEMORYMODEL
+ help
+ This enables support for the Cirrus EP93xx series of CPUs.
+
+@@ -569,6 +570,7 @@ config ARCH_OMAP
+ select ARCH_REQUIRE_GPIOLIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
++ select ARCH_HAS_HOLES_MEMORYMODEL
+ help
+ Support for TI's OMAP platform (OMAP1 and OMAP2).
+
+@@ -891,10 +893,9 @@ config OABI_COMPAT
+ UNPREDICTABLE (in fact it can be predicted that it won't work
+ at all). If in doubt say Y.
+
+-config ARCH_FLATMEM_HAS_HOLES
++config ARCH_HAS_HOLES_MEMORYMODEL
+ bool
+- default y
+- depends on FLATMEM
++ default n
+
+ # Discontigmem is deprecated
+ config ARCH_DISCONTIGMEM_ENABLE
+diff -purN git2/arch/arm/mm/init.c git/arch/arm/mm/init.c
+--- git2/arch/arm/mm/init.c 2009-06-08 06:42:27.000000000 +0530
++++ git/arch/arm/mm/init.c 2009-08-17 12:03:16.000000000 +0530
+@@ -15,7 +15,7 @@
+ #include <linux/mman.h>
+ #include <linux/nodemask.h>
+ #include <linux/initrd.h>
+-
++#include <linux/sort.h>
+ #include <asm/mach-types.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
+@@ -333,12 +333,40 @@ static void __init bootmem_free_node(int
+ free_area_init_node(node, zone_size, start_pfn, zhole_size);
+ }
+
++#ifndef CONFIG_SPARSEMEM
++int pfn_valid(unsigned long pfn)
++{
++ struct meminfo *mi = &meminfo;
++ unsigned int mid, left = 0, right = mi->nr_banks;
++
++ while ((mid = (right - left) / 2) > 0) {
++ struct membank *bank = &mi->bank[mid];
++
++ if (pfn < bank_pfn_start(bank))
++ right = mid;
++ else if (pfn >= bank_pfn_end(bank))
++ left = mid + 1;
++ else
++ return 1;
++ }
++ return 0;
++}
++EXPORT_SYMBOL(pfn_valid);
++#endif
++
++static int __init meminfo_cmp(const void *_a, const void *_b) {
++ const struct membank *a = _a, *b = _b;
++ long cmp = bank_pfn_start(a) - bank_pfn_start(b);
++ return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; }
++
+ void __init bootmem_init(void)
+ {
+ struct meminfo *mi = &meminfo;
+ unsigned long memend_pfn = 0;
+ int node, initrd_node;
+
++ sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL);
++
+ /*
+ * Locate which node contains the ramdisk image, if any.
+ */
+diff -purN git2/include/linux/mmzone.h git/include/linux/mmzone.h
+--- git2/include/linux/mmzone.h 2009-06-08 06:42:40.000000000 +0530
++++ git/include/linux/mmzone.h 2009-08-17 11:57:17.000000000 +0530
+@@ -1095,6 +1095,32 @@ unsigned long __init node_memmap_size_by
+ #define pfn_valid_within(pfn) (1)
+ #endif
+
++#ifdef CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
++/*
++ * pfn_valid() is meant to be able to tell if a given PFN has valid memmap
++ * associated with it or not. In FLATMEM, it is expected that holes always
++ * have valid memmap as long as there is valid PFNs either side of the hole.
++ * In SPARSEMEM, it is assumed that a valid section has a memmap for the
++ * entire section.
++ *
++ * However, an ARM, and maybe other embedded architectures in the future
++ * free memmap backing holes to save memory on the assumption the memmap is
++ * never used. The page_zone linkages are then broken even though pfn_valid()
++ * returns true. A walker of the full memmap must then do this additional
++ * check to ensure the memmap they are looking at is sane by making sure
++ * the zone and PFN linkages are still valid. This is expensive, but walkers
++ * of the full memmap are extremely rare.
++ */
++int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone);
++#else
++static inline int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone)
++{
++ return 1;
++}
++#endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
++
+ #endif /* !__GENERATING_BOUNDS.H */
+ #endif /* !__ASSEMBLY__ */
+ #endif /* _LINUX_MMZONE_H */
+diff -purN git2/mm/mmzone.c git/mm/mmzone.c
+--- git2/mm/mmzone.c 2009-06-08 06:42:41.000000000 +0530
++++ git/mm/mmzone.c 2009-08-17 11:57:17.000000000 +0530
+@@ -6,6 +6,7 @@
+
+
+ #include <linux/stddef.h>
++#include <linux/mm.h>
+ #include <linux/mmzone.h>
+ #include <linux/module.h>
+
+@@ -72,3 +73,17 @@ struct zoneref *next_zones_zonelist(stru
+ *zone = zonelist_zone(z);
+ return z;
+ }
++
++#ifdef CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
++int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone)
++{
++ if (page_to_pfn(page) != pfn)
++ return 0;
++
++ if (page_zone(page) != zone)
++ return 0;
++
++ return 1;
++}
++#endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
+diff -purN git2/mm/vmstat.c git/mm/vmstat.c
+--- git2/mm/vmstat.c 2009-06-08 06:42:41.000000000 +0530
++++ git/mm/vmstat.c 2009-08-17 11:57:17.000000000 +0530
+@@ -516,22 +516,11 @@ static void pagetypeinfo_showblockcount_
+ continue;
+
+ page = pfn_to_page(pfn);
+-#ifdef CONFIG_ARCH_FLATMEM_HAS_HOLES
+- /*
+- * Ordinarily, memory holes in flatmem still have a valid
+- * memmap for the PFN range. However, an architecture for
+- * embedded systems (e.g. ARM) can free up the memmap backing
+- * holes to save memory on the assumption the memmap is
+- * never used. The page_zone linkages are then broken even
+- * though pfn_valid() returns true. Skip the page if the
+- * linkages are broken. Even if this test passed, the impact
+- * is that the counters for the movable type are off but
+- * fragmentation monitoring is likely meaningless on small
+- * systems.
+- */
+- if (page_zone(page) != zone)
++
++ /* Watch for unexpected holes punched in the memmap */
++ if (!memmap_valid_within(pfn, page, zone))
+ continue;
+-#endif
++
+ mtype = get_pageblock_migratetype(page);
+
+ if (mtype < MIGRATE_TYPES)
diff --git a/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig b/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig
index d939aa6b42..a1848d59a4 100644
--- a/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig
+++ b/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.29-omap1
-# Mon May 11 13:05:20 2009
+# Wed Sep 9 09:58:54 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -32,6 +32,7 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
@@ -64,8 +65,7 @@ CONFIG_FAIR_GROUP_SCHED=y
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
@@ -190,8 +190,7 @@ CONFIG_ARCH_OMAP3=y
#
# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
-CONFIG_OMAP_SMARTREFLEX=y
-# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
CONFIG_OMAP_RESET_CLOCKS=y
CONFIG_OMAP_BOOT_TAG=y
CONFIG_OMAP_BOOT_REASON=y
@@ -200,7 +199,7 @@ CONFIG_OMAP_BOOT_REASON=y
# CONFIG_OMAP_MUX is not set
CONFIG_OMAP_MCBSP=y
# CONFIG_OMAP_MBOX_FWK is not set
-# CONFIG_OMAP_IOMMU is not set
+CONFIG_OMAP_IOMMU=m
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
@@ -218,9 +217,9 @@ CONFIG_ARCH_OMAP3430=y
# CONFIG_MACH_NOKIA_RX51 is not set
# CONFIG_MACH_OMAP_LDP is not set
# CONFIG_MACH_OMAP_3430SDP is not set
-# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3EVM=y
CONFIG_MACH_OMAP3_BEAGLE=y
-# CONFIG_MACH_OVERO is not set
+CONFIG_MACH_OVERO=y
# CONFIG_MACH_OMAP3_PANDORA is not set
#
@@ -250,6 +249,7 @@ CONFIG_ARM_THUMBEE=y
# CONFIG_CPU_BPREDICT_DISABLE is not set
CONFIG_HAS_TLS_REG=y
# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=6
#
# Bus support
@@ -269,11 +269,11 @@ CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
CONFIG_HZ=128
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -786,7 +786,9 @@ CONFIG_BT_HCIBFUSB=y
# CONFIG_BT_HCIBRF6150 is not set
# CONFIG_BT_HCIH4P is not set
# CONFIG_BT_HCIVHCI is not set
-# CONFIG_AF_RXRPC is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
# CONFIG_PHONET is not set
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
@@ -1033,8 +1035,44 @@ CONFIG_MACVLAN=m
CONFIG_EQUALIZER=m
CONFIG_TUN=m
CONFIG_VETH=m
-# CONFIG_NET_ETHERNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_ENC28J60=y
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -1095,7 +1133,7 @@ CONFIG_USB_NET_SMSC95XX=y
CONFIG_USB_NET_GL620A=y
CONFIG_USB_NET_NET1080=y
CONFIG_USB_NET_PLUSB=y
-CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_MCS7830=y
CONFIG_USB_NET_RNDIS_HOST=y
CONFIG_USB_NET_CDC_SUBSET=y
CONFIG_USB_ALI_M5632=y
@@ -1104,7 +1142,7 @@ CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_ZAURUS=y
# CONFIG_WAN is not set
CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_DUMMY is not set
@@ -1288,14 +1326,14 @@ CONFIG_SPI_MASTER=y
#
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_GPIO is not set
-# CONFIG_SPI_OMAP24XX is not set
+CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
# CONFIG_SPI_TSC210X is not set
# CONFIG_SPI_TSC2301 is not set
-# CONFIG_SPI_SPIDEV is not set
+CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
@@ -1470,6 +1508,7 @@ CONFIG_MEDIA_TUNER_MXL5005S=m
CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L1=m
CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
CONFIG_VIDEOBUF_DVB=m
CONFIG_VIDEO_IR=m
@@ -1493,7 +1532,8 @@ CONFIG_VIDEO_VIVI=m
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
# CONFIG_VIDEO_AU0828 is not set
-# CONFIG_VIDEO_OMAP3 is not set
+CONFIG_VIDEO_OMAP3=m
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m
# CONFIG_SOC_CAMERA is not set
CONFIG_V4L_USB_DRIVERS=y
CONFIG_USB_VIDEO_CLASS=m
@@ -1817,6 +1857,7 @@ CONFIG_SND_USB_CAIAQ_INPUT=y
CONFIG_SND_SOC=y
CONFIG_SND_OMAP_SOC=y
CONFIG_SND_OMAP_SOC_MCBSP=y
+# CONFIG_SND_OMAP_SOC_OVERO is not set
CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
@@ -2024,7 +2065,7 @@ CONFIG_USB_EMI26=m
# CONFIG_USB_RIO500 is not set
CONFIG_USB_LEGOTOWER=m
CONFIG_USB_LCD=m
-# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_BERRY_CHARGE=m
CONFIG_USB_LED=m
CONFIG_USB_CYPRESS_CY7C63=m
CONFIG_USB_CYTHERM=m
@@ -2038,9 +2079,9 @@ CONFIG_USB_FTDI_ELAN=m
CONFIG_USB_SISUSBVGA=m
CONFIG_USB_SISUSBVGA_CON=y
CONFIG_USB_LD=m
-# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_TRANCEVIBRATOR=m
# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
+CONFIG_USB_TEST=m
# CONFIG_USB_ISIGHTFW is not set
CONFIG_USB_VST=m
CONFIG_USB_ATM=m
@@ -2071,14 +2112,17 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
CONFIG_USB_GADGET_DUALSPEED=y
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-CONFIG_USB_CDC_COMPOSITE=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
#
# OTG and related infrastructure
@@ -2126,7 +2170,7 @@ CONFIG_LEDS_GPIO=y
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=m
CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
@@ -2148,7 +2192,7 @@ CONFIG_RTC_INTF_DEV=y
#
# I2C RTC drivers
#
-# CONFIG_RTC_DRV_DS1307 is not set
+CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
@@ -2158,7 +2202,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
-CONFIG_RTC_DRV_TWL4030=y
+CONFIG_RTC_DRV_TWL4030=m
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set
@@ -2199,7 +2243,11 @@ CONFIG_REGULATOR=y
# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
# CONFIG_REGULATOR_BQ24022 is not set
CONFIG_REGULATOR_TWL4030=y
-# CONFIG_UIO is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
CONFIG_STAGING=y
# CONFIG_STAGING_EXCLUDE_BUILD is not set
# CONFIG_MEILHAUS is not set
@@ -2227,6 +2275,25 @@ CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
CONFIG_ANDROID_TIMED_GPIO=m
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_BMI=y
+
+#
+# BMI Hardware Slot support
+#
+CONFIG_OMAP_SLOT=m
+CONFIG_BMI_PIMS=m
+
+#
+# BMI PIMS
+#
+# CONFIG_BUG_FACTORY_TEST is not set
+CONFIG_BMI_GPS=m
+CONFIG_BMI_MDACC=m
+# CONFIG_BMI_AUDIO is not set
+CONFIG_BMI_VH=m
+# CONFIG_BMI_SENSOR is not set
+# CONFIG_BMI_ZB is not set
+CONFIG_BMI_GSM=m
#
# CBUS support
@@ -2251,8 +2318,17 @@ CONFIG_JBD=y
CONFIG_JBD2=m
# CONFIG_JBD2_DEBUG is not set
CONFIG_FS_MBCACHE=m
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
@@ -2260,9 +2336,17 @@ CONFIG_XFS_FS=m
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
# CONFIG_XFS_DEBUG is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -2274,7 +2358,7 @@ CONFIG_QUOTA_TREE=y
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
@@ -2294,7 +2378,9 @@ CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
#
# Pseudo filesystems
@@ -2308,13 +2394,16 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -2333,23 +2422,25 @@ CONFIG_JFFS2_RUBIN=y
# CONFIG_JFFS2_CMODE_SIZE is not set
CONFIG_JFFS2_CMODE_FAVOURLZO=y
CONFIG_UBIFS_FS=y
-# CONFIG_UBIFS_FS_XATTR is not set
-# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=m
CONFIG_SQUASHFS=y
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -2371,12 +2462,30 @@ CONFIG_SUNRPC_GSS=y
# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
#
# Partition Types
@@ -2386,60 +2495,62 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_OSF_PARTITION is not set
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
+CONFIG_EFI_PARTITION=y
# CONFIG_SYSV68_PARTITION is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-# CONFIG_DLM is not set
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
#
# Kernel hacking
@@ -2462,6 +2573,7 @@ CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -2499,6 +2611,7 @@ CONFIG_TRACING=y
#
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
@@ -2517,7 +2630,8 @@ CONFIG_HAVE_ARCH_KGDB=y
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
@@ -2530,7 +2644,7 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
-# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
@@ -2539,6 +2653,7 @@ CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
@@ -2551,20 +2666,20 @@ CONFIG_CRYPTO_TEST=m
#
# Authenticated Encryption with Associated Data
#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
#
# Block modes
#
CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
+CONFIG_CRYPTO_XTS=m
#
# Hash modes
@@ -2579,10 +2694,10 @@ CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
@@ -2602,8 +2717,8 @@ CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
@@ -2618,7 +2733,7 @@ CONFIG_CRYPTO_LZO=y
#
# Random Number Generation
#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
#
diff --git a/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-puppy.diff b/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-puppy.diff
new file mode 100644
index 0000000000..c7856731e5
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-puppy.diff
@@ -0,0 +1,66 @@
+--- /tmp/board-omap3beagle.c 2009-07-01 01:06:44.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-01 01:06:50.000000000 +0200
+@@ -125,6 +125,13 @@
+ .wires = 8,
+ .gpio_wp = 29,
+ },
++ {
++ .mmc = 2,
++ .wires = 4,
++ .gpio_wp = 141,
++ .gpio_cd = 162,
++ .transceiver = true,
++ },
+ {} /* Terminator */
+ };
+
+@@ -132,6 +139,11 @@
+ .supply = "vmmc",
+ };
+
++static struct regulator_consumer_supply beagle_vmmc2_supply = {
++ .supply = "vmmc",
++};
++
++
+ static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+ };
+@@ -148,6 +160,7 @@
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
++ beagle_vmmc2_supply.dev = mmc[1].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+@@ -209,6 +222,21 @@
+ .consumer_supplies = &beagle_vmmc1_supply,
+ };
+
++/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .min_uV = 2700000,
++ .max_uV = 3150000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
++ | REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
+ /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+ static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+@@ -284,6 +312,7 @@
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
++ .vmmc2 = &beagle_vmmc2,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
diff --git a/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-zippy.diff b/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-zippy.diff
new file mode 100644
index 0000000000..cab479e5d3
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/beagleboard/tincantools-zippy.diff
@@ -0,0 +1,103 @@
+--- /tmp/board-omap3beagle.c 2009-08-13 12:35:01.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-08-13 12:44:00.000000000 +0200
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/leds.h>
+ #include <linux/gpio.h>
++#include <linux/irq.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
+
+@@ -54,6 +55,47 @@
+ #define GPMC_CS_SIZE 0x30
+
+ #define NAND_BLOCK_SIZE SZ_128K
++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
++
++#include <mach/mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
++
++static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
++ .turbo_mode = 0,
++ .single_channel = 1, /* 0: slave, 1: master */
++};
++
++static struct spi_board_info omap3beagle_spi_board_info[] __initdata = {
++ {
++ .modalias = "enc28j60",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 20000000,
++ .controller_data = &enc28j60_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_enc28j60_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
++ omap3beagle_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
++ set_irq_type(omap3beagle_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_spi_board_info,
++ ARRAY_SIZE(omap3beagle_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_enc28j60_init(void) { return; }
++#endif
+
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+@@ -318,7 +360,7 @@
+ .vpll2 = &beagle_vpll2,
+ };
+
+-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
++static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+@@ -327,10 +369,24 @@
+ },
+ };
+
++#if defined(CONFIG_RTC_DRV_DS1307) || \
++ defined(CONFIG_RTC_DRV_DS1307_MODULE)
++
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
++ {
++ I2C_BOARD_INFO("ds1307", 0x68),
++ },
++};
++#else
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+- ARRAY_SIZE(beagle_i2c_boardinfo));
++ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
++ ARRAY_SIZE(beagle_i2c1_boardinfo));
++ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
++ ARRAY_SIZE(beagle_i2c2_boardinfo));
+ /* Bus 3 is attached to the DVI port where devices like the pico DLP
+ * projector don't work reliably with 400kHz */
+ omap_register_i2c_bus(3, 100, NULL, 0);
+@@ -542,6 +598,8 @@
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
++ omap3beagle_enc28j60_init();
++
+ usb_musb_init();
+ usb_ehci_init();
+ omap3beagle_flash_init();
diff --git a/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch b/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch
new file mode 100644
index 0000000000..f556f420e4
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch
@@ -0,0 +1,35774 @@
+---
+ arch/arm/Kconfig | 2
+ arch/arm/mach-omap2/board-omap3beagle.c | 52
+ arch/arm/mach-omap2/mux.c | 25
+ arch/arm/plat-omap/include/mach/mux.h | 7
+ drivers/Kconfig | 3
+ drivers/Makefile | 1
+ drivers/bmi/Kconfig | 17
+ drivers/bmi/Makefile | 8
+ drivers/bmi/core/Makefile | 7
+ drivers/bmi/core/core.c | 319 +
+ drivers/bmi/core/device.c | 35
+ drivers/bmi/core/driver.c | 27
+ drivers/bmi/core/eeprom.c | 32
+ drivers/bmi/core/slot.c | 469 ++
+ drivers/bmi/pims/Kconfig | 104
+ drivers/bmi/pims/Makefile | 17
+ drivers/bmi/pims/camera/Kconfig | 23
+ drivers/bmi/pims/camera/Makefile | 12
+ drivers/bmi/pims/camera/bmi_ov2640.c | 929 +++++
+ drivers/bmi/pims/camera/bmi_vs6624.c | 915 +++++
+ drivers/bmi/pims/camera/bug_camera.c | 611 +++
+ drivers/bmi/pims/camera/bug_camera.h | 72
+ drivers/bmi/pims/camera/ov2640.c | 301 +
+ drivers/bmi/pims/camera/ov2640.h | 14
+ drivers/bmi/pims/camera/vs6624_access.c | 597 +++
+ drivers/bmi/pims/camera/vs6624_access.h | 17
+ drivers/bmi/pims/camera/vs6624_patch.c | 373 ++
+ drivers/bmi/pims/camera/vs6624_regs.h | 467 ++
+ drivers/bmi/pims/factory_test/Makefile | 6
+ drivers/bmi/pims/factory_test/factory_test.c | 952 +++++
+ drivers/bmi/pims/gps/Makefile | 6
+ drivers/bmi/pims/gps/bmi_gps.c | 468 ++
+ drivers/bmi/pims/gsm/Makefile | 6
+ drivers/bmi/pims/gsm/bmi_gsm.c | 301 +
+ drivers/bmi/pims/lcd/Makefile | 9
+ drivers/bmi/pims/lcd/acc.c | 114
+ drivers/bmi/pims/lcd/acc.h | 35
+ drivers/bmi/pims/lcd/bmi_lcd.c | 1790 ++++++++++
+ drivers/bmi/pims/lcd/bmi_lcd_inf.c | 1775 ++++++++++
+ drivers/bmi/pims/lcd/bmi_lcd_mi.c | 1855 +++++++++++
+ drivers/bmi/pims/lcd/bmi_s320x240.c | 632 +++
+ drivers/bmi/pims/lcd/lcd_ctl.c | 421 ++
+ drivers/bmi/pims/lcd/lcd_ctl.h | 87
+ drivers/bmi/pims/mdacc/Kconfig | 6
+ drivers/bmi/pims/mdacc/Makefile | 9
+ drivers/bmi/pims/mdacc/acc.c | 381 ++
+ drivers/bmi/pims/mdacc/acc.h | 54
+ drivers/bmi/pims/mdacc/avr.c | 511 +++
+ drivers/bmi/pims/mdacc/avr.h | 54
+ drivers/bmi/pims/mdacc/cque.c | 150
+ drivers/bmi/pims/mdacc/cque.h | 42
+ drivers/bmi/pims/mdacc/ctl.c | 176 +
+ drivers/bmi/pims/mdacc/ctl.h | 43
+ drivers/bmi/pims/mdacc/md.c | 333 ++
+ drivers/bmi/pims/mdacc/md.h | 60
+ drivers/bmi/pims/mdacc/mdacc.c | 333 ++
+ drivers/bmi/pims/mdacc/mdacc.h | 43
+ drivers/bmi/pims/mdacc/mon.c | 474 ++
+ drivers/bmi/pims/mdacc/mon.h | 61
+ drivers/bmi/pims/projector/Makefile | 7
+ drivers/bmi/pims/projector/bmi_projector.c | 674 ++++
+ drivers/bmi/pims/projector/ch7024.c | 476 ++
+ drivers/bmi/pims/projector/ch7024.h | 166 +
+ drivers/bmi/pims/sensor/Makefile | 6
+ drivers/bmi/pims/sensor/bmi_sensor.c | 4321 ++++++++++++++++++++++++++
+ drivers/bmi/pims/sound/Makefile | 6
+ drivers/bmi/pims/sound/bmi_audio.c | 4434 +++++++++++++++++++++++++++
+ drivers/bmi/pims/vonhippel/Makefile | 6
+ drivers/bmi/pims/vonhippel/bmi_vh.c | 942 +++++
+ drivers/bmi/pims/zb/Makefile | 5
+ drivers/bmi/pims/zb/bmi_zaccel.c | 684 ++++
+ drivers/bmi/pims/zb/bmi_zaccel.h | 288 +
+ drivers/bmi/pims/zb/bmi_zigbee.c | 1296 +++++++
+ drivers/bmi/pims/zb/bmi_zigbee.h | 194 +
+ drivers/bmi/pims/zb/bmi_znetdev.c | 977 +++++
+ drivers/bmi/pims/zb/bmi_zprotocol.c | 619 +++
+ drivers/bmi/slots/Kconfig | 21
+ drivers/bmi/slots/Makefile | 6
+ drivers/bmi/slots/slots_beagle.c | 267 +
+ drivers/bmi/slots/slots_bug.c | 231 +
+ include/linux/bmi-ids.h | 30
+ include/linux/bmi.h | 142
+ include/linux/bmi/at24c02.h | 26
+ include/linux/bmi/bmi-bus.h | 21
+ include/linux/bmi/bmi-control.h | 303 +
+ include/linux/bmi/bmi-eeprom-data.h | 83
+ include/linux/bmi/bmi-eeprom-driver.h | 113
+ include/linux/bmi/bmi-eeprom.h | 75
+ include/linux/bmi/bmi-slot.h | 29
+ include/linux/bmi/bmi_audio.h | 449 ++
+ include/linux/bmi/bmi_camera.h | 36
+ include/linux/bmi/bmi_gps.h | 30
+ include/linux/bmi/bmi_gsm.h | 33
+ include/linux/bmi/bmi_ioctl.h | 27
+ include/linux/bmi/bmi_lcd.h | 71
+ include/linux/bmi/bmi_mdacc.h | 518 +++
+ include/linux/bmi/bmi_projector.h | 33
+ include/linux/bmi/bmi_sensor.h | 673 ++++
+ include/linux/bmi/bmi_vh.h | 135
+ include/linux/bmi/bmi_zb.h | 83
+ include/linux/mod_devicetable.h | 13
+ scripts/mod/file2alias.c | 20
+ 102 files changed, 35212 insertions(+)
+
+--- git.orig/arch/arm/Kconfig
++++ git/arch/arm/Kconfig
+@@ -1342,10 +1342,12 @@ source "drivers/regulator/Kconfig"
+
+ source "drivers/uio/Kconfig"
+
+ source "drivers/staging/Kconfig"
+
++source "drivers/bmi/Kconfig"
++
+ if ARCH_OMAP
+ source "drivers/cbus/Kconfig"
+ endif
+
+ endmenu
+--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
++++ git/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -23,10 +23,12 @@
+ #include <linux/gpio.h>
+ #include <linux/irq.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
+
++
++#include <linux/spi/spi.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+
+ #include <linux/regulator/machine.h>
+@@ -404,10 +406,16 @@ static struct gpio_led gpio_leds[] = {
+ {
+ .name = "beagleboard::usr0",
+ .default_trigger = "heartbeat",
+ .gpio = 150,
+ },
++ /*{
++ .name = "beagleboard::exp21",
++ .default_trigger = "heartbeat",
++ .gpio = 130,
++ },
++ */
+ {
+ .name = "beagleboard::usr1",
+ .default_trigger = "mmc0",
+ .gpio = 149,
+ },
+@@ -537,20 +545,54 @@ static void __init beagle_display_init(v
+ }
+
+ gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+ }
+
++
++static struct resource bmi_slot1_resources[] = {
++ [0] = {
++ .start = 161,
++ .flags = IORESOURCE_IRQ,
++ },
++ [1] = {
++ .start = 134,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device bmi_slot_devices[] = {
++ {
++ .name = "omap_bmi_slot",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bmi_slot1_resources),
++ .resource = bmi_slot1_resources,
++ },
++};
++
++
++static void omap_init_bmi_slots(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(bmi_slot_devices); i++) {
++ if (platform_device_register(&bmi_slot_devices[i]) < 0)
++ dev_err(&bmi_slot_devices[i].dev,
++ "Unable to register BMI slot\n");
++ }
++}
++
+ static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_beagle_uart_config },
+ };
+
+ static struct platform_device *omap3_beagle_devices[] __initdata = {
+ &beagle_dss_device,
+ &leds_gpio,
+ &keys_gpio,
+ };
+
++
+ static void __init omap3beagle_flash_init(void)
+ {
+ u8 cs = 0;
+ u8 nandcs = GPMC_CS_NUM + 1;
+
+@@ -598,14 +640,24 @@ static void __init omap3_beagle_init(voi
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
+ omap3beagle_enc28j60_init();
+
++ omap_cfg_reg(AG4_3530_GPIO134);
++ omap_cfg_reg(K26_34XX_GPIO161);
++ omap_cfg_reg(Y21_3530_GPIO156_OUT);
++ omap_cfg_reg(AF14_34XX_I2C3_SCL);
++ omap_cfg_reg(AG14_34XX_I2C3_SDA);
++ omap_cfg_reg(U21_3530_GPIO159_OUT);
++ gpio_direction_output(156, false);
++ gpio_direction_output(159, false);
++ // BMI Presence and Status
+ usb_musb_init();
+ usb_ehci_init();
+ omap3beagle_flash_init();
+ beagle_display_init();
++ omap_init_bmi_slots();
+ }
+
+ static void __init omap3_beagle_map_io(void)
+ {
+ omap2_set_globals_343x();
+--- git.orig/arch/arm/mach-omap2/mux.c
++++ git/arch/arm/mach-omap2/mux.c
+@@ -480,14 +480,39 @@ MUX_CFG_34XX("AE6_34XX_GPIO141", 0x16e,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+ MUX_CFG_34XX("AF5_34XX_GPIO142", 0x170,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+ MUX_CFG_34XX("AE5_34XX_GPIO143", 0x172,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("K26_34XX_GPIO161", 0x196,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+ MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+ MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++
++/*BeagleBoard/BUG-Hybrid specific GPIO stuff*/
++
++MUX_CFG_34XX("AE2_3530_GPIO130", 0x158,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
++/*
++MUX_CFG_34XX("AG5_3530_GPIO131", 0x15A,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("AH5_3530_GPIO132", 0x15C,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("AH4_3530_GPIO133", 0x15E,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++*/
++MUX_CFG_34XX("AG4_3530_GPIO134", 0x160,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("AF4_3530_GPIO135", 0x162,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("Y21_3530_GPIO156_OUT", 0x18C,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
++MUX_CFG_34XX("AA21_3530_GPIO157", 0x18E,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
++MUX_CFG_34XX("U21_3530_GPIO159_OUT", 0x192,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+ };
+
+ #define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins)
+
+ #else
+--- git.orig/arch/arm/plat-omap/include/mach/mux.h
++++ git/arch/arm/plat-omap/include/mach/mux.h
+@@ -799,12 +799,19 @@ enum omap34xx_index {
+ AE4_34XX_GPIO136_OUT,
+ AF6_34XX_GPIO140_UP,
+ AE6_34XX_GPIO141,
+ AF5_34XX_GPIO142,
+ AE5_34XX_GPIO143,
++ K26_34XX_GPIO161,
+ H19_34XX_GPIO164_OUT,
+ J25_34XX_GPIO170,
++ AE2_3530_GPIO130,
++ AG4_3530_GPIO134,
++ AF4_3530_GPIO135,
++ Y21_3530_GPIO156_OUT,
++ AA21_3530_GPIO157,
++ U21_3530_GPIO159_OUT
+ };
+
+ struct omap_mux_cfg {
+ struct pin_config *pins;
+ unsigned long size;
+--- git.orig/drivers/Kconfig
++++ git/drivers/Kconfig
+@@ -4,10 +4,12 @@ menu "Device Drivers"
+
+ source "drivers/base/Kconfig"
+
+ source "drivers/connector/Kconfig"
+
++source "drivers/bmi/Kconfig"
++
+ source "drivers/mtd/Kconfig"
+
+ source "drivers/of/Kconfig"
+
+ source "drivers/parport/Kconfig"
+@@ -107,6 +109,7 @@ source "drivers/uio/Kconfig"
+ source "drivers/xen/Kconfig"
+
+ source "drivers/staging/Kconfig"
+
+ source "drivers/platform/Kconfig"
++
+ endmenu
+--- git.orig/drivers/Makefile
++++ git/drivers/Makefile
+@@ -91,10 +91,11 @@ obj-y += lguest/
+ obj-$(CONFIG_CPU_FREQ) += cpufreq/
+ obj-$(CONFIG_CPU_IDLE) += cpuidle/
+ obj-y += idle/
+ obj-$(CONFIG_MMC) += mmc/
+ obj-$(CONFIG_MEMSTICK) += memstick/
++obj-$(CONFIG_BMI) += bmi/
+ obj-$(CONFIG_NEW_LEDS) += leds/
+ obj-$(CONFIG_INFINIBAND) += infiniband/
+ obj-$(CONFIG_SGI_SN) += sn/
+ obj-y += firmware/
+ obj-$(CONFIG_CRYPTO) += crypto/
+--- /dev/null
++++ git/drivers/bmi/Kconfig
+@@ -0,0 +1,17 @@
++#
++# BMI Infrastructure
++#
++
++menuconfig BMI
++ tristate "BMI"
++ depends on I2C
++ default n
++ ---help---
++ BMI bus infrastructure
++
++if BMI
++
++source drivers/bmi/slots/Kconfig
++source drivers/bmi/pims/Kconfig
++
++endif # BMI
+--- /dev/null
++++ git/drivers/bmi/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for the bmi bus drivers.
++#
++
++obj-$(CONFIG_BMI) += core/
++obj-$(CONFIG_BMI) += slots/
++obj-$(CONFIG_BMI) += pims/
++
+--- /dev/null
++++ git/drivers/bmi/core/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for BMI subsystem core
++#
++
++#bmicore-objs := core.o slot.o
++
++obj-$(CONFIG_BMI) += core.o driver.o slot.o eeprom.o
+--- /dev/null
++++ git/drivers/bmi/core/core.c
+@@ -0,0 +1,319 @@
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kobject.h>
++#include <linux/bmi.h>
++
++
++static DEFINE_MUTEX(core_lock);
++
++static struct class *bmi_class;
++
++
++struct class* bmi_get_class (void)
++{
++ return bmi_class;
++};
++EXPORT_SYMBOL(bmi_get_class);
++
++
++/**
++ * bmi_device_get - increments the reference count of the bmi device structure
++ * @dev: the device being referenced
++ *
++ * Each live reference to a device should be refcounted.
++ *
++ * Drivers for BMI devices should normally record such references in
++ * their probe() methods, when they bind to a device, and release
++ * them by calling bmi_dev_put(), in their disconnect() methods.
++ *
++ * A pointer to the device with the incremented reference counter is returned.
++ */
++struct bmi_device *bmi_dev_get(struct bmi_device *dev)
++{
++ if (dev)
++ get_device(&dev->dev);
++ return dev;
++}
++
++
++/**
++ * bmi_device_put - release a use of the bmi device structure
++ * @dev: device that's been disconnected
++ *
++ * Must be called when a user of a device is finished with it. When the last
++ * user of the device calls this function, the memory of the device is freed.
++ */
++void bmi_dev_put(struct bmi_device *dev)
++{
++ if (dev)
++ put_device(&dev->dev);
++}
++
++
++/**
++ * bmi_match_one_id - Tell if a BMI device structure has a matching
++ * BMI device id structure
++ * @id: single BMI device id structure to match
++ * @bdev: the BMI device structure to match against
++ *
++ * Returns the matching bmi_device_id structure or %NULL if there is no match.
++ */
++
++static const struct bmi_device_id *bmi_match_one_id(const struct bmi_device_id *id,
++ const struct bmi_device *bdev)
++{
++ if ((id->vendor == bdev->vendor) &&
++ (id->product == bdev->product) &&
++ ((id->revision == bdev->revision) || (id->revision == BMI_ANY)))
++ return id;
++ return NULL;
++}
++
++
++/**
++ * bmi_match_id - See if a BMI device matches a given bmi_device_id table
++ * @ids: array of BMI device id structures to search in
++ * @bdev: the BMI device structure to match against.
++ *
++ * Used by a driver to check whether a BMI device present in the
++ * system is in its list of supported devices. Returns the matching
++ * bmi_device_id structure or %NULL if there is no match.
++ *
++ */
++
++
++const struct bmi_device_id *bmi_match_id(const struct bmi_device_id *ids,
++ struct bmi_device *bdev)
++{
++ if (ids) {
++ while (ids->vendor) {
++ if (bmi_match_one_id(ids, bdev))
++ return ids;
++ ids++;
++ }
++ }
++ return NULL;
++}
++
++/**
++ * bmi_device_match - Tell if a BMI device structure has a matching BMI device id structure
++ * @dev: the BMI device structure to match against
++ * @drv: the device driver to search for matching PCI device id structures
++ *
++ * Used by a driver to check whether a BMI device present in the
++ * system is in its list of supported devices. Returns the matching
++ * bmi_device_id structure or %NULL if there is no match.
++ */
++
++
++static int bmi_device_match(struct device *dev, struct device_driver *driver)
++{
++ struct bmi_device *bmi_dev = to_bmi_device(dev);
++ struct bmi_driver *bmi_drv = to_bmi_driver(driver);
++ const struct bmi_device_id *found_id;
++
++ found_id = bmi_match_id(bmi_drv->id_table, bmi_dev);
++
++ if (found_id)
++ return 1;
++
++ printk(KERN_INFO "BMI: No matching Driver...");
++ return 0;
++}
++
++/*
++ * Uevent Generation for hotplug
++ */
++
++static int bmi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ struct bmi_device *bdev = to_bmi_device(dev);
++
++ if (!dev)
++ return -ENODEV;
++
++ if (add_uevent_var(env, "BMIBUS_SLOT=%01X", bdev->slot->slotnum)) {
++ return -ENOMEM;
++ }
++ if (add_uevent_var(env, "BMIBUS_VENDOR=%04X", bdev->vendor)) {
++ return -ENOMEM;
++ }
++ if (add_uevent_var(env, "BMIBUS_PRODUCT=%04X", bdev->product)) {
++ return -ENOMEM;
++ }
++ if (add_uevent_var(env, "BMIBUS_REV=%04X", bdev->revision)) {
++ return -ENOMEM;
++ }
++ if (add_uevent_var(env, "MODALIAS=bmi:v%04Xp%04Xr%04X",
++ bdev->vendor, bdev->product,
++ bdev->revision)) {
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++
++struct bmi_device *bmi_alloc_dev(struct bmi_slot *slot)
++{
++ struct bmi_device *dev;
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev) {
++ printk(KERN_ERR "BMI: Couldn't Allocate bmi_device structure...\n");
++ return NULL;
++ }
++
++ device_initialize(&dev->dev);
++ dev->dev.bus = &bmi_bus_type;
++ dev_set_name(&dev->dev, "bmi-dev-%d",slot->slotnum);
++ dev->dev.parent = &slot->slotdev;
++ dev->slot = slot;
++
++ return dev;
++}
++
++
++
++/**
++ * __bmi_probe()
++ * @drv: driver to call to check if it wants the BMI device
++ * @bmi_dev: BMI device being probed
++ *
++ * returns 0 on success, else error.
++ * side-effect: bmi_dev->driver is set to drv when drv claims bmi_dev.
++ */
++static int
++__bmi_probe(struct bmi_driver *driver, struct bmi_device *bmi_dev)
++{
++ int error = 0;
++
++ if (!bmi_dev->driver && driver->probe) {
++
++ error = driver->probe(bmi_dev);
++ if (error >= 0) {
++ // bmi_device -> bmi_driver (bmi-bus level )
++ bmi_dev->driver = driver;
++ error = 0;
++ }
++ }
++ return error;
++}
++
++static int bmi_device_probe (struct device *dev)
++{
++ int error = 0;
++ struct bmi_driver *drv;
++ struct bmi_device *bmi_dev;
++
++ //By this time, we have already been match()ed against a driver.
++
++ // device -> device_driver. (driver-core level)
++
++ drv = to_bmi_driver(dev->driver);
++ bmi_dev = to_bmi_device(dev);
++
++
++ bmi_dev_get(bmi_dev);
++
++ error = __bmi_probe(drv, bmi_dev);
++ if (error)
++ bmi_dev_put(bmi_dev);
++ else
++ kobject_uevent(&dev->kobj, KOBJ_ADD);
++
++ return error;
++}
++
++
++
++static int bmi_device_remove (struct device *dev)
++{
++ struct bmi_device * bmi_dev;
++ struct bmi_driver * driver;
++
++ bmi_dev = to_bmi_device(dev);
++ driver = bmi_dev->driver;
++
++ if (driver) {
++ if (driver->remove)
++ driver->remove(bmi_dev);
++ bmi_dev->driver = NULL;
++ }
++
++ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
++ bmi_dev_put(bmi_dev);
++ return 0;
++}
++
++static void bmi_device_shutdown(struct device * dev)
++{
++ return;
++}
++
++static int bmi_device_suspend (struct device * dev, pm_message_t state)
++{
++ return -1;
++}
++
++static int bmi_device_suspend_late (struct device * dev, pm_message_t state)
++{
++ return -1;
++}
++
++static int bmi_device_resume_early (struct device * dev)
++{
++ return -1;
++}
++
++static int bmi_device_resume (struct device * dev)
++{
++ return -1;
++}
++
++
++
++struct bus_type bmi_bus_type = {
++ .name = "bmi",
++ .match = bmi_device_match,
++ .uevent = bmi_device_uevent,
++ .probe = bmi_device_probe,
++ .remove = bmi_device_remove,
++ .shutdown = bmi_device_shutdown,
++ .suspend = bmi_device_suspend,
++ .suspend_late = bmi_device_suspend_late,
++ .resume_early = bmi_device_resume_early,
++ .resume = bmi_device_resume,
++};
++
++static int __init bmi_init(void)
++{
++ int ret = 0;
++
++ ret = bus_register(&bmi_bus_type);
++ if (ret) {
++ printk(KERN_ERR "BMI: (bmi_init) - Bus registration failed...\n");
++ return ret;
++ }
++
++ // ret = class_register(&bmi_class);
++ bmi_class = class_create(THIS_MODULE, "bmi");
++ if (ret) {
++ printk(KERN_ERR "BMI: (bmi_init) - Failed to register BMI Class...\n");
++ bmi_class = NULL;
++ bus_unregister(&bmi_bus_type);
++ }
++ return ret;
++}
++
++static void __exit bmi_cleanup(void)
++{
++ bmi_class = NULL;
++ bus_unregister(&bmi_bus_type);
++}
++
++//subsys_initcall(bmi_init);
++module_init(bmi_init);
++module_exit(bmi_cleanup);
+--- /dev/null
++++ git/drivers/bmi/core/device.c
+@@ -0,0 +1,35 @@
++
++
++// bmi_device accessors
++static inline int bmi_device_get_status_irq (struct bmi_device *bdev)
++{
++ return (bdev->slot->status_irq);
++}
++
++static inline int bmi_device_get_present_irq (struct bmi_device *bdev)
++{
++ return (bdev->slot->present_irq);
++}
++
++static inline struct i2c_adapter* bmi_device_get_i2c_adapter (struct bmi_device *bdev)
++{
++ return (&bdev->slot->adap);
++}
++
++static inline int bmi_device_get_slot (struct bmi_device *bdev)
++{
++ return (bdev->slot->slotnum);
++}
++
++int bmi_device_present (struct bmi_device *bdev);
++struct bmi_device *bmi_device_get(struct bmi_device *dev);
++void bmi_device_put(struct bmi_device *dev);
++
++int bmi_device_read_inventory_eeprom ( struct bmi_device *bdev );
++int bmi_device_init ( struct bmi_device *bdev, struct bmi_info *info, struct bus_type *bmi_bus_type);
++void bmi_device_cleanup( struct bmi_device* bdev);
++int bmi_device_i2c_setup( struct bmi_device *bdev);
++void bmi_device_i2c_cleanup( struct bmi_device* bdev);
++int bmi_device_spi_setup( struct bmi_device *bdev, u32 speed, u8 mode, u8 bits_per_word);
++void bmi_device_spi_cleanup( struct bmi_device* bdev);
++struct spi_device *bmi_device_get_spi( struct bmi_device *bdev);
+--- /dev/null
++++ git/drivers/bmi/core/driver.c
+@@ -0,0 +1,27 @@
++#include <linux/bmi.h>
++
++int __bmi_register_driver(struct bmi_driver *drv, struct module *owner)
++{
++ int error;
++
++ /* initialize common driver fields */
++ drv->driver.name = drv->name;
++ drv->driver.bus = &bmi_bus_type;
++ drv->driver.owner = owner;
++
++ /* register with core */
++ error = driver_register(&drv->driver);
++
++ return error;
++}
++
++
++void
++bmi_unregister_driver(struct bmi_driver *drv)
++{
++ driver_unregister(&drv->driver);
++}
++
++EXPORT_SYMBOL(__bmi_register_driver);
++EXPORT_SYMBOL(bmi_unregister_driver);
++
+--- /dev/null
++++ git/drivers/bmi/core/eeprom.c
+@@ -0,0 +1,32 @@
++#include <linux/types.h>
++#include <linux/bmi/bmi-eeprom.h>
++
++
++static inline __u8 bmi_eeprom_checksum (struct bmi_eeprom_data *raw)
++{
++ int i;
++ __u8 sum = 0;
++ __u8 *buf = (__u8*)raw;
++
++ for (i = 0; i < (sizeof (struct bmi_eeprom_data) - 1); i++) {
++ sum ^= *buf++;
++ }
++ return sum;
++}
++
++
++int bmi_eeprom_checksum_validate (struct bmi_eeprom_data *raw)
++{
++ int ret = 0;
++ u8 calcsum;
++
++ calcsum = bmi_eeprom_checksum (raw);
++
++ if (calcsum != raw->checksum) {
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++
+--- /dev/null
++++ git/drivers/bmi/core/slot.c
+@@ -0,0 +1,469 @@
++/* Matt Isaacs - Kick ass platform independant BMI implementation */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/completion.h>
++#include <linux/sched.h>
++#include <linux/list.h>
++#include <linux/delay.h>
++#include <linux/mutex.h>
++#include <linux/freezer.h>
++#include <linux/idr.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-slot.h>
++
++static DEFINE_MUTEX(slot_lock);
++static DEFINE_IDR(bmi_slot_idr);
++
++
++//#include "slot.h"
++
++/*
++struct slot_driver {
++ const char *description;
++
++ irq_return_t (*irq) (struct bmi_slot);
++ int (*start) (struct bmi_slot);
++ int (*stop) (struct bmi_slot);
++}
++*/
++
++static struct task_struct *kslotd_task;
++
++static DEFINE_SPINLOCK(slot_event_lock);
++static LIST_HEAD(slot_event_list);
++static DECLARE_WAIT_QUEUE_HEAD(kslotd_wait);
++
++static struct i2c_board_info at24c02_info = {
++ I2C_BOARD_INFO("at24c02", 0XA0 >> 1),
++};
++
++static void bmi_slot_work_handler(struct work_struct * work);
++
++struct bmi_slot* bmi_get_slot(int slotnum)
++{
++ struct bmi_slot *slot;
++
++ mutex_lock(&slot_lock);
++ slot = (struct bmi_slot*)idr_find(&bmi_slot_idr, slotnum);
++ if (slot && !try_module_get(slot->owner))
++ slot = NULL;
++
++ mutex_unlock(&slot_lock);
++
++ return slot;
++}
++
++void bmi_slot_power_on (int num)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return;
++ }
++
++ if (slot->actions->power_on)
++ slot->actions->power_on(slot);
++ else
++ printk(KERN_INFO "BMI: Slot %d power is always on...\n", num);
++ return;
++}
++
++void bmi_slot_power_off (int num)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return;
++ }
++
++ if (slot->actions->power_off)
++ slot->actions->power_off(slot);
++ else
++ printk(KERN_INFO "BMI: Slot %d power is always on...\n", num);
++ return;
++}
++
++void bmi_slot_gpio_configure (int num, int gpio)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return;
++ }
++
++ if (slot->actions->gpio_config)
++ slot->actions->gpio_config(slot, gpio);
++ else
++ printk(KERN_INFO "BMI: Slot GPIO not configurable...\n");
++ return;
++
++}
++EXPORT_SYMBOL(bmi_slot_gpio_configure);
++
++int bmi_slot_gpio_get(int num)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return -ENODEV;
++ }
++
++ if (slot->actions->gpio_get)
++ return slot->actions->gpio_get(slot);
++
++ printk(KERN_INFO "BMI: Slot GPIO not writable...\n");
++ return -EIO;
++}
++EXPORT_SYMBOL(bmi_slot_gpio_get);
++
++void bmi_slot_gpio_set(int num, int data)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return;
++ }
++
++ if (slot->actions->gpio_set)
++ slot->actions->gpio_set(slot, data);
++ else
++ printk(KERN_INFO "BMI: Slot GPIO not writable...\n");
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_gpio_set);
++
++void bmi_slot_gpio_write_bit(int num, int gpio, int data)
++{
++ return;
++}
++
++int bmi_slot_gpio_read_bit (int num, int gpio)
++{
++ int gpdat;
++ int bit;
++
++ gpdat = bmi_slot_gpio_get(num);
++ bit = (gpdat & (1 << gpio)) ? 1 : 0;
++ return bit;
++}
++
++
++// NOTE: When a plug-in module is removed, the gpios should be returned to inputs.
++// All requested slot resourece should be released.
++// The slot should be powered down.
++
++void bmi_slot_gpio_configure_all_as_inputs (int slot)
++{
++ return;
++}
++
++
++void bmi_slot_uart_enable (int num)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++
++ if (!slot) {
++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num);
++ return;
++ }
++
++ if (slot->actions->uart_enable)
++ return slot->actions->uart_enable(slot);
++
++ printk(KERN_INFO "BMI: UART always enabled...\n");
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_uart_enable);
++
++void bmi_slot_uart_disable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_uart_disable);
++
++void bmi_slot_spi_enable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_spi_enable);
++
++void bmi_slot_spi_disable (int num)
++{
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_spi_disable);
++
++void bmi_slot_audio_enable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_audio_enable);
++
++void bmi_slot_audio_disable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_audio_disable);
++
++void bmi_slot_battery_enable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_battery_enable);
++
++void bmi_slot_battery_disable (int num)
++{
++
++ return;
++}
++EXPORT_SYMBOL(bmi_slot_battery_disable);
++
++int bmi_slot_module_present (int num)
++{
++ struct bmi_slot *slot = bmi_get_slot(num);
++ // slot->actions->gpio_set
++ if (slot->actions->present != NULL)
++ return slot->actions->present(slot);
++ else
++ printk(KERN_INFO "BMI: Slot Driver incomplete. No presence detection...\n");
++ return 0;
++}
++
++int bmi_slot_read_eeprom(struct bmi_slot *slot, u8* data)
++{
++ unsigned char i = 0;
++ int ret;
++
++ if (slot->eeprom == NULL) {
++ printk(KERN_INFO "Can't get eeprom client...\n");
++ ret = -EIO;
++ }
++ else {
++ ret = i2c_master_send(slot->eeprom, &i, 1);
++ if (ret == 1)
++ ret = i2c_master_recv(slot->eeprom, data, sizeof(struct bmi_eeprom_data));
++ }
++ return ret;
++}
++
++int bmi_slot_status_irq_state (int slot)
++{
++ int state = 0;
++ return state;
++}
++
++
++#define DEBOUNCE_DELAY msecs_to_jiffies(1000)
++
++static irqreturn_t bmi_slot_irq_handler(int irq, void *dev_id)
++{
++ struct bmi_slot *slot = dev_id;
++
++ disable_irq_nosync(irq);
++ printk(KERN_INFO " BMI: IRQ Triggered on slot: %d\n", slot->slotnum);
++ schedule_delayed_work(&slot->work, DEBOUNCE_DELAY);
++ return IRQ_HANDLED;
++}
++
++static void bmi_slot_work_handler(struct work_struct * work)
++{
++ struct bmi_slot *slot;
++ struct bmi_device *bdev;
++ int ret;
++ struct bmi_eeprom_data data;
++ unsigned char* cdat;
++
++ slot = work_to_slot(work);
++
++ mutex_lock(&slot->pres_mutex);
++ if (bmi_slot_module_present(slot->slotnum)) {
++ if (!slot->present) {
++ slot->present = 1;
++ slot->eeprom = i2c_new_device(slot->adap, &at24c02_info);
++
++ ret = bmi_slot_read_eeprom(slot, (u8*)&data);
++
++ if (ret < 0)
++ {
++ printk(KERN_INFO "BMI: EEPROM Trouble on Slot %d...\n",slot->slotnum);
++
++ goto irqenbl;
++ }
++ //Testing stuff here...get rid of this...
++ else
++ printk(KERN_INFO "BMI: EEPROM Found...\n");
++ cdat = (char*)&data;
++ /*for (i = 0; i < 20; i++)
++ printk(KERN_INFO "0x%x\n", cdat[i]);*/
++ printk(KERN_INFO "SLOTS: Vendor: 0x%x\n",(data.vendor_msb<<8) | (data.vendor_lsb));
++ printk(KERN_INFO "SLOTS: Product 0x%x\n",(data.product_msb<<8) | (data.product_lsb));
++ printk(KERN_INFO "SLOTS: Revision 0x%x\n",(data.revision_msb<<8) | (data.revision_lsb));
++
++ //Do new device allocation and hand it over to BMI...
++ bdev = bmi_alloc_dev(slot);
++ bdev->vendor = (data.vendor_msb<<8) | (data.vendor_lsb);
++ bdev->product = (data.product_msb<<8) | (data.product_lsb);
++ bdev->revision = (data.revision_msb<<8) | (data.revision_lsb);
++
++ //Report module plugin so that udev can load appropriate drivers
++ //kobject_uevent (&bdev->dev.kobj, KOBJ_ADD);
++ ret = device_add(&bdev->dev);
++ if (ret) {
++ printk(KERN_ERR "SLOTS: Failed to add device...%d\n",ret);
++ goto irqenbl; //TODO: Memory allocated for by bmi_alloc_dev
++ }
++ slot->bdev = bdev;
++ /*
++ ret = device_attach(&bdev->dev);
++ if (ret != 1) {
++ printk(KERN_ERR "SLOTS: Failed to attach device...%d\n",ret);
++ goto irqenbl; //TODO: Memory allocated for by bmi_alloc_dev must be freed
++ }
++ */
++ }
++ else
++ //spurious insertion event..
++ printk(KERN_INFO "SLOTS: Spurious insertion on Slot %d...\n",slot->slotnum);
++ }
++ else {
++ if (slot->present) {
++ slot->present = 0;
++ printk(KERN_INFO "BMI: Module removed from slot %d...\n", slot->slotnum);
++ if (slot->bdev == NULL) {
++ printk(KERN_ERR "SLOTS: BMI Device NULL...\n");
++ goto del_eeprom;
++ }
++ //Call BMI device removal stuff here...
++ device_del(&slot->bdev->dev);
++ goto del_eeprom;
++ }
++ }
++ irqenbl:
++ mutex_unlock(&slot->pres_mutex);
++ enable_irq(slot->present_irq);
++ return;
++ del_eeprom:
++ i2c_unregister_device(slot->eeprom);
++ slot->bdev = NULL;
++ slot->eeprom = NULL;
++ goto irqenbl;
++
++}
++
++static int bmi_register_slot(struct bmi_slot *slot)
++{
++ int res = 0;
++ struct class *class;
++
++ // mutex_init(&slot->state_lock);
++ if (unlikely(WARN_ON(!bmi_bus_type.p)))
++ return -EAGAIN;
++ if (slot->actions == NULL) {
++ printk(KERN_INFO "SLOTS: No Slot actions defined...\n");
++ goto unlist;
++ }
++ mutex_init(&slot->pres_mutex);
++ mutex_lock(&slot_lock);
++
++ if (slot->slotdev.parent == NULL) {
++ slot->slotdev.parent = &platform_bus;
++ //debug message here
++ }
++
++ dev_set_name(&slot->slotdev, "bmi-%d", slot->slotnum);
++
++ class = bmi_get_class();
++ if (class == NULL) {
++ printk(KERN_ERR "BMI Class doesn't exist...\n");
++ goto unlist;
++ }
++ res = device_register(&slot->slotdev);
++ if (res) {
++ printk(KERN_ERR "SLOT: Couldn't register slot... %d\n",res);
++ goto unlist;
++ //quit
++ }
++
++ //Request IRQ
++ INIT_DELAYED_WORK(&slot->work, bmi_slot_work_handler);
++
++ printk(KERN_ERR "SLOT: Requesting IRQ...\n");
++ res = request_irq(slot->present_irq, bmi_slot_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING , slot->name, (void*)slot);
++
++ if (res) {
++ printk(KERN_ERR "SLOT: IRQ Request failed...\n");
++ goto unlist;
++ }
++
++ unlock:
++ mutex_unlock(&slot_lock);
++ return res;
++ unlist:
++ idr_remove(&bmi_slot_idr, slot->slotnum);
++ goto unlock;
++
++}
++
++
++int bmi_add_slot(struct bmi_slot *slot)
++{
++ int slotnum = 0;
++ int res = 0;
++
++ retry:
++ if (idr_pre_get(&bmi_slot_idr, GFP_KERNEL) == 0)
++ return -ENOMEM;
++
++ mutex_lock(&slot_lock);
++
++ res = idr_get_new_above(&bmi_slot_idr, slot, 0, &slotnum);
++ mutex_unlock(&slot_lock);
++ if (res < 0) {
++ if (res == -EAGAIN)
++ goto retry;
++ return res;
++ }
++ slot->slotnum = slotnum;
++ return bmi_register_slot(slot);
++}
++EXPORT_SYMBOL(bmi_add_slot);
++
++
++int bmi_del_slot(struct bmi_slot *slot)
++{
++ int res = 0;
++
++ mutex_lock(&slot_lock);
++ if (idr_find(&bmi_slot_idr, slot->slotnum)) {
++ printk(KERN_ERR "BMI: Attempting to delete unregistered slot...\n");
++ res = -EINVAL;
++ goto unlock;
++ }
++
++ disable_irq_nosync(slot->present_irq);
++ free_irq(slot->present_irq, slot);
++ device_unregister(&slot->slotdev);
++ idr_remove(&bmi_slot_idr, slot->slotnum);
++ memset(&slot->slotdev, 0, sizeof(slot->slotdev));
++
++ unlock:
++ mutex_unlock(&slot_lock);
++ return res;
++}
++EXPORT_SYMBOL(bmi_del_slot);
++
+--- /dev/null
++++ git/drivers/bmi/pims/Kconfig
+@@ -0,0 +1,104 @@
++#
++# BMI PIMS
++#
++
++config BMI_PIMS
++ tristate "BMI_PIMS"
++ default n
++ ---help---
++ BMI plug-in module support
++
++ This driver must be built as a module.
++
++menu "BMI PIMS"
++
++config BUG_FACTORY_TEST
++ tristate "BUG_FACTORY_TEST"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI FACTORY Test plug-in module
++
++ This driver can also be built as a module.
++
++config BMI_GPS
++ tristate "BMI_GPS"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI GPS plug-in module
++
++ This driver can also be built as a module.
++
++source "drivers/bmi/pims/mdacc/Kconfig"
++
++config VIDEO_BMI_LCD
++ tristate "BMI Bus LCD Module support"
++ depends on FB_MXC && MACH_BUG
++ default n
++ ---help---
++ This is the BMI bus driver for the LCD Plug-In Module.
++
++config VIDEO_BMI_LCD_S320X240
++ tristate "BMI support for Sharp 320x240 module"
++ depends on FB_MXC && MACH_BUG && VIDEO_BMI_LCD
++ default n
++ ---help---
++ This is the BMI LCD driver for the Sharp 320x240 LCD Plug-In Module.
++
++config VIDEO_BMI_PROJECTOR
++ tristate "BMI Bus PROJECTOR Module support"
++ depends on FB_MXC_PROJECTOR && MACH_BUG
++ default n
++ ---help---
++ This is the BMI bus driver for the PROJECTOR Plug-In Module.
++
++config BMI_AUDIO
++ tristate "BMI Bus Audio Module support"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ This is the BMI bus driver for the Audio Plug-In Module.
++
++ Select M to make a kernel-loadable module.
++
++#source "drivers/bmi/pims/camera/Kconfig"
++
++config BMI_VH
++ tristate "BMI von Hippel Module support"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI von Hippel plug-in module
++
++ This driver can also be built as a module.
++
++config BMI_SENSOR
++ tristate "BMI Sensor Module support"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI Sensor plug-in module
++
++ This driver can also be built as a module.
++
++config BMI_ZB
++ tristate "BMI ZigBee Module support"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI ZigBee plug-in module
++
++ This driver can also be built as a module.
++
++config BMI_GSM
++ tristate "BMI GSM/UMTS Module support"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ BMI von Hippel plug-in module
++
++ This driver can also be built as a module.
++
++endmenu
++
+--- /dev/null
++++ git/drivers/bmi/pims/Makefile
+@@ -0,0 +1,17 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BUG_FACTORY_TEST) += factory_test/
++obj-$(CONFIG_BMI_GPS) += gps/
++obj-$(CONFIG_BMI_MDACC) += mdacc/
++obj-$(CONFIG_VIDEO_BMI_LCD) += lcd/
++obj-$(CONFIG_BMI_CAMERA) += camera/
++obj-$(CONFIG_BMI_AUDIO) += sound/
++obj-$(CONFIG_BMI_VH) += vonhippel/
++obj-$(CONFIG_BMI_GSM) += gsm/
++obj-$(CONFIG_BMI_SENSOR) += sensor/
++obj-$(CONFIG_VIDEO_BMI_PROJECTOR) += projector/
++obj-$(CONFIG_BMI_ZB) += zb/
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/Kconfig
+@@ -0,0 +1,23 @@
++config BMI_CAMERA
++ tristate "BMI Camera"
++ depends on MACH_BUG
++ default n
++ ---help---
++ This is the BMI Camera driver.
++
++choice
++ prompt "Select Camera"
++ depends on (BMI_CAMERA)
++
++config BMI_CAMERA_VS6624
++ tristate "ST VS6624 camera support"
++ ---help---
++ If you plan to use the ST VS6624 Camera with your BUG system, say Y here.
++
++config BMI_CAMERA_OV2640
++ tristate "Omnivision OV2640 camera support"
++ ---help---
++ If you plan to use the Omnivision OV2640 Camera with your BUG system, say Y here.
++endchoice
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/Makefile
+@@ -0,0 +1,12 @@
++#ifeq ($(CONFIG_MACH_BUG),y)
++# obj-$(CONFIG_BMI_CAMERA) += bug_v4l2_capture.o
++#endif
++
++obj-$(CONFIG_BMI_CAMERA) += bug_camera.o
++
++bmi_camera_vs6624-objs := bmi_vs6624.o vs6624_access.o
++obj-$(CONFIG_BMI_CAMERA_VS6624) += bmi_camera_vs6624.o
++
++bmi_camera_ov2640-objs := bmi_ov2640.o ov2640.o
++obj-$(CONFIG_BMI_CAMERA_OV2640) += bmi_camera_ov2640.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/bmi_ov2640.c
+@@ -0,0 +1,929 @@
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_camera.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/workqueue.h>
++#include "bug_camera.h"
++#include "ov2640.h"
++
++#define BMI_OV2640_VERSION "1.0"
++
++// BMI device ID table
++static struct bmi_device_id bmi_ov2640_tbl[] =
++{
++ { .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_CAMERA_OV2640,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_ov2640_tbl);
++
++int bmi_ov2640_probe(struct bmi_device *bdev);
++void bmi_ov2640_remove(struct bmi_device *bdev);
++int bmi_ov2640_suspend(struct bmi_device *bdev);
++int bmi_ov2640_resume(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_ov2640_driver =
++{
++ .name = "bmi_ov2640",
++ .id_table = bmi_ov2640_tbl,
++ .probe = bmi_ov2640_probe,
++ .remove = bmi_ov2640_remove,
++ };
++
++
++struct bmi_ov2640 {
++ struct bmi_device *bdev;
++ struct bmi_cam bcam;
++ unsigned int shutter; // shutter button save state
++ unsigned int zoomin; // zoomin button save state
++ unsigned int zoomout; // zoom out button save state
++ unsigned int flash; // state of camera FLASH
++ int irq;
++ struct input_dev *idev;
++ struct work_struct work;
++
++};
++
++#define work_to_bmi_ov2640(w) container_of(w, struct bmi_ov2640, work)
++
++/* IOX Bits Definitions
++
++ IOX Bit 7 CAM_RST* Output: 0 = Reset, 1 = Normal Operation
++ IOX Bit 6 GRNLED Output: 0 = Green LED on, 1 = Green LED off
++ IOX Bit 5 SER_SYNC Output: 0 = Normal Operation, 1 = send SYNC
++ IOX Bit 4 FLASH_TORCH* Output: 0 = low beam, 1 = high beam
++ IOX Bit 3 STROBE_R I/O, not used.
++ IOX Bit 2 ZOOMB Input: Zoom OUT Button: 0 = depressed, 1 = released
++ IOX Bit 1 ZOOMA Input: Zoom IN Button 0 = depressed, 1 = released
++ IOX Bit 0 GPIO0_SHUTTER* Input: Shutter Button 0 = depressed, 1 = released
++
++ GPIO Bits Definitions
++
++ GPIO Bit 3 REDLED Output: 0 = Red LED on, 1 = Red LED off
++ GPIO Bit 2 FLASHON Output: 0 = Flash LED off, 1 = Flash LED on
++ GPIO Bit 1 SER_RST* Output: 0 = Serializer Reset, 1 = Normal Operation
++ GPIO Bit 0 GPIO0_SHUTTER* Input: Shutter Button: 0 = depressed, 1 = released
++
++
++*/
++
++
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++
++// read byte from I2C IO expander
++
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer failed\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++// write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++
++// work handler
++void bmi_ov2640_buttons_work(struct work_struct * work)
++{
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *pim = work_to_bmi_ov2640(work);
++
++ unsigned char iox_data;
++ unsigned int test_value;
++ int sync_flag = 0;
++ int err;
++
++
++ // avoid i2c i/o if camera hardware not present.
++
++ if (bmi_device_present (pim->bdev) == 0) {
++ goto exit;
++ }
++
++ adap = bmi_device_get_i2c_adapter (pim->bdev);
++
++
++ // read IOX data input
++ err = ReadByte_IOX (adap, IOX_INPUT_REG, &iox_data);
++ if (err) {
++ goto exit;
++ }
++
++ // zoom in button
++ test_value = !((iox_data & 0x2) >> 1);
++ if (test_value != pim->zoomin) {
++ pim->zoomin = test_value;
++ input_report_key (pim->idev, BN_ZOOMIN, test_value);
++ sync_flag = 1;
++ }
++
++
++ // zoom out button
++ test_value = !((iox_data & 0x4) >> 2);
++ if (test_value != pim->zoomout) {
++ pim->zoomout = test_value;
++ input_report_key (pim->idev, BN_ZOOMOUT, test_value);
++ sync_flag = 1;
++ }
++
++ if ( sync_flag ) {
++ input_sync (pim->idev);
++ }
++exit:
++ enable_irq (pim->irq);
++ return;
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ struct bmi_ov2640 *pim = dummy;
++ unsigned int test_value;
++
++ int slot;
++
++ disable_irq_nosync(irq);
++
++ slot = bmi_device_get_slot(pim->bdev);
++
++
++ // shutter button on GPIO
++
++ test_value = !(bmi_read_gpio_data_reg (slot) & 0x1);
++
++ if (!test_value == pim->shutter) {
++ pim->shutter = test_value;
++ input_report_key (pim->idev, BN_SHUTTER, test_value);
++ input_sync (pim->idev);
++ }
++
++ // other buttons on I2C IOX
++ schedule_work (&pim->work);
++ return IRQ_HANDLED;
++}
++
++/*
++ * control functions
++ */
++
++
++// configure IOX IO and states
++void configure_IOX(struct bmi_ov2640 *cam)
++{
++ struct i2c_adapter *adap;
++
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, 0xC0); // CAMRST* = 1, GRNLED = Off
++ WriteByte_IOX (adap, IOX_CONTROL, 0x0F); // IOX[7:4]=OUT, IOX[3:0]=IN
++ return;
++
++}
++
++// configure GPIO IO and states
++void configure_GPIO(struct bmi_ov2640 *cam)
++{
++ // set states before turning on outputs
++
++ int slot;
++
++
++ slot = bmi_device_get_slot (cam->bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED=OFF
++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0
++
++ // configure direction
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN); // SHUTTER
++
++ // This is needed.
++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED off.
++ return;
++
++}
++
++// deconfigure IOX and GPIO
++void deconfigure_module(struct bmi_ov2640 *cam)
++{
++ int slot;
++ struct i2c_adapter *adap;
++
++ slot = bmi_device_get_slot (cam->bdev);
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++
++ if ( bmi_device_present (cam->bdev) ) {
++ WriteByte_IOX (adap, IOX_CONTROL, 0xFF);
++ }
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++}
++
++
++// configure serializer on plug-in module
++void configure_serializer(struct bmi_ov2640 *cam)
++{
++ int slot = bmi_device_get_slot (cam->bdev);
++ bmi_set_module_gpio_data (slot, 1, 1); // SER_RST=1
++}
++
++void deconfigure_serializer(struct bmi_ov2640 *cam)
++{
++ int slot = bmi_device_get_slot (cam->bdev);
++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0
++}
++
++void enable_camera(struct bmi_ov2640 *cam)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++
++ iox_data |= (0x80); //Set CAM_RST* to 1.
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ return;
++}
++
++// disable camera on plug-in module
++void disable_camera(struct bmi_ov2640 *cam)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ if (cam == NULL)
++ {
++ printk(KERN_INFO "bmi_camera_ov2640: disable_camera: NULL Pointer on cam\n");
++ return;
++ }
++ if (cam->bdev == NULL)
++ {
++ printk(KERN_INFO "bmi_camera_ov2640: disable_camera: NULL Pointer on cam->bdev\n");
++ return;
++ }
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ if ( bmi_device_present(cam->bdev) ) {
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++
++ iox_data &= ~(0x80); //Set CAM_RST* to 0;
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ }
++ return;
++}
++
++// generate sync
++void generate_camera_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++ udelay(20); // 60 MHz * 1024 = ~17 us sync time
++ return;
++}
++
++void set_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++ return;
++}
++
++void clear_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++ return;
++}
++
++
++// check serializer lock
++int check_camera_lock(void)
++{
++ return bmi_sensor_lock_status();
++}
++
++void bmi_ov2640_set_color(struct bmi_cam *cam, int bright, int saturation, int red, int green, int blue)
++{
++
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ adap = &bmi_ov2640->bdev->adap;
++
++// ov2640_set_color (adap, bright, saturation, red, green, blue);
++ printk (KERN_ERR "bmi_ov2640_set_color() - NOT IMPLEMENTED.\n");
++ return;
++
++}
++
++void bmi_ov2640_get_color(struct bmi_cam *cam, int *bright, int *saturation, int *red, int *green, int *blue)
++{
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ adap = &bmi_ov2640->bdev->adap;
++
++// ov2640_get_color (adap, bright, saturation, red, green, blue);
++ printk (KERN_ERR "bmi_ov2640_get_color() - NOT IMPLEMENTED.\n");
++ return;
++}
++
++
++
++
++void bmi_ov2640_set_ae_mode (struct bmi_cam *cam, int ae_mode)
++{
++ printk (KERN_ERR "bmi_ov2640_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++void bmi_ov2640_get_ae_mode (struct bmi_cam *cam, int *ae_mode)
++{
++ printk (KERN_ERR "bmi_ov2640_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++sensor_interface * bmi_ov2640_config (struct bmi_cam *cam, int *frame_rate, int high_quality)
++{
++
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++ int i;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ adap = &bmi_ov2640->bdev->adap;
++
++ //Bring up the serial link
++
++ bmi_sensor_active(1);
++ configure_serializer (bmi_ov2640);
++
++ adap = &bmi_ov2640->bdev->adap;
++ set_sync (adap);
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_ov2640_config() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync(adap);
++
++
++ if(!check_camera_lock()) {
++ printk(KERN_ERR "bmi_ov2640_config(): camera serializer NOT LOCKED\n");
++ }
++
++ return &cam->interface;
++
++}
++
++
++sensor_interface * bmi_ov2640_reset (struct bmi_cam *cam)
++{
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++
++
++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev);
++
++ //disable the serial link
++
++ deconfigure_serializer (bmi_ov2640);
++ bmi_sensor_inactive();
++
++ return &cam->interface;
++}
++
++int bmi_ov2640_activate (struct bmi_cam *cam, struct input_dev *idev)
++{
++ int rc = 0;
++ int i;
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++
++
++ //bmi_ov2640 struct fields
++ bmi_ov2640->idev = idev;
++
++ bmi_ov2640->shutter = 0;
++ bmi_ov2640->zoomin = 0;
++ bmi_ov2640->zoomout = 0;
++ bmi_ov2640->flash = 0;
++
++
++ // install button irq_handler
++ if (request_irq(bmi_ov2640->irq, &module_irq_handler, 0, "bmi_cam_button", bmi_ov2640)) {
++ printk (KERN_ERR
++ "bmi_ov2640_activate() - request_irq (irq = %d) failed.\n",
++ bmi_ov2640->irq);
++
++ rc = -EBUSY;
++ goto exit;
++ }
++
++ //Activate serial link
++ bmi_sensor_active(1); // rising edge clock
++ configure_serializer (bmi_ov2640);
++
++ adap = &bmi_ov2640->bdev->adap;
++ set_sync (adap);
++
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_ov2640_activate() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++
++exit:
++ return rc;
++}
++
++int bmi_ov2640_deactivate (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++
++ //De-activate serial link
++ deconfigure_serializer (bmi_ov2640);
++ bmi_sensor_inactive();
++
++ //uninstall button irq_handler
++ free_irq(bmi_ov2640->irq, bmi_ov2640);
++ return 0;
++}
++
++
++void bmi_ov2640_link_enable (struct bmi_cam *cam)
++{
++ int i;
++ struct i2c_adapter *adap;
++ struct bmi_ov2640 *bmi_ov2640;
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++
++ //Activate serial link
++ bmi_sensor_active(1); // rising edge clock
++ configure_serializer (bmi_ov2640);
++
++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev);
++
++ set_sync (adap);
++
++
++ //REWORK: Speed this up. (shorten delay)
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_ov2640_activate() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++ return;
++}
++
++
++void bmi_ov2640_link_disable (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++
++
++ //De-activate serial link
++ deconfigure_serializer (bmi_ov2640);
++ bmi_sensor_inactive();
++
++ return;
++}
++
++
++int bmi_ov2640_flash_led_off (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED off.
++ return 0;
++}
++
++int bmi_ov2640_flash_led_on (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 2, 1); // Flash LED on.
++ return 0;
++}
++
++int bmi_ov2640_flash_high_beam (struct bmi_cam *cam)
++{
++ unsigned char data;
++ struct bmi_ov2640 *bmi_ov2640;
++ struct i2c_adapter *adap;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev);
++
++ ReadByte_IOX (adap, IOX_INPUT_REG, &data);
++ data |= 0x10; //High Beam
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, data);
++
++ return 0;
++}
++
++int bmi_ov2640_flash_low_beam (struct bmi_cam *cam)
++{
++ unsigned char data;
++ struct bmi_ov2640 *bmi_ov2640;
++ struct i2c_adapter *adap;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev);
++
++ ReadByte_IOX (adap, IOX_INPUT_REG, &data);
++ data &= ~(0x10); // Low Beam
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, data);
++
++ return 0;
++}
++
++int bmi_ov2640_red_led_off (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF
++ return 0;
++}
++
++
++int bmi_ov2640_red_led_on (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 0); // Red LED=ON
++ return 0;
++}
++
++
++int bmi_ov2640_green_led_off (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ adap = bmi_device_get_i2c_adapter (bdev);
++
++ if ( bmi_device_present(bdev) ) {
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++
++ iox_data |= (0x40); //Set GRNLED to 1.(Off)
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ }
++ return 0;
++}
++
++int bmi_ov2640_green_led_on (struct bmi_cam *cam)
++{
++ struct bmi_ov2640 *bmi_ov2640;
++ struct bmi_device *bdev;
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam);
++ bdev = bmi_ov2640->bdev;
++
++ adap = bmi_device_get_i2c_adapter (bdev);
++
++ if ( bmi_device_present(bdev) ) {
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++
++ iox_data &= ~(0x40); //Set GRNLED to 0.(On)
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data & 0xF0);
++ }
++ return 0;
++}
++
++
++int bmi_ov2640_probe(struct bmi_device *bdev)
++{
++
++ int slot = bmi_device_get_slot(bdev);
++
++ // allocate a driver-specific <this> structure
++
++ struct bmi_ov2640 *bmi_ov2640 = kzalloc(sizeof(struct bmi_ov2640), GFP_KERNEL);
++ if (!bmi_ov2640) {
++ return -1;
++ }
++
++ // attach <this> bmi_device structure (so we can find it later).
++
++ bmi_device_set_drvdata(bdev, bmi_ov2640);
++ printk(KERN_INFO "bmi_ov2640: probe: bmi_ov2640 pointer 0x%p \n",bdev->dev.driver_data);
++
++ // initialize bmi_ov2640 struct
++ bmi_ov2640->bdev = bdev;
++
++ // sensor interface struct fields
++
++ bmi_ov2640->bcam.interface.clk_mode = 0; // gated
++ bmi_ov2640->bcam.interface.ext_vsync = 1; // external vsync
++ bmi_ov2640->bcam.interface.Vsync_pol = 0; // non-inverted
++ bmi_ov2640->bcam.interface.Hsync_pol = 0; // non-inverted
++ bmi_ov2640->bcam.interface.pixclk_pol = 0; // non-inverted
++ bmi_ov2640->bcam.interface.data_pol = 0; // non-inverted
++ bmi_ov2640->bcam.interface.data_width = 1; // 8-bits
++ bmi_ov2640->bcam.interface.width = 1600-1; // 1280 - SXGA 1600 - UXGA
++ bmi_ov2640->bcam.interface.height = 1200-1; // 1024 - SXGA 1200 - UXGA
++
++ bmi_ov2640->bcam.interface.pixel_fmt = IPU_PIX_FMT_UYVY; // YUV422
++ bmi_ov2640->bcam.interface.mclk = 12000000; // frequency/src
++
++ //bmi_camera_sensor struct fields
++
++ bmi_ov2640->bcam.sensor.set_color = bmi_ov2640_set_color;
++ bmi_ov2640->bcam.sensor.get_color = bmi_ov2640_get_color;
++ bmi_ov2640->bcam.sensor.set_ae_mode = bmi_ov2640_set_ae_mode;
++ bmi_ov2640->bcam.sensor.get_ae_mode = bmi_ov2640_get_ae_mode;
++ bmi_ov2640->bcam.sensor.config = bmi_ov2640_config;
++ bmi_ov2640->bcam.sensor.reset = bmi_ov2640_reset;
++
++ //bmi_camera_link struct fields
++
++ bmi_ov2640->bcam.link.enable = bmi_ov2640_link_enable;
++ bmi_ov2640->bcam.link.disable = bmi_ov2640_link_disable;
++
++ //bmi_camera_cntl struct fields
++
++ bmi_ov2640->bcam.cntl.flash_led_off = bmi_ov2640_flash_led_off;
++ bmi_ov2640->bcam.cntl.flash_led_on = bmi_ov2640_flash_led_on;
++ bmi_ov2640->bcam.cntl.flash_high_beam = bmi_ov2640_flash_high_beam;
++ bmi_ov2640->bcam.cntl.flash_low_beam = bmi_ov2640_flash_low_beam;
++ bmi_ov2640->bcam.cntl.red_led_off = bmi_ov2640_red_led_off;
++ bmi_ov2640->bcam.cntl.red_led_on = bmi_ov2640_red_led_on;
++ bmi_ov2640->bcam.cntl.green_led_off = bmi_ov2640_green_led_off;
++ bmi_ov2640->bcam.cntl.green_led_on = bmi_ov2640_green_led_on;
++
++
++ //bmi_cam struct fields
++
++ bmi_ov2640->bcam.activate = bmi_ov2640_activate ;
++ bmi_ov2640->bcam.deactivate = bmi_ov2640_deactivate;
++
++ //bmi_ov2640 struct fields
++ bmi_ov2640->shutter = 0;
++ bmi_ov2640->zoomin = 0;
++ bmi_ov2640->zoomout = 0;
++ bmi_ov2640->flash = 0;
++
++ bmi_ov2640->irq = bmi_device_get_status_irq (bdev);
++
++ //initialize struct work_struct
++ INIT_WORK (&bmi_ov2640->work, bmi_ov2640_buttons_work);
++
++ //Power stablization delay
++ mdelay(500);
++
++ //Do one-time hw initialization (e.g. patch)
++
++ // configure IOX
++ configure_IOX (bmi_ov2640);
++
++ // configure GPIO
++ configure_GPIO (bmi_ov2640);
++
++ // chip enable camera
++ enable_camera (bmi_ov2640);
++
++ ov2640_patch (&bmi_ov2640->bdev->adap);
++
++ //register with bug_camera
++
++ //REWORK: check return code
++ register_bug_camera (&bmi_ov2640->bcam, slot);
++
++ return 0;
++}
++
++void bmi_ov2640_remove(struct bmi_device *bdev)
++{
++
++ //get our <this> pointer
++ struct bmi_ov2640 *bmi_ov2640 = (struct bmi_ov2640*)(bmi_device_get_drvdata (bdev));
++ int slot = bmi_device_get_slot (bdev);
++
++ if (bdev == NULL)
++ {
++ printk(KERN_INFO "bmi_ov2640: bmi-ov2640_remove: NULL Pointer on bdev\n");
++ return;
++ }
++ if (bmi_ov2640 == NULL)
++ {
++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: NULL Pointer on bmi_ov2640\n");
++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.vendor: 0x%x\n",bdev->epid.vendor);
++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.product: 0x%x\n",bdev->epid.product);
++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.revision: 0x%x\n",bdev->epid.revision);
++ printk(KERN_INFO "bmi_ov3640: bmi_ov2640_remove: bmi_ov2640 pointer 0x%p \n",bdev->dev.driver_data);
++ return;
++ }
++ //unregister with bug_camera
++ unregister_bug_camera ( &bmi_ov2640->bcam, slot);
++
++ disable_camera (bmi_ov2640);
++ deconfigure_module (bmi_ov2640);
++
++
++ flush_scheduled_work();
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++
++ //free driver-specific structure
++ kfree (bmi_ov2640);
++ return;
++}
++
++
++static __init int bmi_ov2640_init(void)
++{
++ printk("BMI OV2640 Camera Sensor Driver v%s \n", BMI_OV2640_VERSION);
++
++// Register with BMI bus.
++ return bmi_register_driver (&bmi_ov2640_driver);
++
++}
++
++static void __exit bmi_ov2640_cleanup(void)
++{
++
++// UnRegister with BMI bus.
++ bmi_unregister_driver (&bmi_ov2640_driver);
++ return;
++}
++
++
++module_init(bmi_ov2640_init);
++module_exit(bmi_ov2640_cleanup);
++
++MODULE_AUTHOR("EnCADIS Design, Inc.");
++MODULE_DESCRIPTION("OV2640 Camera Driver");
++MODULE_LICENSE("GPL");
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/bmi_vs6624.c
+@@ -0,0 +1,915 @@
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_camera.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/workqueue.h>
++#include "bug_camera.h"
++#include "vs6624_access.h"
++
++
++// BMI device ID table
++static struct bmi_device_id bmi_vs6624_tbl[] =
++{
++ { .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_CAMERA_VS6624,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_vs6624_tbl);
++
++int bmi_vs6624_probe(struct bmi_device *bdev);
++void bmi_vs6624_remove(struct bmi_device *bdev);
++int bmi_vs6624_suspend(struct bmi_device *bdev);
++int bmi_vs6624_resume(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_vs6624_driver =
++{
++ .name = "bmi_vs6624",
++ .id_table = bmi_vs6624_tbl,
++ .probe = bmi_vs6624_probe,
++ .remove = bmi_vs6624_remove,
++ };
++
++
++struct bmi_vs6624 {
++ struct bmi_device *bdev;
++ struct bmi_cam bcam;
++ unsigned int shutter; // shutter button save state
++ unsigned int zoomin; // zoomin button save state
++ unsigned int zoomout; // zoom out button save state
++ unsigned int flash; // state of camera FLASH
++ int irq;
++ struct input_dev *idev;
++ struct work_struct work;
++
++};
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++
++// read byte from I2C IO expander
++
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ printk (KERN_ERR "ReadByte_IOX() - data = %02X\n", *data);
++
++ ret = 0;
++ }
++ else {
++ //Rework: add conditional debug messages here
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer failed\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++// write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ printk (KERN_ERR "WriteByte_IOX() - data = %02X\n", data);
++ ret = 0;
++ }
++ else {
++ //Rework: add conditional debug messages here
++
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++
++// work handler
++void bmi_vs6624_buttons_work(void *arg)
++{
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *pim = (struct bmi_vs6624*)arg;
++
++ unsigned char iox_data;
++ unsigned int test_value;
++ int sync_flag = 0;
++ int err;
++
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - enter\n");
++
++
++ // avoid i2c i/o if camera hardware not present.
++
++ if (bmi_device_present (pim->bdev) == 0) {
++ goto exit;
++ }
++
++ adap = bmi_device_get_i2c_adapter (pim->bdev);
++
++
++ // read IOX data input
++ err = ReadByte_IOX (adap, IOX_INPUT_REG, &iox_data);
++ if (err) {
++ goto exit;
++ }
++
++ // zoom in button
++ test_value = !((iox_data & 0x2) >> 1);
++ if (test_value != pim->zoomin) {
++ printk (KERN_ERR "bmi_vs6624buttons_work() - report ZOOMIN\n");
++ pim->zoomin = test_value;
++ input_report_key (pim->idev, BN_ZOOMIN, test_value);
++ sync_flag = 1;
++ }
++
++
++ // zoom out button
++ test_value = !((iox_data & 0x4) >> 2);
++ if (test_value != pim->zoomout) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - report ZOOMOUT\n");
++ pim->zoomout = test_value;
++ input_report_key (pim->idev, BN_ZOOMOUT, test_value);
++ sync_flag = 1;
++ }
++#if 0
++ // flash button
++ test_value = (iox_data & 0x8) >> 3;
++ if (test_value != pim->flash) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - report FLASH\n");
++ pim->flash = test_value;
++ input_report_key (pim->idev, BN_FLASH, test_value);
++ sync_flag = 1;
++ }
++#endif
++
++ if ( sync_flag ) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - input_sync()ing..\n");
++ input_sync (pim->idev);
++ }
++exit:
++ printk (KERN_ERR "bmi_vs6624_buttons_work() -exit\n");
++ enable_irq (pim->irq);
++ return;
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ struct bmi_vs6624 *pim = dummy;
++ unsigned int test_value;
++
++ int slot;
++
++ printk (KERN_ERR "module_irq_handler() - enter\n");
++
++ disable_irq_nosync(irq);
++
++ slot = bmi_device_get_slot(pim->bdev);
++
++
++ // shutter button on GPIO
++
++ test_value = !(bmi_read_gpio_data_reg (slot) & 0x1);
++
++ if (!test_value == pim->shutter) {
++ pim->shutter = test_value;
++ printk (KERN_ERR "module_irq_handler() - report SHUTTER\n");
++ input_report_key (pim->idev, BN_SHUTTER, test_value);
++ input_sync (pim->idev);
++ }
++
++ // other buttons on I2C IOX
++ schedule_work (&pim->work);
++ printk (KERN_ERR "module_irq_handler() - exit\n");
++ return IRQ_HANDLED;
++}
++
++/*
++ * control functions
++ */
++
++
++// configure IOX IO and states
++void configure_IOX(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap;
++
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ printk (KERN_ERR "configure_IOX() - enter\n");
++
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, 0x40); // CE=0, F_CHG=1,SYNC=0, TORCH=0
++ WriteByte_IOX (adap, IOX_CONTROL, 0x0F); // IOX[7:4]=OUT, IOX[3:0]=IN
++}
++
++// configure GPIO IO and states
++void configure_GPIO(struct bmi_vs6624 *cam)
++{
++ // set states before turning on outputs
++
++ int slot;
++
++ slot = bmi_device_get_slot (cam->bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data (slot, 2, 1); // Green LED=OFF
++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0
++
++ // configure direction
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN); // SHUTTER
++}
++
++// deconfigure IOX and GPIO
++void deconfigure_module(struct bmi_vs6624 *cam)
++{
++ int slot;
++ struct i2c_adapter *adap;
++
++ slot = bmi_device_get_slot (cam->bdev);
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++
++ if ( bmi_device_present (cam->bdev) ) {
++ WriteByte_IOX (adap, IOX_CONTROL, 0xFF);
++ }
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++}
++
++
++// configure serializer on plug-in module
++void configure_serializer(struct bmi_vs6624 *cam)
++{
++ int slot = bmi_device_get_slot (cam->bdev);
++ bmi_set_module_gpio_data (slot, 1, 1); // SER_RST=1
++}
++
++void deconfigure_serializer(struct bmi_vs6624 *cam)
++{
++ int slot = bmi_device_get_slot (cam->bdev);
++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0
++}
++
++void enable_camera(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ printk (KERN_ERR "enable_camera() enter\n");
++
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ // The first i2c read seems to mess everything up.
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++ printk (KERN_ERR "enable_camera() iox_data = %02X\n", iox_data);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data | 0x80);
++ printk (KERN_ERR "enable_camera() exit\n");
++}
++
++// disable camera on plug-in module
++void disable_camera(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ printk (KERN_ERR "disable_camera() enter\n");
++
++ adap = bmi_device_get_i2c_adapter (cam->bdev);
++
++ if ( bmi_device_present(cam->bdev) ) {
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data & 0x70);
++ }
++
++ printk (KERN_ERR "disable_camera() exit\n");
++}
++
++// generate sync
++void generate_camera_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "generate_camera_sync() - enter\n");
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++
++ printk(KERN_INFO "generate_camera_sync() - read = %02X\n", iox_data[0]);
++ printk(KERN_INFO "generate_camera_sync() - write = %02X\n", *iox_data | 0x20);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++
++ printk(KERN_INFO "generate_camera_sync() - write = %02X\n", *iox_data & 0xD0);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++ udelay(20); // 60 MHz * 1024 = ~17 us sync time
++
++ printk(KERN_INFO "generate_camera_sync() - exit\n");
++}
++
++void set_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "set_sync() - enter\n");
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++
++ printk(KERN_INFO "set_sync() - exit\n");
++}
++
++void clear_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "clear_sync() - enter\n");
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++
++ printk(KERN_INFO "clear_sync() - exit\n");
++}
++
++
++// check serializer lock
++int check_camera_lock(void)
++{
++ return bmi_sensor_lock_status();
++}
++
++void bmi_vs6624_set_color(struct bmi_cam *cam, int bright, int saturation, int red, int green, int blue)
++{
++
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ adap = &bmi_vs6624->bdev->adap;
++
++ vs6624_set_color (adap, bright, saturation, red, green, blue);
++ return;
++
++}
++
++void bmi_vs6624_get_color(struct bmi_cam *cam, int *bright, int *saturation, int *red, int *green, int *blue)
++{
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ adap = &bmi_vs6624->bdev->adap;
++
++ vs6624_get_color (adap, bright, saturation, red, green, blue);
++ return;
++}
++
++
++
++
++void bmi_vs6624_set_ae_mode (struct bmi_cam *cam, int ae_mode)
++{
++ printk (KERN_ERR "bmi_vs6624_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++void bmi_vs6624_get_ae_mode (struct bmi_cam *cam, int *ae_mode)
++{
++ printk (KERN_ERR "bmi_vs6624_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++sensor_interface * bmi_vs6624_config (struct bmi_cam *cam, int *frame_rate, int high_quality)
++{
++ //REWORK: Add code here
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++ int i;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ adap = &bmi_vs6624->bdev->adap;
++
++ printk (KERN_ERR "bmi_vs6624_CONFIG() - enter\n");
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_config(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_config(): camera serializer NOT LOCKED\n");
++ }
++
++ //Bring up the serial link
++
++ bmi_sensor_active(1);
++ configure_serializer (bmi_vs6624);
++
++ adap = &bmi_vs6624->bdev->adap;
++ set_sync (adap);
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_config() - camera serializer locked, i = %d\n", i);
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_config() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++
++
++ if(check_camera_lock()) {
++
++ printk(KERN_INFO "bmi_vs6624_config(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_config(): camera serializer NOT LOCKED\n");
++ }
++
++
++ printk (KERN_ERR "bmi_vs6624_CONFIG() - exit\n");
++ return &cam->interface;
++
++}
++
++
++sensor_interface * bmi_vs6624_reset (struct bmi_cam *cam)
++{
++ //REWORK: Add code here
++ //REWORK: What is a valid soft reset sequence ?
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ printk (KERN_ERR "bmi_vs6624_RESET() - enter\n");
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ adap = bmi_device_get_i2c_adapter (bmi_vs6624->bdev);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_reset(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_reset(): camera serializer NOT LOCKED\n");
++ }
++ //disable the serial link
++
++ deconfigure_serializer (bmi_vs6624);
++ bmi_sensor_inactive();
++
++ if(check_camera_lock()) {
++
++ printk(KERN_INFO "bmi_vs6624_reset(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_reset(): camera serializer NOT LOCKED\n");
++ }
++
++ printk (KERN_ERR "bmi_vs6624_RESET() - exit\n");
++
++ return &cam->interface;
++}
++
++int bmi_vs6624_activate (struct bmi_cam *cam, struct input_dev *idev)
++{
++ //REWORK: Add code here
++ int rc = 0;
++ int i;
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ printk (KERN_ERR "int bmi_vs6624_activate () - enter\n");
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ //bmi_vs6624 struct fields
++ bmi_vs6624->idev = idev;
++
++ bmi_vs6624->shutter = 0;
++ bmi_vs6624->zoomin = 0;
++ bmi_vs6624->zoomout = 0;
++ bmi_vs6624->flash = 0;
++
++ printk (KERN_ERR "bmi_vs6624_activate () - irq = %d\n", bmi_vs6624->irq);
++
++ // install button irq_handler
++ if (request_irq(bmi_vs6624->irq, &module_irq_handler, 0, "bmi_cam_button", bmi_vs6624)) {
++ printk (KERN_ERR
++ "bmi_vs6624_activate() - request_irq (irq = %d) failed.\n",
++ bmi_vs6624->irq);
++
++ rc = -EBUSY;
++ goto exit;
++ }
++
++ //Activate serial link
++ bmi_sensor_active(1); // rising edge clock
++ configure_serializer (bmi_vs6624);
++
++ adap = &bmi_vs6624->bdev->adap;
++ set_sync (adap);
++
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_activate() - camera serializer locked, i = %d\n", i);
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_activate() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_activate(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_activate(): camera serializer NOT LOCKED\n");
++ }
++
++
++exit:
++ printk (KERN_ERR "int bmi_vs6624_activate () - exit\n");
++ return rc;
++}
++
++int bmi_vs6624_deactivate (struct bmi_cam *cam)
++{
++ //REWORK: Add code here
++
++ struct bmi_vs6624 *bmi_vs6624;
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ //De-activate serial link
++ deconfigure_serializer (bmi_vs6624);
++ bmi_sensor_inactive();
++
++
++ //uninstall button irq_handler
++ free_irq(bmi_vs6624->irq, bmi_vs6624);
++
++
++ return 0;
++}
++
++
++void bmi_vs6624_link_enable (struct bmi_cam *cam)
++{
++ //REWORK: Add code here
++
++ int i;
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++ //Activate serial link
++ bmi_sensor_active(1); // rising edge clock
++ configure_serializer (bmi_vs6624);
++
++ adap = bmi_device_get_i2c_adapter (bmi_vs6624->bdev);
++
++ set_sync (adap);
++
++
++ //REWORK: Speed this up. (shorten delay)
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_activate() - camera serializer locked, i = %d\n", i);
++ break;
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_activate() - camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "bmi_vs6624_activate(): camera serializer LOCKED\n");
++ }
++ else {
++ printk(KERN_ERR "bmi_vs6624_activate(): camera serializer NOT LOCKED\n");
++ }
++
++ return;
++}
++
++
++void bmi_vs6624_link_disable (struct bmi_cam *cam)
++{
++ struct bmi_vs6624 *bmi_vs6624;
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ //De-activate serial link
++ deconfigure_serializer (bmi_vs6624);
++ bmi_sensor_inactive();
++
++ return;
++}
++
++
++
++int bmi_vs6624_red_led_off (struct bmi_cam *cam)
++{
++ struct bmi_vs6624 *bmi_vs6624;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ bdev = bmi_vs6624->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF
++ return 0;
++}
++
++
++int bmi_vs6624_red_led_on (struct bmi_cam *cam)
++{
++ struct bmi_vs6624 *bmi_vs6624;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ bdev = bmi_vs6624->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 3, 0); // Red LED=ON
++ return 0;
++}
++
++
++int bmi_vs6624_green_led_off (struct bmi_cam *cam)
++{
++ struct bmi_vs6624 *bmi_vs6624;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ bdev = bmi_vs6624->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 2, 1); // Green LED=OFF
++ return 0;
++}
++
++
++int bmi_vs6624_green_led_on (struct bmi_cam *cam)
++{
++ struct bmi_vs6624 *bmi_vs6624;
++ struct bmi_device *bdev;
++ int slot;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ bdev = bmi_vs6624->bdev;
++
++ slot = bmi_device_get_slot (bdev);
++
++ bmi_set_module_gpio_data (slot, 2, 0); // Green LED=ON
++ return 0;
++}
++
++
++int bmi_vs6624_probe(struct bmi_device *bdev)
++{
++
++ //REWORK: Add code here
++
++ int slot = bmi_device_get_slot(bdev);
++
++
++ // allocate a driver-specific <this> structure
++
++ struct bmi_vs6624 *bmi_vs6624 = kzalloc(sizeof(struct bmi_vs6624), GFP_KERNEL);
++ if (!bmi_vs6624) {
++ return -1;
++ }
++
++ // attach <this> bmi_device structure (so we can find it later).
++ bmi_device_set_drvdata(bdev, bmi_vs6624);
++
++
++ // initialize bmi_vs6624 struct
++ bmi_vs6624->bdev = bdev;
++
++ // sensor interface struct fields
++# if 1
++ bmi_vs6624->bcam.interface.clk_mode = 0; // gated
++ bmi_vs6624->bcam.interface.ext_vsync = 1; // external vsync
++#else
++ bmi_vs6624->bcam.interface.clk_mode = 2; // progressive
++ bmi_vs6624->bcam.interface.ext_vsync = 0; // internal vsync
++# endif
++ bmi_vs6624->bcam.interface.Vsync_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.Hsync_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.pixclk_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.data_pol = 0; // non-inverted MTW=1
++ bmi_vs6624->bcam.interface.data_width = 1; // 8-bits
++ bmi_vs6624->bcam.interface.width = 1280-1; // 1280 - SXGA
++ bmi_vs6624->bcam.interface.height = 1024-1; // 1024 - SXGA
++
++ bmi_vs6624->bcam.interface.pixel_fmt = IPU_PIX_FMT_UYVY; // YUV422
++ bmi_vs6624->bcam.interface.mclk = 12000000; // frequency/src
++
++ //bmi_camera_sensor struct fields
++
++ bmi_vs6624->bcam.sensor.set_color = bmi_vs6624_set_color;
++ bmi_vs6624->bcam.sensor.get_color = bmi_vs6624_get_color;
++ bmi_vs6624->bcam.sensor.set_ae_mode = bmi_vs6624_set_ae_mode;
++ bmi_vs6624->bcam.sensor.get_ae_mode = bmi_vs6624_get_ae_mode;
++ bmi_vs6624->bcam.sensor.config = bmi_vs6624_config;
++ bmi_vs6624->bcam.sensor.reset = bmi_vs6624_reset;
++
++ //bmi_camera_link struct fields
++
++ bmi_vs6624->bcam.link.enable = bmi_vs6624_link_enable;
++ bmi_vs6624->bcam.link.disable = bmi_vs6624_link_disable;
++
++ //bmi_camera_cntl struct fields
++
++ bmi_vs6624->bcam.cntl.flash_led_off = 0;
++ bmi_vs6624->bcam.cntl.flash_led_off = 0;
++ bmi_vs6624->bcam.cntl.flash_high_beam = 0;
++ bmi_vs6624->bcam.cntl.flash_low_beam = 0;
++ bmi_vs6624->bcam.cntl.red_led_off = bmi_vs6624_red_led_off;
++ bmi_vs6624->bcam.cntl.red_led_on = bmi_vs6624_red_led_on;
++ bmi_vs6624->bcam.cntl.green_led_off = bmi_vs6624_green_led_off;
++ bmi_vs6624->bcam.cntl.green_led_on = bmi_vs6624_green_led_on;
++
++
++ //bmi_cam struct fields
++
++ bmi_vs6624->bcam.activate = bmi_vs6624_activate ;
++ bmi_vs6624->bcam.deactivate = bmi_vs6624_deactivate;
++
++ //bmi_vs6624 struct fields
++ bmi_vs6624->shutter = 0;
++ bmi_vs6624->zoomin = 0;
++ bmi_vs6624->zoomout = 0;
++ bmi_vs6624->flash = 0;
++
++ bmi_vs6624->irq = bmi_device_get_status_irq (bdev);
++
++ //initialize struct work_struct
++ INIT_WORK (&bmi_vs6624->work, bmi_vs6624_buttons_work, bmi_vs6624);
++
++ //Power stablization delay
++ mdelay(500);
++
++ //Do one-time hw initialization (e.g. patch)
++
++ // configure IOX
++ configure_IOX (bmi_vs6624);
++
++ // configure GPIO
++ configure_GPIO (bmi_vs6624);
++
++ // chip enable camera
++ enable_camera (bmi_vs6624);
++
++ vs6624_patch (&bmi_vs6624->bdev->adap);
++
++ //register with bug_camera
++
++ //REWORK: check return code
++ register_bug_camera (&bmi_vs6624->bcam, slot);
++
++ return 0;
++}
++
++void bmi_vs6624_remove(struct bmi_device *bdev)
++{
++ //REWORK: Add code here
++
++
++ //get our <this> pointer
++ struct bmi_vs6624 *bmi_vs6624 = (struct bmi_vs6624*)(bmi_device_get_drvdata (bdev));
++ int slot = bmi_device_get_slot (bdev);
++
++
++ //unregister with bug_camera
++ unregister_bug_camera ( &bmi_vs6624->bcam, slot);
++
++ //REWORK: Avoid I2c access if camera module is not present.
++
++ disable_camera (bmi_vs6624);
++ deconfigure_module (bmi_vs6624);
++
++
++ flush_scheduled_work();
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++
++ //free driver-specific structure
++ kfree (bmi_vs6624);
++ return;
++}
++
++
++static __init int bmi_vs6624_init(void)
++{
++
++// Register with BMI bus.
++ return bmi_register_driver (&bmi_vs6624_driver);
++
++}
++
++static void __exit bmi_vs6624_cleanup(void)
++{
++
++// UnRegister with BMI bus.
++ bmi_unregister_driver (&bmi_vs6624_driver);
++ return;
++}
++
++
++module_init(bmi_vs6624_init);
++module_exit(bmi_vs6624_cleanup);
++
++MODULE_AUTHOR("EnCADIS Design, Inc.");
++MODULE_DESCRIPTION("VS6624 Camera Driver");
++MODULE_LICENSE("GPL");
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/bug_camera.c
+@@ -0,0 +1,611 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <linux/cdev.h>
++#include <linux/bmi/bmi_camera.h>
++#include "bug_camera.h"
++
++#define BUG_CAMERA_VERSION "1.0"
++
++
++struct cam_ctl
++{
++ int slot;
++ struct cdev cdev;
++ struct device *class_dev;
++};
++
++// private device structure
++struct bug_cam
++{
++ unsigned int cam_cnt; //number of cameras present
++ unsigned int active; //active camera slot
++
++ struct bmi_cam *bcam[4]; //slot-specific behavior
++
++ struct input_dev *input_dev; // input device
++ struct cam_ctl cntl[4]; // control character device
++ struct device *class_dev;
++ int cntl_devno; // control device number
++ int open_flag; // force single open
++};
++
++static struct bug_cam bug_cam;
++
++static int cntl_open (struct inode *, struct file *);
++static int cntl_release (struct inode *, struct file *);
++static int cntl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
++// control file operations
++
++struct file_operations cam_ctl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++/*
++ * control device operations
++ */
++
++static int cam_ctl_major;
++
++int ctl_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BUG Camera Control");
++
++ if (retval) {
++ return -1;
++ }
++ cam_ctl_major = MAJOR(dev_id);
++ return 0;
++}
++
++void ctl_clean (void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(cam_ctl_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int ctl_probe (struct cam_ctl *cam_ctl, int slot)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ cdev = &cam_ctl->cdev;
++ cdev_init (cdev, &cam_ctl_fops);
++
++ dev_id = MKDEV (cam_ctl_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++ bmi_class = bmi_get_bmi_class ();
++
++ cam_ctl->class_dev = device_create (bmi_class, NULL, MKDEV(cam_ctl_major, slot), cam_ctl, "bmi_cam_ctl_m%i", slot+1);
++
++ if (IS_ERR(cam_ctl->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_cam_ctl_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(cam_ctl->class_dev));
++ cam_ctl->class_dev = NULL;
++ }
++ cam_ctl->slot = slot;
++
++ return ret;
++}
++
++void ctl_remove (struct cam_ctl *cam_ctl, int slot)
++{
++ struct class *bmi_class;
++
++ bmi_class = bmi_get_bmi_class ();
++ device_destroy (bmi_class, MKDEV(cam_ctl_major, slot));
++
++ cam_ctl->class_dev = 0;
++
++ cdev_del (&cam_ctl->cdev);
++ return;
++}
++
++// open
++static int cntl_open(struct inode *inode, struct file *filp)
++{
++ if (bug_cam.open_flag) {
++ return - EBUSY;
++ }
++ bug_cam.open_flag = 1;
++ filp->private_data = &bug_cam;
++ return 0;
++}
++
++// release
++static int cntl_release(struct inode *inode, struct file *filp)
++{
++ bug_cam.open_flag = 0;
++ return 0;
++}
++
++
++
++
++static struct bmi_cam* get_selected (void)
++{
++ struct bmi_cam *bcam;
++
++ if (bug_cam.active == -1) {
++ return 0;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++ return bcam;
++
++}
++
++
++static int select_slot (int slot)
++{
++ struct bmi_cam *bcam;
++
++ // validate slot number
++ if ((slot < 0) || slot > 3) {
++
++ printk(KERN_ERR
++ "bug_camera.c: Invalid value (%d) for camera selection.\n",
++ slot);
++
++ return -EINVAL;
++ }
++
++ // error if this slot not registered
++ if ( bug_cam.bcam [slot] == NULL ) {
++ return -ENODEV;
++ }
++
++ // abort if this slot already active
++ if (bug_cam.active == slot) {
++ return 0;
++ }
++
++ // if another slot is active, deactivate it.
++ if (bug_cam.active != -1) {
++ bcam = bug_cam.bcam [bug_cam.active];
++ if ((bcam) && (bcam->deactivate)) {
++ bcam->deactivate (bcam);
++ }
++ }
++
++ // activate this slot
++ bcam = bug_cam.bcam [slot];
++ if (bcam->activate) {
++ bcam->activate (bcam, bug_cam.input_dev);
++ }
++ bug_cam.active = slot;
++ return 0;
++}
++
++
++// ioctl
++static int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct bmi_cam *bcam;
++ int err;
++
++ switch (cmd) {
++
++ // error if no camera selected. (active)
++
++ case BMI_CAM_FLASH_LED_ON:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.flash_led_on)) {
++ bcam->cntl.flash_led_on (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_FLASH_LED_OFF:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.flash_led_off)) {
++ bcam->cntl.flash_led_off (bcam);
++ }
++ return 0;
++
++
++ case BMI_CAM_FLASH_HIGH_BEAM:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.flash_high_beam)) {
++ bcam->cntl.flash_high_beam (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_FLASH_LOW_BEAM:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.flash_low_beam)) {
++ bcam->cntl.flash_low_beam (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_RED_LED_OFF:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.red_led_off)) {
++ bcam->cntl.red_led_off (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_RED_LED_ON:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.red_led_on)) {
++ bcam->cntl.red_led_on (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_GREEN_LED_OFF:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.green_led_off)) {
++ bcam->cntl.green_led_off (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_GREEN_LED_ON:
++
++ bcam = get_selected();
++ if ((bcam) && (bcam->cntl.green_led_on)) {
++ bcam->cntl.green_led_on (bcam);
++ }
++ return 0;
++
++ case BMI_CAM_SELECT:
++
++ err = select_slot (arg);
++ return err;
++
++ case BMI_CAM_GET_SELECTED:
++
++ return (int) bug_cam.active;
++
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++
++void bug_camera_set_color(int bright, int saturation, int red, int green, int blue)
++{
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++
++ if (bug_cam.active == -1) {
++ return;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->sensor.set_color)) {
++ bcam->sensor.set_color (bcam, bright, saturation, red, green, blue);
++ }
++ return;
++
++}
++
++void bug_camera_get_color(int *bright, int *saturation, int *red, int *green, int *blue)
++{
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++
++ if (bug_cam.active == -1) {
++ return;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->sensor.get_color)) {
++ bcam->sensor.get_color (bcam, bright, saturation, red, green, blue);
++ }
++ return;
++}
++
++
++
++
++void bug_camera_set_ae_mode (int ae_mode)
++{
++ //delegate to active bmi_cam.
++ printk (KERN_ERR " bug_camera_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++void bug_camera_get_ae_mode (int *ae_mode)
++{
++ //delegate to active bmi_cam.
++ printk (KERN_ERR " bug_camera_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++sensor_interface * bug_camera_config (int *frame_rate, int high_quality)
++{
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++ sensor_interface *sensor_if = 0;
++
++ if (bug_cam.active == -1) {
++ return 0;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->sensor.config)) {
++ sensor_if = bcam->sensor.config (bcam, frame_rate, high_quality);
++ }
++ return sensor_if;
++}
++
++
++sensor_interface * bug_camera_reset (void)
++{
++
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++ sensor_interface *sensor_if = 0;
++
++ if (bug_cam.active == -1) {
++ return 0;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->sensor.reset)) {
++ sensor_if = bcam->sensor.reset(bcam);
++ }
++ return sensor_if;
++}
++
++void bug_camera_link_enable (void)
++{
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++
++ if (bug_cam.active == -1) {
++ return;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->link.enable)) {
++ bcam->link.enable(bcam);
++ }
++ return;
++}
++
++void bug_camera_link_disable (void)
++{
++ //delegate to active bmi_cam.
++
++ struct bmi_cam *bcam;
++
++ if (bug_cam.active == -1) {
++ return;
++ }
++
++ bcam = bug_cam.bcam [bug_cam.active];
++
++ if ((bcam) && (bcam->link.disable)) {
++ bcam->link.disable(bcam);
++ }
++ return;
++}
++
++
++// Link point for bug_v4l2_capture
++
++struct camera_sensor camera_sensor_if = {
++
++ set_color: bug_camera_set_color,
++ get_color: bug_camera_get_color,
++ config: bug_camera_config,
++ reset: bug_camera_reset,
++};
++
++
++struct camera_link camera_link_if = {
++ enable: bug_camera_link_enable,
++ disable: bug_camera_link_disable,
++
++};
++
++int register_bug_camera( struct bmi_cam *bcam, int slot)
++{
++ printk (KERN_ERR "register_bug_camera() - slot = %d\n", slot);
++
++ if (!bcam) {
++ return -1;
++ }
++ if ((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if ( bug_cam.bcam [slot]) {
++ return -1;
++ }
++ else {
++ bug_cam.bcam [slot] = bcam;
++ bug_cam.cam_cnt += 1;
++ }
++
++ if (ctl_probe(&bug_cam.cntl[slot], slot)) {
++ printk(KERN_ERR "\n");
++ }
++ // Activate this camera if no other is active
++ if ( bug_cam.active == -1) {
++ bug_cam.active = slot;
++ bcam->activate( bcam, bug_cam.input_dev);
++ }
++
++ return 0;
++
++}
++
++int unregister_bug_camera( struct bmi_cam *bcam, int slot)
++{
++
++ if (!bcam) {
++ return -1;
++ }
++ if ((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if ( bug_cam.bcam [slot] != bcam) {
++ return -1;
++ }
++ else {
++ bug_cam.bcam [slot] = 0;
++ bug_cam.cam_cnt -= 1;
++
++ // Deactivate this camera if active
++
++ if (bug_cam.active == slot) {
++ bcam->deactivate( bcam);
++ bug_cam.active = -1;
++ }
++
++ }
++ return 0;
++}
++
++static __init int bug_camera_init(void)
++{
++ int err = 0;
++ struct class *bmi_class;
++
++ printk("BUG Camera Driver v%s \n", BUG_CAMERA_VERSION);
++
++ memset (&bug_cam, 0, sizeof(struct bug_cam));
++
++ //No camera is active.
++ bug_cam.active = -1;
++
++ //No cameras registered.
++ bug_cam.cam_cnt = 0;
++
++ // Allocate and Register input device.
++
++ // allocate input device
++ bug_cam.input_dev = input_allocate_device();
++ if (!bug_cam.input_dev) {
++ printk(KERN_ERR "bug_camera_init: Can't allocate input_dev\n");
++ err = -ENOMEM;
++ goto exit;
++ }
++
++ // set up input device
++ bug_cam.input_dev->name = "bug_cam";
++ bug_cam.input_dev->phys = "bug_cam";
++ bug_cam.input_dev->id.bustype = BUS_BMI;
++ //bug_cam.input_dev->private = &bug_cam;
++ bug_cam.input_dev->evbit[0] = BIT(EV_KEY);
++ bug_cam.input_dev->keybit[BIT_WORD(BN_SHUTTER)] = BIT_MASK(BN_SHUTTER) |
++ BIT_MASK(BN_ZOOMIN) |
++ BIT_MASK(BN_ZOOMOUT);
++ // register input device
++ err = input_register_device (bug_cam.input_dev);
++ if (err) {
++ printk(KERN_ERR
++ "bug_camera_init() - input_register_device failed.\n");
++ input_free_device(bug_cam.input_dev);
++ goto exit;
++ }
++
++ //Register character device.
++ /*
++ // allocate char device number
++ err = alloc_chrdev_region (&bug_cam.cntl_devno, 0, 1,
++ "bug_camera_control");
++ if (err < 0) {
++ printk(KERN_ERR "bug_camera_init(): alloc_chrdev_region failed.\n");
++ goto err_exit;
++ }
++
++ // init and add control character device
++ cdev_init (&bug_cam.cntl, &cntl_fops);
++
++ err = cdev_add (&bug_cam.cntl, bug_cam.cntl_devno, 1);
++ if (err ) {
++ printk(KERN_ERR "bmi_camera_init(): cdev_add failed\n");
++ goto err_exit2;
++ }
++
++ // create class device
++ bmi_class = bmi_get_bmi_class ();
++
++ bug_cam.class_dev = device_create (bmi_class, NULL, bug_cam.cntl_devno, &bug_cam, "bug_camera_control");
++
++ if (IS_ERR(bug_cam.class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bug_camera; errno = %ld\n",
++ PTR_ERR(bug_cam.class_dev));
++ bug_cam.class_dev = NULL;
++ goto err_exit2;
++ }
++ */
++ goto exit;
++
++err_exit2:
++ unregister_chrdev_region (bug_cam.cntl_devno, 1);
++err_exit:
++ input_unregister_device (bug_cam.input_dev);
++exit:
++ return err;
++}
++
++static void __exit bug_camera_clean(void)
++{
++ /* struct class *bmi_class;
++
++ bmi_class = bmi_get_bmi_class ();
++ device_destroy (bmi_class, bug_cam.cntl_devno);*/
++
++ bug_cam.class_dev = 0;
++ // Unregister character device.
++ unregister_chrdev_region (bug_cam.cntl_devno, 1);
++
++ // Unregister input device.
++ input_unregister_device (bug_cam.input_dev);
++
++// input_free_device (bug_cam.input_dev);
++ return;
++}
++
++
++module_init(bug_camera_init);
++module_exit(bug_camera_clean);
++
++// Exported symbols
++EXPORT_SYMBOL(camera_sensor_if);
++EXPORT_SYMBOL(camera_link_if);
++EXPORT_SYMBOL(register_bug_camera);
++EXPORT_SYMBOL(unregister_bug_camera);
++
++MODULE_AUTHOR("EnCADIS Design, Inc.");
++MODULE_DESCRIPTION("Bug Camera Driver");
++MODULE_LICENSE("GPL");
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/bug_camera.h
+@@ -0,0 +1,72 @@
++#ifndef BUG_CAMARA_H
++#define BUG_CAMARA_H
++
++#include <linux/bmi.h>
++#include <mach/bug_v4l2_capture.h>
++
++
++struct bmi_cam;
++struct input_dev;
++
++# if 1
++struct bmi_camera_sensor {
++
++ void (*set_color) (struct bmi_cam *bcam, int bright, int saturation, int red, int green,
++ int blue);
++
++ void (*get_color) (struct bmi_cam *bcam, int *bright, int *saturation, int *red, int *green,
++ int *blue);
++
++ void (*set_ae_mode) (struct bmi_cam *bcam, int ae_mode);
++ void (*get_ae_mode) (struct bmi_cam *bcam, int *ae_mode);
++ sensor_interface *(*config) (struct bmi_cam *bcam, int *frame_rate, int high_quality);
++ sensor_interface *(*reset) (struct bmi_cam *bcam);
++};
++
++struct bmi_camera_link {
++
++ void (*enable) (struct bmi_cam *bcam);
++ void (*disable) (struct bmi_cam *bcam);
++
++};
++# endif
++
++struct bmi_camera_cntl {
++
++ int (*flash_led_on) (struct bmi_cam *bcam);
++ int (*flash_led_off) (struct bmi_cam *bcam);
++ int (*flash_high_beam) (struct bmi_cam *bcam);
++ int (*flash_low_beam ) (struct bmi_cam *bcam);
++ int (*red_led_off) (struct bmi_cam *bcam);
++ int (*red_led_on) (struct bmi_cam *bcam);
++ int (*green_led_off) (struct bmi_cam *bcam);
++ int (*green_led_on) (struct bmi_cam *bcam);
++
++};
++
++struct bmi_cam {
++
++ sensor_interface interface; // pointer to this struct is returned by config()
++
++ struct bmi_camera_sensor sensor; // v4l function pointers
++
++ struct bmi_camera_link link; // bug link control function pointers
++
++ struct bmi_camera_cntl cntl; // bmi camera control function pointers
++
++
++ int (*activate) (struct bmi_cam *cam, struct input_dev *idev);
++
++ int (*deactivate) (struct bmi_cam *cam);
++
++
++};
++
++
++
++int register_bug_camera( struct bmi_cam *bcam, int slot);
++int unregister_bug_camera( struct bmi_cam *bcam, int slot);
++
++
++#endif
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/ov2640.c
+@@ -0,0 +1,301 @@
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <mach/mxc_i2c.h>
++
++/* I2C Slave Address */
++#define OV2640_I2C_ADDRESS 0x30 // 7-bit address
++
++
++int ov2640_ReadByte(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with 8-Bit Pointer */
++
++ rmsg[0].addr = OV2640_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = OV2640_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ov2640_ReadByte() - i2c_transfer failed.\n");
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++int ov2640_WriteByte(struct i2c_adapter *adap, unsigned char addr, unsigned char offset, unsigned char data)
++{
++ int ret;
++ struct i2c_msg wmsg;
++ int num_msgs;
++
++ char buf[2];
++
++ buf[0] = (char)offset;
++ buf[1] = (char)data;
++
++
++ wmsg.addr = addr >> 1;
++ wmsg.flags = 0; /* write */
++ wmsg.len = 2;
++ wmsg.buf = buf;
++ num_msgs = 1;
++
++ ret = i2c_transfer (adap, &wmsg, num_msgs);
++
++ if (ret == 1) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ov2640_WriteByte() - i2c_transfer failed.\n");
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++
++void load_2640_12MHZ_Initial_UXGA_YUV (struct i2c_adapter *adap)
++
++{
++
++ // ;2640_Initial_100206.ovt
++ ov2640_WriteByte (adap, 0x60, 0xff, 0x01);
++ ov2640_WriteByte (adap, 0x60, 0x12, 0x80);
++
++ msleep(1); // delay 1ms
++
++ ov2640_WriteByte (adap, 0x60, 0xff, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x2c, 0xff);
++ ov2640_WriteByte (adap, 0x60, 0x2e, 0xdf);
++ ov2640_WriteByte (adap, 0x60, 0xff, 0x01);
++ ov2640_WriteByte (adap, 0x60, 0x3c, 0x32);
++// ov2640_WriteByte (adap, 0x60, 0x11, 0x01); //7.5fps);
++ ov2640_WriteByte (adap, 0x60, 0x11, 0x00); //7.5fps for 48;
++ ov2640_WriteByte (adap, 0x60, 0x09, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x04, 0x28);
++ ov2640_WriteByte (adap, 0x60, 0x13, 0xe5);
++ ov2640_WriteByte (adap, 0x60, 0x14, 0x48);
++ ov2640_WriteByte (adap, 0x60, 0x2c, 0x0c);
++ ov2640_WriteByte (adap, 0x60, 0x33, 0x78);
++ ov2640_WriteByte (adap, 0x60, 0x3a, 0x33);
++ ov2640_WriteByte (adap, 0x60, 0x3b, 0xfb);
++ ov2640_WriteByte (adap, 0x60, 0x3e, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x43, 0x11);
++ ov2640_WriteByte (adap, 0x60, 0x16, 0x10);
++ ov2640_WriteByte (adap, 0x60, 0x39, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x35, 0x88);
++ ov2640_WriteByte (adap, 0x60, 0x22, 0x0a);
++ ov2640_WriteByte (adap, 0x60, 0x37, 0x40);
++ ov2640_WriteByte (adap, 0x60, 0x23, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x34, 0xa0);
++ ov2640_WriteByte (adap, 0x60, 0x36, 0x1a);
++ ov2640_WriteByte (adap, 0x60, 0x06, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x07, 0xc0);
++ ov2640_WriteByte (adap, 0x60, 0x0d, 0xb7);
++ ov2640_WriteByte (adap, 0x60, 0x0e, 0x01);
++ ov2640_WriteByte (adap, 0x60, 0x4c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x4a, 0x81);
++ ov2640_WriteByte (adap, 0x60, 0x21, 0x99);
++ ov2640_WriteByte (adap, 0x60, 0x24, 0x3a);
++ ov2640_WriteByte (adap, 0x60, 0x25, 0x32);
++ ov2640_WriteByte (adap, 0x60, 0x26, 0x82);
++ ov2640_WriteByte (adap, 0x60, 0x5c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x63, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x5d, 0x55);
++ ov2640_WriteByte (adap, 0x60, 0x5e, 0x7d);
++ ov2640_WriteByte (adap, 0x60, 0x5f, 0x7d);
++ ov2640_WriteByte (adap, 0x60, 0x60, 0x55);
++ ov2640_WriteByte (adap, 0x60, 0x61, 0x70);
++ ov2640_WriteByte (adap, 0x60, 0x62, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0x7c, 0x05);
++ ov2640_WriteByte (adap, 0x60, 0x20, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0x28, 0x30);
++ ov2640_WriteByte (adap, 0x60, 0x6c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x6d, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0x6e, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x70, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x71, 0x94);
++ ov2640_WriteByte (adap, 0x60, 0x73, 0xc1);
++// ov2640_WriteByte (adap, 0x60, 0x3d, 0x28); //12MHz XVCLK
++ ov2640_WriteByte (adap, 0x60, 0x3d, 0x30); //12MHz XVCLK -> 48 MHz);
++// ov2640_WriteByte (adap, 0x60, 0x3d, 0x38); //12MHz XVCLK -> 24 MHz); //MTW
++ ov2640_WriteByte (adap, 0x60, 0x5a, 0x57);
++ ov2640_WriteByte (adap, 0x60, 0x4f, 0xbb);
++ ov2640_WriteByte (adap, 0x60, 0x50, 0x9c);
++ ov2640_WriteByte (adap, 0x60, 0x12, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x17, 0x11);
++ ov2640_WriteByte (adap, 0x60, 0x18, 0x76); //M+
++ ov2640_WriteByte (adap, 0x60, 0x19, 0x01);
++ ov2640_WriteByte (adap, 0x60, 0x1a, 0x97);
++ ov2640_WriteByte (adap, 0x60, 0x32, 0x36);
++
++ ov2640_WriteByte (adap, 0x60, 0xff, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xe5, 0x7f);
++ ov2640_WriteByte (adap, 0x60, 0xf9, 0xc0);
++ ov2640_WriteByte (adap, 0x60, 0x41, 0x24);
++ ov2640_WriteByte (adap, 0x60, 0xe0, 0x14);
++ ov2640_WriteByte (adap, 0x60, 0x76, 0xff);
++ ov2640_WriteByte (adap, 0x60, 0x33, 0xa0);
++ ov2640_WriteByte (adap, 0x60, 0x42, 0x20);
++ ov2640_WriteByte (adap, 0x60, 0x43, 0x18);
++ ov2640_WriteByte (adap, 0x60, 0x4c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x87, 0xd0);
++ ov2640_WriteByte (adap, 0x60, 0x88, 0x3f);
++ ov2640_WriteByte (adap, 0x60, 0xd7, 0x03);
++ ov2640_WriteByte (adap, 0x60, 0xd9, 0x10);
++ ov2640_WriteByte (adap, 0x60, 0xd3, 0x82);
++ ov2640_WriteByte (adap, 0x60, 0xc8, 0x08);
++ ov2640_WriteByte (adap, 0x60, 0xc9, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0x7c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x7c, 0x03);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x48);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x48);
++ ov2640_WriteByte (adap, 0x60, 0x7c, 0x08);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x20);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x10);
++ ov2640_WriteByte (adap, 0x60, 0x7d, 0x0e);
++ ov2640_WriteByte (adap, 0x60, 0x90, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x0e);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x1a);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x31);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x5a);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x69);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x75);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x7e);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x88);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x8f);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x96);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0xa3);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0xaf);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0xc4);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0xd7);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0xe8);
++ ov2640_WriteByte (adap, 0x60, 0x91, 0x20);
++ ov2640_WriteByte (adap, 0x60, 0x92, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x06);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0xe3);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x05);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x05);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x93, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x96, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x08);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x19);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x0c);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x24);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x30);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x28);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x26);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x02);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x98);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x97, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xc3, 0xed);
++ ov2640_WriteByte (adap, 0x60, 0xa4, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xa8, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xc5, 0x11);
++ ov2640_WriteByte (adap, 0x60, 0xc6, 0x51);
++ ov2640_WriteByte (adap, 0x60, 0xbf, 0x80);
++ ov2640_WriteByte (adap, 0x60, 0xc7, 0x10);
++ ov2640_WriteByte (adap, 0x60, 0xb6, 0x66);
++ ov2640_WriteByte (adap, 0x60, 0xb8, 0xa5);
++ ov2640_WriteByte (adap, 0x60, 0xb7, 0x64);
++ ov2640_WriteByte (adap, 0x60, 0xb9, 0x7c);
++ ov2640_WriteByte (adap, 0x60, 0xb3, 0xaf);
++ ov2640_WriteByte (adap, 0x60, 0xb4, 0x97);
++ ov2640_WriteByte (adap, 0x60, 0xb5, 0xff);
++ ov2640_WriteByte (adap, 0x60, 0xb0, 0xc5);
++ ov2640_WriteByte (adap, 0x60, 0xb1, 0x94);
++ ov2640_WriteByte (adap, 0x60, 0xb2, 0x0f);
++ ov2640_WriteByte (adap, 0x60, 0xc4, 0x5c);
++//
++ ov2640_WriteByte (adap, 0x60, 0xc0, 0xca); //M+
++ ov2640_WriteByte (adap, 0x60, 0xc1, 0x96);
++ ov2640_WriteByte (adap, 0x60, 0x8c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x86, 0x3d); //2M
++ ov2640_WriteByte (adap, 0x60, 0x50, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x51, 0x90);
++ ov2640_WriteByte (adap, 0x60, 0x52, 0x2c);
++ ov2640_WriteByte (adap, 0x60, 0x53, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x54, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x55, 0x88);
++ ov2640_WriteByte (adap, 0x60, 0x57, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x5a, 0x90);
++ ov2640_WriteByte (adap, 0x60, 0x5b, 0x2c);
++ ov2640_WriteByte (adap, 0x60, 0x5c, 0x05);
++//
++ ov2640_WriteByte (adap, 0x60, 0xc3, 0xed);
++ ov2640_WriteByte (adap, 0x60, 0x7f, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xda, 0x01); //UYVY
++ ov2640_WriteByte (adap, 0x60, 0xd3, 0x82);
++ ov2640_WriteByte (adap, 0x60, 0xe5, 0x1f);
++ ov2640_WriteByte (adap, 0x60, 0xe1, 0x67);
++ ov2640_WriteByte (adap, 0x60, 0xe0, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0xdd, 0x7f);
++ ov2640_WriteByte (adap, 0x60, 0x05, 0x00);
++// ov2640_WriteByte (adap, 0x60, 0xff, 0x01);
++}
++
++void load_2640_UXGA(struct i2c_adapter *adap)
++{
++
++// ;1600x1200
++ ov2640_WriteByte (adap, 0x60, 0xc0, 0xca); //M+
++ ov2640_WriteByte (adap, 0x60, 0xc1, 0x96);
++ ov2640_WriteByte (adap, 0x60, 0x8c, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x86, 0x3d); //2M
++ ov2640_WriteByte (adap, 0x60, 0x50, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x51, 0x90);
++ ov2640_WriteByte (adap, 0x60, 0x52, 0x2c);
++ ov2640_WriteByte (adap, 0x60, 0x53, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x54, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x55, 0x88);
++ ov2640_WriteByte (adap, 0x60, 0x57, 0x00);
++ ov2640_WriteByte (adap, 0x60, 0x5a, 0x90);
++ ov2640_WriteByte (adap, 0x60, 0x5b, 0x2c);
++ ov2640_WriteByte (adap, 0x60, 0x5c, 0x05);
++}
++
++
++
++
++void ov2640_patch (struct i2c_adapter *adap)
++{
++ load_2640_12MHZ_Initial_UXGA_YUV (adap);
++ load_2640_UXGA(adap);
++
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/ov2640.h
+@@ -0,0 +1,14 @@
++#ifndef VS6624_ACCESS_H
++#define VS6624_ACCESS_H
++
++#include <linux/i2c.h>
++
++void ov2640_patch (struct i2c_adapter *adap);
++
++int vs6624_ReadByte(struct i2c_adapter *adap, unsigned short offset, unsigned char *data);
++int vs6624_WriteByte(struct i2c_adapter *adap, unsigned short offset, unsigned char data);
++int vs6624_WriteSequence(struct i2c_adapter *adap, const unsigned short array[][2], unsigned short len);
++void vs6624_dump_regs(struct i2c_adapter *adap);
++
++#endif
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/vs6624_access.c
+@@ -0,0 +1,597 @@
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <mach/mxc_i2c.h>
++#include "vs6624_regs.h"
++
++# include "vs6624_patch.c"
++
++
++int vs6624_ReadByte(struct i2c_adapter *adap, unsigned short offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ char buf[2];
++
++ buf[0] = (offset & 0xFF00) >> 8;
++ buf[1] = (offset & 0x00FF);
++
++ /* Read Byte with 16-Bit Pointer */
++
++ rmsg[0].addr = VS6624_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 2;
++ rmsg[0].buf = buf;
++
++ rmsg[1].addr = VS6624_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "vs6624_ReadByte() - i2c_transfer failed.\n");
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++int vs6624_WriteByte(struct i2c_adapter *adap, unsigned short offset, unsigned char data)
++{
++ int ret;
++ char buf[2];
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ buf[0] = (offset & 0xFF00) >> 8;
++ buf[1] = (offset & 0x00FF);
++
++ wmsg[0].addr = VS6624_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 2;
++ wmsg[0].buf = buf;
++
++ wmsg[1].addr = VS6624_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "vs6624_WriteByte() - i2c_transfer failed.\n");
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++int vs6624_WriteSequence(struct i2c_adapter *adap, const unsigned short array[][2], unsigned short len)
++{
++ u16 x;
++
++ for (x = 0; x < len; x++)
++ vs6624_WriteByte (adap, array[x][0], (unsigned char) array[x][1]);
++
++ return 0;
++}
++
++
++static unsigned char get_reg(struct i2c_adapter *adap, unsigned short offset)
++{
++ unsigned char buf[1];
++
++ vs6624_ReadByte (adap, offset, &buf[0]);
++
++ return buf[0];
++}
++
++void
++vs6624_set_color(struct i2c_adapter *adap, int bright, int saturation, int red, int green, int blue)
++{
++ switch (saturation) {
++ case 150:
++ vs6624_WriteByte(adap, bColourSaturation0, 0xFF & 0xFF);
++ break;
++ case 75:
++ vs6624_WriteByte(adap, bColourSaturation0, 0xC0 & 0xFF);
++ break;
++ case 50:
++ vs6624_WriteByte(adap, bColourSaturation0, 0x80 & 0xFF);
++ break;
++ case 25:
++ vs6624_WriteByte(adap, bColourSaturation0, 0x40 & 0xFF);
++ break;
++ default:
++ vs6624_WriteByte(adap, bColourSaturation0, 0x78 & 0xFF);
++ break;
++ }
++}
++
++void
++vs6624_get_color(struct i2c_adapter *adap, int *bright, int *saturation, int *red, int *green, int *blue)
++{
++ *saturation = (int) get_reg( adap, bColourSaturation0);
++ switch (*saturation) {
++ case 0xFF:
++ *saturation = 150;
++ break;
++ case 0xC0:
++ *saturation = 75;
++ break;
++ case 0x80:
++ *saturation = 50;
++ break;
++ case 0x40:
++ *saturation = 25;
++ break;
++ default:
++ *saturation = 100;
++ break;
++ }
++}
++
++
++
++static int vs_probe(struct i2c_adapter *adap)
++{
++
++ unsigned char buf[2];
++
++ vs6624_ReadByte (adap, DeviceID_MSB, &buf[0]);
++ vs6624_ReadByte (adap, DeviceID_LSB, &buf[1]);
++
++ if ((((buf[0] & 0xFF) << 8) | (buf[1] & 0xFF)) == VS6624_ID) {
++
++ printk(KERN_INFO "%s: Firmware Version %d.%d \n",
++ SENSOR_NAME, get_reg(adap, bFirmwareVsnMajor), get_reg (adap, bFirmwareVsnMinor));
++ printk(KERN_INFO "%s: Patch Version %d.%d \n",
++ SENSOR_NAME, get_reg(adap, bPatchVsnMajor), get_reg(adap, bPatchVsnMinor));
++
++ return 0;
++ }
++
++ printk (KERN_ERR "vs_probe: No VS6624 found.\n");
++ printk (KERN_ERR "vs_probe: buf[0] = 0x%x\n", (buf[0] & 0xFF) << 8);
++ printk (KERN_ERR "vs_probe: buf[1] = 0x%x\n", (buf[1] & 0xFF));
++ printk (KERN_ERR "vs_probe: DeviceID = %d\n", ((buf[0] & 0xFF) << 8) | (buf[1] & 0xFF));
++
++ return -ENODEV;
++}
++
++void vs6624_patch (struct i2c_adapter *adap)
++{
++ printk (KERN_ERR "vs6624_patch() - enter\n");
++ msleep(100);
++
++ vs6624_WriteByte (adap, PWR_MAN_SETUP_MODE_SELECT, 0x0);
++ msleep(10);
++ vs_probe (adap);
++
++ printk (KERN_ERR "vs6624_patch() - applying patch p1\n");
++ vs6624_WriteSequence (adap, patch_p1, sizeof(patch_p1) / (sizeof(u16) * 2));
++ msleep(50);
++
++ printk (KERN_ERR "vs6624_patch() - applying patch p2\n");
++ vs6624_WriteSequence (adap, patch_p2, sizeof(patch_p2) / (sizeof(u16) * 2));
++
++ vs6624_WriteByte (adap, PWR_MAN_SETUP_MODE_SELECT, 0x2);
++ msleep(100);
++
++ vs6624_WriteByte (adap, PWR_MAN_DIO_ENABLE, 0x1);
++ msleep(1);
++
++ printk(KERN_INFO "MODE: %d \n", get_reg(adap, bState)); //pjg
++
++ vs_probe (adap);
++
++
++ // Flicker correction
++ vs6624_WriteByte (adap, bLightingFrequencyHz, 0x64); // AC frequency == 100
++
++ // Pan step size
++ vs6624_WriteByte (adap, uwPanStepHSizeMSB0, 0x0); // H pan step == 15
++ vs6624_WriteByte (adap, uwPanStepHSizeLSB0, 0xf);
++ vs6624_WriteByte (adap, uwPanStepVSizeMSB0, 0x0); // V pan step == 15
++ vs6624_WriteByte (adap, uwPanStepVSizeLSB0, 0xf);
++
++ vs6624_WriteByte (adap, bSyncCodeSetup, 0x21); // SYNC //pjg
++ vs6624_WriteByte (adap, bHSyncSetup, 0xF); // Active lines only, Automatic //pjg
++ vs6624_WriteByte (adap, bVSyncSetup, 0x7); // Active lines only, Automatic //pjg
++
++ vs6624_WriteByte (adap, uwDesiredFrameRate_Num_MSB, 0x0);
++ vs6624_WriteByte (adap, uwDesiredFrameRate_Num_LSB, 0x0F); // frame rate numerator == 15 MTW
++ vs6624_WriteByte (adap, bDesiredFrameRate_Den, 0x1); // frame rate denominator == 1
++
++ printk(KERN_INFO "MODE: %d \n", get_reg(adap, bState)); //pjg
++
++ vs6624_WriteByte (adap, uwExternalClockFrequencyMhzNumeratorMSB, 0x0);
++ vs6624_WriteByte (adap, uwExternalClockFrequencyMhzNumeratorLSB, 12);
++ vs6624_WriteByte (adap, bExternalClockFrequencyMhzDenominator, 0x1);
++
++ vs6624_WriteByte (adap, bPClkSetup, 0x85); // Pix Clk Mode == free run
++
++ printk(KERN_INFO "MODE: %d \n", get_reg(adap, bState)); //pjg
++ vs6624_WriteByte (adap, bUserCommand, 0x2); // RUN
++
++ printk(KERN_INFO "MODE: %d \n", get_reg(adap, bState)); //pjg
++ printk (KERN_ERR "vs6624_patch() - writing setup patch\n");
++ vs6624_WriteSequence (adap, patch_run_setup, sizeof(patch_run_setup) / (sizeof(u16) * 2));
++
++
++ printk(KERN_INFO "MODE: %d \n", get_reg(adap, bState)); //pjg
++
++ vs_probe (adap); //pjg
++ printk (KERN_ERR "vs6624_patch() - exit\n");
++ return;
++}
++
++
++
++static int ReadByteV(struct i2c_adapter *adap, unsigned short offset, char* name)
++{
++ unsigned char tmp[1];
++ vs6624_ReadByte(adap, offset, &tmp[0]);
++ printk (KERN_ERR "vs6624 offset = %04X, data = %02X %s\n", offset, tmp[0], name);
++ return 0;
++
++}
++
++
++void vs6624_dump_regs(struct i2c_adapter *adap)
++{
++
++ printk (KERN_ERR "vs6624_dump_regs() - enter\n");
++
++ ReadByteV(adap, 0xc044,"PWR_MAN_DIO_ENABLE ");
++ ReadByteV(adap, 0x0001,"uwDeviceId ");
++ ReadByteV(adap, 0x0001,"DeviceID_MSB ");
++ ReadByteV(adap, 0x0002,"DeviceID_LSB ");
++ ReadByteV(adap, 0x0004,"bFirmwareVsnMajor ");
++ ReadByteV(adap, 0x0006,"bFirmwareVsnMinor ");
++ ReadByteV(adap, 0x0008,"bPatchVsnMajor ");
++ ReadByteV(adap, 0x000a,"bPatchVsnMinor ");
++ ReadByteV(adap, 0x0180,"bUserCommand ");
++ ReadByteV(adap, 0x0186,"bManualNextState ");
++ ReadByteV(adap, 0x0200,"bNextState ");
++ ReadByteV(adap, 0x0202,"bState ");
++ ReadByteV(adap, 0x0280,"fMeteringOn ");
++ ReadByteV(adap, 0x0282,"fExitOnStable ");
++ ReadByteV(adap, 0x0284,"bStreamLength ");
++ ReadByteV(adap, 0x0300,"fIsColdStart ");
++ ReadByteV(adap, 0x0302,"bNonViewLive_ActivePipeSetupBank ");
++ ReadByteV(adap, 0x0304,"bSnapShoot_ActivePipeSetupBank ");
++ ReadByteV(adap, 0x0306,"fSnapShoot_NoWaiting ");
++ ReadByteV(adap, 0x0308,"SensorMode ");
++ ReadByteV(adap, 0x0380,"bImageSize0 ");
++ ReadByteV(adap, 0x0383,"uwManualHSize0 ");
++ ReadByteV(adap, 0x0383,"uwManualHSizeMSB0 ");
++ ReadByteV(adap, 0x0384,"uwManualHSizeLSB0 ");
++ ReadByteV(adap, 0x0387,"uwManualVSize0 ");
++ ReadByteV(adap, 0x0387,"uwManualVSizeMSB0 ");
++ ReadByteV(adap, 0x0388,"uwManualVSizeLSB0 ");
++ ReadByteV(adap, 0x038b,"uwZoomStepHSize0 ");
++ ReadByteV(adap, 0x038b,"uwZoomStepHSizeMSB0 ");
++ ReadByteV(adap, 0x038c,"uwZoomStepHSizeLSB0 ");
++ ReadByteV(adap, 0x038f,"uwZoomStepVSize0 ");
++ ReadByteV(adap, 0x038f,"uwZoomStepVSizeMSB0 ");
++ ReadByteV(adap, 0x0390,"uwZoomStepVSizeLSB0 ");
++ ReadByteV(adap, 0x0392,"bZoomControl0 ");
++ ReadByteV(adap, 0x0395,"uwPanStepHSize0 ");
++ ReadByteV(adap, 0x0395,"uwPanStepHSizeMSB0 ");
++ ReadByteV(adap, 0x0396,"uwPanStepHSizeLSB0 ");
++ ReadByteV(adap, 0x0399,"uwPanStepVSize0 ");
++ ReadByteV(adap, 0x0399,"uwPanStepVSizeMSB0 ");
++ ReadByteV(adap, 0x039a,"uwPanStepVSizeLSB0 ");
++ ReadByteV(adap, 0x039c,"bPanControl0 ");
++ ReadByteV(adap, 0x039e,"bCropControl0 ");
++ ReadByteV(adap, 0x03a1,"uwManualCropHorizontalStart0 ");
++ ReadByteV(adap, 0x03a5,"uwManualCropHorizontalSize0 ");
++ ReadByteV(adap, 0x03a9,"uwManualCropVerticalStart0 ");
++ ReadByteV(adap, 0x03ad,"uwManualCropVerticalSize0 ");
++ ReadByteV(adap, 0x03a1,"bCropHStartMSB0 ");
++ ReadByteV(adap, 0x03a2,"bCropHStartLSB0 ");
++ ReadByteV(adap, 0x03a9,"bCropVStartMSB0 ");
++ ReadByteV(adap, 0x03aa,"bCropVStartLSB0 ");
++ ReadByteV(adap, 0x03a5,"bCropHSizeMSB0 ");
++ ReadByteV(adap, 0x03a6,"bCropHSizeLSB0 ");
++ ReadByteV(adap, 0x03ad,"bCropVSizeMSB0 ");
++ ReadByteV(adap, 0x03ae,"bCropVSizeLSB0 ");
++ ReadByteV(adap, 0x03b0,"bDataFormat0 ");
++ ReadByteV(adap, 0x03b2,"bBayerOutputAlignment0 ");
++ ReadByteV(adap, 0x03b4,"bContrast0 ");
++ ReadByteV(adap, 0x03b6,"bColourSaturation0 ");
++ ReadByteV(adap, 0x03b8,"bGamma0 ");
++ ReadByteV(adap, 0x03ba,"fHorizontalMirror0 ");
++ ReadByteV(adap, 0x03bc,"fVerticalFlip0 ");
++ ReadByteV(adap, 0x03be,"bChannelID0 ");
++ ReadByteV(adap, 0x0400,"bImageSize1 ");
++ ReadByteV(adap, 0x0403,"uwManualHSize1 ");
++ ReadByteV(adap, 0x0407,"uwManualVSize1 ");
++ ReadByteV(adap, 0x040b,"uwZoomStepHSize1 ");
++ ReadByteV(adap, 0x040f,"uwZoomStepVSize1 ");
++ ReadByteV(adap, 0x0412,"bZoomControl1 ");
++ ReadByteV(adap, 0x0415,"uwPanStepHSize1 ");
++ ReadByteV(adap, 0x0419,"uwPanStepVSize1 ");
++ ReadByteV(adap, 0x041c,"bPanControl1 ");
++ ReadByteV(adap, 0x041e,"bCropControl1 ");
++ ReadByteV(adap, 0x0421,"uwManualCropHorizontalStart1 ");
++ ReadByteV(adap, 0x0425,"uwManualCropHorizontalSize1 ");
++ ReadByteV(adap, 0x0429,"uwManualCropVerticalStart1 ");
++ ReadByteV(adap, 0x042d,"uwManualCropVerticalSize1 ");
++ ReadByteV(adap, 0x0421,"bCropHStartMSB1 ");
++ ReadByteV(adap, 0x0422,"bCropHStartLSB1 ");
++ ReadByteV(adap, 0x0429,"bCropVStartMSB1 ");
++ ReadByteV(adap, 0x042a,"bCropVStartLSB1 ");
++ ReadByteV(adap, 0x0425,"bCropHSizeMSB1 ");
++ ReadByteV(adap, 0x0426,"bCropHSizeLSB1 ");
++ ReadByteV(adap, 0x042d,"bCropVSizeMSB1 ");
++ ReadByteV(adap, 0x042e,"bCropVSizeLSB1 ");
++ ReadByteV(adap, 0x0430,"bDataFormat1 ");
++ ReadByteV(adap, 0x0432,"bBayerOutputAlignment1 ");
++ ReadByteV(adap, 0x0434,"bContrast1 ");
++ ReadByteV(adap, 0x0436,"bColourSaturation1 ");
++ ReadByteV(adap, 0x0438,"bGamma1 ");
++ ReadByteV(adap, 0x043a,"fHorizontalMirror1 ");
++ ReadByteV(adap, 0x043c,"fVerticalFlip1 ");
++ ReadByteV(adap, 0x043e,"bChannelID1 ");
++ ReadByteV(adap, 0x0480,"fEnable ");
++ ReadByteV(adap, 0x0482,"bInitialPipeSetupBank ");
++ ReadByteV(adap, 0x0500,"CurrentPipeSetupBank ");
++ ReadByteV(adap, 0x0580,"bTimeToPowerdown ");
++ ReadByteV(adap, 0x058a,"fVRegSleep ");
++ ReadByteV(adap, 0x058c,"fSmoothLineReading ");
++ ReadByteV(adap, 0x0605,"uwExternalClockFrequencyMhzNumerator ");
++ ReadByteV(adap, 0x0605,"uwExternalClockFrequencyMhzNumeratorMSB ");
++ ReadByteV(adap, 0x0606,"uwExternalClockFrequencyMhzNumeratorLSB ");
++ ReadByteV(adap, 0x0608,"bExternalClockFrequencyMhzDenominator ");
++ ReadByteV(adap, 0x0681,"fpExternalClockFrequencyMhz ");
++ ReadByteV(adap, 0x0880,"bSysClkMode ");
++ ReadByteV(adap, 0x0882,"bMode ");
++ ReadByteV(adap, 0x0c80,"bLightingFrequencyHz ");
++ ReadByteV(adap, 0x0c82,"fFlickerCompatibleFrameLength ");
++ ReadByteV(adap, 0x0d05,"fpFlickerFreePeriod_us ");
++ ReadByteV(adap, 0x0d08,"fAntiFlickerEnabled ");
++ ReadByteV(adap, 0x0d81,"uwDesiredFrameRate_Num ");
++ ReadByteV(adap, 0x0d81,"uwDesiredFrameRate_Num_MSB ");
++ ReadByteV(adap, 0x0d82,"uwDesiredFrameRate_Num_LSB ");
++ ReadByteV(adap, 0x0d84,"bDesiredFrameRate_Den ");
++ ReadByteV(adap, 0x0e01,"fpRequestedFrameRate_Hz ");
++ ReadByteV(adap, 0x0e01,"fpRequestedFrameRate_Hz_MSB ");
++ ReadByteV(adap, 0x0e02,"fpRequestedFrameRate_Hz_LSB ");
++ ReadByteV(adap, 0x0e05,"fpMaxFrameRate_Hz ");
++ ReadByteV(adap, 0x0e09,"fpMinFrameRate_Hz ");
++ ReadByteV(adap, 0x0e0c,"fChangePending ");
++ ReadByteV(adap, 0x0e0f,"uwRequiredFrameLength_lines ");
++ ReadByteV(adap, 0x0e12,"ClipFrameRate ");
++ ReadByteV(adap, 0x0e80,"fDisableFrameRateDamper ");
++ ReadByteV(adap, 0x0e82,"bImpliedGainThresholdLow_num ");
++ ReadByteV(adap, 0x0e84,"bImpliedGainThresholdLow_den ");
++ ReadByteV(adap, 0x0e86,"bImpliedGainThresholdHigh_num ");
++ ReadByteV(adap, 0x0e88,"bImpliedGainThresholdHigh_den ");
++ ReadByteV(adap, 0x0e8a,"bUserMinimumFrameRate_Hz ");
++ ReadByteV(adap, 0x0e8c,"bUserMaximumFrameRate_Hz ");
++ ReadByteV(adap, 0x0e8e,"bRelativeChange_num ");
++ ReadByteV(adap, 0x0e90,"bRelativeChange_den ");
++ ReadByteV(adap, 0x0e92,"fDivorceMinFrameRateFromMaxIntegration ");
++ ReadByteV(adap, 0x0f01,"fpImpliedGain ");
++ ReadByteV(adap, 0x0f05,"uwMaximumFrameLength_lines ");
++ ReadByteV(adap, 0x0f09,"uwMinimumFrameLength_lines ");
++ ReadByteV(adap, 0x0f0d,"uwFrameLengthChange_lines ");
++ ReadByteV(adap, 0x0f11,"fpDesiredAutomaticFrameRate_Hz ");
++ ReadByteV(adap, 0x0f15,"uwCurrentFrameLength_lines ");
++ ReadByteV(adap, 0x0f19,"uwDesiredFrameLength_lines ");
++ ReadByteV(adap, 0x0f1c,"fAutomaticFrameRateStable ");
++ ReadByteV(adap, 0x0f1e,"fAutomaticFrameRateClip ");
++ ReadByteV(adap, 0x0f81,"uwXOffset ");
++ ReadByteV(adap, 0x0f85,"uwYOffset ");
++ ReadByteV(adap, 0x0f89,"uwXSize ");
++ ReadByteV(adap, 0x0f8d,"uwYSize ");
++ ReadByteV(adap, 0x1180,"ExposureControls_bMode ");
++ ReadByteV(adap, 0x1182,"bExposureMetering ");
++ ReadByteV(adap, 0x1184,"bManualExposureTime_s_num ");
++ ReadByteV(adap, 0x1186,"bManualExposureTime_s_den ");
++ ReadByteV(adap, 0x1189,"fpManualDesiredExposureTime_us ");
++ ReadByteV(adap, 0x1190,"iExposureCompensation ");
++ ReadByteV(adap, 0x1195,"uwDirectModeCoarseIntegration_lines ");
++ ReadByteV(adap, 0x1199,"uwDirectModeFineIntegration_pixels ");
++ ReadByteV(adap, 0x119d,"uwDirectModeCodedAnalogGain ");
++ ReadByteV(adap, 0x11a1,"fpDirectModeDigitalGain ");
++ ReadByteV(adap, 0x11a5,"uwFlashGunModeCoarseIntegration_lines ");
++ ReadByteV(adap, 0x11a9,"uwFlashGunModeFineIntegration_pixels ");
++ ReadByteV(adap, 0x11ad,"uwFlashGunModeCodedAnalogGain ");
++ ReadByteV(adap, 0x11b1,"fpFlashGunModeDigitalGain ");
++ ReadByteV(adap, 0x11b4,"fFreezeAutoExposure ");
++ ReadByteV(adap, 0x11b7,"fpUserMaximumIntegrationTime_us ");
++ ReadByteV(adap, 0x11bb,"fpRecommendFlashGunAnalogGainThreshold ");
++ ReadByteV(adap, 0x11be,"fEnableHighClipForDesiredExposureTime ");
++ ReadByteV(adap, 0x11c0,"bAntiFlickerMode ");
++ ReadByteV(adap, 0x1201,"fpMaximumStep ");
++ ReadByteV(adap, 0x1205,"fpMinimumStep ");
++ ReadByteV(adap, 0x1209,"fpMinimumDesiredExposureTime_us ");
++ ReadByteV(adap, 0x120d,"fpStepProportion ");
++ ReadByteV(adap, 0x1211,"fpMaximumNegativeStepThreshold ");
++ ReadByteV(adap, 0x1215,"fpRelativeOnTargetStabilityThreshold ");
++ ReadByteV(adap, 0x1219,"fpDigitalGainFloor ");
++ ReadByteV(adap, 0x121d,"fpDigitalGainCeiling ");
++ ReadByteV(adap, 0x1221,"fpRelativeIntTimeHysThreshold ");
++ ReadByteV(adap, 0x1225,"fpRelativeDigitalGainHysThreshold ");
++ ReadByteV(adap, 0x1229,"fpRelativeCompilationProblemThreshold ");
++ ReadByteV(adap, 0x122d,"fpRoundUpBunchFudge ");
++ ReadByteV(adap, 0x1231,"fpFineClampThreshold ");
++ ReadByteV(adap, 0x1235,"fpMaximumManualExposureTime_s ");
++ ReadByteV(adap, 0x1239,"fpRelativeStabilityThresholdForAutoFocus ");
++ ReadByteV(adap, 0x123c,"bLeakShift ");
++ ReadByteV(adap, 0x1281,"fpLeakyEnergy ");
++ ReadByteV(adap, 0x1285,"fpRelativeStep ");
++ ReadByteV(adap, 0x1309,"uwCoarseIntegrationPending_lines ");
++ ReadByteV(adap, 0x130d,"uwFineIntegrationPending_pixels ");
++ ReadByteV(adap, 0x1311,"fpAnalogGainPending ");
++ ReadByteV(adap, 0x1315,"fpDigitalGainPending ");
++ ReadByteV(adap, 0x1319,"fpDesiredExposureTime_us ");
++ ReadByteV(adap, 0x131d,"fpCompiledExposureTime_us ");
++ ReadByteV(adap, 0x132b,"uwCodedAnalogGainPending ");
++ ReadByteV(adap, 0x1480,"bWhiteBalanceMode ");
++ ReadByteV(adap, 0x1482,"bManualRedGain ");
++ ReadByteV(adap, 0x1484,"bManualGreenGain ");
++ ReadByteV(adap, 0x1486,"bManualBlueGain ");
++ ReadByteV(adap, 0x148b,"fpFlashRedGain ");
++ ReadByteV(adap, 0x148f,"fpFlashGreenGain ");
++ ReadByteV(adap, 0x1493,"fpFlashBlueGain ");
++ ReadByteV(adap, 0x1500,"bStatus ");
++ ReadByteV(adap, 0x1505,"fpRedGain ");
++ ReadByteV(adap, 0x1509,"fpGreenGain ");
++ ReadByteV(adap, 0x150d,"fpBlueGain ");
++ ReadByteV(adap, 0x1581,"fpStableTotalStepThreshold ");
++ ReadByteV(adap, 0x1585,"fpMinimumRelativeStep ");
++ ReadByteV(adap, 0x1589,"fpMaximumRelativeStep ");
++ ReadByteV(adap, 0x1601,"fpRedA ");
++ ReadByteV(adap, 0x1605,"fpBlueA ");
++ ReadByteV(adap, 0x1609,"fpRedB ");
++ ReadByteV(adap, 0x160d,"fpBlueB ");
++ ReadByteV(adap, 0x1611,"fpMaximumDistanceAllowedFromLocus ");
++ ReadByteV(adap, 0x1614,"fEnableConstrainedWhiteBalance ");
++ ReadByteV(adap, 0x1616,"bACCSRCCtrl ");
++ ReadByteV(adap, 0x1681,"fpOutputRedGain ");
++ ReadByteV(adap, 0x1685,"fpOutputGreenGain ");
++ ReadByteV(adap, 0x1689,"fpOutputBlueGain ");
++ ReadByteV(adap, 0x168c,"fAreGainsConstrained ");
++ ReadByteV(adap, 0x1701,"fpGradientOfLocusAB ");
++ ReadByteV(adap, 0x1705,"fpDistanceOfInputPointFromLocusAB ");
++ ReadByteV(adap, 0x1709,"fpConstrainedRedPoint ");
++ ReadByteV(adap, 0x170d,"fpConstrainedBluePoint ");
++ ReadByteV(adap, 0x1880,"bMaxNumberOfFramesToWaitForStability ");
++ ReadByteV(adap, 0x1900,"fWhiteBalanceStable ");
++ ReadByteV(adap, 0x1902,"fExposureStable ");
++ ReadByteV(adap, 0x1904,"fDarkCalStable ");
++ ReadByteV(adap, 0x1906,"fStable ");
++ ReadByteV(adap, 0x1908,"fForcedStablility ");
++ ReadByteV(adap, 0x1985,"fpRedTilt ");
++ ReadByteV(adap, 0x1989,"fpGreenTilt ");
++ ReadByteV(adap, 0x198d,"fpBlueTilt ");
++ ReadByteV(adap, 0x1990,"bBlackCorrectionOffset ");
++ ReadByteV(adap, 0x1a01,"uwSensorAnalogGainFloor ");
++ ReadByteV(adap, 0x1a05,"uwSensorAnalogGainCeiling ");
++ ReadByteV(adap, 0x1a80,"bFlashMode ");
++ ReadByteV(adap, 0x1a83,"uwFlashOffLine ");
++ ReadByteV(adap, 0x1b00,"fFlashRecommended ");
++ ReadByteV(adap, 0x1b02,"fFlashGrabComplete ");
++ ReadByteV(adap, 0x1d01,"uwHorizontalOffset ");
++ ReadByteV(adap, 0x1d05,"uwVerticalOffset ");
++ ReadByteV(adap, 0x1d08,"iR2RCoefficient ");
++ ReadByteV(adap, 0x1d0a,"iR2GRCoefficient ");
++ ReadByteV(adap, 0x1d0c,"iR2GBCoefficient ");
++ ReadByteV(adap, 0x1d0e,"iR2BCoefficient ");
++ ReadByteV(adap, 0x1d10,"iR4RCoefficient ");
++ ReadByteV(adap, 0x1d12,"iR4GRCoefficient ");
++ ReadByteV(adap, 0x1d14,"iR4GBCoefficient ");
++ ReadByteV(adap, 0x1d16,"iR4BCoefficient ");
++ ReadByteV(adap, 0x1d80,"ScythefDisableFilter ");
++ ReadByteV(adap, 0x1e00,"JackfDisableFilter ");
++ ReadByteV(adap, 0x1e80,"bAntiAliasFilterSuppress ");
++ ReadByteV(adap, 0x1f00,"ColourMatrixDamperfDisable ");
++ ReadByteV(adap, 0x1f03,"fpLowThreshold ");
++ ReadByteV(adap, 0x1f07,"fpHighThreshold ");
++ ReadByteV(adap, 0x1f0b,"fpMinimumOutput ");
++ ReadByteV(adap, 0x1f81,"fpGInR ");
++ ReadByteV(adap, 0x1f85,"fpBInR ");
++ ReadByteV(adap, 0x1f89,"fpRInG ");
++ ReadByteV(adap, 0x1f8d,"fpBInG ");
++ ReadByteV(adap, 0x1f91,"fpRInB ");
++ ReadByteV(adap, 0x1f95,"fpGInB ");
++ ReadByteV(adap, 0x2000,"bUserPeakGain ");
++ ReadByteV(adap, 0x2002,"fDisableGainDamping ");
++ ReadByteV(adap, 0x2005,"fpDamperLowThreshold_Gain ");
++ ReadByteV(adap, 0x2009,"fpDamperHighThreshold_Gain ");
++ ReadByteV(adap, 0x200d,"fpMinimumDamperOutput_Gain ");
++ ReadByteV(adap, 0x2010,"bUserPeakLoThresh ");
++ ReadByteV(adap, 0x2012,"fDisableCoringDamping ");
++ ReadByteV(adap, 0x2014,"bUserPeakHiThresh ");
++ ReadByteV(adap, 0x2017,"fpDamperLowThreshold_Coring ");
++ ReadByteV(adap, 0x201b,"fpDamperHighThreshold_Coring ");
++ ReadByteV(adap, 0x201f,"fpMinimumDamperOutput_Coring ");
++ ReadByteV(adap, 0x2022,"bBlockControl ");
++ ReadByteV(adap, 0x2280,"fGammaManuCtrl0 ");
++ ReadByteV(adap, 0x2282,"bRPeakGamma0 ");
++ ReadByteV(adap, 0x2284,"bGPeakGamma0 ");
++ ReadByteV(adap, 0x2286,"bBPeakGamma0 ");
++ ReadByteV(adap, 0x2288,"bRUnPeakGamma0 ");
++ ReadByteV(adap, 0x228a,"bGUnPeakGamma0 ");
++ ReadByteV(adap, 0x228c,"bBUnPeakGamma0 ");
++ ReadByteV(adap, 0x2294,"bYuvSetup MTW ");
++ ReadByteV(adap, 0x2300,"fGammaManuCtrl1 ");
++ ReadByteV(adap, 0x2302,"bRPeakGamma1 ");
++ ReadByteV(adap, 0x2304,"bGPeakGamma1 ");
++ ReadByteV(adap, 0x2306,"bBPeakGamma1 ");
++ ReadByteV(adap, 0x2308,"bRUnPeakGamma1 ");
++ ReadByteV(adap, 0x230a,"bGUnPeakGamma1 ");
++ ReadByteV(adap, 0x230c,"bBUnPeakGamma1 ");
++ ReadByteV(adap, 0x2381,"uwLumaExcursion0 ");
++ ReadByteV(adap, 0x2385,"uwLumaMidpointTimes20 ");
++ ReadByteV(adap, 0x2389,"uwChromaExcursion0 ");
++ ReadByteV(adap, 0x238d,"uwChromaMidpointTimes20 ");
++ ReadByteV(adap, 0x2401,"uwLumaExcursion1 ");
++ ReadByteV(adap, 0x2405,"uwLumaMidpointTimes21 ");
++ ReadByteV(adap, 0x2409,"uwChromaExcursion1 ");
++ ReadByteV(adap, 0x240d,"uwChromaMidpointTimes21 ");
++ ReadByteV(adap, 0x2480,"FadeToBlackfDisable ");
++ ReadByteV(adap, 0x2483,"fpBlackValue ");
++ ReadByteV(adap, 0x2487,"fpDamperLowThreshold ");
++ ReadByteV(adap, 0x248b,"fpDamperHighThreshold ");
++ ReadByteV(adap, 0x248f,"fpDamperOutput ");
++ ReadByteV(adap, 0x2580,"bCodeCheckEn ");
++ ReadByteV(adap, 0x2582,"bBlankFormat ");
++ ReadByteV(adap, 0x2584,"bSyncCodeSetup ");
++ ReadByteV(adap, 0x2586,"bHSyncSetup ");
++ ReadByteV(adap, 0x2588,"bVSyncSetup ");
++ ReadByteV(adap, 0x258a,"bPClkSetup ");
++ ReadByteV(adap, 0x258c,"fPclkEn ");
++ ReadByteV(adap, 0x258e,"bOpfSpSetup ");
++ ReadByteV(adap, 0x2590,"bBlankData_MSB ");
++ ReadByteV(adap, 0x2592,"bBlankData_LSB ");
++ ReadByteV(adap, 0x2594,"bRgbSetup ");
++ ReadByteV(adap, 0x2596,"bYuvSetup ");
++ ReadByteV(adap, 0x2598,"bVsyncRisingCoarseH ");
++ ReadByteV(adap, 0x259a,"bVsyncRisingCoarseL ");
++ ReadByteV(adap, 0x259c,"bVsyncRisingFineH ");
++ ReadByteV(adap, 0x259e,"bVsyncRisingFineL ");
++ ReadByteV(adap, 0x25a0,"bVsyncFallingCoarseH ");
++ ReadByteV(adap, 0x25a2,"bVsyncFallingCoarseL ");
++ ReadByteV(adap, 0x25a4,"bVsyncFallingFineH ");
++ ReadByteV(adap, 0x25a6,"bVsyncFallingFineL ");
++ ReadByteV(adap, 0x25a8,"bHsyncRisingH ");
++ ReadByteV(adap, 0x25aa,"bHsyncRisingL ");
++ ReadByteV(adap, 0x25ac,"bHsyncFallingH ");
++ ReadByteV(adap, 0x25ae,"bHsyncFallingL ");
++ ReadByteV(adap, 0x25b0,"bOutputInterface ");
++ ReadByteV(adap, 0x25b2,"bCCPExtraData ");
++ ReadByteV(adap, 0x2600,"NoRAfDisable ");
++ ReadByteV(adap, 0x2602,"bUsage ");
++ ReadByteV(adap, 0x2604,"bSplit_Kn ");
++ ReadByteV(adap, 0x2606,"bSplit_Nl ");
++ ReadByteV(adap, 0x2608,"bTight_Green ");
++ ReadByteV(adap, 0x260a,"fDisableNoraPromoting ");
++ ReadByteV(adap, 0x260d,"DamperLowThreshold ");
++ ReadByteV(adap, 0x2611,"DamperHighThreshold ");
++ ReadByteV(adap, 0x2615,"MinimumDamperOutput ");
++
++ return;
++}
+--- /dev/null
++++ git/drivers/bmi/pims/camera/vs6624_access.h
+@@ -0,0 +1,17 @@
++#ifndef VS6624_ACCESS_H
++#define VS6624_ACCESS_H
++
++#include <linux/i2c.h>
++void vs6624_get_color(struct i2c_adapter *adap, int *bright, int *saturation, int *red, int *green, int *blue);
++void vs6624_set_color(struct i2c_adapter *adap, int bright, int saturation, int red, int green, int blue);
++
++
++
++void vs6624_patch (struct i2c_adapter *adap);
++int vs6624_ReadByte(struct i2c_adapter *adap, unsigned short offset, unsigned char *data);
++int vs6624_WriteByte(struct i2c_adapter *adap, unsigned short offset, unsigned char data);
++int vs6624_WriteSequence(struct i2c_adapter *adap, const unsigned short array[][2], unsigned short len);
++void vs6624_dump_regs(struct i2c_adapter *adap);
++
++#endif
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/vs6624_patch.c
+@@ -0,0 +1,373 @@
++static const unsigned short patch_p1[][2] = {
++ {0x8104, 3},
++ {0x8105, 1},
++ {0xc900, 0x03},
++ {0xc904, 0x47},
++ {0xc905, 0x10},
++ {0xc906, 0x80},
++ {0xc907, 0x3a},
++ {0x903a, 0x02},
++ {0x903b, 0x47},
++ {0x903c, 0x15},
++ {0xc908, 0x31},
++ {0xc909, 0xdc},
++ {0xc90a, 0x80},
++ {0xc90b, 0x44},
++ {0x9044, 0x02},
++ {0x9045, 0x31},
++ {0x9046, 0xe2},
++ {0xc90c, 0x07},
++ {0xc90d, 0xe0},
++ {0xc90e, 0x80},
++ {0xc90f, 0x47},
++ {0x9047, 0x90},
++ {0x9048, 0x83},
++ {0x9049, 0x81},
++ {0x904a, 0xe0},
++ {0x904b, 0x60},
++ {0x904c, 0x08},
++ {0x904d, 0x90},
++ {0x904e, 0xc0},
++ {0x904f, 0x43},
++ {0x9050, 0x74},
++ {0x9051, 0x01},
++ {0x9052, 0xf0},
++ {0x9053, 0x80},
++ {0x9054, 0x05},
++ {0x9055, 0xE4},
++ {0x9056, 0x90},
++ {0x9057, 0xc0},
++ {0x9058, 0x43},
++ {0x9059, 0xf0},
++ {0x905a, 0x02},
++ {0x905b, 0x07},
++ {0x905c, 0xec},
++ {0xc910, 0x5d},
++ {0xc911, 0xca},
++ {0xc912, 0x80},
++ {0xc913, 0x5d},
++ {0x905d, 0xa3},
++ {0x905e, 0x04},
++ {0x905f, 0xf0},
++ {0x9060, 0xa3},
++ {0x9061, 0x04},
++ {0x9062, 0xf0},
++ {0x9063, 0x22},
++ {0xc914, 0x72},
++ {0xc915, 0x92},
++ {0xc916, 0x80},
++ {0xc917, 0x64},
++ {0x9064, 0x74},
++ {0x9065, 0x01},
++ {0x9066, 0x02},
++ {0x9067, 0x72},
++ {0x9068, 0x95},
++ {0xc918, 0x47},
++ {0xc919, 0xf2},
++ {0xc91a, 0x81},
++ {0xc91b, 0x69},
++ {0x9169, 0x74},
++ {0x916a, 0x02},
++ {0x916b, 0xf0},
++ {0x916c, 0xec},
++ {0x916d, 0xb4},
++ {0x916e, 0x10},
++ {0x916f, 0x0a},
++ {0x9170, 0x90},
++ {0x9171, 0x80},
++ {0x9172, 0x16},
++ {0x9173, 0xe0},
++ {0x9174, 0x70},
++ {0x9175, 0x04},
++ {0x9176, 0x90},
++ {0x9177, 0xd3},
++ {0x9178, 0xc4},
++ {0x9179, 0xf0},
++ {0x917a, 0x22},
++ {0xc91c, 0x0a},
++ {0xc91d, 0xbe},
++ {0xc91e, 0x80},
++ {0xc91f, 0x73},
++ {0x9073, 0xfc},
++ {0x9074, 0xa3},
++ {0x9075, 0xe0},
++ {0x9076, 0xf5},
++ {0x9077, 0x82},
++ {0x9078, 0x8c},
++ {0x9079, 0x83},
++ {0x907a, 0xa3},
++ {0x907b, 0xa3},
++ {0x907c, 0xe0},
++ {0x907d, 0xfc},
++ {0x907e, 0xa3},
++ {0x907f, 0xe0},
++ {0x9080, 0xc3},
++ {0x9081, 0x9f},
++ {0x9082, 0xff},
++ {0x9083, 0xec},
++ {0x9084, 0x9e},
++ {0x9085, 0xfe},
++ {0x9086, 0x02},
++ {0x9087, 0x0a},
++ {0x9088, 0xea},
++ {0xc920, 0x47},
++ {0xc921, 0x38},
++ {0xc922, 0x80},
++ {0xc923, 0x89},
++ {0x9089, 0xec},
++ {0x908a, 0xd3},
++ {0x908b, 0x94},
++ {0x908c, 0x20},
++ {0x908d, 0x40},
++ {0x908e, 0x01},
++ {0x908f, 0x1c},
++ {0x9090, 0x90},
++ {0x9091, 0xd3},
++ {0x9092, 0xd4},
++ {0x9093, 0xec},
++ {0x9094, 0xf0},
++ {0x9095, 0x02},
++ {0x9096, 0x47},
++ {0x9097, 0x3d},
++ {0xc924, 0x45},
++ {0xc925, 0xca},
++ {0xc926, 0x80},
++ {0xc927, 0x98},
++ {0x9098, 0x12},
++ {0x9099, 0x77},
++ {0x909a, 0xd6},
++ {0x909b, 0x02},
++ {0x909c, 0x45},
++ {0x909d, 0xcd},
++ {0xc928, 0x20},
++ {0xc929, 0xd5},
++ {0xc92a, 0x80},
++ {0xc92b, 0x9e},
++ {0x909e, 0x90},
++ {0x909f, 0x82},
++ {0x90a0, 0x18},
++ {0x90a1, 0xe0},
++ {0x90a2, 0xb4},
++ {0x90a3, 0x03},
++ {0x90a4, 0x0e},
++ {0x90a5, 0x90},
++ {0x90a6, 0x83},
++ {0x90a7, 0xbf},
++ {0x90a8, 0xe0},
++ {0x90a9, 0x60},
++ {0x90aa, 0x08},
++ {0x90ab, 0x90},
++ {0x90ac, 0x81},
++ {0x90ad, 0xfc},
++ {0x90ae, 0xe0},
++ {0x90af, 0xff},
++ {0x90b0, 0xc3},
++ {0x90b1, 0x13},
++ {0x90b2, 0xf0},
++ {0x90b3, 0x90},
++ {0x90b4, 0x81},
++ {0x90b5, 0xfc},
++ {0x90b6, 0xe0},
++ {0x90b7, 0xff},
++ {0x90b8, 0x02},
++ {0x90b9, 0x20},
++ {0x90ba, 0xda},
++ {0xc92c, 0x70},
++ {0xc92d, 0xbc},
++ {0xc92e, 0x80},
++ {0xc92f, 0xbb},
++ {0x90bb, 0x90},
++ {0x90bc, 0x82},
++ {0x90bd, 0x18},
++ {0x90be, 0xe0},
++ {0x90bf, 0xb4},
++ {0x90c0, 0x03},
++ {0x90c1, 0x06},
++ {0x90c2, 0x90},
++ {0x90c3, 0xc1},
++ {0x90c4, 0x06},
++ {0x90c5, 0x74},
++ {0x90c6, 0x05},
++ {0x90c7, 0xf0},
++ {0x90c8, 0x90},
++ {0x90c9, 0xd3},
++ {0x90ca, 0xa0},
++ {0x90cb, 0x02},
++ {0x90cc, 0x70},
++ {0x90cd, 0xbf},
++ {0xc930, 0x72},
++ {0xc931, 0x21},
++ {0xc932, 0x81},
++ {0xc933, 0x3b},
++ {0x913b, 0x7d},
++ {0x913c, 0x02},
++ {0x913d, 0x7f},
++ {0x913e, 0x7b},
++ {0x913f, 0x02},
++ {0x9140, 0x72},
++ {0x9141, 0x25},
++ {0xc934, 0x28},
++ {0xc935, 0xae},
++ {0xc936, 0x80},
++ {0xc937, 0xd2},
++ {0x90d2, 0xf0},
++ {0x90d3, 0x90},
++ {0x90d4, 0xd2},
++ {0x90d5, 0x0a},
++ {0x90d6, 0x02},
++ {0x90d7, 0x28},
++ {0x90d8, 0xb4},
++ {0xc938, 0x28},
++ {0xc939, 0xb1},
++ {0xc93a, 0x80},
++ {0xc93b, 0xd9},
++ {0x90d9, 0x90},
++ {0x90da, 0x83},
++ {0x90db, 0xba},
++ {0x90dc, 0xe0},
++ {0x90dd, 0xff},
++ {0x90de, 0x90},
++ {0x90df, 0xd2},
++ {0x90e0, 0x08},
++ {0x90e1, 0xe0},
++ {0x90e2, 0xe4},
++ {0x90e3, 0xef},
++ {0x90e4, 0xf0},
++ {0x90e5, 0xa3},
++ {0x90e6, 0xe0},
++ {0x90e7, 0x74},
++ {0x90e8, 0xff},
++ {0x90e9, 0xf0},
++ {0x90ea, 0x90},
++ {0x90eb, 0xd2},
++ {0x90ec, 0x0a},
++ {0x90ed, 0x02},
++ {0x90ee, 0x28},
++ {0x90ef, 0xb4},
++ {0xc93c, 0x29},
++ {0xc93d, 0x79},
++ {0xc93e, 0x80},
++ {0xc93f, 0xf0},
++ {0x90f0, 0xf0},
++ {0x90f1, 0x90},
++ {0x90f2, 0xd2},
++ {0x90f3, 0x0e},
++ {0x90f4, 0x02},
++ {0x90f5, 0x29},
++ {0x90f6, 0x7f},
++ {0xc940, 0x29},
++ {0xc941, 0x7c},
++ {0xc942, 0x80},
++ {0xc943, 0xf7},
++ {0x90f7, 0x90},
++ {0x90f8, 0x83},
++ {0x90f9, 0xba},
++ {0x90fa, 0xe0},
++ {0x90fb, 0xff},
++ {0x90fc, 0x90},
++ {0x90fd, 0xd2},
++ {0x90fe, 0x0c},
++ {0x90ff, 0xe0},
++ {0x9100, 0xe4},
++ {0x9101, 0xef},
++ {0x9102, 0xf0},
++ {0x9103, 0xa3},
++ {0x9104, 0xe0},
++ {0x9105, 0x74},
++ {0x9106, 0xff},
++ {0x9107, 0xf0},
++ {0x9108, 0x90},
++ {0x9109, 0xd2},
++ {0x910a, 0x0e},
++ {0x910b, 0x02},
++ {0x910c, 0x29},
++ {0x910d, 0x7f},
++ {0xc944, 0x2a},
++ {0xc945, 0x42},
++ {0xc946, 0x81},
++ {0xc947, 0x0e},
++ {0x910e, 0xf0},
++ {0x910f, 0x90},
++ {0x9110, 0xd2},
++ {0x9111, 0x12},
++ {0x9112, 0x02},
++ {0x9113, 0x2a},
++ {0x9114, 0x48},
++ {0xc948, 0x2a},
++ {0xc949, 0x45},
++ {0xc94a, 0x81},
++ {0xc94b, 0x15},
++ {0x9115, 0x90},
++ {0x9116, 0x83},
++ {0x9117, 0xba},
++ {0x9118, 0xe0},
++ {0x9119, 0xff},
++ {0x911a, 0x90},
++ {0x911b, 0xd2},
++ {0x911c, 0x10},
++ {0x911d, 0xe0},
++ {0x911e, 0xe4},
++ {0x911f, 0xef},
++ {0x9120, 0xf0},
++ {0x9121, 0xa3},
++ {0x9122, 0xe0},
++ {0x9123, 0x74},
++ {0x9124, 0xff},
++ {0x9125, 0xf0},
++ {0x9126, 0x90},
++ {0x9127, 0xd2},
++ {0x9128, 0x12},
++ {0x9129, 0x02},
++ {0x912a, 0x2a},
++ {0x912b, 0x48},
++ {0xc900, 0x01}
++};
++
++static const unsigned short patch_p2[][2] = {
++ {0x806f, 0x01},
++ {0x058c, 0x01}
++};
++
++static const unsigned short patch_run_setup[][2] = {
++ {0x2596, 0x01}, /* U first */
++ {0x1d18, 0x00}, /* Enableconstrainedwhitebalance */
++ {0x200d, 0x3c}, /* Damper PeakGain Output MSB */
++ {0x200e, 0x66}, /* Damper PeakGain Output LSB */
++ {0x1f03, 0x65}, /* Damper Low MSB */
++ {0x1f04, 0xd1}, /* Damper Low LSB */
++ {0x1f07, 0x66}, /* Damper High MSB */
++ {0x1f08, 0x62}, /* Damper High LSB */
++ {0x1f0b, 0x00}, /* Damper Min output MSB */
++ {0x1f0c, 0x00}, /* Damper Min output LSB */
++ {0x2600, 0x00}, /* Nora fDisable */
++ {0x2602, 0x04}, /* Nora usage */
++ {0x260d, 0x63}, /* Damper Low MSB Changed 0x63 to 0x65 */
++ {0x260e, 0xd1}, /* Damper Low LSB */
++ {0x2611, 0x68}, /* Damper High MSB */
++ {0x2612, 0xdd}, /* Damper High LSB */
++ {0x2615, 0x3a}, /* Damper Min output MSB */
++ {0x2616, 0x00}, /* Damper Min output LSB */
++ {0x2480, 0x00}, /* Disable */
++ {0x1d8a, 0x30}, /* MAXWeightHigh */
++ {0x1d91, 0x62}, /* fpDamperLowThresholdHigh MSB */
++ {0x1d92, 0x4a}, /* fpDamperLowThresholdHigh LSB */
++ {0x1d95, 0x65}, /* fpDamperHighThresholdHigh MSB */
++ {0x1d96, 0x0e}, /* fpDamperHighThresholdHigh LSB */
++ {0x1da1, 0x3a}, /* fpMinimumDamperOutputLow MSB */
++ {0x1da2, 0xb8}, /* fpMinimumDamperOutputLow LSB */
++ {0x1e08, 0x06}, /* MAXWeightLow */
++ {0x1e0a, 0x0a}, /* MAXWeightHigh */
++ {0x1601, 0x3a}, /* Red A MSB */
++ {0x1602, 0x14}, /* Red A LSB */
++ {0x1605, 0x3b}, /* Blue A MSB */
++ {0x1606, 0x85}, /* BLue A LSB */
++ {0x1609, 0x3b}, /* RED B MSB */
++ {0x160a, 0x85}, /* RED B LSB */
++ {0x160d, 0x3a}, /* Blue B MSB */
++ {0x160e, 0x14}, /* Blue B LSB */
++ {0x1611, 0x30}, /* Max Distance from Locus MSB */
++ {0x1612, 0x8f}, /* Max Distance from Locus MSB */
++ {0x1614, 0x01} /* Enable constrainer */
++};
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/camera/vs6624_regs.h
+@@ -0,0 +1,467 @@
++/*
++ * File: drivers/media/video/mxc/capture/_vs6624.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the header file for the ST VS6624 camera on the
++ * MX31 BUG platform. It is derived from the following
++ * Blackfin and MX31 sources:
++ *
++ */
++
++/*
++ * <BLACKFIN>
++ *
++ * Based on: drivers/media/video/blackfin/vs6624.h
++ * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
++ *
++ * Created:
++ * Description: Command driver for STM VS6624 sensor
++ *
++ *
++ * Modified:
++ * Copyright 2004-2007 Analog Devices Inc.
++ *
++ * Bugs: Enter bugs at http://blackfin.uclinux.org/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * <MX31>
++ *
++ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*!
++ * @defgroup Camera Sensor Drivers
++ */
++
++/*!
++ * @file mt9v111.h
++ *
++ * @brief MT9V111 Camera Header file
++ *
++ * It include all the defines for bitmaps operations, also two main structure
++ * one for IFP interface structure, other for sensor core registers.
++ *
++ * @ingroup Camera
++ */
++
++#ifndef _VS6624_H
++#define _VS6624_H
++
++/* I2C Slave Address */
++#define VS6624_I2C_ADDRESS 0x10 // 7-bit address
++#define SENSOR_NAME "VS6624"
++
++//pjg #define USE_ITU656
++
++/* VS6624 register definitions */
++#define VS6624_ID 624
++#define PWR_MAN_SETUP_MODE_SELECT 0xc003 /* (7:0) */
++#define PWR_MAN_DIO_ENABLE 0xc044 /* (7:0) */
++#define uwDeviceId 0x0001 /* (7:0) IndexLo 0x0002 */
++#define DeviceID_MSB 0x0001 /* (7:0) */
++#define DeviceID_LSB 0x0002 /* (7:0) */
++#define bFirmwareVsnMajor 0x0004 /* (7:0) */
++#define bFirmwareVsnMinor 0x0006 /* (7:0) */
++#define bPatchVsnMajor 0x0008 /* (7:0) */
++#define bPatchVsnMinor 0x000a /* (7:0) */
++
++#define bUserCommand 0x0180 /* (7:0) */
++#define bManualNextState 0x0186 /* (7:0) */
++
++#define bNextState 0x0200 /* (7:0) */
++#define bState 0x0202 /* (7:0) */
++
++#define fMeteringOn 0x0280 /* (7:0) */
++#define fExitOnStable 0x0282 /* (7:0) */
++#define bStreamLength 0x0284 /* (7:0) */
++
++#define fIsColdStart 0x0300 /* (7:0) */
++#define bNonViewLive_ActivePipeSetupBank 0x0302 /* (7:0) */
++#define bSnapShoot_ActivePipeSetupBank 0x0304 /* (7:0) */
++#define fSnapShoot_NoWaiting 0x0306 /* (7:0) */
++#define SensorMode 0x0308 /* (7:0) */
++
++#define bImageSize0 0x0380 /* (7:0) */
++#define uwManualHSize0 0x0383 /* (7:0) IndexLo 0x0384 */
++#define uwManualHSizeMSB0 0x0383 /* (7:0) */
++#define uwManualHSizeLSB0 0x0384 /* (7:0) */
++#define uwManualVSize0 0x0387 /* (7:0) IndexLo 0x0388 */
++#define uwManualVSizeMSB0 0x0387 /* (7:0) */
++#define uwManualVSizeLSB0 0x0388 /* (7:0) */
++#define uwZoomStepHSize0 0x038b /* (7:0) IndexLo 0x038c */
++#define uwZoomStepHSizeMSB0 0x038b /* (7:0) */
++#define uwZoomStepHSizeLSB0 0x038c /* (7:0) */
++#define uwZoomStepVSize0 0x038f /* (7:0) IndexLo 0x0390 */
++#define uwZoomStepVSizeMSB0 0x038f /* (7:0) */
++#define uwZoomStepVSizeLSB0 0x0390 /* (7:0) */
++#define bZoomControl0 0x0392 /* (7:0) */
++#define uwPanStepHSize0 0x0395 /* (7:0) IndexLo 0x0396 */
++#define uwPanStepHSizeMSB0 0x0395 /* (7:0) */
++#define uwPanStepHSizeLSB0 0x0396 /* (7:0) */
++#define uwPanStepVSize0 0x0399 /* (7:0) IndexLo 0x039a */
++#define uwPanStepVSizeMSB0 0x0399 /* (7:0) */
++#define uwPanStepVSizeLSB0 0x039a /* (7:0) */
++#define bPanControl0 0x039c /* (7:0) */
++#define bCropControl0 0x039e /* (7:0) */
++#define uwManualCropHorizontalStart0 0x03a1 /* (7:0) IndexLo 0x03a2 */
++#define uwManualCropHorizontalSize0 0x03a5 /* (7:0) IndexLo 0x03a6 */
++#define uwManualCropVerticalStart0 0x03a9 /* (7:0) IndexLo 0x03aa */
++#define uwManualCropVerticalSize0 0x03ad /* (7:0) IndexLo 0x03ae */
++#define bCropHStartMSB0 0x03a1 /* (7:0) */
++#define bCropHStartLSB0 0x03a2 /* (7:0) */
++#define bCropVStartMSB0 0x03a9 /* (7:0) */
++#define bCropVStartLSB0 0x03aa /* (7:0) */
++#define bCropHSizeMSB0 0x03a5 /* (7:0) */
++#define bCropHSizeLSB0 0x03a6 /* (7:0) */
++#define bCropVSizeMSB0 0x03ad /* (7:0) */
++#define bCropVSizeLSB0 0x03ae /* (7:0) */
++#define bDataFormat0 0x03b0 /* (7:0) */
++#define bBayerOutputAlignment0 0x03b2 /* (7:0) */
++#define bContrast0 0x03b4 /* (7:0) */
++#define bColourSaturation0 0x03b6 /* (7:0) */
++#define bGamma0 0x03b8 /* (7:0) */
++#define fHorizontalMirror0 0x03ba /* (7:0) */
++#define fVerticalFlip0 0x03bc /* (7:0) */
++#define bChannelID0 0x03be /* (7:0) */
++
++#define bImageSize1 0x0400 /* (7:0) */
++#define uwManualHSize1 0x0403 /* (7:0) IndexLo 0x0404 */
++#define uwManualVSize1 0x0407 /* (7:0) IndexLo 0x0408 */
++#define uwZoomStepHSize1 0x040b /* (7:0) IndexLo 0x040c */
++#define uwZoomStepVSize1 0x040f /* (7:0) IndexLo 0x0410 */
++#define bZoomControl1 0x0412 /* (7:0) */
++#define uwPanStepHSize1 0x0415 /* (7:0) IndexLo 0x0416 */
++#define uwPanStepVSize1 0x0419 /* (7:0) IndexLo 0x041a */
++#define bPanControl1 0x041c /* (7:0) */
++#define bCropControl1 0x041e /* (7:0) */
++#define uwManualCropHorizontalStart1 0x0421 /* (7:0) IndexLo 0x0422 */
++#define uwManualCropHorizontalSize1 0x0425 /* (7:0) IndexLo 0x0426 */
++#define uwManualCropVerticalStart1 0x0429 /* (7:0) IndexLo 0x042a */
++#define uwManualCropVerticalSize1 0x042d /* (7:0) IndexLo 0x042e */
++#define bCropHStartMSB1 0x0421 /* (7:0) */
++#define bCropHStartLSB1 0x0422 /* (7:0) */
++#define bCropVStartMSB1 0x0429 /* (7:0) */
++#define bCropVStartLSB1 0x042a /* (7:0) */
++#define bCropHSizeMSB1 0x0425 /* (7:0) */
++#define bCropHSizeLSB1 0x0426 /* (7:0) */
++#define bCropVSizeMSB1 0x042d /* (7:0) */
++#define bCropVSizeLSB1 0x042e /* (7:0) */
++#define bDataFormat1 0x0430 /* (7:0) */
++#define bBayerOutputAlignment1 0x0432 /* (7:0) */
++#define bContrast1 0x0434 /* (7:0) */
++#define bColourSaturation1 0x0436 /* (7:0) */
++#define bGamma1 0x0438 /* (7:0) */
++#define fHorizontalMirror1 0x043a /* (7:0) */
++#define fVerticalFlip1 0x043c /* (7:0) */
++#define bChannelID1 0x043e /* (7:0) */
++
++#define fEnable 0x0480 /* (7:0) */
++#define bInitialPipeSetupBank 0x0482 /* (7:0) */
++
++#define CurrentPipeSetupBank 0x0500 /* (7:0) */
++
++#define bTimeToPowerdown 0x0580 /* (7:0) */
++#define fVRegSleep 0x058a /* (7:0) */
++#define fSmoothLineReading 0x058c /* (7:0) */
++
++#define uwExternalClockFrequencyMhzNumerator 0x0605 /* (7:0) IndexLo 0x0606 */
++#define uwExternalClockFrequencyMhzNumeratorMSB 0x0605 /* (7:0) IndexLo 0x0606 */
++#define uwExternalClockFrequencyMhzNumeratorLSB 0x0606 /* (7:0) IndexLo 0x0606 */
++#define bExternalClockFrequencyMhzDenominator 0x0608 /* (7:0) */
++
++#define fpExternalClockFrequencyMhz 0x0681 /* (7:0) IndexLo 0x0682 */
++
++#define bSysClkMode 0x0880 /* (7:0) */
++#define bMode 0x0882 /* (7:0) */
++#define bLightingFrequencyHz 0x0c80 /* (7:0) */
++#define fFlickerCompatibleFrameLength 0x0c82 /* (7:0) */
++
++#define fpFlickerFreePeriod_us 0x0d05 /* (7:0) IndexLo 0x0d06 */
++#define fAntiFlickerEnabled 0x0d08 /* (7:0) */
++
++#define uwDesiredFrameRate_Num 0x0d81 /* (7:0) IndexLo 0x0d82 */
++#define uwDesiredFrameRate_Num_MSB 0x0d81 /* (7:0) */
++#define uwDesiredFrameRate_Num_LSB 0x0d82 /* (7:0) */
++#define bDesiredFrameRate_Den 0x0d84 /* (7:0) */
++
++#define fpRequestedFrameRate_Hz 0x0e01 /* (7:0) IndexLo 0x0e02 */
++#define fpRequestedFrameRate_Hz_MSB 0x0e01 /* (7:0) */
++#define fpRequestedFrameRate_Hz_LSB 0x0e02 /* (7:0) */
++#define fpMaxFrameRate_Hz 0x0e05 /* (7:0) IndexLo 0x0e06 */
++#define fpMinFrameRate_Hz 0x0e09 /* (7:0) IndexLo 0x0e0a */
++#define fChangePending 0x0e0c /* (7:0) */
++#define uwRequiredFrameLength_lines 0x0e0f /* (7:0) IndexLo 0x0e10 */
++#define ClipFrameRate 0x0e12 /* (7:0) */
++
++#define fDisableFrameRateDamper 0x0e80 /* (7:0) */
++#define bImpliedGainThresholdLow_num 0x0e82 /* (7:0) */
++#define bImpliedGainThresholdLow_den 0x0e84 /* (7:0) */
++#define bImpliedGainThresholdHigh_num 0x0e86 /* (7:0) */
++#define bImpliedGainThresholdHigh_den 0x0e88 /* (7:0) */
++#define bUserMinimumFrameRate_Hz 0x0e8a /* (7:0) */
++#define bUserMaximumFrameRate_Hz 0x0e8c /* (7:0) */
++#define bRelativeChange_num 0x0e8e /* (7:0) */
++#define bRelativeChange_den 0x0e90 /* (7:0) */
++#define fDivorceMinFrameRateFromMaxIntegration 0x0e92 /* (7:0) */
++
++#define fpImpliedGain 0x0f01 /* (7:0) IndexLo 0x0f02 */
++#define uwMaximumFrameLength_lines 0x0f05 /* (7:0) IndexLo 0x0f06 */
++#define uwMinimumFrameLength_lines 0x0f09 /* (7:0) IndexLo 0x0f0a */
++#define uwFrameLengthChange_lines 0x0f0d /* (7:0) IndexLo 0x0f0e */
++#define fpDesiredAutomaticFrameRate_Hz 0x0f11 /* (7:0) IndexLo 0x0f12 */
++#define uwCurrentFrameLength_lines 0x0f15 /* (7:0) IndexLo 0x0f16 */
++#define uwDesiredFrameLength_lines 0x0f19 /* (7:0) IndexLo 0x0f1a */
++#define fAutomaticFrameRateStable 0x0f1c /* (7:0) */
++#define fAutomaticFrameRateClip 0x0f1e /* (7:0) */
++
++#define uwXOffset 0x0f81 /* (7:0) IndexLo 0x0f82 */
++#define uwYOffset 0x0f85 /* (7:0) IndexLo 0x0f86 */
++#define uwXSize 0x0f89 /* (7:0) IndexLo 0x0f8a */
++#define uwYSize 0x0f8d /* (7:0) IndexLo 0x0f8e */
++
++#define ExposureControls_bMode 0x1180 /* (7:0) */
++#define bExposureMetering 0x1182 /* (7:0) */
++#define bManualExposureTime_s_num 0x1184 /* (7:0) */
++#define bManualExposureTime_s_den 0x1186 /* (7:0) */
++#define fpManualDesiredExposureTime_us 0x1189 /* (7:0) IndexLo 0x118a */
++#define iExposureCompensation 0x1190 /* (7:0) Signed */
++#define uwDirectModeCoarseIntegration_lines 0x1195 /* (7:0) IndexLo 0x1196 */
++#define uwDirectModeFineIntegration_pixels 0x1199 /* (7:0) IndexLo 0x119a */
++#define uwDirectModeCodedAnalogGain 0x119d /* (7:0) IndexLo 0x119e */
++#define fpDirectModeDigitalGain 0x11a1 /* (7:0) IndexLo 0x11a2 */
++#define uwFlashGunModeCoarseIntegration_lines 0x11a5 /* (7:0) IndexLo 0x11a6 */
++#define uwFlashGunModeFineIntegration_pixels 0x11a9 /* (7:0) IndexLo 0x11aa */
++#define uwFlashGunModeCodedAnalogGain 0x11ad /* (7:0) IndexLo 0x11ae */
++#define fpFlashGunModeDigitalGain 0x11b1 /* (7:0) IndexLo 0x11b2 */
++#define fFreezeAutoExposure 0x11b4 /* (7:0) */
++#define fpUserMaximumIntegrationTime_us 0x11b7 /* (7:0) IndexLo 0x11b8 */
++#define fpRecommendFlashGunAnalogGainThreshold 0x11bb /* (7:0) IndexLo 0x11bc */
++#define fEnableHighClipForDesiredExposureTime 0x11be /* (7:0) */
++#define bAntiFlickerMode 0x11c0 /* (7:0) */
++
++#define fpMaximumStep 0x1201 /* (7:0) IndexLo 0x1202 */
++#define fpMinimumStep 0x1205 /* (7:0) IndexLo 0x1206 */
++#define fpMinimumDesiredExposureTime_us 0x1209 /* (7:0) IndexLo 0x120a */
++#define fpStepProportion 0x120d /* (7:0) IndexLo 0x120e */
++#define fpMaximumNegativeStepThreshold 0x1211 /* (7:0) IndexLo 0x1212 */
++#define fpRelativeOnTargetStabilityThreshold 0x1215 /* (7:0) IndexLo 0x1216 */
++#define fpDigitalGainFloor 0x1219 /* (7:0) IndexLo 0x121a */
++#define fpDigitalGainCeiling 0x121d /* (7:0) IndexLo 0x121e */
++#define fpRelativeIntTimeHysThreshold 0x1221 /* (7:0) IndexLo 0x1222 */
++#define fpRelativeDigitalGainHysThreshold 0x1225 /* (7:0) IndexLo 0x1226 */
++#define fpRelativeCompilationProblemThreshold 0x1229 /* (7:0) IndexLo 0x122a */
++#define fpRoundUpBunchFudge 0x122d /* (7:0) IndexLo 0x122e */
++#define fpFineClampThreshold 0x1231 /* (7:0) IndexLo 0x1232 */
++#define fpMaximumManualExposureTime_s 0x1235 /* (7:0) IndexLo 0x1236 */
++#define fpRelativeStabilityThresholdForAutoFocus 0x1239 /* (7:0) IndexLo 0x123a */
++#define bLeakShift 0x123c /* (7:0) */
++
++#define fpLeakyEnergy 0x1281 /* (7:0) IndexLo 0x1282 */
++#define fpRelativeStep 0x1285 /* (7:0) IndexLo 0x1286 */
++
++#define uwCoarseIntegrationPending_lines 0x1309 /* (7:0) IndexLo 0x130a */
++#define uwFineIntegrationPending_pixels 0x130d /* (7:0) IndexLo 0x130e */
++#define fpAnalogGainPending 0x1311 /* (7:0) IndexLo 0x1312 */
++#define fpDigitalGainPending 0x1315 /* (7:0) IndexLo 0x1316 */
++#define fpDesiredExposureTime_us 0x1319 /* (7:0) IndexLo 0x131a */
++#define fpCompiledExposureTime_us 0x131d /* (7:0) IndexLo 0x131e */
++#define uwCodedAnalogGainPending 0x132b /* (7:0) IndexLo 0x132c */
++
++#define bWhiteBalanceMode 0x1480 /* (7:0) */
++#define bManualRedGain 0x1482 /* (7:0) */
++#define bManualGreenGain 0x1484 /* (7:0) */
++#define bManualBlueGain 0x1486 /* (7:0) */
++#define fpFlashRedGain 0x148b /* (7:0) IndexLo 0x148c */
++#define fpFlashGreenGain 0x148f /* (7:0) IndexLo 0x1490 */
++#define fpFlashBlueGain 0x1493 /* (7:0) IndexLo 0x1494 */
++
++#define bStatus 0x1500 /* (7:0) */
++#define fpRedGain 0x1505 /* (7:0) IndexLo 0x1506 */
++#define fpGreenGain 0x1509 /* (7:0) IndexLo 0x150a */
++#define fpBlueGain 0x150d /* (7:0) IndexLo 0x150e */
++
++#define fpStableTotalStepThreshold 0x1581 /* (7:0) IndexLo 0x1582 */
++#define fpMinimumRelativeStep 0x1585 /* (7:0) IndexLo 0x1586 */
++#define fpMaximumRelativeStep 0x1589 /* (7:0) IndexLo 0x158a */
++/*#define fpStepProportion 0x158d*/ /* (7:0) IndexLo 0x158e */
++
++#define fpRedA 0x1601 /* (7:0) IndexLo 0x1602 */
++#define fpBlueA 0x1605 /* (7:0) IndexLo 0x1606 */
++#define fpRedB 0x1609 /* (7:0) IndexLo 0x160a */
++#define fpBlueB 0x160d /* (7:0) IndexLo 0x160e */
++#define fpMaximumDistanceAllowedFromLocus 0x1611 /* (7:0) IndexLo 0x1612 */
++#define fEnableConstrainedWhiteBalance 0x1614 /* (7:0) */
++#define bACCSRCCtrl 0x1616 /* (7:0) */
++
++#define fpOutputRedGain 0x1681 /* (7:0) IndexLo 0x1682 */
++#define fpOutputGreenGain 0x1685 /* (7:0) IndexLo 0x1686 */
++#define fpOutputBlueGain 0x1689 /* (7:0) IndexLo 0x168a */
++#define fAreGainsConstrained 0x168c /* (7:0) */
++
++#define fpGradientOfLocusAB 0x1701 /* (7:0) IndexLo 0x1702 */
++#define fpDistanceOfInputPointFromLocusAB 0x1705 /* (7:0) IndexLo 0x1706 */
++#define fpConstrainedRedPoint 0x1709 /* (7:0) IndexLo 0x170a */
++#define fpConstrainedBluePoint 0x170d /* (7:0) IndexLo 0x170e */
++
++#define bMaxNumberOfFramesToWaitForStability 0x1880 /* (7:0) */
++
++#define fWhiteBalanceStable 0x1900 /* (7:0) */
++#define fExposureStable 0x1902 /* (7:0) */
++#define fDarkCalStable 0x1904 /* (7:0) */
++#define fStable 0x1906 /* (7:0) */
++#define fForcedStablility 0x1908 /* (7:0) */
++
++#define fpRedTilt 0x1985 /* (7:0) IndexLo 0x1986 */
++#define fpGreenTilt 0x1989 /* (7:0) IndexLo 0x198a */
++#define fpBlueTilt 0x198d /* (7:0) IndexLo 0x198e */
++#define bBlackCorrectionOffset 0x1990 /* (7:0) */
++
++#define uwSensorAnalogGainFloor 0x1a01 /* (7:0) IndexLo 0x1a02 */
++#define uwSensorAnalogGainCeiling 0x1a05 /* (7:0) IndexLo 0x1a06 */
++
++#define bFlashMode 0x1a80 /* (7:0) */
++#define uwFlashOffLine 0x1a83 /* (7:0) IndexLo 0x1a84 */
++
++#define fFlashRecommended 0x1b00 /* (7:0) */
++#define fFlashGrabComplete 0x1b02 /* (7:0) */
++
++#define uwHorizontalOffset 0x1d01 /* (7:0) IndexLo 0x1d02 */
++#define uwVerticalOffset 0x1d05 /* (7:0) IndexLo 0x1d06 */
++#define iR2RCoefficient 0x1d08 /* (7:0) Signed */
++#define iR2GRCoefficient 0x1d0a /* (7:0) Signed */
++#define iR2GBCoefficient 0x1d0c /* (7:0) Signed */
++#define iR2BCoefficient 0x1d0e /* (7:0) Signed */
++#define iR4RCoefficient 0x1d10 /* (7:0) Signed */
++#define iR4GRCoefficient 0x1d12 /* (7:0) Signed */
++#define iR4GBCoefficient 0x1d14 /* (7:0) Signed */
++#define iR4BCoefficient 0x1d16 /* (7:0) Signed */
++
++#define ScythefDisableFilter 0x1d80 /* (7:0) */
++#define JackfDisableFilter 0x1e00 /* (7:0) */
++
++#define bAntiAliasFilterSuppress 0x1e80 /* (7:0) */
++
++#define ColourMatrixDamperfDisable 0x1f00 /* (7:0) */
++#define fpLowThreshold 0x1f03 /* (7:0) IndexLo 0x1f04 */
++#define fpHighThreshold 0x1f07 /* (7:0) IndexLo 0x1f08 */
++#define fpMinimumOutput 0x1f0b /* (7:0) IndexLo 0x1f0c */
++
++#define fpGInR 0x1f81 /* (7:0) IndexLo 0x1f82 */
++#define fpBInR 0x1f85 /* (7:0) IndexLo 0x1f86 */
++#define fpRInG 0x1f89 /* (7:0) IndexLo 0x1f8a */
++#define fpBInG 0x1f8d /* (7:0) IndexLo 0x1f8e */
++#define fpRInB 0x1f91 /* (7:0) IndexLo 0x1f92 */
++#define fpGInB 0x1f95 /* (7:0) IndexLo 0x1f96 */
++
++#define bUserPeakGain 0x2000 /* (7:0) */
++#define fDisableGainDamping 0x2002 /* (7:0) */
++#define fpDamperLowThreshold_Gain 0x2005 /* (7:0) IndexLo 0x2006 */
++#define fpDamperHighThreshold_Gain 0x2009 /* (7:0) IndexLo 0x200a */
++#define fpMinimumDamperOutput_Gain 0x200d /* (7:0) IndexLo 0x200e */
++#define bUserPeakLoThresh 0x2010 /* (7:0) */
++#define fDisableCoringDamping 0x2012 /* (7:0) */
++#define bUserPeakHiThresh 0x2014 /* (7:0) */
++#define fpDamperLowThreshold_Coring 0x2017 /* (7:0) IndexLo 0x2018 */
++#define fpDamperHighThreshold_Coring 0x201b /* (7:0) IndexLo 0x201c */
++#define fpMinimumDamperOutput_Coring 0x201f /* (7:0) IndexLo 0x2020 */
++#define bBlockControl 0x2022 /* (7:0) */
++
++#define fGammaManuCtrl0 0x2280 /* (7:0) */
++#define bRPeakGamma0 0x2282 /* (7:0) */
++#define bGPeakGamma0 0x2284 /* (7:0) */
++#define bBPeakGamma0 0x2286 /* (7:0) */
++#define bRUnPeakGamma0 0x2288 /* (7:0) */
++#define bGUnPeakGamma0 0x228a /* (7:0) */
++#define bBUnPeakGamma0 0x228c /* (7:0) */
++
++#define fGammaManuCtrl1 0x2300 /* (7:0) */
++#define bRPeakGamma1 0x2302 /* (7:0) */
++#define bGPeakGamma1 0x2304 /* (7:0) */
++#define bBPeakGamma1 0x2306 /* (7:0) */
++#define bRUnPeakGamma1 0x2308 /* (7:0) */
++#define bGUnPeakGamma1 0x230a /* (7:0) */
++#define bBUnPeakGamma1 0x230c /* (7:0) */
++
++#define uwLumaExcursion0 0x2381 /* (7:0) IndexLo 0x2382 */
++#define uwLumaMidpointTimes20 0x2385 /* (7:0) IndexLo 0x2386 */
++#define uwChromaExcursion0 0x2389 /* (7:0) IndexLo 0x238a */
++#define uwChromaMidpointTimes20 0x238d /* (7:0) IndexLo 0x238e */
++
++#define uwLumaExcursion1 0x2401 /* (7:0) IndexLo 0x2402 */
++#define uwLumaMidpointTimes21 0x2405 /* (7:0) IndexLo 0x2406 */
++#define uwChromaExcursion1 0x2409 /* (7:0) IndexLo 0x240a */
++#define uwChromaMidpointTimes21 0x240d /* (7:0) IndexLo 0x240e */
++
++#define FadeToBlackfDisable 0x2480 /* (7:0) */
++#define fpBlackValue 0x2483 /* (7:0) IndexLo 0x2484 */
++#define fpDamperLowThreshold 0x2487 /* (7:0) IndexLo 0x2488 */
++#define fpDamperHighThreshold 0x248b /* (7:0) IndexLo 0x248c */
++#define fpDamperOutput 0x248f /* (7:0) IndexLo 0x2490 */
++
++#define bCodeCheckEn 0x2580 /* (7:0) */
++#define bBlankFormat 0x2582 /* (7:0) */
++#define bSyncCodeSetup 0x2584 /* (7:0) */
++#define bHSyncSetup 0x2586 /* (7:0) */
++#define bVSyncSetup 0x2588 /* (7:0) */
++#define bPClkSetup 0x258a /* (7:0) */
++#define fPclkEn 0x258c /* (7:0) */
++#define bOpfSpSetup 0x258e /* (7:0) */
++#define bBlankData_MSB 0x2590 /* (7:0) */
++#define bBlankData_LSB 0x2592 /* (7:0) */
++#define bRgbSetup 0x2594 /* (7:0) */
++#define bYuvSetup 0x2596 /* (7:0) */
++#define bVsyncRisingCoarseH 0x2598 /* (7:0) */
++#define bVsyncRisingCoarseL 0x259a /* (7:0) */
++#define bVsyncRisingFineH 0x259c /* (7:0) */
++#define bVsyncRisingFineL 0x259e /* (7:0) */
++#define bVsyncFallingCoarseH 0x25a0 /* (7:0) */
++#define bVsyncFallingCoarseL 0x25a2 /* (7:0) */
++#define bVsyncFallingFineH 0x25a4 /* (7:0) */
++#define bVsyncFallingFineL 0x25a6 /* (7:0) */
++#define bHsyncRisingH 0x25a8 /* (7:0) */
++#define bHsyncRisingL 0x25aa /* (7:0) */
++#define bHsyncFallingH 0x25ac /* (7:0) */
++#define bHsyncFallingL 0x25ae /* (7:0) */
++#define bOutputInterface 0x25b0 /* (7:0) */
++#define bCCPExtraData 0x25b2 /* (7:0) */
++
++#define NoRAfDisable 0x2600 /* (7:0) */
++#define bUsage 0x2602 /* (7:0) */
++#define bSplit_Kn 0x2604 /* (7:0) */
++#define bSplit_Nl 0x2606 /* (7:0) */
++#define bTight_Green 0x2608 /* (7:0) */
++#define fDisableNoraPromoting 0x260a /* (7:0) */
++#define DamperLowThreshold 0x260d /* (7:0) IndexLo 0x260e */
++#define DamperHighThreshold 0x2611 /* (7:0) IndexLo 0x2612 */
++#define MinimumDamperOutput 0x2615 /* (7:0) IndexLo 0x2616 */
++
++
++
++
++#endif /* VS6624_H */
++
+--- /dev/null
++++ git/drivers/bmi/pims/factory_test/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS - Factory Test Module
++#
++
++obj-$(CONFIG_BUG_FACTORY_TEST) += factory_test.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/factory_test/factory_test.c
+@@ -0,0 +1,952 @@
++/*
++ * factory_test.c
++ *
++ * BIG factory test board device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/ioctl.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/mxc_i2c.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <asm/arch/mx31bug_cpld.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/board-bug.h>
++#include <asm/arch/mx31bug_gpio.h>
++#include <asm/arch/mx31bug_cpld.h>
++#include <../arch/arm/mach-mx3/iomux.h>
++
++#define BUG_FACTORY_TEST_VERSION "1.0"
++#define BUF_MAX_SIZE 0x20
++#define FT_ERR -1
++#define MX31_GPIO_PORT1 0
++
++static int major;
++ // IOX I2C transfer structure
++struct iox_i2c_xfer {
++ unsigned char addr;
++ unsigned char offset;
++ unsigned char data;
++} iox_i2c_xfer;
++
++ // SPI transfer structure
++struct spi_xfer {
++ unsigned char addr;
++ unsigned char data[2];
++} spi_xfer;
++
++enum sig_bus {
++ MX31,
++ CPLD
++};
++ // MX31 signals
++enum msig {
++ CTS0,
++ RTS0,
++ CTS3,
++ RTS3,
++ CAM,
++ VSYNC1,
++ I2S_RXD0,
++ I2S_RXD1,
++ I2S_RXD2,
++ I2S_RXD3
++};
++
++ // CPLD signals
++enum csig {
++ GPIO0,
++ GPIO1,
++ GPIO2,
++ GPIO3,
++ PRES0,
++ PRES1,
++ PRES2,
++ PRES3,
++ CAM_IF,
++ CAM_LOCK_STATUS,
++ LCD
++};
++
++ // MX31/CPLD signal structure
++struct mc_signal {
++ enum sig_bus bus;
++ unsigned int signal;
++ unsigned char funct;
++ unsigned int value;
++} mc_signal;
++
++ // IOCTL commands for Factory Test Module
++#define FT_READ_IOX _IOR('f', 0x1, struct iox_i2c_xfer *) // read IOX
++#define FT_WRITE_IOX _IOR('f', 0x2, struct iox_i2c_xfer *) // write IOX
++#define FT_READ_SPI _IOR('f', 0x3, struct spi_xfer *) // read SPI
++#define FT_WRITE_SPI _IOR('f', 0x4, struct spi_xfer *) // write SPI
++#define FT_SIGNAL _IOR('f', 0x5, struct mc_signal *) // MX31/CPLD signals
++
++ // private device structure
++struct bug_ft
++{
++ struct cdev cdev; // character device (4 minor numbers)
++ unsigned int active; // at lease 1 bdev active
++ struct bmi_device *bdev[4]; // BMI device per slot
++ int open_flag[4]; // force single open on each device
++ struct spi_device *spi[4]; // SPI device
++ char rbuf[BUF_MAX_SIZE]; // SPI read buffer
++ char wbuf[BUF_MAX_SIZE]; // SPI write buffer
++};
++
++static struct bug_ft bug_ft; // global private data
++
++/*
++ * SPI function
++ */
++
++static int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
++{
++ struct spi_transfer t = {
++ .tx_buf = (const void *)buf,
++ .rx_buf = buf,
++ .len = len,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++
++ spi_message_add_tail(&t, &m);
++ if (spi_sync(spi, &m) != 0 || m.status != 0)
++ return FT_ERR;
++
++ return m.actual_length;
++}
++
++/*!
++ * This function allows writing 1 register on a SPI device.
++ *
++ * @param buf pointer on the buffer
++ * @param count size of the buffer
++ * @return This function returns the number of written bytes.
++ */
++static ssize_t spi_write_reg(struct bug_ft *priv, char *buf, int slot)
++{
++ int res = 0;
++
++ memset(priv->wbuf, 0, BUF_MAX_SIZE);
++ priv->wbuf[0] = buf[0];
++ priv->wbuf[1] = buf[1];
++ priv->wbuf[2] = buf[2];
++ priv->wbuf[3] = buf[3];
++ if (res > 0) {
++ return -EFAULT;
++ }
++ res = spi_rw(priv->spi[slot], priv->wbuf, 1);
++
++ return res;
++}
++
++/*!
++ * This function allows reading 1 register from a SPI device.
++ *
++ * @param buf pointer on the buffer
++ * @param off offset in the buffer
++
++ * @return This function returns the number of read bytes.
++ */
++static ssize_t spi_read_reg(struct bug_ft *priv, char *buf, int slot)
++{
++ spi_write_reg(priv, buf, slot);
++
++ memset(priv->rbuf, 0, BUF_MAX_SIZE);
++ buf[0] = priv->wbuf[3];
++ buf[1] = priv->wbuf[2];
++ buf[2] = priv->wbuf[1];
++ buf[3] = priv->wbuf[0];
++
++ return 4;
++}
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bug_ft_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_FACTORY_TEST,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bug_ft_tbl);
++
++int bug_ft_probe(struct bmi_device *bdev);
++void bug_ft_remove(struct bmi_device *bdev);
++
++ // BMI driver structure
++static struct bmi_driver bug_ft_driver =
++{
++ .name = "bug_ft_control",
++ .id_table = bug_ft_tbl,
++ .probe = bug_ft_probe,
++ .remove = bug_ft_remove,
++};
++
++/*
++ * I2C set up
++ *
++ * IOX A on slots 1 & 3
++ * IOX B on slots 0 & 4
++ */
++
++ // I2C IOX register addresses
++#define IOX0 (0xE8) // I2C port A
++#define IOX1 (0xEA) // I2C port A
++#define IOX2 (0xEC) // I2C port A
++#define IOX3 (0xEE) // I2C port A
++#define IOX4 (0xE8) // I2C port B
++#define IOX5 (0xEA) // I2C port B
++#define IOX6 (0xEC) // I2C port B
++#define IOX7 (0xEE) // I2C port B
++
++ // I2C IOX register offset addresses
++#define IOX_INPUT0_REG 0x0
++#define IOX_INPUT1_REG 0x1
++#define IOX_OUTPUT0_REG 0x2
++#define IOX_OUTPUT1_REG 0x3
++#define IOX_POLARITY0_REG 0x4
++#define IOX_POLARITY1_REG 0x5
++#define IOX_CONTROL0 0x6
++#define IOX_CONTROL1 0x7
++
++ // read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char addr,
++ unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ rmsg[0].addr = addr;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = addr;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = FT_ERR;
++ }
++ return ret;
++}
++
++ // write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char addr,
++ unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ wmsg[0].addr = addr;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = addr;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = FT_ERR;
++ }
++ return ret;
++}
++
++/*
++ * control device operations
++ */
++
++// open
++int bug_ft_open(struct inode *inode, struct file *filp)
++{
++ int slot = MINOR(inode->i_rdev);
++
++ if (bug_ft.open_flag[slot]) {
++ return - EBUSY;
++ }
++ bug_ft.open_flag[slot] = 1;
++ filp->private_data = &bug_ft;
++ return 0;
++}
++
++// release
++int bug_ft_release(struct inode *inode, struct file *filp)
++{
++ int slot = MINOR(inode->i_rdev);
++
++ bug_ft.open_flag[slot] = 0;
++ return 0;
++}
++
++/*
++ * ioctl and support functions
++ */
++
++ // do_mx31_sig
++int do_mx31_sig(struct mc_signal * mc_signal)
++{
++ int read_value;
++
++ switch(mc_signal->signal) {
++ case CTS0: // GPIO2_7
++ if(mc_signal->funct != 'W') {
++ printk("do_mx31_sig(): CTS0 is a Write-Only signal\n");
++ return -1;
++ }
++ iomux_config_mux(MX31_PIN_CTS1, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
++ mxc_set_gpio_direction(MX31_PIN_CTS1, 0);
++ mxc_set_gpio_dataout(MX31_PIN_CTS1, mc_signal->value);
++ break;
++ case RTS0: // GPIO2_6
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): RTS0 is a Read-Only signal\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_RTS1, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ read_value = mxc_get_gpio_datain(MX31_PIN_RTS1);
++ mc_signal->value = read_value;
++ break;
++ case CTS3: // GPIO3_29
++ if(mc_signal->funct != 'W') {
++ printk("do_mx31_sig(): CTS3 is a Write-Only signal\n");
++ return -1;
++ }
++ iomux_config_mux(MX31_PIN_ATA_DIOW, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
++ mxc_set_gpio_direction(MX31_PIN_ATA_DIOW, 0);
++ mxc_set_gpio_dataout(MX31_PIN_ATA_DIOW, mc_signal->value);
++ break;
++ case RTS3: // GPIO3_27
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): RTS3 is a Read-Only signal\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_ATA_CS1, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ read_value = mxc_get_gpio_datain(MX31_PIN_ATA_CS1);
++ mc_signal->value = read_value;
++ break;
++ case CAM: // camera interface -> GPIO
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): CAM is a Read-Only signal\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_CSI_D8, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D9, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D10, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D11, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D12, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D13, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D14, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_D15, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_HSYNC, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ mxc_request_iomux(MX31_PIN_CSI_VSYNC, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++
++ mc_signal->value = mxc_get_gpio_datain(MX31_PIN_CSI_HSYNC) << 9;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_VSYNC) << 8;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D15) << 7;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D14) << 6;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D13) << 5;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D12) << 4;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D11) << 3;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D10) << 2;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D9) << 1;
++ mc_signal->value |= mxc_get_gpio_datain(MX31_PIN_CSI_D8);
++
++ mxc_request_iomux(MX31_PIN_CSI_D8, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D9, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D10, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D11, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D12, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D13, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D14, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_D15, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_HSYNC, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ mxc_request_iomux(MX31_PIN_CSI_VSYNC, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
++ break;
++ case VSYNC1: // read VSYNC1 state
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): VSYNC1 is a Read-Only signal\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_SRST0, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
++ mc_signal->value = mxc_get_gpio_datain(MX31_PIN_SRST0);
++ mxc_request_iomux(MX31_PIN_SRST0, OUTPUTCONFIG_FUNC, INPUTCONFIG_ALT2);
++ break;
++ case I2S_RXD0: // GPIO1_20
++ case I2S_RXD2:
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): I2S_RXD[02] are Read-Only signals\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_SRXD4, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ read_value = mxc_get_gpio_datain(MX31_PIN_SRXD4);
++ mc_signal->value = read_value;
++ break;
++ case I2S_RXD1: // GPIO1_22
++ case I2S_RXD3:
++ if(mc_signal->funct != 'R') {
++ printk("do_mx31_sig(): I2S_RXD[13] are Read-Only signals\n");
++ return -1;
++ }
++ mxc_request_iomux(MX31_PIN_SRXD5, OUTPUTCONFIG_FUNC, INPUTCONFIG_GPIO);
++ read_value = mxc_get_gpio_datain(MX31_PIN_SRXD5);
++ mc_signal->value = read_value;
++ break;
++ default:
++ printk("do_mx31_sig(): unknown signal\n");
++ return -1;
++ }
++ return 0;
++}
++
++ // do_cpld_sig
++int do_cpld_sig(struct mc_signal * mc_signal)
++{
++ int read_value;
++
++ switch(mc_signal->signal) {
++ case GPIO0:
++ if(mc_signal->funct == 'R') {
++ // set GPIO to input
++ cpld_set_module_gpio_dir(CPLD_M1, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 3, CPLD_GPIO_IN);
++ // read GPIO
++ read_value = cpld_read_gpio_data_reg(CPLD_M1);
++ // read interrupt
++ read_value |= cpld_interrupt_status(INT_M1_INT) << 4;
++ mc_signal->value = read_value;
++ } else if(mc_signal->funct == 'H') {
++ // write GPIO
++ cpld_set_module_gpio_data(CPLD_M1, 0, mc_signal->value & 0x1);
++ cpld_set_module_gpio_data(CPLD_M1, 1, (mc_signal->value & 0x2) >> 1);
++ cpld_set_module_gpio_data(CPLD_M1, 2, (mc_signal->value & 0x4) >> 2);
++ cpld_set_module_gpio_data(CPLD_M1, 3, (mc_signal->value & 0x8) >> 3);
++ // set GPIO to output
++ cpld_set_module_gpio_dir(CPLD_M1, 0, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M1, 1, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M1, 2, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M1, 3, CPLD_GPIO_OUT);
++ } else {
++ printk("do_cpld_sig(): Illegal function for CPLD GPIO\n");
++ return -1;
++ }
++ break;
++ case GPIO1:
++ if(mc_signal->funct == 'R') {
++ // set GPIO to input
++ cpld_set_module_gpio_dir(CPLD_M2, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 3, CPLD_GPIO_IN);
++ // read GPIO
++ read_value = cpld_read_gpio_data_reg(CPLD_M2);
++ // read interrupt
++ read_value |= cpld_interrupt_status(INT_M2_INT) << 4;
++ mc_signal->value = read_value;
++ } else if(mc_signal->funct == 'H') {
++ // write GPIO
++ cpld_set_module_gpio_data(CPLD_M2, 0, mc_signal->value & 0x1);
++ cpld_set_module_gpio_data(CPLD_M2, 1, (mc_signal->value & 0x2) >> 1);
++ cpld_set_module_gpio_data(CPLD_M2, 2, (mc_signal->value & 0x4) >> 2);
++ cpld_set_module_gpio_data(CPLD_M2, 3, (mc_signal->value & 0x8) >> 3);
++ // set GPIO to output
++ cpld_set_module_gpio_dir(CPLD_M2, 0, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M2, 1, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M2, 2, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M2, 3, CPLD_GPIO_OUT);
++ } else {
++ printk("do_cpld_sig(): Illegal function for CPLD GPIO\n");
++ return -1;
++ }
++ break;
++ case GPIO2:
++ if(mc_signal->funct == 'R') {
++ // set GPIO to input
++ cpld_set_module_gpio_dir(CPLD_M3, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 3, CPLD_GPIO_IN);
++ // read GPIO
++ read_value = cpld_read_gpio_data_reg(CPLD_M3);
++ // read interrupt
++ read_value |= cpld_interrupt_status(INT_M3_INT) << 4;
++ mc_signal->value = read_value;
++ } else if(mc_signal->funct == 'H') {
++ // write GPIO
++ cpld_set_module_gpio_data(CPLD_M3, 0, mc_signal->value & 0x1);
++ cpld_set_module_gpio_data(CPLD_M3, 1, (mc_signal->value & 0x2) >> 1);
++ cpld_set_module_gpio_data(CPLD_M3, 2, (mc_signal->value & 0x4) >> 2);
++ cpld_set_module_gpio_data(CPLD_M3, 3, (mc_signal->value & 0x8) >> 3);
++ // set GPIO to output
++ cpld_set_module_gpio_dir(CPLD_M3, 0, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M3, 1, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M3, 2, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M3, 3, CPLD_GPIO_OUT);
++ } else {
++ printk("do_cpld_sig(): Illegal function for CPLD GPIO\n");
++ return -1;
++ }
++ break;
++ case GPIO3:
++ if(mc_signal->funct == 'R') {
++ // set GPIO to input
++ cpld_set_module_gpio_dir(CPLD_M4, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 3, CPLD_GPIO_IN);
++ // read GPIO
++ read_value = cpld_read_gpio_data_reg(CPLD_M4);
++ // read interrupt
++ read_value |= cpld_interrupt_status(INT_M4_INT) << 4;
++ mc_signal->value = read_value;
++ } else if(mc_signal->funct == 'H') {
++ // write GPIO
++ cpld_set_module_gpio_data(CPLD_M4, 0, mc_signal->value & 0x1);
++ cpld_set_module_gpio_data(CPLD_M4, 1, (mc_signal->value & 0x2) >> 1);
++ cpld_set_module_gpio_data(CPLD_M4, 2, (mc_signal->value & 0x4) >> 2);
++ cpld_set_module_gpio_data(CPLD_M4, 3, (mc_signal->value & 0x8) >> 3);
++ // set GPIO to output
++ cpld_set_module_gpio_dir(CPLD_M4, 0, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M4, 1, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M4, 2, CPLD_GPIO_OUT);
++ cpld_set_module_gpio_dir(CPLD_M4, 3, CPLD_GPIO_OUT);
++ } else {
++ return -1;
++ }
++ break;
++ case PRES0:
++ if(mc_signal->funct != 'R') {
++ printk("do_cpld_sig(): Illegal function for CPLD PRES signal\n");
++ return -1;
++ }
++ read_value = (cpld_read_module_present_status(CPLD_M1) >> 2) & 0x1;
++ mc_signal->value = read_value;
++ break;
++ case PRES1:
++ if(mc_signal->funct != 'R') {
++ printk("do_cpld_sig(): Illegal function for CPLD PRES signal\n");
++ return -1;
++ }
++ read_value = (cpld_read_module_present_status(CPLD_M2) >> 2) & 0x1;
++ mc_signal->value = read_value;
++ break;
++ case PRES2:
++ if(mc_signal->funct != 'R') {
++ printk("do_cpld_sig(): Illegal function for CPLD PRES signal\n");
++ return -1;
++ }
++ read_value = (cpld_read_module_present_status(CPLD_M3) >> 2) & 0x1;
++ mc_signal->value = read_value;
++ break;
++ case PRES3:
++ if(mc_signal->funct != 'R') {
++ printk("do_cpld_sig(): Illegal function for CPLD PRES signal\n");
++ return -1;
++ }
++ read_value = (cpld_read_module_present_status(CPLD_M4) >> 2) & 0x1;
++ mc_signal->value = read_value;
++ break;
++ case CAM_IF:
++ if(mc_signal->funct != 'W') {
++ printk("do_cpld_sig(): Illegal function for CPLD CAM_IF signal\n");
++ return -1;
++ }
++ cpld_sensor_active(CAM_CLK_RISE);
++ break;
++ case CAM_LOCK_STATUS:
++ if(mc_signal->funct != 'R') {
++ printk("do_cpld_sig(): Illegal function for CPLD CAM_LOCK_STATUS signal\n");
++ return -1;
++ }
++ read_value = (int) __raw_readw(CPLD_BASE_ADDRESS+CPLD_CAM);
++ read_value = cpld_sensor_lock_status();
++ mc_signal->value = read_value;
++ break;
++ case LCD:
++ if(mc_signal->funct != 'W') {
++ printk("do_cpld_sig(): Illegal function for CPLD LCD signal\n");
++ return -1;
++ }
++ cpld_lcd_inactive(0);
++ cpld_lcd_inactive(1);
++ cpld_lcd_active(0, 0, LCD_MODE_I80);
++ cpld_lcd_active(1, 0, LCD_MODE_I80);
++ break;
++ default:
++ printk("do_cpld_sig(): unknown signal\n");
++ return -1;
++ }
++ return 0;
++}
++
++ // ioctl
++int bug_ft_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ int slot = MINOR(inode->i_rdev);
++ struct bug_ft *bug_ft = (struct bug_ft *) filp->private_data;
++ struct i2c_adapter *adap = &bug_ft->bdev[slot]->adap;
++ unsigned char iox_data[1];
++ struct iox_i2c_xfer iox_i2c_xfer;
++ struct spi_xfer spi_xfer;
++ struct mc_signal mc_signal;
++ u8 buf[4];
++ int ret = 0;
++
++ // error if no ft active.
++ if(bug_ft->active == -1)
++ return -ENODEV;
++
++ // error if no BMI device
++ if(bug_ft->bdev[slot] == 0)
++ return -ENODEV;
++
++ // get I2C transfer structure
++ if((cmd == FT_READ_IOX) || (cmd == FT_WRITE_IOX))
++ if(copy_from_user(&iox_i2c_xfer, (struct iox_i2c_xfer *) arg, sizeof(struct iox_i2c_xfer))) {
++ printk(KERN_INFO "factory_test ioctl(%d): copy_from_user #1 = %d\n", slot, ret);
++ return -EFAULT;
++ }
++
++ // get SPI transfer structure
++ if((cmd == FT_READ_SPI) || (cmd == FT_WRITE_SPI))
++ if(copy_from_user(&spi_xfer, (struct spi_xfer *) arg, sizeof(struct spi_xfer))) {
++ printk(KERN_INFO "factory_test ioctl(%d): copy_from_user #1 = %d\n", slot, ret);
++ return -EFAULT;
++ }
++
++ // get signal structure
++ if(cmd == FT_SIGNAL)
++ if(copy_from_user(&mc_signal, (struct mc_signal *) arg, sizeof(struct mc_signal))) {
++ printk(KERN_INFO "factory_test ioctl(%d): copy_from_user #1 = %d\n", slot, ret);
++ return -EFAULT;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ // read IOX
++ case FT_READ_IOX:
++ ret = ReadByte_IOX(adap, iox_i2c_xfer.addr, iox_i2c_xfer.offset, iox_data);
++ if(ret == 0) {
++ iox_i2c_xfer.data = *iox_data;
++ if(copy_to_user((struct iox_i2c_xfer *) arg, &iox_i2c_xfer, sizeof(struct iox_i2c_xfer)))
++ ret = -EFAULT;
++ }
++ break;
++ // write IOX
++ case FT_WRITE_IOX:
++ *iox_data = iox_i2c_xfer.data;
++ ret = WriteByte_IOX(adap, iox_i2c_xfer.addr, iox_i2c_xfer.offset, *iox_data);
++ if(ret == 0) {
++ if(copy_to_user((struct iox_i2c_xfer *) arg, &iox_i2c_xfer, sizeof(struct iox_i2c_xfer))) {
++ ret = -EFAULT;
++ }
++ }
++ break;
++ // read SPI
++ case FT_READ_SPI:
++ // READ
++ buf[3] = 0xC0 | ((spi_xfer.addr & 0x3F) >> 1);
++ buf[2] = 0x00 | ((spi_xfer.addr & 0x1) << 7);
++ buf[1] = 0x00;
++ buf[0] = 0x00;
++ ret = spi_read_reg(bug_ft, buf, slot);
++ if(ret == 4) {
++ spi_xfer.data[1] = ((buf[2] & 0x7F) << 1) | ((buf[1] & 0x80) >> 7);
++ spi_xfer.data[0] = ((buf[1] & 0x7F) << 1) | ((buf[0] & 0x80) >> 7);
++ if(copy_to_user((struct spi_xfer *) arg, &spi_xfer, sizeof(struct spi_xfer)))
++ ret = -EFAULT;
++ else
++ ret = 0;
++ } else
++ ret = FT_ERR;
++ break;
++ // write SPI
++ case FT_WRITE_SPI:
++ // EWEN
++ buf[3] = 0x98;
++ buf[2] = 0x00;
++ buf[1] = 0x00;
++ buf[0] = 0x00;
++ ret = spi_write_reg(bug_ft, buf, slot);
++ if(ret != 1) {
++ ret = FT_ERR;
++ break;
++ }
++ // WRITE
++ buf[3] = 0xA0 | ((spi_xfer.addr & 0x3F) >> 1);
++ buf[2] = 0x00 | ((spi_xfer.addr & 0x1) << 7) | (spi_xfer.data[1] >> 1);
++ buf[1] = ((spi_xfer.data[1] & 0x1) << 7) | (spi_xfer.data[0] >> 1);
++ buf[0] = spi_xfer.data[0] << 0x7;
++ ret = spi_write_reg(bug_ft, buf, slot);
++ if(ret == 1) {
++ if(copy_to_user((struct spi_xfer *) arg, &spi_xfer, sizeof(struct spi_xfer)))
++ ret = -EFAULT;
++ else
++ ret = 0;
++ } else
++ ret = FT_ERR;
++
++ break;
++ case FT_SIGNAL:
++ if(mc_signal.bus == MX31) {
++ ret = do_mx31_sig(&mc_signal);
++ if((mc_signal.funct == 'R') && (ret == 0)) {
++ if(copy_to_user((struct mc_signal *) arg, &mc_signal, sizeof(struct mc_signal))) {
++ ret = -EFAULT;
++ } else {
++ ret = 0;
++ }
++ }
++ } else if(mc_signal.bus == CPLD) {
++ ret = do_cpld_sig(&mc_signal);
++ if((mc_signal.funct == 'R') && (ret == 0)) {
++ if(copy_to_user((struct mc_signal *) arg, &mc_signal, sizeof(struct mc_signal))) {
++ ret = -EFAULT;
++ } else {
++ ret = 0;
++ }
++ }
++ } else {
++ ret = FT_ERR;
++ }
++ break;
++ default:
++ return -ENOTTY;
++ }
++
++ return ret;
++}
++
++/*
++ * BMI functions
++ */
++
++static const struct file_operations bug_ft_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = bug_ft_ioctl,
++ .open = bug_ft_open,
++ .release = bug_ft_release,
++};
++
++int bug_ft_probe(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++ struct cdev *cdev_ptr;
++ dev_t dev_id;
++ int ret;
++ unsigned long speed = 1000000;
++ unsigned char mode = SPI_MODE_2 | SPI_CS_HIGH;
++ unsigned char bits_per_word = 32;
++
++
++ printk(KERN_INFO "factory_test.c: probe slot %d\n", slot);
++
++ cdev_ptr = &bug_ft.cdev;
++ cdev_init(cdev_ptr, &bug_ft_fops);
++
++ dev_id = MKDEV(major, bdev->info->slot);
++ ret = cdev_add(cdev_ptr, dev_id, 1);
++ if(ret)
++ return ret;
++
++ switch(slot) {
++ case 0:
++ cpld_set_module_gpio_dir(CPLD_M1, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M1, 3, CPLD_GPIO_IN);
++ ret = bmi_device_spi_setup(bdev, speed, mode, bits_per_word);
++ if (ret) {
++ printk (KERN_ERR "bug_ft_probe() - bmi_device_spi_setup(0) failed.\n");
++ return ret;
++ }
++ bug_ft.spi[0] = &bdev->spi;
++ break;
++ case 1:
++ cpld_set_module_gpio_dir(CPLD_M2, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M2, 3, CPLD_GPIO_IN);
++ ret = bmi_device_spi_setup(bdev, speed, mode, bits_per_word);
++ if (ret) {
++ printk (KERN_ERR "bug_ft_probe() - bmi_device_spi_setup(2) failed.\n");
++ return ret;
++ }
++ bug_ft.spi[1] = &bdev->spi;
++ break;
++ case 2:
++ cpld_set_module_gpio_dir(CPLD_M3, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M3, 3, CPLD_GPIO_IN);
++ ret = bmi_device_spi_setup(bdev, speed, mode, bits_per_word);
++ if (ret) {
++ printk (KERN_ERR "bug_ft_probe() - bmi_device_spi_setup(3) failed.\n");
++ return ret;
++ }
++ bug_ft.spi[2] = &bdev->spi;
++ break;
++ case 3:
++ cpld_set_module_gpio_dir(CPLD_M4, 0, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 1, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 2, CPLD_GPIO_IN);
++ cpld_set_module_gpio_dir(CPLD_M4, 3, CPLD_GPIO_IN);
++ ret = bmi_device_spi_setup(bdev, speed, mode, bits_per_word);
++ if (ret) {
++ printk (KERN_ERR "bug_ft_probe() - bmi_device_spi_setup(3) failed.\n");
++ return ret;
++ }
++ bug_ft.spi[3] = &bdev->spi;
++ break;
++ }
++ if(ret) {
++ cdev_del(cdev_ptr);
++ return ret;
++ }
++
++ bmi_device_set_drvdata(bdev, &bug_ft);
++
++ bug_ft.bdev[slot] = bdev;
++
++ bug_ft.active = 1;
++
++ return 0;
++}
++
++void bug_ft_remove(struct bmi_device *bdev)
++{
++ struct bug_ft *bug_ft = (struct bug_ft*)(bmi_device_get_drvdata (bdev));
++ int slot = bdev->info->slot;
++ struct cdev *cdev_ptr;
++ dev_t dev_id;
++
++ switch(slot) {
++ case 0:
++ bmi_device_spi_cleanup(bdev);
++ break;
++ case 1:
++ bmi_device_spi_cleanup(bdev);
++ break;
++ case 2:
++ bmi_device_spi_cleanup(bdev);
++ break;
++ case 3:
++ bmi_device_spi_cleanup(bdev);
++ break;
++ }
++
++ bug_ft->bdev[slot] = 0;
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata(&bdev[slot], 0);
++
++ if((bug_ft->bdev[0]==0) && (bug_ft->bdev[1]==0) &&
++ (bug_ft->bdev[2]==0) && (bug_ft->bdev[3]==0)) {
++ bug_ft->active = -1;
++ cdev_ptr = &bug_ft->cdev;
++ dev_id = MKDEV(major, bdev->info->slot);
++ cdev_del(cdev_ptr);
++ }
++
++ return;
++}
++
++/*
++ * Module functions
++ */
++
++static __init int bug_ft_init(void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // No ft is active.
++ bug_ft.active = -1;
++
++ // alloc char driver with 4 minor numbers
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BUG Factory Test Driver");
++ if (retval) {
++ return -1;
++ }
++
++ major = MAJOR(dev_id);
++
++ printk("factory_test.c: BUG FACTORY TEST Driver v%s (major = %d)\n", BUG_FACTORY_TEST_VERSION, major);
++
++ return bmi_register_driver(&bug_ft_driver);
++}
++
++static void __exit bug_ft_clean(void)
++{
++ dev_t dev_id = MKDEV(major, 0);
++
++ unregister_chrdev_region(dev_id, 4);
++ bmi_unregister_driver(&bug_ft_driver);
++
++ return;
++}
++
++module_init(bug_ft_init);
++module_exit(bug_ft_clean);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BUG Factory Test board device driver");
++MODULE_SUPPORTED_DEVICE("bug_ft_control");
++
+--- /dev/null
++++ git/drivers/bmi/pims/gps/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BMI_GPS) += bmi_gps.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/gps/bmi_gps.c
+@@ -0,0 +1,468 @@
++/*
++ * bmi_gps.c
++ *
++ * BMI gps device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++
++//REWORK: Which are not needed ?
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <asm/uaccess.h>
++//#include <mach/mxc_i2c.h>
++#include <linux/bmi.h>
++//#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_gps.h>
++//#include <mach/mx31bug_cpld.h>
++
++//MTW
++#include <linux/cdev.h>
++
++
++#define BMIGPS_VERSION "1.1"
++
++
++// private device structure
++struct bmi_gps
++{
++ struct bmi_device *bdev; // BMI device
++ struct cdev cdev;
++ struct device *class_dev;
++ int open_flag; // single open flag
++ struct i2c_client *iox;
++};
++
++static struct bmi_gps bmi_gps[4];
++static int major;
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_gps_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_GPS_J32,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_gps_tbl);
++
++int bmi_gps_probe(struct bmi_device *bdev);
++void bmi_gps_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_gps_driver =
++{
++ .name = "bmi_gps",
++ .id_table = bmi_gps_tbl,
++ .probe = bmi_gps_probe,
++ .remove = bmi_gps_remove,
++};
++
++/*
++ * I2C set up
++ */
++
++// I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++
++// I2C IOX register addresses
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++static struct i2c_board_info iox_info = {
++ I2C_BOARD_INFO("VH_IOX", BMI_IOX_I2C_ADDRESS),
++};
++
++// read byte from I2C IO expander
++
++static int ReadByte_IOX (struct i2c_client *client, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++
++ ret = i2c_master_send(client, &offset, 1);
++ if (ret == 1)
++ ret = i2c_master_recv(client, data, 1);
++ if (ret < 0)
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++// write byte to I2C IO expander
++static int WriteByte_IOX (struct i2c_client *client, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ unsigned char msg[2];
++
++ msg[0] = offset;
++ msg[1] = data;
++ ret = i2c_master_send(client, msg, sizeof(msg));
++
++ if (ret < 0)
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed...%d\n",ret);
++
++ return ret;
++}
++
++
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *file)
++{
++ struct bmi_gps *gps;
++
++ gps = container_of(inode->i_cdev, struct bmi_gps, cdev);
++
++ // Enforce single-open behavior
++
++ if (gps->open_flag) {
++ return -EBUSY;
++ }
++ gps->open_flag = 1;
++
++ // Save gps_dev pointer for later.
++
++ file->private_data = gps;
++ return 0;
++
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *file)
++{
++ struct bmi_gps *gps;
++
++ gps = (struct bmi_gps *)(file->private_data);
++ gps->open_flag = 0;
++ return 0;
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++
++ unsigned char gpio_mask;
++ struct bmi_gps *gps;
++ int slot;
++
++ gps = (struct bmi_gps *)(file->private_data);
++
++ // error if gps not present
++ if(gps->bdev == 0)
++ return -ENODEV;
++
++ slot = gps->bdev->slot->slotnum;
++ adap = gps->bdev->slot->adap;
++
++ // ioctl's
++ gpio_mask = bmi_slot_gpio_get(slot);
++ switch (cmd) {
++ case BMI_GPS_RLEDOFF:
++ bmi_slot_gpio_set (slot, (gpio_mask | RED_LED)); // Red LED=OFF
++ break;
++
++ case BMI_GPS_RLEDON:
++ bmi_slot_gpio_set (slot, (gpio_mask & ~RED_LED)); // Red LED=ON
++ break;
++
++ case BMI_GPS_GLEDOFF:
++ bmi_slot_gpio_set (slot, (gpio_mask | GREEN_LED)); // Greem LED=OFF
++ break;
++
++ case BMI_GPS_GLEDON:
++ bmi_slot_gpio_set (slot, (gpio_mask & ~GREEN_LED)); // Greem LED=ON
++ break;
++
++ case BMI_GPS_SETBOOT:
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data |= 0x08;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ if(ReadByte_IOX (gps->iox, IOX_CONTROL, &iox_data)) // IOX[3]=BOOT=0, IOX[4]=WAKEUP=0
++ return -ENODEV;
++ iox_data |= 0x08;
++ if(WriteByte_IOX (gps->iox, IOX_CONTROL, iox_data)) // IOX[3]=BOOT=0, IOX[4]=WAKEUP=0
++ return -ENODEV;
++ break;
++
++ case BMI_GPS_CLRBOOT:
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data &= ~0x08;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ break;
++
++ case BMI_GPS_SETWAKE:
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data |= 0x10;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ if(ReadByte_IOX (gps->iox, IOX_CONTROL, &iox_data)) // IOX[3]=BOOT=0, IOX[4]=WAKEUP=0
++ return -ENODEV;
++ iox_data |= 0x10;
++ if(WriteByte_IOX (gps->iox, IOX_CONTROL, iox_data)) // IOX[3]=BOOT=0, IOX[4]=WAKEUP=0
++ return -ENODEV;
++ break;
++
++ case BMI_GPS_CLRWAKE:
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data &= ~0x10;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ break;
++
++ case BMI_GPS_SETRST:
++ bmi_slot_gpio_set (slot, (gpio_mask & ~GPIO_1)); // RST = 0;
++
++ break;
++
++ case BMI_GPS_CLRRST:
++ bmi_slot_gpio_set (slot, (gpio_mask | GPIO_1)); // RST=tristate
++ break;
++
++ case BMI_GPS_GETSTAT:
++ {
++ int read_data;
++
++ if(ReadByte_IOX (gps->iox, IOX_INPUT_REG, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data | (bmi_slot_gpio_get(slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_GPS_ACTIVE_ANT :
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data &= ~0x40;
++ iox_data |= 0x80;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ break;
++
++ case BMI_GPS_PASSIVE_ANT:
++ if(ReadByte_IOX (gps->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ iox_data &= ~0x80;
++ iox_data |= 0x40;
++ if(WriteByte_IOX (gps->iox, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ break;
++
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++// control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++/*
++ * Module functions
++ */
++
++/*
++ * BMI functions
++ */
++
++int bmi_gps_probe(struct bmi_device *bdev)
++{
++ int err;
++ int slot;
++ struct bmi_gps *gps;
++ struct i2c_adapter *adap;
++ struct cdev *cdev;
++ struct class *bmi_class;
++ dev_t dev_id;
++
++ err = 0;
++ slot = bdev->slot->slotnum;
++ adap = bdev->slot->adap;
++ gps = &bmi_gps[slot];
++
++
++ gps->bdev = 0;
++ gps->open_flag = 0;
++
++ //Create 1 minor device
++ cdev = &gps->cdev;
++ cdev_init(cdev, &cntl_fops);
++
++ dev_id = MKDEV(major, slot);
++ err = cdev_add(cdev, dev_id, 1);
++ if (err) {
++ return err;
++ }
++
++ //Create class device
++ bmi_class = bmi_get_class ();
++ gps->class_dev = device_create(bmi_class, NULL, MKDEV(major, slot), gps, "bmi_gps_control_m%i", slot+1);
++
++ if (IS_ERR(gps->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_gps_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(gps->class_dev));
++ gps->class_dev = NULL;
++ }
++
++ //bind driver and bmi_device
++ gps->bdev = bdev;
++ bmi_device_set_drvdata(bdev, gps);
++
++ printk(KERN_INFO "bmi_gps.c: probe slot %d\n", slot);
++
++ // configure IOX - leave ouputs as inputs unless needed
++
++ gps->iox = i2c_new_device(bdev->slot->adap, &iox_info);
++ if (gps->iox == NULL)
++ printk(KERN_ERR "IOX NULL...\n");
++ if(WriteByte_IOX(gps->iox, IOX_OUTPUT_REG, 0x40)) { //
++ return -ENODEV;
++ }
++ if(WriteByte_IOX(gps->iox, IOX_CONTROL, 0x3F)) { // IOX[4:3]=OUT, IOX[7:5,2:0]=IN
++ return -ENODEV;
++ }
++
++
++ // Initialize GPIOs (turn LED's on )
++
++// bmi_slot_gpio_configure_as_output (int slot, int gpio, int data)
++
++ bmi_slot_gpio_configure(slot, RED_LED | GREEN_LED | GPIO_1); // Red, Green LEDS and GPIO_1 outputs
++ bmi_slot_gpio_set(slot, 0);
++
++ //Enable uart transceiver
++ bmi_slot_uart_enable (slot);
++
++ mdelay(275);
++
++ // release reset to J32 device
++ bmi_slot_gpio_set ( slot, RED_LED | GREEN_LED | GPIO_1); // reset high, Red, Green LEDS off
++
++ return 0;
++}
++
++
++void bmi_gps_remove(struct bmi_device *bdev)
++{
++ int slot;
++ struct bmi_gps *gps;
++ struct class *bmi_class;
++
++ slot = bdev->slot->slotnum;
++ gps = &bmi_gps[slot];
++
++ //Disable uart transceiver
++ bmi_slot_uart_disable (slot);
++ bmi_slot_gpio_configure(slot, 0);
++
++ bmi_class = bmi_get_class ();
++ device_destroy(bmi_class, MKDEV(major, slot));
++
++ gps->class_dev = 0;
++
++ cdev_del (&gps->cdev);
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++ gps->bdev = 0;
++
++ return;
++}
++
++
++
++
++
++static void __exit bmi_gps_cleanup(void)
++{
++ dev_t dev_id;
++
++ bmi_unregister_driver (&bmi_gps_driver);
++
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++
++
++
++static int __init bmi_gps_init(void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI GPS Driver");
++
++ if (retval) {
++ return -1;
++ }
++
++ major = MAJOR(dev_id);
++ retval = bmi_register_driver (&bmi_gps_driver);
++
++ if (retval) {
++ unregister_chrdev_region(dev_id, 4);
++ return -1;
++ }
++ printk("bmi_gps.c: BMI_GPS Driver v%s \n", BMIGPS_VERSION);
++
++ return 0;
++}
++
++
++module_init(bmi_gps_init);
++module_exit(bmi_gps_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BMI gps device driver");
++MODULE_SUPPORTED_DEVICE("bmi_gps_control");
++
+--- /dev/null
++++ git/drivers/bmi/pims/gsm/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BMI_GSM) += bmi_gsm.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/gsm/bmi_gsm.c
+@@ -0,0 +1,301 @@
++/*
++ * bmi_gsm.c
++ *
++ * BMI GSM device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/input.h>
++#include <linux/kernel.h>
++#include <linux/major.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <asm/uaccess.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/miscdevice.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi_gsm.h>
++
++#define DEBUG
++#undef DEBUG
++
++#define BMIGSM_VERSION "1.0" // driver version
++
++
++// private device structure
++struct bmi_gsm
++{
++ struct bmi_device *bdev; // BMI device
++ struct cdev cdev; // control device
++ struct device *class_dev; // control class device
++ int open_flag;
++};
++
++static struct bmi_gsm bmi_gsm_priv[4]; // per slot device structure
++static int major; // control device major
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_gsm_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_GSM,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_gsm_tbl);
++
++
++int bmi_gsm_probe(struct bmi_device *bdev);
++void bmi_gsm_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_gsm_driver =
++{
++ .name = "bmi_gsm",
++ .id_table = bmi_gsm_tbl,
++ .probe = bmi_gsm_probe,
++ .remove = bmi_gsm_remove,
++};
++
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *file)
++{
++ struct bmi_gsm *gsmod;
++
++ gsmod = container_of (inode->i_cdev, struct bmi_gsm, cdev);
++
++ // Enforce single-open behavior
++
++ if (gsmod->open_flag) {
++ return -EBUSY;
++ }
++ gsmod->open_flag = 1;
++
++ // Save gsm_dev pointer for later.
++
++ file->private_data = gsmod;
++ return 0;
++
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *file)
++{
++ struct bmi_gsm *gsmod;
++
++ gsmod = (struct bmi_gsm *)(file->private_data);
++ gsmod->open_flag = 0;
++ return 0;
++}
++
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct bmi_gsm *gsmod;
++ unsigned char temp = 0;
++ int slot;
++
++
++ gsmod = (struct bmi_gsm *)(filp->private_data);
++
++ if(gsmod->bdev == 0)
++ return -ENODEV;
++
++ slot = gsmod->bdev->slot->slotnum;
++
++ // ioctl's
++ temp = bmi_slot_gpio_get(slot);
++ switch (cmd) {
++ case BMI_GSM_RLEDOFF:
++ bmi_slot_gpio_set(slot, temp & (~RED_LED)); // Red LED=OFF
++ break;
++ case BMI_GSM_RLEDON:
++ bmi_slot_gpio_set(slot, temp | RED_LED); // Red LED=ON
++ break;
++ case BMI_GSM_GLEDOFF:
++ bmi_slot_gpio_set(slot, temp & (~GREEN_LED)); // Green LED=OFF
++ break;
++ case BMI_GSM_GLEDON:
++ bmi_slot_gpio_set(slot, temp | GREEN_LED); // Green LED=ON
++ break;
++ }
++ return 0;
++}
++
++// control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++
++// Probe
++int bmi_gsm_probe(struct bmi_device *bdev)
++{
++ int slot;
++ int status;
++ int temp = 0;
++ dev_t dev_id;
++ struct cdev *cdev;
++ struct class *bmi_class;
++ struct bmi_gsm *gsmod;
++
++
++ slot = bdev->slot->slotnum;
++ gsmod = &bmi_gsm_priv[slot];
++ gsmod->bdev = 0;
++ gsmod->open_flag = 0;
++
++ cdev = &gsmod->cdev;
++ cdev_init(cdev, &cntl_fops);
++ dev_id = MKDEV(major, slot);
++ status = cdev_add(cdev, dev_id, 1);
++ if ( status)
++ return status;
++
++ bmi_class = bmi_get_class();
++ gsmod->class_dev = device_create (bmi_class, NULL, MKDEV(major, slot), NULL, "bmi_gsm_ctl_m%i", slot + 1);
++
++ if (IS_ERR(gsmod->class_dev))
++ {
++ printk(KERN_ERR "Unable to create class device for bmi_gsm_ctl_m%i...", slot + 1);
++ gsmod->class_dev = NULL;
++ cdev_del(&gsmod->cdev);
++ return -ENODEV;
++ }
++
++ // configure GPIO
++
++ // set GPIO direction
++ bmi_slot_gpio_configure (slot, RED_LED | GREEN_LED | GPIO_0);
++
++ // turn LED's on
++ bmi_slot_gpio_set (slot, ~(RED_LED | GREEN_LED | GPIO_0));
++ mdelay(500);
++ // turn LED's off
++ bmi_slot_gpio_set (slot, (RED_LED | GREEN_LED));
++
++ // Check if SIM is present...
++ // gpio_reg = bmi_read_gpio_data_reg(slot);
++ // turn mini-card on
++ printk(KERN_INFO "Turning Sierra Wireless Card On...\n");
++ temp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set(slot, temp & (~GPIO_0));
++
++ // set up bdev/pbmi_gsm pointers
++ gsmod->bdev = bdev;
++ bmi_device_set_drvdata(bdev, &gsmod);
++
++ return 0;
++}
++
++// remove
++void bmi_gsm_remove(struct bmi_device *bdev)
++{
++ int slot;
++ struct bmi_gsm *gsmod;
++ struct class *bmi_class;
++
++ slot = bdev->slot->slotnum;
++
++ gsmod = &bmi_gsm_priv[slot];
++
++ bmi_slot_gpio_configure(slot, 0);
++
++ bmi_class = bmi_get_class ();
++ device_destroy (bmi_class, MKDEV(major, slot));
++
++ gsmod->class_dev = 0;
++
++ cdev_del (&gsmod->cdev);
++
++ // de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++ gsmod->bdev = 0;
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, NULL);
++
++ return;
++}
++
++
++static __init int bmi_gsm_init(void)
++{
++
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++ retval = alloc_chrdev_region (&dev_id, 0, 4, "BMI GSM Driver");
++ if (retval) {
++ return -ENODEV;
++ }
++
++ major = MAJOR(dev_id);
++ retval = bmi_register_driver (&bmi_gsm_driver);
++ if (retval) {
++ unregister_chrdev_region(dev_id, 4);
++ return -ENODEV;
++ }
++
++ printk("bmi_gsm.c: BMI_GSM Driver v%s \n", BMIGSM_VERSION);
++
++ return 0;
++}
++
++static void __exit bmi_gsm_clean(void)
++{
++ dev_t dev_id;
++
++ bmi_unregister_driver (&bmi_gsm_driver);
++
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region (dev_id, 4);
++ return;
++}
++
++module_init(bmi_gsm_init);
++module_exit(bmi_gsm_clean);
++
++MODULE_AUTHOR("Matt Isaacs <izzy@buglabs.net>");
++MODULE_DESCRIPTION("BMI gsm device driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/Makefile
+@@ -0,0 +1,9 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_VIDEO_BMI_LCD) += bmi_lcd_core.o
++bmi_lcd_core-objs := bmi_lcd.o acc.o
++
++obj-$(CONFIG_VIDEO_BMI_LCD_S320X240) += bmi_s320x240.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/acc.c
+@@ -0,0 +1,114 @@
++#include "acc.h"
++#include <asm/uaccess.h>
++#include <linux/bmi.h>
++#include <linux/device.h>
++
++#define BMI_SLOT_NUM 4
++
++static dev_t acc_dev_number;
++
++static struct file_operations acc_fops = {
++ .owner = THIS_MODULE,
++ .open = acc_open,
++ .read = acc_read,
++ .release = acc_release
++};
++
++
++int acc_open(struct inode *inode, struct file *file)
++{
++ struct acc_dev * acc;
++
++ printk(KERN_DEBUG "ACC_OPEN\n");
++
++ acc = container_of(inode->i_cdev, struct acc_dev, cdev);
++
++ file->private_data = acc;
++
++ return 0;
++}
++
++int acc_release(struct inode *inode, struct file *file)
++{
++ printk(KERN_DEBUG "ACC_RELEASE");
++
++ return 0;
++}
++
++int acc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
++{
++ struct acc_dev * acc = file->private_data;
++ int result = 0;
++
++ if(count < 6) {
++ return -EINVAL;
++ }
++
++ if(wait_event_interruptible(acc->wq, acc->flag != 0)) {
++ return -ERESTARTSYS;
++ }
++
++ result = copy_to_user(buf, acc->sample, 6);
++ acc->flag = 0;
++ if(result) {
++ return -EFAULT;
++ }
++
++ return 6;
++}
++
++int acc_init()
++{
++ if(alloc_chrdev_region(&acc_dev_number, 0, BMI_SLOT_NUM, "bmi_lcd_acc") < 0) {
++ printk(KERN_DEBUG "Unable to register accelerometer device\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++int acc_clean()
++{
++ unregister_chrdev_region(MAJOR(acc_dev_number), BMI_SLOT_NUM);
++ return 0;
++}
++
++/* BMI Functions */
++int acc_probe (struct acc_dev *acc, int slot)
++{
++ struct class * bmi_class;
++ struct cdev * cdev;
++ int ret;
++
++ printk(__FUNCTION__);
++ cdev = &acc->cdev;
++ printk(KERN_DEBUG "\nAbout to cdev_init acc=%p cdev=%p\n acc_fops=%p\n", acc, cdev, &acc_fops);
++ cdev_init(cdev, &acc_fops);
++ printk(KERN_DEBUG "After cdev_init\n");
++
++ ret = cdev_add(cdev, acc_dev_number + slot, 1);
++ printk(KERN_DEBUG "After cdev_add" );
++
++ bmi_class = (struct class *) bmi_get_bmi_class();
++ printk(KERN_DEBUG "After bmi_get_bmi_class" );
++ acc->class_dev = device_create(bmi_class, NULL, acc_dev_number + slot, acc, "bmi_lcd_acc_m%d", slot + 1);
++ printk(KERN_DEBUG "After class_device_create" );
++
++ init_waitqueue_head(&acc->wq);
++ printk(KERN_DEBUG "After init_waitqueue_head" );
++ return ret;
++}
++
++void acc_remove (struct acc_dev *acc, int slot)
++{
++ struct class *bmi_class;
++ int acc_major = MAJOR(acc_dev_number);
++
++ bmi_class = (struct class *) bmi_get_bmi_class();
++ device_destroy (bmi_class, MKDEV(acc_major, slot));
++
++ acc->class_dev = 0;
++
++ cdev_del (&acc->cdev);
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/acc.h
+@@ -0,0 +1,35 @@
++#ifndef _ACC_H_
++#define _ACC_H_
++
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++
++/* Accelerometer device structure */
++struct acc_dev {
++ struct cdev cdev;
++ u8 sample[6];
++ u8 flag;
++ struct device * class_dev;
++ wait_queue_head_t wq;
++};
++
++
++int acc_open(struct inode *inode, struct file *file);
++
++int acc_release(struct inode *inode, struct file *file);
++
++int acc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
++
++int acc_init(void);
++
++int acc_clean(void);
++
++/*BMI Functions */
++void acc_remove(struct acc_dev *acc, int slot);
++
++int acc_probe(struct acc_dev *acc, int slot);
++
++#endif //_ACC_H_
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/bmi_lcd.c
+@@ -0,0 +1,1790 @@
++/*
++ * bmi_lcd.c
++ *
++ * BMI LCD device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/input.h>
++#include <linux/kernel.h>
++#include <linux/major.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <asm/uaccess.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/cdev.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <mach/mxc_i2c.h>
++#include <mach/mx31bug_cpld.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/bmi/bmi_lcd.h>
++#include <mach/ipu.h>
++
++#undef ACCELEROMETER
++#define ACCELEROMETER
++
++#ifdef ACCELEROMETER
++#include "acc.h"
++#endif //ACCELEROMETER
++
++#define DEBUG
++#undef DEBUG
++
++#define BMILCD_VERSION "1.2" // driver version
++#define BUF_MAX_SIZE 0x20 // spi buffer size
++#define WORK_DELAY (1) // interrupt work handler delay
++#define DEBOUNCE 10 // touch screen debounce
++#define X_PLATE 400 // touch screen X plate resistance //pjg - This is not the correct value
++#define BMI_SLOT_NUM (4) // number of BMI slots
++#define MAX_STRG (40) // Max string buffer size
++
++#define VSYNC_DISABLE 0x0
++#define VSYNC_ENABLE 0x1
++
++ // lcd
++struct lcd_interface {
++ char lcd_type[MAX_STRG]; // text description of LCD type
++ u8 suspended; // power management state
++ u8 rotation; // screen rotation
++ u8 disp; // display number (DISP0 or DISP1)
++ u8 addr_mode; // display addressing mode
++ u8 vsync_mode; // VSYNC signal enable (VSYNC_ENABLE | VSYNC_DISABLE)
++ u8 bus_if_type; // bus type (XY | FullWoBE | FullWithBE)
++ ipu_adc_sig_cfg_t adc_sig; // IPU ADC set-up parameters
++ ipu_di_signal_cfg_t di_sig; // IPU DI set-up parameters
++};
++
++
++struct lcd_ctl
++{
++ int slot;
++ struct cdev cdev;
++ struct device *class_dev;
++};
++
++
++static struct lcd_interface s320x240_lcd_interface = {
++ .lcd_type = "MXCFB_SHARP_320X240",
++ .suspended = 0,
++ .rotation = IPU_ROTATE_NONE,
++ .disp = DISP0,
++ .vsync_mode = VSYNC_DISABLE,
++ .bus_if_type = XY,
++ .adc_sig = { 0, 0, 0, 0, 0, 0, 0, 0, IPU_ADC_BURST_WCS, IPU_ADC_IFC_MODE_SYS80_TYPE2,
++ 16, 0, 0, IPU_ADC_SER_NO_RW },
++ .di_sig = { 0,0,0,0,0,0,0,0 }, //pjg - reserved for multiple LCD driver
++};
++
++extern void s320x240_config(int disp);
++extern void s320x240_disp_off(int disp);
++extern void s320x240_disp_on(int disp);
++
++
++struct bmi_lcd;
++
++struct bmi_lcd_ops {
++ void *(*config) (int disp); // LCD configuration/initialization
++ void *(*reset) (int slot); // LCD reset
++ int *(*suspend) (struct bmi_lcd *blcd); // power management
++ int *(*resume) (struct bmi_lcd *blcd); // power management
++ int *(*disp_on) (int disp); // display on
++ int *(*disp_off) (int disp); // display off
++ int (*activate) (struct bmi_lcd *lcd, int slot); // enable LCD backlight, touchscreen, accelerometer, ...
++ int (*deactivate) (struct bmi_lcd *lcd, int slot); // disable LCD backlight, touchscreen, accelerometer, ...
++};
++
++struct bmi_lcd_ops s320x240_bmi_lcd_ops;
++
++struct bmi_lcd {
++ struct lcd_interface interface; // pointer to this struct is returned by config()
++ struct bmi_lcd_ops lcd_ops; // function pointers
++};
++
++static struct bmi_lcd s320x240_bmi_lcd;
++
++int register_bmi_lcd(struct bmi_lcd *blcd, int slot);
++int unregister_bmi_lcd(struct bmi_lcd *blcd, int slot);
++
++ // private device structure
++struct pbmi_lcd
++{
++ unsigned int lcd_cnt; // number of LCD's present
++ unsigned int active; // indication of LCD presence
++ unsigned int activated[BMI_SLOT_NUM]; // indication of LCD presence
++
++ struct bmi_lcd *blcd[BMI_SLOT_NUM]; // BMI LCD structure - placeholder for multiple display types
++ struct bmi_device *bdev[BMI_SLOT_NUM]; // BMI device per slot
++ unsigned int interrupt[BMI_SLOT_NUM]; // input device interrupt handlers
++ char int_name[MAX_STRG]; // interrupt name
++
++ struct input_dev *input_dev[BMI_TS_NUM]; // input device (touch screen and accelerometer)
++ struct timer_list timer[BMI_SLOT_NUM]; // touch timer
++ struct lcd_ctl ctl_dev[BMI_SLOT_NUM];
++ int pen_down[BMI_SLOT_NUM];
++ int scount[BMI_SLOT_NUM];
++
++ struct spi_device *spi[BMI_SLOT_NUM]; // touch screen device interface
++ struct semaphore sem[BMI_SLOT_NUM]; // spi semaphore
++ char rbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi read buffer
++ char wbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi write buffer
++
++#ifdef ACCELEROMETER
++ struct acc_dev acc[BMI_SLOT_NUM];
++#endif
++};
++
++static struct pbmi_lcd pbmi_lcd; // LCD device sructure
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_lcd_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_LCD_SHARP_320X240,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_lcd_tbl);
++
++/*printk(KERN_INFO "MDT: 0x%x\n", __mod_bmi_device_table);*/
++
++int bmi_lcd_probe(struct bmi_device *bdev);
++void bmi_lcd_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_lcd_driver =
++{
++ .name = "bmi_lcd",
++ .id_table = bmi_lcd_tbl,
++ .probe = bmi_lcd_probe,
++ .remove = bmi_lcd_remove,
++};
++
++//Accelerometer driver structure
++
++
++/*
++ * I2C set up
++ */
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define BMI_ACC_I2C_ADDRESS 0x17 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0 // IOX input data register
++#define IOX_OUTPUT_REG 0x1 // IOX output data register
++#define IOX_POLARITY_REG 0x2 // IOX polarity data register
++#define IOX_CONTROL 0x3 // IOX direction control register
++#define IOX_B1 (0) // bit 0 - backlight control
++#define IOX_A1_A2 (1) // bit 1 - backlight control
++#define IOX_ACC_RST_N (2) // bit 2 - acceleromter reset
++#define IOX_VSYNC_EN_N (3) // bit 3 - VSYNC output buffer enable
++#define IOX_LCD_RST_N (4) // bit 4 - LCD reset
++#define IOX_SERDES_PD_N (5) // bit 5 - SERDES power down
++#define IOX_X_INT (6) // bit 6 - accelerometer interrupt
++#define IOX_Y_INT (7) // bit 7 - accelerometer interrupt
++
++ // I2C ACC register addresses - OKI
++#define ACC_PAGESEL 0x1E // device ready status
++ // page 0
++#define ACC_DVRST 0x01 // device reset
++ #define ACC_DVRST_RST 0x3C // device reset
++ #define ACC_DVRST_EN 0xC3 // device enable
++#define ACC_PDWN 0x02 // osc power down
++ #define ACC_PWDN_RST 0x01 // device reset
++ #define ACC_PWDN_EN 0x00 // device enable
++#define ACC_CTRL0 0x03 // control 0
++ #define ACC_CTRL0_CTSTR 0x40 // control 0 - temp sensor
++ #define ACC_CTRL0_CGSTRNC 0x08 // control 0 - 3-axis/no tilt
++ #define ACC_CTRL0_CGSTRC 0x04 // control 0 - 3-axis/tilt
++ #define ACC_CTRL0_CGAUTO 0x01 // control 0 - auto
++#define ACC_MODE0 0x05 // control 0
++ #define ACC_MODE0_PDOFF 0x80 // mode 0 - disable auto power down
++ #define ACC_MODE0_RVOFF 0x40 // mode 0 - disable temp compensation
++ #define ACC_MODE0_TMPOFF 0x20 // mode 0 - disable temp measurement
++ #define ACC_MODE0_AGCON 0x10 // mode 0 - enable auto mode pitch and roll
++ #define ACC_MODE0_MAUTO 0x04 // mode 0 - enable auto termination
++ #define ACC_MODE0_GDET00 0x00 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET01 0x01 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET10 0x02 // mode 0 - g detection threshold - see ML8953 data sheet
++#define ACC_MODE1 0x06 // mode 1
++ #define ACC_MODE1_MOFF 0x20 // mode 1 - disable 3-axis continuous mode
++ #define ACC_MODE1_ZAXIS 0x03 // mode 1 - Z axis
++ #define ACC_MODE1_YAXIS 0x02 // mode 1 - Y axis
++ #define ACC_MODE1_XAXIS 0x01 // mode 1 - X axis
++ #define ACC_MODE1_RAXIS 0x00 // mode 1 - Reference axis
++#define ACC_INTRQ 0x07 // interrupt request (1 = request)
++#define ACC_INTMSK 0x08 // interrupt mask (1 = masked)
++ #define ACC_INT_TREQ 0x20 // interrupt - temperature
++ #define ACC_INT_GREQ 0x08 // interrupt - acceleration/no tilt
++ #define ACC_INT_GCREQ 0x04 // interrupt - acceleration/tilt
++ #define ACC_INT_GAREQ 0x01 // interrupt - automatic
++#define ACC_TMDL 0x09 // timer LSB = (1/6.2 MHz) x 2048 x TMD
++#define ACC_TMDH 0x0A // timer MSB
++#define ACC_CFG 0x0C // configuration
++ #define ACC_CFG_REGMD 0x80 // address auto-increment
++ #define ACC_CFG_SPI3M_3 0x40 // spi mode = 3-wire
++ #define ACC_CFG_SPI3M_4 0x00 // spi mode = 4-wire
++ #define ACC_CFG_SDOCFG_T 0x10 // sdo mode = totem-pole
++ #define ACC_CFG_SDOCFG_OC 0x00 // sdo mode = open-drain
++ #define ACC_CFG_INT1EN_G 0x08 // interrupt 1 mode = g only
++ #define ACC_CFG_INT1EN_ALL 0x00 // interrupt 1 mode = all
++ #define ACC_CFG_INTLVL 0x04 // interrupt level mode
++ #define ACC_CFG_INT1CFG_T 0x02 // interrupt 1 mode = totem-pole
++ #define ACC_CFG_INT1CFG_OC 0x00 // interrupt 1 mode = open-drain
++ #define ACC_CFG_INT0CFG_T 0x01 // interrupt 0 mode = totem-pole
++ #define ACC_CFG_INT0CFG_OC 0x00 // interrupt 0 mode = open-drain
++#define ACC_INTOTM 0x0D // interrupt output conditions
++#define ACC_GAAVE 0x0E // Data averaging - automatic mode
++#define ACC_GNAVE 0x0F // Data averaging - normal mode
++#define ACC_GDTCT0L 0x11 // threshold 0 LSB
++#define ACC_GDTCT0H 0x12 // threshold 0 MSB
++#define ACC_GDTCT1L 0x13 // threshold 1 LSB
++#define ACC_GDTCT1H 0x14 // threshold 1 MSB
++#define ACC_CPURDY 0x15 // device ready status (ready = 0x01)
++ // page 1
++#define ACC_STATUS 0x01 // measurment status
++ #define ACC_STATUS_ASTS 0x02 // acceleration measurement - automatic modes
++ #define ACC_STATUS_STS 0x01 // acceleration measurement - non-automatic modes
++#define ACC_GAXL 0x02 // g vector
++#define ACC_GAXH 0x03 // g vector
++#define ACC_GAYL 0x04 // g vector
++#define ACC_GAYH 0x05 // g vector
++#define ACC_GAZL 0x06 // g vector
++#define ACC_GAZH 0x07 // g vector
++#define ACC_GASVL 0x08 // g vector
++#define ACC_GASVH 0x09 // g vector
++#define ACC_GNXL 0x0A // g vector
++#define ACC_GNXH 0x0B // g vector
++#define ACC_GNYL 0x0C // g vector
++#define ACC_GNYH 0x0D // g vector
++#define ACC_GNZL 0x0E // g vector
++#define ACC_GNZH 0x0F // g vector
++#define ACC_GNSVL 0x10 // g vector
++#define ACC_GNSVH 0x11 // g vector
++#define ACC_PITCHL 0x12 // pitch
++#define ACC_PITCHH 0x13 // pitch
++#define ACC_ROLLL 0x14 // roll
++#define ACC_ROLLH 0x15 // roll
++#define ACC_TEMPL 0x19 // temperature
++#define ACC_TEMPH 0x1A // temperature
++
++ // read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++#if defined ACCELEROMETER
++ // read byte from I2C acceleromter
++static int ReadByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C accelerometer
++static int WriteByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++#endif // ACCELEROMETER
++
++/*
++ * SPI functions
++ */
++
++ // TSC2046 touch screen controller command register bit definitons
++#define SPI_START 0x80 // command start
++#define SPI_AT0 0x00 // read temperature - not supported
++#define SPI_AY 0x10 // read Y
++#define SPI_ABAT 0x20 // read battery - not supported
++#define SPI_AZ1 0x30 // read Z1
++#define SPI_AZ2 0x40 // read Z2
++#define SPI_AX 0x50 // read X
++#define SPI_AAUX 0x60 // read AUX - not supported
++#define SPI_AT1 0x70 // read temperature - not supported
++#define SPI_MODE_12 0x00 // 12-bit mode - Preferred
++#define SPI_MODE_8 0x08 // 8-bit mode
++#define SPI_MODE_DFR 0x00 // differential mode - Preferred
++#define SPI_MODE_SER 0x04 // single ended mode
++#define SPI_PD 0x00 // power down - PENIRQ enabled
++#define SPI_ADC 0x01 // ADC enabled
++#define SPI_REF 0x02 // Vref enabled - unused
++#define SPI_REF_ADC 0x03 // Vref & ADC enabled - unused
++
++ // spi access
++static int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
++{
++ struct spi_transfer t = {
++ .tx_buf = (const void *)buf,
++ .rx_buf = buf,
++ .len = len,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++
++ spi_message_add_tail(&t, &m);
++ if (spi_sync(spi, &m) != 0 || m.status != 0)
++ return -1;
++
++ return m.actual_length;
++}
++
++ // spi write register
++static ssize_t spi_lcd_write_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++ // spi read register
++static ssize_t spi_lcd_read_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ memset(priv->rbuf[slot], 0, BUF_MAX_SIZE);
++ buf[0] = priv->wbuf[slot][2];
++ buf[1] = priv->wbuf[slot][1];
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++
++// control file operations
++static int lcd_ctl_open (struct inode *, struct file *);
++static int lcd_ctl_release (struct inode *, struct file *);
++static int lcd_ctl_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
++
++struct file_operations lcd_ctl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = lcd_ctl_ioctl,
++ .open = lcd_ctl_open,
++ .release = lcd_ctl_release,
++};
++
++/*
++ * control device operations
++ */
++static int lcd_ctl_major;
++
++int lcd_ctl_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI LCD Control Driver");
++
++ if (retval) {
++ return -1;
++ }
++ lcd_ctl_major = MAJOR(dev_id);
++ return 0;
++}
++
++void lcd_ctl_clean (void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(lcd_ctl_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int lcd_ctl_probe (struct lcd_ctl *lcd_ctl, int slot)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ cdev = &lcd_ctl->cdev;
++ cdev_init (cdev, &lcd_ctl_fops);
++
++ dev_id = MKDEV (lcd_ctl_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++ bmi_class = bmi_get_bmi_class ();
++
++ lcd_ctl->class_dev = device_create (bmi_class, NULL, MKDEV(lcd_ctl_major, slot), lcd_ctl, "bmi_lcd_ctl_m%i", slot+1);
++
++ if (IS_ERR(lcd_ctl->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_lcd_ctl_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(lcd_ctl->class_dev));
++ lcd_ctl->class_dev = NULL;
++ }
++ lcd_ctl->slot = slot;
++
++ return ret;
++}
++
++void lcd_ctl_remove (struct lcd_ctl *lcd_ctl, int slot)
++{
++ struct class *bmi_class;
++
++ bmi_class = bmi_get_bmi_class ();
++ device_destroy (bmi_class, MKDEV(lcd_ctl_major, slot));
++
++ lcd_ctl->class_dev = 0;
++
++ cdev_del (&lcd_ctl->cdev);
++ return;
++}
++
++// open
++static int lcd_ctl_open (struct inode *inode, struct file *file)
++{
++ struct lcd_ctl *lcd_ctl;
++
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++
++
++ // Save ctl pointer for later.
++
++ file->private_data = lcd_ctl;
++ return 0;
++}
++
++// release
++static int lcd_ctl_release (struct inode *inode, struct file *file)
++{
++ struct lcd_ctl *lcd_ctl;
++
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++ return 0;
++}
++
++// ioctl
++int lcd_ctl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct lcd_ctl *lcd_ctl;
++ struct i2c_adapter *adap;
++ unsigned char iox_data[1];
++ int slot;
++ int bl = ((__user arg) & 0x70) >> 4;
++
++ // error if no lcd active.
++
++ if(cmd != BMI_LCD_GETSTAT) {
++ // i2c adapter
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++ slot = lcd_ctl->slot;
++ if (slot < 0) {
++ return -ENODEV;
++ }
++ adap = &pbmi_lcd.bdev[slot]->adap;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ case BMI_LCD_RLEDOFF:
++ bmi_set_module_gpio_data(slot, 3, 1);// Red LED=OFF
++ break;
++ case BMI_LCD_RLEDON:
++ bmi_set_module_gpio_data(slot, 3, 0);// Red LED=ON
++ break;
++ case BMI_LCD_GLEDOFF:
++ bmi_set_module_gpio_data(slot, 2, 1);// Green LED=OFF
++ break;
++ case BMI_LCD_GLEDON:
++ bmi_set_module_gpio_data(slot, 2, 0);// Green LED=ON
++ break;
++ case BMI_LCD_VSYNC_DIS: // enable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_VSYNC_EN: // disable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_EN: // enable LCD component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_DIS: // disable LCD component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_EN: // enable Serializer component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_DIS: // disable Serializer component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SETRST: // overall module reset
++ bmi_set_module_gpio_data (slot, 1, 0); // RST=0
++ break;
++ case BMI_LCD_CLRRST: // overall module enable
++ bmi_set_module_gpio_data (slot, 1, 1); // RST=1
++ break;
++ case BMI_LCD_SET_BL: // set backlight brightness
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xFC) | bl;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_GETSTAT:
++ {
++ int *slot = ((int __user *) arg);
++ int read_data;
++
++ *slot &= 0xF;
++
++ // error if slot invalid
++ if((*slot < CPLD_M1) || (*slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[*slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[*slot]->adap;
++
++ if(ReadByte_IOX(adap, IOX_INPUT_REG, iox_data))
++ return -ENODEV;
++
++ read_data = *iox_data | (bmi_read_gpio_data_reg(*slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++ case BMI_LCD_ACTIVATE: //pjg fix/test
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ return -ENODEV;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ return -ENODEV;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ return -ENODEV;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ return -ENODEV;
++ }
++ break;
++ }
++ // activate
++ if((!pbmi_lcd.activated[slot]) && (pbmi_lcd.bdev[slot] != 0)) {
++ bmi_lcd_probe(pbmi_lcd.bdev[slot]);
++ }
++ break;
++ case BMI_LCD_DEACTIVATE:
++ if(pbmi_lcd.activated[slot]) {
++ disable_irq_nosync(pbmi_lcd.interrupt[slot]);
++ pbmi_lcd.activated[slot] = 0;
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8);
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ bmi_slot_power_off(slot);
++ }
++ break;
++ case BMI_LCD_SUSPEND:
++ printk(KERN_ERR "BMI_LCD_SUSPEND NOT IMPLEMENTED\n"); //pjg
++ break;
++ case BMI_LCD_RESUME:
++ printk(KERN_ERR "BMI_LCD_RESUME NOT IMPLEMENTED\n"); //pjg
++ break;
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++
++/*
++ * BMI functions
++ */
++
++static irqreturn_t module_irq_handler(int irq, void *dummy);
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp);
++
++ // probe
++int bmi_lcd_probe(struct bmi_device *bdev)
++{
++#if defined ACCELEROMETER
++ unsigned char acc_data[1];
++#endif // ACCELEROMETER
++ unsigned char iox_data[1];
++ int slot = bdev->info->slot;
++ struct i2c_adapter *adap;
++ struct bmi_lcd *lcd;
++ char buf[4];
++ /*int first_time = 1;*/
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d\n", slot);
++
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ /*bmi_slot_power_off(2);*/
++ pbmi_lcd.bdev[0] = bdev;
++ /*bdev = pbmi_lcd.bdev[2];
++ slot = 2;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ /*bmi_slot_power_off(3);*/
++ pbmi_lcd.bdev[1] = bdev;
++ /*bdev = pbmi_lcd.bdev[3];
++ slot = 3;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ /*bmi_slot_power_off(0);*/
++ pbmi_lcd.bdev[2] = bdev;
++ /*bdev = pbmi_lcd.bdev[0];
++ slot = 0;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ /*bmi_slot_power_off(1);*/
++ pbmi_lcd.bdev[3] = bdev;
++ /*bdev = pbmi_lcd.bdev[1];
++ slot = 1;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ }
++
++ adap = &bdev->adap;
++ bmi_slot_power_on(slot);
++
++ mdelay(500);
++
++ if (lcd_ctl_probe(&pbmi_lcd.ctl_dev[slot], slot)) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d control device node error...\n", slot);
++ return -ENODEV;
++ }
++
++ // configure IOX
++ // [7:6]=interrupts, [5]=SER_PD*, [4]=LCD_RST*, [3]=VSYNC_OE*, [2]=ACC_RST*, [1:0]=backlight
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFF)) // normal - no accelerometer interrupts
++ return -ENODEV;
++
++ // normal operation - no accelerometer interrupts
++ if(WriteByte_IOX(adap, IOX_CONTROL, 0x00)) // IOX[7:0]=OUT
++ return -ENODEV;
++
++ // clear interrupts
++ if(ReadByte_IOX(adap, IOX_INPUT_REG, iox_data))
++ return -ENODEV;
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d iox data = %x\n", slot, *iox_data);
++
++#if defined ACCELEROMETER
++ // accelerometer
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x\n", slot, bdev->epraw.revision_msb);
++
++ // check for PCB revision >= 1.2
++ if(bdev->epraw.revision_msb >= 0x12) {
++
++ // normal IOX operation - accelerometer interrupts
++ if(WriteByte_IOX(adap, IOX_CONTROL, 0xC0)) // IOX[7:6]=IN, IOX[5:0]=OUT
++ return -ENODEV;
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFB)) // reset OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFF)) // enable OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return -ENODEV;
++
++ // read device to verify existance
++ if(ReadByte_ACC(adap, ACC_CPURDY, acc_data))
++ return -ENODEV;
++
++ // set TMD = 0x300 (~250 ms)
++ *acc_data = 0x5;
++ if(WriteByte_ACC(adap, ACC_TMDH, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_TMDL, *acc_data))
++ return -ENODEV;
++
++ // set INTOTM
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_INTOTM, *acc_data))
++ return -ENODEV;
++
++ // set GxAVE
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_GAAVE, *acc_data))
++ return -ENODEV;
++
++ // set GDTCT[01]
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT0L, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT0H, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT1L, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT1H, *acc_data))
++ return -ENODEV;
++
++ // set MODE0
++ *acc_data = ACC_MODE0_PDOFF | ACC_MODE0_TMPOFF | ACC_MODE0_AGCON | ACC_MODE0_MAUTO | ACC_MODE0_GDET10;
++ if(WriteByte_ACC(adap, ACC_MODE0, *acc_data))
++ return -ENODEV;
++
++ // set CFG
++ *acc_data = ACC_CFG_REGMD | ACC_CFG_INTLVL;
++ if(WriteByte_ACC(adap, ACC_CFG, *acc_data))
++ return -ENODEV;
++
++ // set INTMSK
++ *acc_data = 0xFE;
++ if(WriteByte_ACC(adap, ACC_INTMSK, *acc_data))
++ return -ENODEV;
++
++ // set CTRL0
++ *acc_data = ACC_CTRL0_CGAUTO;
++ if(WriteByte_ACC(adap, ACC_CTRL0, *acc_data))
++ return -ENODEV;
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return -ENODEV;
++
++ acc_probe(&pbmi_lcd.acc[slot], slot);
++
++ } else {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x (accelerometer not supported)\n", slot, bdev->epraw.revision_msb);
++ }
++#endif // ACCELEROMETER
++
++ // reset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ bmi_lcd_inactive(0);
++ } else {
++ bmi_lcd_inactive(1);
++ }
++
++ // configure GPIO
++ // turn LED's on
++ bmi_set_module_gpio_data(slot, 3, 0); // Red LED=ON
++ bmi_set_module_gpio_data(slot, 2, 0); // Green LED=ON
++
++ // assert reset
++ bmi_set_module_gpio_data(slot, 1, 0); // RST=0
++
++ // set GPIO direction
++ bmi_set_module_gpio_dir(slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 0, BMI_GPIO_IN); // real-time pen int state
++
++ mdelay(200);
++
++ // turn LED's off
++ bmi_set_module_gpio_data(slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data(slot, 2, 1); // Green LED=OFF
++
++ // deassert reset (module)
++ bmi_set_module_gpio_data(slot, 1, 1); // RST=1
++
++ mdelay(500);
++
++ // unreset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_active(0, 0x0, LCD_MODE_I80);
++ } else {
++ mdelay(2);
++ bmi_lcd_active(1, 0x0, LCD_MODE_I80);
++ }
++
++
++ // set up bdev/pbmi_lcd pointers
++ bmi_device_set_drvdata(bdev, &pbmi_lcd);
++ pbmi_lcd.bdev[slot] = bdev;
++
++ // spi set-up
++ if (bmi_device_spi_setup(bdev, 2000000, SPI_MODE_2, 32)) {
++ printk(KERN_ERR "bmi_lcd.c: Unable to setup spi%d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++ bmi_slot_spi_enable(slot);
++ pbmi_lcd.spi[slot] = bmi_device_get_spi(bdev);
++
++
++ // check spi access and enable touch screen
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ if(spi_lcd_write_reg(&pbmi_lcd, buf, 1, slot) != 1) {
++ printk(KERN_WARNING "bmi_lcd.c: Unable set-up spi for bmi_lcd %d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_spi_disable(slot);
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++
++ // complete pbmi_lcd set-up
++ pbmi_lcd.lcd_cnt++;
++ pbmi_lcd.active = 1;
++ pbmi_lcd.activated[slot] = 1;
++
++
++ mdelay(100);
++
++ lcd = pbmi_lcd.blcd[slot];
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_config(lcd, 0);
++ mdelay(2);
++ } else {
++ mdelay(2);
++ bmi_lcd_config(lcd, 1);
++ mdelay(2);
++ }
++
++
++ // request input event interrupt handler
++ pbmi_lcd.interrupt[0] = M1_IRQ;
++ pbmi_lcd.interrupt[1] = M2_IRQ;
++ pbmi_lcd.interrupt[2] = M3_IRQ;
++ pbmi_lcd.interrupt[3] = M4_IRQ;
++ snprintf(pbmi_lcd.int_name, sizeof(pbmi_lcd.int_name), "bmi_lcd%d", slot);
++ if (request_irq(pbmi_lcd.interrupt[slot], &module_irq_handler, 0, pbmi_lcd.int_name, &pbmi_lcd)) {
++ printk( KERN_ERR "bmi_lcd.c: Can't allocate irq %d or find lcd in slot %d\n", pbmi_lcd.interrupt[slot], slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_power_off(slot);
++ return -EBUSY;
++ }
++
++ // check GPIO status
++ printk(KERN_INFO "bmi_lcd.c: slot %d gpio = %x\n", slot, bmi_read_gpio_data_reg(slot));
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return 0;
++}
++
++extern struct delayed_work bmilcd_work0;
++extern struct delayed_work bmilcd_work1;
++extern struct delayed_work bmilcd_work2;
++extern struct delayed_work bmilcd_work3;
++
++ // remove
++void bmi_lcd_remove(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++
++ if(pbmi_lcd.activated[slot] == 0)
++ return;
++
++ switch(slot) {
++ case 0:
++ cancel_delayed_work(&bmilcd_work0);
++ break;
++ case 1:
++ cancel_delayed_work(&bmilcd_work1);
++ break;
++ case 2:
++ cancel_delayed_work(&bmilcd_work2);
++ break;
++ case 3:
++ cancel_delayed_work(&bmilcd_work3);
++ break;
++ }
++ lcd_ctl_remove(&pbmi_lcd.ctl_dev[slot], slot);
++
++ free_irq(pbmi_lcd.interrupt[slot], &pbmi_lcd);
++
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN);
++
++ // bmi/spi clean-up
++ bmi_device_spi_cleanup(bdev);
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_slot_spi_disable(slot);
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, NULL);
++
++ // deactivate
++ pbmi_lcd.activated[slot] = 0;
++ pbmi_lcd.bdev[slot] = 0;
++ pbmi_lcd.lcd_cnt--;
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[2] == 0)) {
++ bmi_lcd_inactive(0); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[1] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ bmi_lcd_inactive(1); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[1] == 0) &&
++ (pbmi_lcd.activated[2] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ pbmi_lcd.active = -1;
++ }
++
++ // enable LCD on opposite side
++ switch(slot) {
++ case 0:
++ if(pbmi_lcd.bdev[2] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[2]);
++ break;
++ case 1:
++ if(pbmi_lcd.bdev[3] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[3]);
++ break;
++ case 2:
++ if(pbmi_lcd.bdev[0] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[0]);
++ break;
++ case 3:
++ if(pbmi_lcd.bdev[1] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[1]);
++ break;
++ }
++
++#ifdef ACCELEROMETER
++ acc_remove(&pbmi_lcd.acc[slot], slot);
++#endif
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return;
++}
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++static void update_pen_state(void *arg, int slot, int x, int y, int pressure)
++{
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++ int sync = 0;
++
++ if (pressure)
++ {
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, pressure);
++ }
++ else
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, pressure);
++ }
++
++ if (!pbmi_lcd->pen_down[slot])
++ {
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 1);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 1);
++ }
++
++ }
++ sync = 1;
++ }
++ else if (pbmi_lcd->pen_down[slot])
++ {
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, 0);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, 0);
++ }
++ sync = 1;
++ }
++
++ if (sync)
++ {
++ if((slot == 0) || (slot == 2))
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M13]);
++ }
++ else
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M24]);
++ }
++ }
++ pbmi_lcd->pen_down[slot] = pressure ? 1 : 0;
++
++}
++
++
++void bmilcd_input_work(void *arg, int slot);
++
++void bmilcd_input_work0(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 0);
++}
++
++void bmilcd_input_work1(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 1);
++}
++
++void bmilcd_input_work2(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 2);
++}
++
++void bmilcd_input_work3(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 3);
++}
++
++DECLARE_DELAYED_WORK(bmilcd_work0, bmilcd_input_work0);
++DECLARE_DELAYED_WORK(bmilcd_work1, bmilcd_input_work1);
++DECLARE_DELAYED_WORK(bmilcd_work2, bmilcd_input_work2);
++DECLARE_DELAYED_WORK(bmilcd_work3, bmilcd_input_work3);
++
++// work handler
++void bmilcd_input_work(void *arg, int slot) {
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++#if defined ACCELEROMETER
++ struct i2c_adapter *adap = &pbmi_lcd->bdev[slot]->adap;
++ unsigned char acc_data[1];
++ static int pitch = 0;
++ static int roll = 0;
++ static int gx = 0;
++ static int gy = 0;
++
++#endif // ACCELEROMETER
++ unsigned char buf[4];
++ int x = 0;
++ int y = 0;
++ int z1 = 0;
++ int z2 = 0;
++ int pressure = 0;
++ int debounce;
++ int penirq;
++
++#if defined DEBUG
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d)\n", slot);
++#endif
++
++ if(pbmi_lcd->bdev[slot] == 0) {
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work called with no bdev active (slot %d)\n", slot);
++ return;
++ }
++
++#if defined ACCELEROMETER
++ if(pbmi_lcd->bdev[slot]->epraw.revision_msb >= 0x12) {
++
++ // orientation
++ // read ROLL
++ if(ReadByte_ACC(adap, ACC_ROLLH, acc_data))
++ goto touch;
++ roll = (0x0000 | *acc_data) << 8;
++
++ if(ReadByte_ACC(adap, ACC_ROLLL, acc_data))
++ goto touch;
++ roll = roll | *acc_data;
++ // read PITCH
++ if(ReadByte_ACC(adap, ACC_PITCHH, acc_data))
++ goto touch;
++ pitch = (0x0000 | *acc_data) << 8;
++
++ if(ReadByte_ACC(adap, ACC_PITCHL, acc_data))
++ goto touch;
++ pitch = pitch | *acc_data;
++
++
++
++
++ if(ReadByte_ACC(adap, ACC_GAZH, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[0] = *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAZL, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[1] = *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAYH, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[2] = *acc_data;
++ gy = *acc_data << 8;
++
++ if(ReadByte_ACC(adap, ACC_GAYL, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[3] = *acc_data;
++ gy = gy | *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAXH, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[4] = *acc_data;
++ gx = *acc_data << 8;
++
++ if(ReadByte_ACC(adap, ACC_GAXL, acc_data))
++ goto touch;
++ pbmi_lcd->acc[slot].sample[5] = *acc_data;
++ gx = gx | *acc_data;
++
++ //wake up any read's
++ pbmi_lcd->acc[slot].flag = 1;
++ wake_up_interruptible(&pbmi_lcd->acc[slot].wq);
++
++ // read STATUS
++ if(ReadByte_ACC(adap, ACC_STATUS, acc_data))
++ goto touch;
++
++ if((*acc_data & 0x1) == 0) {
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ goto touch;
++
++ // read INTRQ
++ if(ReadByte_ACC(adap, ACC_INTRQ, acc_data))
++ goto touch;
++ }
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ goto touch;
++
++ // report orientation
++ // printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d) pitch=0x%x, roll=0x%x, ABS_MISC=0x%x\n",
++ // slot, pitch, roll, pitch << 16 | roll); //pjg - debug
++
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_MISC, (pitch << 16) | roll);
++ input_sync(pbmi_lcd->input_dev[slot]);
++ }
++#endif // ACCELEROMETER
++
++
++ // read touch screen - X, Y, TOUCH, PRESSURE
++ touch:
++ penirq = bmi_slot_status_irq_state(slot);
++ /*printk(KERN_INFO "bmi_lcd.c: IRQ Status %d (slot %d) %d\n", penirq, slot,msecs_to_jiffies(10));*/
++
++ if (pbmi_lcd->activated[slot] && penirq)
++ {
++
++ for(debounce = 0; debounce < DEBOUNCE; debounce++)
++ {
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AY | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ y = (((buf[0] << 5) | buf[1] >> 3)) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AX | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ x = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ1 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z1 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ2 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z2 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++ mdelay(1);
++ }
++
++ if(x && y && z1 && z2)
++ pressure = (X_PLATE * x / 4096) * ((z2 / z1) - 1);
++
++ x = 4096 - x;
++ y = 4096 - y;
++
++ if (pressure < 70)
++ {
++ if (pbmi_lcd->scount)
++ update_pen_state(arg, slot, x, y, pressure);
++ else
++ {
++ pbmi_lcd->scount[slot]++;
++ /*update_pen_state(arg, slot, 0, 0, pressure);*/
++ }
++ }
++
++ switch(slot)
++ {
++ case BMI_TS_M1:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ break;
++ case BMI_TS_M2:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ break;
++ case BMI_TS_M3:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ break;
++ case BMI_TS_M4:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ break;
++ }
++ /* printk(KERN_INFO "bmi_lcd.c: work scheduled on (slot %d)\n", slot); */
++ /*buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);*/
++ }
++
++ else
++ {
++ /*printk(KERN_INFO "bmi_lcd.c: Pen up on (slot %d)\n", slot);*/
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);
++ update_pen_state(arg,slot, 0, 0, 0);
++ enable_irq(pbmi_lcd->interrupt[slot]);
++ }
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ disable_irq_nosync(irq);
++ /*printk(KERN_INFO "bmi_lcd.c: Interupt on (slot %d)\n", irq);*/
++ switch(irq)
++ {
++ case M1_IRQ:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M1] = 0;
++ break;
++ case M2_IRQ:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M2] = 0;
++ break;
++ case M3_IRQ:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M3] = 0;
++ break;
++ case M4_IRQ:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M4] = 0;
++ break;
++ }
++ return IRQ_HANDLED;
++}
++
++
++ // BMI LCD fops
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.config)) {
++ lcd->lcd_ops.config(disp);
++ }
++}
++
++void bmi_lcd_reset(struct bmi_lcd *lcd, int slot)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.reset)) {
++ lcd->lcd_ops.reset(slot);
++ }
++}
++
++int register_bmi_lcd(struct bmi_lcd *lcd, int slot) //pjg - placeholder for multiple LCD types
++{
++ if(!lcd) {
++ return -1;
++ }
++ if((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if(pbmi_lcd.blcd[slot]) {
++ return -1;
++ }
++ else {
++ pbmi_lcd.blcd[slot] = lcd;
++ }
++
++ if(lcd->lcd_ops.activate) {
++ lcd->lcd_ops.activate(lcd, slot);
++ }
++
++ return 0;
++}
++
++int unregister_bmi_lcd(struct bmi_lcd *lcd, int slot) //pjg - placeholder for multiple LCD types
++{
++ if (!lcd) {
++ return -1;
++ }
++ if ((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if (pbmi_lcd.blcd[slot] != lcd) {
++ return -1;
++ }
++ else {
++ pbmi_lcd.blcd [slot] = 0;
++ lcd->lcd_ops.deactivate(lcd, slot);
++ }
++ return 0;
++}
++
++/*
++ * Module functions
++ */
++
++char const input_name0[MAX_STRG] = "bmi_lcd_ts0";
++char const input_name1[MAX_STRG] = "bmi_lcd_ts1";
++char const input_name2[MAX_STRG] = "bmi_lcd_ts2";
++char const input_name3[MAX_STRG] = "bmi_lcd_ts3";
++char const input_name4[MAX_STRG] = "bmi_lcd_ts4";
++char const input_name5[MAX_STRG] = "bmi_lcd_ts5";
++char const input_name6[MAX_STRG] = "bmi_lcd_ts6";
++
++static __init int bmi_lcd_init(void)
++{
++ int ts;
++ int rc = 0;
++
++ // No lcd is active.
++ pbmi_lcd.active = -1;
++ pbmi_lcd.activated[0] = 0;
++ pbmi_lcd.activated[1] = 0;
++ pbmi_lcd.activated[2] = 0;
++ pbmi_lcd.activated[3] = 0;
++
++ // set up control character device - bmi_lcd_control
++ rc = lcd_ctl_init();
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't allocate bmi_lcd_control device\n");
++ return rc;
++ }
++
++ // Allocate and Register input device. - bmi_lcd_ts[BMI_TS_M1:BMI_TS_M1234]
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++) {
++ pbmi_lcd.input_dev[ts] = input_allocate_device();
++ if(!pbmi_lcd.input_dev[ts]) {
++ printk(KERN_ERR "bmi_lcd_init: Can't allocate input_dev[ts]\n");
++ return -ENOMEM;
++ }
++
++ // set up input device
++ switch(ts) {
++ case BMI_TS_M1:
++ pbmi_lcd.input_dev[BMI_TS_M1]->name = input_name0;
++ pbmi_lcd.input_dev[BMI_TS_M1]->phys = input_name0;
++ break;
++ case BMI_TS_M2:
++ pbmi_lcd.input_dev[BMI_TS_M2]->name = input_name1;
++ pbmi_lcd.input_dev[BMI_TS_M2]->phys = input_name1;
++ break;
++ case BMI_TS_M3:
++ pbmi_lcd.input_dev[BMI_TS_M3]->name = input_name2;
++ pbmi_lcd.input_dev[BMI_TS_M3]->phys = input_name2;
++ break;
++ case BMI_TS_M4:
++ pbmi_lcd.input_dev[BMI_TS_M4]->name = input_name3;
++ pbmi_lcd.input_dev[BMI_TS_M4]->phys = input_name3;
++ break;
++ case BMI_TS_M13:
++ pbmi_lcd.input_dev[BMI_TS_M13]->name = input_name4;
++ pbmi_lcd.input_dev[BMI_TS_M13]->phys = input_name4;
++ break;
++ case BMI_TS_M24:
++ pbmi_lcd.input_dev[BMI_TS_M24]->name = input_name5;
++ pbmi_lcd.input_dev[BMI_TS_M24]->phys = input_name5;
++ break;
++ case BMI_TS_M1234:
++ pbmi_lcd.input_dev[BMI_TS_M1234]->name = input_name6;
++ pbmi_lcd.input_dev[BMI_TS_M1234]->phys = input_name6;
++ break;
++ }
++ pbmi_lcd.input_dev[ts]->id.bustype = BUS_BMI;
++ //pbmi_lcd.input_dev[ts]->private = &pbmi_lcd;
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
++ pbmi_lcd.input_dev[ts]->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_X)] |= BIT_MASK(ABS_X);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_Y)] |= BIT_MASK(ABS_Y);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_PRESSURE)] |= BIT_MASK(ABS_PRESSURE);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_X, BMI_LCD_MIN_XC, BMI_LCD_MAX_XC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_Y, BMI_LCD_MIN_YC, BMI_LCD_MAX_YC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_PRESSURE, 0, 1024, 0, 0);
++
++ // register input device
++ if(input_register_device(pbmi_lcd.input_dev[ts])) {
++ int tts;
++ printk(KERN_ERR "bmi_lcd_init() - input_register_device failed.\n");
++
++ for(tts = BMI_TS_M1; tts < ts; tts++)
++ input_unregister_device(pbmi_lcd.input_dev[tts]);
++
++ lcd_ctl_clean();
++
++ return -ENODEV;
++ }
++ }
++
++ pbmi_lcd.lcd_cnt = 0;
++
++ // hardware specfic set-up
++ s320x240_bmi_lcd.interface = s320x240_lcd_interface,
++ s320x240_bmi_lcd_ops.config = (void(*)) &s320x240_config;
++ s320x240_bmi_lcd_ops.reset = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.suspend = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.resume = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_on = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_off = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.activate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.deactivate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd.lcd_ops = s320x240_bmi_lcd_ops;
++ pbmi_lcd.blcd[0] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[1] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[2] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[3] = &s320x240_bmi_lcd;
++
++ sema_init(&pbmi_lcd.sem[0], 1);
++ sema_init(&pbmi_lcd.sem[1], 1);
++ sema_init(&pbmi_lcd.sem[2], 1);
++ sema_init(&pbmi_lcd.sem[3], 1);
++
++
++#ifdef ACCELEROMETER
++ acc_init();
++#endif
++ /*s320x240_config(0);
++ s320x240_config(1);*/
++
++ // register with BMI
++ rc = bmi_register_driver(&bmi_lcd_driver);
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't register bmi_lcd_driver\n");
++
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ lcd_ctl_clean();
++
++ return rc;
++ }
++
++ printk("bmi_lcd.c: BMI_LCD Driver v%s \n", BMILCD_VERSION);
++
++ return 0;
++}
++
++static void __exit bmi_lcd_clean(void)
++{
++ int ts;
++
++ // delete timers
++ del_timer(&pbmi_lcd.timer[0]);
++ del_timer(&pbmi_lcd.timer[1]);
++ del_timer(&pbmi_lcd.timer[2]);
++ del_timer(&pbmi_lcd.timer[3]);
++
++ // remove input devices
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ // remove control device
++ lcd_ctl_clean();
++
++ // remove bmi driver
++ bmi_unregister_driver(&bmi_lcd_driver);
++
++#ifdef ACCELEROMETER
++ acc_clean();
++#endif
++ return;
++}
++
++module_init(bmi_lcd_init);
++module_exit(bmi_lcd_clean);
++
++// Exported symbols
++EXPORT_SYMBOL(register_bmi_lcd);
++EXPORT_SYMBOL(unregister_bmi_lcd);
++
++
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BMI lcd device driver");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_control");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_ts");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_acc");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/bmi_lcd_inf.c
+@@ -0,0 +1,1775 @@
++/*
++ * bmi_lcd.c
++ *
++ * BMI LCD device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/input.h>
++#include <linux/kernel.h>
++#include <linux/major.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <asm/uaccess.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/miscdevice.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <mach/mxc_i2c.h>
++#include <mach/mx31bug_cpld.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/bmi/bmi_lcd.h>
++#include <mach/ipu.h>
++
++#undef ACCELEROMETER
++#define ACCELEROMETER
++
++#ifdef ACCELEROMETER
++#include "acc.h"
++#endif //ACCELEROMETER
++
++#define DEBUG
++#undef DEBUG
++
++#define BMILCD_VERSION "1.2" // driver version
++#define BUF_MAX_SIZE 0x20 // spi buffer size
++#define WORK_DELAY (1) // interrupt work handler delay
++#define DEBOUNCE 10 // touch screen debounce
++#define X_PLATE 400 // touch screen X plate resistance //pjg - This is not the correct value
++#define BMI_SLOT_NUM (4) // number of BMI slots
++#define MAX_STRG (40) // Max string buffer size
++
++#define VSYNC_DISABLE 0x0
++#define VSYNC_ENABLE 0x1
++
++ // lcd
++struct lcd_interface {
++ char lcd_type[MAX_STRG]; // text description of LCD type
++ u8 suspended; // power management state
++ u8 rotation; // screen rotation
++ u8 disp; // display number (DISP0 or DISP1)
++ u8 addr_mode; // display addressing mode
++ u8 vsync_mode; // VSYNC signal enable (VSYNC_ENABLE | VSYNC_DISABLE)
++ u8 bus_if_type; // bus type (XY | FullWoBE | FullWithBE)
++ ipu_adc_sig_cfg_t adc_sig; // IPU ADC set-up parameters
++ ipu_di_signal_cfg_t di_sig; // IPU DI set-up parameters
++};
++
++static struct lcd_interface s320x240_lcd_interface = {
++ .lcd_type = "MXCFB_SHARP_320X240",
++ .suspended = 0,
++ .rotation = IPU_ROTATE_NONE,
++ .disp = DISP0,
++ .vsync_mode = VSYNC_DISABLE,
++ .bus_if_type = XY,
++ .adc_sig = { 0, 0, 0, 0, 0, 0, 0, 0, IPU_ADC_BURST_WCS, IPU_ADC_IFC_MODE_SYS80_TYPE2,
++ 16, 0, 0, IPU_ADC_SER_NO_RW },
++ .di_sig = { 0,0,0,0,0,0,0,0 }, //pjg - reserved for multiple LCD driver
++};
++
++
++struct bmi_lcd;
++
++struct bmi_lcd_ops {
++ void *(*config) (int disp); // LCD configuration/initialization
++ void *(*reset) (int slot); // LCD reset
++ int *(*suspend) (struct bmi_lcd *blcd); // power management
++ int *(*resume) (struct bmi_lcd *blcd); // power management
++ int *(*disp_on) (int disp); // display on
++ int *(*disp_off) (int disp); // display off
++ int (*activate) (struct bmi_lcd *lcd, int slot); // enable LCD backlight, touchscreen, accelerometer, ...
++ int (*deactivate) (struct bmi_lcd *lcd, int slot); // disable LCD backlight, touchscreen, accelerometer, ...
++};
++
++
++struct bmi_lcd {
++ struct lcd_interface interface; // pointer to this struct is returned by config()
++ struct bmi_lcd_ops lcd_ops; // function pointers
++};
++
++
++int register_bmi_lcd(struct bmi_lcd *blcd, int slot);
++int unregister_bmi_lcd(struct bmi_lcd *blcd, int slot);
++
++ // private device structure
++struct pbmi_lcd
++{
++ int open_flag; // force single open
++ unsigned int lcd_cnt; // number of LCD's present
++ unsigned int active; // indication of LCD presence
++ unsigned int activated[BMI_SLOT_NUM]; // indication of LCD presence
++
++ struct bmi_lcd *blcd[BMI_SLOT_NUM]; // BMI LCD structure - placeholder for multiple display types
++ struct bmi_device *bdev[BMI_SLOT_NUM]; // BMI device per slot
++ unsigned int interrupt[BMI_SLOT_NUM]; // input device interrupt handlers
++ char int_name[MAX_STRG]; // interrupt name
++
++ struct input_dev *input_dev[BMI_TS_NUM]; // input device (touch screen and accelerometer)
++ struct timer_list timer[BMI_SLOT_NUM]; // touch timer
++
++ int pen_down[BMI_SLOT_NUM];
++ int scount[BMI_SLOT_NUM];
++
++ struct spi_device *spi[BMI_SLOT_NUM]; // touch screen device interface
++ struct semaphore sem[BMI_SLOT_NUM]; // spi semaphore
++ char rbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi read buffer
++ char wbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi write buffer
++
++#ifdef ACCELEROMETER
++ struct acc_dev acc[BMI_SLOT_NUM];
++#endif
++};
++
++static struct pbmi_lcd pbmi_lcd; // LCD device sructure
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_lcd_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_LCD_SHARP_320X240,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_lcd_tbl);
++
++/*printk(KERN_INFO "MDT: 0x%x\n", __mod_bmi_device_table);*/
++
++int bmi_lcd_probe(struct bmi_device *bdev);
++void bmi_lcd_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_lcd_driver =
++{
++ .name = "bmi_lcd",
++ .id_table = bmi_lcd_tbl,
++ .probe = bmi_lcd_probe,
++ .remove = bmi_lcd_remove,
++};
++
++//Accelerometer driver structure
++
++
++/*
++ * I2C set up
++ */
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define BMI_ACC_I2C_ADDRESS 0x17 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0 // IOX input data register
++#define IOX_OUTPUT_REG 0x1 // IOX output data register
++#define IOX_POLARITY_REG 0x2 // IOX polarity data register
++#define IOX_CONTROL 0x3 // IOX direction control register
++#define IOX_B1 (0) // bit 0 - backlight control
++#define IOX_A1_A2 (1) // bit 1 - backlight control
++#define IOX_ACC_RST_N (2) // bit 2 - acceleromter reset
++#define IOX_VSYNC_EN_N (3) // bit 3 - VSYNC output buffer enable
++#define IOX_LCD_RST_N (4) // bit 4 - LCD reset
++#define IOX_SERDES_PD_N (5) // bit 5 - SERDES power down
++#define IOX_X_INT (6) // bit 6 - accelerometer interrupt
++#define IOX_Y_INT (7) // bit 7 - accelerometer interrupt
++
++ // I2C ACC register addresses - OKI
++#define ACC_PAGESEL 0x1E // device ready status
++ // page 0
++#define ACC_DVRST 0x01 // device reset
++ #define ACC_DVRST_RST 0x3C // device reset
++ #define ACC_DVRST_EN 0xC3 // device enable
++#define ACC_PDWN 0x02 // osc power down
++ #define ACC_PWDN_RST 0x01 // device reset
++ #define ACC_PWDN_EN 0x00 // device enable
++#define ACC_CTRL0 0x03 // control 0
++ #define ACC_CTRL0_CTSTR 0x40 // control 0 - temp sensor
++ #define ACC_CTRL0_CGSTRNC 0x08 // control 0 - 3-axis/no tilt
++ #define ACC_CTRL0_CGSTRC 0x04 // control 0 - 3-axis/tilt
++ #define ACC_CTRL0_CGAUTO 0x01 // control 0 - auto
++#define ACC_MODE0 0x05 // control 0
++ #define ACC_MODE0_PDOFF 0x80 // mode 0 - disable auto power down
++ #define ACC_MODE0_RVOFF 0x40 // mode 0 - disable temp compensation
++ #define ACC_MODE0_TMPOFF 0x20 // mode 0 - disable temp measurement
++ #define ACC_MODE0_AGCON 0x10 // mode 0 - enable auto mode pitch and roll
++ #define ACC_MODE0_MAUTO 0x04 // mode 0 - enable auto termination
++ #define ACC_MODE0_GDET00 0x00 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET01 0x01 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET10 0x02 // mode 0 - g detection threshold - see ML8953 data sheet
++#define ACC_MODE1 0x06 // mode 1
++ #define ACC_MODE1_MOFF 0x20 // mode 1 - disable 3-axis continuous mode
++ #define ACC_MODE1_ZAXIS 0x03 // mode 1 - Z axis
++ #define ACC_MODE1_YAXIS 0x02 // mode 1 - Y axis
++ #define ACC_MODE1_XAXIS 0x01 // mode 1 - X axis
++ #define ACC_MODE1_RAXIS 0x00 // mode 1 - Reference axis
++#define ACC_INTRQ 0x07 // interrupt request (1 = request)
++#define ACC_INTMSK 0x08 // interrupt mask (1 = masked)
++ #define ACC_INT_TREQ 0x20 // interrupt - temperature
++ #define ACC_INT_GREQ 0x08 // interrupt - acceleration/no tilt
++ #define ACC_INT_GCREQ 0x04 // interrupt - acceleration/tilt
++ #define ACC_INT_GAREQ 0x01 // interrupt - automatic
++#define ACC_TMDL 0x09 // timer LSB = (1/6.2 MHz) x 2048 x TMD
++#define ACC_TMDH 0x0A // timer MSB
++#define ACC_CFG 0x0C // configuration
++ #define ACC_CFG_REGMD 0x80 // address auto-increment
++ #define ACC_CFG_SPI3M_3 0x40 // spi mode = 3-wire
++ #define ACC_CFG_SPI3M_4 0x00 // spi mode = 4-wire
++ #define ACC_CFG_SDOCFG_T 0x10 // sdo mode = totem-pole
++ #define ACC_CFG_SDOCFG_OC 0x00 // sdo mode = open-drain
++ #define ACC_CFG_INT1EN_G 0x08 // interrupt 1 mode = g only
++ #define ACC_CFG_INT1EN_ALL 0x00 // interrupt 1 mode = all
++ #define ACC_CFG_INTLVL 0x04 // interrupt level mode
++ #define ACC_CFG_INT1CFG_T 0x02 // interrupt 1 mode = totem-pole
++ #define ACC_CFG_INT1CFG_OC 0x00 // interrupt 1 mode = open-drain
++ #define ACC_CFG_INT0CFG_T 0x01 // interrupt 0 mode = totem-pole
++ #define ACC_CFG_INT0CFG_OC 0x00 // interrupt 0 mode = open-drain
++#define ACC_INTOTM 0x0D // interrupt output conditions
++#define ACC_GAAVE 0x0E // Data averaging - automatic mode
++#define ACC_GNAVE 0x0F // Data averaging - normal mode
++#define ACC_GDTCT0L 0x11 // threshold 0 LSB
++#define ACC_GDTCT0H 0x12 // threshold 0 MSB
++#define ACC_GDTCT1L 0x13 // threshold 1 LSB
++#define ACC_GDTCT1H 0x14 // threshold 1 MSB
++#define ACC_CPURDY 0x15 // device ready status (ready = 0x01)
++ // page 1
++#define ACC_STATUS 0x01 // measurment status
++ #define ACC_STATUS_ASTS 0x02 // acceleration measurement - automatic modes
++ #define ACC_STATUS_STS 0x01 // acceleration measurement - non-automatic modes
++#define ACC_GAXL 0x02 // g vector
++#define ACC_GAXH 0x03 // g vector
++#define ACC_GAYL 0x04 // g vector
++#define ACC_GAYH 0x05 // g vector
++#define ACC_GAZL 0x06 // g vector
++#define ACC_GAZH 0x07 // g vector
++#define ACC_GASVL 0x08 // g vector
++#define ACC_GASVH 0x09 // g vector
++#define ACC_GNXL 0x0A // g vector
++#define ACC_GNXH 0x0B // g vector
++#define ACC_GNYL 0x0C // g vector
++#define ACC_GNYH 0x0D // g vector
++#define ACC_GNZL 0x0E // g vector
++#define ACC_GNZH 0x0F // g vector
++#define ACC_GNSVL 0x10 // g vector
++#define ACC_GNSVH 0x11 // g vector
++#define ACC_PITCHL 0x12 // pitch
++#define ACC_PITCHH 0x13 // pitch
++#define ACC_ROLLL 0x14 // roll
++#define ACC_ROLLH 0x15 // roll
++#define ACC_TEMPL 0x19 // temperature
++#define ACC_TEMPH 0x1A // temperature
++
++ // read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ int retries = 0;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ while (retries < 5)
++ {
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ if (ret == 2)
++ break;
++ else
++ retries++;
++ }
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++#if defined ACCELEROMETER
++ // read byte from I2C acceleromter
++static int ReadByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ int retries = 0;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ while (retries < 5)
++ {
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ if (ret == 2)
++ break;
++ else
++ retries++;
++ mdelay(1);
++ }
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++static int ReadByteLock_ACC(struct pbmi_lcd *priv, unsigned char offset, unsigned char *data, int slot)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ int retries = 0;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ while (retries < 5)
++ {
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ if (ret == 2)
++ break;
++ else
++ retries++;
++ mdelay(1);
++ }
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C accelerometer
++static int WriteByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++#endif // ACCELEROMETER
++
++/*
++ * SPI functions
++ */
++
++ // TSC2046 touch screen controller command register bit definitons
++#define SPI_START 0x80 // command start
++#define SPI_AT0 0x00 // read temperature - not supported
++#define SPI_AY 0x10 // read Y
++#define SPI_ABAT 0x20 // read battery - not supported
++#define SPI_AZ1 0x30 // read Z1
++#define SPI_AZ2 0x40 // read Z2
++#define SPI_AX 0x50 // read X
++#define SPI_AAUX 0x60 // read AUX - not supported
++#define SPI_AT1 0x70 // read temperature - not supported
++#define SPI_MODE_12 0x00 // 12-bit mode - Preferred
++#define SPI_MODE_8 0x08 // 8-bit mode
++#define SPI_MODE_DFR 0x00 // differential mode - Preferred
++#define SPI_MODE_SER 0x04 // single ended mode
++#define SPI_PD 0x00 // power down - PENIRQ enabled
++#define SPI_ADC 0x01 // ADC enabled
++#define SPI_REF 0x02 // Vref enabled - unused
++#define SPI_REF_ADC 0x03 // Vref & ADC enabled - unused
++
++ // spi access
++static int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
++{
++ struct spi_transfer t = {
++ .tx_buf = (const void *)buf,
++ .rx_buf = buf,
++ .len = len,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++
++ spi_message_add_tail(&t, &m);
++ if (spi_sync(spi, &m) != 0 || m.status != 0)
++ return -1;
++
++ return m.actual_length;
++}
++
++ // spi write register
++static ssize_t spi_lcd_write_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++ // spi read register
++static ssize_t spi_lcd_read_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ memset(priv->rbuf[slot], 0, BUF_MAX_SIZE);
++ buf[0] = priv->wbuf[slot][2];
++ buf[1] = priv->wbuf[slot][1];
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++/*
++ * BMI functions
++ */
++
++static irqreturn_t module_irq_handler(int irq, void *dummy);
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp);
++
++ // probe
++int bmi_lcd_probe(struct bmi_device *bdev)
++{
++#if defined ACCELEROMETER
++ unsigned char acc_data[1];
++#endif // ACCELEROMETER
++ unsigned char iox_data[1];
++ int slot = bdev->info->slot;
++ struct i2c_adapter *adap;
++ struct bmi_lcd *lcd;
++ char buf[4];
++ /*int first_time = 1;*/
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d\n", slot);
++
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ /*bmi_slot_power_off(2);*/
++ pbmi_lcd.bdev[0] = bdev;
++ /*bdev = pbmi_lcd.bdev[2];
++ slot = 2;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ /*bmi_slot_power_off(3);*/
++ pbmi_lcd.bdev[1] = bdev;
++ /*bdev = pbmi_lcd.bdev[3];
++ slot = 3;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ /*bmi_slot_power_off(0);*/
++ pbmi_lcd.bdev[2] = bdev;
++ /*bdev = pbmi_lcd.bdev[0];
++ slot = 0;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ /*bmi_slot_power_off(1);*/
++ pbmi_lcd.bdev[3] = bdev;
++ /*bdev = pbmi_lcd.bdev[1];
++ slot = 1;
++ first_time = 0;*/
++ return 0;
++ }
++ break;
++ }
++
++ adap = &bdev->adap;
++ bmi_slot_power_on(slot);
++
++ mdelay(500);
++
++ // configure IOX
++ // [7:6]=interrupts, [5]=SER_PD*, [4]=LCD_RST*, [3]=VSYNC_OE*, [2]=ACC_RST*, [1:0]=backlight
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFF)) // normal - no accelerometer interrupts
++ return -ENODEV;
++
++ // normal operation - no accelerometer interrupts
++ if(WriteByte_IOX(adap, IOX_CONTROL, 0x00)) // IOX[7:0]=OUT
++ return -ENODEV;
++
++ // clear interrupts
++ if(ReadByte_IOX(adap, IOX_INPUT_REG, iox_data))
++ return -ENODEV;
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d iox data = %x\n", slot, *iox_data);
++
++#if defined ACCELEROMETER
++ // accelerometer
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x\n", slot, bdev->epraw.revision_msb);
++
++ // check for PCB revision >= 1.2
++ if(bdev->epraw.revision_msb >= 0x12) {
++
++ // normal IOX operation - accelerometer interrupts
++ if(WriteByte_IOX(adap, IOX_CONTROL, 0xC0)) // IOX[7:6]=IN, IOX[5:0]=OUT
++ return -ENODEV;
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFB)) // reset OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFF)) // enable OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return -ENODEV;
++
++ // read device to verify existance
++ if(ReadByte_ACC(adap, ACC_CPURDY, acc_data))
++ return -ENODEV;
++
++ // set TMD = 0x300 (~250 ms)
++ *acc_data = 0x5;
++ if(WriteByte_ACC(adap, ACC_TMDH, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_TMDL, *acc_data))
++ return -ENODEV;
++
++ // set INTOTM
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_INTOTM, *acc_data))
++ return -ENODEV;
++
++ // set GxAVE
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_GAAVE, *acc_data))
++ return -ENODEV;
++
++ // set GDTCT[01]
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT0L, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT0H, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT1L, *acc_data))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByte_ACC(adap, ACC_GDTCT1H, *acc_data))
++ return -ENODEV;
++
++ // set MODE0
++ *acc_data = ACC_MODE0_PDOFF | ACC_MODE0_TMPOFF | ACC_MODE0_AGCON | ACC_MODE0_MAUTO | ACC_MODE0_GDET10;
++ if(WriteByte_ACC(adap, ACC_MODE0, *acc_data))
++ return -ENODEV;
++
++ // set CFG
++ *acc_data = ACC_CFG_REGMD | ACC_CFG_INTLVL;
++ if(WriteByte_ACC(adap, ACC_CFG, *acc_data))
++ return -ENODEV;
++
++ // set INTMSK
++ *acc_data = 0xFE;
++ if(WriteByte_ACC(adap, ACC_INTMSK, *acc_data))
++ return -ENODEV;
++
++ // set CTRL0
++ *acc_data = ACC_CTRL0_CGAUTO;
++ if(WriteByte_ACC(adap, ACC_CTRL0, *acc_data))
++ return -ENODEV;
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return -ENODEV;
++
++ acc_probe(&pbmi_lcd.acc[slot], slot);
++
++ } else {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x (accelerometer not supported)\n", slot, bdev->epraw.revision_msb);
++ }
++#endif // ACCELEROMETER
++
++ // reset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ bmi_lcd_inactive(0);
++ } else {
++ bmi_lcd_inactive(1);
++ }
++
++ // configure GPIO
++ // turn LED's on
++ bmi_set_module_gpio_data(slot, 3, 0); // Red LED=ON
++ bmi_set_module_gpio_data(slot, 2, 0); // Green LED=ON
++
++ // assert reset
++ bmi_set_module_gpio_data(slot, 1, 0); // RST=0
++
++ // set GPIO direction
++ bmi_set_module_gpio_dir(slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 0, BMI_GPIO_IN); // real-time pen int state
++
++ mdelay(200);
++
++ // turn LED's off
++ bmi_set_module_gpio_data(slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data(slot, 2, 1); // Green LED=OFF
++
++ // deassert reset (module)
++ bmi_set_module_gpio_data(slot, 1, 1); // RST=1
++
++ mdelay(500);
++
++ // unreset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_active(0, 0x0, LCD_MODE_I80);
++ } else {
++ mdelay(2);
++ bmi_lcd_active(1, 0x0, LCD_MODE_I80);
++ }
++
++
++ // set up bdev/pbmi_lcd pointers
++ bmi_device_set_drvdata(bdev, &pbmi_lcd);
++ pbmi_lcd.bdev[slot] = bdev;
++
++ // spi set-up
++ if (bmi_device_spi_setup(bdev, 2000000, SPI_MODE_2, 32)) {
++ printk(KERN_ERR "bmi_lcd.c: Unable to setup spi%d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++ bmi_slot_spi_enable(slot);
++ pbmi_lcd.spi[slot] = bmi_device_get_spi(bdev);
++
++
++ // check spi access and enable touch screen
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ if(spi_lcd_write_reg(&pbmi_lcd, buf, 1, slot) != 1) {
++ printk(KERN_WARNING "bmi_lcd.c: Unable set-up spi for bmi_lcd %d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_spi_disable(slot);
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++
++ // complete pbmi_lcd set-up
++ pbmi_lcd.lcd_cnt++;
++ pbmi_lcd.active = 1;
++ pbmi_lcd.activated[slot] = 1;
++
++
++ mdelay(100);
++
++ lcd = pbmi_lcd.blcd[slot];
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_config(lcd, 0);
++ mdelay(2);
++ } else {
++ mdelay(2);
++ bmi_lcd_config(lcd, 1);
++ mdelay(2);
++ }
++
++
++ // request input event interrupt handler
++ pbmi_lcd.interrupt[0] = M1_IRQ;
++ pbmi_lcd.interrupt[1] = M2_IRQ;
++ pbmi_lcd.interrupt[2] = M3_IRQ;
++ pbmi_lcd.interrupt[3] = M4_IRQ;
++ snprintf(pbmi_lcd.int_name, sizeof(pbmi_lcd.int_name), "bmi_lcd%d", slot);
++ if (request_irq(pbmi_lcd.interrupt[slot], &module_irq_handler, 0, pbmi_lcd.int_name, &pbmi_lcd)) {
++ printk( KERN_ERR "bmi_lcd.c: Can't allocate irq %d or find lcd in slot %d\n", pbmi_lcd.interrupt[slot], slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_power_off(slot);
++ return -EBUSY;
++ }
++
++ // check GPIO status
++ printk(KERN_INFO "bmi_lcd.c: slot %d gpio = %x\n", slot, bmi_read_gpio_data_reg(slot));
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return 0;
++}
++
++extern struct delayed_work bmilcd_work0;
++extern struct delayed_work bmilcd_work1;
++extern struct delayed_work bmilcd_work2;
++extern struct delayed_work bmilcd_work3;
++
++ // remove
++void bmi_lcd_remove(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++
++ if(pbmi_lcd.activated[slot] == 0)
++ return;
++
++ switch(slot) {
++ case 0:
++ cancel_delayed_work(&bmilcd_work0);
++ break;
++ case 1:
++ cancel_delayed_work(&bmilcd_work1);
++ break;
++ case 2:
++ cancel_delayed_work(&bmilcd_work2);
++ break;
++ case 3:
++ cancel_delayed_work(&bmilcd_work3);
++ break;
++ }
++
++ free_irq(pbmi_lcd.interrupt[slot], &pbmi_lcd);
++
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN);
++
++ // bmi/spi clean-up
++ bmi_device_spi_cleanup(bdev);
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_slot_spi_disable(slot);
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (&bdev[slot], 0);
++
++ // deactivate
++ pbmi_lcd.activated[slot] = 0;
++ pbmi_lcd.bdev[slot] = 0;
++ pbmi_lcd.lcd_cnt--;
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[2] == 0)) {
++ bmi_lcd_inactive(0); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[1] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ bmi_lcd_inactive(1); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[1] == 0) &&
++ (pbmi_lcd.activated[2] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ pbmi_lcd.active = -1;
++ }
++
++ // enable LCD on opposite side
++ switch(slot) {
++ case 0:
++ if(pbmi_lcd.bdev[2] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[2]);
++ break;
++ case 1:
++ if(pbmi_lcd.bdev[3] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[3]);
++ break;
++ case 2:
++ if(pbmi_lcd.bdev[0] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[0]);
++ break;
++ case 3:
++ if(pbmi_lcd.bdev[1] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[1]);
++ break;
++ }
++
++#ifdef ACCELEROMETER
++ acc_remove(&pbmi_lcd.acc[slot], slot);
++#endif
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return;
++}
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++static void update_pen_state(void *arg, int slot, int x, int y, int pressure)
++{
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++ int sync = 0;
++
++ if (pressure)
++ {
++ /*input_report_abs(pbmi_lcd->input_dev[slot], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_PRESSURE, pressure);
++
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_PRESSURE, pressure);*/
++
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, pressure);
++ }
++ else
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, pressure);
++ }
++
++ if (!pbmi_lcd->pen_down[slot])
++ {
++ /*input_report_key(pbmi_lcd->input_dev[slot], BTN_TOUCH, 1);
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M1234], BTN_TOUCH, 1);*/
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 1);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 1);
++ }
++
++ }
++ sync = 1;
++ }
++ else if (pbmi_lcd->pen_down[slot])
++ {
++ /*input_report_key(pbmi_lcd->input_dev[slot], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_PRESSURE, 0);
++
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M1234], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_PRESSURE, 0); */
++
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, 0);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, 0);
++ }
++ sync = 1;
++ }
++
++ if (sync)
++ {
++ /*input_sync(pbmi_lcd->input_dev[slot]);
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M1234]);*/
++ if((slot == 0) || (slot == 2))
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M13]);
++ }
++ else
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M24]);
++ }
++ }
++ pbmi_lcd->pen_down[slot] = pressure ? 1 : 0;
++
++}
++
++
++void bmilcd_input_work(void *arg, int slot);
++
++void bmilcd_input_work0(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 0);
++}
++
++void bmilcd_input_work1(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 1);
++}
++
++void bmilcd_input_work2(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 2);
++}
++
++void bmilcd_input_work3(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 3);
++}
++
++DECLARE_DELAYED_WORK(bmilcd_work0, bmilcd_input_work0);
++DECLARE_DELAYED_WORK(bmilcd_work1, bmilcd_input_work1);
++DECLARE_DELAYED_WORK(bmilcd_work2, bmilcd_input_work2);
++DECLARE_DELAYED_WORK(bmilcd_work3, bmilcd_input_work3);
++
++// work handler
++void bmilcd_input_work(void *arg, int slot) {
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++#if defined ACCELEROMETER
++ struct i2c_adapter *adap = &pbmi_lcd->bdev[slot]->adap;
++ unsigned char acc_data[1];
++ static int pitch = 0;
++ static int roll = 0;
++ static int gx = 0;
++ static int gy = 0;
++
++#endif // ACCELEROMETER
++ unsigned char buf[4];
++ int x = 0;
++ int y = 0;
++ int z1 = 0;
++ int z2 = 0;
++ int pressure = 0;
++ int debounce;
++ int penirq;
++
++#if defined DEBUG
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d)\n", slot);
++#endif
++
++ if(pbmi_lcd->bdev[slot] == 0) {
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work called with no bdev active (slot %d)\n", slot);
++ return;
++ }
++
++#if defined ACCELEROMETER
++ if(pbmi_lcd->bdev[slot]->epraw.revision_msb >= 0x12) {
++
++ // orientation
++ // read ROLL
++ if(ReadByte_ACC(adap, ACC_ROLLH, acc_data))
++ return;
++ roll = (0x0000 | *acc_data) << 8;
++
++ if(ReadByte_ACC(adap, ACC_ROLLL, acc_data))
++ return;
++ roll = roll | *acc_data;
++ // read PITCH
++ if(ReadByte_ACC(adap, ACC_PITCHH, acc_data))
++ return;
++ pitch = (0x0000 | *acc_data) << 8;
++
++ if(ReadByte_ACC(adap, ACC_PITCHL, acc_data))
++ return;
++ pitch = pitch | *acc_data;
++
++
++
++
++ if(ReadByte_ACC(adap, ACC_GAZH, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[0] = *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAZL, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[1] = *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAYH, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[2] = *acc_data;
++ gy = *acc_data << 8;
++
++ if(ReadByte_ACC(adap, ACC_GAYL, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[3] = *acc_data;
++ gy = gy | *acc_data;
++
++ if(ReadByte_ACC(adap, ACC_GAXH, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[4] = *acc_data;
++ gx = *acc_data << 8;
++
++ if(ReadByte_ACC(adap, ACC_GAXL, acc_data))
++ return;
++ pbmi_lcd->acc[slot].sample[5] = *acc_data;
++ gx = gx | *acc_data;
++
++ //wake up any read's
++ pbmi_lcd->acc[slot].flag = 1;
++ wake_up_interruptible(&pbmi_lcd->acc[slot].wq);
++
++ // read STATUS
++ if(ReadByte_ACC(adap, ACC_STATUS, acc_data))
++ return;
++
++ if((*acc_data & 0x1) == 0) {
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return;
++
++ // read INTRQ
++ if(ReadByte_ACC(adap, ACC_INTRQ, acc_data))
++ return;
++ }
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByte_ACC(adap, ACC_PAGESEL, *acc_data))
++ return;
++
++ // report orientation
++ // printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d) pitch=0x%x, roll=0x%x, ABS_MISC=0x%x\n",
++ // slot, pitch, roll, pitch << 16 | roll); //pjg - debug
++
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_MISC, (pitch << 16) | roll);
++ input_sync(pbmi_lcd->input_dev[slot]);
++ }
++#endif // ACCELEROMETER
++
++
++ // read touch screen - X, Y, TOUCH, PRESSURE
++
++ penirq = bmi_slot_status_irq_state(slot);
++ /*printk(KERN_INFO "bmi_lcd.c: IRQ Status %d (slot %d) %d\n", penirq, slot,msecs_to_jiffies(10));*/
++
++ if (pbmi_lcd->activated[slot] && penirq)
++ {
++
++ for(debounce = 0; debounce < DEBOUNCE; debounce++)
++ {
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AY | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ y = (((buf[0] << 5) | buf[1] >> 3)) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AX | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ x = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ1 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z1 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ2 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z2 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++ mdelay(1);
++ }
++
++ if(x && y && z1 && z2)
++ pressure = (X_PLATE * x / 4096) * ((z2 / z1) - 1);
++
++ x = 4096 - x;
++ y = 4096 - y;
++
++ if (pressure < 70)
++ {
++ if (pbmi_lcd->scount)
++ update_pen_state(arg, slot, x, y, pressure);
++ else
++ {
++ pbmi_lcd->scount[slot]++;
++ /*update_pen_state(arg, slot, 0, 0, pressure);*/
++ }
++ }
++ /* else
++ {
++ update_pen_state(arg, slot, 0, 0, pressure);
++ }*/
++
++ switch(slot)
++ {
++ case BMI_TS_M1:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ break;
++ case BMI_TS_M2:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ break;
++ case BMI_TS_M3:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ break;
++ case BMI_TS_M4:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ break;
++ }
++ /* printk(KERN_INFO "bmi_lcd.c: work scheduled on (slot %d)\n", slot); */
++ /*buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);*/
++ }
++
++ else
++ {
++ /*printk(KERN_INFO "bmi_lcd.c: Pen up on (slot %d)\n", slot);*/
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);
++ update_pen_state(arg,slot, 0, 0, 0);
++ enable_irq(pbmi_lcd->interrupt[slot]);
++ }
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ disable_irq(irq);
++ /*printk(KERN_INFO "bmi_lcd.c: Interupt on (slot %d)\n", irq);*/
++ switch(irq)
++ {
++ case M1_IRQ:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M1] = 0;
++ break;
++ case M2_IRQ:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M2] = 0;
++ break;
++ case M3_IRQ:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M3] = 0;
++ break;
++ case M4_IRQ:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M4] = 0;
++ break;
++ }
++ return IRQ_HANDLED;
++}
++
++/*
++ * control device operations
++ */
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *filp)
++{
++ if(pbmi_lcd.open_flag) {
++ return - EBUSY;
++ }
++ pbmi_lcd.open_flag = 1;
++ filp->private_data = &pbmi_lcd;
++ return 0;
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *filp)
++{
++ pbmi_lcd.open_flag = 0;
++ return 0;
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data[1];
++ int slot = (__user arg) & 0xF;
++ int bl = ((__user arg) & 0x70) >> 4;
++
++ // error if no lcd active.
++ if(pbmi_lcd.active == -1)
++ return -ENODEV;
++
++ if(cmd != BMI_LCD_GETSTAT) {
++
++ // error if slot invalid
++ if((slot < CPLD_M1) || (slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[slot]->adap;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ case BMI_LCD_RLEDOFF:
++ bmi_set_module_gpio_data(slot, 3, 1);// Red LED=OFF
++ break;
++ case BMI_LCD_RLEDON:
++ bmi_set_module_gpio_data(slot, 3, 0);// Red LED=ON
++ break;
++ case BMI_LCD_GLEDOFF:
++ bmi_set_module_gpio_data(slot, 2, 1);// Green LED=OFF
++ break;
++ case BMI_LCD_GLEDON:
++ bmi_set_module_gpio_data(slot, 2, 0);// Green LED=ON
++ break;
++ case BMI_LCD_VSYNC_DIS: // enable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_VSYNC_EN: // disable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_EN: // enable LCD component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_DIS: // disable LCD component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_EN: // enable Serializer component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_DIS: // disable Serializer component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SETRST: // overall module reset
++ bmi_set_module_gpio_data (slot, 1, 0); // RST=0
++ break;
++ case BMI_LCD_CLRRST: // overall module enable
++ bmi_set_module_gpio_data (slot, 1, 1); // RST=1
++ break;
++ case BMI_LCD_SET_BL: // set backlight brightness
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8) | bl;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_GETSTAT:
++ {
++ int *slot = ((int __user *) arg);
++ int read_data;
++
++ *slot &= 0xF;
++
++ // error if slot invalid
++ if((*slot < CPLD_M1) || (*slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[*slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[*slot]->adap;
++
++ if(ReadByte_IOX(adap, IOX_INPUT_REG, iox_data))
++ return -ENODEV;
++
++ read_data = *iox_data | (bmi_read_gpio_data_reg(*slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++ case BMI_LCD_ACTIVATE: //pjg fix/test
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ return -ENODEV;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ return -ENODEV;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ return -ENODEV;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ return -ENODEV;
++ }
++ break;
++ }
++ // activate
++ if((!pbmi_lcd.activated[slot]) && (pbmi_lcd.bdev[slot] != 0)) {
++ bmi_lcd_probe(pbmi_lcd.bdev[slot]);
++ }
++ break;
++ case BMI_LCD_DEACTIVATE:
++ if(pbmi_lcd.activated[slot]) {
++ disable_irq_nosync(pbmi_lcd.interrupt[slot]);
++ pbmi_lcd.activated[slot] = 0;
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8);
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ bmi_slot_power_off(slot);
++ }
++ break;
++ case BMI_LCD_SUSPEND:
++ printk(KERN_ERR "BMI_LCD_SUSPEND NOT IMPLEMENTED\n"); //pjg
++ break;
++ case BMI_LCD_RESUME:
++ printk(KERN_ERR "BMI_LCD_RESUME NOT IMPLEMENTED\n"); //pjg
++ break;
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++ // control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++ // BMI LCD fops
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.config)) {
++ lcd->lcd_ops.config(disp);
++ }
++}
++
++void bmi_lcd_reset(struct bmi_lcd *lcd, int slot)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.reset)) {
++ lcd->lcd_ops.reset(slot);
++ }
++}
++
++int register_bmi_lcd(struct bmi_lcd *lcd, int slot) //pjg - placeholder for multiple LCD types
++{
++ if(!lcd) {
++ return -1;
++ }
++ if((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if(pbmi_lcd.blcd[slot]) {
++ return -1;
++ }
++ else {
++ pbmi_lcd.blcd[slot] = lcd;
++ }
++
++ if(lcd->lcd_ops.activate) {
++ lcd->lcd_ops.activate(lcd, slot);
++ }
++
++ return 0;
++}
++
++int unregister_bmi_lcd(struct bmi_lcd *lcd, int slot) //pjg - placeholder for multiple LCD types
++{
++ if (!lcd) {
++ return -1;
++ }
++ if ((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if (pbmi_lcd.blcd[slot] != lcd) {
++ return -1;
++ }
++ else {
++ pbmi_lcd.blcd [slot] = 0;
++ lcd->lcd_ops.deactivate(lcd, slot);
++ }
++ return 0;
++}
++
++static struct miscdevice cntl_dev = {
++ MISC_DYNAMIC_MINOR,
++ "bmi_lcd_control",
++ &cntl_fops
++};
++
++/*
++ * Module functions
++ */
++
++char const input_name0[MAX_STRG] = "bmi_lcd_ts0";
++char const input_name1[MAX_STRG] = "bmi_lcd_ts1";
++char const input_name2[MAX_STRG] = "bmi_lcd_ts2";
++char const input_name3[MAX_STRG] = "bmi_lcd_ts3";
++char const input_name4[MAX_STRG] = "bmi_lcd_ts4";
++char const input_name5[MAX_STRG] = "bmi_lcd_ts5";
++char const input_name6[MAX_STRG] = "bmi_lcd_ts6";
++
++static __init int bmi_lcd_init(void)
++{
++ int ts;
++ int rc = 0;
++
++ // No lcd is active.
++ pbmi_lcd.active = -1;
++ pbmi_lcd.activated[0] = 0;
++ pbmi_lcd.activated[1] = 0;
++ pbmi_lcd.activated[2] = 0;
++ pbmi_lcd.activated[3] = 0;
++
++ // set up control character device - bmi_lcd_control
++ rc = misc_register(&cntl_dev);
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't allocate bmi_lcd_control device\n");
++ return rc;
++ }
++
++ // Allocate and Register input device. - bmi_lcd_ts[BMI_TS_M1:BMI_TS_M1234]
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++) {
++ pbmi_lcd.input_dev[ts] = input_allocate_device();
++ if(!pbmi_lcd.input_dev[ts]) {
++ printk(KERN_ERR "bmi_lcd_init: Can't allocate input_dev[ts]\n");
++ return -ENOMEM;
++ }
++
++ // set up input device
++ switch(ts) {
++ case BMI_TS_M1:
++ pbmi_lcd.input_dev[BMI_TS_M1]->name = input_name0;
++ pbmi_lcd.input_dev[BMI_TS_M1]->phys = input_name0;
++ break;
++ case BMI_TS_M2:
++ pbmi_lcd.input_dev[BMI_TS_M2]->name = input_name1;
++ pbmi_lcd.input_dev[BMI_TS_M2]->phys = input_name1;
++ break;
++ case BMI_TS_M3:
++ pbmi_lcd.input_dev[BMI_TS_M3]->name = input_name2;
++ pbmi_lcd.input_dev[BMI_TS_M3]->phys = input_name2;
++ break;
++ case BMI_TS_M4:
++ pbmi_lcd.input_dev[BMI_TS_M4]->name = input_name3;
++ pbmi_lcd.input_dev[BMI_TS_M4]->phys = input_name3;
++ break;
++ case BMI_TS_M13:
++ pbmi_lcd.input_dev[BMI_TS_M13]->name = input_name4;
++ pbmi_lcd.input_dev[BMI_TS_M13]->phys = input_name4;
++ break;
++ case BMI_TS_M24:
++ pbmi_lcd.input_dev[BMI_TS_M24]->name = input_name5;
++ pbmi_lcd.input_dev[BMI_TS_M24]->phys = input_name5;
++ break;
++ case BMI_TS_M1234:
++ pbmi_lcd.input_dev[BMI_TS_M1234]->name = input_name6;
++ pbmi_lcd.input_dev[BMI_TS_M1234]->phys = input_name6;
++ break;
++ }
++ pbmi_lcd.input_dev[ts]->id.bustype = BUS_BMI;
++ pbmi_lcd.input_dev[ts]->private = &pbmi_lcd;
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
++ pbmi_lcd.input_dev[ts]->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_X)] |= BIT_MASK(ABS_X);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_Y)] |= BIT_MASK(ABS_Y);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_PRESSURE)] |= BIT_MASK(ABS_PRESSURE);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_X, BMI_LCD_MIN_XC, BMI_LCD_MAX_XC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_Y, BMI_LCD_MIN_YC, BMI_LCD_MAX_YC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_PRESSURE, 0, 1024, 0, 0);
++
++ // register input device
++ if(input_register_device(pbmi_lcd.input_dev[ts])) {
++ int tts;
++ printk(KERN_ERR "bmi_lcd_init() - input_register_device failed.\n");
++
++ for(tts = BMI_TS_M1; tts < ts; tts++)
++ input_unregister_device(pbmi_lcd.input_dev[tts]);
++
++ misc_deregister(&cntl_dev);
++
++ return -ENODEV;
++ }
++ }
++
++ pbmi_lcd.lcd_cnt = 0;
++
++ // hardware specfic set-up
++ s320x240_bmi_lcd.interface = s320x240_lcd_interface;
++ s320x240_bmi_lcd_ops.config = (void(*)) &s320x240_config;
++ s320x240_bmi_lcd_ops.reset = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.suspend = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.resume = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_on = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_off = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.activate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.deactivate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd.lcd_ops = s320x240_bmi_lcd_ops;
++ pbmi_lcd.blcd[0] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[1] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[2] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[3] = &s320x240_bmi_lcd;
++
++ sema_init(&pbmi_lcd.sem[0], 1);
++ sema_init(&pbmi_lcd.sem[1], 1);
++ sema_init(&pbmi_lcd.sem[2], 1);
++ sema_init(&pbmi_lcd.sem[3], 1);
++
++
++ acc_init();
++
++ // register with BMI
++ rc = bmi_register_driver(&bmi_lcd_driver);
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't register bmi_lcd_driver\n");
++
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ misc_deregister(&cntl_dev);
++
++ return rc;
++ }
++
++ printk("bmi_lcd.c: BMI_LCD Driver v%s \n", BMILCD_VERSION);
++
++ return 0;
++}
++
++
++static void __exit bmi_lcd_clean(void)
++{
++ int ts;
++
++ // remove input devices
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ // remove control device
++ misc_deregister(&cntl_dev);
++
++ // remove bmi driver
++ bmi_unregister_driver(&bmi_lcd_driver);
++ acc_clean();
++ return;
++}
++
++module_init(bmi_lcd_init);
++module_exit(bmi_lcd_clean);
++
++// Exported symbols
++EXPORT_SYMBOL(register_bmi_lcd);
++EXPORT_SYMBOL(unregister_bmi_lcd);
++
++
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BMI lcd device driver");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_control");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_ts");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_acc");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/bmi_lcd_mi.c
+@@ -0,0 +1,1855 @@
++/*
++ * bmi_lcd.c
++ *
++ * BMI LCD device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/input.h>
++#include <linux/kernel.h>
++#include <linux/major.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <asm/uaccess.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/miscdevice.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <mach/mxc_i2c.h>
++#include <mach/mx31bug_cpld.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/bmi/bmi_lcd.h>
++#include <mach/ipu.h>
++
++#include "acc.h"
++
++
++#define DEBUG
++#undef DEBUG
++
++#define BMILCD_VERSION "1.2" // driver version
++#define BUF_MAX_SIZE 0x20 // spi buffer size
++#define WORK_DELAY (1) // interrupt work handler delay
++#define DEBOUNCE 10 // touch screen debounce
++#define X_PLATE 400 // touch screen X plate resistance //pjg - This is not the correct value
++#define BMI_SLOT_NUM (4) // number of BMI slots
++#define MAX_STRG (40) // Max string buffer size
++
++#define VSYNC_DISABLE 0x0
++#define VSYNC_ENABLE 0x1
++
++ // lcd
++struct lcd_interface {
++ char lcd_type[MAX_STRG]; // text description of LCD type
++ u8 suspended; // power management state
++ u8 rotation; // screen rotation
++ u8 disp; // display number (DISP0 or DISP1)
++ u8 addr_mode; // display addressing mode
++ u8 vsync_mode; // VSYNC signal enable (VSYNC_ENABLE | VSYNC_DISABLE)
++ u8 bus_if_type; // bus type (XY | FullWoBE | FullWithBE)
++ ipu_adc_sig_cfg_t adc_sig; // IPU ADC set-up parameters
++ ipu_di_signal_cfg_t di_sig; // IPU DI set-up parameters
++};
++
++static struct lcd_interface s320x240_lcd_interface = {
++ .lcd_type = "MXCFB_SHARP_320X240",
++ .suspended = 0,
++ .rotation = IPU_ROTATE_NONE,
++ .disp = DISP0,
++ .vsync_mode = VSYNC_DISABLE,
++ .bus_if_type = XY,
++ .adc_sig = { 0, 0, 0, 0, 0, 0, 0, 0, IPU_ADC_BURST_WCS, IPU_ADC_IFC_MODE_SYS80_TYPE2,
++ 16, 0, 0, IPU_ADC_SER_NO_RW },
++ .di_sig = { 0,0,0,0,0,0,0,0 }, //pjg - reserved for multiple LCD driver
++};
++
++extern void s320x240_config(int disp);
++extern void s320x240_disp_off(int disp);
++extern void s320x240_disp_on(int disp);
++
++
++struct bmi_lcd;
++
++struct bmi_lcd_ops {
++ void *(*config) (int disp); // LCD configuration/initialization
++ void *(*reset) (int slot); // LCD reset
++ int *(*suspend) (struct bmi_lcd *blcd); // power management
++ int *(*resume) (struct bmi_lcd *blcd); // power management
++ int *(*disp_on) (int disp); // display on
++ int *(*disp_off) (int disp); // display off
++ int (*activate) (struct bmi_lcd *lcd, int slot); // enable LCD backlight, touchscreen, accelerometer, ...
++ int (*deactivate) (struct bmi_lcd *lcd, int slot); // disable LCD backlight, touchscreen, accelerometer, ...
++};
++
++struct bmi_lcd_ops s320x240_bmi_lcd_ops;
++
++struct bmi_lcd {
++ struct lcd_interface interface; // pointer to this struct is returned by config()
++ struct bmi_lcd_ops lcd_ops; // function pointers
++};
++
++static struct bmi_lcd s320x240_bmi_lcd;
++
++int register_bmi_lcd(struct bmi_lcd *blcd, int slot);
++int unregister_bmi_lcd(struct bmi_lcd *blcd, int slot);
++
++ // private device structure
++struct pbmi_lcd
++{
++ int open_flag; // force single open
++ unsigned int lcd_cnt; // number of LCD's present
++ unsigned int active; // indication of LCD presence
++ unsigned int activated[BMI_SLOT_NUM]; // indication of LCD presence
++
++ struct bmi_lcd *blcd[BMI_SLOT_NUM]; // BMI LCD structure - placeholder for multiple display types
++ struct bmi_device *bdev[BMI_SLOT_NUM]; // BMI device per slot
++ unsigned int interrupt[BMI_SLOT_NUM]; // input device interrupt handlers
++ char int_name[MAX_STRG]; // interrupt name
++
++ struct input_dev *input_dev[BMI_TS_NUM]; // input device (touch screen and accelerometer)
++ struct timer_list timer[BMI_SLOT_NUM]; // touch timer
++
++ int pen_down[BMI_SLOT_NUM];
++ int scount[BMI_SLOT_NUM];
++
++ struct semaphore i2c_sem[BMI_SLOT_NUM];
++
++ struct spi_device *spi[BMI_SLOT_NUM]; // touch screen device interface
++ struct semaphore sem[BMI_SLOT_NUM]; // spi semaphore
++ char rbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi read buffer
++ char wbuf[BMI_SLOT_NUM][BUF_MAX_SIZE]; // spi write buffer
++
++ struct acc_dev acc[BMI_SLOT_NUM];
++
++};
++
++static struct pbmi_lcd pbmi_lcd; // LCD device sructure
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_lcd_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_LCD_SHARP_320X240,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_lcd_tbl);
++
++/*printk(KERN_INFO "MDT: 0x%x\n", __mod_bmi_device_table);*/
++
++int bmi_lcd_probe(struct bmi_device *bdev);
++void bmi_lcd_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_lcd_driver =
++{
++ .name = "bmi_lcd",
++ .id_table = bmi_lcd_tbl,
++ .probe = bmi_lcd_probe,
++ .remove = bmi_lcd_remove,
++};
++
++//Accelerometer driver structure
++
++
++/*
++ * I2C set up
++ */
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define BMI_ACC_I2C_ADDRESS 0x17 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0 // IOX input data register
++#define IOX_OUTPUT_REG 0x1 // IOX output data register
++#define IOX_POLARITY_REG 0x2 // IOX polarity data register
++#define IOX_CONTROL 0x3 // IOX direction control register
++#define IOX_B1 (0) // bit 0 - backlight control
++#define IOX_A1_A2 (1) // bit 1 - backlight control
++#define IOX_ACC_RST_N (2) // bit 2 - acceleromter reset
++#define IOX_VSYNC_EN_N (3) // bit 3 - VSYNC output buffer enable
++#define IOX_LCD_RST_N (4) // bit 4 - LCD reset
++#define IOX_SERDES_PD_N (5) // bit 5 - SERDES power down
++#define IOX_X_INT (6) // bit 6 - accelerometer interrupt
++#define IOX_Y_INT (7) // bit 7 - accelerometer interrupt
++
++ // I2C ACC register addresses - OKI
++#define ACC_PAGESEL 0x1E // device ready status
++ // page 0
++#define ACC_DVRST 0x01 // device reset
++ #define ACC_DVRST_RST 0x3C // device reset
++ #define ACC_DVRST_EN 0xC3 // device enable
++#define ACC_PDWN 0x02 // osc power down
++ #define ACC_PWDN_RST 0x01 // device reset
++ #define ACC_PWDN_EN 0x00 // device enable
++#define ACC_CTRL0 0x03 // control 0
++ #define ACC_CTRL0_CTSTR 0x40 // control 0 - temp sensor
++ #define ACC_CTRL0_CGSTRNC 0x08 // control 0 - 3-axis/no tilt
++ #define ACC_CTRL0_CGSTRC 0x04 // control 0 - 3-axis/tilt
++ #define ACC_CTRL0_CGAUTO 0x01 // control 0 - auto
++#define ACC_MODE0 0x05 // control 0
++ #define ACC_MODE0_PDOFF 0x80 // mode 0 - disable auto power down
++ #define ACC_MODE0_RVOFF 0x40 // mode 0 - disable temp compensation
++ #define ACC_MODE0_TMPOFF 0x20 // mode 0 - disable temp measurement
++ #define ACC_MODE0_AGCON 0x10 // mode 0 - enable auto mode pitch and roll
++ #define ACC_MODE0_MAUTO 0x04 // mode 0 - enable auto termination
++ #define ACC_MODE0_GDET00 0x00 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET01 0x01 // mode 0 - g detection threshold - see ML8953 data sheet
++ #define ACC_MODE0_GDET10 0x02 // mode 0 - g detection threshold - see ML8953 data sheet
++#define ACC_MODE1 0x06 // mode 1
++ #define ACC_MODE1_MOFF 0x20 // mode 1 - disable 3-axis continuous mode
++ #define ACC_MODE1_ZAXIS 0x03 // mode 1 - Z axis
++ #define ACC_MODE1_YAXIS 0x02 // mode 1 - Y axis
++ #define ACC_MODE1_XAXIS 0x01 // mode 1 - X axis
++ #define ACC_MODE1_RAXIS 0x00 // mode 1 - Reference axis
++#define ACC_INTRQ 0x07 // interrupt request (1 = request)
++#define ACC_INTMSK 0x08 // interrupt mask (1 = masked)
++ #define ACC_INT_TREQ 0x20 // interrupt - temperature
++ #define ACC_INT_GREQ 0x08 // interrupt - acceleration/no tilt
++ #define ACC_INT_GCREQ 0x04 // interrupt - acceleration/tilt
++ #define ACC_INT_GAREQ 0x01 // interrupt - automatic
++#define ACC_TMDL 0x09 // timer LSB = (1/6.2 MHz) x 2048 x TMD
++#define ACC_TMDH 0x0A // timer MSB
++#define ACC_CFG 0x0C // configuration
++ #define ACC_CFG_REGMD 0x80 // address auto-increment
++ #define ACC_CFG_SPI3M_3 0x40 // spi mode = 3-wire
++ #define ACC_CFG_SPI3M_4 0x00 // spi mode = 4-wire
++ #define ACC_CFG_SDOCFG_T 0x10 // sdo mode = totem-pole
++ #define ACC_CFG_SDOCFG_OC 0x00 // sdo mode = open-drain
++ #define ACC_CFG_INT1EN_G 0x08 // interrupt 1 mode = g only
++ #define ACC_CFG_INT1EN_ALL 0x00 // interrupt 1 mode = all
++ #define ACC_CFG_INTLVL 0x04 // interrupt level mode
++ #define ACC_CFG_INT1CFG_T 0x02 // interrupt 1 mode = totem-pole
++ #define ACC_CFG_INT1CFG_OC 0x00 // interrupt 1 mode = open-drain
++ #define ACC_CFG_INT0CFG_T 0x01 // interrupt 0 mode = totem-pole
++ #define ACC_CFG_INT0CFG_OC 0x00 // interrupt 0 mode = open-drain
++#define ACC_INTOTM 0x0D // interrupt output conditions
++#define ACC_GAAVE 0x0E // Data averaging - automatic mode
++#define ACC_GNAVE 0x0F // Data averaging - normal mode
++#define ACC_GDTCT0L 0x11 // threshold 0 LSB
++#define ACC_GDTCT0H 0x12 // threshold 0 MSB
++#define ACC_GDTCT1L 0x13 // threshold 1 LSB
++#define ACC_GDTCT1H 0x14 // threshold 1 MSB
++#define ACC_CPURDY 0x15 // device ready status (ready = 0x01)
++ // page 1
++#define ACC_STATUS 0x01 // measurment status
++ #define ACC_STATUS_ASTS 0x02 // acceleration measurement - automatic modes
++ #define ACC_STATUS_STS 0x01 // acceleration measurement - non-automatic modes
++#define ACC_GAXL 0x02 // g vector
++#define ACC_GAXH 0x03 // g vector
++#define ACC_GAYL 0x04 // g vector
++#define ACC_GAYH 0x05 // g vector
++#define ACC_GAZL 0x06 // g vector
++#define ACC_GAZH 0x07 // g vector
++#define ACC_GASVL 0x08 // g vector
++#define ACC_GASVH 0x09 // g vector
++#define ACC_GNXL 0x0A // g vector
++#define ACC_GNXH 0x0B // g vector
++#define ACC_GNYL 0x0C // g vector
++#define ACC_GNYH 0x0D // g vector
++#define ACC_GNZL 0x0E // g vector
++#define ACC_GNZH 0x0F // g vector
++#define ACC_GNSVL 0x10 // g vector
++#define ACC_GNSVH 0x11 // g vector
++#define ACC_PITCHL 0x12 // pitch
++#define ACC_PITCHH 0x13 // pitch
++#define ACC_ROLLL 0x14 // roll
++#define ACC_ROLLH 0x15 // roll
++#define ACC_TEMPL 0x19 // temperature
++#define ACC_TEMPH 0x1A // temperature
++
++ // read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++static int ReadByteLock_IOX(struct pbmi_lcd *priv, unsigned char offset, unsigned char *data, int slot)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ struct i2c_adapter *adap;
++
++ /* Read Byte with Pointer */
++
++ adap = &priv->bdev[slot]->adap;
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ down(&priv->i2c_sem[slot]);
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ up(&priv->i2c_sem[slot]);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++ // write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++static int WriteByteLock_IOX(struct pbmi_lcd *priv, unsigned char offset, unsigned char data, int slot)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++ struct i2c_adapter *adap;
++ /* Write Byte with Pointer */
++
++ adap = &priv->bdev[slot]->adap;
++ if (adap == NULL)
++ {
++ printk(KERN_INFO "WriteByteLock_IOX adap NULL\n");
++ return -1;
++ }
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ down(&priv->i2c_sem[slot]);
++ printk(KERN_INFO "WriteByteLock_IOX attempting I2C xfer\n");
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++ up(&priv->i2c_sem[slot]);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByteLock_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++ // read byte from I2C acceleromter
++static int ReadByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ int retries = 0;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ while (retries < 5)
++ {
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ if (ret == 2)
++ break;
++ else
++ retries++;
++ mdelay(1);
++ }
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++static int ReadByteLock_ACC(struct pbmi_lcd *priv, unsigned char offset, unsigned char *data, int slot)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++ struct i2c_adapter *adap;
++
++ /* Read Byte with Pointer */
++
++ adap = &priv->bdev[slot]->adap;
++
++ rmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++
++ down(&priv->i2c_sem[slot]);
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++ up(&priv->i2c_sem[slot]);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByteLock_ACC() - i2c_transfer() failed.0x%x\n",-ret);
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C accelerometer
++static int WriteByte_ACC(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++static int WriteByteLock_ACC(struct pbmi_lcd *priv, unsigned char offset, unsigned char data, int slot)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++ struct i2c_adapter *adap;
++ /* Write Byte with Pointer */
++
++ adap = &priv->bdev[slot]->adap;
++
++ wmsg[0].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_ACC_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ down(&priv->i2c_sem[slot]);
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++ up(&priv->i2c_sem[slot]);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByteLock_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++/*
++ * SPI functions
++ */
++
++ // TSC2046 touch screen controller command register bit definitons
++#define SPI_START 0x80 // command start
++#define SPI_AT0 0x00 // read temperature - not supported
++#define SPI_AY 0x10 // read Y
++#define SPI_ABAT 0x20 // read battery - not supported
++#define SPI_AZ1 0x30 // read Z1
++#define SPI_AZ2 0x40 // read Z2
++#define SPI_AX 0x50 // read X
++#define SPI_AAUX 0x60 // read AUX - not supported
++#define SPI_AT1 0x70 // read temperature - not supported
++#define SPI_MODE_12 0x00 // 12-bit mode - Preferred
++#define SPI_MODE_8 0x08 // 8-bit mode
++#define SPI_MODE_DFR 0x00 // differential mode - Preferred
++#define SPI_MODE_SER 0x04 // single ended mode
++#define SPI_PD 0x00 // power down - PENIRQ enabled
++#define SPI_ADC 0x01 // ADC enabled
++#define SPI_REF 0x02 // Vref enabled - unused
++#define SPI_REF_ADC 0x03 // Vref & ADC enabled - unused
++
++ // spi access
++static int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
++{
++ struct spi_transfer t = {
++ .tx_buf = (const void *)buf,
++ .rx_buf = buf,
++ .len = len,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++
++ spi_message_add_tail(&t, &m);
++ if (spi_sync(spi, &m) != 0 || m.status != 0)
++ return -1;
++
++ return m.actual_length;
++}
++
++ // spi write register
++static ssize_t spi_lcd_write_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++ // spi read register
++static ssize_t spi_lcd_read_reg(struct pbmi_lcd *priv, char *buf, int len, int slot)
++{
++ int res = 0;
++
++ down(&priv->sem[slot]);
++
++ memset(priv->wbuf[slot], 0, BUF_MAX_SIZE);
++ priv->wbuf[slot][0] = buf[0];
++ priv->wbuf[slot][1] = buf[1];
++ priv->wbuf[slot][2] = buf[2];
++ priv->wbuf[slot][3] = buf[3];
++ res = spi_rw(priv->spi[slot], priv->wbuf[slot], len);
++ if (res != 1) {
++ up(&priv->sem[slot]);
++ return -EFAULT;
++ }
++
++ memset(priv->rbuf[slot], 0, BUF_MAX_SIZE);
++ buf[0] = priv->wbuf[slot][2];
++ buf[1] = priv->wbuf[slot][1];
++
++ up(&priv->sem[slot]);
++
++ return res;
++}
++
++/*
++ * BMI functions
++ */
++
++static irqreturn_t module_irq_handler(int irq, void *dummy);
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp);
++
++ // probe
++int bmi_lcd_probe(struct bmi_device *bdev)
++{
++
++ unsigned char acc_data[1];
++ unsigned char iox_data[1];
++ int slot = bdev->info->slot;
++ struct i2c_adapter *adap;
++ struct bmi_lcd *lcd;
++ char buf[4];
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d\n", slot);
++
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ pbmi_lcd.bdev[0] = bdev;
++ return 0;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ pbmi_lcd.bdev[1] = bdev;
++ return 0;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ pbmi_lcd.bdev[2] = bdev;
++ return 0;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ pbmi_lcd.bdev[3] = bdev;
++ return 0;
++ }
++ break;
++ }
++
++ adap = &bdev->adap;
++ bmi_slot_power_on(slot);
++
++ // set up bdev/pbmi_lcd pointers
++ bmi_device_set_drvdata(bdev, &pbmi_lcd);
++ pbmi_lcd.bdev[slot] = bdev;
++
++ printk(KERN_INFO "Adap = 0x%x",adap);
++
++ printk(KERN_INFO "Lock stuff = 0x%x", &(pbmi_lcd.bdev[slot]->adap));
++
++ mdelay(500);
++
++ // configure IOX
++ // [7:6]=interrupts, [5]=SER_PD*, [4]=LCD_RST*, [3]=VSYNC_OE*, [2]=ACC_RST*, [1:0]=backlight
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, 0xFF)) // normal - no accelerometer interrupts
++ return -ENODEV;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, 0xFF, slot)) // normal - no accelerometer interrupts
++ return -ENODEV;
++
++ // normal operation - no accelerometer interrupts
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_CONTROL, 0x00, slot)) // IOX[7:0]=OUT
++ return -ENODEV;
++
++ // clear interrupts
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_INPUT_REG, iox_data, slot))
++ return -ENODEV;
++
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d iox data = %x\n", slot, *iox_data);
++
++
++ // accelerometer
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x\n", slot, bdev->epraw.revision_msb);
++
++ // check for PCB revision >= 1.2
++ if(bdev->epraw.revision_msb >= 0x12)
++ {
++
++ // normal IOX operation - accelerometer interrupts
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_CONTROL, 0xC0, slot)) // IOX[7:6]=IN, IOX[5:0]=OUT
++ return -ENODEV;
++
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, 0xFB, slot)) // reset OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, 0xFF, slot)) // enable OKI accelerometer
++ return -ENODEV;
++
++ mdelay(2);
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_PAGESEL, *acc_data, slot))
++ return -ENODEV;
++
++ // read device to verify existance
++ if(ReadByteLock_ACC(&pbmi_lcd, ACC_CPURDY, acc_data, slot))
++ return -ENODEV;
++
++ // set TMD = 0x300 (~250 ms)
++ *acc_data = 0x5;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_TMDH, *acc_data, slot))
++ return -ENODEV;
++
++ *acc_data = 0x0;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_TMDL, *acc_data, slot))
++ return -ENODEV;
++
++ // set INTOTM
++ *acc_data = 0x00;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_INTOTM, *acc_data, slot))
++ return -ENODEV;
++
++ // set GxAVE
++ *acc_data = 0x0;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_GAAVE, *acc_data, slot))
++ return -ENODEV;
++
++ // set GDTCT[01]
++ *acc_data = 0x00;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_GDTCT0L, *acc_data, slot))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_GDTCT0H, *acc_data, slot))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_GDTCT1L, *acc_data, slot))
++ return -ENODEV;
++
++ *acc_data = 0x00;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_GDTCT1H, *acc_data, slot))
++ return -ENODEV;
++
++ // set MODE0
++ *acc_data = ACC_MODE0_PDOFF | ACC_MODE0_TMPOFF | ACC_MODE0_AGCON | ACC_MODE0_MAUTO | ACC_MODE0_GDET10;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_MODE0, *acc_data, slot))
++ return -ENODEV;
++
++ // set CFG
++ *acc_data = ACC_CFG_REGMD | ACC_CFG_INTLVL;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_CFG, *acc_data, slot))
++ return -ENODEV;
++
++ // set INTMSK
++ *acc_data = 0xFE;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_INTMSK, *acc_data, slot))
++ return -ENODEV;
++
++ // set CTRL0
++ *acc_data = ACC_CTRL0_CGAUTO;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_CTRL0, *acc_data, slot))
++ return -ENODEV;
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByteLock_ACC(&pbmi_lcd, ACC_PAGESEL, *acc_data, slot))
++ return -ENODEV;
++
++ acc_probe(&pbmi_lcd.acc[slot], slot);
++ }
++ else
++ {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d hardware version = 0x%x (accelerometer not supported)\n", slot, bdev->epraw.revision_msb);
++ }
++
++ // reset serial link (master)
++ if((slot == 0) || (slot == 2))
++ {
++ bmi_lcd_inactive(0);
++ }
++ else
++ {
++ bmi_lcd_inactive(1);
++ }
++
++ // configure GPIO
++ // turn LED's on
++ bmi_set_module_gpio_data(slot, 3, 0); // Red LED=ON
++ bmi_set_module_gpio_data(slot, 2, 0); // Green LED=ON
++
++ // assert reset
++ bmi_set_module_gpio_data(slot, 1, 0); // RST=0
++
++ // set GPIO direction
++ bmi_set_module_gpio_dir(slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_dir(slot, 0, BMI_GPIO_IN); // real-time pen int state
++
++ mdelay(200);
++
++ // turn LED's off
++ bmi_set_module_gpio_data(slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data(slot, 2, 1); // Green LED=OFF
++
++ // deassert reset (module)
++ bmi_set_module_gpio_data(slot, 1, 1); // RST=1
++
++ mdelay(500);
++
++ // unreset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_active(0, 0x0, LCD_MODE_I80);
++ } else {
++ mdelay(2);
++ bmi_lcd_active(1, 0x0, LCD_MODE_I80);
++ }
++
++
++
++
++ // spi set-up
++ if (bmi_device_spi_setup(bdev, 2000000, SPI_MODE_2, 32)) {
++ printk(KERN_ERR "bmi_lcd.c: Unable to setup spi%d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++ bmi_slot_spi_enable(slot);
++ pbmi_lcd.spi[slot] = bmi_device_get_spi(bdev);
++
++
++ // check spi access and enable touch screen
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ if(spi_lcd_write_reg(&pbmi_lcd, buf, 1, slot) != 1) {
++ printk(KERN_WARNING "bmi_lcd.c: Unable set-up spi for bmi_lcd %d\n", slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_spi_disable(slot);
++ bmi_slot_power_off(slot);
++ return -EFAULT;
++ }
++
++
++ // complete pbmi_lcd set-up
++ pbmi_lcd.lcd_cnt++;
++ pbmi_lcd.active = 1;
++ pbmi_lcd.activated[slot] = 1;
++
++
++ mdelay(100);
++
++ lcd = pbmi_lcd.blcd[slot];
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_config(lcd, 0);
++ mdelay(2);
++ } else {
++ mdelay(2);
++ bmi_lcd_config(lcd, 1);
++ mdelay(2);
++ }
++
++
++ // request input event interrupt handler
++ pbmi_lcd.interrupt[0] = M1_IRQ;
++ pbmi_lcd.interrupt[1] = M2_IRQ;
++ pbmi_lcd.interrupt[2] = M3_IRQ;
++ pbmi_lcd.interrupt[3] = M4_IRQ;
++ snprintf(pbmi_lcd.int_name, sizeof(pbmi_lcd.int_name), "bmi_lcd%d", slot);
++ if (request_irq(pbmi_lcd.interrupt[slot], &module_irq_handler, 0, pbmi_lcd.int_name, &pbmi_lcd))
++ {
++ printk( KERN_ERR "bmi_lcd.c: Can't allocate irq %d or find lcd in slot %d\n", pbmi_lcd.interrupt[slot], slot);
++ bmi_device_set_drvdata(bdev, NULL);
++ pbmi_lcd.bdev[slot] = NULL;
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_device_spi_cleanup(bdev);
++ bmi_slot_power_off(slot);
++ return -EBUSY;
++ }
++
++ // check GPIO status
++ printk(KERN_INFO "bmi_lcd.c: slot %d gpio = %x\n", slot, bmi_read_gpio_data_reg(slot));
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return 0;
++}
++
++extern struct delayed_work bmilcd_work0;
++extern struct delayed_work bmilcd_work1;
++extern struct delayed_work bmilcd_work2;
++extern struct delayed_work bmilcd_work3;
++
++ // remove
++void bmi_lcd_remove(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++
++ if(pbmi_lcd.activated[slot] == 0)
++ return;
++
++ switch(slot) {
++ case 0:
++ cancel_delayed_work(&bmilcd_work0);
++ break;
++ case 1:
++ cancel_delayed_work(&bmilcd_work1);
++ break;
++ case 2:
++ cancel_delayed_work(&bmilcd_work2);
++ break;
++ case 3:
++ cancel_delayed_work(&bmilcd_work3);
++ break;
++ }
++
++ free_irq(pbmi_lcd.interrupt[slot], &pbmi_lcd);
++
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN);
++
++ // bmi/spi clean-up
++ bmi_device_spi_cleanup(bdev);
++ pbmi_lcd.spi[slot] = NULL;
++ bmi_slot_spi_disable(slot);
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (&bdev[slot], 0);
++
++ // deactivate
++ pbmi_lcd.activated[slot] = 0;
++ pbmi_lcd.bdev[slot] = 0;
++ pbmi_lcd.lcd_cnt--;
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[2] == 0)) {
++ bmi_lcd_inactive(0); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[1] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ bmi_lcd_inactive(1); // disable serializer
++ }
++
++ if((pbmi_lcd.activated[0] == 0) && (pbmi_lcd.activated[1] == 0) &&
++ (pbmi_lcd.activated[2] == 0) && (pbmi_lcd.activated[3] == 0)) {
++ pbmi_lcd.active = -1;
++ }
++
++ // enable LCD on opposite side
++ switch(slot) {
++ case 0:
++ if(pbmi_lcd.bdev[2] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[2]);
++ break;
++ case 1:
++ if(pbmi_lcd.bdev[3] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[3]);
++ break;
++ case 2:
++ if(pbmi_lcd.bdev[0] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[0]);
++ break;
++ case 3:
++ if(pbmi_lcd.bdev[1] != 0)
++ bmi_lcd_probe(pbmi_lcd.bdev[1]);
++ break;
++ }
++
++ acc_remove(&pbmi_lcd.acc[slot], slot);
++ printk(KERN_INFO "bmi_lcd.c: LCD count = %d\n", pbmi_lcd.lcd_cnt);
++
++ return;
++}
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++static void update_pen_state(void *arg, int slot, int x, int y, int pressure)
++{
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++ int sync = 0;
++
++ if (pressure)
++ {
++ /*input_report_abs(pbmi_lcd->input_dev[slot], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_PRESSURE, pressure);
++
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_PRESSURE, pressure);*/
++
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, pressure);
++ }
++ else
++ {
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_Y, y);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_X, x);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, pressure);
++ }
++
++ if (!pbmi_lcd->pen_down[slot])
++ {
++ /*input_report_key(pbmi_lcd->input_dev[slot], BTN_TOUCH, 1);
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M1234], BTN_TOUCH, 1);*/
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 1);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 1);
++ }
++
++ }
++ sync = 1;
++ }
++ else if (pbmi_lcd->pen_down[slot])
++ {
++ /*input_report_key(pbmi_lcd->input_dev[slot], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_PRESSURE, 0);
++
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M1234], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M1234], ABS_PRESSURE, 0); */
++
++ if((slot == 0) || (slot == 2))
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M13], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M13], ABS_PRESSURE, 0);
++ }
++ else
++ {
++ input_report_key(pbmi_lcd->input_dev[BMI_TS_M24], BTN_TOUCH, 0);
++ input_report_abs(pbmi_lcd->input_dev[BMI_TS_M24], ABS_PRESSURE, 0);
++ }
++ sync = 1;
++ }
++
++ if (sync)
++ {
++ /*input_sync(pbmi_lcd->input_dev[slot]);
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M1234]);*/
++ if((slot == 0) || (slot == 2))
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M13]);
++ }
++ else
++ {
++ input_sync(pbmi_lcd->input_dev[BMI_TS_M24]);
++ }
++ }
++ pbmi_lcd->pen_down[slot] = pressure ? 1 : 0;
++
++}
++
++
++void bmilcd_input_work(void *arg, int slot);
++
++void bmilcd_input_work0(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 0);
++}
++
++void bmilcd_input_work1(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 1);
++}
++
++void bmilcd_input_work2(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 2);
++}
++
++void bmilcd_input_work3(struct work_struct * work) {
++ bmilcd_input_work(&pbmi_lcd, 3);
++}
++
++DECLARE_DELAYED_WORK(bmilcd_work0, bmilcd_input_work0);
++DECLARE_DELAYED_WORK(bmilcd_work1, bmilcd_input_work1);
++DECLARE_DELAYED_WORK(bmilcd_work2, bmilcd_input_work2);
++DECLARE_DELAYED_WORK(bmilcd_work3, bmilcd_input_work3);
++
++// work handler
++void bmilcd_input_work(void *arg, int slot) {
++ struct pbmi_lcd *pbmi_lcd = (struct pbmi_lcd *)arg;
++ struct i2c_adapter *adap = &pbmi_lcd->bdev[slot]->adap;
++ unsigned char acc_data[1];
++ static int pitch = 0;
++ static int roll = 0;
++ static int gx = 0;
++ static int gy = 0;
++
++ unsigned char iox_data[1];
++
++ unsigned char buf[4];
++ int x = 0;
++ int y = 0;
++ int z1 = 0;
++ int z2 = 0;
++ int pressure = 0;
++ int debounce;
++ int penirq;
++
++#if defined DEBUG
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d)\n", slot);
++#endif
++
++ if(pbmi_lcd->bdev[slot] == 0) {
++ printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work called with no bdev active (slot %d)\n", slot);
++ return;
++ }
++
++ if(pbmi_lcd->bdev[slot]->epraw.revision_msb >= 0x12) {
++
++ // orientation
++ // read ROLL
++ printk(KERN_INFO "ACC Work: ROLLH\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_ROLLH, acc_data, slot))
++ return;
++ roll = (0x0000 | *acc_data) << 8;
++ printk(KERN_INFO "ACC Work: ROLLL\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_ROLLL, acc_data, slot))
++ return;
++ roll = roll | *acc_data;
++ // read PITCH
++ printk(KERN_INFO "ACC Work: PITCHH\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_PITCHH, acc_data, slot))
++ return;
++ pitch = (0x0000 | *acc_data) << 8;
++ printk(KERN_INFO "ACC Work: PITCHL\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_PITCHL, acc_data, slot))
++ return;
++ pitch = pitch | *acc_data;
++
++
++
++ printk(KERN_INFO "ACC Work: GAZH\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAZH, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[0] = *acc_data;
++ printk(KERN_INFO "ACC Work: GAZL\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAZL, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[1] = *acc_data;
++ printk(KERN_INFO "ACC Work: GAYH\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAYH, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[2] = *acc_data;
++ gy = *acc_data << 8;
++ printk(KERN_INFO "ACC Work: GAYL\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAYL, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[3] = *acc_data;
++ gy = gy | *acc_data;
++ printk(KERN_INFO "ACC Work: GAXH\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAXH, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[4] = *acc_data;
++ gx = *acc_data << 8;
++ printk(KERN_INFO "ACC Work: GAXL\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_GAXL, acc_data, slot))
++ return;
++ pbmi_lcd->acc[slot].sample[5] = *acc_data;
++ gx = gx | *acc_data;
++
++ //wake up any read's
++ pbmi_lcd->acc[slot].flag = 1;
++ wake_up_interruptible(&pbmi_lcd->acc[slot].wq);
++
++ if(ReadByteLock_IOX(pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return;
++ *iox_data = (*iox_data & 0xF8) | 0x4;
++ if(WriteByteLock_IOX(pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return;
++ printk(KERN_INFO "ACC Work: IOX\n");
++
++ // read STATUS
++ printk(KERN_INFO "ACC Work: STATUS\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_STATUS, acc_data, slot))
++ return;
++
++ if((*acc_data & 0x1) == 0) {
++
++ // write PAGESEL
++ *acc_data = 0x0;
++ if(WriteByteLock_ACC(pbmi_lcd, ACC_PAGESEL, *acc_data, slot))
++ return;
++
++ // read INTRQ
++ printk(KERN_INFO "ACC Work: INTRQ\n");
++ if(ReadByteLock_ACC(pbmi_lcd, ACC_INTRQ, acc_data, slot))
++ return;
++ }
++
++ // write PAGESEL
++ *acc_data = 0x1;
++ if(WriteByteLock_ACC(pbmi_lcd, ACC_PAGESEL, *acc_data, slot))
++ return;
++
++
++
++ // report orientation
++ // printk(KERN_INFO "bmi_lcd.c: bmi_lcd_input work (slot %d) pitch=0x%x, roll=0x%x, ABS_MISC=0x%x\n",
++ // slot, pitch, roll, pitch << 16 | roll); //pjg - debug
++
++ input_report_abs(pbmi_lcd->input_dev[slot], ABS_MISC, (pitch << 16) | roll);
++ input_sync(pbmi_lcd->input_dev[slot]);
++ }
++
++ // read touch screen - X, Y, TOUCH, PRESSURE
++
++
++ penirq = bmi_slot_status_irq_state(slot);
++ /*printk(KERN_INFO "bmi_lcd.c: IRQ Status %d (slot %d) %d\n", penirq, slot,msecs_to_jiffies(10));*/
++
++ if (pbmi_lcd->activated[slot] && penirq)
++ {
++
++ for(debounce = 0; debounce < DEBOUNCE; debounce++)
++ {
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AY | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ y = (((buf[0] << 5) | buf[1] >> 3)) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AX | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ x = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ1 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z1 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_AZ2 | SPI_MODE_12 | SPI_MODE_DFR | SPI_ADC;
++ spi_lcd_read_reg(pbmi_lcd, buf, 1, slot);
++ z2 = (((buf[0] << 5) | buf[1]) >> 3) & 0xFFF;
++ mdelay(1);
++ }
++
++ if(x && y && z1 && z2)
++ pressure = (X_PLATE * x / 4096) * ((z2 / z1) - 1);
++
++ x = 4096 - x;
++ y = 4096 - y;
++
++ if (pressure < 70)
++ {
++ if (pbmi_lcd->scount)
++ update_pen_state(arg, slot, x, y, pressure);
++ else
++ {
++ pbmi_lcd->scount[slot]++;
++ /*update_pen_state(arg, slot, 0, 0, pressure);*/
++ }
++ }
++ /* else
++ {
++ update_pen_state(arg, slot, 0, 0, pressure);
++ }*/
++
++ switch(slot)
++ {
++ case BMI_TS_M1:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ break;
++ case BMI_TS_M2:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ break;
++ case BMI_TS_M3:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ break;
++ case BMI_TS_M4:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ break;
++ }
++ /* printk(KERN_INFO "bmi_lcd.c: work scheduled on (slot %d)\n", slot); */
++ /*buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);*/
++ }
++
++ else
++ {
++ /*printk(KERN_INFO "bmi_lcd.c: Pen up on (slot %d)\n", slot);*/
++ memset(buf, 0, 4);
++ buf[3] = SPI_START | SPI_PD;
++ spi_lcd_write_reg(pbmi_lcd, buf, 1, slot);
++ update_pen_state(arg,slot, 0, 0, 0);
++ enable_irq(pbmi_lcd->interrupt[slot]);
++ }
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ disable_irq(irq);
++ /*printk(KERN_INFO "bmi_lcd.c: Interupt on (slot %d)\n", irq);*/
++ switch(irq)
++ {
++ case M1_IRQ:
++ schedule_delayed_work(&bmilcd_work0, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M1] = 0;
++ break;
++ case M2_IRQ:
++ schedule_delayed_work(&bmilcd_work1, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M2] = 0;
++ break;
++ case M3_IRQ:
++ schedule_delayed_work(&bmilcd_work2, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M3] = 0;
++ break;
++ case M4_IRQ:
++ schedule_delayed_work(&bmilcd_work3, WORK_DELAY);
++ pbmi_lcd.scount[BMI_TS_M4] = 0;
++ break;
++ }
++ return IRQ_HANDLED;
++}
++
++/*
++ * control device operations
++ */
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *filp)
++{
++ if(pbmi_lcd.open_flag) {
++ return - EBUSY;
++ }
++ pbmi_lcd.open_flag = 1;
++ filp->private_data = &pbmi_lcd;
++ return 0;
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *filp)
++{
++ pbmi_lcd.open_flag = 0;
++ return 0;
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data[1];
++ int slot = (__user arg) & 0xF;
++ int bl = ((__user arg) & 0x70) >> 4;
++
++ // error if no lcd active.
++ if(pbmi_lcd.active == -1)
++ return -ENODEV;
++
++ if(cmd != BMI_LCD_GETSTAT) {
++
++ // error if slot invalid
++ if((slot < CPLD_M1) || (slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[slot]->adap;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ case BMI_LCD_RLEDOFF:
++ bmi_set_module_gpio_data(slot, 3, 1);// Red LED=OFF
++ break;
++ case BMI_LCD_RLEDON:
++ bmi_set_module_gpio_data(slot, 3, 0);// Red LED=ON
++ break;
++ case BMI_LCD_GLEDOFF:
++ bmi_set_module_gpio_data(slot, 2, 1);// Green LED=OFF
++ break;
++ case BMI_LCD_GLEDON:
++ bmi_set_module_gpio_data(slot, 2, 0);// Green LED=ON
++ break;
++ case BMI_LCD_VSYNC_DIS: // enable VSYNC buffer tristate output
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data |= 0x08;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_VSYNC_EN: // disable VSYNC buffer tristate output
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data &= ~0x08;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_EN: // enable LCD component
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data &= ~0x10;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_DIS: // disable LCD component only
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data |= 0x10;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_EN: // enable Serializer component
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data &= ~0x20;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_DIS: // disable Serializer component only
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data |= 0x20;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SETRST: // overall module reset
++ bmi_set_module_gpio_data (slot, 1, 0); // RST=0
++ break;
++ case BMI_LCD_CLRRST: // overall module enable
++ bmi_set_module_gpio_data (slot, 1, 1); // RST=1
++ break;
++ case BMI_LCD_SET_BL: // set backlight brightness
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8) | bl;
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ break;
++ case BMI_LCD_GETSTAT:
++ {
++ int *slot = ((int __user *) arg);
++ int read_data;
++
++ *slot &= 0xF;
++
++ // error if slot invalid
++ if((*slot < CPLD_M1) || (*slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[*slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[*slot]->adap;
++
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_INPUT_REG, iox_data, *slot))
++ return -ENODEV;
++
++ read_data = *iox_data | (bmi_read_gpio_data_reg(*slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++ case BMI_LCD_ACTIVATE: //pjg fix/test
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ return -ENODEV;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ return -ENODEV;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ return -ENODEV;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ return -ENODEV;
++ }
++ break;
++ }
++ // activate
++ if((!pbmi_lcd.activated[slot]) && (pbmi_lcd.bdev[slot] != 0)) {
++ bmi_lcd_probe(pbmi_lcd.bdev[slot]);
++ }
++ break;
++ case BMI_LCD_DEACTIVATE:
++ if(pbmi_lcd.activated[slot]) {
++ disable_irq_nosync(pbmi_lcd.interrupt[slot]);
++ pbmi_lcd.activated[slot] = 0;
++ if(ReadByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, iox_data, slot))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8);
++ if(WriteByteLock_IOX(&pbmi_lcd, IOX_OUTPUT_REG, *iox_data, slot))
++ return -ENODEV;
++ bmi_slot_power_off(slot);
++ }
++ break;
++ case BMI_LCD_SUSPEND:
++ printk(KERN_ERR "BMI_LCD_SUSPEND NOT IMPLEMENTED\n"); //pjg
++ break;
++ case BMI_LCD_RESUME:
++ printk(KERN_ERR "BMI_LCD_RESUME NOT IMPLEMENTED\n"); //pjg
++ break;
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++ // control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++ // BMI LCD fops
++void bmi_lcd_config(struct bmi_lcd *lcd, int disp)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.config)) {
++ lcd->lcd_ops.config(disp);
++ }
++}
++
++void bmi_lcd_reset(struct bmi_lcd *lcd, int slot)
++{
++ if(pbmi_lcd.active == -1) {
++ return;
++ }
++
++ if((lcd) && (lcd->lcd_ops.reset)) {
++ lcd->lcd_ops.reset(slot);
++ }
++}
++
++
++static struct miscdevice cntl_dev = {
++ MISC_DYNAMIC_MINOR,
++ "bmi_lcd_control",
++ &cntl_fops
++};
++
++/*
++ * Module functions
++ */
++
++char const input_name0[MAX_STRG] = "bmi_lcd_ts0";
++char const input_name1[MAX_STRG] = "bmi_lcd_ts1";
++char const input_name2[MAX_STRG] = "bmi_lcd_ts2";
++char const input_name3[MAX_STRG] = "bmi_lcd_ts3";
++char const input_name4[MAX_STRG] = "bmi_lcd_ts4";
++char const input_name5[MAX_STRG] = "bmi_lcd_ts5";
++char const input_name6[MAX_STRG] = "bmi_lcd_ts6";
++
++static __init int bmi_lcd_init(void)
++{
++ int ts;
++ int rc = 0;
++
++ // No lcd is active.
++ pbmi_lcd.active = -1;
++ pbmi_lcd.activated[0] = 0;
++ pbmi_lcd.activated[1] = 0;
++ pbmi_lcd.activated[2] = 0;
++ pbmi_lcd.activated[3] = 0;
++
++ // set up control character device - bmi_lcd_control
++ rc = misc_register(&cntl_dev);
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't allocate bmi_lcd_control device\n");
++ return rc;
++ }
++
++ // Allocate and Register input device. - bmi_lcd_ts[BMI_TS_M1:BMI_TS_M1234]
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++) {
++ pbmi_lcd.input_dev[ts] = input_allocate_device();
++ if(!pbmi_lcd.input_dev[ts]) {
++ printk(KERN_ERR "bmi_lcd_init: Can't allocate input_dev[ts]\n");
++ return -ENOMEM;
++ }
++
++ // set up input device
++ switch(ts) {
++ case BMI_TS_M1:
++ pbmi_lcd.input_dev[BMI_TS_M1]->name = input_name0;
++ pbmi_lcd.input_dev[BMI_TS_M1]->phys = input_name0;
++ break;
++ case BMI_TS_M2:
++ pbmi_lcd.input_dev[BMI_TS_M2]->name = input_name1;
++ pbmi_lcd.input_dev[BMI_TS_M2]->phys = input_name1;
++ break;
++ case BMI_TS_M3:
++ pbmi_lcd.input_dev[BMI_TS_M3]->name = input_name2;
++ pbmi_lcd.input_dev[BMI_TS_M3]->phys = input_name2;
++ break;
++ case BMI_TS_M4:
++ pbmi_lcd.input_dev[BMI_TS_M4]->name = input_name3;
++ pbmi_lcd.input_dev[BMI_TS_M4]->phys = input_name3;
++ break;
++ case BMI_TS_M13:
++ pbmi_lcd.input_dev[BMI_TS_M13]->name = input_name4;
++ pbmi_lcd.input_dev[BMI_TS_M13]->phys = input_name4;
++ break;
++ case BMI_TS_M24:
++ pbmi_lcd.input_dev[BMI_TS_M24]->name = input_name5;
++ pbmi_lcd.input_dev[BMI_TS_M24]->phys = input_name5;
++ break;
++ case BMI_TS_M1234:
++ pbmi_lcd.input_dev[BMI_TS_M1234]->name = input_name6;
++ pbmi_lcd.input_dev[BMI_TS_M1234]->phys = input_name6;
++ break;
++ }
++ pbmi_lcd.input_dev[ts]->id.bustype = BUS_BMI;
++ pbmi_lcd.input_dev[ts]->private = &pbmi_lcd;
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
++ pbmi_lcd.input_dev[ts]->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
++ pbmi_lcd.input_dev[ts]->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_X)] |= BIT_MASK(ABS_X);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_Y)] |= BIT_MASK(ABS_Y);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_PRESSURE)] |= BIT_MASK(ABS_PRESSURE);
++ pbmi_lcd.input_dev[ts]->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_X, BMI_LCD_MIN_XC, BMI_LCD_MAX_XC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_Y, BMI_LCD_MIN_YC, BMI_LCD_MAX_YC, 0, 0);
++ input_set_abs_params(pbmi_lcd.input_dev[ts], ABS_PRESSURE, 0, 1024, 0, 0);
++
++ // register input device
++ if(input_register_device(pbmi_lcd.input_dev[ts])) {
++ int tts;
++ printk(KERN_ERR "bmi_lcd_init() - input_register_device failed.\n");
++
++ for(tts = BMI_TS_M1; tts < ts; tts++)
++ input_unregister_device(pbmi_lcd.input_dev[tts]);
++
++ misc_deregister(&cntl_dev);
++
++ return -ENODEV;
++ }
++ }
++
++ pbmi_lcd.lcd_cnt = 0;
++
++ // hardware specfic set-up
++ s320x240_bmi_lcd.interface = s320x240_lcd_interface,
++ s320x240_bmi_lcd_ops.config = (void(*)) &s320x240_config;
++ s320x240_bmi_lcd_ops.reset = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.suspend = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.resume = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_on = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.disp_off = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.activate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd_ops.deactivate = NULL; //pjg - placeholder for multiple LCD hardware types
++ s320x240_bmi_lcd.lcd_ops = s320x240_bmi_lcd_ops;
++ pbmi_lcd.blcd[0] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[1] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[2] = &s320x240_bmi_lcd;
++ pbmi_lcd.blcd[3] = &s320x240_bmi_lcd;
++
++ sema_init(&pbmi_lcd.sem[0], 1);
++ sema_init(&pbmi_lcd.sem[1], 1);
++ sema_init(&pbmi_lcd.sem[2], 1);
++ sema_init(&pbmi_lcd.sem[3], 1);
++
++ sema_init(&pbmi_lcd.i2c_sem[0], 1);
++ sema_init(&pbmi_lcd.i2c_sem[1], 1);
++ sema_init(&pbmi_lcd.i2c_sem[2], 1);
++ sema_init(&pbmi_lcd.i2c_sem[3], 1);
++
++ acc_init();
++
++ /*s320x240_config(0);
++ s320x240_config(1);*/
++
++ // register with BMI
++ rc = bmi_register_driver(&bmi_lcd_driver);
++ if(rc) {
++ printk(KERN_ERR "bmi_lcd.c: Can't register bmi_lcd_driver\n");
++
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ misc_deregister(&cntl_dev);
++
++ return rc;
++ }
++
++ printk("bmi_lcd.c: BMI_LCD Driver v%s \n", BMILCD_VERSION);
++
++ return 0;
++}
++
++static void __exit bmi_lcd_clean(void)
++{
++ int ts;
++
++ // delete timers
++ del_timer(&pbmi_lcd.timer[0]);
++ del_timer(&pbmi_lcd.timer[1]);
++ del_timer(&pbmi_lcd.timer[2]);
++ del_timer(&pbmi_lcd.timer[3]);
++
++ // remove input devices
++ for(ts = BMI_TS_M1; ts < BMI_TS_NUM; ts++)
++ input_unregister_device(pbmi_lcd.input_dev[ts]);
++
++ // remove control device
++ misc_deregister(&cntl_dev);
++
++ // remove bmi driver
++ bmi_unregister_driver(&bmi_lcd_driver);
++
++ acc_clean();
++
++ return;
++}
++
++module_init(bmi_lcd_init);
++module_exit(bmi_lcd_clean);
++
++
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BMI lcd device driver");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_control");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_ts");
++MODULE_SUPPORTED_DEVICE("bmi_lcd_acc");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/bmi_s320x240.c
+@@ -0,0 +1,632 @@
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_camera.h> //pjg
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/workqueue.h>
++#include "bug_lcd.h"
++
++// BMI device ID table
++static struct bmi_device_id bmi_vs6624_tbl[] =
++{
++ { //pjg .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .match_flags = BMI_ANY,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_CAMERA_VS6624,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_vs6624_tbl);
++
++int bmi_vs6624_probe(struct bmi_device *bdev);
++void bmi_vs6624_remove(struct bmi_device *bdev);
++int bmi_vs6624_suspend(struct bmi_device *bdev);
++int bmi_vs6624_resume(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_vs6624_driver =
++{
++ .name = "bmi_vs6624",
++ .id_table = bmi_vs6624_tbl,
++ .probe = bmi_vs6624_probe,
++ .remove = bmi_vs6624_remove,
++ };
++
++
++struct bmi_vs6624 {
++ struct bmi_device *bdev;
++ struct bmi_cam bcam;
++ unsigned int shutter; // shutter button save state
++ unsigned int zoomin; // zoomin button save state
++ unsigned int zoomout; // zoom out button save state
++ unsigned int flash; // state of camera FLASH
++ int irq;
++ struct input_dev *idev;
++ struct work_struct work;
++
++};
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++
++// read byte from I2C IO expander
++
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ //Rework: add conditional debug messages here
++ ret = -1;
++ }
++ return ret;
++}
++
++
++// write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ //Rework: add conditional debug messages here
++
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++
++// work handler
++void bmi_vs6624_buttons_work(void *arg)
++{
++ struct bmi_vs6624 *bmicam = (struct bmi_vs6624*)arg;
++ struct i2c_adapter *adap = &bmicam->bdev->adap;
++
++ unsigned char iox_data;
++ unsigned int test_value;
++ int sync_flag = 0;
++
++
++ // read IOX data input
++ ReadByte_IOX (adap, IOX_INPUT_REG, &iox_data);
++
++ // zoom in button
++ test_value = !((iox_data & 0x2) >> 1);
++ if (test_value != bmicam->zoomin) {
++ printk (KERN_ERR "bmi_vs6624buttons_work() - report ZOOMIN\n");
++ bmicam->zoomin = test_value;
++ input_report_key(bmicam->idev, BN_ZOOMIN, test_value);
++ sync_flag = 1;
++ }
++
++
++ // zoom out button
++ test_value = !((iox_data & 0x4) >> 2);
++ if (test_value != bmicam->zoomout) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - report ZOOMOUT\n");
++ bmicam->zoomout = test_value;
++ input_report_key(bmicam->idev, BN_ZOOMOUT, test_value);
++ sync_flag = 1;
++ }
++
++ // flash button
++ test_value = (iox_data & 0x8) >> 3;
++ if (test_value != bmicam->flash) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - report FLASH\n");
++ bmicam->flash = test_value;
++ input_report_key(bmicam->idev, BN_FLASH, test_value);
++ sync_flag = 1;
++ }
++
++
++ if ( sync_flag ) {
++ printk (KERN_ERR "bmi_vs6624_buttons_work() - input_sync()ing..\n");
++ input_sync(bmicam->idev);
++ }
++
++ enable_irq(bmicam->irq);
++
++}
++
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ struct bmi_vs6624 *bmicam = dummy;
++ unsigned int test_value;
++
++ int slot;
++
++
++ disable_irq_nosync(irq);
++
++ slot = bmicam->bdev->info->slot;
++
++
++ // shutter button on GPIO
++
++ test_value = !(bmi_read_gpio_data_reg (slot) & 0x1);
++
++ if (!test_value == bmicam->shutter) {
++ bmicam->shutter = test_value;
++ printk (KERN_ERR "module_irq_handler() - report SHUTTER\n");
++ input_report_key(bmicam->idev, BN_SHUTTER, test_value);
++ input_sync(bmicam->idev);
++ }
++
++
++
++ // other buttons on I2C IOX
++ schedule_work (&bmicam->work);
++ return IRQ_HANDLED;
++}
++
++/*
++ * control functions
++ */
++
++
++// configure IOX IO and states
++void configure_IOX(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap = &cam->bdev->adap;
++
++ printk (KERN_ERR "configure_IOX() - enter\n");
++ printk (KERN_ERR "configure_IOX() - cam = %p\n", cam);
++ printk (KERN_ERR "configure_IOX() - cam->bdev = %p\n", cam->bdev);
++ printk (KERN_ERR "configure_IOX() - cam->bdev->adap = %p\n", &cam->bdev->adap);
++
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, 0x40); // CE=0, F_CHG=1,SYNC=0, TORCH=0
++ WriteByte_IOX (adap, IOX_CONTROL, 0x0F); // IOX[7:4]=OUT, IOX[3:0]=IN
++}
++
++// configure GPIO IO and states
++void configure_GPIO(struct bmi_vs6624 *cam)
++{
++ // set states before turning on outputs
++
++ int slot = cam->bdev->info->slot;
++
++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF
++ bmi_set_module_gpio_data (slot, 2, 1); // Green LED=OFF
++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0
++
++ // configure direction
++ bmi_set_module_gpio_data (slot, 3, BMI_GPIO_OUT);
++ bmi_set_module_gpio_data (slot, 2, BMI_GPIO_OUT);
++ bmi_set_module_gpio_data (slot, 1, BMI_GPIO_OUT);
++ bmi_set_module_gpio_data (slot, 0, BMI_GPIO_IN); // SHUTTER
++}
++
++// deconfigure IOX and GPIO
++void deconfigure_module(struct bmi_vs6624 *cam)
++{
++ int slot = cam->bdev->info->slot;
++ struct i2c_adapter *adap = &cam->bdev->adap;
++
++ WriteByte_IOX (adap, IOX_CONTROL, 0xFF);
++ bmi_set_module_gpio_data (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_data (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_data (slot, 1, BMI_GPIO_IN);
++}
++
++
++// configure serializer on plug-in module
++void configure_serializer(struct bmi_vs6624 *cam)
++{
++ int slot = cam->bdev->info->slot;
++
++ bmi_set_module_gpio_data(slot, 1, 1); // SER_RST=1
++}
++
++void deconfigure_serializer(struct bmi_vs6624 *cam)
++{
++ int slot = cam->bdev->info->slot;
++ bmi_set_module_gpio_data(slot, 1, 0); // SER_RST=0
++}
++
++void enable_camera(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap = &cam->bdev->adap;
++ unsigned char iox_data;
++
++ printk (KERN_ERR "enable_camera() enter\n");
++
++ // The first i2c read seems to mess everything up.
++
++ ReadByte_IOX(adap, IOX_OUTPUT_REG, &iox_data);
++ printk (KERN_ERR "enable_camera() iox_data = %02X\n", iox_data);
++
++ WriteByte_IOX(adap, IOX_OUTPUT_REG, iox_data | 0x80);
++ printk (KERN_ERR "enable_camera() exit\n");
++}
++
++// disable camera on plug-in module
++void disable_camera(struct bmi_vs6624 *cam)
++{
++ struct i2c_adapter *adap = &cam->bdev->adap;
++ unsigned char iox_data;
++
++ printk (KERN_ERR "disable_camera() enter\n");
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data & 0x70);
++
++ printk (KERN_ERR "disable_camera() exit\n");
++}
++
++// generate sync
++void generate_camera_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "generate_camera_sync() - enter\n");
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++
++ printk(KERN_INFO "generate_camera_sync() - read = %02X\n", iox_data[0]);
++ printk(KERN_INFO "generate_camera_sync() - write = %02X\n", *iox_data | 0x20);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++
++ printk(KERN_INFO "generate_camera_sync() - write = %02X\n", *iox_data & 0xD0);
++
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++ udelay(20); // 60 MHz * 1024 = ~17 us sync time
++
++ printk(KERN_INFO "generate_camera_sync() - exit\n");
++}
++
++void set_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "set_sync() - enter\n");
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1
++
++ printk(KERN_INFO "set_sync() - exit\n");
++}
++
++void clear_sync(struct i2c_adapter *adap)
++{
++ unsigned char iox_data[0];
++
++ printk(KERN_INFO "clear_sync() - enter\n");
++
++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data);
++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0
++
++ printk(KERN_INFO "clear_sync() - exit\n");
++}
++
++
++// check serializer lock
++int check_camera_lock(void)
++{
++ return bmi_sensor_lock_status();
++}
++
++void bmi_vs6624_set_color(struct bmi_cam *cam, int bright, int saturation, int red, int green, int blue)
++{
++
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ adap = &bmi_vs6624->bdev->adap;
++
++ vs6624_set_color (adap, bright, saturation, red, green, blue);
++ return;
++
++}
++
++void bmi_vs6624_get_color(struct bmi_cam *cam, int *bright, int *saturation, int *red, int *green, int *blue)
++{
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++ adap = &bmi_vs6624->bdev->adap;
++
++ vs6624_get_color (adap, bright, saturation, red, green, blue);
++ return;
++}
++
++
++
++
++void bmi_vs6624_set_ae_mode (struct bmi_cam *cam, int ae_mode)
++{
++ printk (KERN_ERR "bmi_vs6624_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++void bmi_vs6624_get_ae_mode (struct bmi_cam *cam, int *ae_mode)
++{
++ printk (KERN_ERR "bmi_vs6624_set_ae_mode() - NOT IMPLEMENTED.\n");
++}
++
++
++sensor_interface * bmi_vs6624_config (struct bmi_cam *cam, int *frame_rate, int high_quality)
++{
++ //REWORK: Add code here
++ return 0;
++
++}
++
++
++sensor_interface * bmi_vs6624_reset (struct bmi_cam *cam)
++{
++ //REWORK: Add code here
++ //REWORK: What is a valid soft reset sequence ?
++ return 0;
++}
++
++int bmi_vs6624_activate (struct bmi_cam *cam, struct input_dev *idev)
++{
++ //REWORK: Add code here
++ int rc = 0;
++ int i;
++ struct i2c_adapter *adap;
++ struct bmi_vs6624 *bmi_vs6624;
++
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ //bmi_vs6624 struct fields
++ bmi_vs6624->shutter = 0;
++ bmi_vs6624->zoomin = 0;
++ bmi_vs6624->zoomout = 0;
++ bmi_vs6624->flash = 0;
++
++ // install button irq_handler
++ if (request_irq(bmi_vs6624->irq, &module_irq_handler, 0, "bmi_cam_button", bmi_vs6624)) {
++ printk( KERN_ERR
++ "bmi_vs6624_activate() Can't allocate irq %d\n",
++ bmi_vs6624->irq
++ );
++
++ rc = -EBUSY;
++ goto exit;
++ }
++
++ //Activate serial link
++ bmi_sensor_active(0); // rising edge clock
++ bmi_sensor_active(1); // rising edge clock
++ configure_serializer (bmi_vs6624);
++
++ adap = &bmi_vs6624->bdev->adap;
++ set_sync (adap);
++
++ for (i = 0; i < 10; i++) {
++
++ msleep(10);
++
++ if(check_camera_lock()) {
++ printk(KERN_INFO "vs6624.c: camera serializer locked, i = %d\n", i);
++ break;
++ }
++ else {
++ printk(KERN_ERR "vs6624.c: camera serializer did not lock,i = %d\n", i);
++ }
++
++ }
++ clear_sync (adap);
++
++
++exit:
++ return rc;
++}
++int bmi_vs6624_deactivate (struct bmi_cam *cam)
++{
++ //REWORK: Add code here
++ struct bmi_vs6624 *bmi_vs6624;
++ bmi_vs6624 = container_of(cam, struct bmi_vs6624, bcam);
++
++
++ //De-activate serial link
++ deconfigure_serializer (bmi_vs6624);
++
++
++ //uninstall button irq_handler
++
++ free_irq(bmi_vs6624->irq, bmi_vs6624);
++
++
++ return 0;
++}
++
++int bmi_vs6624_probe(struct bmi_device *bdev)
++{
++
++ //REWORK: Add code here
++
++ int slot = bdev->info->slot;
++
++
++ // allocate a driver-specific <this> structure
++
++ struct bmi_vs6624 *bmi_vs6624 = kzalloc(sizeof(struct bmi_vs6624), GFP_KERNEL);
++ if (!bmi_vs6624) {
++ return -1;
++ }
++
++ // attach <this> bmi_device structure (so we can find it later).
++
++ bmi_device_set_drvdata(bdev, bmi_vs6624);
++
++
++
++ // initialize bmi_vs6624 struct
++
++ bmi_vs6624->bdev = bdev;
++
++ // sensor interface struct fields
++
++ bmi_vs6624->bcam.interface.clk_mode = 0; // gated
++ bmi_vs6624->bcam.interface.ext_vsync = 1; // external vsync
++ bmi_vs6624->bcam.interface.Vsync_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.Hsync_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.pixclk_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.data_pol = 0; // non-inverted
++ bmi_vs6624->bcam.interface.data_width = 1; // 8-bits
++ bmi_vs6624->bcam.interface.width = 1280-1; // 1280 - SXGA
++ bmi_vs6624->bcam.interface.height = 1024-1; // 1024 - SXGA
++ bmi_vs6624->bcam.interface.pixel_fmt = IPU_PIX_FMT_UYVY; // YUV422
++ bmi_vs6624->bcam.interface.mclk = 12000000; // frequency/src
++
++ //bmi_camera_sensor struct fields
++
++ bmi_vs6624->bcam.sensor.set_color = bmi_vs6624_set_color;
++ bmi_vs6624->bcam.sensor.get_color = bmi_vs6624_get_color;
++ bmi_vs6624->bcam.sensor.set_ae_mode = bmi_vs6624_set_ae_mode;
++ bmi_vs6624->bcam.sensor.get_ae_mode = bmi_vs6624_get_ae_mode;
++ bmi_vs6624->bcam.sensor.config = bmi_vs6624_config;
++ bmi_vs6624->bcam.sensor.reset = bmi_vs6624_reset;
++
++ //bmi_cam struct fields
++
++ bmi_vs6624->bcam.activate = bmi_vs6624_activate ;
++ bmi_vs6624->bcam.deactivate = bmi_vs6624_deactivate;
++
++ //bmi_vs6624 struct fields
++ bmi_vs6624->shutter = 0;
++ bmi_vs6624->zoomin = 0;
++ bmi_vs6624->zoomout = 0;
++ bmi_vs6624->flash = 0;
++
++ //initialize struct work_struct
++ PREPARE_WORK (&bmi_vs6624->work, bmi_vs6624_buttons_work, bmi_vs6624);
++
++
++ //Do one-time hw initialization (e.g. patch)
++
++ // configure IOX
++ configure_IOX (bmi_vs6624);
++
++ // configure GPIO
++ configure_GPIO (bmi_vs6624);
++
++ // chip enable camera
++ enable_camera (bmi_vs6624);
++
++ vs6624_patch (&bmi_vs6624->bdev->adap);
++
++ //register with bug_camera
++
++ //REWORK: check return code
++ register_bug_camera (&bmi_vs6624->bcam, slot);
++
++ return 0;
++}
++
++void bmi_vs6624_remove(struct bmi_device *bdev)
++{
++ //REWORK: Add code here
++
++
++ //get our <this> pointer
++ struct bmi_vs6624 *bmi_vs6624 = (struct bmi_vs6624*)(bmi_device_get_drvdata (bdev));
++ int slot = bdev->info->slot;
++
++
++
++ unregister_bug_camera ( &bmi_vs6624->bcam, slot);
++
++ //REWORK: Avoid I2c access if camera module is not present.
++
++ disable_camera (bmi_vs6624);
++ deconfigure_module (bmi_vs6624);
++
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++
++ //free driver-specific structure
++ kfree (bmi_vs6624);
++ return;
++}
++
++
++static __init int bmi_vs6624_init(void)
++{
++
++// REWORK: Add code here.
++
++// Register with BMI bus.
++ return bmi_register_driver (&bmi_vs6624_driver);
++
++}
++
++static void __exit bmi_vs6624_cleanup(void)
++{
++// REWORK: Add code here.
++ bmi_unregister_driver (&bmi_vs6624_driver);
++ return;
++}
++
++
++module_init(bmi_vs6624_init);
++module_exit(bmi_vs6624_cleanup);
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/lcd_ctl.c
+@@ -0,0 +1,421 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include <linux/ioctl.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include "lcd_ctl.h"
++
++static int lcd_ctl_open (struct inode *, struct file *);
++static int lcd_ctl_release (struct inode *, struct file *);
++static int lcd_ctl_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
++static int ReadByte_IOX(struct i2c_adapter *, unsigned char, unsigned char *)
++
++
++struct file_operations lcd_ctl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = lcd_ctl_ioctl,
++ .open = lcd_ctl_open,
++ .release = lcd_ctl_release,
++};
++
++
++ // read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ /* Read Byte with Pointer */
++
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; /* write */
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; /* read */
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++ // write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ /* Write Byte with Pointer */
++
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; /* write */
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; /* write */
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++
++static int lcd_ctl_major;
++
++int lcd_ctl_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI LCD Control Driver");
++
++ if (retval) {
++ return -1;
++ }
++ lcd_ctl_major = MAJOR(dev_id);
++ return 0;
++}
++
++void lcd_ctl_clean (void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(lcd_ctl_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int lcd_ctl_probe (struct lcd_ctl *lcd_ctl, int slot)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ cdev = &lcd_ctl->cdev;
++ cdev_init (cdev, &lcd_ctl_fops);
++
++ dev_id = MKDEV (lcd_ctl_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++ bmi_class = bmi_get_bmi_class ();
++
++ lcd_ctl->class_dev = device_create (bmi_class, NULL, MKDEV(lcd_ctl_major, slot), lcd_ctl, "bmi_lcd_ctl_m%i", slot+1);
++
++ if (IS_ERR(lcd_ctl->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_lcd_ctl_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(lcd_ctl->class_dev));
++ lcd_ctl->class_dev = NULL;
++ }
++ lcd_ctl->slot = slot;
++
++ return ret;
++}
++
++void lcd_ctl_remove (struct lcd_ctl *lcd_ctl, int slot)
++{
++ struct class *bmi_class;
++
++ bmi_class = bmi_get_bmi_class ();
++ device_destroy (bmi_class, MKDEV(lcd_ctl_major, slot));
++
++ lcd_ctl->class_dev = 0;
++
++ cdev_del (&lcd_ctl->cdev);
++ return;
++}
++
++
++static int lcd_ctl_open (struct inode *inode, struct file *file)
++{
++ struct lcd_ctl *lcd_ctl;
++
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++
++
++ // Save ctl pointer for later.
++
++ file->private_data = lcd_ctl;
++ return 0;
++}
++
++static int lcd_ctl_release (struct inode *inode, struct file *file)
++{
++ struct lcd_ctl *lcd_ctl;
++
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++ return 0;
++}
++
++
++/*// ioctl
++int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data[1];
++ int slot = (__user arg) & 0xF;
++ int bl = ((__user arg) & 0x70) >> 4;
++
++ // error if no lcd active.
++ if(pbmi_lcd.active == -1)
++ return -ENODEV;
++
++ if(cmd != BMI_LCD_GETSTAT) {
++
++ // error if slot invalid
++ if((slot < CPLD_M1) || (slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[slot]->adap;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ case BMI_LCD_RLEDOFF:
++ bmi_set_module_gpio_data(slot, 3, 1);// Red LED=OFF
++ break;
++ case BMI_LCD_RLEDON:
++ bmi_set_module_gpio_data(slot, 3, 0);// Red LED=ON
++ break;
++ case BMI_LCD_GLEDOFF:
++ bmi_set_module_gpio_data(slot, 2, 1);// Green LED=OFF
++ break;
++ case BMI_LCD_GLEDON:
++ bmi_set_module_gpio_data(slot, 2, 0);// Green LED=ON
++ break;
++ case BMI_LCD_VSYNC_DIS: // enable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_VSYNC_EN: // disable VSYNC buffer tristate output
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x08;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_EN: // enable LCD component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_DIS: // disable LCD component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x10;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_EN: // enable Serializer component
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data &= ~0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SER_DIS: // disable Serializer component only
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data |= 0x20;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_SETRST: // overall module reset
++ bmi_set_module_gpio_data (slot, 1, 0); // RST=0
++ break;
++ case BMI_LCD_CLRRST: // overall module enable
++ bmi_set_module_gpio_data (slot, 1, 1); // RST=1
++ break;
++ case BMI_LCD_SET_BL: // set backlight brightness
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xFC) | bl;
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ break;
++ case BMI_LCD_GETSTAT:
++ {
++ int *slot = ((int __user *) arg);
++ int read_data;
++
++ *slot &= 0xF;
++
++ // error if slot invalid
++ if((*slot < CPLD_M1) || (*slot > CPLD_M4))
++ return -ENODEV;
++
++ // error if no lcd in chosen slot
++ if(pbmi_lcd.bdev[*slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_lcd.bdev[*slot]->adap;
++
++ if(ReadByte_IOX(adap, IOX_INPUT_REG, iox_data))
++ return -ENODEV;
++
++ read_data = *iox_data | (bmi_read_gpio_data_reg(*slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++ case BMI_LCD_ACTIVATE: //pjg fix/test
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_lcd.activated[2] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ return -ENODEV;
++ }
++ break;
++ case 1:
++ if(pbmi_lcd.activated[3] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ return -ENODEV;
++ }
++ break;
++ case 2:
++ if(pbmi_lcd.activated[0] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ return -ENODEV;
++ }
++ break;
++ case 3:
++ if(pbmi_lcd.activated[1] == 1) {
++ printk(KERN_INFO "bmi_lcd.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ return -ENODEV;
++ }
++ break;
++ }
++ // activate
++ if((!pbmi_lcd.activated[slot]) && (pbmi_lcd.bdev[slot] != 0)) {
++ bmi_lcd_probe(pbmi_lcd.bdev[slot]);
++ }
++ break;
++ case BMI_LCD_DEACTIVATE:
++ if(pbmi_lcd.activated[slot]) {
++ disable_irq_nosync(pbmi_lcd.interrupt[slot]);
++ pbmi_lcd.activated[slot] = 0;
++ if(ReadByte_IOX(adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++ *iox_data = (*iox_data & 0xF8);
++ if(WriteByte_IOX(adap, IOX_OUTPUT_REG, *iox_data))
++ return -ENODEV;
++ bmi_slot_power_off(slot);
++ }
++ break;
++ case BMI_LCD_SUSPEND:
++ printk(KERN_ERR "BMI_LCD_SUSPEND NOT IMPLEMENTED\n"); //pjg
++ break;
++ case BMI_LCD_RESUME:
++ printk(KERN_ERR "BMI_LCD_RESUME NOT IMPLEMENTED\n"); //pjg
++ break;
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++*/
++
++static int lcd_ctl_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct lcd_ctl *lcd_ctl;
++ int slot;
++
++ lcd_ctl = container_of(inode->i_cdev, struct lcd_ctl, cdev);
++ slot = lcd_ctl->slot;
++ if (slot < 0) {
++ return -ENODEV;
++ }
++
++
++ switch (cmd) {
++
++ case BMI_LCD_RLEDOFF:
++ bmi_slot_gpio_write_bit (slot, 3, 1); //Red LED Off
++ break;
++
++ case BMI_LCD_RLEDON:
++ bmi_slot_gpio_write_bit (slot, 3, 0); //Red LED On
++ break;
++
++ case BMI_LCD_GLEDOFF:
++ bmi_slot_gpio_write_bit (slot, 2, 1); //Green LED Off
++ break;
++
++ case BMI_LCD_GLEDON:
++ bmi_slot_gpio_write_bit (slot, 2, 0); //Green LED On
++ break;
++
++ default:
++ printk (KERN_ERR "lcd_ctl_ioctl() - error exit\n");
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/lcd/lcd_ctl.h
+@@ -0,0 +1,87 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI LCD Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef LCD_CTL_H
++#define LCD_CTL_H
++
++#include <linux/kernel.h>
++
++#include <linux/fs.h>
++#include <linux/cdev.h>
++
++#include <linux/bmi/bmi_ioctl.h>
++
++ // IOCTL commands for BMI LCD driver
++#define BMI_LCD_RLEDOFF _IOW(BMI_LCD_IOCTL, 0x1, __u32) // turn off Red LED
++#define BMI_LCD_RLEDON _IOW(BMI_LCD_IOCTL, 0x2, __u32) // turn on Red LED
++#define BMI_LCD_GLEDOFF _IOW(BMI_LCD_IOCTL, 0x3, __u32) // turn off Green LED
++#define BMI_LCD_GLEDON _IOW(BMI_LCD_IOCTL, 0x4, __u32) // turn on Green LED
++#define BMI_LCD_VSYNC_DIS _IOW(BMI_LCD_IOCTL, 0x5, __u32) // Enable VSYNC output buffer
++#define BMI_LCD_VSYNC_EN _IOW(BMI_LCD_IOCTL, 0x6, __u32) // Disable VSYNC output buffer
++#define BMI_LCD_EN _IOW(BMI_LCD_IOCTL, 0x7, __u32) // Enable LCD component
++#define BMI_LCD_DIS _IOW(BMI_LCD_IOCTL, 0x8, __u32) // Disable LCD component
++#define BMI_LCD_SER_EN _IOW(BMI_LCD_IOCTL, 0x9, __u32) // Enable Seriallizer component
++#define BMI_LCD_SER_DIS _IOW(BMI_LCD_IOCTL, 0xa, __u32) // Disable Seriallizer component
++#define BMI_LCD_SETRST _IOW(BMI_LCD_IOCTL, 0xb, __u32) // Disable entire module
++#define BMI_LCD_CLRRST _IOW(BMI_LCD_IOCTL, 0xc, __u32) // Enable entire module
++#define BMI_LCD_SET_BL _IOW(BMI_LCD_IOCTL, 0xd, __u32) // Set IOX backlight bits [2:0]
++#define BMI_LCD_GETSTAT _IOR(BMI_LCD_IOCTL, 0xe, __u32) // Get IOX state
++#define BMI_LCD_ACTIVATE _IOW(BMI_LCD_IOCTL, 0xf, __u32) // Activate SER, TS, ACCEL
++#define BMI_LCD_DEACTIVATE _IOW(BMI_LCD_IOCTL, 0x10, __u32) // Deactivate SER, TS, ACCEL
++#define BMI_LCD_SUSPEND _IOW(BMI_LCD_IOCTL, 0x11, __u32) // Power down module
++#define BMI_LCD_RESUME _IOW(BMI_LCD_IOCTL, 0x12, __u32) // Power up module
++
++/*
++ * I2C set up
++ */
++
++ // I2C Slave Address
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define BMI_ACC_I2C_ADDRESS 0x17 // 7-bit address
++
++ // I2C IOX register addresses
++#define IOX_INPUT_REG 0x0 // IOX input data register
++#define IOX_OUTPUT_REG 0x1 // IOX output data register
++#define IOX_POLARITY_REG 0x2 // IOX polarity data register
++#define IOX_CONTROL 0x3 // IOX direction control register
++#define IOX_B1 (0) // bit 0 - backlight control
++#define IOX_A1_A2 (1) // bit 1 - backlight control
++#define IOX_ACC_RST_N (2) // bit 2 - acceleromter reset
++#define IOX_VSYNC_EN_N (3) // bit 3 - VSYNC output buffer enable
++#define IOX_LCD_RST_N (4) // bit 4 - LCD reset
++#define IOX_SERDES_PD_N (5) // bit 5 - SERDES power down
++#define IOX_X_INT (6) // bit 6 - accelerometer interrupt
++#define IOX_Y_INT (7) // bit 7 - accelerometer interrupt
++
++struct lcd_ctl
++{
++ int slot;
++ struct cdev cdev;
++ struct device *class_dev;
++};
++
++extern int lcd_ctl_init (void);
++extern void lcd_ctl_clean(void);
++extern int lcd_ctl_probe (struct lcd_ctl *lcd_ctl, int slot);
++extern void lcd_ctl_remove(struct lcd_ctl *lcd_ctl, int slot);
++
++
++#endif
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/Kconfig
+@@ -0,0 +1,6 @@
++config BMI_MDACC
++ tristate "BMI Motion Detector/Accelerometer"
++ depends on BMI_PIMS
++ default n
++ ---help---
++ This is the BMI Motion Detector/Acceleromter driver.
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/Makefile
+@@ -0,0 +1,9 @@
++#
++# BMI PIM: Motion Detector Accelerometer
++#
++
++bmi_mdacc-objs := mdacc.o avr.o md.o acc.o ctl.o mon.o cque.o
++obj-$(CONFIG_BMI_MDACC) += bmi_mdacc.o
++
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/acc.c
+@@ -0,0 +1,381 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include "acc.h"
++#include "mdacc.h"
++#include "mon.h"
++#include <linux/bmi/bmi_mdacc.h>
++#include <linux/ioctl.h>
++#include <linux/poll.h>
++
++static int acc_open (struct inode *, struct file *);
++static int acc_release (struct inode *, struct file *);
++static int acc_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
++static ssize_t acc_read (struct file *, char __user *, size_t, loff_t *);
++static unsigned int acc_poll (struct file *, struct poll_table_struct *);
++
++struct file_operations acc_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = acc_ioctl,
++ .open = acc_open,
++ .release = acc_release,
++ .read = acc_read,
++ .poll = acc_poll,
++};
++
++static int acc_major;
++
++int acc_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI MDACC Accelerometer Driver");
++
++ if (retval) {
++ return -1;
++ }
++ acc_major = MAJOR(dev_id);
++ return 0;
++}
++
++void acc_clean(void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(acc_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int acc_probe (struct acc *acc, int slot, struct mon *mon)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ // initialize cdev
++
++ cdev = &acc->cdev;
++ cdev_init (cdev, &acc_fops);
++
++ dev_id = MKDEV (acc_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++
++ bmi_class = bmi_get_class ();
++
++ acc->class_dev = device_create (bmi_class, NULL, MKDEV(acc_major, slot), acc, "bmi_mdacc_acc_m%i", slot+1);
++
++ if (IS_ERR(acc->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_mdacc_acc_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(acc->class_dev));
++ acc->class_dev = NULL;
++ }
++
++ acc->open_flag = 0;
++ acc->mon = mon;
++
++
++ // initialize mdacc_accel_config
++
++ acc->cfg.read_queue_size = 1;
++ acc->cfg.read_queue_threshold = 1;
++ acc->cfg.delay_mode = 0;
++ acc->cfg.delay = 4000;
++ acc->cfg.delay_resolution = 1;
++ acc->cfg.sensitivity = 0;
++ acc->cfg.run = 0;
++
++
++ // initialize cque
++
++ acc->cque = cque_create (acc->cfg.read_queue_size, acc->cfg.read_queue_threshold);
++
++ // initialize read_wait_queue
++
++ init_waitqueue_head (&acc->read_wait_queue);
++ return ret;
++}
++
++void acc_remove (struct acc *acc, int slot)
++{
++ struct class *bmi_class;
++
++ cque_destroy (acc->cque);
++
++ bmi_class = bmi_get_class ();
++ device_destroy (bmi_class, MKDEV(acc_major, slot));
++
++ acc->class_dev = 0;
++
++ cdev_del (&acc->cdev);
++
++
++ return;
++}
++
++
++static int acc_open (struct inode *inode, struct file *file)
++{
++ struct acc *acc;
++
++ acc = container_of(inode->i_cdev, struct acc, cdev);
++
++ //Enforce single open behavior
++ if (acc->open_flag) {
++ return -EBUSY;
++ }
++ acc->open_flag = 1;
++
++ // Save acc_drv pointer for later.
++ file->private_data = acc;
++ return 0;
++}
++
++static int acc_release (struct inode *inode, struct file *file)
++{
++ struct acc *acc;
++
++ acc = container_of(inode->i_cdev, struct acc, cdev);
++ acc->open_flag = 0;
++
++ //Enforce stop-on-close behavior.
++ if (acc->cfg.run) {
++ acc->cfg.run = 0;
++ mon_stop_accel (acc->mon);
++ }
++ return 0;
++
++}
++
++static int check_config (struct mdacc_accel_config *config)
++{
++ int err = 0;
++
++ if (!config) {
++ err = 1;
++ goto exit;
++ }
++
++ if (config->read_queue_size < 1) {
++ err = 1;
++ }
++ if (config->read_queue_threshold > config->read_queue_size) {
++ err = 1;
++ }
++ if (config->delay_mode) {
++ switch (config->delay_resolution)
++ {
++ case 0:
++ err = 1;
++ break;
++ case 1: // 1 => 1 usec
++ if (config->delay < 5000) {
++ err = 1;
++ }
++ break;
++ case 2:
++ if (config->delay < 625) { // 2 => 8 usec
++ err = 1;
++ }
++ break;
++ case 3:
++ if (config->delay < 79) { // 3 => 64 usec
++ err = 1;
++ }
++ break;
++ case 4:
++ if (config->delay < 20) { // 4 => 256 usec
++ err = 1;
++ }
++ break;
++ case 5:
++ if (config->delay < 5) { // 5 => 1024 usec
++ err = 1;
++ }
++ break;
++ default:
++ err = 1;
++ break;
++ }
++ }
++
++ if (config->sensitivity > 3) {
++ err = 1;
++ }
++
++exit:
++ return err;
++}
++
++static int acc_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int err = 0;
++ struct acc *acc;
++ acc = container_of(inode->i_cdev, struct acc, cdev);
++
++ switch (cmd) {
++
++ case BMI_MDACC_ACCELEROMETER_SET_CONFIG:
++ {
++ struct mdacc_accel_config new_cfg;
++
++ err = copy_from_user ( (void*)&new_cfg, (void*)arg, sizeof (struct mdacc_accel_config) );
++ if (err) {
++ return -EFAULT;
++ }
++
++ err = check_config (&new_cfg);
++ if (err) {
++ return -EINVAL;
++ }
++
++ if (acc->cfg.run) {
++ mon_stop_accel (acc->mon);
++ }
++
++ // take the mon semaphore
++ down_interruptible (&acc->mon->sem);
++
++ memcpy ( &acc->cfg, &new_cfg, sizeof (struct mdacc_accel_config) );
++ cque_destroy (acc->cque);
++ acc->cque = cque_create (acc->cfg.read_queue_size, acc->cfg.read_queue_threshold);
++
++ // release the mon semaphore
++ up (&acc->mon->sem);
++
++ mon_set_config_accel( acc->mon, &acc->cfg);
++
++ }
++ break;
++
++ case BMI_MDACC_ACCELEROMETER_GET_CONFIG:
++
++ mon_get_config_accel( acc->mon, &acc->cfg);
++
++
++ err = copy_to_user ( (void*)arg, &acc->cfg, sizeof (struct mdacc_accel_config) );
++ if (err) {
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_MDACC_ACCELEROMETER_RUN:
++
++ acc->cfg.run = 1;
++ err = mon_start_accel (acc->mon);
++ if (err){
++ return -ENODEV;
++ }
++ break;
++
++
++ case BMI_MDACC_ACCELEROMETER_STOP:
++
++ acc->cfg.run = 0;
++ err = mon_stop_accel (acc->mon);
++ if (err){
++ return -ENODEV;
++ }
++ break;
++
++ default:
++ printk (KERN_ERR "acc_ioctl() - error exit\n");
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++static ssize_t acc_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
++{
++// if fd is non-blocking and acc is not enabled, return EAGAIN
++// if fd is non-blocking and acc is enabled, and cque is not ready, return EAGAIN
++// if fd is non-blocking and acc is enabled, and cque is ready, read cque, copy to user,
++
++// if fd is blocking and acc is not enabled, , return EAGAIN
++//
++
++// if fs is blocking and acc is enabled, and cque is not ready, sleep until ready.
++// when ready, read cque, copy to user,
++
++
++
++ struct acc *acc = file->private_data;
++ unsigned char temp[6];
++ int bytes_read;
++
++ if (count < 6) {
++ return -EINVAL;
++ }
++
++ if (!acc->cfg.run) {
++ return -EAGAIN;
++ }
++
++ while (!cque_is_ready_for_read(acc->cque)) {
++ if (file->f_flags & O_NONBLOCK)
++ return -EAGAIN;
++ if (wait_event_interruptible (acc->read_wait_queue, (cque_is_ready_for_read(acc->cque))))
++ return -ERESTARTSYS;
++ }
++
++ //loop through 1 sample at a time.
++
++ bytes_read = 0;
++
++ while (count >= 6) {
++
++ if (cque_read (acc->cque, &temp))
++ break;
++ if (copy_to_user (buf, &temp, 6))
++ break;
++ bytes_read += 6;
++ buf += 6;
++ count -= 6;
++ }
++ return bytes_read;
++}
++
++
++static unsigned int acc_poll (struct file *file, struct poll_table_struct *table)
++{
++ unsigned int mask = 0;
++ struct acc *acc = file->private_data;
++
++ poll_wait(file, &acc->read_wait_queue, table);
++
++ if (cque_is_ready_for_read( acc->cque) ) {
++ mask |= POLLIN | POLLRDNORM; /* readable */
++ }
++ if (mdacc_check_bdev_acc (acc) ) {
++ mask |= POLLHUP; /* hang-up */
++ }
++ if (!acc->cfg.run) {
++ mask |= POLLHUP; /* hang-up */
++ }
++ return mask;
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/acc.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef MDACC_ACC_H
++#define MDACC_ACC_H
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/bmi.h>
++#include <linux/delay.h>
++#include <linux/bmi/bmi_mdacc.h>
++#include "cque.h"
++
++struct mon;
++
++struct acc
++{
++ struct cdev cdev;
++ struct device *class_dev;
++ int open_flag;
++ struct mon *mon;
++ struct mdacc_accel_config cfg;
++ struct cque *cque;
++ wait_queue_head_t read_wait_queue;
++};
++
++
++extern int acc_init (void);
++extern void acc_clean(void);
++extern int acc_probe (struct acc *acc, int slot, struct mon *mon);
++extern void acc_remove(struct acc *acc, int slot);
++
++
++
++
++#endif
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/avr.c
+@@ -0,0 +1,511 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include <linux/device.h>
++#include <linux/spi/spi.h>
++
++
++struct avr_regs
++{
++ unsigned char timer_res; // SPI Register 0
++ unsigned char timer_msb; // SPI Register 1
++ unsigned char timer_lsb; // SPI Register 2
++ unsigned char mode; // SPI Register 3
++
++ unsigned char status; // SPI Register 4
++
++ unsigned char adc0h; // SPI Register 5
++ unsigned char adc0l; // SPI Register 6
++ unsigned char adc1h; // SPI Register 7
++ unsigned char adc1l; // SPI Register 8
++ unsigned char adc2h; // SPI Register 9
++ unsigned char adc2l; // SPI Register 10
++};
++
++
++
++/*
++
++Cmd Bit Definitions
++
++Cmd bit 7 - R0/W1
++Cmd bit 6 - Cnt 2
++Cmd bit 5 - Cnt 1
++Cmd bit 4 - Cnt 0
++Cmd bit 3 - Address 3
++Cmd bit 2 - Address 2
++Cmd bit 1 - Address 1
++Cmd bit 0 - Address 0
++*/
++
++
++
++#define AVR_CMD_READ_ADC (0x65)
++#define AVR_CMD_READ_STATUS (0x14)
++#define AVR_CMD_READ_STATUS_AND_ADC (0x74)
++#define AVR_CMD_READ_MODE (0x13)
++#define AVR_CMD_READ_TIMER (0x30)
++#define AVR_CMD_READ_TIMER_AND_MODE (0x40)
++#define AVR_CMD_WRITE_MODE (0x93)
++#define AVR_CMD_WRITE_TIMER (0xB0)
++#define AVR_CMD_WRITE_TIMER_AND_MODE (0xC0)
++
++int avr_read_adc (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_status (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_status_and_adc (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_timer (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_timer_and_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_timer (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_timer_and_mode (struct spi_device *spi, struct avr_regs *regs);
++
++
++int avr_read_adc (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++
++ struct spi_transfer x[7];
++ struct spi_message message;
++
++ cmd = AVR_CMD_READ_ADC;
++ sync = 0;
++
++ dont_care = 0;
++
++ spi_message_init(&message);
++ memset(x, 0, sizeof x);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ x[0].bits_per_word = 8;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->adc0h;
++ x[1].delay_usecs = 400;
++ x[1].bits_per_word = 8;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &dont_care;
++ x[2].rx_buf = &regs->adc0l;
++ x[2].delay_usecs = 400;
++ x[2].bits_per_word = 8;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &dont_care;
++ x[3].rx_buf = &regs->adc1h;
++ x[3].delay_usecs = 400;
++ x[3].bits_per_word = 8;
++ spi_message_add_tail(&x[3], &message);
++
++ x[4].len = 1;
++ x[4].tx_buf = &dont_care;
++ x[4].rx_buf = &regs->adc1l;
++ x[4].delay_usecs = 400;
++ x[4].bits_per_word = 8;
++ spi_message_add_tail(&x[4], &message);
++
++ x[5].len = 1;
++ x[5].tx_buf = &dont_care;
++ x[5].rx_buf = &regs->adc2h;
++ x[5].delay_usecs = 400;
++ x[5].bits_per_word = 8;
++ spi_message_add_tail(&x[5], &message);
++
++ x[6].len = 1;
++ x[6].tx_buf = &dont_care;
++ x[6].rx_buf = &regs->adc2l;
++ x[6].delay_usecs = 400;
++ x[6].bits_per_word = 8;
++ spi_message_add_tail(&x[6], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++
++int avr_read_status (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++ struct spi_transfer x[2];
++ struct spi_message message;
++
++ cmd = AVR_CMD_READ_STATUS;
++ sync = 0;
++
++ dont_care = 0;;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->status;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_read_status_and_adc (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++ struct spi_transfer x[8];
++ struct spi_message message;
++
++ cmd = AVR_CMD_READ_STATUS_AND_ADC;
++ sync = 0;
++ dont_care = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->status;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &dont_care;
++ x[2].rx_buf = &regs->adc0h;
++ x[2].delay_usecs = 400;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &dont_care;
++ x[3].rx_buf = &regs->adc0l;
++ x[3].delay_usecs = 400;
++ spi_message_add_tail(&x[3], &message);
++
++ x[4].len = 1;
++ x[4].tx_buf = &dont_care;
++ x[4].rx_buf = &regs->adc1h;
++ x[4].delay_usecs = 400;
++ spi_message_add_tail(&x[4], &message);
++
++ x[5].len = 1;
++ x[5].tx_buf = &dont_care;
++ x[5].rx_buf = &regs->adc1l;
++ x[5].delay_usecs = 400;
++ spi_message_add_tail(&x[5], &message);
++
++ x[6].len = 1;
++ x[6].tx_buf = &dont_care;
++ x[6].rx_buf = &regs->adc2h;
++ x[6].delay_usecs = 400;
++ spi_message_add_tail(&x[6], &message);
++
++ x[7].len = 1;
++ x[7].tx_buf = &dont_care;
++ x[7].rx_buf = &regs->adc2l;
++ x[7].delay_usecs = 400;
++ spi_message_add_tail(&x[7], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_read_mode (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++
++ struct spi_transfer x[2];
++ struct spi_message message;
++
++
++ cmd = AVR_CMD_READ_MODE;
++ sync = 0;
++
++ dont_care = 0;
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->mode;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_read_timer (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++ struct spi_transfer x[4];
++ struct spi_message message;
++
++
++ cmd = AVR_CMD_READ_TIMER;
++ sync = 0;
++ dont_care = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->timer_res;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &dont_care;
++ x[2].rx_buf = &regs->timer_msb;
++ x[2].delay_usecs = 400;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &dont_care;
++ x[3].rx_buf = &regs->timer_lsb;
++ x[3].delay_usecs = 400;
++ spi_message_add_tail(&x[3], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++int avr_read_timer_and_mode (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ unsigned char dont_care;
++ struct spi_transfer x[5];
++ struct spi_message message;
++
++
++ cmd = AVR_CMD_READ_TIMER_AND_MODE;
++ sync = 0;
++ dont_care = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &dont_care;
++ x[1].rx_buf = &regs->timer_res;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &dont_care;
++ x[2].rx_buf = &regs->timer_msb;
++ x[2].delay_usecs = 400;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &dont_care;
++ x[3].rx_buf = &regs->timer_lsb;
++ x[3].delay_usecs = 400;
++ spi_message_add_tail(&x[3], &message);
++
++ x[4].len = 1;
++ x[4].tx_buf = &dont_care;
++ x[4].rx_buf = &regs->mode;
++ x[4].delay_usecs = 400;
++ spi_message_add_tail(&x[4], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_write_mode (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ struct spi_transfer x[2];
++ struct spi_message message;
++
++ cmd = AVR_CMD_WRITE_MODE;
++ sync = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &regs->mode;
++ x[1].rx_buf = 0;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_write_timer (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ struct spi_transfer x[4];
++ struct spi_message message;
++
++ cmd = AVR_CMD_WRITE_TIMER;
++ sync = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &regs->timer_res;
++ x[1].rx_buf = 0;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &regs->timer_msb;
++ x[2].rx_buf = 0;
++ x[2].delay_usecs = 400;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &regs->timer_lsb;
++ x[3].rx_buf = 0;
++ x[3].delay_usecs = 400;
++ spi_message_add_tail(&x[3], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
++int avr_write_timer_and_mode (struct spi_device *spi, struct avr_regs *regs)
++{
++ int err;
++ unsigned char cmd;
++ unsigned char sync;
++ struct spi_transfer x[5];
++ struct spi_message message;
++
++
++ cmd = AVR_CMD_WRITE_TIMER_AND_MODE;
++ sync = 0;
++
++ memset(x, 0, sizeof x);
++ spi_message_init(&message);
++
++ x[0].len = 1;
++ x[0].tx_buf = &cmd;
++ x[0].rx_buf = &sync;
++ x[0].delay_usecs = 400;
++ spi_message_add_tail(&x[0], &message);
++
++ x[1].len = 1;
++ x[1].tx_buf = &regs->timer_res;
++ x[1].rx_buf = 0;
++ x[1].delay_usecs = 400;
++ spi_message_add_tail(&x[1], &message);
++
++ x[2].len = 1;
++ x[2].tx_buf = &regs->timer_msb;
++ x[2].rx_buf = 0;
++ x[2].delay_usecs = 400;
++ spi_message_add_tail(&x[2], &message);
++
++ x[3].len = 1;
++ x[3].tx_buf = &regs->timer_lsb;
++ x[3].rx_buf = 0;
++ x[3].delay_usecs = 400;
++ spi_message_add_tail(&x[3], &message);
++
++ x[4].len = 1;
++ x[4].tx_buf = &regs->mode;
++ x[4].rx_buf = 0;
++ x[4].delay_usecs = 400;
++ spi_message_add_tail(&x[4], &message);
++
++ err = spi_sync(spi, &message);
++
++ return err;
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/avr.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++#ifndef MDACC_AVR_H
++#define MDACC_AVR_H
++
++#include <linux/device.h>
++#include <linux/spi/spi.h>
++
++struct avr_regs
++{
++ unsigned char timer_res; // SPI Register 0
++ unsigned char timer_msb; // SPI Register 1
++ unsigned char timer_lsb; // SPI Register 2
++ unsigned char mode; // SPI Register 3
++
++ unsigned char status; // SPI Register 4
++
++ unsigned char adc0h; // SPI Register 5
++ unsigned char adc0l; // SPI Register 6
++ unsigned char adc1h; // SPI Register 7
++ unsigned char adc1l; // SPI Register 8
++ unsigned char adc2h; // SPI Register 9
++ unsigned char adc2l; // SPI Register 10
++};
++
++int avr_read_adc (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_status (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_status_and_adc (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_timer (struct spi_device *spi, struct avr_regs *regs);
++int avr_read_timer_and_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_mode (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_timer (struct spi_device *spi, struct avr_regs *regs);
++int avr_write_timer_and_mode (struct spi_device *spi, struct avr_regs *regs);
++
++#endif
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/cque.c
+@@ -0,0 +1,150 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include "cque.h"
++#include <linux/slab.h>
++#include <linux/byteorder/generic.h>
++
++struct cque *cque_create (int num_entries, int threshold)
++{
++
++ int entry_size;
++ struct cque *cque;
++ void *buf_base;
++ int buf_size;
++
++ entry_size = 6;
++ cque = 0;
++ buf_size = entry_size * num_entries;
++ if (!buf_size) {
++ return 0;
++ }
++
++ if (( threshold > num_entries) ||
++ ( threshold < 1)) {
++ return 0;
++ }
++
++ cque = kmalloc (sizeof(cque), GFP_KERNEL);
++ if (!cque) {
++ return 0;
++ }
++
++ buf_base = kmalloc (buf_size, GFP_KERNEL);
++ if (!buf_base) {
++ kfree (cque);
++ return 0;
++ }
++
++ cque->entry_size = entry_size;
++ cque->num_entries = num_entries;
++ cque->entry_cnt = 0;
++ cque->threshold = threshold;
++ cque->start = buf_base;
++ cque->end = buf_base + buf_size - entry_size;
++ cque->top = buf_base;
++ cque->bot = buf_base;
++
++ return cque;
++}
++
++void cque_destroy (struct cque *cque)
++{
++
++ if (cque) {
++ kfree (cque->start);
++ kfree (cque);
++ }
++ return;
++
++}
++
++int cque_write (struct cque *cque, void *data)
++{
++ int size;
++ int err;
++
++ size = 6;
++ err = 1;
++ if (cque) {
++ //insert
++
++ memcpy (cque->top, data, size);
++ cque->top += size;
++ if (cque->top > cque->end) {
++ cque->top = cque->start;
++ }
++
++
++ if (cque->entry_cnt < cque->num_entries) {
++ cque->entry_cnt++;
++ }
++ else {
++ cque->bot += size;
++ if (cque->bot > cque->end) {
++ cque->bot = cque->start;
++ }
++ }
++ err = 0;
++ }
++ return err;
++
++}
++
++int cque_read (struct cque *cque, void *data )
++{
++ int size;
++ int err;
++
++ size = 6;
++ err = 1;
++ if (cque) {
++
++ if (cque->entry_cnt) {
++
++ //remove
++
++ //memcpy (data, cque->bot, size) with swab ;
++
++ *((short*)(data)) = ntohs (*((short*)(cque->bot)));
++ *((short*)(data+2)) = ntohs (*((short*)(cque->bot+2)));
++ *((short*)(data+4)) = ntohs (*((short*)(cque->bot+4)));
++ cque->bot += size;
++ if (cque->bot > cque->end) {
++ cque->bot = cque->start;
++ }
++ cque->entry_cnt--;
++ err = 0;
++ }
++ }
++ return err;
++}
++
++int cque_is_ready_for_read (struct cque *cque)
++{
++ int ready;
++
++ ready = 0;
++ if ((cque) && (cque->entry_cnt >= cque->threshold)) {
++ ready = 1;
++ }
++ return ready;
++}
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/cque.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++#ifndef MDACC_CQUE_H
++#define MDACC_CQUE_H
++
++struct cque
++{
++ int entry_size;
++ int num_entries;
++ int entry_cnt;
++ int threshold;
++
++ void *start;
++ void *end;
++ void *top;
++ void *bot;
++};
++
++struct cque *cque_create (int num_entries, int threshold);
++void cque_destroy (struct cque *cque);
++
++int cque_write (struct cque *cque, void *data);
++int cque_read (struct cque *cque, void *data);
++int cque_is_ready_for_read (struct cque *cque);
++
++#endif
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/ctl.c
+@@ -0,0 +1,176 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include "ctl.h"
++#include "mdacc.h"
++#include <linux/bmi/bmi_mdacc.h>
++#include <linux/ioctl.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-slot.h>
++
++
++#include <linux/module.h>
++
++static int ctl_open (struct inode *, struct file *);
++static int ctl_release (struct inode *, struct file *);
++static int ctl_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
++
++struct file_operations ctl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = ctl_ioctl,
++ .open = ctl_open,
++ .release = ctl_release,
++};
++
++static int ctl_major;
++
++int ctl_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI MDACC Control Driver");
++
++ if (retval) {
++ return -1;
++ }
++ ctl_major = MAJOR(dev_id);
++ return 0;
++}
++
++void ctl_clean (void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(ctl_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int ctl_probe (struct ctl *ctl, int slot)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ cdev = &ctl->cdev;
++ cdev_init (cdev, &ctl_fops);
++
++ dev_id = MKDEV (ctl_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++ bmi_class = bmi_get_class ();
++
++ ctl->class_dev = device_create (bmi_class, NULL, MKDEV(ctl_major, slot), ctl, "bmi_mdacc_ctl_m%i", slot+1);
++
++ if (IS_ERR(ctl->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_mdacc_ctl_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(ctl->class_dev));
++ ctl->class_dev = NULL;
++ }
++
++ return ret;
++}
++
++void ctl_remove (struct ctl *ctl, int slot)
++{
++ struct class *bmi_class;
++
++ bmi_class = bmi_get_class ();
++ device_destroy (bmi_class, MKDEV(ctl_major, slot));
++
++ ctl->class_dev = 0;
++
++ cdev_del (&ctl->cdev);
++ return;
++}
++
++
++static int ctl_open (struct inode *inode, struct file *file)
++{
++ struct ctl *ctl;
++
++ ctl = container_of(inode->i_cdev, struct ctl, cdev);
++
++
++ // Save ctl pointer for later.
++
++ file->private_data = ctl;
++ return 0;
++}
++
++static int ctl_release (struct inode *inode, struct file *file)
++{
++ struct ctl *ctl;
++
++ ctl = container_of(inode->i_cdev, struct ctl, cdev);
++ return 0;
++}
++
++static int ctl_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct ctl *ctl;
++ int slot;
++ unsigned char tmp = 0;
++
++ ctl = container_of(inode->i_cdev, struct ctl, cdev);
++ slot = mdacc_get_slot_ctl (ctl);
++ if (slot < 0) {
++ return -ENODEV;
++ }
++
++ switch (cmd) {
++
++ case BMI_MDACC_CTL_RED_LED_OFF:
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp | RED_LED);
++ //bmi_slot_gpio_write_bit (slot, 3, 1); //Red LED Off
++ break;
++
++ case BMI_MDACC_CTL_RED_LED_ON:
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp & ~RED_LED);
++ //bmi_slot_gpio_write_bit (slot, 3, 0); //Red LED On
++ break;
++
++ case BMI_MDACC_CTL_GREEN_LED_OFF:
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp | GREEN_LED);
++ //bmi_slot_gpio_write_bit (slot, 2, 1); //Green LED Off
++ break;
++
++ case BMI_MDACC_CTL_GREEN_LED_ON:
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp & ~GREEN_LED);
++ //bmi_slot_gpio_write_bit (slot, 2, 0); //Green LED On
++ break;
++
++ default:
++ printk (KERN_ERR "ctl_ioctl() - error exit\n");
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/ctl.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef MDACC_CTL_H
++#define MDACC_CTL_H
++
++#include <linux/kernel.h>
++
++#include <linux/fs.h>
++#include <linux/cdev.h>
++
++
++struct ctl
++{
++ struct cdev cdev;
++ struct device *class_dev;
++};
++
++extern int ctl_init (void);
++extern void ctl_clean(void);
++extern int ctl_probe (struct ctl *ctl, int slot);
++extern void ctl_remove(struct ctl *ctl, int slot);
++
++
++#endif
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/md.c
+@@ -0,0 +1,333 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include "md.h"
++#include "mdacc.h"
++#include "mon.h"
++#include <linux/bmi/bmi_mdacc.h>
++#include <linux/ioctl.h>
++#include <linux/poll.h>
++
++static int md_open (struct inode *, struct file *);
++static int md_release (struct inode *, struct file *);
++static int md_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
++static ssize_t md_read (struct file *, char __user *, size_t, loff_t *);
++static unsigned int md_poll (struct file *, struct poll_table_struct *);
++
++struct file_operations md_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = md_ioctl,
++ .open = md_open,
++ .release = md_release,
++ .read = md_read,
++ .poll = md_poll,
++};
++
++static int md_major;
++
++#define BMI_MOTION_DETECT_MASK (BMI_MOTION_DETECT_STATUS | \
++ BMI_MOTION_DETECT_LATCHED_STATUS | \
++ BMI_MOTION_DETECT_DELTA | \
++ BMI_MOTION_DETECT_ENABLED)
++
++
++
++void md_update (struct md *md, char data)
++{
++
++ unsigned char old_delta;
++ unsigned char new_delta;
++ unsigned char merge_bits;
++ unsigned char new_bits;
++
++
++ // Delta and Latched Status Bit Handling.
++
++ // MOTION_STATUS Bit 3
++ // LATCHED_STATUS Bit 2
++ // DELTA Bit 1
++ // ENABLED Bit 0
++
++
++ // Handle bits individually
++
++ old_delta = md->status & 0x02;
++ new_delta = data & 0x02;
++
++ if (!new_delta) {
++ //preserve old latch bit, update delta bit
++ merge_bits = (md->status & 0x06) | (data & 0x02);
++ }
++ else {
++ //update latch bit and delta bit
++ merge_bits = (md->status & 0x06) | (data & 0x06);
++ }
++ new_bits = data & 0x09;
++ md->status = merge_bits | new_bits;
++
++ if (!old_delta && new_delta) {
++ md->ready = 1;
++ //wake up anyone sleeping on our read wait queue
++ wake_up_interruptible (&md->read_wait_queue);
++
++ }
++ return;
++}
++
++
++void md_clear_status (struct md *md)
++{
++
++ md->status &= ~(BMI_MOTION_DETECT_LATCHED_STATUS |
++ BMI_MOTION_DETECT_DELTA);
++
++ md->ready = 0;
++ return;
++
++}
++
++
++int md_init (void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI MDACC Motion Detector Driver");
++
++ if (retval) {
++ return -1;
++ }
++ md_major = MAJOR(dev_id);
++ return 0;
++}
++
++void md_clean (void)
++{
++ dev_t dev_id;
++
++ dev_id = MKDEV(md_major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++int md_probe (struct md *md, int slot, struct mon *mon)
++{
++ struct cdev *cdev;
++ dev_t dev_id;
++ int ret;
++ struct class *bmi_class;
++
++ md->removed = 0;
++
++ cdev = &md->cdev;
++ cdev_init (cdev, &md_fops);
++
++ dev_id = MKDEV (md_major, slot);
++ ret = cdev_add (cdev, dev_id, 1);
++
++ //Create class device
++ bmi_class = bmi_get_class ();
++
++ md->class_dev = device_create (bmi_class, NULL, MKDEV(md_major, slot), md, "bmi_mdacc_mot_m%i", slot+1);
++
++ if (IS_ERR(md->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_mdacc_mot_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(md->class_dev));
++ md->class_dev = NULL;
++ }
++
++ md->open_flag = 0;
++ md->enabled = 0;
++ md->status = 0;
++ init_waitqueue_head (&md->read_wait_queue);
++ md->mon = mon;
++ return ret;
++}
++
++void md_remove (struct md *md, int slot )
++{
++ struct class *bmi_class;
++
++ md->removed = 1;
++ md->ready = -1;
++ wake_up_interruptible (&md->read_wait_queue);
++
++ cdev_del (&md->cdev);
++ bmi_class = bmi_get_class ();
++ device_destroy (bmi_class, MKDEV(md_major, slot));
++ md->class_dev = 0;
++ return;
++}
++
++
++static int md_open (struct inode *inode, struct file *file)
++{
++ struct md *md;
++
++ md = container_of(inode->i_cdev, struct md, cdev);
++
++ //Enforce single open behavior
++ if (md->open_flag) {
++ return -EBUSY;
++ }
++ md->open_flag = 1;
++
++ // Save md_drv pointer for later.
++ file->private_data = md;
++ return 0;
++}
++
++static int md_release (struct inode *inode, struct file *file)
++{
++ struct md *md;
++
++ md = container_of(inode->i_cdev, struct md, cdev);
++ md->open_flag = 0;
++
++ //Enforce stop-on-close behavior.
++ if (md->enabled) {
++ mon_stop_motion (md->mon);
++ }
++ return 0;
++}
++
++static int md_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ int err = 0;
++ struct md *md;
++ md = container_of(inode->i_cdev, struct md, cdev);
++
++ switch (cmd) {
++
++ case BMI_MDACC_MOTION_DETECTOR_GET_STATUS:
++
++ err = mon_status_request (md->mon);
++ if (err){
++ return -ENODEV;
++ }
++
++ //copy to user
++ err = copy_to_user((void*)(arg), &md->status, sizeof(md->status));
++ md_clear_status (md);
++ if (err) {
++ return -EFAULT;
++ }
++ break;
++
++
++ case BMI_MDACC_MOTION_DETECTOR_RUN:
++
++ err = mon_start_motion (md->mon);
++
++ if (err){
++ return -ENODEV;
++ }
++ mon_status_request (md->mon);
++ md->enabled = 1;
++ break;
++
++
++ case BMI_MDACC_MOTION_DETECTOR_STOP:
++
++ err = mon_stop_motion (md->mon);
++ if (err){
++ return -ENODEV;
++ }
++
++ break;
++
++ default:
++ printk (KERN_ERR "md_ioctl() - error exit\n");
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++static ssize_t md_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
++{
++
++//
++// if fd is non-blocking and md is not enabled, return EWOULDBLOCK
++// if fd is non-blocking and md is enabled, and md is not ready, return EWOULDBLOCK
++// if fd is non-blocking and md is enabled, and md is ready, copy md->status to user, md_clear_status(),
++
++// if fd is blocking and md is not enabled, avr_read_status,
++// md_update, copy md->status to user, md_clear_status()
++
++// if fs is blocking and md is enabled, and md is not ready, sleep until ready.
++// when ready, copy md->status to user, md_clear_status()
++
++
++ int err;
++ struct md *md = file->private_data;
++
++
++ if (!md->enabled) {
++ return -EAGAIN;
++ }
++
++ if (file->f_flags & O_NONBLOCK) {
++ return -EAGAIN;
++ }
++
++ while (!md->ready) {
++
++ if (file->f_flags & O_NONBLOCK)
++ return -EAGAIN;
++ if (wait_event_interruptible (md->read_wait_queue, (md->ready)))
++ return -ERESTARTSYS;
++
++ if(md->removed) {
++ return -1;
++ }
++ }
++
++ err = copy_to_user (buf, &md->status, 1);
++ md_clear_status (md);
++ if (err) {
++ return -EFAULT;
++ }
++ return 1;
++}
++
++static unsigned int md_poll (struct file *file, struct poll_table_struct *table)
++{
++ unsigned int mask = 0;
++ struct md *md = file->private_data;
++
++ poll_wait(file, &md->read_wait_queue, table);
++
++ if (md->ready) {
++ mask |= POLLIN | POLLRDNORM; /* readable */
++ }
++
++ if (mdacc_check_bdev_md (md) ) {
++ mask |= POLLHUP; /* hang-up */
++ }
++
++ if (!md->enabled) {
++ mask |= POLLHUP; /* hang-up */
++ }
++ return mask;
++}
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/md.h
+@@ -0,0 +1,60 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef MDACC_MD_H
++#define MDACC_MD_H
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <linux/fs.h>
++#include <linux/cdev.h>
++
++#include <linux/bmi.h>
++#include <linux/delay.h>
++
++#include <linux/workqueue.h>
++
++struct mon;
++
++struct md
++{
++ struct cdev cdev;
++ struct device *class_dev;
++ int open_flag;
++ int enabled;
++ unsigned char status;
++ int ready;
++ wait_queue_head_t read_wait_queue;
++ struct mon *mon;
++ u8 removed;
++};
++
++
++extern int md_init (void);
++extern void md_clean(void);
++extern int md_probe (struct md *md, int slot, struct mon *mon);
++extern void md_remove(struct md *md, int slot);
++
++
++void md_update ( struct md *md, char data);
++void md_clear_status (struct md *md );
++
++
++#endif
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/mdacc.c
+@@ -0,0 +1,333 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ * This kernel module contains the device drivers for the Bug MDACC Plug-In
++ * Module. Refer to include/linux/bmi/bmi_mdacc.h for user-level device driver
++ * programming information.
++ *------------------------------------------------------------------------------
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <linux/fs.h>
++#include <linux/cdev.h>
++
++#include <linux/bmi.h>
++#include <linux/delay.h>
++
++#include <linux/workqueue.h>
++
++#define BMI_MDACC_VERSION "1.0" // driver version
++
++
++#include "md.h"
++#include "acc.h"
++#include "ctl.h"
++#include "mon.h"
++#include "avr.h"
++#include "cque.h"
++#include "mdacc.h"
++
++
++// private device structure
++struct pim
++{
++ struct bmi_device *bdev;
++ struct ctl ctl;
++ struct md md;
++ struct acc acc;
++ struct mon mon;
++ char *name;
++};
++
++static struct pim bug_mdacc_pim[4];
++
++// BMI device ID table
++static struct bmi_device_id bmi_mdacc_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_MOT_ACCEL,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_mdacc_tbl);
++
++int bmi_mdacc_probe(struct bmi_device *bdev);
++void bmi_mdacc_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_mdacc_driver =
++{
++ .name = "bmi_mdacc",
++ .id_table = bmi_mdacc_tbl,
++ .probe = bmi_mdacc_probe,
++ .remove = bmi_mdacc_remove,
++};
++
++
++// Support functions
++
++int mdacc_get_slot_mon (struct mon *mon)
++{
++ struct pim *pim;
++ int slot;
++
++ pim = container_of(mon, struct pim, mon);
++
++ if (pim->bdev == 0) {
++ slot = -1;
++ }
++ else {
++ slot = pim->bdev->slot->slotnum;
++ }
++ return slot;
++}
++
++int mdacc_get_slot_ctl (struct ctl *ctl)
++{
++ struct pim *pim;
++ int slot;
++
++ pim = container_of(ctl, struct pim, ctl);
++
++ if (pim->bdev == 0) {
++ slot = -1;
++ }
++ else {
++ slot = pim->bdev->slot->slotnum;
++ }
++ return slot;
++}
++
++
++struct spi_device* mdacc_get_spi_mon (struct mon *mon)
++{
++ struct pim *pim;
++ struct spi_device *spi = 0;
++
++ /*
++ pim = container_of(mon, struct pim, mon);
++
++ if (pim->bdev) {
++ spi = pim->bdev->slot->slotnum;
++ }
++ */
++ return spi;
++}
++
++struct bmi_device* mdacc_get_bdev_mon (struct mon *mon)
++{
++ struct pim *pim;
++
++ pim = container_of(mon, struct pim, mon);
++ return pim->bdev;
++}
++
++int mdacc_check_bdev_md (struct md *md)
++{
++ int err;
++ struct pim *pim;
++
++ err = 0;
++ pim = container_of(md, struct pim, md);
++ if (!pim->bdev) {
++ err = 1;
++ }
++ return err;
++}
++
++int mdacc_check_bdev_acc (struct acc *acc)
++{
++ int err;
++ struct pim *pim;
++
++ err = 0;
++ pim = container_of(acc, struct pim, acc);
++ if (!pim->bdev) {
++ err = 1;;
++ }
++ return err;
++}
++
++// BMI Functions
++
++int bmi_mdacc_probe(struct bmi_device *bdev)
++{
++ int slot;
++ struct pim *pim;
++ int irq;
++ unsigned char tmp = 0;
++
++ // Module GPIO use:
++ // 0 1
++ // GPIO 3 Red LED On Off
++ // GPIO 2 Green LED On Off
++ // GPIO 1 AVR Reset Reset Normal Operation
++ // GPIO 0 Accel. Sleep Mode Sleep Normal Operation
++
++ slot = bdev->slot->slotnum;
++ pim = &bug_mdacc_pim[slot];
++
++ bmi_device_set_drvdata(bdev, pim);
++ pim->bdev = bdev;
++
++
++ // Setup GPIOs for this slot
++
++ bmi_slot_gpio_configure(slot, RED_LED | GREEN_LED | GPIO_1 | GPIO_0); //Red LED: On
++ bmi_slot_gpio_set(slot, GPIO_0);
++
++ bmi_slot_spi_enable(slot);
++
++ //AVR Reset Active time
++ mdelay(1);
++
++
++ //Take AVR out of reset
++ bmi_slot_gpio_set(slot, GPIO_1 | GPIO_0);
++
++ //AVR Reset Recovery time
++
++ mdelay (100);
++
++
++ switch (slot) {
++ case 0:
++ pim->name = "mdacc_m1";
++ break;
++ case 1:
++ pim->name = "mdacc_m2";
++ break;
++ case 2:
++ pim->name = "mdacc_m3";
++ break;
++ case 3:
++ pim->name = "mdacc_m4";
++ break;
++ }
++
++ irq = bdev->slot->status_irq;
++
++ if (mon_probe (&pim->mon, pim->name, irq, &pim->md, &pim->acc) ) {
++ printk (KERN_ERR "bmi_mdacc_probe() - mon_probe() failed.\n");
++ goto exit1;
++ }
++ if (md_probe (&pim->md, slot, &pim->mon) ) {
++ printk (KERN_ERR "bmi_mdacc_probe() - md_probe() failed.\n");
++ goto exit2;
++ }
++ if (acc_probe (&pim->acc, slot, &pim->mon) ) {
++ printk (KERN_ERR "bmi_mdacc_probe() - acc_probe() failed.\n");
++ goto exit3;
++ }
++ if (ctl_probe (&pim->ctl, slot) ) {
++ printk (KERN_ERR "bmi_mdacc_probe() - ctl_probe() failed.\n");
++ goto exit4;
++ }
++
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp | RED_LED); //Red + Green LEDs Off
++ return 0;
++
++exit4:
++ acc_remove (&pim->acc, slot);
++exit3:
++ md_remove (&pim->md, slot);
++exit2:
++ mon_remove (&pim->mon);
++
++exit1:
++ bmi_slot_spi_disable(slot);
++ bmi_device_set_drvdata (bdev, 0);
++ pim->bdev = 0;
++ // bmi_slot_gpio_write_bit (slot, 2, 1); //Green LED Off
++ tmp = bmi_slot_gpio_get(slot);
++ bmi_slot_gpio_set (slot, tmp | GREEN_LED);
++ return -1;
++}
++
++void bmi_mdacc_remove(struct bmi_device *bdev)
++{
++ int slot;
++ struct pim *pim;
++
++ slot = bdev->slot->slotnum;
++ pim = &bug_mdacc_pim[slot];
++
++ ctl_remove (&pim->ctl, slot);
++ acc_remove (&pim->acc, slot);
++ md_remove (&pim->md, slot);
++ mon_remove (&pim->mon);
++
++ bmi_slot_spi_disable(slot);
++
++ bmi_device_set_drvdata (bdev, 0);
++#if 0
++ pim->bdev = 0;
++#endif
++
++ return;
++}
++
++
++
++static __init int bmi_mdacc_init(void)
++{
++ int rc = 0;
++
++ acc_init();
++ md_init();
++ ctl_init();
++
++// Register with BMI bus.
++ rc = bmi_register_driver(&bmi_mdacc_driver);
++ if(rc) {
++ printk(KERN_ERR "bmi_mdacc_init() - bmi_register_driver failed\n");
++ return rc;
++ }
++
++ printk("BMI MDACC Driver v%s \n", BMI_MDACC_VERSION);
++ return 0;
++}
++
++static void __exit bmi_mdacc_clean(void)
++{
++// Unregister with BMI bus.
++ bmi_unregister_driver(&bmi_mdacc_driver);
++
++ ctl_clean();
++ md_clean();
++ acc_clean();
++ return;
++}
++
++module_init(bmi_mdacc_init);
++module_exit(bmi_mdacc_clean);
++
++MODULE_AUTHOR("EnCADIS Design, Inc.");
++MODULE_DESCRIPTION("BMI Motion Detector/Accelerometer Driver");
++MODULE_LICENSE("GPL");
++
++
++
++
++
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/mdacc.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef MDACC_H
++#define MDACC_H
++
++struct acc;
++struct ctl;
++struct md;
++struct mon;
++struct spi_device;
++struct bmi_device;
++
++extern int mdacc_get_slot_mon (struct mon *mon);
++extern int mdacc_get_slot_ctl (struct ctl *ctl);
++
++extern struct bmi_device* mdacc_get_bdev_mon (struct mon *mon);
++extern struct spi_device* mdacc_get_spi_mon (struct mon *mon);
++
++int mdacc_check_bdev_md (struct md *md);
++int mdacc_check_bdev_acc (struct acc *acc);
++
++struct mon *mdacc_get_mon_md(struct md *md);
++struct mon *mdacc_get_mon_acc(struct acc *acc);
++
++#endif
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/mon.c
+@@ -0,0 +1,474 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#include "mon.h"
++#include "mdacc.h"
++#include <linux/interrupt.h>
++
++#include <linux/spi/spi.h>
++
++#define work_to_mon(w) container_of(w, struct mon, work_item)
++
++enum
++{
++ MON_STATE_IDLE,
++ MON_STATE_MOTION_ONLY,
++ MON_STATE_ACC_ONLY,
++ MON_STATE_MOTION_AND_ACC
++};
++
++enum
++{
++ MON_ACTION_START_ACC,
++ MON_ACTION_START_MOTION,
++ MON_ACTION_STOP_ACC,
++ MON_ACTION_STOP_MOTION
++};
++
++
++
++
++/*
++ Spi Mode Register
++ --------------------------------
++ Timer Enable Bit 4
++ ADC Poll Enable Bit 3
++ Motion Detect Enable Bit 2
++ GSEL1:0 Bits 1:0
++
++
++ SPI Status Register
++ ------------------------------------
++ Not used Bit 7
++ Timer Enabled Bit 6
++ Adc Complete Bit 5
++ Adc Enabled Bit 4
++ Motion Detect Status Bit 3
++ Motion Detect Latched Status Bit 2
++ Motion Detect Delta Bit 1
++ Motion Detect Enabled Bit 0
++
++
++
++*/
++
++static void mon_change_state (struct mon* mon, int action)
++{
++ switch (mon->state) {
++
++ case MON_STATE_IDLE:
++
++ switch (action) {
++
++ case MON_ACTION_START_MOTION:
++ mon->state = MON_STATE_MOTION_ONLY;
++ break;
++
++ case MON_ACTION_START_ACC:
++ mon->state = MON_STATE_ACC_ONLY;
++ break;
++ }
++ break;
++
++ case MON_STATE_MOTION_ONLY:
++
++ switch (action) {
++
++ case MON_ACTION_STOP_MOTION:
++ mon->state = MON_STATE_IDLE;
++ break;
++
++ case MON_ACTION_START_ACC:
++ mon->state = MON_STATE_MOTION_AND_ACC;
++ break;
++ }
++ break;
++
++ case MON_STATE_ACC_ONLY:
++
++ switch (action) {
++
++ case MON_ACTION_STOP_ACC:
++ mon->state = MON_STATE_IDLE;
++ break;
++
++ case MON_ACTION_START_MOTION:
++ mon->state = MON_STATE_MOTION_AND_ACC;
++ break;
++ }
++ break;
++
++ case MON_STATE_MOTION_AND_ACC:
++
++ switch (action) {
++
++ case MON_ACTION_STOP_ACC:
++ mon->state = MON_STATE_MOTION_ONLY;
++ break;
++
++ case MON_ACTION_STOP_MOTION:
++ mon->state = MON_STATE_ACC_ONLY;
++ break;
++ }
++ break;
++ }
++ return;
++}
++
++int mon_start_motion (struct mon *mon)
++{
++ int err = 0;
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++ mon->regs.mode |= 0x04;
++ avr_write_mode (spi, &mon->regs);
++ mon_change_state (mon, MON_ACTION_START_MOTION);
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_start_motion() - FAIL - spi is 0.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++int mon_stop_motion (struct mon *mon)
++{
++ int err = 0;
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++ mon->regs.mode &= ~(0x04);
++ avr_write_mode (spi, &mon->regs);
++ mon_change_state (mon, MON_ACTION_STOP_MOTION);
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_stop_motion() - FAIL - spi is 0.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++
++int mon_set_config_accel (struct mon *mon, struct mdacc_accel_config *cfg)
++{
++ int err = 0;
++ unsigned char tmp;
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (cfg && spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++ if (cfg->delay_mode) {
++
++ mon->regs.timer_res = cfg->delay_resolution;
++ mon->regs.timer_msb = cfg->delay >> 8;
++ mon->regs.timer_lsb = cfg->delay;
++ mon->regs.mode |= 0x10;
++ }
++ else {
++ mon->regs.mode &= ~0x10;
++ }
++
++ if (cfg->run) {
++ mon->regs.mode |= 0x08;
++ mon_change_state (mon, MON_ACTION_START_ACC);
++ }
++ else {
++ mon->regs.mode &= ~0x08;
++ mon_change_state (mon, MON_ACTION_STOP_ACC);
++
++ }
++
++ tmp = mon->regs.mode & 0xFC;
++ tmp |= cfg->sensitivity & 0x03;
++ mon->regs.mode = tmp;
++
++ if (cfg->delay_mode) {
++ avr_write_timer_and_mode (spi, &mon->regs);
++ }
++ else {
++ avr_write_mode (spi, &mon->regs);
++ }
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_set_config_accel() - FAIL - null pointer.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++int mon_get_config_accel (struct mon *mon, struct mdacc_accel_config *cfg)
++{
++ int err = 0;
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (cfg && spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++
++ avr_read_timer_and_mode (spi, &mon->regs);
++
++
++ if (mon->regs.mode & 0x10) {
++ cfg->delay_mode = 1;
++ cfg->delay_resolution = mon->regs.timer_res;
++ cfg->delay = mon->regs.timer_msb << 8 | mon->regs.timer_lsb;
++ }
++ else {
++ cfg->delay_mode = 0;
++ cfg->delay_resolution = 1;
++ cfg->delay = 5000;
++ }
++
++ if (mon->regs.mode & 0x08) {
++ cfg->run = 1;
++ }
++ else {
++ cfg->run = 0;
++ }
++ cfg->sensitivity = mon->regs.mode & 0x03;
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_get_config_accel() - FAIL - null pointer.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++int mon_start_accel (struct mon *mon)
++{
++ int err = 0;
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++ mon->regs.mode |= 0x08;
++ avr_write_mode (spi, &mon->regs);
++ mon_change_state (mon, MON_ACTION_START_ACC);
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_start_accel() - FAIL - spi is 0.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++
++int mon_stop_accel (struct mon *mon)
++{
++ int err = 0;
++
++ struct spi_device *spi;
++
++ spi = mon->spi;
++ if (spi) {
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++
++ mon->regs.mode &= ~0x08;
++ avr_write_mode (spi, &mon->regs);
++ mon_change_state (mon, MON_ACTION_STOP_ACC);
++ up (&mon->sem);
++ }
++ else {
++ printk (KERN_ERR "mon_stop_accel() - FAIL - spi is 0.\n");
++ err = 1;
++ }
++ return err ;
++}
++
++
++int mon_status_request (struct mon* mon)
++{
++ struct spi_device *spi;
++ int err = 0;
++
++
++ spi = mon->spi;
++
++ if (!spi) {
++ printk (KERN_ERR "mon_status_request() - FAIL - spi is 0.\n");
++ err = 1;
++ }
++ else {
++
++ if (down_interruptible (&mon->sem))
++ return -ERESTARTSYS;
++ //Read the avr status register
++
++ switch (mon->state) {
++
++
++ case MON_STATE_IDLE:
++
++ avr_read_status (spi, &mon->regs);
++
++ //update md status
++ md_update (mon->md, mon->regs.status);
++ break;
++
++ case MON_STATE_MOTION_ONLY:
++
++ avr_read_status (spi, &mon->regs);
++
++ //update md status
++ md_update (mon->md, mon->regs.status);
++ break;
++
++
++ case MON_STATE_ACC_ONLY:
++
++ avr_read_status_and_adc (spi, &mon->regs);
++
++ cque_write (mon->acc->cque, &mon->regs.adc0h);
++ if (cque_is_ready_for_read (mon->acc->cque) ) {
++ wake_up_interruptible (&mon->acc->read_wait_queue);
++ }
++ break;
++
++ case MON_STATE_MOTION_AND_ACC:
++
++ avr_read_status (spi, &mon->regs);
++
++ //update md status
++ md_update (mon->md, mon->regs.status);
++
++ // adc complete status ?
++ if (mon->regs.status & 0x20) {
++ avr_read_adc (spi, &mon->regs);
++ cque_write (mon->acc->cque, &mon->regs.adc0h);
++ if (cque_is_ready_for_read (mon->acc->cque) ) {
++ wake_up_interruptible (&mon->acc->read_wait_queue);
++ }
++ }
++
++ break;
++
++ default:
++ printk (KERN_ERR "mon_work_handler() - invalid state.\n");
++
++ }
++ up (&mon->sem);
++ }
++ return err;
++}
++
++// work handler
++static void mon_work_handler (struct work_struct * work)
++{
++
++ struct mon *mon = work_to_mon(work);
++
++ if ( !mon_status_request(mon) ) {
++ enable_irq (mon->irq);
++ }
++ return;
++}
++
++// interrupt handler
++static irqreturn_t mon_irq_handler(int irq, void *dummy)
++{
++ struct mon *mon = dummy;
++
++ disable_irq_nosync(irq);
++ schedule_work (&mon->work_item);
++ return IRQ_HANDLED;
++}
++
++int mon_probe (struct mon *mon, const char *name, int irq, struct md *md, struct acc *acc)
++{
++ int err;
++ struct bmi_device *bdev;
++ unsigned long speed;
++
++ unsigned char mode;
++ unsigned char bits_per_word;
++
++ err = 1;
++ if (mon) {
++ bdev = mdacc_get_bdev_mon (mon);
++ speed = 250000;
++// speed = 125000;
++ mode = 1;
++ bits_per_word = 8;
++
++ strcpy(mon->mon_spi_info.modalias, "bug_mdacc_spi");
++ mon->mon_spi_info.max_speed_hz = speed;
++ mon->mon_spi_info.bus_num = bdev->slot->spi_bus_num;
++ mon->mon_spi_info.chip_select = bdev->slot->spi_cs;
++ mon->mon_spi_info.mode = mode;
++ mon->spi = spi_new_device(spi_busnum_to_master(mon->mon_spi_info.bus_num), &mon->mon_spi_info) ;
++ if (!mon->spi) {
++ printk (KERN_ERR "mon_probe() - bmi_device_spi_setup() failed.\n");
++ goto exit;
++ }
++
++ mon->irq = irq;
++ mon->md = md;
++ mon->acc = acc;
++ init_MUTEX (&mon->sem);
++ mon->state = MON_STATE_IDLE;
++ memset (&mon->regs, 0, sizeof (struct avr_regs) );
++
++ mon->workqueue = create_singlethread_workqueue (name);
++ if (!mon->workqueue) {
++ printk (KERN_ERR "mon_probe() - create_singlethread_workqueue() failed.\n");
++ goto exit;
++ }
++ INIT_WORK(&mon->work_item, mon_work_handler);
++
++ if (request_irq(irq, &mon_irq_handler, 0, name, mon)) {
++ printk (KERN_ERR "mon_probe() - request_irq (irq = %d) failed.\n", irq);
++ destroy_workqueue( mon->workqueue );
++ goto exit;
++ }
++ err = 0;
++ }
++exit:
++ return err;
++}
++
++
++void mon_remove (struct mon *mon)
++{
++ if (mon) {
++ free_irq(mon->irq, mon);
++ destroy_workqueue( mon->workqueue );
++ spi_unregister_device(mon->spi);
++ }
++ return;
++}
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/mdacc/mon.h
+@@ -0,0 +1,61 @@
++/*
++ * Copyright 2008 EnCADIS Designs, Inc. All Rights Reserved.
++ * Copyright 2008 Bug-Labs, Inc. All Rights Reserved.
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * Part of BMI Motion Detector Accelerometer (MDACC) Kernel Module
++ *
++ *-----------------------------------------------------------------------------
++ */
++
++#ifndef MDACC_MON_H
++#define MDACC_MON_H
++
++#include "avr.h"
++#include "md.h"
++#include "acc.h"
++
++#include <linux/workqueue.h>
++
++struct mon
++{
++ int irq;
++ struct md *md;
++ struct acc *acc;
++ struct spi_device *spi;
++ struct spi_board_info mon_spi_info;
++ struct semaphore sem;
++ int state;
++ struct avr_regs regs;
++ struct workqueue_struct *workqueue;
++ struct work_struct work_item;
++};
++
++struct md;
++struct acc;
++
++int mon_probe (struct mon *mon, const char *name, int irq, struct md *md, struct acc *acc);
++void mon_remove (struct mon *mon);
++
++int mon_start_motion (struct mon *mon);
++int mon_stop_motion (struct mon *mon);
++
++int mon_set_config_accel (struct mon *mon, struct mdacc_accel_config *cfg);
++int mon_get_config_accel (struct mon *mon, struct mdacc_accel_config *cfg);
++int mon_start_accel (struct mon *mon);
++int mon_stop_accel (struct mon *mon);
++
++int mon_status_request (struct mon *mon);
++
++
++#endif
++
+--- /dev/null
++++ git/drivers/bmi/pims/projector/Makefile
+@@ -0,0 +1,7 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_VIDEO_BMI_PROJECTOR) += bmi_projector_core.o
++bmi_projector_core-objs := bmi_projector.o ch7024.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/projector/bmi_projector.c
+@@ -0,0 +1,674 @@
++/*
++ * bmi_projector.c
++ *
++ * BMI PROJECTOR device driver
++ *
++ * Derived from: bmi_lcd.c
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/input.h>
++#include <linux/kernel.h>
++#include <linux/major.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/i2c.h>
++#include <asm/uaccess.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/miscdevice.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <mach/mxc_i2c.h>
++#include <mach/mx31bug_cpld.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/bmi/bmi_projector.h>
++#include <mach/ipu.h>
++
++#include "ch7024.h"
++
++#define DEBUG_PROJECTOR
++#undef DEBUG_PROJECTOR
++
++#define BMIPROJECTOR_VERSION "1.0" // driver version
++#define BMI_SLOT_NUM (4) // number of BMI slots
++#define MAX_STRG (40) // Max string buffer size
++#define VSYNC_DISABLE 0x0
++#define VSYNC_ENABLE 0x1
++#define PROJ_DEF_MODE 0x09 // Projector default mode of operation
++
++ // projector
++struct projector_interface {
++ char projector_type[MAX_STRG]; // text description of PROJECTOR type
++ u8 suspended; // power management state
++ u8 rotation; // screen rotation
++ u8 disp; // display number (DISP0 or DISP1)
++ u8 addr_mode; // display addressing mode
++ u8 vsync_mode; // VSYNC signal enable (VSYNC_ENABLE | VSYNC_DISABLE)
++ u8 bus_if_type; // bus type (XY | FullWoBE | FullWithBE)
++ ipu_adc_sig_cfg_t adc_sig; // IPU ADC set-up parameters
++ ipu_di_signal_cfg_t di_sig; // IPU DI set-up parameters
++};
++
++static struct projector_interface projector_interface = {
++ .projector_type = "MXCFB_PROJECTOR",
++ .suspended = 0,
++ .rotation = IPU_ROTATE_NONE,
++ .disp = DISP0,
++ .vsync_mode = VSYNC_DISABLE,
++ .bus_if_type = XY,
++ .adc_sig = { 0, 0, 0, 0, 0, 0, 0, 0, IPU_ADC_BURST_WCS, IPU_ADC_IFC_MODE_SYS80_TYPE2,
++ 16, 0, 0, IPU_ADC_SER_NO_RW },
++ .di_sig = { 0,0,0,0,0,0,0,0 }, //pjg - reserved for multiple Projector driver
++};
++
++extern void projector_config(int disp);
++extern int projector_disp_on(int disp);
++extern int projector_disp_regset(int disp, unsigned short reg, unsigned short val);
++
++struct bmi_projector;
++static int disp_mode_reg = 0x09; // Bit 3 of GPIO control register should always be maintained high
++//static int proj_mode = 0x1; // Bit 3 of GPIO control register should always be maintained high
++
++struct bmi_projector_ops {
++ void *(*config) (int disp); // Projector configuration/initialization
++ void *(*reset) (int slot); // Projector reset
++ int *(*suspend) (struct bmi_projector *bprojector); // power management
++ int *(*resume) (struct bmi_projector *bprojector); // power management
++ int *(*disp_on) (int disp); // display on
++ int *(*disp_off) (int disp); // display off
++ int (*activate) (struct bmi_projector *projector, int slot); // enable Projector
++ int (*deactivate) (struct bmi_projector *projector, int slot); // disable Projector
++};
++
++struct bmi_projector_ops bmi_projector_ops;
++
++struct bmi_projector {
++ struct projector_interface interface; // pointer to this struct is returned by config()
++ struct bmi_projector_ops projector_ops; // function pointers
++};
++
++static struct bmi_projector bmi_projector;
++
++int register_bmi_projector(struct bmi_projector *bprojector, int slot);
++int unregister_bmi_projector(struct bmi_projector *bprojector, int slot);
++
++ // private device structure
++struct pbmi_projector
++{
++ int open_flag; // force single open
++ unsigned int projector_cnt; // number of Projector's present
++ unsigned int active; // indication of Projector's presence
++ unsigned int activated[BMI_SLOT_NUM]; // indication of Projector's presence
++ int proj_mode[BMI_SLOT_NUM]; // Indicate the state of projector on the slot
++ //int disp_mode_reg[BMI_SLOT_NUM];
++
++ struct bmi_projector *bprojector[BMI_SLOT_NUM]; // BMI Projector structure - placeholder for multiple display types
++ struct bmi_device *bdev[BMI_SLOT_NUM]; // BMI device per slot
++ unsigned int interrupt[BMI_SLOT_NUM]; // input device interrupt handlers
++ char int_name[MAX_STRG]; // interrupt name
++};
++
++static struct pbmi_projector pbmi_projector; // Projector device sructure
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_projector_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_PROJECTOR,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_projector_tbl);
++
++int bmi_projector_probe(struct bmi_device *bdev);
++void bmi_projector_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_projector_driver =
++{
++ .name = "bmi_projector",
++ .id_table = bmi_projector_tbl,
++ .probe = bmi_projector_probe,
++ .remove = bmi_projector_remove,
++};
++
++void bmi_projector_config(struct bmi_projector *projector, int disp);
++
++ // probe
++int bmi_projector_probe(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++ struct i2c_adapter *adap;
++ struct bmi_projector *projector;
++ /*int first_time = 1;*/
++
++ printk(KERN_INFO "bmi_projector.c: probe slot %d\n", slot);
++
++ // check for opposite side already active
++ switch(slot) { // opposite side
++ case 0:
++ if(pbmi_projector.activated[2] == 1) {
++ printk(KERN_INFO "bmi_projector.c: probe slot %d not allowed (slot 2 already active)\n", slot);
++ bmi_slot_power_off(0);
++ pbmi_projector.bdev[0] = bdev;
++ return 0;
++ }
++ break;
++ case 1:
++ if(pbmi_projector.activated[3] == 1) {
++ printk(KERN_INFO "bmi_projector.c: probe slot %d not allowed (slot 3 already active)\n", slot);
++ bmi_slot_power_off(1);
++ pbmi_projector.bdev[1] = bdev;
++ return 0;
++ }
++ break;
++ case 2:
++ if(pbmi_projector.activated[0] == 1) {
++ printk(KERN_INFO "bmi_projector.c: probe slot %d not allowed (slot 0 already active)\n", slot);
++ bmi_slot_power_off(2);
++ pbmi_projector.bdev[2] = bdev;
++ return 0;
++ }
++ break;
++ case 3:
++ if(pbmi_projector.activated[1] == 1) {
++ printk(KERN_INFO "bmi_projector.c: probe slot %d not allowed (slot 1 already active)\n", slot);
++ bmi_slot_power_off(3);
++ pbmi_projector.bdev[3] = bdev;
++ return 0;
++ }
++ break;
++ }
++
++ adap = &bdev->adap;
++
++// bmi_slot_power_on(slot);
++
++ mdelay(500);
++
++ if (!ch7024_detect (adap))
++ {
++ /* setup for NTSC */
++ ch7024_setup (adap, PROJOUT_FMT_NTSC);
++#ifdef DEBUG_PROJECTOR
++ printk ("\nFound encoder on slot %d \n", slot);
++#endif
++ ch7024_enable (adap);
++ }
++ else
++ {
++ printk ("\nError! Failed to detect encoder chip\n");
++ return 0;
++ }
++
++ // reset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ bmi_lcd_inactive(0); // We are using Same CPLD pins for projector
++ } else {
++ bmi_lcd_inactive(1);
++ }
++
++ // FPGA PROG_0 - Active low signal
++ bmi_set_module_gpio_data(slot, 0, 0);
++ bmi_set_module_gpio_dir(slot, 0, BMI_GPIO_OUT);
++
++ /* Reset the FPGA */
++ bmi_set_module_gpio_data(slot, 1, 1);
++ bmi_set_module_gpio_dir(slot, 0, BMI_GPIO_OUT);
++ mdelay(100);
++ bmi_set_module_gpio_data(slot, 1, 0);
++
++ // unreset serial link (master)
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_lcd_active(0, 0x0, LCD_MODE_I80);
++ } else {
++ mdelay(2);
++ bmi_lcd_active(1, 0x0, LCD_MODE_I80);
++ }
++
++
++ // set up bdev/pbmi_projector pointers
++ bmi_device_set_drvdata(bdev, &pbmi_projector);
++ pbmi_projector.bdev[slot] = bdev;
++
++ // complete pbmi_projector set-up
++ pbmi_projector.projector_cnt++;
++ pbmi_projector.active = 1;
++ pbmi_projector.activated[slot] = 1;
++ pbmi_projector.proj_mode[slot] = 1;
++
++ mdelay(100);
++
++ projector = pbmi_projector.bprojector[slot];
++ if((slot == 0) || (slot == 2)) {
++ mdelay(2);
++ bmi_projector_config(projector, 0);
++ mdelay(2);
++ } else {
++ mdelay(2);
++ bmi_projector_config(projector, 1);
++ mdelay(2);
++ }
++
++ // Turn on Projctor
++ disp_mode_reg = PROJ_DEF_MODE;
++ projector_disp_regset((slot & 0x1), 0x1, disp_mode_reg);
++ // check GPIO status
++ printk(KERN_INFO "bmi_projector.c: slot %d gpio = %x\n", slot, bmi_read_gpio_data_reg(slot));
++ printk(KERN_INFO "bmi_projector.c: Projector count = %d\n", pbmi_projector.projector_cnt);
++
++ return 0;
++}
++
++ // remove
++void bmi_projector_remove(struct bmi_device *bdev)
++{
++ int slot = bdev->info->slot;
++
++ if(pbmi_projector.activated[slot] == 0)
++ return;
++
++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN);
++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN);
++
++ //de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, NULL);
++
++ // deactivate
++ pbmi_projector.activated[slot] = 0;
++ pbmi_projector.bdev[slot] = 0;
++ pbmi_projector.projector_cnt--;
++
++ if((pbmi_projector.activated[0] == 0) && (pbmi_projector.activated[2] == 0)) {
++ bmi_lcd_inactive(0); // disable serializer
++ }
++
++ if((pbmi_projector.activated[1] == 0) && (pbmi_projector.activated[3] == 0)) {
++ bmi_lcd_inactive(1); // disable serializer
++ }
++
++ if((pbmi_projector.activated[0] == 0) && (pbmi_projector.activated[1] == 0) &&
++ (pbmi_projector.activated[2] == 0) && (pbmi_projector.activated[3] == 0)) {
++ pbmi_projector.active = -1;
++ }
++
++ // enable Projector on opposite side
++ switch(slot) {
++ case 0:
++ if(pbmi_projector.bdev[2] != 0)
++ bmi_projector_probe(pbmi_projector.bdev[2]);
++ break;
++ case 1:
++ if(pbmi_projector.bdev[3] != 0)
++ bmi_projector_probe(pbmi_projector.bdev[3]);
++ break;
++ case 2:
++ if(pbmi_projector.bdev[0] != 0)
++ bmi_projector_probe(pbmi_projector.bdev[0]);
++ break;
++ case 3:
++ if(pbmi_projector.bdev[1] != 0)
++ bmi_projector_probe(pbmi_projector.bdev[1]);
++ break;
++ }
++
++ printk(KERN_INFO "bmi_projector.c: projector count = %d\n", pbmi_projector.projector_cnt);
++
++ return;
++}
++
++/*
++ * control device operations
++ */
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *filp)
++{
++ if(pbmi_projector.open_flag) {
++ return - EBUSY;
++ }
++ pbmi_projector.open_flag = 1;
++ filp->private_data = &pbmi_projector;
++ return 0;
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *filp)
++{
++ pbmi_projector.open_flag = 0;
++ return 0;
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ int slot = (__user arg) & 0xF;
++ int disp = 0;
++ int ret = 0;
++
++ // error if no projector active.
++ if(pbmi_projector.active == -1)
++ return -ENODEV;
++
++ // error if slot invalid
++ if((slot < CPLD_M1) || (slot > CPLD_M4))
++ return -ENODEV;
++
++ disp = slot & 0x1; // disp=0 for Slot 0 and 2, disp=1 for 1 and 3
++#ifdef DEBUG_PROJECTOR
++ printk (KERN_INFO "Slot No is:%d\n", slot);
++ printk (KERN_INFO "Disp No is:%d\n", disp);
++#endif
++
++ // error if no projector in chosen slot
++ if(pbmi_projector.bdev[slot] == 0)
++ return -ENODEV;
++
++ // i2c adapter
++ adap = &pbmi_projector.bdev[slot]->adap;
++
++ if( (cmd != BMI_PROJECTOR_ON) && (pbmi_projector.proj_mode[slot]/*proj_mode*/ == 0) )
++ {
++ printk(KERN_ERR "Project is in OFF state !!!\n");
++ return -EINVAL;
++ }
++
++ // ioctl's
++ switch (cmd) {
++ case BMI_PROJECTOR_ON:
++ {
++ printk(KERN_INFO "BMI_PROJECTOR turning on\n");
++ disp_mode_reg &= ~(0x3);
++ disp_mode_reg |= 0x1;
++ ch7024_enable(adap);
++ projector_disp_regset(disp, 0x1, disp_mode_reg);
++ mdelay(100);
++ projector_disp_regset(disp, 0x0, 0x1);
++ //proj_mode = 0x1;
++ pbmi_projector.proj_mode[slot] = 0x1;
++ }
++ break;
++
++ case BMI_PROJECTOR_MODE:
++ {
++ int mode = ((__user arg) & 0xF0) >> 4;
++ printk(KERN_INFO "BMI_PROJECTOR setting mode to 0x%x \n",mode);
++
++ disp_mode_reg &= ~(0x3);
++ switch(mode)
++ {
++ case PROJECTOR_ECONOMY_MODE:
++ disp_mode_reg |= 0x2; //Economy mode
++ break;
++ case PROJECTOR_BRIGHT_MODE:
++ disp_mode_reg |= 0x1;
++ break;
++ default:
++ printk(KERN_ERR "Invalid Mode\n");
++ return -EINVAL;
++ }
++
++ projector_disp_regset(disp, 0x1, disp_mode_reg);
++ }
++ break;
++
++ case BMI_PROJECTOR_OFF:
++ {
++ disp_mode_reg &= ~(0x3);
++ disp_mode_reg |= 0x3;
++ ch7024_disable(adap);
++#ifdef DEBUG_PROJECTOR
++ printk (KERN_INFO "Mode reg value is:0x%X\n", disp_mode_reg);
++#endif
++ projector_disp_regset(disp, 0x1, disp_mode_reg);
++ //proj_mode = 0x0;
++ pbmi_projector.proj_mode[slot] = 0x0;
++ }
++ break;
++
++ case BMI_PROJECTOR_BATTERY:
++ {
++ printk(KERN_INFO "BMI_PROJECTOR Staring Battery Charger for BUG\n");
++ ch7024_disable(adap);
++ projector_disp_regset(disp, 0x1, 0xF);
++ //proj_mode = 0x0;
++ pbmi_projector.proj_mode[slot] = 0x0;
++ }
++
++ break;
++ case BMI_PROJECTOR_HUE:
++ {
++ int val = ((__user arg) >> 8) & 0xff;
++ printk(KERN_INFO "BMI_PROJECTOR setting Hue to 0x%x\n",val);
++ ret = ch7024_set_hue(adap, val);
++ }
++ break;
++ case BMI_PROJECTOR_SATURATION:
++ {
++ int val = ((__user arg) >> 8) & 0xff;
++ printk(KERN_INFO "BMI_PROJECTOR setting Saturation to 0x%x\n",val);
++ ret = ch7024_set_sat(adap, val);
++ }
++ break;
++ case BMI_PROJECTOR_CONTRAST:
++ {
++ int val = ((__user arg) >> 8) & 0xff;
++ printk(KERN_INFO "BMI_PROJECTOR setting Contrast to 0x%x\n",val);
++ ret = ch7024_set_cont(adap, val);
++ }
++ break;
++ case BMI_PROJECTOR_BRIGHTNESS:
++ {
++ int val = ((__user arg) >> 8) & 0xff;
++ printk(KERN_INFO "BMI_PROJECTOR setting Brightness to 0x%x\n",val);
++ ret = ch7024_set_bright(adap, val);
++ }
++ break;
++ case BMI_PROJECTOR_SHARPNESS:
++ {
++ int val = ((__user arg) >> 8) & 0xff;
++ printk(KERN_INFO "BMI_PROJECTOR setting Sharpness to 0x%x\n",val);
++ ret = ch7024_set_sharp(adap, val);
++ }
++ break;
++ default:
++ return -ENOTTY;
++ }
++ return ret;
++}
++
++ // control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++ // BMI Projector fops
++void bmi_projector_config(struct bmi_projector *projector, int disp)
++{
++ if(pbmi_projector.active == -1) {
++ return;
++ }
++
++ if((projector) && (projector->projector_ops.config)) {
++ projector->projector_ops.config(disp);
++ }
++}
++
++void bmi_projector_reset(struct bmi_projector *projector, int slot)
++{
++ if(pbmi_projector.active == -1) {
++ return;
++ }
++
++ if((projector) && (projector->projector_ops.reset)) {
++ projector->projector_ops.reset(slot);
++ }
++}
++
++int register_bmi_projector(struct bmi_projector *projector, int slot) //pjg - placeholder for multiple Projector types
++{
++ if(!projector) {
++ return -1;
++ }
++ if((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if(pbmi_projector.bprojector[slot]) {
++ return -1;
++ }
++ else {
++ pbmi_projector.bprojector[slot] = projector;
++ }
++
++ if(projector->projector_ops.activate) {
++ projector->projector_ops.activate(projector, slot);
++ }
++
++ return 0;
++}
++
++int unregister_bmi_projector(struct bmi_projector *projector, int slot) //pjg - placeholder for multiple projector types
++{
++ if (!projector) {
++ return -1;
++ }
++ if ((slot < 0) || (slot > 3)) {
++ return -1;
++ }
++ if (pbmi_projector.bprojector[slot] != projector) {
++ return -1;
++ }
++ else {
++ pbmi_projector.bprojector [slot] = 0;
++ projector->projector_ops.deactivate(projector, slot);
++ }
++ return 0;
++}
++
++static struct miscdevice cntl_dev = {
++ MISC_DYNAMIC_MINOR,
++ "bmi_projector",
++ &cntl_fops
++};
++
++static __init int bmi_projector_init(void)
++{
++ int rc = 0;
++
++ // No projector is active.
++ pbmi_projector.active = -1;
++ pbmi_projector.activated[0] = 0;
++ pbmi_projector.activated[1] = 0;
++ pbmi_projector.activated[2] = 0;
++ pbmi_projector.activated[3] = 0;
++ pbmi_projector.proj_mode[0] = 0;
++ pbmi_projector.proj_mode[1] = 0;
++ pbmi_projector.proj_mode[2] = 0;
++ pbmi_projector.proj_mode[3] = 0;
++
++ // set up control character device - bmi_projector_control
++ rc = misc_register(&cntl_dev);
++ if(rc) {
++ printk(KERN_ERR "bmi_projector.c: Can't allocate bmi_projector_control device\n");
++ return rc;
++ }
++
++ pbmi_projector.projector_cnt = 0;
++
++ // hardware specfic set-up
++ bmi_projector.interface = projector_interface,
++ bmi_projector_ops.config = (void(*)) &projector_config;
++ bmi_projector_ops.reset = NULL; //pjg - placeholder for multiple projector hardware types
++ bmi_projector_ops.suspend = NULL; //pjg - placeholder for multiple projector hardware types
++ bmi_projector_ops.resume = NULL; //pjg - placeholder for multiple projector hardware types
++ bmi_projector_ops.disp_on = NULL; //pjg - placeholder for multiple projector hardware types
++ bmi_projector_ops.disp_off = NULL; //pjg - placeholder for multiple projector hardware types
++ bmi_projector_ops.activate = NULL; //pjg - placeholder for multiple Projector hardware types
++ bmi_projector_ops.deactivate = NULL; //pjg - placeholder for multiple Projector hardware types
++ bmi_projector.projector_ops = bmi_projector_ops;
++ pbmi_projector.bprojector[0] = &bmi_projector;
++ pbmi_projector.bprojector[1] = &bmi_projector;
++ pbmi_projector.bprojector[2] = &bmi_projector;
++ pbmi_projector.bprojector[3] = &bmi_projector;
++
++ // register with BMI
++ rc = bmi_register_driver(&bmi_projector_driver);
++ if(rc) {
++ printk(KERN_ERR "bmi_projector.c: Can't register bmi_projector_driver\n");
++
++ misc_deregister(&cntl_dev);
++
++ return rc;
++ }
++
++ printk("bmi_projector.c: BMI_Projector Driver v%s \n", BMIPROJECTOR_VERSION);
++
++ return 0;
++}
++
++static void __exit bmi_projector_clean(void)
++{
++
++ // remove control device
++ misc_deregister(&cntl_dev);
++
++ // remove bmi driver
++ bmi_unregister_driver(&bmi_projector_driver);
++
++ return;
++}
++
++module_init(bmi_projector_init);
++module_exit(bmi_projector_clean);
++
++// Exported symbols
++EXPORT_SYMBOL(register_bmi_projector);
++EXPORT_SYMBOL(unregister_bmi_projector);
++
++
++MODULE_AUTHOR("Suresh Rao");
++MODULE_DESCRIPTION("BMI projector device driver");
++MODULE_SUPPORTED_DEVICE("bmi_projector_control");
++MODULE_LICENSE("GPL");
++
+--- /dev/null
++++ git/drivers/bmi/pims/projector/ch7024.c
+@@ -0,0 +1,476 @@
++/*
++ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++ /*!
++ * @file ch7024.c
++ * @brief Driver for CH7024 TV encoder
++ *
++ * @ingroup Framebuffer
++ */
++//#define DEBUG
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <asm/uaccess.h>
++
++#include "ch7024.h"
++
++#define DEBUG_CH7024
++
++static int ch7024_found = 0;
++static struct i2c_adapter *ch7024_adap = NULL;
++
++static int i2c_ch7024_client_xfer( char *reg, int reg_len, char *buf, int num,
++ int tran_flag)
++{
++ struct i2c_msg msg[2];
++ int ret;
++ if ((ch7024_adap == NULL))
++ {
++ printk (KERN_ERR "ch7024_adap is NULL\n");
++ return -1;
++ }
++ msg[0].addr = CH7024_I2C_ADDR;
++ msg[0].len = reg_len;
++ msg[0].buf = reg;
++ msg[0].flags = tran_flag;
++ msg[0].flags &= ~I2C_M_RD;
++
++ msg[1].addr = CH7024_I2C_ADDR;
++ msg[1].len = num;
++ msg[1].buf = buf;
++
++ msg[1].flags = tran_flag;
++ if (tran_flag & I2C_M_RD) {
++ msg[1].flags |= I2C_M_RD;
++ } else {
++ msg[1].flags &= ~I2C_M_RD;
++ }
++
++ ret = i2c_transfer(ch7024_adap, msg, 2);
++ return ret;
++}
++
++static int bug_i2c_ch7024_polling_read(char *reg, int reg_len, char *buf, int num)
++{
++ return i2c_ch7024_client_xfer(reg, reg_len, buf, num,I2C_M_RD);
++}
++
++static int bug_i2c_ch7024_polling_write(char *reg, int reg_len, char *buf,
++ int num)
++{
++ return i2c_ch7024_client_xfer(reg, reg_len, buf, num, 0);
++
++}
++
++static int ch7024_read_reg(u32 reg, u32 * word, u32 len)
++{
++ int i;
++ u8 *wp = (u8 *) word;
++
++ *word = 0;
++
++ for (i = 0; i < len; i++) {
++ int ret = bug_i2c_ch7024_polling_read((char *)&reg, 1, wp, 1);
++ if (ret < 0)
++ return ret;
++ wp++;
++ reg++;
++ }
++ return 0;
++}
++
++static int ch7024_write_reg(u32 reg, u32 word, u32 len)
++{
++ return bug_i2c_ch7024_polling_write((char *)&reg, 1, (u8 *) & word, len);
++}
++
++/**
++ * PAL B/D/G/H/K/I clock and timting structures
++ */
++static struct ch7024_clock ch7024_clk_pal = {
++ .A = 0x0,
++ .P = 0x36b00,
++ .N = 0x41eb00,
++ .T = 0x3f,
++ .PLLN1 = 0x0,
++ .PLLN2 = 0x1b,
++ .PLLN3 = 0x12,
++};
++
++static struct ch7024_input_timing ch7024_timing_pal = {
++ .HTI = 950,
++ .VTI = 560,
++ .HAI = 640,
++ .VAI = 480,
++ .HW = 60,
++ .HO = 250,
++ .VW = 40,
++ .VO = 40,
++ .VOS = CH7024_VOS_PAL_BDGHKI,
++};
++
++/**
++ * NTSC_M clock and timting structures
++ * TODO: change values to work well.
++ */
++static struct ch7024_clock ch7024_clk_ntsc = {
++ .A = 0x0,
++ .P = 0x2ac90,
++ .N = 0x36fc90,
++ .T = 0x3f,
++ .PLLN1 = 0x0,
++ .PLLN2 = 0x1b,
++ .PLLN3 = 0x12,
++};
++
++static struct ch7024_input_timing ch7024_timing_ntsc = {
++ .HTI = 801,
++ .VTI = 554,
++ .HAI = 640,
++ .VAI = 480,
++ .HW = 60,
++ .HO = 101,
++ .VW = 20,
++ .VO = 54,
++ .VOS = CH7024_VOS_NTSC_M,
++};
++
++/**
++ * ch7024_setup
++ * initial the CH7024 chipset by setting register
++ * @param:
++ * vos: output video format
++ * @return:
++ * 0 successful
++ * otherwise failed
++ */
++int ch7024_setup(struct i2c_adapter *adap,int vos)
++{
++ struct ch7024_input_timing *ch_timing;
++ struct ch7024_clock *ch_clk;
++#ifdef DEBUG_CH7024
++ int i, val;
++#endif
++ ch7024_adap = adap;
++#if 0
++ if (!ch7024_found) {
++ printk(KERN_ERR "CH7024: no such device to setup!\n");
++ return -ENODEV;
++ }
++#endif
++ /* select output video format */
++ if (vos == PROJOUT_FMT_PAL) {
++ ch_timing = &ch7024_timing_pal;
++ ch_clk = &ch7024_clk_pal;
++ pr_debug("CH7024: change to PAL video\n");
++ } else if (vos == PROJOUT_FMT_NTSC) {
++ ch_timing = &ch7024_timing_ntsc;
++ ch_clk = &ch7024_clk_ntsc;
++ pr_debug("CH7024: change to NTSC video\n");
++ } else if (vos == PROJOUT_FMT_QVGA) {
++ ch_timing = &ch7024_timing_ntsc;
++ ch_clk = &ch7024_clk_ntsc;
++ pr_debug("CH7024: change to NTSC video\n");
++ }
++ else {
++
++ pr_debug("CH7024: no such video format.\n");
++ return -EINVAL;
++ }
++ printk("Resetting Chrontel Card\n");
++ ch7024_write_reg(CH7024_POWER, 0x0C, 1); /* power on, disable DAC */
++ ch7024_write_reg(CH7024_RESET, 0x00, 1); /* Reset */
++ ch7024_write_reg(CH7024_RESET, 0x03, 1); /* Reset */
++ mdelay(10);
++
++ ch7024_write_reg(CH7024_POWER, 0x0C, 1); /* power on, disable DAC */
++ ch7024_write_reg(CH7024_XTAL, CH7024_XTAL_13MHZ, 1); /* 13MHz cystal */
++ ch7024_write_reg(CH7024_SYNC, 0x0D, 1); /* Master mode, and TTL */
++ ch7024_write_reg(CH7024_IDF1, 0x00, 1);
++ ch7024_write_reg(CH7024_TVFILTER1, 0x00, 1); /* set XCH=0 */
++
++ /* set input clock and divider */
++ /* set PLL */
++ ch7024_write_reg(CH7024_PLL1, ch_clk->PLLN1, 1);
++ ch7024_write_reg(CH7024_PLL2, ch_clk->PLLN2, 1);
++ ch7024_write_reg(CH7024_PLL3, ch_clk->PLLN3, 1);
++
++ /* set A register */
++ ch7024_write_reg(CH7024_PCLK_A1, 0x00, 1);
++ ch7024_write_reg(CH7024_PCLK_A2, 0x00, 1);
++ ch7024_write_reg(CH7024_PCLK_A3, 0x00, 1);
++ ch7024_write_reg(CH7024_PCLK_A4, 0x00, 1);
++ /* set P register */
++ ch7024_write_reg(CH7024_CLK_P1, (ch_clk->P >> 16) & 0xFF, 1);
++ ch7024_write_reg(CH7024_CLK_P2, (ch_clk->P >> 8) & 0xFF, 1);
++ ch7024_write_reg(CH7024_CLK_P3, ch_clk->P & 0xFF, 1);
++ /* set N register */
++ ch7024_write_reg(CH7024_CLK_N1, (ch_clk->N >> 16) & 0xFF, 1);
++ ch7024_write_reg(CH7024_CLK_N2, (ch_clk->N >> 8) & 0xFF, 1);
++ ch7024_write_reg(CH7024_CLK_N3, ch_clk->N & 0xFF, 1);
++ /* set T register */
++ ch7024_write_reg(CH7024_CLK_T, ch_clk->T & 0xFF, 1);
++
++ /* set sub-carrier frequency generation method */
++ ch7024_write_reg(CH7024_ACIV, 0x10, 1); /* ACIV = 1, automatical SCF */
++ /* TV out pattern and DAC switch */
++ ch7024_write_reg(CH7024_OUT_FMT, (0x10 | ch_timing->VOS) & 0xFF, 1);
++
++if (vos != PROJOUT_FMT_QVGA)
++{
++
++ /* input settings */
++ ch7024_write_reg(CH7024_IDF2, 0x033, 1);
++ /* HAI/HTI VAI */
++ ch7024_write_reg(CH7024_IN_TIMING1, ((ch_timing->HTI >> 5) & 0x38) |
++ ((ch_timing->HAI >> 8) & 0x07), 1);
++ ch7024_write_reg(CH7024_IN_TIMING2, ch_timing->HAI & 0xFF, 1);
++ ch7024_write_reg(CH7024_IN_TIMING8, ch_timing->VAI & 0xFF, 1);
++ /* HTI VTI */
++ ch7024_write_reg(CH7024_IN_TIMING3, ch_timing->HTI & 0xFF, 1);
++ ch7024_write_reg(CH7024_IN_TIMING9, ch_timing->VTI & 0xFF, 1);
++ /* HW/HO(h) VW */
++ ch7024_write_reg(CH7024_IN_TIMING4, ((ch_timing->HW >> 5) & 0x18) |
++ ((ch_timing->HO >> 8) & 0x7), 1);
++ ch7024_write_reg(CH7024_IN_TIMING6, ch_timing->HW & 0xFF, 1);
++ ch7024_write_reg(CH7024_IN_TIMING11, ch_timing->VW & 0x3F, 1);
++ /* HO(l) VO/VAI/VTI */
++ ch7024_write_reg(CH7024_IN_TIMING5, ch_timing->HO & 0xFF, 1);
++ ch7024_write_reg(CH7024_IN_TIMING7, ((ch_timing->VO >> 4) & 0x30) |
++ ((ch_timing->VTI >> 6) & 0x0C) |
++ ((ch_timing->VAI >> 8) & 0x03), 1);
++ ch7024_write_reg(CH7024_IN_TIMING10, ch_timing->VO & 0xFF, 1);
++
++}
++ /* adjust the brightness */
++ ch7024_write_reg(CH7024_TVBRI, 0x90, 1);
++
++ ch7024_write_reg(CH7024_OUT_TIMING1, 0x4, 1);
++ ch7024_write_reg(CH7024_OUT_TIMING2, 0xe0, 1);
++
++ if (vos == PROJOUT_FMT_PAL) {
++ ch7024_write_reg(CH7024_V_POS1, 0x03, 1);
++ ch7024_write_reg(CH7024_V_POS2, 0x7d, 1);
++ } else {
++ ch7024_write_reg(CH7024_V_POS1, 0x02, 1);
++ ch7024_write_reg(CH7024_V_POS2, 0x7b, 1);
++ }
++
++ /* Set up the sub carrier frequency */
++ if (vos == PROJOUT_FMT_PAL) {
++ }
++ else {
++ /* We have crystal of 13MHz */
++ ch7024_write_reg(CH7024_SC_FREQ4, 0x7E, 1);
++ ch7024_write_reg(CH7024_SC_FREQ3, 0xEA, 1);
++ ch7024_write_reg(CH7024_SC_FREQ2, 0x33, 1);
++ ch7024_write_reg(CH7024_SC_FREQ1, 0x02, 1);
++
++ }
++
++#ifdef DEBUG_CH7024
++ for (i = 0; i < CH7024_SC_FREQ4; i++) {
++
++ ch7024_read_reg(i, &val, 1);
++ pr_debug("CH7024, reg[0x%x] = %x\n", i, val);
++ }
++#endif
++ return 0;
++}
++
++/**
++ * ch7024_enable
++ * Enable the ch7024 Power to begin TV encoder
++ */
++void ch7024_enable(struct i2c_adapter *adap)
++{
++ ch7024_adap = adap;
++ if (ch7024_found) {
++ ch7024_write_reg(CH7024_POWER, 0x00, 1);
++ printk("CH7024 power on.\n");
++ }
++}
++
++/**
++ * ch7024_disable
++ * Disable the ch7024 Power to stop TV encoder
++ */
++void ch7024_disable(struct i2c_adapter *adap)
++{
++ ch7024_adap = adap;
++ if (ch7024_found) {
++ ch7024_write_reg(CH7024_POWER, 0x0D, 1);
++ printk("CH7024 power off.\n");
++ }
++}
++
++int ch7024_dump (struct i2c_adapter *adap)
++ {
++ int i;
++ u32 data;
++ ch7024_adap = adap;
++ for (i =0; i <= CH7024_SC_FREQ4; i++)
++ {
++ ch7024_read_reg(i, &data, 1);
++ printk ("Offset :0%X Value :0%X\n", i, data);
++ }
++ ch7024_read_reg(0x62, &data, 1);
++ printk ("Offset :0x62 Value :0%X\n", data);
++ ch7024_read_reg(0x63, &data, 1);
++ printk ("Offset :0x63 Value :0%X\n", data);
++ ch7024_read_reg(0x7E, &data, 1);
++ printk ("Offset :0x7E Value :0%X\n", data);
++ return 0;
++ }
++EXPORT_SYMBOL(ch7024_dump);
++
++int encoder_read_reg (struct i2c_adapter *adap, u32 offset, u32 *data)
++ {
++ int ret;
++ ch7024_adap = adap;
++ ret = ch7024_read_reg(offset, data, 1);
++ if (ret < 0)
++ {
++ printk ("Encoder read register failed at offset 0x%X\n", offset);
++ return ret;
++ }
++ return 0;
++
++ }
++EXPORT_SYMBOL(encoder_read_reg);
++
++int encoder_write_reg (struct i2c_adapter *adap, u32 offset, u32 data)
++ {
++ int ret;
++ ch7024_adap = adap;
++ ret = ch7024_write_reg(offset, data, 1);
++ if (ret < 0)
++ {
++ printk ("Encoder write2 register failed at offset 0x%X\n", offset);
++ return ret;
++ }
++ return 0;
++
++ }
++EXPORT_SYMBOL(encoder_write_reg);
++
++int ch7024_detect (struct i2c_adapter *adap)
++{
++ int ret;
++ u32 id;
++ ch7024_adap = adap;
++ /*TODO client detection */
++ ret = ch7024_read_reg(CH7024_DEVID, &id, 1);
++ if (ret < 0 || id != CH7024_DEVICE_ID) {
++ printk(KERN_ERR
++ "ch7024: TV encoder not present: %d, read ret %d\n", id,
++ ret);
++ return -1;
++ }
++ printk(KERN_ERR "ch7024: TV encoder present: %x, read ret %x\n", id,
++ ret);
++ ch7024_found = 1;
++ return 0;
++
++}
++EXPORT_SYMBOL(ch7024_detect);
++
++int ch7024_set_bright (struct i2c_adapter *adap,u32 val)
++{
++ ch7024_adap = adap;
++ if (val & ~0xFF) {
++ printk ("Brighness value is out of range[0-255] %d\n", val);
++ return -1;
++ } else {
++ ch7024_write_reg(CH7024_TVBRI, val, 1);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ch7024_set_bright);
++
++int ch7024_set_cont (struct i2c_adapter *adap,u32 val)
++{
++ ch7024_adap = adap;
++ if (val & ~0x7F) {
++ printk ("Contrast value is out of range[0-127] %d\n", val);
++ return -1;
++ } else {
++ ch7024_write_reg(CH7024_TVCTA, val, 1);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ch7024_set_cont);
++
++int ch7024_set_hue (struct i2c_adapter *adap,u32 val)
++{
++ ch7024_adap = adap;
++ if (val & ~0x7F) {
++ printk ("Hue value is out of range[0-127] %d\n", val);
++ return -1;
++ } else {
++ ch7024_write_reg(CH7024_TVHUE, val, 1);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ch7024_set_hue);
++
++int ch7024_set_sharp (struct i2c_adapter *adap,u32 val)
++{
++ ch7024_adap = adap;
++ if (val & ~0x07) {
++ printk ("Sharpness value is out of range[0-8] %d\n", val);
++ return -1;
++ } else {
++ ch7024_write_reg(CH7024_TVSHARP, val, 1);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ch7024_set_sharp);
++
++int ch7024_set_sat (struct i2c_adapter *adap,u32 val)
++{
++ ch7024_adap = adap;
++ if (val & ~0x7F) {
++ printk ("Saturation value is out of range[0-127] %d\n", val);
++ return -1;
++ } else {
++ ch7024_write_reg(CH7024_TVSAT, val, 1);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ch7024_set_sat);
++
++void ch7024_set_attr (struct i2c_adapter *adap,struct ch7024_attr *attributes)
++{
++ if (!attributes)
++ return;
++ ch7024_set_bright (adap, attributes->brghtness & 0xFF);
++ ch7024_set_cont (adap, attributes->contrast & 0xFF);
++ ch7024_set_hue (adap, attributes->hue & 0xFF);
++ ch7024_set_sharp (adap, attributes->sharpness & 0xFF);
++ ch7024_set_sat (adap,attributes->saturation & 0xFF);
++ return;
++}
++
++EXPORT_SYMBOL(ch7024_set_attr);
++
++
++EXPORT_SYMBOL(ch7024_setup);
++EXPORT_SYMBOL(ch7024_enable);
++EXPORT_SYMBOL(ch7024_disable);
++
++
++
+--- /dev/null
++++ git/drivers/bmi/pims/projector/ch7024.h
+@@ -0,0 +1,166 @@
++/*
++ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*!
++ * @file ch7024.h
++ * @brief Driver for CH7024 TV encoder
++ *
++ * @ingroup Framebuffer
++ */
++#ifndef _CH7024_H_
++#define _CH7024_H_
++
++#ifdef __KERNEL__
++
++
++/* I2C bus id and device address of CH7024 chip */
++
++#define CH7024_I2C_ADDR 0x76 /* 7bits I2C address */
++
++/*!
++ * CH7024 registers
++ */
++#define CH7024_DEVID 0x00
++#define CH7024_REVID 0x01
++#define CH7024_PG 0x02
++
++#define CH7024_RESET 0x03
++#define CH7024_POWER 0x04
++#define CH7024_TVHUE 0x05
++#define CH7024_TVSAT 0x06
++#define CH7024_TVCTA 0x07
++#define CH7024_TVBRI 0x08
++#define CH7024_TVSHARP 0x09
++#define CH7024_OUT_FMT 0x0A
++#define CH7024_XTAL 0x0B
++#define CH7024_IDF1 0x0C
++#define CH7024_IDF2 0x0D
++#define CH7024_SYNC 0x0E
++#define CH7024_TVFILTER1 0x0F
++#define CH7024_TVFILTER2 0x10
++#define CH7024_IN_TIMING1 0x11
++#define CH7024_IN_TIMING2 0x12
++#define CH7024_IN_TIMING3 0x13
++#define CH7024_IN_TIMING4 0x14
++#define CH7024_IN_TIMING5 0x15
++#define CH7024_IN_TIMING6 0x16
++#define CH7024_IN_TIMING7 0x17
++#define CH7024_IN_TIMING8 0x18
++#define CH7024_IN_TIMING9 0x19
++#define CH7024_IN_TIMING10 0x1A
++#define CH7024_IN_TIMING11 0x1B
++#define CH7024_ACIV 0x1C
++#define CH7024_OUT_TIMING1 0x1E
++#define CH7024_OUT_TIMING2 0x1F
++#define CH7024_V_POS1 0x20
++#define CH7024_V_POS2 0x21
++#define CH7024_H_POS1 0x22
++#define CH7024_H_POS2 0x23
++#define CH7024_PCLK_A1 0x24
++#define CH7024_PCLK_A2 0x25
++#define CH7024_PCLK_A3 0x26
++#define CH7024_PCLK_A4 0x27
++#define CH7024_CLK_P1 0x28
++#define CH7024_CLK_P2 0x29
++#define CH7024_CLK_P3 0x2A
++#define CH7024_CLK_N1 0x2B
++#define CH7024_CLK_N2 0x2C
++#define CH7024_CLK_N3 0x2D
++#define CH7024_CLK_T 0x2E
++#define CH7024_PLL1 0x2F
++#define CH7024_PLL2 0x30
++#define CH7024_PLL3 0x31
++#define CH7024_SC_FREQ1 0x34
++#define CH7024_SC_FREQ2 0x35
++#define CH7024_SC_FREQ3 0x36
++#define CH7024_SC_FREQ4 0x37
++#define CH7024_DATA_IO 0x63
++
++/*!
++ * CH7024 register values
++ */
++/* video output formats */
++#define CH7024_VOS_NTSC_M 0x0
++#define CH7024_VOS_NTSC_J 0x1
++#define CH7024_VOS_NTSC_443 0x2
++#define CH7024_VOS_PAL_BDGHKI 0x3
++#define CH7024_VOS_PAL_M 0x4
++#define CH7024_VOS_PAL_N 0x5
++#define CH7024_VOS_PAL_NC 0x6
++#define CH7024_VOS_PAL_60 0x7
++/* crystal predefined */
++#define CH7024_XTAL_13MHZ 0x4
++#define CH7024_XTAL_26MHZ 0xB
++#define CH7024_XTAL_27MHZ 0xC
++
++/* chip ID */
++#define CH7024_DEVICE_ID 0x45
++
++/* clock source define */
++#define CLK_HIGH 0
++#define CLK_LOW 1
++
++/* CH7024 presets structs */
++struct ch7024_clock {
++ u32 A;
++ u32 P;
++ u32 N;
++ u32 T;
++ u8 PLLN1;
++ u8 PLLN2;
++ u8 PLLN3;
++};
++
++struct ch7024_input_timing {
++ u32 HTI;
++ u32 VTI;
++ u32 HAI;
++ u32 VAI;
++ u32 HW;
++ u32 HO;
++ u32 VW;
++ u32 VO;
++ u32 VOS;
++};
++
++struct ch7024_attr{
++ u32 brghtness;
++ u32 sharpness;
++ u32 hue;
++ u32 contrast;
++ u32 saturation;
++};
++
++/* function declare, used by bmi projector module */
++int ch7024_setup (struct i2c_adapter *adap,int vos);
++void ch7024_enable (struct i2c_adapter *adap);
++void ch7024_disable (struct i2c_adapter *adap);
++int ch7024_detect (struct i2c_adapter *adap);
++void ch7024_set_attr (struct i2c_adapter *adap, struct ch7024_attr *attributes);
++int ch7024_set_sat (struct i2c_adapter *adap, u32 val);
++int ch7024_set_sharp (struct i2c_adapter *adap, u32 val);
++int ch7024_set_hue (struct i2c_adapter *adap, u32 val);
++int ch7024_set_cont (struct i2c_adapter *adap, u32 val);
++int ch7024_set_bright (struct i2c_adapter *adap, u32 val);
++int ch7024_dump (struct i2c_adapter *adap);
++int encoder_read_reg (struct i2c_adapter *adap, u32 offset, u32 *data);
++int encoder_write_reg (struct i2c_adapter *adap, u32 offset, u32 data);
++
++#endif /* __KERNEL__ */
++
++/* output video format */
++#define PROJOUT_FMT_PAL 0x01
++#define PROJOUT_FMT_NTSC 0x02
++#define PROJOUT_FMT_QVGA 0x03
++
++#endif /* _CH7024_H_ */
+--- /dev/null
++++ git/drivers/bmi/pims/sensor/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BMI_SENSOR) += bmi_sensor.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/sensor/bmi_sensor.c
+@@ -0,0 +1,4321 @@
++/*
++ * bmi_sensor.c
++ *
++ * BMI sensor device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/wait.h>
++#include <linux/workqueue.h>
++
++#include <asm/uaccess.h>
++#include <asm/arch-mxc/mxc_i2c.h>
++
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_sensor.h>
++
++#define BMISENSOR_VERSION "1.0"
++
++#define work_to_sensor(w) container_of(w, struct bmi_sensor, work_item)
++#define dev_to_bmi_device(d) container_of(d, struct bmi_device, dev)
++
++/*
++ * Global variables
++ */
++
++static ushort factory_test = 0;
++static int eeprom_init = 0;
++static ushort xdac_init = 0;
++static ushort ydac_init = 0;
++static ushort zdac_init = 0;
++static ushort fcc_test = 0;
++
++// private device structure
++struct bmi_sensor
++{
++ struct semaphore sem; // bmi_sensor mutex
++ struct bmi_device *bdev; // BMI device
++ struct cdev cdev; // control device
++ struct device *class_dev; // control class device
++ struct sensor_eeprom_raw eeprom; // eeprom contents
++ char int_name[20]; // interrupt name
++ struct workqueue_struct *workqueue; // interrupt work queue
++ struct work_struct work_item; // interrupt work structure
++ char work_name[20]; // workqueue name
++ wait_queue_head_t pl_wait_queue; // Proximity/Light interrupt wait queue
++ unsigned char pl_int_en; // Proximity/Light interrupts are enabled
++ unsigned char pl_int_fl; // Proximity/Light interrupt occurred
++ wait_queue_head_t temp_wait_queue; // Temperature interrupt wait queue
++ unsigned char temp_int_en; // Temperature interrupts are enabled
++ unsigned char temp_int_fl; // Temperature interrupt occurred
++ wait_queue_head_t mot_wait_queue; // Motion interrupt wait queue
++ unsigned char mot_int_en; // Motion interrupts are enabled
++ unsigned char mot_int_fl; // Motion interrupt occurred
++ unsigned int mot_state; // previous motion detector state
++ wait_queue_head_t acc_wait1_queue; // Accelerometer interrupt wait queue
++ unsigned char acc_int1_en; // Accelerometer interrupts are enabled
++ unsigned char acc_int1_fl; // Accelerometer interrupt occurred
++ wait_queue_head_t acc_wait2_queue; // Accelerometer interrupt wait queue
++ unsigned char acc_int2_en; // Accelerometer interrupts are enabled
++ unsigned char acc_int2_fl; // Accelerometer interrupt occurred
++ wait_queue_head_t usb_wait_queue; // USB interrupt wait queue
++ unsigned char usb_int_en; // USB interrupts are enabled
++ unsigned char usb_int_fl; // USB interrupt occurred
++ wait_queue_head_t dcomp_wait_queue; // Digital compass interrupt wait queue
++ unsigned char dcomp_int_en; // Digital compass interrupts are enabled
++ unsigned char dcomp_int_fl; // Digital compass interrupt occurred
++ unsigned int aprox_duration; // Analog Proximity LED burst duration (ms)
++ struct timer_list aprox_timer; // Analog Proximity LED burst timer
++ wait_queue_head_t aprox_wait_queue; // Analog Proximity timer wait queue
++ unsigned char aprox_int_en; // Analog Proximity timer are enabled
++ unsigned char aprox_int_fl; // Analog Proximity timer occurred
++ wait_queue_head_t dlight_wait_queue; // Digital Light interrupt wait queue
++ unsigned char dlight_int_en; // Digital Light interrupts are enabled
++ unsigned char dlight_int_fl; // Digital Light interrupt occurred
++ unsigned int comp_xsf; // Compass calibration
++ unsigned int comp_ysf; // Compass calibration
++ unsigned int comp_zsf; // Compass calibration
++ unsigned int comp_xoff; // Compass calibration
++ unsigned int comp_yoff; // Compass calibration
++ unsigned int comp_zoff; // Compass calibration
++};
++
++static struct bmi_sensor bmi_sensor[4]; // per slot device structure
++static int major; // control device major
++
++/*
++ * BMI set up
++ */
++
++// BMI device ID table
++static struct bmi_device_id bmi_sensor_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_SENSOR,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_sensor_tbl);
++
++int bmi_sensor_probe(struct bmi_device *bdev);
++void bmi_sensor_remove(struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_sensor_driver =
++{
++ .name = "bmi_sensor",
++ .id_table = bmi_sensor_tbl,
++ .probe = bmi_sensor_probe,
++ .remove = bmi_sensor_remove,
++};
++
++/*
++ * I2C set up
++ */
++
++// IOX
++// write byte to I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// ADC
++// write byte to ADC
++static int WriteByte_ADC(struct i2c_adapter *adap, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[1];
++ int num_msgs;
++
++ wmsg[0].addr = BMI_ADC_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &data;
++
++ num_msgs = 1;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 1) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_ADC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read data from ADC
++static int ReadByte_ADC(struct i2c_adapter *adap, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[1];
++ int num_msgs;
++
++ rmsg[0].addr = BMI_ADC_I2C_ADDRESS;
++ rmsg[0].flags = I2C_M_RD; // read
++ rmsg[0].len = 2;
++ rmsg[0].buf = data;
++
++ num_msgs = 1;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 1) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_ADC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// Proximity/Light and Digital Light (same I2c address and format)
++// write byte to I2C PL
++static int WriteByte_PL(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_PL_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_PL_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_PL() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte from I2C PL
++static int ReadByte_PL(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_PL_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_PL_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_PL() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// write byte to I2C PL SYNC
++static int WriteByte_PL_SYNC(struct i2c_adapter *adap)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[1];
++ int num_msgs;
++ unsigned char offset = SENSOR_PL_EXT_SYNC;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_PL_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ num_msgs = 1;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 1) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_PL_SYNC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// write byte to I2C DL Interrupt Clear
++static int WriteByte_DL_IC(struct i2c_adapter *adap)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[1];
++ int num_msgs;
++ unsigned char offset = SENSOR_DL_INT_CLR;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_DLIGHT_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ num_msgs = 1;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 1) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_DL_IC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// Temperature
++// write byte to Temperature sensor
++static int WriteByte_TEMP(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_TEMP_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_TEMP_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_TEMP() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte from Temperature sensor
++static int ReadByte_TEMP(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_TEMP_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_TEMP_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_TEMP() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// Accelerometer
++// write byte to I2C Accelerometer
++static int WriteByte_ACC(struct i2c_adapter *adap, struct sensor_acc_rw *acc_rw)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_ACCEL_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &acc_rw->address;
++
++ wmsg[1].addr = BMI_ACCEL_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = acc_rw->data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte(s) from Acceleromter
++static int ReadByte_ACC(struct i2c_adapter *adap, struct sensor_acc_rw *acc_rw)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_ACCEL_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &acc_rw->address;
++
++ rmsg[1].addr = BMI_ACCEL_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = acc_rw->count;
++ rmsg[1].buf = acc_rw->data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_ACC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// digital compass
++// write byte to digital compass
++static int WriteByte_DCOMP(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_DCOMP_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_DCOMP_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_DCOMP() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte from digital compass
++static int ReadByte_DCOMP(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_DCOMP_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_DCOMP_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_DCOMP() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// EEPROM
++// write byte to I2C EEPROM
++static int WriteByte_EE(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_MEE_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_MEE_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "WriteByte_EE() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// read byte from I2C EEPROM
++static int ReadByte_EE(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_MEE_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_MEE_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk(KERN_ERR "ReadByte_EE() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *file)
++{
++ struct bmi_sensor *sensor;
++
++ sensor = container_of(inode->i_cdev, struct bmi_sensor, cdev);
++ file->private_data = sensor;
++ return 0;
++
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++// analog proximity timer function
++void aptimer(unsigned long arg)
++{
++ struct bmi_sensor *sensor = (struct bmi_sensor *) arg;
++ int ret;
++
++ del_timer (&sensor->aprox_timer);
++
++ // wake sleepers
++ ret = down_interruptible(&sensor->sem);
++ sensor->aprox_int_en = 0;
++ sensor->aprox_int_fl = 1;
++ up(&sensor->sem);
++ wake_up_all(&sensor->aprox_wait_queue);
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++ struct bmi_sensor *sensor = (struct bmi_sensor *)(file->private_data);
++ int slot;
++ int ret = 0;
++
++ // error if sensor not present
++ if(sensor->bdev == 0)
++ return -ENODEV;
++
++ slot = bmi_device_get_slot(sensor->bdev);
++ adap = bmi_device_get_i2c_adapter(sensor->bdev);
++
++ // ioctl's
++ switch(cmd) {
++
++ case BMI_SENSOR_RLEDOFF:
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_RED_LED, SENSOR_GPIO_LED_OFF); // Red LED=OFF
++ break;
++
++ case BMI_SENSOR_RLEDON:
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_RED_LED, SENSOR_GPIO_LED_ON); // Red LED=ON
++ break;
++
++ case BMI_SENSOR_GLEDOFF:
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_GREEN_LED, SENSOR_GPIO_LED_OFF); // Green LED=OFF
++ break;
++
++ case BMI_SENSOR_GLEDON:
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_GREEN_LED, SENSOR_GPIO_LED_ON); // Green LED=ON
++ break;
++
++ case BMI_SENSOR_GETSTAT:
++ {
++ int read_data;
++
++ if(ReadByte_IOX(adap, IOX_INPUT0_REG, &iox_data))
++ return -ENODEV;
++ read_data = iox_data;
++
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ return -ENODEV;
++ read_data |= (iox_data << 8) | (bmi_read_gpio_data_reg(slot) << 16);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_ADCWR:
++ {
++ unsigned char adc_data;
++
++ if(sensor->eeprom.adc_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ adc_data = (unsigned char) (arg & 0xFF);
++ if(WriteByte_ADC(adap, adc_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_ADCRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.adc_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_HUMRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.humidity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_HUMIDITY | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_ACOMPRST:
++ {
++ if(sensor->eeprom.acompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_IOX(adap, IOX_INPUT0_REG, &iox_data))
++ return -ENODEV;
++
++ iox_data &= ~(0x1 << SENSOR_IOX_COMP_RS_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++
++ mdelay(5);
++
++ iox_data |= (0x1 << SENSOR_IOX_COMP_RS_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_ACOMPXRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.acompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_X | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_ACOMPYRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.acompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Y | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_ACOMPZRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.acompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Z | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_PLWR:
++ {
++ struct sensor_pl_rw *pl = NULL;
++ unsigned char pl_data;
++
++ if(sensor->eeprom.light_proximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((pl = kmalloc(sizeof(struct sensor_pl_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(pl, (struct sensor_pl_rw *) arg, sizeof(struct sensor_pl_rw))) {
++ kfree(pl);
++ return -EFAULT;
++ }
++
++ pl_data = pl->cmd1;
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->cmd2;
++ if(WriteByte_PL(adap, SENSOR_PL_CMD2, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_lt_lsb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_LT_LSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_lt_msb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_LT_MSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_ht_lsb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_HT_LSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_ht_msb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_HT_MSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ kfree(pl);
++ }
++ break;
++
++ case BMI_SENSOR_PLRD:
++ {
++ struct sensor_pl_rw *pl = NULL;
++ unsigned char pl_data;
++
++ if(sensor->eeprom.light_proximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((pl = kmalloc(sizeof(struct sensor_pl_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ if(ReadByte_PL(adap, SENSOR_PL_CMD1, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->cmd1 = pl_data;
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->dm = pl_data;
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_LSB, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->dl = pl_data;
++
++ if(copy_to_user((struct sensor_pl_rw *) arg, pl, sizeof(struct sensor_pl_rw))) {
++ kfree(pl);
++ return -EFAULT;
++ }
++
++ kfree(pl);
++ }
++ break;
++
++ case BMI_SENSOR_PL_SYNC:
++ {
++ if(sensor->eeprom.light_proximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_PL_SYNC(adap))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_PL_IWAIT:
++ {
++ struct sensor_pl_rw *pl = NULL;
++ unsigned char pl_data;
++
++ if(sensor->eeprom.light_proximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((pl = kmalloc(sizeof(struct sensor_pl_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(pl, (struct sensor_pl_rw *) arg, sizeof(struct sensor_pl_rw))) {
++ kfree(pl);
++ return -EFAULT;
++ }
++
++ pl_data = pl->cmd1;
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->cmd2;
++ if(WriteByte_PL(adap, SENSOR_PL_CMD2, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_lt_lsb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_LT_LSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_lt_msb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_LT_MSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_ht_lsb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_HT_LSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ pl_data = pl->int_ht_msb;
++ if(WriteByte_PL(adap, SENSOR_PL_INT_HT_MSB, pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->pl_int_en = 1;
++ sensor->pl_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->pl_wait_queue, (sensor->pl_int_fl == 1));
++ if(ret)
++ return ret;
++
++ if(ReadByte_PL(adap, SENSOR_PL_CMD1, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->cmd1 = pl_data;
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->dm = pl_data;
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_LSB, &pl_data)) {
++ kfree(pl);
++ return -ENODEV;
++ }
++ pl->dl = pl_data;
++
++ if(copy_to_user((struct sensor_pl_rw *) arg, pl, sizeof(struct sensor_pl_rw))) {
++ kfree(pl);
++ return -EFAULT;
++ }
++
++ kfree(pl);
++ }
++ break;
++
++ case BMI_SENSOR_SNDARD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.sound_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_AVG | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_SNDPRD:
++ case BMI_SENSOR_SNDIRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.sound_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ // read peak
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_PEAK | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ // clear peak
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ return -ENODEV;
++
++ iox_data &= ~(0x1 << SENSOR_IOX_S_PK_CLR_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ return -ENODEV;
++
++ mdelay(1);
++
++ iox_data |= (0x1 << SENSOR_IOX_S_PK_CLR_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ return -ENODEV;
++
++ if(cmd == BMI_SENSOR_SNDPRD) {
++ // return data
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ } else {
++
++ // read peak
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_PEAK | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ // return data
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++
++ }
++ break;
++
++ case BMI_SENSOR_TEMPWR:
++ {
++ struct sensor_temp_rw *temp = NULL;
++ unsigned char temp_addr;
++ unsigned char temp_data;
++
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((temp = kmalloc(sizeof(struct sensor_temp_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(temp, (struct sensor_temp_rw *) arg, sizeof(struct sensor_temp_rw))) {
++ kfree(temp);
++ return -EFAULT;
++ }
++
++ temp_addr = temp->address;
++ temp_data = temp->d1;
++ if(WriteByte_TEMP(adap, temp_addr, temp_data)) {
++ kfree(temp);
++ return -ENODEV;
++ }
++
++ kfree(temp);
++ }
++ break;
++
++ case BMI_SENSOR_TEMPRD:
++ {
++ struct sensor_temp_rw *temp = NULL;
++ unsigned char temp_addr;
++ unsigned char temp_data;
++
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((temp = kmalloc(sizeof(struct sensor_temp_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(temp, (struct sensor_temp_rw *) arg, sizeof(struct sensor_temp_rw))) {
++ kfree(temp);
++ return -EFAULT;
++ }
++
++ temp_addr = temp->address;
++ if(ReadByte_TEMP(adap, temp_addr, &temp_data)) {
++ kfree(temp);
++ return -ENODEV;
++ }
++
++ temp->d1 = temp_data;
++ if(copy_to_user((struct sensor_temp_rw *) arg, temp, sizeof(struct sensor_temp_rw))) {
++ kfree(temp);
++ return -EFAULT;
++ }
++
++ kfree(temp);
++ }
++ break;
++
++ case BMI_SENSOR_TEMPRD_SL:
++ {
++ unsigned int read_data;
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_MSB, &temp_datam)) {
++ return -ENODEV;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_LSB, &temp_datal)) {
++ return -ENODEV;
++ }
++
++ read_data = (temp_datam << 8) | temp_datal;
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++
++ }
++ break;
++
++ case BMI_SENSOR_TEMPRD_SR:
++ {
++ unsigned int read_data;
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_MSB, &temp_datam)) {
++ return -ENODEV;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_LSB, &temp_datal)) {
++ return -ENODEV;
++ }
++
++ read_data = (temp_datam << 8) | temp_datal;
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++
++ }
++ break;
++
++ case BMI_SENSOR_TEMPRD_UR:
++ {
++ unsigned int read_data;
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_MSB, &temp_datam)) {
++ return -ENODEV;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_LSB, &temp_datal)) {
++ return -ENODEV;
++ }
++
++ read_data = (temp_datam << 8) | temp_datal;
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++
++ }
++ break;
++
++ case BMI_SENSOR_TEMP_IWAIT:
++ {
++ if(sensor->eeprom.temperature_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->temp_int_en = 1;
++ sensor->temp_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->temp_wait_queue, (sensor->temp_int_fl == 1));
++ if(ret)
++ return ret;
++ }
++ break;
++
++ case BMI_SENSOR_MOTRD:
++ {
++ unsigned int read_data;
++
++ if(sensor->eeprom.motion_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ read_data = bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET);
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++
++ }
++ break;
++
++ case BMI_SENSOR_MOT_IWAIT:
++ {
++ unsigned int read_data;
++
++ if(sensor->eeprom.motion_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->mot_int_en = 1;
++ sensor->mot_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->mot_wait_queue, (sensor->mot_int_fl == 1));
++ if(ret)
++ return ret;
++
++ read_data = bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET);
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++
++ }
++ break;
++
++ case BMI_SENSOR_ACCWR:
++ {
++ struct sensor_acc_rw *acc = NULL;
++
++ if((sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT)
++ && (sensor->eeprom.acc302_present != SENSOR_DEVICE_PRESENT))
++ return -ENODEV;
++
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(acc, (struct sensor_acc_rw *) arg, sizeof(struct sensor_acc_rw))) {
++ kfree(acc);
++ return -EFAULT;
++ }
++
++ if(WriteByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ kfree(acc);
++ }
++ break;
++
++ case BMI_SENSOR_ACCRD:
++ {
++ struct sensor_acc_rw *acc = NULL;
++
++ if((sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT)
++ && (sensor->eeprom.acc302_present != SENSOR_DEVICE_PRESENT))
++ return -ENODEV;
++
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(acc, (struct sensor_acc_rw *) arg, sizeof(struct sensor_acc_rw))) {
++ kfree(acc);
++ return -EFAULT;
++ }
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ if(copy_to_user((struct sensor_acc_rw *) arg, acc, sizeof(struct sensor_acc_rw))) {
++ kfree(acc);
++ return -EFAULT;
++ }
++
++ kfree(acc);
++ }
++ break;
++
++ case BMI_SENSOR_ACCXRD:
++ {
++ struct sensor_acc_rw *acc = NULL;
++ unsigned int read_data;
++
++ if(sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT) {
++
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_ACC_DX0;
++ acc->count = 2;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = (acc->data[1] << 8) | acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else if(sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT) {
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_A3_OUTX;
++ acc->count = 1;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else {
++ return -ENODEV;
++ }
++
++ kfree(acc);
++ }
++ break;
++
++ case BMI_SENSOR_ACCYRD:
++ {
++ struct sensor_acc_rw *acc = NULL;
++ unsigned int read_data;
++
++ if(sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT) {
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_ACC_DY0;
++ acc->count = 2;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = (acc->data[1] << 8) | acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else if(sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT) {
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_A3_OUTY;
++ acc->count = 1;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else {
++ return -ENODEV;
++ }
++
++ kfree(acc);
++ }
++ break;
++
++ case BMI_SENSOR_ACCZRD:
++ {
++ struct sensor_acc_rw *acc = NULL;
++ unsigned int read_data;
++
++ if(sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT) {
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_ACC_DZ0;
++ acc->count = 2;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = (acc->data[1] << 8) | acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else if(sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT) {
++ if ((acc = kmalloc(sizeof(struct sensor_acc_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ acc->address = SENSOR_A3_OUTZ;
++ acc->count = 1;
++
++ if(ReadByte_ACC(adap, acc)) {
++ kfree(acc);
++ return -ENODEV;
++ }
++
++ read_data = acc->data[0];
++ if(put_user(read_data, (int __user *) arg)) {
++ kfree(acc);
++ return -EFAULT;
++ }
++ } else {
++ return -ENODEV;
++ }
++
++ kfree(acc);
++ }
++ break;
++
++ case BMI_SENSOR_ACC_I1WAIT:
++ {
++ if((sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT)
++ && (sensor->eeprom.acc302_present != SENSOR_DEVICE_PRESENT))
++ return -ENODEV;
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->acc_int1_en = 1;
++ sensor->acc_int1_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->acc_wait1_queue, (sensor->acc_int1_fl == 1));
++ if(ret)
++ return ret;
++ }
++ break;
++
++ case BMI_SENSOR_ACC_I2WAIT:
++ {
++ if((sensor->eeprom.accel_present != SENSOR_DEVICE_PRESENT)
++ && (sensor->eeprom.acc302_present != SENSOR_DEVICE_PRESENT))
++ return -ENODEV;
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->acc_int2_en = 1;
++ sensor->acc_int2_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->acc_wait2_queue, (sensor->acc_int2_fl == 1));
++ if(ret)
++ return ret;
++ }
++ break;
++
++ case BMI_SENSOR_EEWR:
++ {
++ struct sensor_rw *ee = NULL;
++ unsigned char ee_addr;
++ unsigned char ee_data;
++
++ if ((ee = kmalloc(sizeof(struct sensor_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(ee, (struct sensor_rw *) arg, sizeof(struct sensor_rw))) {
++ kfree(ee);
++ return -EFAULT;
++ }
++
++ ee_addr = ee->address;
++ ee_data = ee->data;
++ if(WriteByte_EE(adap, ee_addr, ee_data)) {
++ kfree(ee);
++ return -ENODEV;
++ }
++
++ kfree(ee);
++ }
++ break;
++
++ case BMI_SENSOR_EERD:
++ {
++ struct sensor_rw *ee = NULL;
++ unsigned char ee_addr;
++ unsigned char ee_data;
++
++ if ((ee = kmalloc(sizeof(struct sensor_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(ee, (struct sensor_rw *) arg, sizeof(struct sensor_rw))) {
++ kfree(ee);
++ return -EFAULT;
++ }
++
++ ee_addr = ee->address;
++ if(ReadByte_EE(adap, ee_addr, &ee_data)) {
++ kfree(ee);
++ return -ENODEV;
++ }
++
++ ee->data = ee_data;
++ if(copy_to_user((struct sensor_rw *) arg, ee, sizeof(struct sensor_rw))) {
++ kfree(ee);
++ return -EFAULT;
++ }
++
++ kfree(ee);
++ }
++ break;
++
++ case BMI_SENSOR_MOT_IE:
++ {
++ if(sensor->eeprom.motion_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_IOX(adap, IOX_OUTPUT0_REG, &iox_data))
++ return -ENODEV;
++
++ if(arg == BMI_SENSOR_ON)
++ iox_data |= (0x1 << SENSOR_IOX_MOT_EN);
++ else
++ iox_data &= ~(0x1 << SENSOR_IOX_MOT_EN);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_USB_IWAIT:
++ {
++ ret = down_interruptible(&sensor->sem);
++ sensor->usb_int_en = 1;
++ sensor->usb_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->usb_wait_queue, (sensor->usb_int_fl == 1));
++ if(ret)
++ return ret;
++ }
++ break;
++
++ case BMI_SENSOR_USB_PWR_EN:
++ {
++ if(ReadByte_IOX(adap, IOX_OUTPUT0_REG, &iox_data))
++ return -ENODEV;
++
++ if(arg == BMI_SENSOR_ON)
++ iox_data |= (0x1 << SENSOR_IOX_USB_EN);
++ else
++ iox_data &= ~(0x1 << SENSOR_IOX_USB_EN);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_HUM_PWR_EN:
++ {
++ if(ReadByte_IOX(adap, IOX_OUTPUT0_REG, &iox_data))
++ return -ENODEV;
++
++ if(arg == BMI_SENSOR_ON)
++ iox_data |= (0x1 << SENSOR_IOX_HUM_EN);
++ else
++ iox_data &= ~(0x1 << SENSOR_IOX_HUM_EN);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_DCOM_RST:
++ {
++ if(ReadByte_IOX(adap, IOX_OUTPUT0_REG, &iox_data))
++ return -ENODEV;
++
++ if(arg == BMI_SENSOR_ON)
++ iox_data |= (0x1 << SENSOR_IOX_COMP_RS_N);
++ else
++ iox_data &= ~(0x1 << SENSOR_IOX_COMP_RS_N);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, iox_data))
++ return -ENODEV;
++
++ }
++ break;
++
++ case BMI_SENSOR_COM_GCAL:
++ {
++ struct sensor_comp_cal *cal = NULL;
++ unsigned char ee_datam;
++ unsigned char ee_datal;
++
++ if ((cal = kmalloc(sizeof(struct sensor_comp_cal), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ if(ReadByte_EE(adap, 0x0, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0x1, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->xsf = (ee_datam << 8) | ee_datal;
++
++ if(ReadByte_EE(adap, 0x2, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0x3, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->ysf = (ee_datam << 8) | ee_datal;
++
++ if(ReadByte_EE(adap, 0x4, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0x5, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->zsf = (ee_datam << 8) | ee_datal;
++
++ if(ReadByte_EE(adap, 0x6, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0x7, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->xoff = (ee_datam << 8) | ee_datal;
++
++ if(ReadByte_EE(adap, 0x8, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0x9, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->yoff = (ee_datam << 8) | ee_datal;
++
++ if(ReadByte_EE(adap, 0xA, &ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(ReadByte_EE(adap, 0xB, &ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ cal->zoff = (ee_datam << 8) | ee_datal;
++
++ if(copy_to_user((struct sensor_comp_cal *) arg, cal, sizeof(struct sensor_comp_cal))) {
++ kfree(cal);
++ return -EFAULT;
++ }
++
++ kfree(cal);
++ }
++ break;
++
++ case BMI_SENSOR_COM_SCAL:
++ {
++ struct sensor_comp_cal *cal = NULL;
++ unsigned char ee_datam;
++ unsigned char ee_datal;
++
++ if ((cal = kmalloc(sizeof(struct sensor_comp_cal), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(cal, (struct sensor_comp_cal *) arg, sizeof(struct sensor_comp_cal))) {
++ kfree(cal);
++ return -EFAULT;
++ }
++
++ sensor->comp_xsf = cal->xsf;
++ sensor->comp_ysf = cal->ysf;
++ sensor->comp_zsf = cal->zsf;
++ sensor->comp_xoff = cal->xoff;
++ sensor->comp_xoff = cal->xoff;
++ sensor->comp_zoff = cal->zoff;
++
++ ee_datam = (unsigned char) ((cal->xsf >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->xsf & 0xff);
++
++ if(WriteByte_EE(adap, 0x0, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0x1, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ ee_datam = (unsigned char) ((cal->ysf >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->ysf & 0xff);
++
++ if(WriteByte_EE(adap, 0x2, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0x3, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ ee_datam = (unsigned char) ((cal->zsf >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->zsf & 0xff);
++
++ if(WriteByte_EE(adap, 0x4, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0x5, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ ee_datam = (unsigned char) ((cal->xoff >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->xoff & 0xff);
++
++ if(WriteByte_EE(adap, 0x6, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0x7, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ ee_datam = (unsigned char) ((cal->yoff >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->yoff & 0xff);
++
++ if(WriteByte_EE(adap, 0x8, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0x9, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ ee_datam = (unsigned char) ((cal->zoff >> 8) & 0xff);
++ ee_datal = (unsigned char) (cal->zoff & 0xff);
++
++ if(WriteByte_EE(adap, 0xA, ee_datam)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ if(WriteByte_EE(adap, 0xB, ee_datal)) {
++ kfree(cal);
++ return -ENODEV;
++ }
++
++ kfree(cal);
++ }
++ break;
++
++ case BMI_SENSOR_DCWR:
++ {
++ struct sensor_rw *dc = NULL;
++ unsigned char dc_addr;
++ unsigned char dc_data;
++
++ if(sensor->eeprom.dcompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((dc = kmalloc(sizeof(struct sensor_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dc, (struct sensor_rw *) arg, sizeof(struct sensor_rw))) {
++ kfree(dc);
++ return -EFAULT;
++ }
++
++ dc_addr = dc->address;
++ dc_data = dc->data;
++ if(WriteByte_DCOMP(adap, dc_addr, dc_data)) {
++ kfree(dc);
++ return -ENODEV;
++ }
++
++ kfree(dc);
++ }
++ break;
++
++ case BMI_SENSOR_DCRD:
++ {
++ struct sensor_rw *dc = NULL;
++ unsigned char dc_addr;
++ unsigned char dc_data;
++
++ if(sensor->eeprom.dcompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((dc = kmalloc(sizeof(struct sensor_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dc, (struct sensor_rw *) arg, sizeof(struct sensor_rw))) {
++ kfree(dc);
++ return -EFAULT;
++ }
++
++ dc_addr = dc->address;
++ if(ReadByte_DCOMP(adap, dc_addr, &dc_data)) {
++ kfree(dc);
++ return -ENODEV;
++ }
++
++ dc->data = dc_data;
++ if(copy_to_user((struct sensor_rw *) arg, dc, sizeof(struct sensor_rw))) {
++ kfree(dc);
++ return -EFAULT;
++ }
++
++ kfree(dc);
++ }
++ break;
++
++ case BMI_SENSOR_DC_GDAC:
++ {
++ struct sensor_comp_dac *dac = NULL;
++
++ if(sensor->eeprom.dcompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((dac = kmalloc(sizeof(struct sensor_comp_dac), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ dac->xdac = sensor->eeprom.xdac;
++ dac->ydac = sensor->eeprom.ydac;
++ dac->zdac = sensor->eeprom.zdac;
++
++ if(copy_to_user((struct sensor_comp_dac *) arg, dac, sizeof(struct sensor_comp_dac))) {
++ kfree(dac);
++ return -EFAULT;
++ }
++
++ kfree(dac);
++ }
++ break;
++
++ case BMI_SENSOR_DC_SDAC:
++ {
++ struct sensor_comp_dac *dac = NULL;
++
++ if(sensor->eeprom.dcompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((dac = kmalloc(sizeof(struct sensor_comp_dac), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dac, (struct sensor_comp_dac *) arg, sizeof(struct sensor_comp_dac))) {
++ kfree(dac);
++ return -EFAULT;
++ }
++
++ sensor->eeprom.xdac = dac->xdac;
++ sensor->eeprom.ydac = dac->ydac;
++ sensor->eeprom.zdac = dac->zdac;
++
++ if(WriteByte_EE(adap, SENSOR_EE_XDAC, dac->xdac & 0xFF)) {
++ kfree(dac);
++ return -ENODEV;
++ }
++ mdelay(5);
++
++ if(WriteByte_EE(adap, SENSOR_EE_YDAC, dac->ydac & 0xFF)) {
++ kfree(dac);
++ return -ENODEV;
++ }
++ mdelay(5);
++
++ if(WriteByte_EE(adap, SENSOR_EE_ZDAC, dac->zdac & 0xFF)) {
++ kfree(dac);
++ return -ENODEV;
++ }
++ mdelay(5);
++
++ kfree(dac);
++ }
++ break;
++
++ case BMI_SENSOR_DC_IWAIT:
++ {
++ if(sensor->eeprom.dcompass_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ ret = down_interruptible(&sensor->sem);
++ sensor->dcomp_int_en = 1;
++ sensor->dcomp_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->dcomp_wait_queue, (sensor->dcomp_int_fl == 1));
++ if(ret)
++ return ret;
++ }
++ break;
++
++ case BMI_SENSOR_APROX_DUR:
++ {
++ if(sensor->eeprom.aproximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(arg < 2)
++ sensor->aprox_duration = HZ/50;
++ else if(arg > 100)
++ sensor->aprox_duration = HZ/10;
++ else
++ sensor->aprox_duration = (HZ/100) * arg;
++ }
++ break;
++
++ case BMI_SENSOR_APROXRD:
++ {
++ unsigned char aprox_data[2];
++ int read_data;
++
++ if(sensor->eeprom.aproximity_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ // start burst to LED
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ return -ENODEV;
++ iox_data |= (0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ return -ENODEV;
++
++ // set up timer
++ sensor->aprox_timer.expires = jiffies + sensor->aprox_duration;
++ add_timer (&sensor->aprox_timer);
++
++ // wait for timer
++ ret = down_interruptible(&sensor->sem);
++ sensor->aprox_int_en = 1;
++ sensor->aprox_int_fl = 0;
++ up(&sensor->sem);
++ ret = wait_event_interruptible(sensor->aprox_wait_queue, (sensor->aprox_int_fl == 1));
++ if(ret)
++ return ret;
++
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ return -ENODEV;
++
++ // digital output
++ read_data = (iox_data & (0x1 << SENSOR_IOX_PROX_OUT)) << 14;
++
++ // read ADC - analog output
++ if(WriteByte_ADC(adap, SENSOR_ADC_APROXIMITY | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, aprox_data))
++ return -ENODEV;
++ read_data |= (aprox_data[0] << 8) | aprox_data[1];
++
++ // stop burst to LED
++ iox_data &= ~(0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ return -ENODEV;
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_ALIGHTRD:
++ {
++ unsigned char adc_data[2];
++ int read_data;
++
++ if(sensor->eeprom.alight_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_LIGHT | SENSOR_ADC_PD_OFF))
++ return -ENODEV;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data))
++ return -ENODEV;
++ read_data = ((adc_data[0] & SENSOR_ADC_DATA_MSB) << 8) | adc_data[1];
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_DLIGHTWR:
++ {
++ struct sensor_dl_rw *dl = NULL;
++ unsigned char dl_data;
++
++ if(sensor->eeprom.dlight_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if ((dl = kmalloc(sizeof(struct sensor_dl_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dl, (struct sensor_dl_rw *) arg, sizeof(struct sensor_dl_rw))) {
++ kfree(dl);
++ return -EFAULT;
++ }
++
++ dl_data = dl->cmd;
++ if(WriteByte_PL(adap, SENSOR_DL_CMD, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->control;
++ if(WriteByte_PL(adap, SENSOR_DL_CONT, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->int_thi;
++ if(WriteByte_PL(adap, SENSOR_DL_INT_THI, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->int_tlo;
++ if(WriteByte_PL(adap, SENSOR_DL_INT_TLO, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ kfree(dl);
++ }
++ break;
++
++ case BMI_SENSOR_DLIGHTRD:
++ {
++ unsigned char dl_data;
++ unsigned int read_data;
++
++ if(sensor->eeprom.dlight_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ // read sensor data
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_MSB, &dl_data)) {
++ return -ENODEV;
++ }
++ read_data = ((unsigned int) (dl_data)) << 8;
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_LSB, &dl_data)) {
++ return -ENODEV;
++ }
++ read_data |= dl_data;
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_SENSOR_DLIGHT_IC:
++ {
++ if(sensor->eeprom.dlight_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(WriteByte_DL_IC(adap))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_SENSOR_DLIGHT_IWAIT:
++ {
++ struct sensor_dl_rw *dl = NULL;
++ unsigned char dl_data;
++ unsigned int read_data;
++
++ if(sensor->eeprom.dlight_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ // write all register
++ if ((dl = kmalloc(sizeof(struct sensor_dl_rw), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dl, (struct sensor_dl_rw *) arg, sizeof(struct sensor_dl_rw))) {
++ kfree(dl);
++ return -EFAULT;
++ }
++
++ dl_data = dl->cmd;
++ if(WriteByte_PL(adap, SENSOR_DL_CMD, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->control;
++ if(WriteByte_PL(adap, SENSOR_DL_CONT, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->int_thi;
++ if(WriteByte_PL(adap, SENSOR_DL_INT_THI, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ dl_data = dl->int_tlo;
++ if(WriteByte_PL(adap, SENSOR_DL_INT_TLO, dl_data)) {
++ kfree(dl);
++ return -ENODEV;
++ }
++
++ // enable interrupt
++ ret = down_interruptible(&sensor->sem);
++ sensor->dlight_int_en = 1;
++ sensor->dlight_int_fl = 0;
++ up(&sensor->sem);
++ // wait on interrupt
++ ret = wait_event_interruptible(sensor->dlight_wait_queue, (sensor->dlight_int_fl == 1));
++ if(ret)
++ return ret;
++
++ // read sensor data
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_MSB, &dl_data)) {
++ return -ENODEV;
++ }
++ read_data = ((unsigned int) (dl_data)) << 8;
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_LSB, &dl_data)) {
++ return -ENODEV;
++ }
++ read_data |= dl_data;
++ dl->sensor_data = read_data;
++
++ if(copy_to_user((struct sensor_dl_rw *) arg, dl, sizeof(struct sensor_dl_rw))) {
++ kfree(dl);
++ return -EFAULT;
++ }
++
++ kfree(dl);
++ }
++ break;
++
++ case BMI_SENSOR_MIC_EN:
++ {
++ if(sensor->eeprom.sound_present != SENSOR_DEVICE_PRESENT)
++ return -ENODEV;
++
++ if(ReadByte_IOX(adap, IOX_OUTPUT1_REG, &iox_data))
++ return -ENODEV;
++
++ if(arg == BMI_SENSOR_ON)
++ iox_data |= (0x1 << SENSOR_IOX_MIC_EN);
++ else
++ iox_data &= ~(0x1 << SENSOR_IOX_MIC_EN);
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ return -ENODEV;
++ }
++ break;
++
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++// control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++/*
++ * PIM functions
++ */
++
++// interrupt handler
++static void sensor_work_handler(struct work_struct * work)
++{
++ struct bmi_sensor *sensor = work_to_sensor(work);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(sensor->bdev);
++ int slot = bmi_device_get_slot(sensor->bdev);
++ unsigned char iox0;
++ unsigned char iox1;
++ unsigned char i2c_dummy;
++ struct sensor_acc_rw acc_rw;
++
++ if(ReadByte_IOX(adap, IOX_INPUT0_REG, &iox0)) {
++ printk(KERN_ERR "bmi_sensor.c: sensor_work_handler - IOX0 error\n");
++ return;
++ }
++
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox1)) {
++ printk(KERN_ERR "bmi_sensor.c: sensor_work_handler - IOX1 error\n");
++ return;
++ }
++
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ if(sensor->pl_int_en) {
++ if((iox1 & (0x1 << SENSOR_IOX_PL_INT)) == 0) {
++ sensor->pl_int_en = 0;
++ sensor->pl_int_fl = 1;
++ // clear interrupts
++ if(ReadByte_PL(adap, SENSOR_PL_CMD1, &i2c_dummy)) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++ wake_up_all(&sensor->pl_wait_queue);
++ }
++ }
++ }
++
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ if(sensor->temp_int_en) {
++ if((iox1 & (0x1 << SENSOR_IOX_TEMP_INT)) == 0) {
++ sensor->temp_int_en = 0;
++ sensor->temp_int_fl = 1;
++ // disable interrupts
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF1_WR, SENSOR_TEMP_CONF1_STOP)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write error\n");
++ }
++ wake_up_all(&sensor->temp_wait_queue);
++ }
++ }
++ }
++
++ if(sensor->eeprom.motion_present == SENSOR_DEVICE_PRESENT) {
++ if(sensor->mot_int_en) {
++ if(sensor->mot_state != bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET)) {
++ sensor->mot_state = bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET);
++ sensor->mot_int_en = 0;
++ sensor->mot_int_fl = 1;
++ wake_up_all(&sensor->mot_wait_queue);
++ }
++ }
++ }
++
++ if((sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT)
++ || (sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT)) {
++ if(sensor->acc_int1_en) {
++ if((iox0 & (0x1 << SENSOR_IOX_ACC_INT1)) == 0) {
++ sensor->acc_int1_en = 0;
++ sensor->acc_int1_fl = 1;
++ wake_up_all(&sensor->acc_wait1_queue);
++ }
++ }
++
++ if(sensor->acc_int2_en) {
++ if((iox0 & (0x1 << SENSOR_IOX_ACC_INT2)) == 0) {
++ sensor->acc_int2_en = 0;
++ sensor->acc_int2_fl = 1;
++ wake_up_all(&sensor->acc_wait2_queue);
++ }
++ }
++
++ if(sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT) {
++ // clear interrupts
++ acc_rw.address = SENSOR_ACC_IS;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC_IS read error\n");
++ }
++
++ acc_rw.address = SENSOR_ACC_DX0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DX0) error\n");
++ }
++
++ acc_rw.address = SENSOR_ACC_DY0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DY0) error\n");
++ }
++
++ acc_rw.address = SENSOR_ACC_DZ0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DZ0) error\n");
++ }
++ } else { // LIS302DL
++ // clear interrupts
++ if(sensor->acc_int1_en) {
++ if((iox0 & (0x1 << SENSOR_IOX_ACC_INT1)) == 0) {
++ acc_rw.address = SENSOR_A3_SRC1;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3_SRC1 read error\n");
++ }
++ }
++ }
++
++ if(sensor->acc_int2_en) {
++ if((iox0 & (0x1 << SENSOR_IOX_ACC_INT2)) == 0) {
++ acc_rw.address = SENSOR_A3_SRC2;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3_SRC2 read error\n");
++ }
++ }
++ }
++
++ acc_rw.address = SENSOR_A3_STAT;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3_STAT read error\n");
++ }
++
++ acc_rw.address = SENSOR_A3_OUTX;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3 read (OUTX) error\n");
++ }
++
++ acc_rw.address = SENSOR_A3_OUTY;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3 read (OUTY) error\n");
++ }
++
++ acc_rw.address = SENSOR_A3_OUTZ;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: A3 read (OUTZ) error\n");
++ }
++ }
++ }
++
++ if(sensor->eeprom.dcompass_present == SENSOR_DEVICE_PRESENT) {
++ if(sensor->dcomp_int_en) {
++ if((iox1 & (0x1 << SENSOR_IOX_DCOMP_INT)) != 0) {
++ sensor->dcomp_int_en = 0;
++ sensor->dcomp_int_fl = 1;
++ // clear interrupts
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_TMPS, &i2c_dummy)) {
++ printk(KERN_ERR "bmi_sensor.c: TMPS error\n");
++ }
++
++ wake_up_all(&sensor->dcomp_wait_queue);
++ }
++ }
++ }
++
++ if(sensor->eeprom.dlight_present == SENSOR_DEVICE_PRESENT) {
++ if(sensor->dlight_int_en) {
++ if((iox1 & (0x1 << SENSOR_IOX_PL_INT)) == 0) {
++ sensor->dlight_int_en = 0;
++ sensor->dlight_int_fl = 1;
++ // clear interrupts
++ if(ReadByte_PL(adap, SENSOR_DL_CONT, &i2c_dummy)) {
++ printk(KERN_ERR "bmi_sensor.c: DL read error\n");
++ }
++ i2c_dummy &= ~(SENSOR_DL_CONT_INT);
++ if(WriteByte_PL(adap, SENSOR_DL_CONT, i2c_dummy)) {
++ printk(KERN_ERR "bmi_sensor.c: DL write error\n");
++ }
++ if(WriteByte_DL_IC(adap)) {
++ printk(KERN_ERR "bmi_sensor.c: DL interrupt clear error\n");
++ }
++ wake_up_all(&sensor->pl_wait_queue);
++ }
++ }
++ }
++
++
++ if((iox0 & (0x1 << SENSOR_IOX_USB_FL_N)) == 0) {
++ sensor->usb_int_en = 0;
++ sensor->usb_int_fl = 1;
++ // disable USB power
++ if(ReadByte_IOX(adap, IOX_INPUT0_REG, &i2c_dummy)) // clear IOX interrupts
++ printk(KERN_ERR "bmi_sensor.c: USB IOX read error\n");
++ wake_up_all(&sensor->usb_wait_queue);
++ }
++
++ return;
++}
++
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ struct bmi_sensor *sensor = (struct bmi_sensor *) dummy;
++
++ schedule_work (&sensor->work_item);
++ return IRQ_HANDLED;
++}
++
++/*
++ * BMI functions
++ */
++
++/*-------------------------------------
++ *
++ * bmi device sysfs attributes
++ *
++ *-------------------------------------
++ */
++
++static ssize_t show_humidity(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_HUMIDITY)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (adc_data[0] << 8) | adc_data[1]);
++}
++static DEVICE_ATTR(humidity, S_IRUGO, show_humidity, NULL);
++
++static ssize_t show_acompass(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char adc_data[2];
++ unsigned int compass_x;
++ unsigned int compass_y;
++ unsigned int compass_z;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_X)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++ compass_x = (adc_data[0] << 8) | adc_data[1];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Y)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++ compass_y = (adc_data[0] << 8) | adc_data[1];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Z)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++ compass_z = (adc_data[0] << 8) | adc_data[1];
++
++ return sprintf(buf, "X=0x%x\nY=0x%x\nZ=0x%x\n",
++ compass_x, compass_y, compass_z);
++}
++static DEVICE_ATTR(acompass, S_IRUGO, show_acompass, NULL);
++
++static ssize_t show_dcompass(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char compass_i;
++ unsigned char compass_t;
++ unsigned char compass_x;
++ unsigned char compass_y;
++ unsigned char compass_z;
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_MS1, SENSOR_DCOMP_MS1_SENSOR)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP MS1 write error\n");
++ }
++
++ mdelay(20);
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_ST, &compass_i)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++ if((compass_i & SENSOR_DCOMP_ST_INT) == 0) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP interrupt error\n");
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_TMPS, &compass_t)) {
++ printk(KERN_ERR "bmi_sensor.c: TMPS error\n");
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1X, &compass_x)) {
++ printk(KERN_ERR "bmi_sensor.c: H1X error\n");
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1Y, &compass_y)) {
++ printk(KERN_ERR "bmi_sensor.c: H1Y error\n");
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1Z, &compass_z)) {
++ printk(KERN_ERR "bmi_sensor.c: H1Z error\n");
++ }
++
++ return sprintf(buf, "T=0x%x\nX=0x%x\nY=0x%x\nZ=0x%x\n",
++ compass_t, compass_x, compass_y, compass_z);
++}
++static DEVICE_ATTR(dcompass, S_IRUGO, show_dcompass, NULL);
++
++static ssize_t show_als(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char pl_data[2];
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_ALS_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write error\n");
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_LSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (pl_data[0] << 8) | pl_data[1]);
++}
++static DEVICE_ATTR(als, S_IRUGO, show_als, NULL);
++
++static ssize_t show_ir(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char pl_data[2];
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_IR_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write error\n");
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_LSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (pl_data[0] << 8) | pl_data[1]);
++}
++static DEVICE_ATTR(ir, S_IRUGO, show_ir, NULL);
++
++static ssize_t show_proximity(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char pl_data[2];
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_PROX_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write error\n");
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_LSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (pl_data[0] << 8) | pl_data[1]);
++}
++static DEVICE_ATTR(proximity, S_IRUGO, show_proximity, NULL);
++
++static ssize_t show_snda(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_AVG)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (adc_data[0] << 8) | adc_data[1]);
++}
++static DEVICE_ATTR(sound_avg, S_IRUGO, show_snda, NULL);
++
++static ssize_t show_sndp(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_PEAK)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (adc_data[0] << 8) | adc_data[1]);
++}
++static DEVICE_ATTR(sound_peak, S_IRUGO, show_sndp, NULL);
++
++static ssize_t show_temp_l(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF1_WR, SENSOR_TEMP_CONF1_STOP)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_ONE_SHOT, 0x0)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ mdelay(400);
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (LOCAL MSB) error\n");
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (LOCAL LSB) error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (temp_datam << 8) | temp_datal);
++}
++static DEVICE_ATTR(temp_local, S_IRUGO, show_temp_l, NULL);
++
++static ssize_t show_temp_sr(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF1_WR, SENSOR_TEMP_CONF1_STOP)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_ONE_SHOT, 0x0)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ mdelay(400);
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (REM MSB) error\n");
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (REM LSB) error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (temp_datam << 8) | temp_datal);
++}
++static DEVICE_ATTR(temp_sremote, S_IRUGO, show_temp_sr, NULL);
++
++static ssize_t show_temp_ur(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF1_WR, SENSOR_TEMP_CONF1_STOP)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_ONE_SHOT, 0x0)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ }
++
++ mdelay(400);
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (UREM MSB) error\n");
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (UREM LSB) error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (temp_datam << 8) | temp_datal);
++}
++static DEVICE_ATTR(temp_uremote, S_IRUGO, show_temp_ur, NULL);
++
++static ssize_t show_motion(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ int slot = bmi_device_get_slot(bdev);
++
++ return sprintf(buf, "0x%x\n", bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET));
++}
++static DEVICE_ATTR(motion, S_IRUGO, show_motion, NULL);
++
++static ssize_t show_accel(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ int slot = bmi_device_get_slot(bdev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ struct sensor_acc_rw acc_rw;
++ int x;
++ int y;
++ int z;
++
++ if(bmi_sensor[slot].eeprom.accel_present != SENSOR_DEVICE_PRESENT) {
++ acc_rw.address = SENSOR_ACC_DX0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DX0) error\n");
++ }
++ x = (acc_rw.data[0] << 8) | acc_rw.data[1];
++
++ acc_rw.address = SENSOR_ACC_DY0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DY0) error\n");
++ }
++ y = (acc_rw.data[0] << 8) | acc_rw.data[1];
++
++ acc_rw.address = SENSOR_ACC_DZ0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DZ0) error\n");
++ }
++ z = (acc_rw.data[0] << 8) | acc_rw.data[1];
++ } else {
++ acc_rw.address = SENSOR_A3_OUTX;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (OUTX) error\n");
++ }
++ x = acc_rw.data[0];
++
++ acc_rw.address = SENSOR_A3_OUTY;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (OUTY) error\n");
++ }
++ y = acc_rw.data[0];
++
++ acc_rw.address = SENSOR_A3_OUTZ;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (OUTZ) error\n");
++ }
++ z = acc_rw.data[0];
++ }
++ return sprintf(buf, "X=0x%x\nY=0x%x\nZ=0x%x\n", x, y, z);
++}
++static DEVICE_ATTR(accel, S_IRUGO, show_accel, NULL);
++
++static ssize_t show_aprox(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ int slot = bmi_device_get_slot(bdev);
++ struct bmi_sensor *sensor = &bmi_sensor[slot];
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned int read_data;
++ unsigned char iox_data;
++ unsigned char aprox_data;
++ int ret;
++
++ // start burst to LED
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ printk(KERN_ERR "bmi_sensor.c: IOX read error\n");
++ iox_data |= (0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ printk(KERN_ERR "bmi_sensor.c: IOX write error\n");
++
++ // set up timer
++ sensor->aprox_timer.expires = jiffies + sensor->aprox_duration;
++ add_timer (&sensor->aprox_timer);
++
++ // wait for timer
++ ret = down_interruptible(&sensor->sem);
++ sensor->aprox_int_en = 1;
++ sensor->aprox_int_fl = 0;
++ up(&sensor->sem);
++ wait_event_interruptible(sensor->aprox_wait_queue, (sensor->aprox_int_fl == 1));
++
++ // stop burst to LED
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ printk(KERN_ERR "bmi_sensor.c: IOX read error\n");
++ iox_data &= ~(0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ printk(KERN_ERR "bmi_sensor.c: IOX write error\n");
++
++ // digital output
++ read_data = (iox_data & (0x1 << SENSOR_IOX_PROX_OUT)) << 14;
++
++ // read ADC - analog output
++ if(WriteByte_ADC(adap, SENSOR_ADC_APROXIMITY | SENSOR_ADC_PD_OFF))
++ printk(KERN_ERR "bmi_sensor.c: IOX write error\n");
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, &aprox_data))
++ printk(KERN_ERR "bmi_sensor.c: IOX read error\n");
++ read_data |= aprox_data;
++
++ return sprintf(buf, "Analog Proxiimity = 0x%x\n", read_data);
++}
++static DEVICE_ATTR(aprox, S_IRUGO, show_aprox, NULL);
++
++static ssize_t show_alight(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_LIGHT)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (adc_data[0] << 8) | adc_data[1]);
++}
++static DEVICE_ATTR(alight, S_IRUGO, show_alight, NULL);
++
++static ssize_t show_dlight(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct bmi_device *bdev = dev_to_bmi_device(dev);
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ unsigned char dl_data[2];
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_MSB, &dl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: DL read error\n");
++ }
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_LSB, &dl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: DL read error\n");
++ }
++
++ return sprintf(buf, "0x%x\n", (dl_data[0] << 8) | dl_data[1]);
++}
++static DEVICE_ATTR(dlight, S_IRUGO, show_dlight, NULL);
++
++
++// read calibration/equipage EEPROM
++int read_eeprom(struct i2c_adapter *adap, struct sensor_eeprom_raw *eeprom)
++{
++ unsigned char ee_data;
++
++ if(ReadByte_EE(adap, 0x0, &ee_data))
++ return -ENODEV;
++ eeprom->xsf_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x1, &ee_data))
++ return -ENODEV;
++ eeprom->xsf_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x2, &ee_data))
++ return -ENODEV;
++ eeprom->ysf_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x3, &ee_data))
++ return -ENODEV;
++ eeprom->ysf_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x4, &ee_data))
++ return -ENODEV;
++ eeprom->zsf_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x5, &ee_data))
++ return -ENODEV;
++ eeprom->zsf_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x6, &ee_data))
++ return -ENODEV;
++ eeprom->xoff_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x7, &ee_data))
++ return -ENODEV;
++ eeprom->xoff_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x8, &ee_data))
++ return -ENODEV;
++ eeprom->yoff_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x9, &ee_data))
++ return -ENODEV;
++ eeprom->zoff_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xA, &ee_data))
++ return -ENODEV;
++ eeprom->zoff_msb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xB, &ee_data))
++ return -ENODEV;
++ eeprom->yoff_lsb = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xC, &ee_data))
++ return -ENODEV;
++ eeprom->xdac = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xD, &ee_data))
++ return -ENODEV;
++ eeprom->ydac = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xE, &ee_data))
++ return -ENODEV;
++ eeprom->zdac = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0xF, &ee_data))
++ return -ENODEV;
++ eeprom->adc_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x10, &ee_data))
++ return -ENODEV;
++ eeprom->humidity_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x11, &ee_data))
++ return -ENODEV;
++ eeprom->acompass_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x12, &ee_data))
++ return -ENODEV;
++ eeprom->light_proximity_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x13, &ee_data))
++ return -ENODEV;
++ eeprom->sound_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x14, &ee_data))
++ return -ENODEV;
++ eeprom->temperature_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x15, &ee_data))
++ return -ENODEV;
++ eeprom->motion_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x16, &ee_data))
++ return -ENODEV;
++ eeprom->accel_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x17, &ee_data))
++ return -ENODEV;
++ eeprom->dcompass_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x18, &ee_data))
++ return -ENODEV;
++ eeprom->aproximity_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x19, &ee_data))
++ return -ENODEV;
++ eeprom->alight_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x1A, &ee_data))
++ return -ENODEV;
++ eeprom->dlight_present = (__u8) ee_data;
++
++ if(ReadByte_EE(adap, 0x1B, &ee_data))
++ return -ENODEV;
++ eeprom->acc302_present = (__u8) ee_data;
++
++ return 0;
++}
++
++// probe - insert PIM
++int bmi_sensor_probe(struct bmi_device *bdev)
++{
++ int err = 0;
++ int slot = bmi_device_get_slot(bdev);
++ struct bmi_sensor *sensor = &bmi_sensor[slot];
++ struct i2c_adapter *adap = bmi_device_get_i2c_adapter(bdev);
++ struct cdev *cdev;
++ struct class *bmi_class;
++ dev_t dev_id;
++ int irq;
++ unsigned char iox_data;
++
++ sensor->bdev = 0;
++
++ // Create 1 minor device
++ cdev = &sensor->cdev;
++ cdev_init(cdev, &cntl_fops);
++
++ dev_id = MKDEV(major, slot);
++ err = cdev_add(cdev, dev_id, 1);
++ if(err) {
++ return err;
++ }
++
++ // Create class device
++ bmi_class = bmi_get_bmi_class();
++ sensor->class_dev = device_create(bmi_class, NULL,
++ MKDEV(major, slot), NULL,
++ "bmi_sensor_cntl_m%i", slot+1);
++
++ if(IS_ERR(sensor->class_dev)) {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_sensor_cntl_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(sensor->class_dev));
++ goto error;
++ }
++
++ // bind driver and bmi_device
++ sensor->bdev = bdev;
++ bmi_device_set_drvdata(bdev, sensor);
++
++ printk(KERN_INFO "bmi_sensor.c: probe slot %d\n", slot);
++
++ // configure IOX
++ if(factory_test || fcc_test) {
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, 0x98)) { // USB/HUM on, MOT_INT off, COMPASS RST High
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, 0x08)) { // Speaker Peak Clear, all other outputs low
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++ } else {
++ if(WriteByte_IOX(adap, IOX_OUTPUT0_REG, 0x80)) { // USB/HUM/MOT_INT off, COMPASS RST High
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, 0x0A)) { // Speaker Peak Clear/analog proximity enable high, all other outputs low
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++ }
++
++ if(WriteByte_IOX(adap, IOX_CONTROL0_REG, 0x27)) { // IOX[5,2:0]=IN, IOX[7:6,4:3]=OUT
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++
++ if(WriteByte_IOX(adap, IOX_CONTROL1_REG, 0xb4)) { // IOX[7,5:4,2]=IN, IOX[6,3,1:0]=OUT
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto error;
++ }
++
++ // Initialize GPIOs (turn LED's on)
++ bmi_slot_gpio_configure_as_output(slot, SENSOR_GPIO_RED_LED, SENSOR_GPIO_LED_ON); // Red LED=ON
++ bmi_slot_gpio_configure_as_output(slot, SENSOR_GPIO_GREEN_LED, SENSOR_GPIO_LED_ON); // Green LED=ON
++ bmi_slot_gpio_configure_as_input(slot, SENSOR_GPIO_PDOUT); // proximity real-time state
++ bmi_slot_gpio_configure_as_input(slot, SENSOR_GPIO_MOT_DET); // motion real-time state
++
++ mdelay(200);
++
++ // turn LED's off
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_RED_LED, SENSOR_GPIO_LED_OFF); // Red LED=OFF
++ bmi_slot_gpio_write_bit(slot, SENSOR_GPIO_GREEN_LED, SENSOR_GPIO_LED_OFF); // Green LED=OFF
++
++ // bmi_sensor initialization
++ init_MUTEX(&sensor->sem);
++ sprintf(sensor->work_name, "sensor_m%d", slot + 1);
++ init_waitqueue_head(&sensor->pl_wait_queue);
++ sensor->pl_int_en = 0;
++ sensor->pl_int_fl = 0;
++ init_waitqueue_head(&sensor->temp_wait_queue);
++ sensor->temp_int_en = 0;
++ sensor->temp_int_fl = 0;
++ init_waitqueue_head(&sensor->mot_wait_queue);
++ sensor->mot_int_en = 0;
++ sensor->mot_int_fl = 0;
++ sensor->mot_state = bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET); // initial motion detector state
++ init_waitqueue_head(&sensor->acc_wait1_queue);
++ sensor->acc_int1_en = 0;
++ sensor->acc_int1_fl = 0;
++ init_waitqueue_head(&sensor->acc_wait2_queue);
++ sensor->acc_int2_en = 0;
++ sensor->acc_int2_fl = 0;
++ init_waitqueue_head(&sensor->usb_wait_queue);
++ sensor->usb_int_en = 0;
++ sensor->usb_int_fl = 0;
++ init_waitqueue_head(&sensor->dcomp_wait_queue);
++ sensor->dcomp_int_en = 0;
++ sensor->dcomp_int_fl = 0;
++ sensor->aprox_duration = 200;
++ init_timer(&sensor->aprox_timer);
++ sensor->aprox_timer.data = (unsigned long) &bmi_sensor[slot];
++ sensor->aprox_timer.function = aptimer;
++ init_waitqueue_head(&sensor->aprox_wait_queue);
++ sensor->aprox_int_en = 0;
++ sensor->aprox_int_fl = 0;
++
++ sensor->workqueue = create_singlethread_workqueue(sensor->work_name);
++ if (!sensor->workqueue) {
++ printk(KERN_ERR "bmi_sensor.c: Can't create_singlethread_workqueue() in slot %d\n",
++ slot);
++ goto error;
++ }
++ INIT_WORK(&sensor->work_item, sensor_work_handler);
++
++ // initialize EEPROM for presence
++ if(factory_test && eeprom_init) {
++ unsigned char addr = SENSOR_PRESENT_START;
++
++ // presence
++ while(addr <= SENSOR_PRESENT_END) {
++ if(eeprom_init & 0x1) {
++ WriteByte_EE(adap, addr++, SENSOR_DEVICE_PRESENT);
++ } else {
++ WriteByte_EE(adap, addr++, SENSOR_DEVICE_NOT_PRESENT);
++ }
++ eeprom_init = eeprom_init >> 1;
++ mdelay(5);
++ }
++ }
++
++ if(factory_test && xdac_init) {
++ WriteByte_EE(adap, SENSOR_EE_XDAC, xdac_init & 0xFF);
++ mdelay(5);
++ }
++
++ if(factory_test && ydac_init) {
++ WriteByte_EE(adap, SENSOR_EE_YDAC, ydac_init & 0xFF);
++ mdelay(5);
++ }
++
++ if(factory_test && zdac_init) {
++ WriteByte_EE(adap, SENSOR_EE_ZDAC, zdac_init & 0xFF);
++ mdelay(5);
++ }
++
++ // read EEPROM for calibration/presence
++ if(read_eeprom(adap, &sensor->eeprom)) {
++ printk(KERN_ERR "bmi_sensor.c: Can't read calibration EEPROM in slot %d\n",
++ slot);
++ goto error;
++ }
++
++ sensor->comp_xsf = (sensor->eeprom.xsf_msb << 8) | sensor->eeprom.xsf_lsb;
++ sensor->comp_ysf = (sensor->eeprom.ysf_msb << 8) | sensor->eeprom.ysf_lsb;
++ sensor->comp_zsf = (sensor->eeprom.zsf_msb << 8) | sensor->eeprom.zsf_lsb;
++ sensor->comp_xoff = (sensor->eeprom.xoff_msb << 8) | sensor->eeprom.xoff_lsb;
++ sensor->comp_yoff = (sensor->eeprom.yoff_msb << 8) | sensor->eeprom.yoff_lsb;
++ sensor->comp_zoff = (sensor->eeprom.zoff_msb << 8) | sensor->eeprom.zoff_lsb;
++
++ if(sensor->eeprom.adc_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_CH0)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ goto error;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ goto error;
++ }
++
++ if((adc_data[0] & 0xF0) != 0x0) {
++ printk(KERN_ERR "bmi_sensor.c: ADC compare error\n");
++ goto error;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: ADC present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.humidity_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_HUMIDITY)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write (Humidity) error\n");
++ goto error;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Humidity) error\n");
++ goto error;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Humidity = %d\n",
++ (adc_data[0] << 8) | adc_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_humidity)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (humidity) failed.\n",
++ slot);
++ goto sysfs_err1;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: HUMIDITY Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.acompass_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char adc_data[2];
++ unsigned int compass_x;
++ unsigned int compass_y;
++ unsigned int compass_z;
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_X)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ goto sysfs_err1;
++
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ device_remove_file(&sensor->bdev->dev, &dev_attr_humidity);
++ goto sysfs_err1;
++ }
++ compass_x = (adc_data[0] << 8) | adc_data[1];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Y)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ goto sysfs_err1;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ goto sysfs_err1;
++ }
++ compass_y = (adc_data[0] << 8) | adc_data[1];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_ACOMPASS_Z)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write error\n");
++ goto sysfs_err1;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read error\n");
++ goto sysfs_err1;
++ }
++ compass_z = (adc_data[0] << 8) | adc_data[1];
++
++ printk(KERN_INFO "bmi_sensor.c: initial COMPASS (X,Y,Z) = %d,%d,%d\n",
++ compass_x, compass_y, compass_z);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_acompass)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (acompass) failed.\n",
++ slot);
++ goto sysfs_err1;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: ACOMPASS Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.dcompass_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char hxga;
++ unsigned char hyga;
++ unsigned char hzga;
++ unsigned char compass_i;
++ unsigned char compass_t;
++ unsigned char compass_x;
++ unsigned char compass_y;
++ unsigned char compass_z;
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_MS1, SENSOR_DCOMP_MS1_EEPROM)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_MS1 write error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_EE_EHXGA, &hxga)) {
++ printk(KERN_ERR "bmi_sensor.c: EE_EHXGA read error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_EE_EHYGA, &hyga)) {
++ printk(KERN_ERR "bmi_sensor.c: EE_EHYGA read error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_EE_EHZGA, &hzga)) {
++ printk(KERN_ERR "bmi_sensor.c: EE_EHZGA read error\n");
++ goto sysfs_err2;
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_MS1, SENSOR_DCOMP_MS1_PD)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_MS1 write error\n");
++ goto sysfs_err2;
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HXGA, hxga)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HXGA write error\n");
++ goto sysfs_err2;
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HYGA, hyga)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HYGA write error\n");
++ goto sysfs_err2;
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HZGA, hzga)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HZGA write error\n");
++ goto sysfs_err2;
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HXDA, sensor->eeprom.xdac)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HXDA write error\n");
++ goto sysfs_err2;
++
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HYDA, sensor->eeprom.ydac)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HYDA write error\n");
++ goto sysfs_err2;
++
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_HZDA, sensor->eeprom.zdac)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_HZDA write error\n");
++ goto sysfs_err2;
++
++ }
++
++ if(WriteByte_DCOMP(adap, SENSOR_DCOMP_MS1, SENSOR_DCOMP_MS1_SENSOR)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_MS1 write error\n");
++ goto sysfs_err2;
++
++ }
++
++ mdelay(20);
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_ST, &compass_i)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_ST read error\n");
++ goto sysfs_err2;
++ }
++
++ if((compass_i & SENSOR_DCOMP_ST_INT) == 0) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP interrupt error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_TMPS, &compass_t)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_TMPS error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1X, &compass_x)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_H1X error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1Y, &compass_y)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_H1Y error\n");
++ goto sysfs_err2;
++ }
++
++ if(ReadByte_DCOMP(adap, SENSOR_DCOMP_H1Z, &compass_z)) {
++ printk(KERN_ERR "bmi_sensor.c: DCOMP_H1Z error\n");
++ goto sysfs_err2;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial COMPASS (T,X,Y,Z) = 0x%x,0x%x,0x%x,0x%x\n",
++ compass_t, compass_x, compass_y, compass_z);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_dcompass)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (dcompass) failed.\n",
++ slot);
++ goto sysfs_err2;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: DCOMPASS Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char pl_data[2];
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_ALS_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write (ALS) error\n");
++ goto sysfs_err3;
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read (ALS) error\n");
++ goto sysfs_err3;
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: PL read (ALS) error\n");
++ goto sysfs_err3;
++ }
++ printk(KERN_INFO "bmi_sensor.c: initial PL ALS = %d\n",
++ (pl_data[0] << 8) | pl_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_als)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (ALS) failed.\n",
++ slot);
++ goto sysfs_err3;
++ }
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_IR_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write (IR) error\n");
++ goto sysfs_err4;
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (IR) error\n");
++ goto sysfs_err4;
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (IR) error\n");
++ goto sysfs_err4;
++ }
++ printk(KERN_INFO "bmi_sensor.c: initial IR = %d\n",
++ (pl_data[0] << 8) | pl_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_ir)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (IR) failed.\n",
++ slot);
++ goto sysfs_err4;
++ }
++
++ if(WriteByte_PL(adap, SENSOR_PL_CMD1, SENSOR_PL_CMD1_PROX_1X)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write (Proximity) error\n");
++ goto sysfs_err5;
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Proximity) error\n");
++ goto sysfs_err5;
++ }
++
++ if(ReadByte_PL(adap, SENSOR_PL_DATA_MSB, &pl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Proximity) error\n");
++ goto sysfs_err5;
++ }
++ printk(KERN_INFO "bmi_sensor.c: initial Proximity = %d\n",
++ (pl_data[0] << 8) | pl_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_proximity)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (Proximity) failed.\n",
++ slot);
++ goto sysfs_err5;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: Combined LIGHT/PROXIMITY Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.sound_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_AVG)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write (Sound Average) error\n");
++ goto sysfs_err6;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Sound Average) error\n");
++ goto sysfs_err6;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Sound Average = %d\n",
++ (adc_data[0] << 8) | adc_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_sound_avg)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (Sound Average) failed.\n",
++ slot);
++ goto sysfs_err6;
++ }
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_SOUND_PEAK)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write (Sound Peak) error\n");
++ goto sysfs_err7;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Sound Peak) error\n");
++ goto sysfs_err7;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Sound Peak = %d\n",
++ (adc_data[0] << 8) | adc_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_sound_peak)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (Sound Peak) failed.\n",
++ slot);
++ goto sysfs_err7;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: SOUND PRESSURE Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char temp_datam;
++ unsigned char temp_datal;
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_MAN_ID, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (Manufacturer ID) error\n");
++ goto sysfs_err8;
++ }
++
++ if(temp_datam != SENSOR_TEMP_MAN_ID_DATA) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP MAN ID error (read=0x%x, expected=0x%x\n",
++ temp_datam, SENSOR_TEMP_MAN_ID_DATA);
++ goto sysfs_err8;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: TEMP Manufacturer ID = 0x%x\n", temp_datam);
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REV_ID, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (Revision ID) error\n");
++ goto sysfs_err8;
++ }
++
++ if(temp_datam != SENSOR_TEMP_REV_ID_DATA) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP REV ID error (read=0x%x, expected=0x%x\n",
++ temp_datam, SENSOR_TEMP_REV_ID_DATA);
++ goto sysfs_err8;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: TEMP Revision ID = 0x%x\n", temp_datam);
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF2, 0x0)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF2) error\n");
++ goto sysfs_err8;
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONF1_WR, SENSOR_TEMP_CONF1_STOP)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ goto sysfs_err8;
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_CONV_WR, SENSOR_TEMP_CONV_P364)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ goto sysfs_err8;
++ }
++
++ if(WriteByte_TEMP(adap, SENSOR_TEMP_ONE_SHOT, 0x0)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP write (CONF1) error\n");
++ goto sysfs_err8;
++ }
++
++ mdelay(400);
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (LOCAL MSB) error\n");
++ goto sysfs_err8;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_LOC_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (LOCAL LSB) error\n");
++ goto sysfs_err8;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Local temperature = 0x%x\n",
++ (temp_datam << 8) | temp_datal);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_temp_local)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (TEMP local) failed.\n",
++ slot);
++ goto sysfs_err8;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (REM MSB) error\n");
++ goto sysfs_err9;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_REM_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (REM LSB) error\n");
++ goto sysfs_err9;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Remote temperature = 0x%x\n",
++ (temp_datam << 8) | temp_datal);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_temp_sremote)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (TEMP sremote) failed.\n",
++ slot);
++ goto sysfs_err9;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_MSB, &temp_datam)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (UREM MSB) error\n");
++ goto sysfs_err10;
++ }
++
++ if(ReadByte_TEMP(adap, SENSOR_TEMP_UREM_LSB, &temp_datal)) {
++ printk(KERN_ERR "bmi_sensor.c: TEMP read (UREM LSB) error\n");
++ goto sysfs_err10;
++ }
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_temp_uremote)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (TEMP uremote) failed.\n",
++ slot);
++ goto sysfs_err10;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Remote temperature (unsigned) = 0x%x\n",
++ (temp_datam << 8) | temp_datal);
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: TEMPERATURE Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.motion_present == SENSOR_DEVICE_PRESENT) {
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_motion)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (motion) failed.\n",
++ slot);
++ goto sysfs_err11;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Motion state = 0x%x\n",
++ bmi_slot_gpio_read_bit(slot, SENSOR_GPIO_MOT_DET));
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: MOTION Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT) {
++ struct sensor_acc_rw acc_rw;
++
++ acc_rw.address = SENSOR_ACC_ID;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (ID) error\n");
++ goto sysfs_err12;
++ }
++
++ if(acc_rw.data[0] != SENSOR_ACC_ID_DATA) {
++ printk(KERN_ERR "bmi_sensor.c: ACC ID error (read=0x%x, expected=0x%x)\n",
++ acc_rw.data[0], SENSOR_ACC_ID_DATA);
++ goto sysfs_err12;
++ }
++
++ acc_rw.address = SENSOR_ACC_RATE;
++ acc_rw.count = 1;
++ acc_rw.data[0] = SENSOR_ACC_RC_3200_1600;
++ if(WriteByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC write (RATE) error\n");
++ goto sysfs_err12;
++ }
++
++ acc_rw.address = SENSOR_ACC_POWER;
++ acc_rw.count = 1;
++ acc_rw.data[0] = SENSOR_ACC_P_NORM;
++ if(WriteByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC write (RATE) error\n");
++ goto sysfs_err12;
++ }
++
++ acc_rw.address = SENSOR_ACC_DF;
++ acc_rw.count = 1;
++ acc_rw.data[0] = SENSOR_ACC_DF_LENGTH;
++ if(WriteByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC write (DF) error\n");
++ goto sysfs_err12;
++ }
++
++ mdelay(20);
++
++ acc_rw.address = SENSOR_ACC_DX0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DX0) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC X state = 0x%x\n",
++ (acc_rw.data[0] << 8) | acc_rw.data[1]);
++
++ acc_rw.address = SENSOR_ACC_DY0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DY0) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC Y state = 0x%x\n",
++ (acc_rw.data[0] << 8) | acc_rw.data[1]);
++
++ acc_rw.address = SENSOR_ACC_DZ0;
++ acc_rw.count = 2;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC read (DZ0) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC Z state = 0x%x\n",
++ (acc_rw.data[0] << 8) | acc_rw.data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_accel)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (accel) failed.\n",
++ slot);
++ goto sysfs_err12;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: ACCELEROMETER Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT) {
++ struct sensor_acc_rw acc_rw;
++
++ acc_rw.address = SENSOR_A3_WAI;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 read (WAI) error\n");
++ goto sysfs_err12;
++ }
++
++ if(acc_rw.data[0] != SENSOR_A3_WAI_ID) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 ID error (read=0x%x, expected=0x%x)\n",
++ acc_rw.data[0], SENSOR_A3_WAI_ID);
++ goto sysfs_err12;
++ }
++
++ acc_rw.address = SENSOR_A3_CTRL1;
++ acc_rw.count = 1;
++ if(factory_test)
++ acc_rw.data[0] = SENSOR_A3_CTRL1_DR400 | SENSOR_A3_CTRL1_PU |
++ SENSOR_A3_CTRL1_STP | SENSOR_A3_CTRL1_STM | SENSOR_A3_CTRL1_XYZEN;
++ else
++ acc_rw.data[0] = SENSOR_A3_CTRL1_DR400 | SENSOR_A3_CTRL1_PU
++ | SENSOR_A3_CTRL1_XYZEN;
++ if(WriteByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 write (RATE) error\n");
++ goto sysfs_err12;
++ }
++
++ acc_rw.address = SENSOR_A3_CTRL3;
++ acc_rw.count = 1;
++ acc_rw.data[0] = SENSOR_A3_CTRL3_IL;
++ if(WriteByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 write (RATE) error\n");
++ goto sysfs_err12;
++ }
++
++ mdelay(20);
++
++ acc_rw.address = SENSOR_A3_OUTX;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 read (OUTX) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC302 X state = 0x%x\n",
++ acc_rw.data[0]);
++
++ acc_rw.address = SENSOR_A3_OUTY;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 read (OUTY) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC302 Y state = 0x%x\n",
++ acc_rw.data[0]);
++
++ acc_rw.address = SENSOR_A3_OUTZ;
++ acc_rw.count = 1;
++ if(ReadByte_ACC(adap, &acc_rw)) {
++ printk(KERN_ERR "bmi_sensor.c: ACC302 read (OUTZ) error\n");
++ goto sysfs_err12;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial ACC302 Z state = 0x%x\n",
++ acc_rw.data[0]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_accel)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (accel) failed.\n",
++ slot);
++ goto sysfs_err12;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: ISL302 ACCELEROMETER Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.aproximity_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char aprox_data;
++ unsigned int read_data;
++ int ret;
++
++ // enable sensor
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data)) {
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto sysfs_err13;
++ }
++ iox_data &= ~(0x1 << SENSOR_IOX_PROX_EN_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data)) {
++ printk(KERN_ERR "bmi_sensor.c: IOX error in slot %d\n", slot);
++ goto sysfs_err13;
++ }
++
++ // start burst to LED
++ iox_data |= (0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ goto sysfs_err13;
++
++ // set up timer
++ sensor->aprox_timer.expires = jiffies + sensor->aprox_duration;
++ add_timer (&sensor->aprox_timer);
++
++ // wait for timer
++ ret = down_interruptible(&sensor->sem);
++ sensor->aprox_int_en = 1;
++ sensor->aprox_int_fl = 0;
++ up(&sensor->sem);
++ wait_event_interruptible(sensor->aprox_wait_queue, (sensor->aprox_int_fl == 1));
++
++ // stop burst to LED
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data))
++ goto sysfs_err13;
++ iox_data &= ~(0x1 << SENSOR_IOX_PROX_RST_N);
++ if(WriteByte_IOX(adap, IOX_OUTPUT1_REG, iox_data))
++ goto sysfs_err13;
++
++ // digital output
++ read_data = (iox_data & (0x1 << SENSOR_IOX_PROX_OUT)) << 14;
++
++ // read ADC - analog output
++ if(WriteByte_ADC(adap, SENSOR_ADC_APROXIMITY | SENSOR_ADC_PD_OFF))
++ goto sysfs_err13;
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, &aprox_data))
++ goto sysfs_err13;
++ read_data |= aprox_data;
++
++ printk(KERN_INFO "bmi_sensor.c: initial analog proximity = 0x%x\n", read_data);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_aprox)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (aprox) failed.\n",
++ slot);
++ goto sysfs_err13;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: Analog PROXIMITY Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.alight_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char adc_data[2];
++
++ if(WriteByte_ADC(adap, SENSOR_ADC_LIGHT)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC write (Analog Light) error\n");
++ goto sysfs_err14;
++ }
++
++ mdelay(1);
++
++ if(ReadByte_ADC(adap, adc_data)) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Humidity) error\n");
++ goto sysfs_err14;
++ }
++
++ printk(KERN_INFO "bmi_sensor.c: initial Analog Light = 0x%x\n",
++ (adc_data[0] << 8) | adc_data[1]);
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_alight)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (alight) failed.\n",
++ slot);
++ goto sysfs_err14;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: Analog LIGHT Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(sensor->eeprom.dlight_present == SENSOR_DEVICE_PRESENT) {
++ unsigned char dl_data[2];
++
++ if(WriteByte_PL(adap, SENSOR_DL_CMD, SENSOR_DL_CMD_ADC_EN)) {
++ printk(KERN_ERR "bmi_sensor.c: PL write (Digital Light) error\n");
++ goto sysfs_err15;
++ }
++
++ mdelay(20);
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_MSB, &dl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Digital Light) error\n");
++ goto sysfs_err15;
++ }
++
++ if(ReadByte_PL(adap, SENSOR_DL_SENSOR_MSB, &dl_data[1])) {
++ printk(KERN_ERR "bmi_sensor.c: ADC read (Digital Light) error\n");
++ goto sysfs_err15;
++ }
++ printk(KERN_INFO "bmi_sensor.c: initial Digital Light = %d\n",
++ (dl_data[0] << 8) | dl_data[1]);
++
++ // clear interrupts
++ if(ReadByte_PL(adap, SENSOR_DL_CONT, &dl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: DL read error\n");
++ }
++ dl_data[0] &= ~(SENSOR_DL_CONT_INT);
++ if(WriteByte_PL(adap, SENSOR_DL_CONT, dl_data[0])) {
++ printk(KERN_ERR "bmi_sensor.c: DL write error\n");
++ }
++ if(WriteByte_DL_IC(adap)) {
++ printk(KERN_ERR "bmi_sensor.c: DL interrupt clear error\n");
++ }
++
++ if(device_create_file(&sensor->bdev->dev, &dev_attr_dlight)) {
++ printk (KERN_ERR
++ "bmi_sensor.c (%d): attr (Digital Light) failed.\n",
++ slot);
++ goto sysfs_err15;
++ }
++
++ if(factory_test == 1) {
++ printk(KERN_INFO "bmi_sensor.c: Digital LIGHT Sensor present in slot %d\n", slot);
++ }
++ }
++
++ if(ReadByte_IOX(adap, IOX_INPUT0_REG, &iox_data)) { // clear IOX interrupts
++ printk (KERN_ERR
++ "bmi_sensor.c(%d): IOX0 interrupt clear fail.\n",
++ slot);
++ goto sysfs_err16;
++ }
++
++ if(ReadByte_IOX(adap, IOX_INPUT1_REG, &iox_data)) { // clear IOX interrupts
++ printk (KERN_ERR
++ "bmi_sensor.c(%d): IOX1 interrupt clear fail.\n",
++ slot);
++ goto sysfs_err16;
++ }
++
++ // request PIM interrupt
++ irq = bmi_device_get_status_irq(bdev);
++ sprintf(sensor->int_name, "bmi_sensor%d", slot);
++ //pjg if(request_irq(irq, &module_irq_handler, 0, sensor->int_name, sensor)) {
++ //pjg printk(KERN_ERR "bmi_sensor.c: Can't allocate irq %d or find Sensor in slot %d\n",
++ //pjg irq, slot);
++ //pjg goto sysfs_err16;
++ //pjg }
++
++ return 0;
++
++sysfs_err16:
++ if(sensor->eeprom.dlight_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_dlight);
++ }
++sysfs_err15:
++ if(sensor->eeprom.alight_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_alight);
++ }
++sysfs_err14:
++ if(sensor->eeprom.aproximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_aprox);
++ }
++sysfs_err13:
++ if(sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_accel);
++ }
++sysfs_err12:
++ if(sensor->eeprom.motion_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_motion);
++ }
++sysfs_err11:
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_uremote);
++ }
++sysfs_err10:
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_sremote);
++ }
++sysfs_err9:
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_local);
++ }
++sysfs_err8:
++ if(sensor->eeprom.sound_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_sound_peak);
++ }
++sysfs_err7:
++ if(sensor->eeprom.sound_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_sound_avg);
++ }
++sysfs_err6:
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_proximity);
++ }
++sysfs_err5:
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_ir);
++ }
++sysfs_err4:
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_als);
++ }
++sysfs_err3:
++ if(sensor->eeprom.dcompass_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_dcompass);
++ }
++sysfs_err2:
++ if(sensor->eeprom.acompass_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_acompass);
++ }
++sysfs_err1:
++ if(sensor->eeprom.humidity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_humidity);
++ }
++error:
++ sensor->class_dev = NULL;
++ cdev_del(&sensor->cdev);
++ device_destroy(bmi_class, MKDEV(major, slot));
++ bmi_device_set_drvdata(bdev, 0);
++ sensor->bdev = 0;
++ printk(KERN_ERR "bmi_sensor.c: probe slot %d FAILED\n", slot);
++ return -ENODEV;
++
++}
++
++// remove PIM
++void bmi_sensor_remove(struct bmi_device *bdev)
++{
++ int slot;
++ struct bmi_sensor *sensor;
++ struct class *bmi_class;
++ int irq;
++
++ slot = bmi_device_get_slot(bdev);
++ sensor = &bmi_sensor[slot];
++
++ irq = bmi_device_get_status_irq(bdev);
++ free_irq(irq, sensor);
++
++ destroy_workqueue(sensor->workqueue);
++
++ if(sensor->eeprom.humidity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_humidity);
++ }
++ if(sensor->eeprom.acompass_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_acompass);
++ }
++ if(sensor->eeprom.dcompass_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_dcompass);
++ }
++ if(sensor->eeprom.light_proximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_als);
++ device_remove_file(&sensor->bdev->dev, &dev_attr_ir);
++ device_remove_file(&sensor->bdev->dev, &dev_attr_proximity);
++ }
++ if(sensor->eeprom.sound_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_sound_avg);
++ device_remove_file(&sensor->bdev->dev, &dev_attr_sound_peak);
++ }
++ if(sensor->eeprom.temperature_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_local);
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_sremote);
++ device_remove_file(&sensor->bdev->dev, &dev_attr_temp_uremote);
++ }
++ if(sensor->eeprom.motion_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_motion);
++ }
++ if(sensor->eeprom.acc302_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_accel);
++ }
++ if(sensor->eeprom.accel_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_accel);
++ }
++ if(sensor->eeprom.aproximity_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_aprox);
++ del_timer(&sensor->aprox_timer);
++ }
++ if(sensor->eeprom.alight_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_alight);
++ }
++ if(sensor->eeprom.dlight_present == SENSOR_DEVICE_PRESENT) {
++ device_remove_file(&sensor->bdev->dev, &dev_attr_dlight);
++ }
++
++ bmi_slot_gpio_configure_all_as_inputs(slot);
++
++ bmi_class = bmi_get_bmi_class();
++ device_destroy(bmi_class, MKDEV(major, slot));
++
++ sensor->class_dev = 0;
++
++ cdev_del(&sensor->cdev);
++
++ // de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata(bdev, 0);
++ sensor->bdev = 0;
++
++ return;
++}
++
++/*
++ * module routines
++ */
++
++static int __init bmi_sensor_init(void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI SENSOR Driver");
++ if(retval) {
++ return -ENODEV;
++ }
++
++ major = MAJOR(dev_id);
++ retval = bmi_register_driver(&bmi_sensor_driver);
++ if(retval) {
++ unregister_chrdev_region(dev_id, 4);
++ return -ENODEV;
++ }
++
++ if(factory_test) {
++ printk(KERN_INFO "bmi_sensor.c: Factory Test mode enabled\n");
++ if(eeprom_init)
++ printk(KERN_INFO "bmi_sensor.c: eeprom init = 0x%x\n", eeprom_init);
++ if(xdac_init)
++ printk(KERN_INFO "bmi_sensor.c: XDAC init = 0x%x\n", xdac_init);
++ if(ydac_init)
++ printk(KERN_INFO "bmi_sensor.c: YDAC init = 0x%x\n", ydac_init);
++ if(zdac_init)
++ printk(KERN_INFO "bmi_sensor.c: ZDAC init = 0x%x\n", zdac_init);
++ }
++
++ if(fcc_test)
++ printk(KERN_INFO "bmi_sensor.c: FCC Test mode enabled\n");
++
++ printk(KERN_INFO "bmi_sensor.c: BMI_SENSOR Driver v%s \n", BMISENSOR_VERSION);
++
++ return 0;
++}
++
++static void __exit bmi_sensor_cleanup(void)
++{
++ dev_t dev_id;
++
++ bmi_unregister_driver(&bmi_sensor_driver);
++
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region(dev_id, 4);
++ return;
++}
++
++module_init(bmi_sensor_init);
++module_exit(bmi_sensor_cleanup);
++
++module_param(factory_test, ushort, S_IRUGO);
++MODULE_PARM_DESC(factory_test, "Factory Test code enable");
++
++module_param(eeprom_init, int, S_IRUGO);
++MODULE_PARM_DESC(eeprom_init, "Factory presence EEPROM programming");
++
++module_param(xdac_init, ushort, S_IRUGO);
++MODULE_PARM_DESC(xdac_init, "Factory EEPROM XDAC programming");
++
++module_param(ydac_init, ushort, S_IRUGO);
++MODULE_PARM_DESC(ydac_init, "Factory EEPROM YDAC programming");
++
++module_param(zdac_init, ushort, S_IRUGO);
++MODULE_PARM_DESC(zdac_init, "Factory EEPROM ZDAC programming");
++
++module_param(fcc_test, ushort, S_IRUGO);
++MODULE_PARM_DESC(fcc_test, "FCC Test code enable");
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Peter Giacomini <p.giacomini@encadis.com>");
++MODULE_DESCRIPTION("BMI Sensor device driver");
++MODULE_SUPPORTED_DEVICE("bmi_sensor_cntl_mX");
++
+--- /dev/null
++++ git/drivers/bmi/pims/sound/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BMI_AUDIO) += bmi_audio.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/sound/bmi_audio.c
+@@ -0,0 +1,4434 @@
++/*
++ * bmi_audio.c
++ *
++ * BMI audio device driver for audio PIMs
++ *
++ * The BMI Audio driver and this API were developed to support
++ * audio playback and record on the BUG audio PIMs.
++ *
++ * The following operating modes are supported:
++ *
++ * Operating Mode PIM
++ * ---------------------------- -------
++ * Stereo DAC Playback Yes
++ * Stereo ADC Record Yes
++ * Output Amplifier Control Yes
++ * Input Mixer Control Yes
++ *
++ * This file also implements the sound driver mixer interface for ALSA.
++ *
++ * Playback and Recording supports 11025, 22050, and 44100 kHz for stereo.
++ *
++ * Future Enhanement Options:
++ * 48000-based rates
++ * efx control
++ * I2S -> TDM mode
++ * power management
++ */
++
++/*
++ * This code was derived from the following sources:
++ *
++ * @file pmic_audio.c
++ * @file mxc-alsa-mixer.c
++ * @file mxc-alsa-pmic.c
++ *
++ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++#undef CODEC // disable CODEC access for code testing
++#define CODEC // enable CODEC access for code testing
++
++#define DEBUG // enable debug printk
++#undef DEBUG // disable debug printk
++
++#ifdef DEBUG
++
++# define DDPRINTK(fmt, args...) printk(KERN_ERR"%s :: %d :: %s - " \
++ fmt, __FILE__,__LINE__,__FUNCTION__ , ## args)
++# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
++# define PRINTK(fmt) printk(KERN_INFO fmt)
++
++# define FUNC_START DPRINTK(" func start\n")
++# define FUNC_END DPRINTK(" func end\n")
++
++# define FUNC_ERR printk(KERN_ERR"%s :: %d :: %s err= %d \n", \
++ __FILE__,__LINE__,__FUNCTION__ ,err)
++
++#else // DEBUG
++
++#define DDPRINTK(fmt, args...) do {} while(0)
++#define DPRINTK(fmt, args...) do {} while(0)
++#define PRINTK(fmt) do {} while(0)
++
++#endif // DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/clk.h>
++
++// BMI/BUG interfaces
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi-ids.h>
++#include <linux/bmi/bmi_ioctl.h>
++#include <linux/bmi/bmi_audio.h>
++
++// control interface - LED/RESET/MODULE ACTIVATION
++#include <asm/ioctl.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/major.h>
++
++// I2C interface - IOX/CODEC
++#include <linux/i2c.h>
++#include <mach/mxc_i2c.h>
++
++// Input interface - BUTTONS/JACKS
++#include <linux/input.h>
++#include <linux/interrupt.h>
++
++// includes from mxc-alsa-mixer.c:
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <linux/soundcard.h>
++#include "../../../mxc/bug_audio/bug-alsa-common.h"
++
++// includes from mxc-alsa-pmic.c:
++#include <linux/moduleparam.h>
++#include <linux/errno.h>
++#include <linux/ioctl.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#ifdef CONFIG_PM
++#include <linux/pm.h>
++#endif // CONFIG_PM
++
++#include <mach/dma.h>
++#include <mach/spba.h>
++#include <mach/clock.h>
++#include <asm/mach-types.h>
++
++#include "../../../../arch/arm/mach-mx3/crm_regs.h"
++#include "../../../mxc/ssi/ssi.h"
++#include "../../../mxc/ssi/registers.h"
++#include "../../../mxc/dam/dam.h"
++
++// Global variables
++static ushort fcc_test = 0;
++static ushort output_ints = 0;
++
++// BMI defines
++#define BMIAUDIO_VERSION "1.0"
++#define MAX_STRG (20)
++#define WORK_DELAY (1) // input debounce
++
++// BMI private device structure
++struct bmi_audio
++{
++ struct bmi_device *bdev; // BMI device
++ struct cdev cdev; // control character device
++ struct device *class_dev; // control device class
++ unsigned int active; // PIM active
++ unsigned int irq; // interrupt number
++ char int_name[MAX_STRG]; // interrupt name for /proc
++ struct input_dev *input_dev; // button/insertion input device
++};
++
++static struct bmi_audio bmi_audio[BMI_AUDIO_PIM_NUM]; // PIM structures
++static int major; // control device major
++
++//
++// I2C
++//
++
++// I2C Slave Addresses
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define BMI_CODEC_I2C_ADDRESS 0x18 // 7-bit address
++
++// I2C IOX register definitions
++#define IOX_INPUT_REG 0x0 // IOX input data register
++#define IOX_OUTPUT_REG 0x1 // IOX output data register
++#define IOX_POLARITY_REG 0x2 // IOX polarity data register
++#define IOX_CONTROL 0x3 // IOX direction control register
++#define IOX_AMP (0) // bit 0 - amplifier off (O - low active)
++#define IOX_SPARE (1) // bit 1 - spare
++#define IOX_VOLP (2) // bit 2 - VOLP (I - interrupt)
++#define IOX_VOLD (3) // bit 3 - VOLD (I - interrupt)
++#define IOX_HP_INS (4) // bit 4 - HP_INS (I - interrupt)
++#define IOX_MIC_INS (5) // bit 5 - MIC_INS (I - interrupt)
++#define IOX_LI_INS (6) // bit 6 - LI_INS (I - interrupt)
++#define IOX_LO_INS (7) // bit 7 - LO_INS (I - interrupt)
++
++//
++// I2C routines
++//
++
++// read byte from I2C IO expander
++static int ReadByte_IOX (struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// write byte to I2C IO expander
++static int WriteByte_IOX (struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++#ifdef CODEC
++// read byte from I2C CODEC
++static int ReadByte_CODEC (struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_CODEC_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_CODEC_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer (adap, rmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "ReadByte_CODEC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// write byte to I2C CODEC
++static int WriteByte_CODEC (struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_CODEC_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_CODEC_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++
++ ret = i2c_transfer (adap, wmsg, num_msgs);
++
++ if (ret == 2) {
++ ret = 0;
++ }
++ else {
++ printk (KERN_ERR "WriteByte_CODEC() - i2c_transfer() failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++#endif // CODEC
++
++//
++// control cdev routines
++//
++
++// open
++int cntl_open (struct inode *inode, struct file *file)
++{
++ struct bmi_audio *audio;
++
++ audio = container_of (inode->i_cdev, struct bmi_audio, cdev);
++ file->private_data = audio;
++ return 0;
++
++}
++
++// release
++int cntl_release (struct inode *inode, struct file *file)
++{
++ file->private_data = 0;
++ return 0;
++}
++
++static int configure_CODEC(struct i2c_adapter *adap, struct bmi_audio *audio);
++
++// ioctl
++int cntl_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct bmi_audio *audio = (struct bmi_audio *) (file->private_data);
++ struct codec_xfer codec_xfer;
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++ int slot;
++
++ // error if audio/bdev not present
++ if (audio == 0)
++ return -ENODEV;
++
++ if (audio->bdev == 0)
++ return -ENODEV;
++
++ adap = bmi_device_get_i2c_adapter (audio->bdev);
++ slot = bmi_device_get_slot (audio->bdev);
++
++ // get codec transfer structure
++ if ((cmd == BMI_AUDIO_WCODEC) || (cmd == BMI_AUDIO_RCODEC)) {
++ if (copy_from_user (&codec_xfer, (struct codec_xfer *) arg, sizeof(struct codec_xfer))) {
++ printk (KERN_INFO "bmi_audio.c: ioctl(%d): copy_from_user error\n", slot);
++ return -EFAULT;
++ }
++ }
++
++ // ioctl's
++ switch (cmd) {
++
++ case BMI_AUDIO_RLEDOFF:
++ bmi_slot_gpio_write_bit (slot, GPIO_RED, BMI_GPIO_ON); // Red LED=OFF
++ break;
++
++ case BMI_AUDIO_RLEDON:
++ bmi_slot_gpio_write_bit (slot, GPIO_RED, BMI_GPIO_OFF); // Red LED=ON
++ break;
++
++ case BMI_AUDIO_GLEDOFF:
++ bmi_slot_gpio_write_bit (slot, GPIO_GREEN, BMI_GPIO_ON); // Greem LED=OFF
++ break;
++
++ case BMI_AUDIO_GLEDON:
++ bmi_slot_gpio_write_bit (slot, GPIO_GREEN, BMI_GPIO_OFF); // Greem LED=ON
++ break;
++
++ case BMI_AUDIO_SPKON:
++ {
++ printk(KERN_INFO "BMI_AUDIO: SPKOFF Called...\n");
++ if (ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ printk(KERN_INFO "BMI_AUDIO: IOX Output Read: 0x%x\n", iox_data);
++ if (WriteByte_IOX (adap, IOX_OUTPUT_REG, (iox_data | (1 << IOX_AMP))))
++ return -ENODEV;
++ }
++ break;
++ case BMI_AUDIO_SPKOFF:
++ {
++ printk(KERN_INFO "BMI_AUDIO: SPKON Called...\n");
++ if (ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++ printk(KERN_INFO "BMI_AUDIO: IOX Output Read: 0x%x\n", iox_data);
++ if (WriteByte_IOX (adap, IOX_OUTPUT_REG, (iox_data & ~(1 << IOX_AMP))))
++ return -ENODEV;
++ }
++ break;
++ case BMI_AUDIO_SETRST:
++ bmi_slot_gpio_configure_as_output (slot, GPIO_RESET, BMI_GPIO_OFF); // RST = 0;
++ break;
++
++ case BMI_AUDIO_CLRRST:
++ bmi_slot_gpio_configure_as_output (slot, GPIO_RESET, BMI_GPIO_ON); // RST = 1;
++ break;
++
++ case BMI_AUDIO_GETSTAT:
++ {
++ int read_data;
++
++ if(ReadByte_IOX (adap, IOX_INPUT_REG, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data | (bmi_read_gpio_data_reg(slot) << 8);
++
++ if(put_user(read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_AUDIO_ACTIVATE:
++ audio->active = 0;
++ switch (slot) {
++ case 0:
++ if (bmi_audio[2].active == 0) {
++ audio->active = 1;
++ }
++ break;
++ case 1:
++ if (bmi_audio[3].active == 0) {
++ audio->active = 1;
++ }
++ break;
++ case 2:
++ if (bmi_audio[0].active == 0) {
++ audio->active = 1;
++ }
++ break;
++ case 3:
++ if (bmi_audio[1].active == 0) {
++ audio->active = 1;
++ }
++ break;
++ }
++#ifdef CODEC
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (audio->active) { // power-up ADC
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, CODEC_L_PGA(0x00) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, CODEC_L_PGA(0x00) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ configure_CODEC(adap, audio);
++ } else { // power-down ADC
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, 0x38))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, 0x38))
++ return -ENODEV;
++ }
++#endif // CODEC
++
++ case BMI_AUDIO_DEACTIVATE:
++#ifdef CODEC
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ // power-down ADC
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, 0x38))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, 0x38))
++ return -ENODEV;
++#endif // CODEC
++ audio->active = 0;
++ break;
++
++ case BMI_AUDIO_WCODEC:
++#ifdef CODEC
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, codec_xfer.page))
++ return -ENODEV;
++ // write codec register
++ if (WriteByte_CODEC (adap, codec_xfer.reg, codec_xfer.data))
++ return -ENODEV;
++#endif // CODEC
++ break;
++
++ case BMI_AUDIO_RCODEC:
++#ifdef CODEC
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, codec_xfer.page))
++ return -ENODEV;
++ // read codec register
++ if (ReadByte_CODEC (adap, codec_xfer.reg, &codec_xfer.data))
++ return -ENODEV;
++ if (copy_to_user ((struct codec_xfer *) arg, &codec_xfer,
++ sizeof(struct codec_xfer)))
++ return -EFAULT;
++#endif // CODEC
++ break;
++
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++// control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++// functionality from mxc-alsa-pmic.h:
++#define DAM_PORT_4 port_4
++#define DAM_PORT_5 port_5
++#define TX_WATERMARK 0x4
++#define RX_WATERMARK 0x6
++
++// functionality from mxc-alsa-pmic.c:
++
++/*
++ * driver buffer policy.
++ * Customize here if the sound is not correct
++ */
++#define MAX_BUFFER_SIZE (32*1024)
++#define DMA_BUF_SIZE (8*1024)
++#define MIN_PERIOD_SIZE 64
++#define MIN_PERIOD 2
++#define MAX_PERIOD 255
++
++#define AUD_MUX_CONF 0x0031010
++#define MASK_2_TS 0xfffffffc
++#define SOUND_CARD13_NAME "PIM_AUDIO13"
++#define SOUND_CARD24_NAME "PIM_AUDIO24"
++
++// These defines enable DMA chaining for playback and capture respectively.
++#define MXC_SOUND_PLAYBACK_CHAIN_DMA_EN 1
++#define MXC_SOUND_CAPTURE_CHAIN_DMA_EN 1
++
++// ID for the PIM cards
++static char id13[] = "PIM_AUDIO13"; // slots 1 & 3
++static char id24[] = "PIM_AUDIO24"; // slots 2 & 4
++
++#define MXC_ALSA_MAX_PCM_DEV 1
++#define MXC_ALSA_MAX_PLAYBACK 1
++#define MXC_ALSA_MAX_CAPTURE 1
++
++#define PLAYBACK_STREAM (0)
++#define CAPTURE_STREAM (1)
++
++#define NUM_CARDS (2)
++
++/*
++ * This structure is the global configuration of the soundcard
++ * that are accessed by the mixer as well as by the playback/recording
++ * stream. This contains various settings.
++ */
++typedef struct audio_mixer_control {
++
++ /*
++ * This variable holds the current volume for ouput devices
++ */
++ int vol_for_output[OP_MAXDEV];
++
++ /*
++ * This variable holds the current volume for input devices
++ */
++ int vol_for_input[IP_MAXDEV];
++
++ /*
++ * This variable holds the current volume for playback devices.
++ */
++ int master_volume_out;
++
++ /*
++ * These variables holds the current state of the jack indicators
++ */
++ int hp_indicator;
++ int mic_indicator;
++ int li_indicator;
++ int lo_indicator;
++
++ /*
++ * Semaphore used to control the access to this structure.
++ */
++ struct semaphore sem;
++
++ /*
++ * These variables are set by PCM stream
++ */
++ int codec_playback_active;
++ int codec_capture_active;
++
++} audio_mixer_control_t;
++
++/*
++ * This structure represents an audio stream in term of
++ * channel DMA, HW configuration on CODEC and AudioMux/SSI
++ */
++typedef struct audio_stream {
++ /*
++ * identification string
++ */
++ char *id;
++
++ /*
++ * numeric identification
++ */
++ int stream_id;
++
++ /*
++ * SSI ID on the ARM side
++ */
++ int ssi;
++
++ /*
++ * DAM port on the ARM side
++ */
++ int dam_port;
++
++ /*
++ * device identifier for DMA
++ */
++ int dma_wchannel;
++
++ /*
++ * we are using this stream for transfer now
++ */
++ int active:1;
++
++ /*
++ * current transfer period
++ */
++ int period;
++
++ /*
++ * current count of transfered periods
++ */
++ int periods;
++
++ /*
++ * are we recording - flag used to do DMA trans. for sync
++ */
++ int tx_spin;
++
++ /*
++ * Previous offset value for resume
++ */
++ unsigned int old_offset;
++
++ /*
++ * for locking in DMA operations
++ */
++ spinlock_t dma_lock;
++
++ /*
++ * Alsa substream pointer
++ */
++ struct snd_pcm_substream *stream;
++
++} audio_stream_t;
++
++/*
++ * This structure represents the CODEC sound card with its
++ * streams and its shared parameters
++ */
++typedef struct snd_card_mxc_bmi_audio {
++ /*
++ * ALSA sound card handle
++ */
++ struct snd_card *card;
++
++ /*
++ * ALSA pcm driver type handle
++ */
++ struct snd_pcm *pcm[MXC_ALSA_MAX_PCM_DEV];
++
++ /*
++ * playback & capture streams handle
++ * We can support a maximum of 1 playback streams
++ * We can support a maximum of 1 capture streams
++ */
++ audio_stream_t s[MXC_ALSA_MAX_CAPTURE + MXC_ALSA_MAX_PLAYBACK];
++
++} mxc_bmi_audio_t;
++
++/*
++ * bmi audio chip parameters for IP/OP and volume controls
++ */
++audio_mixer_control_t audio_mixer_control[NUM_CARDS];
++
++/*
++ * Global variable that represents the CODEC soundcard.
++ */
++mxc_bmi_audio_t *mxc_audio[NUM_CARDS] = { NULL, NULL };
++
++/*
++ * Supported playback rates array
++ */
++static unsigned int playback_rates_stereo[] = {
++ 8000,
++ 11025,
++ 12000,
++ 16000,
++ 22050,
++ 24000,
++ 32000,
++ 44100,
++ 48000,
++ 88200,
++ 96000
++};
++
++/*
++ * Supported capture rates array
++ */
++static unsigned int capture_rates_stereo[] = {
++ 8000,
++ 11025,
++ 12000,
++ 16000,
++ 22050,
++ 24000,
++ 32000,
++ 44100,
++ 48000,
++ 88200,
++ 96000
++};
++
++/*
++ * this structure represents the sample rates supported
++ * by CODEC for playback operations on DAC.
++ */
++static struct snd_pcm_hw_constraint_list hw_playback_rates_stereo = {
++ .count = ARRAY_SIZE(playback_rates_stereo),
++ .list = playback_rates_stereo,
++ .mask = 0,
++};
++
++/*
++ * this structure represents the sample rates supported
++ * by capture operations on ADC.
++ */
++static struct snd_pcm_hw_constraint_list hw_capture_rates_stereo = {
++ .count = ARRAY_SIZE(capture_rates_stereo),
++ .list = capture_rates_stereo,
++ .mask = 0,
++};
++
++/*
++ * This function configures audio multiplexer to support
++ * audio data routing in CODEC slave mode.
++ *
++ * @param ssi SSI of the ARM to connect to the DAM.
++ */
++void configure_dam_bmi_master(int ssi)
++{
++ int source_port;
++ int target_port;
++
++ if (ssi == SSI1) {
++ PRINTK("DAM: port 1 -> port 4\n");
++ source_port = port_1;
++ target_port = port_4;
++ } else {
++ PRINTK("DAM: port 2 -> port 5\n");
++ source_port = port_2;
++ target_port = port_5;
++ }
++
++ dam_reset_register (source_port);
++ dam_reset_register (target_port);
++
++ dam_select_mode (source_port, normal_mode);
++ dam_select_mode (target_port, normal_mode);
++
++ dam_set_synchronous (source_port, true);
++ dam_set_synchronous (target_port, true);
++
++ dam_select_RxD_source (source_port, target_port);
++ dam_select_RxD_source (target_port, source_port);
++
++ dam_select_TxFS_direction (source_port, signal_in);
++ dam_select_TxFS_direction (target_port, signal_out);
++ dam_select_TxFS_source (target_port, false, source_port);
++
++ dam_select_TxClk_direction (source_port, signal_in);
++ dam_select_TxClk_direction (target_port, signal_out);
++ dam_select_TxClk_source (target_port, false, source_port);
++
++ dam_select_RxFS_direction (source_port, signal_in);
++ dam_select_RxFS_direction (target_port, signal_out);
++ dam_select_RxFS_source (source_port, false, target_port);
++ dam_select_RxFS_source (target_port, false, source_port);
++
++ dam_select_RxClk_direction (source_port, signal_in);
++ dam_select_RxClk_direction (target_port, signal_out);
++ dam_select_RxClk_source (source_port, false, target_port);
++ dam_select_RxClk_source (target_port, false, source_port);
++}
++
++void ssi_rx_sampleRate (int ssi, int samplerate) {
++ struct clk *ssi_clk;
++
++ ssi_rx_clock_divide_by_two (ssi, false);
++ ssi_rx_clock_prescaler (ssi, false);
++ ssi_rx_frame_rate (ssi, 2);
++
++ ssi_clk = clk_get (NULL, "usb_pll.0");
++
++ if (ssi == SSI1) {
++ ssi_clk = clk_get (NULL, "ssi_clk.0");
++ } else {
++ ssi_clk = clk_get (NULL, "ssi_clk.1");
++ }
++
++ clk_set_rate (ssi_clk, clk_round_rate (ssi_clk, 11289600));
++ switch (samplerate) {
++ case 8000:
++ ssi_rx_prescaler_modulus (ssi, 17);
++ break;
++ case 11025:
++ ssi_rx_prescaler_modulus (ssi, 12);
++ break;
++ case 16000:
++ ssi_rx_prescaler_modulus (ssi, 8);
++ break;
++ case 22050:
++ ssi_rx_prescaler_modulus (ssi, 6);
++ break;
++ default:
++ if (samplerate != 44100)
++ printk (KERN_ERR
++ "ssi_rx_sampleRate(): samplerate=%d not supported (default to 44100).\n",
++ samplerate);
++
++ ssi_rx_prescaler_modulus (ssi, 3);
++ break;
++ }
++}
++
++void ssi_tx_sampleRate (int ssi, int samplerate) {
++ struct clk *ssi_clk;
++
++ ssi_tx_clock_divide_by_two (ssi, false);
++ ssi_tx_clock_prescaler (ssi, false);
++ ssi_tx_frame_rate (ssi, 2);
++
++ ssi_clk = clk_get (NULL, "usb_pll.0");
++
++ if (ssi == SSI1) {
++ ssi_clk = clk_get (NULL, "ssi_clk.0");
++ } else {
++ ssi_clk = clk_get (NULL, "ssi_clk.1");
++ }
++
++ clk_set_rate (ssi_clk, clk_round_rate (ssi_clk, 11289600));
++ switch (samplerate) {
++ case 8000:
++ ssi_tx_prescaler_modulus (ssi, 17);
++ break;
++ case 11025:
++ ssi_tx_prescaler_modulus (ssi, 12);
++ break;
++ case 16000:
++ ssi_tx_prescaler_modulus (ssi, 8);
++ break;
++ case 22050:
++ ssi_tx_prescaler_modulus (ssi, 6);
++ break;
++ default:
++ if (samplerate != 44100)
++ printk (KERN_ERR
++ "ssi_tx_sampleRate(): samplerate=%d not supported (default to 44100).\n",
++ samplerate);
++
++ ssi_tx_prescaler_modulus (ssi, 3);
++ break;
++ }
++}
++
++/*
++ * This function configures the SSI in order to receive audio
++ * from CODEC (recording). Configuration of SSI consists mainly in
++ * setting the following:
++ *
++ * 1) SSI to use (SSI1 or SSI2)
++ * 2) SSI mode (normal or network. We use always network mode)
++ * 3) SSI STCCR register settings, which control the sample rate (BCL and
++ * FS clocks)
++ * 4) Watermarks for SSI FIFOs as well as timeslots to be used.
++ * 5) Enable SSI.
++ *
++ * @param substream pointer to the structure of the current stream.
++ */
++void configure_ssi_rx (int ssi)
++{
++ DPRINTK("configure_ssi_rx: SSI%d\n", ssi + 1);
++
++ // receive set up
++ ssi_rx_shift_direction (ssi, ssi_msb_first);
++ ssi_rx_clock_polarity (ssi, ssi_clock_on_falling_edge);
++ ssi_rx_frame_sync_active (ssi, ssi_frame_sync_active_low);
++ ssi_rx_frame_sync_length (ssi, ssi_frame_sync_one_word);
++ ssi_rx_early_frame_sync (ssi, ssi_frame_sync_one_bit_before);
++ ssi_rx_word_length (ssi, ssi_16_bits);
++ ssi_rx_bit0 (ssi, false);
++
++ // FIFO set up
++ ssi_rx_fifo_full_watermark (ssi, ssi_fifo_0, RX_WATERMARK);
++ ssi_rx_fifo_enable (ssi, ssi_fifo_0, true);
++}
++
++/*
++ * This function configures the SSI in order to
++ * send data to CODEC. Configuration of SSI consists
++ * mainly in setting the following:
++ *
++ * 1) SSI to use (SSI1 or SSI2)
++ * 2) SSI mode (normal for normal use e.g. playback, network for mixing)
++ * 3) SSI STCCR register settings, which control the sample rate (BCL and
++ * FS clocks)
++ * 4) Watermarks for SSI FIFOs as well as timeslots to be used.
++ * 5) Enable SSI.
++ *
++ * @param substream pointer to the structure of the current stream.
++ */
++void configure_ssi_tx (int ssi)
++{
++ DPRINTK("configure_ssi_tx: SSI%d\n", ssi + 1);
++
++ // disable SSI
++ ssi_clock_off (ssi, false);
++
++ // I2S master, 16 bits, 44.1 KHz
++ // basic I2S settings
++ ssi_network_mode (ssi, true);
++ ssi_synchronous_mode (ssi, true);
++ ssi_tx_shift_direction (ssi, ssi_msb_first);
++ ssi_tx_clock_polarity (ssi, ssi_clock_on_falling_edge);
++ ssi_tx_frame_sync_active (ssi, ssi_frame_sync_active_low);
++ ssi_tx_frame_sync_length (ssi, ssi_frame_sync_one_word);
++ ssi_tx_early_frame_sync (ssi, ssi_frame_sync_one_bit_before);
++ ssi_tx_word_length (ssi, ssi_16_bits);
++ ssi_tx_bit0 (ssi, false);
++
++ // clocks are being provided by SSI
++ ssi_tx_frame_direction (ssi, ssi_tx_rx_internally);
++ ssi_tx_clock_direction (ssi, ssi_tx_rx_internally);
++
++ // FIFO set up
++ ssi_tx_fifo_enable (ssi, ssi_fifo_0, true);
++ ssi_tx_fifo_empty_watermark (ssi, ssi_fifo_0, TX_WATERMARK);
++
++ // Clocking
++ ssi_tx_sampleRate (ssi, 44100);
++ ssi_system_clock (ssi, true);
++
++ // enable ssi
++ ssi_i2s_mode (ssi, i2s_master);
++ ssi_enable (ssi, true);
++}
++
++/*
++ * This function configures number of channels for next audio operation
++ * (recording/playback) Number of channels define if sound is stereo
++ * or mono.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++void set_bmi_channels (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ audio_stream_t *s;
++
++ chip = snd_pcm_substream_chip (substream);
++ s = &chip->s[substream->pstr->stream];
++
++ ssi_tx_mask_time_slot (s->ssi, MASK_2_TS);
++ ssi_rx_mask_time_slot (s->ssi, MASK_2_TS);
++}
++
++/*
++ * This function configures the DMA channel used to transfer
++ * audio from MCU to CODEC
++ *
++ * @param substream pointer to the structure of the current stream.
++ * @param callback pointer to function that will be
++ * called when a SDMA TX transfer finishes.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int
++configure_write_channel (audio_stream_t *s, mxc_dma_callback_t callback, int stream_id)
++{
++ int ret = -1;
++ int channel = -1;
++
++ if (s->ssi == SSI1)
++ channel = mxc_dma_request (MXC_DMA_SSI1_16BIT_TX0, "ALSA TX DMA1");
++ else
++ channel = mxc_dma_request (MXC_DMA_SSI2_16BIT_TX0, "ALSA TX DMA2");
++
++ if (channel < 0) {
++ PRINTK("error requesting a write dma channel\n");
++ return -1;
++ }
++
++ ret = mxc_dma_callback_set (channel, (mxc_dma_callback_t) callback, (void *) s);
++ if (ret != 0) {
++ mxc_dma_free (channel);
++ return -1;
++ }
++ s->dma_wchannel = channel;
++
++ return 0;
++}
++
++/*
++ * This function configures the DMA channel used to transfer
++ * audio from CODEC to MCU
++ *
++ * @param substream pointer to the structure of the current stream.
++ * @param callback pointer to function that will be
++ * called when a SDMA RX transfer finishes.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int configure_read_channel (audio_stream_t *s,
++ mxc_dma_callback_t callback)
++{
++ int ret = -1;
++ int channel = -1;
++
++ if (s->ssi == SSI1)
++ channel = mxc_dma_request (MXC_DMA_SSI1_16BIT_RX0, "ALSA RX DMA1");
++ else
++ channel = mxc_dma_request (MXC_DMA_SSI2_16BIT_RX0, "ALSA RX DMA2");
++
++ if (channel < 0) {
++ PRINTK("error requesting a read dma channel\n");
++ return -1;
++ }
++
++ ret =
++ mxc_dma_callback_set (channel, (mxc_dma_callback_t) callback,
++ (void *) s);
++ if (ret != 0) {
++ mxc_dma_free (channel);
++ return -1;
++ }
++ s->dma_wchannel = channel;
++
++ return 0;
++}
++
++/*
++ * This function frees the stream structure
++ *
++ * @param s pointer to the structure of the current stream.
++ */
++static void audio_dma_free (audio_stream_t *s)
++{
++ /*
++ * There is nothing to be done here since the dma channel has been
++ * freed either in the callback or in the stop method
++ */
++}
++
++/*
++ * This function gets the dma pointer position during record.
++ * Our DMA implementation does not allow to retrieve this position
++ * when a transfer is active, so, it answers the middle of
++ * the current period beeing transfered
++ *
++ * @param s pointer to the structure of the current stream.
++ *
++ */
++static u_int audio_get_capture_dma_pos (audio_stream_t *s)
++{
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int offset;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++ offset = 0;
++
++ // tx_spin value is used here to check if a transfer is active
++ if (s->tx_spin) {
++ offset = (runtime->period_size * (s->periods)) + 0;
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++ DPRINTK("MXC: audio_get_dma_pos offset %d\n", offset);
++ } else {
++ offset = (runtime->period_size * (s->periods));
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++ DPRINTK("MXC: audio_get_dma_pos BIS offset %d\n", offset);
++ }
++
++ return offset;
++}
++
++/*
++ * This function gets the dma pointer position during playback.
++ * Our DMA implementation does not allow to retrieve this position
++ * when a transfer is active, so, it answers the middle of
++ * the current period beeing transfered
++ *
++ * @param s pointer to the structure of the current stream.
++ *
++ */
++static u_int audio_get_playback_dma_pos (audio_stream_t *s)
++{
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int offset;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++ offset = 0;
++
++ // tx_spin value is used here to check if a transfer is active
++ if (s->tx_spin) {
++ offset = (runtime->period_size * (s->periods)) + 0;
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++ DPRINTK("MXC: audio_get_dma_pos offset %d\n", offset);
++ } else {
++ offset = (runtime->period_size * (s->periods));
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++ DPRINTK("MXC: audio_get_dma_pos BIS offset %d\n", offset);
++ }
++
++ return offset;
++}
++
++/*
++ * This function stops the current dma transfer for playback
++ * and clears the dma pointers.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static void audio_playback_stop_dma (audio_stream_t *s)
++{
++ unsigned long flags;
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size;
++ unsigned int offset;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ offset = dma_size * s->periods;
++
++ spin_lock_irqsave (&s->dma_lock, flags);
++
++ PRINTK("MXC : audio_stop_dma active = 0\n");
++ s->active = 0;
++ s->period = 0;
++ s->periods = 0;
++
++ // this stops the dma channel and clears the buffer ptrs
++ mxc_dma_disable (s->dma_wchannel);
++ dma_unmap_single (NULL, runtime->dma_addr + offset, dma_size,
++ DMA_TO_DEVICE);
++
++ spin_unlock_irqrestore (&s->dma_lock, flags);
++}
++
++/*
++ * This function stops the current dma transfer for capture
++ * and clears the dma pointers.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static void audio_capture_stop_dma (audio_stream_t *s)
++{
++ unsigned long flags;
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size;
++ unsigned int offset;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ offset = dma_size * s->periods;
++
++ spin_lock_irqsave (&s->dma_lock, flags);
++
++ PRINTK("MXC : audio_stop_dma active = 0\n");
++ s->active = 0;
++ s->period = 0;
++ s->periods = 0;
++
++ // this stops the dma channel and clears the buffer ptrs
++ mxc_dma_disable (s->dma_wchannel);
++ dma_unmap_single (NULL, runtime->dma_addr + offset, dma_size,
++ DMA_FROM_DEVICE);
++
++ spin_unlock_irqrestore (&s->dma_lock, flags);
++}
++
++/*
++ * This function is called whenever a new audio block needs to be
++ * transferred to CODEC. The function receives the address and the size
++ * of the new block and start a new DMA transfer.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static void audio_playback_dma (audio_stream_t *s)
++{
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size = 0;
++ unsigned int offset;
++ int ret = 0;
++ mxc_dma_requestbuf_t dma_request;
++ int device;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++ device = substream->pcm->device;
++
++ DPRINTK("\nDMA direction %d\(0 is playback 1 is capture)\n",
++ s->stream_id);
++
++ memset (&dma_request, 0, sizeof (mxc_dma_requestbuf_t));
++
++ if (s->active) {
++ if (ssi_get_status(s->ssi) & ssi_transmitter_underrun_0) {
++ ssi_enable (s->ssi, false);
++ ssi_transmit_enable (s->ssi, false);
++ ssi_enable (s->ssi, true);
++ }
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ DPRINTK("s->period (%x) runtime->periods (%d)\n",
++ s->period, runtime->periods);
++ DPRINTK("runtime->period_size (%d) dma_size (%d)\n",
++ (unsigned int) runtime->period_size,
++ runtime->dma_bytes);
++
++ offset = dma_size * s->period;
++ snd_assert (dma_size <= DMA_BUF_SIZE,);
++
++ dma_request.src_addr = (dma_addr_t) (dma_map_single (NULL,
++ runtime->
++ dma_area +
++ offset,
++ dma_size,
++ DMA_TO_DEVICE));
++
++ if (s->ssi == SSI1)
++ dma_request.dst_addr = (dma_addr_t) (SSI1_BASE_ADDR + MXC_SSI1STX0);
++ else
++ dma_request.dst_addr = (dma_addr_t) (SSI2_BASE_ADDR + MXC_SSI2STX0);
++ dma_request.num_of_bytes = dma_size;
++
++ DPRINTK("MXC: Start DMA offset (%d) size (%d)\n", offset,
++ runtime->dma_bytes);
++
++ mxc_dma_config (s->dma_wchannel, &dma_request, 1,
++ MXC_DMA_MODE_WRITE);
++ ret = mxc_dma_enable (s->dma_wchannel);
++ ssi_transmit_enable (s->ssi, true);
++ ssi_enable (s->ssi, true);
++ s->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
++
++ if (ret) {
++ DPRINTK("audio_process_dma: cannot queue DMA buffer\
++ (%i)\n", ret);
++ return;
++ }
++ s->period++;
++ s->period %= runtime->periods;
++
++#ifdef MXC_SOUND_PLAYBACK_CHAIN_DMA_EN
++ if ((s->period > s->periods) && ((s->period - s->periods) > 1)) {
++ PRINTK("audio playback chain dma: already double buffered\n");
++ return;
++ }
++
++ if ((s->period < s->periods)
++ && ((s->period + runtime->periods - s->periods) > 1)) {
++ PRINTK("audio playback chain dma: already double buffered\n");
++ return;
++ }
++
++ if (s->period == s->periods) {
++ PRINTK("audio playback chain dma: s->period == s->periods\n");
++ return;
++ }
++
++ if (snd_pcm_playback_hw_avail(runtime) <
++ 2 * runtime->period_size) {
++ PRINTK("audio playback chain dma: available data is not enough\n");
++ return;
++ }
++
++ PRINTK("audio playback chain dma:to set up the 2nd dma buffer\n");
++ offset = dma_size * s->period;
++ dma_request.src_addr = (dma_addr_t) (dma_map_single (NULL,
++ runtime->
++ dma_area +
++ offset,
++ dma_size,
++ DMA_TO_DEVICE));
++ mxc_dma_config (s->dma_wchannel, &dma_request, 1,
++ MXC_DMA_MODE_WRITE);
++ ret = mxc_dma_enable (s->dma_wchannel);
++
++ s->period++;
++ s->period %= runtime->periods;
++#endif // MXC_SOUND_PLAYBACK_CHAIN_DMA_EN
++ }
++}
++
++/*
++ * This function is called whenever a new audio block needs to be
++ * transferred from CODEC. The function receives the address and the size
++ * of the block that will store the audio samples and start a new DMA transfer.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static void audio_capture_dma (audio_stream_t *s)
++{
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size;
++ unsigned int offset;
++ int ret = 0;
++ mxc_dma_requestbuf_t dma_request;
++
++ substream = s->stream;
++ runtime = substream->runtime;
++
++ DPRINTK("\nDMA direction %d\
++ (0 is playback 1 is capture)\n", s->stream_id);
++
++ memset (&dma_request, 0, sizeof (mxc_dma_requestbuf_t));
++
++ if (s->active) {
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ DPRINTK("s->period (%x) runtime->periods (%d)\n",
++ s->period, runtime->periods);
++ DPRINTK("runtime->period_size (%d) dma_size (%d)\n",
++ (unsigned int) runtime->period_size,
++ runtime->dma_bytes);
++
++ offset = dma_size * s->period;
++ snd_assert (dma_size <= DMA_BUF_SIZE,);
++
++ dma_request.dst_addr = (dma_addr_t) (dma_map_single(NULL,
++ runtime->
++ dma_area +
++ offset,
++ dma_size,
++ DMA_FROM_DEVICE));
++ if (s->ssi == SSI1)
++ dma_request.src_addr = (dma_addr_t) (SSI1_BASE_ADDR + MXC_SSI1SRX0);
++ else
++ dma_request.src_addr = (dma_addr_t) (SSI2_BASE_ADDR + MXC_SSI2SRX0);
++ dma_request.num_of_bytes = dma_size;
++
++ DPRINTK("MXC: Start DMA offset (%d) size (%d)\n", offset,
++ runtime->dma_bytes);
++
++ mxc_dma_config (s->dma_wchannel, &dma_request, 1,
++ MXC_DMA_MODE_READ);
++ ret = mxc_dma_enable (s->dma_wchannel);
++
++ s->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
++
++ if (ret) {
++ DPRINTK("audio_process_dma: cannot queue DMA buffer\
++ (%i)\n", ret);
++ return;
++ }
++ s->period++;
++ s->period %= runtime->periods;
++
++#ifdef MXC_SOUND_CAPTURE_CHAIN_DMA_EN
++ if ((s->period > s->periods) && ((s->period - s->periods) > 1)) {
++ PRINTK("audio capture chain dma: already double buffered\n");
++ return;
++ }
++
++ if ((s->period < s->periods)
++ && ((s->period + runtime->periods - s->periods) > 1)) {
++ PRINTK("audio capture chain dma: already double buffered\n");
++ return;
++ }
++
++ if (s->period == s->periods) {
++ PRINTK("audio capture chain dma: s->period == s->periods\n");
++ return;
++ }
++
++ if (snd_pcm_capture_hw_avail (runtime) <
++ 2 * runtime->period_size) {
++ PRINTK("audio capture chain dma: available data is not enough\n");
++ return;
++ }
++
++ PRINTK("audio capture chain dma:to set up the 2nd dma buffer\n");
++ offset = dma_size * s->period;
++ dma_request.dst_addr = (dma_addr_t) (dma_map_single(NULL,
++ runtime->
++ dma_area +
++ offset,
++ dma_size,
++ DMA_FROM_DEVICE));
++ mxc_dma_config (s->dma_wchannel, &dma_request, 1,
++ MXC_DMA_MODE_READ);
++ ret = mxc_dma_enable (s->dma_wchannel);
++
++ s->period++;
++ s->period %= runtime->periods;
++#endif // MXC_SOUND_CAPTURE_CHAIN_DMA_EN
++ }
++}
++
++/*
++ * This is a callback which will be called
++ * when a TX transfer finishes. The call occurs
++ * in interrupt context.
++ *
++ * @param dat pointer to the structure of the current stream.
++ *
++ */
++static void audio_playback_dma_callback (void *data, int error,
++ unsigned int count)
++{
++ audio_stream_t *s;
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size;
++ unsigned int previous_period;
++ unsigned int offset;
++
++ s = data;
++ substream = s->stream;
++ runtime = substream->runtime;
++ previous_period = s->periods;
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ offset = dma_size * previous_period;
++
++ s->tx_spin = 0;
++ s->periods++;
++ s->periods %= runtime->periods;
++
++ // Give back to the CPU the access to the non cached memory
++ dma_unmap_single (NULL, runtime->dma_addr + offset, dma_size,
++ DMA_TO_DEVICE);
++
++ /*
++ * If we are getting a callback for an active stream then we inform
++ * the PCM middle layer we've finished a period
++ */
++ if (s->active)
++ snd_pcm_period_elapsed (s->stream);
++
++ spin_lock (&s->dma_lock);
++
++ // Trig next DMA transfer
++ audio_playback_dma (s);
++
++ spin_unlock (&s->dma_lock);
++}
++
++/*
++ * This is a callback which will be called when a RX transfer finishes. The
++ * call occurs in interrupt context.
++ *
++ * @param substream pointer to the structure of the current stream.
++ */
++static void audio_capture_dma_callback (void *data, int error,
++ unsigned int count)
++{
++ audio_stream_t *s;
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ unsigned int dma_size;
++ unsigned int previous_period;
++ unsigned int offset;
++
++ s = data;
++ substream = s->stream;
++ runtime = substream->runtime;
++ previous_period = s->periods;
++ dma_size = frames_to_bytes (runtime, runtime->period_size);
++ offset = dma_size * previous_period;
++
++ s->tx_spin = 0;
++ s->periods++;
++ s->periods %= runtime->periods;
++
++ // Give back to the CPU the access to the non cached memory
++ dma_unmap_single (NULL, runtime->dma_addr + offset, dma_size,
++ DMA_FROM_DEVICE);
++
++ /*
++ * If we are getting a callback for an active stream then we inform
++ * the PCM middle layer we've finished a period
++ */
++ if (s->active)
++ snd_pcm_period_elapsed (s->stream);
++
++ spin_lock (&s->dma_lock);
++
++ // Trig next DMA transfer
++ audio_capture_dma (s);
++
++ spin_unlock (&s->dma_lock);
++}
++
++/*
++ * This function is a dispatcher of command to be executed
++ * by the driver for playback.
++ *
++ * @param substream pointer to the structure of the current stream.
++ * @param cmd command to be executed
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int
++snd_mxc_audio_playback_trigger (struct snd_pcm_substream *substream, int cmd)
++{
++ mxc_bmi_audio_t *chip;
++ int stream_id = PLAYBACK_STREAM;
++ audio_stream_t *s;
++ int err;
++ int device;
++
++ device = substream->pcm->device;
++ chip = snd_pcm_substream_chip (substream);
++ stream_id = substream->pstr->stream;
++ s = &chip->s[stream_id];
++ err = 0;
++
++ // note local interrupts are already disabled in the midlevel code
++ spin_lock (&s->dma_lock);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_START\n");
++ s->tx_spin = 0;
++ // requested stream startup
++ s->active = 1;
++ audio_playback_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_STOP\n");
++ // requested stream shutdown
++ audio_playback_stop_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ PRINTK("MXC : SNDRV_PCM_TRIGGER_SUSPEND active = 0\n");
++ s->active = 0;
++ s->periods = 0;
++ break;
++ case SNDRV_PCM_TRIGGER_RESUME:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_RESUME\n");
++ s->active = 1;
++ s->tx_spin = 0;
++ audio_playback_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_PAUSE_PUSH\n");
++ s->active = 0;
++ break;
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_PAUSE_RELEASE\n");
++ s->active = 1;
++ if (s->old_offset) {
++ s->tx_spin = 0;
++ audio_playback_dma (s);
++ break;
++ }
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++ spin_unlock (&s->dma_lock);
++ return err;
++}
++
++/*
++ * This function is a dispatcher of command to be executed
++ * by the driver for capture.
++ *
++ * @param substream pointer to the structure of the current stream.
++ * @param cmd command to be executed
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int
++snd_mxc_audio_capture_trigger (struct snd_pcm_substream *substream, int cmd)
++{
++ mxc_bmi_audio_t *chip;
++ int stream_id;
++ audio_stream_t *s;
++ int err;
++
++ chip = snd_pcm_substream_chip (substream);
++ stream_id = substream->pstr->stream;
++ s = &chip->s[stream_id];
++ err = 0;
++
++ // note local interrupts are already disabled in the midlevel code
++ spin_lock (&s->dma_lock);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_START\n");
++ s->tx_spin = 0;
++ // requested stream startup
++ s->active = 1;
++ audio_capture_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_STOP\n");
++ // requested stream shutdown
++ audio_capture_stop_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ PRINTK("MXC : SNDRV_PCM_TRIGGER_SUSPEND active = 0\n");
++ s->active = 0;
++ s->periods = 0;
++ break;
++ case SNDRV_PCM_TRIGGER_RESUME:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_RESUME\n");
++ s->active = 1;
++ s->tx_spin = 0;
++ audio_capture_dma (s);
++ break;
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_PAUSE_PUSH\n");
++ s->active = 0;
++ break;
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ PRINTK("MXC: SNDRV_PCM_TRIGGER_PAUSE_RELEASE\n");
++ s->active = 1;
++ if (s->old_offset) {
++ s->tx_spin = 0;
++ audio_capture_dma (s);
++ break;
++ }
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++ spin_unlock (&s->dma_lock);
++ return err;
++}
++
++/*
++ * This function configures the hardware to allow audio
++ * playback operations. It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_playback_prepare (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ audio_stream_t *s;
++ int ssi;
++ int device = -1;
++ int stream_id = PLAYBACK_STREAM;
++ struct snd_pcm_runtime *runtime;
++
++ device = substream->pcm->device;
++
++ chip = snd_pcm_substream_chip (substream);
++ runtime = substream->runtime;
++ s = &chip->s[stream_id];
++ ssi = s->ssi;
++
++ configure_dam_bmi_master (ssi);
++ configure_ssi_rx (ssi);
++ ssi_rx_sampleRate (ssi, runtime->rate);
++ configure_ssi_tx (ssi);
++ ssi_tx_sampleRate (ssi, runtime->rate);
++ set_bmi_channels (substream);
++ ssi_interrupt_enable (ssi, ssi_tx_dma_interrupt_enable);
++ ssi_interrupt_enable(ssi, ssi_tx_interrupt_enable);
++ ssi_interrupt_enable (ssi, ssi_tx_fifo_0_empty);
++ ssi_enable(ssi, true);
++
++ s->period = 0;
++ s->periods = 0;
++
++ msleep (100);
++
++ return 0;
++}
++
++/*
++ * This function gets the current capture pointer position.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static snd_pcm_uframes_t
++snd_mxc_audio_capture_pointer (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++
++ chip = snd_pcm_substream_chip (substream);
++ return audio_get_capture_dma_pos (&chip->s[substream->pstr->stream]);
++}
++
++/*
++ * This function gets the current playback pointer position.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ */
++static snd_pcm_uframes_t
++snd_mxc_audio_playback_pointer (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ int device;
++ int stream_id;
++ device = substream->pcm->device;
++ stream_id = PLAYBACK_STREAM;
++ chip = snd_pcm_substream_chip (substream);
++ return audio_get_playback_dma_pos (&chip->s[stream_id]);
++}
++
++/*
++ * This structure reprensents the capabilities of the driver
++ * in capture mode.
++ * It is used by ALSA framework.
++ */
++static struct snd_pcm_hardware snd_mxc_bmi_capture = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = (SNDRV_PCM_RATE_8000_96000 | SNDRV_PCM_RATE_CONTINUOUS),
++ .rate_min = 8000,
++ .rate_max = 96000,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = MAX_BUFFER_SIZE,
++ .period_bytes_min = MIN_PERIOD_SIZE,
++ .period_bytes_max = DMA_BUF_SIZE,
++ .periods_min = MIN_PERIOD,
++ .periods_max = MAX_PERIOD,
++ .fifo_size = 0,
++};
++
++/*
++ * This structure reprensents the capabilities of the driver
++ * in playback mode for ST-Dac.
++ * It is used by ALSA framework.
++ */
++static struct snd_pcm_hardware snd_mxc_bmi_playback_stereo = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = (SNDRV_PCM_RATE_8000_96000 | SNDRV_PCM_RATE_CONTINUOUS),
++ .rate_min = 8000,
++ .rate_max = 96000,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = MAX_BUFFER_SIZE,
++ .period_bytes_min = MIN_PERIOD_SIZE,
++ .period_bytes_max = DMA_BUF_SIZE,
++ .periods_min = MIN_PERIOD,
++ .periods_max = MAX_PERIOD,
++ .fifo_size = 0,
++};
++
++/*
++ * This function opens a CODEC audio device in playback mode
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_card_mxc_audio_playback_open (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ struct snd_pcm_runtime *runtime;
++ int stream_id = -1;
++ int err;
++ int device = -1;
++
++ device = substream->pcm->device;
++
++ chip = snd_pcm_substream_chip (substream);
++ runtime = substream->runtime;
++ stream_id = PLAYBACK_STREAM;
++
++ err = -1;
++
++ audio_mixer_control[chip->s->ssi].codec_playback_active = 1;
++
++ chip->s[stream_id].stream = substream;
++
++ runtime->hw = snd_mxc_bmi_playback_stereo;
++
++ if ((err = snd_pcm_hw_constraint_integer (runtime,
++ SNDRV_PCM_HW_PARAM_PERIODS)) <
++ 0)
++ return err;
++ if ((err = snd_pcm_hw_constraint_list (runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
++ &hw_playback_rates_stereo)) < 0)
++ return err;
++
++ msleep (10);
++
++ // setup DMA controller for playback
++ if ((err =
++ configure_write_channel (&mxc_audio[chip->s->ssi]->s[stream_id],
++ audio_playback_dma_callback,
++ stream_id)) < 0)
++ return err;
++
++ return 0;
++}
++
++/*
++ * This function closes an CODEC audio device for playback.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_card_mxc_audio_playback_close (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ audio_stream_t *s;
++ int ssi;
++ int device, stream_id = -1;
++
++ device = substream->pcm->device;
++ stream_id = PLAYBACK_STREAM;
++
++ chip = snd_pcm_substream_chip (substream);
++ s = &chip->s[stream_id];
++ ssi = s->ssi;
++
++ audio_mixer_control[chip->s->ssi].codec_playback_active = 0;
++
++ ssi_tx_fifo_enable (ssi, ssi_fifo_0, false);
++ ssi_interrupt_disable (ssi, ssi_tx_interrupt_enable);
++ ssi_interrupt_disable (ssi, ssi_tx_dma_interrupt_enable);
++ ssi_interrupt_disable (ssi, ssi_tx_fifo_0_empty);
++ mxc_dma_free ((mxc_audio[ssi]->s[stream_id]).dma_wchannel);
++
++ chip->s[stream_id].stream = NULL;
++
++ return 0;
++}
++
++/*
++ * This function closes a audio device for capture.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_card_mxc_audio_capture_close (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ audio_stream_t *s;
++ int ssi;
++
++ chip = snd_pcm_substream_chip (substream);
++ s = &chip->s[substream->pstr->stream];
++ ssi = s->ssi;
++
++ audio_mixer_control[ssi].codec_capture_active = 0;
++
++ ssi_rx_fifo_enable (ssi, ssi_fifo_0, false);
++ ssi_interrupt_disable(ssi, ssi_rx_interrupt_enable);
++ ssi_interrupt_disable (ssi, ssi_rx_dma_interrupt_enable);
++ ssi_interrupt_disable (ssi, ssi_rx_fifo_0_full);
++ mxc_dma_free ((mxc_audio[ssi]->s[1]).dma_wchannel);
++
++ chip->s[substream->pstr->stream].stream = NULL;
++
++ return 0;
++}
++
++/*
++ * This function configure the Audio HW in terms of memory allocation.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_hw_params (struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ struct snd_pcm_runtime *runtime;
++ int ret;
++
++ runtime = substream->runtime;
++ ret =
++ snd_pcm_lib_malloc_pages (substream, params_buffer_bytes (hw_params));
++ if (ret < 0)
++ return ret;
++
++ runtime->dma_addr = virt_to_phys (runtime->dma_area);
++
++ DPRINTK("MXC: snd_mxc_audio_hw_params runtime->dma_addr 0x(%x)\n",
++ (unsigned int) runtime->dma_addr);
++ DPRINTK("MXC: snd_mxc_audio_hw_params runtime->dma_area 0x(%x)\n",
++ (unsigned int) runtime->dma_area);
++ DPRINTK("MXC: snd_mxc_audio_hw_params runtime->dma_bytes 0x(%x)\n",
++ (unsigned int) runtime->dma_bytes);
++
++ return ret;
++}
++
++/*
++ * This function frees the audio hardware at the end of playback/capture.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_hw_free (struct snd_pcm_substream *substream)
++{
++ return snd_pcm_lib_free_pages (substream);
++}
++
++/*
++ * This function configures the hardware to allow audio
++ * capture operations. It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_capture_prepare (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ audio_stream_t *s;
++ struct snd_pcm_runtime *runtime;
++ int ssi;
++
++ chip = snd_pcm_substream_chip (substream);
++ runtime = substream->runtime;
++ s = &chip->s[substream->pstr->stream];
++ ssi = s->ssi;
++
++ DPRINTK("substream->pstr->stream %d\n", substream->pstr->stream);
++ DPRINTK("SSI%d\n", ssi + 1);
++
++ configure_dam_bmi_master (ssi);
++ configure_ssi_tx (ssi);
++ ssi_tx_sampleRate (ssi, runtime->rate);
++ configure_ssi_rx (ssi);
++ ssi_rx_sampleRate (ssi, runtime->rate);
++
++ ssi_interrupt_enable (ssi, ssi_rx_fifo_0_full);
++ ssi_interrupt_enable (ssi, ssi_rx_dma_interrupt_enable);
++ ssi_interrupt_enable (ssi, ssi_rx_interrupt_enable);
++ set_bmi_channels (substream);
++ ssi_receive_enable (ssi, true);
++
++ msleep(20);
++
++ s->period = 0;
++ s->periods = 0;
++
++ return 0;
++}
++
++/*
++ * This function opens an audio device in capture mode on Codec.
++ * It is called by ALSA framework.
++ *
++ * @param substream pointer to the structure of the current stream.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_card_mxc_audio_capture_open (struct snd_pcm_substream *substream)
++{
++ mxc_bmi_audio_t *chip;
++ struct snd_pcm_runtime *runtime;
++ int stream_id;
++ int err;
++
++ chip = snd_pcm_substream_chip (substream);
++ runtime = substream->runtime;
++ stream_id = substream->pstr->stream;
++ err = -1;
++
++ audio_mixer_control[chip->s->ssi].codec_capture_active = 1;
++
++ chip->s[stream_id].stream = substream;
++
++ if (stream_id == SNDRV_PCM_STREAM_CAPTURE) {
++ runtime->hw = snd_mxc_bmi_capture;
++ } else {
++ return err;
++ }
++
++ if ((err = snd_pcm_hw_constraint_integer (runtime,
++ SNDRV_PCM_HW_PARAM_PERIODS)) <
++ 0) {
++ return err;
++ }
++
++ if ((err = snd_pcm_hw_constraint_list (runtime, 0,
++ SNDRV_PCM_HW_PARAM_RATE,
++ &hw_capture_rates_stereo)) < 0) {
++ return err;
++ }
++
++ // setup DMA controller for Record
++ err = configure_read_channel (&mxc_audio[chip->s->ssi]->s[SNDRV_PCM_STREAM_CAPTURE],
++ audio_capture_dma_callback);
++ if (err < 0) {
++ return err;
++ }
++
++ msleep (50);
++
++ return 0;
++}
++
++/*
++ * This structure is the list of operation that the driver
++ * must provide for the capture interface
++ */
++static struct snd_pcm_ops snd_card_mxc_audio_capture_ops = {
++ .open = snd_card_mxc_audio_capture_open,
++ .close = snd_card_mxc_audio_capture_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_mxc_audio_hw_params,
++ .hw_free = snd_mxc_audio_hw_free,
++ .prepare = snd_mxc_audio_capture_prepare,
++ .trigger = snd_mxc_audio_capture_trigger,
++ .pointer = snd_mxc_audio_capture_pointer,
++};
++
++/*
++ * This structure is the list of operation that the driver
++ * must provide for the playback interface
++ */
++static struct snd_pcm_ops snd_card_mxc_audio_playback_ops = {
++ .open = snd_card_mxc_audio_playback_open,
++ .close = snd_card_mxc_audio_playback_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_mxc_audio_hw_params,
++ .hw_free = snd_mxc_audio_hw_free,
++ .prepare = snd_mxc_audio_playback_prepare,
++ .trigger = snd_mxc_audio_playback_trigger,
++ .pointer = snd_mxc_audio_playback_pointer,
++};
++
++/*
++ * This functions initializes the capture audio device supported by
++ * CODEC IC.
++ *
++ * @param mxc_audio pointer to the sound card structure
++ * @param device SSI interface
++ */
++void init_device_capture (mxc_bmi_audio_t *mxc_audio, int device)
++{
++ audio_stream_t *audio_stream;
++
++ audio_stream = &mxc_audio->s[SNDRV_PCM_STREAM_CAPTURE];
++
++ /*
++ * These parameters defines the identity of
++ * the device (stereoadc or stereodac)
++ */
++ if (device == 0) {
++ audio_stream->ssi = SSI1;
++ audio_stream->dam_port = DAM_PORT_4;
++ } else {
++ audio_stream->ssi = SSI2;
++ audio_stream->dam_port = DAM_PORT_5;
++ }
++}
++
++/*
++ * This functions initializes the playback audio device supported by
++ * CODEC IC.
++ *
++ * @param mxc_audio pointer to the sound card structure.
++ * @param device SSI interface
++ */
++void init_device_playback (mxc_bmi_audio_t *mxc_audio, int device)
++{
++ audio_stream_t *audio_stream;
++ audio_stream = &mxc_audio->s[0];
++
++ /* These parameters defines the identity of
++ * the device (codec or stereodac)
++ */
++ if (device == 0) {
++ audio_stream->ssi = SSI1;
++ audio_stream->dam_port = DAM_PORT_4;
++ } else {
++ audio_stream->ssi = SSI2;
++ audio_stream->dam_port = DAM_PORT_5;
++ }
++}
++
++void mxc_bmi_mixer_controls_init (mxc_bmi_audio_t *mxc_audio, int device)
++{
++ audio_mixer_control_t *audio_control;
++ struct i2c_adapter *adap = 0;
++ char iox_data[1];
++ int i = 0;
++
++ audio_control = &audio_mixer_control[device];
++
++ memset (audio_control, 0, sizeof (audio_mixer_control_t));
++ sema_init (&audio_control->sem, 1);
++
++ for (i = 0; i < OP_MAXDEV; i++) {
++ audio_control->vol_for_output[i] = 9; // maximum gain
++ }
++ for (i = 0; i < IP_MAXDEV; i++) {
++ audio_control->vol_for_input[i] = 4; // gain = -6 dB
++ }
++
++ audio_control->master_volume_out = 127;
++
++ if(device == 0) {
++ if (bmi_audio[0].active == 1) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active == 1) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++ } else {
++ if (bmi_audio[1].active == 1) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active == 1) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++ }
++
++ if (adap) {
++ // IOX status
++ if (ReadByte_IOX (adap, IOX_INPUT_REG, iox_data) == 0) {
++ audio_control->lo_indicator = (*iox_data >> IOX_LO_INS) & 0x1;
++ audio_control->li_indicator = (*iox_data >> IOX_LI_INS) & 0x1;
++ audio_control->mic_indicator = (*iox_data >> IOX_MIC_INS) & 0x1;
++ audio_control->hp_indicator = (*iox_data >> IOX_HP_INS) & 0x1;
++ }
++ }
++}
++
++/*
++ * This functions initializes the audio devices supported by
++ * CODEC IC.
++ *
++ * @param mxc_audio pointer to the sound card structure.
++ * @param device SSi interface
++ */
++void mxc_bmi_audio_init (mxc_bmi_audio_t *mxc_audio, int device)
++{
++ mxc_audio->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Audio out";
++ mxc_audio->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK;
++ mxc_audio->s[SNDRV_PCM_STREAM_CAPTURE].id = "Audio in";
++ mxc_audio->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE;
++
++ init_device_playback (mxc_audio, device);
++ init_device_capture (mxc_audio, device);
++}
++
++/*
++ * This function initializes the soundcard structure.
++ *
++ * @param mxc_audio pointer to the sound card structure.
++ * @param device the device index (zero based)
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int __init snd_card_mxc_audio_pcm (mxc_bmi_audio_t *mxc_audio, int device)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ // Create a new PCM instance with 1 capture stream and 1 playback substream
++ if (device == 0) {
++ if ((err = snd_pcm_new (mxc_audio->card, "PIM_AUDIO13", 0, 1, 1, &pcm)) < 0) {
++ return err;
++ }
++ } else {
++ if ((err = snd_pcm_new (mxc_audio->card, "PIM_AUDIO24", 0, 1, 1, &pcm)) < 0) {
++ return err;
++ }
++ }
++
++ /*
++ * this sets up our initial buffers and sets the dma_type to isa.
++ * isa works but I'm not sure why (or if) it's the right choice
++ * this may be too large, trying it for now
++ */
++ snd_pcm_lib_preallocate_pages_for_all (pcm, SNDRV_DMA_TYPE_CONTINUOUS,
++ snd_dma_continuous_data
++ (GFP_KERNEL), MAX_BUFFER_SIZE * 2,
++ MAX_BUFFER_SIZE * 2);
++
++ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_card_mxc_audio_playback_ops);
++ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_CAPTURE,
++ &snd_card_mxc_audio_capture_ops);
++
++ pcm->private_data = mxc_audio;
++ pcm->info_flags = 0;
++ if (device == 0)
++ strncpy (pcm->name, SOUND_CARD13_NAME, sizeof (pcm->name));
++ else
++ strncpy (pcm->name, SOUND_CARD24_NAME, sizeof (pcm->name));
++ mxc_audio->pcm[0] = pcm;
++ mxc_bmi_audio_init (mxc_audio, device);
++ mxc_bmi_mixer_controls_init (mxc_audio, device);
++
++ return 0;
++}
++
++#if 0 //pjg - POWER_MANAGEMENT
++#ifdef CONFIG_PM
++/*
++ * This function suspends all active streams.
++ *
++ * TBD
++ *
++ * @param card pointer to the sound card structure.
++ * @param state requested state
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_suspend (struct bmi_device *bdev,
++ pm_message_t state)
++{
++ struct snd_card *card = bmi_device_get_drvdata (bdev);
++ mxc_bmi_audio_t *chip = card->private_data;
++
++ snd_power_change_state (card, SNDRV_CTL_POWER_D3hot);
++ snd_pcm_suspend_all (chip->pcm[0]);
++ //mxc_alsa_audio_shutdown (chip);
++
++ return 0;
++}
++
++/*
++ * This function resumes all suspended streams.
++ *
++ * TBD
++ *
++ * @param card pointer to the sound card structure.
++ * @param state requested state
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++static int snd_mxc_audio_resume (struct bmi_device *bdev)
++{
++ struct snd_card *card = bmi_device_get_drvdata (bdev);
++
++ snd_power_change_state (card, SNDRV_CTL_POWER_D0);
++
++ return 0;
++}
++#endif // CONFIG_PM
++#endif //pjg - POWER_MANAGEMENT
++
++/*
++ * This function frees the sound card structure
++ *
++ * @param card pointer to the sound card structure.
++ *
++ * @return 0 on success, -1 otherwise.
++ */
++void snd_mxc_audio_free (struct snd_card *card)
++{
++ mxc_bmi_audio_t *chip;
++
++ chip = card->private_data;
++ audio_dma_free (&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
++ audio_dma_free (&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
++ mxc_audio[chip->s->ssi] = NULL;
++ card->private_data = NULL;
++ kfree (chip);
++
++}
++
++/*
++ * Input interrupt handler and support routines
++ */
++
++ // work handler
++void bmiaudio_input_work (void *arg, int slot) {
++ struct bmi_audio *audio = (struct bmi_audio *) arg;
++ audio_mixer_control_t *audio_control;
++ struct i2c_adapter *adap;
++ unsigned char iox_data[1];
++ int input_data;
++
++ if (audio->bdev == 0) {
++ printk (KERN_INFO
++ "bmi_audio.c: bmi_audio_input work called with no bdev (slot %d)\n",
++ slot);
++ return;
++ }
++
++ if (bmi_device_present (audio->bdev) == 0) {
++ printk (KERN_INFO
++ "bmi_audio.c: bmi_audio_input work called with no bdev active (slot %d)\n",
++ slot);
++ return;
++ }
++
++ adap = bmi_device_get_i2c_adapter (audio->bdev);
++
++ // IOX status
++ if (ReadByte_IOX (adap, IOX_INPUT_REG, iox_data) != 0) {
++ return;
++ }
++ input_data = 0;
++ if ((*iox_data & GETSTAT_VOLP) == 0)
++ input_data |= VOLUME_UP;
++ if ((*iox_data & GETSTAT_VOLD) == 0)
++ input_data |= VOLUME_DOWN;
++ if ((*iox_data & GETSTAT_LI_INS) == GETSTAT_LI_INS)
++ input_data |= LINEIN_INSERTED;
++ if ((*iox_data & GETSTAT_MIC_INS) != GETSTAT_MIC_INS)
++ input_data |= MICROPHONE_INSERTED;
++ if (output_ints) {
++ if ((*iox_data & GETSTAT_LO_INS) == GETSTAT_LO_INS)
++ input_data |= LINEOUT_INSERTED;
++ if ((*iox_data & GETSTAT_HP_INS) == GETSTAT_HP_INS)
++ input_data |= HEADPHONE_INSERTED;
++ }
++ input_report_abs (audio->input_dev, ABS_MISC, input_data);
++ input_sync (audio->input_dev);
++
++ if ((slot == 0) || (slot == 2)) {
++ audio_control = &audio_mixer_control[0];
++ } else {
++ audio_control = &audio_mixer_control[1];
++ }
++
++ if (down_interruptible (&audio_control->sem) == 0) {
++ audio_control->lo_indicator = (*iox_data >> IOX_LO_INS) & 0x1;
++ audio_control->li_indicator = (*iox_data >> IOX_LI_INS) & 0x1;
++ audio_control->mic_indicator = (*iox_data >> IOX_MIC_INS) & 0x1;
++ audio_control->hp_indicator = (*iox_data >> IOX_HP_INS) & 0x1;
++ up (&audio_control->sem);
++ }
++
++ enable_irq (audio->irq);
++ return;
++}
++
++void bmiaudio_input_work0 (struct work_struct *work) {
++ bmiaudio_input_work (&bmi_audio[0], 0);
++}
++
++void bmiaudio_input_work1 (struct work_struct *work) {
++ bmiaudio_input_work (&bmi_audio[1], 1);
++}
++
++void bmiaudio_input_work2 (struct work_struct *work) {
++ bmiaudio_input_work (&bmi_audio[2], 2);
++}
++
++void bmiaudio_input_work3 (struct work_struct *work) {
++ bmiaudio_input_work (&bmi_audio[3], 3);
++}
++
++DECLARE_DELAYED_WORK(bmiaudio_work0, bmiaudio_input_work0);
++DECLARE_DELAYED_WORK(bmiaudio_work1, bmiaudio_input_work1);
++DECLARE_DELAYED_WORK(bmiaudio_work2, bmiaudio_input_work2);
++DECLARE_DELAYED_WORK(bmiaudio_work3, bmiaudio_input_work3);
++
++static irqreturn_t module_irq_handler (int irq, void *dummy)
++{
++ disable_irq_nosync (irq);
++
++ switch (irq) {
++ case M1_IRQ:
++ schedule_delayed_work (&bmiaudio_work0, WORK_DELAY);
++ break;
++ case M2_IRQ:
++ schedule_delayed_work (&bmiaudio_work1, WORK_DELAY);
++ break;
++ case M3_IRQ:
++ schedule_delayed_work (&bmiaudio_work2, WORK_DELAY);
++ break;
++ case M4_IRQ:
++ schedule_delayed_work (&bmiaudio_work3, WORK_DELAY);
++ break;
++ }
++ return IRQ_HANDLED;
++}
++
++/*
++ * Configure the CODEC registers to the initial values
++ */
++
++static int configure_CODEC(struct i2c_adapter *adap, struct bmi_audio *audio)
++{
++ unsigned char codec_data[1];
++
++ // page select = 0
++ if (WriteByte_CODEC (adap, CODEC_PAGE_SEL, 0x00))
++ goto nodev;
++ if (ReadByte_CODEC (adap, CODEC_PAGE_SEL, codec_data))
++ goto nodev;
++ if (*codec_data != 0x00)
++ goto nodev;
++
++ // ADC,DAC SR = SR/1
++ if (WriteByte_CODEC (adap, CODEC_SAMPLE_RATE, (CODEC_SR1 << CODEC_SR_SHIFT) | CODEC_SR1))
++ goto nodev;
++
++ // PLL disabled, Q = 2 => Fsref = 46875 Hz
++ if (WriteByte_CODEC (adap, CODEC_PLLA, CODEC_PLLA_DIS | CODEC_PLLA_Q(2)))
++ goto nodev;
++
++ // CODEC datapath normal
++ if (WriteByte_CODEC (adap, CODEC_DATAPATH,
++ CODEC_DP_44 | CODEC_DP_L(CODEC_DP_REVERSE) | CODEC_DP_R(CODEC_DP_NORMAL)))
++ goto nodev;
++
++ // CODEC is slave
++ if (WriteByte_CODEC (adap, CODEC_AIFA, CODEC_AIFA_BCLK_S | CODEC_AIFA_WCLK_S |
++ CODEC_AIFA_DOUT_TS | CODEC_AIFA_CLK_F | CODEC_AIFA_FX_OFF))
++ goto nodev;
++
++ // CODEC is in I2S mode, WL = 32
++ if (WriteByte_CODEC (adap, CODEC_AIFB, CODEC_AIFB_I2S | CODEC_AIFB_32))
++ goto nodev;
++
++ // HP outputs AC coupled
++ if (WriteByte_CODEC (adap, CODEC_HS, CODEC_HS_COUPLED | CODEC_HS_ADIFF))
++ goto nodev;
++
++ // ADC PGA not muted, maximum gain
++ if (WriteByte_CODEC (adap, CODEC_LADC_PGA, CODEC_ADC_PGA_G(0x3C))) // 59 dB
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_RADC_PGA, CODEC_ADC_PGA_G(0x3C))) // 59 dB
++ goto nodev;
++
++ // M3R -> [LR]PGA -6 dB gain, M3L muted
++ if (WriteByte_CODEC (adap, CODEC_M3_LPGA, CODEC_M3_PGA_R(0x04) | CODEC_M3_PGA_LOFF))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_M3_RPGA, CODEC_M3_PGA_R(0x04) | CODEC_M3_PGA_LOFF))
++ goto nodev;
++
++ // L1 -> [LR]PGA gain = -6 dB
++ // selectively activate ADC
++ if (audio->active) {
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, CODEC_L_PGA(0x04) | CODEC_LX_PGA_PU))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, CODEC_L_PGA(0x04) | CODEC_LX_PGA_PU))
++ goto nodev;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, CODEC_L_PGA(0x0F)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, CODEC_L_PGA(0x0F)))
++ goto nodev;
++ }
++
++ // L2 -> [LR]PGA gain = -6 dB
++ if (WriteByte_CODEC (adap, CODEC_L2L_LPGA, CODEC_L_PGA(0x04)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_L2R_RPGA, CODEC_L_PGA(0x04)))
++ goto nodev;
++
++ // MIC Bias = 2V
++ if (WriteByte_CODEC (adap, CODEC_MIC_BIAS, CODEC_MIC_BIAS_2V))
++ goto nodev;
++
++ // {LR]AGC A
++ if (WriteByte_CODEC (adap, CODEC_MIC_LAGC_A, CODEC_MIC_AGC_EN))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_MIC_LAGC_A, CODEC_MIC_AGC_EN))
++ goto nodev;
++
++ // {LR]AGC B
++ if (WriteByte_CODEC (adap, CODEC_MIC_LAGC_B, CODEC_MIC_AGC_MG(0x40))) // 30 dB, 0xEC=59 dB
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_MIC_RAGC_B, CODEC_MIC_AGC_MG(0x40))) // 30 dB, 0xEC=59 dB
++ goto nodev;
++
++ // DAC powered up
++ if (WriteByte_CODEC (adap, CODEC_DAC_PWR,
++ CODEC_DAC_PWR_L_EN | CODEC_DAC_PWR_R_EN | CODEC_DAC_PWR_HP_ISE))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DAC_HPWR, CODEC_DAC_HPWR_HPL_DIFF))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DAC_HPOS, CODEC_DAC_HPOS_SS_DIS))
++ goto nodev;
++
++ // DAC volume = max
++ if (WriteByte_CODEC (adap, CODEC_DAC_LVOL, CODEC_DAC_VOL(0x0)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DAC_RVOL, CODEC_DAC_VOL(0x0)))
++ goto nodev;
++
++ // MIC3->speaker
++ if(fcc_test)
++ if (WriteByte_CODEC (adap, CODEC_PGAR_HPLCOM, 0x80))
++ goto nodev;
++
++ // output switching volume = max
++ if (WriteByte_CODEC (adap, CODEC_DACL1_HPL, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DACL1_HPLCOM, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++
++ if (WriteByte_CODEC (adap, CODEC_DACR1_HPR, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DACR1_HPRCOM, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++
++ if (WriteByte_CODEC (adap, CODEC_DACL1_LLOPM, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_DACR1_RLOPM, CODEC_HP_EN | CODEC_HP_VOL(0x0)))
++ goto nodev;
++
++ // output levels = max
++ if (WriteByte_CODEC (adap, CODEC_HPLOUT,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_HPLCOM,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_HPROUT,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_HPRCOM,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_LLOPM,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_RLOPM,
++ CODEC_HPX_LC(0x09) | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ goto nodev;
++
++ // clocking
++ if (WriteByte_CODEC (adap, CODEC_CLK, CODEC_CLK_CLKDIV))
++ goto nodev;
++ if (WriteByte_CODEC (adap, CODEC_CLKGEN, CODEC_CLKGEN_C_M))
++ goto nodev;
++ return (0);
++
++nodev:
++ WriteByte_CODEC (adap, CODEC_L1L_LPGA, 0x38);
++ WriteByte_CODEC (adap, CODEC_L1R_RPGA, 0x38);
++ return -ENODEV;
++}
++
++/*
++ * This function initializes the driver in terms of BMI and
++ * CODEC functionality.
++ *
++ * @return 0 on success, >0 otherwise.
++ */
++static int mxc_alsa_audio_probe (struct bmi_device *bdev)
++{
++ int rc = 0;
++ struct bmi_audio *audio;
++ struct i2c_adapter *adap;
++ struct cdev *cdev;
++ struct class *bmi_class;
++ int slot;
++ dev_t dev_id;
++ int ssi;
++ unsigned char iox_data[1];
++
++ // bmi set-up
++ slot = bmi_device_get_slot (bdev);
++ adap = bmi_device_get_i2c_adapter (bdev);
++ audio = &bmi_audio[slot];
++
++ audio->bdev = 0;
++
++ // Create 1 minor device
++ cdev = &audio->cdev;
++ cdev_init (cdev, &cntl_fops);
++
++ dev_id = MKDEV(major, slot);
++ rc = cdev_add (cdev, dev_id, 1);
++ if (rc)
++ return rc;
++
++ // Create class device
++ bmi_class = bmi_get_bmi_class ();
++ audio->class_dev = device_create (bmi_class, NULL, MKDEV(major, slot), audio, "bmi_audio_ctrl_m%i", slot+1);
++
++ if (IS_ERR(audio->class_dev)) {
++ printk (KERN_ERR "Unable to create class_device for bmi_audio_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(audio->class_dev));
++ cdev_del (&audio->cdev);
++ audio->class_dev = NULL;
++ return -ENODEV;
++ }
++
++ // bind driver and bmi_device
++ audio->bdev = bdev;
++
++ // check for opposite side already active
++ switch (slot) {
++ case 0:
++ ssi = 0;
++ if (bmi_audio[2].active == 0) {
++ mxc_audio[0]->card->dev = &bdev->dev;
++ audio->active = 1;
++ }
++ break;
++ case 1:
++ ssi = 1;
++ if (bmi_audio[3].active == 0) {
++ mxc_audio[1]->card->dev = &bdev->dev;
++ audio->active = 1;
++ }
++ break;
++ case 2:
++ ssi = 0;
++ if (bmi_audio[0].active == 0) {
++ mxc_audio[0]->card->dev = &bdev->dev;
++ audio->active = 1;
++ }
++ break;
++ case 3:
++ ssi = 1;
++ if (bmi_audio[1].active == 0) {
++ mxc_audio[1]->card->dev = &bdev->dev;
++ audio->active = 1;
++ }
++ break;
++ }
++
++ bmi_device_set_drvdata (bdev, &bmi_audio[slot]);
++
++ // Initialize GPIOs (turn LED's on )
++ // bmi_slot_gpio_configure_as_output (int slot, int gpio, int data)
++ bmi_slot_gpio_configure_as_output (slot, GPIO_RED, BMI_GPIO_OFF); // Red LED=ON
++ bmi_slot_gpio_configure_as_output (slot, GPIO_GREEN, BMI_GPIO_OFF); // Green LED=ON
++ bmi_slot_gpio_configure_as_output (slot, GPIO_RESET, BMI_GPIO_OFF); // Assert RST = 0;
++ bmi_slot_gpio_configure_as_input (slot, GPIO_SPARE); // unused
++
++ mdelay (200);
++
++ // turn LED's off
++ bmi_slot_gpio_write_bit (slot, GPIO_RED, BMI_GPIO_ON); // Red LED=OFF
++ bmi_slot_gpio_write_bit (slot, GPIO_GREEN, BMI_GPIO_ON); // Green LED=OFF
++
++ // release reset
++ bmi_slot_gpio_write_bit (slot, GPIO_RESET, BMI_GPIO_ON); // Reset = 1
++
++ // configure IOX
++ if (WriteByte_IOX (adap, IOX_OUTPUT_REG, 0x01))
++ goto nodev;
++
++ if (output_ints) {
++ if (WriteByte_IOX (adap, IOX_CONTROL, 0xFC)) // IOX[1:0]=OUT, IOX[7:2]=IN
++ goto nodev;
++ } else {
++ if (WriteByte_IOX (adap, IOX_CONTROL, 0x6C)) // IOX[7,4,1:0]=OUT, IOX[6:5,3:2]=IN
++ goto nodev;
++ }
++
++ if (ReadByte_IOX (adap, IOX_INPUT_REG, iox_data)) // clear interrupts
++ goto nodev;
++
++ printk (KERN_INFO "bmi_audio.c: probe(%d) IOX = 0x%x\n", slot, *iox_data & 0xFF);
++
++#ifdef CODEC // CODEC
++ // configure codec
++ if (configure_CODEC(adap, audio))
++ goto nodev;
++#endif // CODEC
++
++ // set up input interrupt
++ audio->irq = bmi_device_get_status_irq (bdev);
++ snprintf (audio->int_name, sizeof (audio->int_name), "bmi_audio_stat_m%d", slot + 1);
++ if (request_irq (audio->irq, &module_irq_handler, 0, audio->int_name, &bmi_audio[slot])) {
++ printk (KERN_ERR "bmi_audio.c: Can't allocate irq %d or find audio in slot %d\n",
++ audio->irq, slot + 1);
++ device_destroy (bmi_class, MKDEV(major, slot));
++ cdev_del (&audio->cdev);
++ audio->class_dev = NULL;
++ return -EBUSY;
++ }
++
++ // power stablization delay
++ mdelay (500);
++ return 0;
++
++nodev:
++ device_destroy (bmi_class, MKDEV(major, slot));
++ cdev_del (&audio->cdev);
++ audio->class_dev = NULL;
++ return -ENODEV;
++}
++
++void mxc_alsa_audio_remove (struct bmi_device *bdev)
++{
++ struct bmi_audio *audio = (struct bmi_audio *) (bmi_device_get_drvdata (bdev));
++ int slot = bmi_device_get_slot (bdev);
++ struct class *bmi_class;
++
++ // release sound card srtucture
++ if (bmi_audio[slot].active && ((slot == 0) || (slot == 2)))
++ mxc_audio[0]->card->dev = NULL;
++ else if (bmi_audio[slot]. active && ((slot == 1) || (slot == 3)))
++ mxc_audio[1]->card->dev = NULL;
++
++ // remove input interrupt scheduled work
++ free_irq (bmi_device_get_status_irq (bdev), &bmi_audio[slot]);
++ switch(slot) {
++ case 0:
++ cancel_delayed_work(&bmiaudio_work0);
++ break;
++ case 1:
++ cancel_delayed_work(&bmiaudio_work1);
++ break;
++ case 2:
++ cancel_delayed_work(&bmiaudio_work2);
++ break;
++ case 3:
++ cancel_delayed_work(&bmiaudio_work3);
++ break;
++ }
++
++
++ // deconfigure GPIO
++ bmi_slot_gpio_configure_all_as_inputs (slot);
++
++ // remove class device
++ bmi_class = bmi_get_bmi_class ();
++ device_destroy (bmi_class, MKDEV(major, slot));
++
++ // clean slot structure
++ cdev_del (&audio->cdev);
++ audio->class_dev = NULL;
++ audio->bdev = NULL;
++ audio->active = 0;
++
++ // de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++
++ return;
++}
++
++// BMI device ID table
++static struct bmi_device_id bmi_audio_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_AUDIO,
++ .revision = BMI_ANY,
++ },
++ { 0, }, // terminate list
++};
++MODULE_DEVICE_TABLE(bmi, bmi_audio_tbl);
++
++static struct bmi_driver bmi_audio_driver = {
++ .name = "bmi_audio",
++ .id_table = bmi_audio_tbl,
++ .probe = mxc_alsa_audio_probe,
++ .remove = mxc_alsa_audio_remove,
++#if 0 //pjg - POWER_MANAGEMENT
++#ifdef CONFIG_PM
++ .suspend = snd_mxc_audio_suspend,
++ .resume = snd_mxc_audio_resume,
++#endif
++#endif //pjg - POWER_MANAGEMENT
++ .driver = {
++ .name = "pim_ALSA",
++ },
++};
++
++// mxc-alsa-mixer.c
++
++/*
++ * These are the functions implemented in the ALSA PCM driver that
++ * are used for mixer operations
++ *
++ */
++
++ //
++ // DAC Volume control
++ //
++ // PIM_AUDIO13
++static int bmi_pb_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 127 - volume;
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_DAC_LVOL, CODEC_DAC_VOL(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_DAC_RVOL, CODEC_DAC_VOL(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].master_volume_out = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_pb_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 127;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_pb_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ char val[1];
++
++ *val = 0x0;
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (ReadByte_CODEC (adap, CODEC_DAC_LVOL, val))
++ return -ENODEV;
++ } else {
++ *val = 0;
++ }
++#endif // CODEC
++
++ uvalue->value.integer.value[0] = 127 - ((int) *val);
++
++#ifdef CODEC
++ if (adap)
++ return 0;
++ else
++ return -1;
++#endif // CODEC
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_pb_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Master Playback Volume",
++ .index = 0x00,
++ .info = bmi_pb_volume_info0,
++ .get = bmi_pb_volume_get0,
++ .put = bmi_pb_volume_put0,
++ .private_value = 0xffab1,
++};
++
++// PIM_AUDIO24
++static int bmi_pb_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 127 - volume;
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_DAC_LVOL, CODEC_DAC_VOL(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_DAC_RVOL, CODEC_DAC_VOL(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].master_volume_out = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_pb_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 127;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_pb_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ char val[1];
++
++ *val = 0x0;
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (ReadByte_CODEC (adap, CODEC_DAC_LVOL, val))
++ return -ENODEV;
++ } else {
++ *val = 0;
++ }
++#endif // CODEC
++
++ uvalue->value.integer.value[0] = 127 - ((int) *val);
++
++#ifdef CODEC
++ if (adap)
++ return 0;
++ else
++ return -1;
++#endif // CODEC
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_pb_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Master Playback Volume",
++ .index = 0x00,
++ .info = bmi_pb_volume_info1,
++ .get = bmi_pb_volume_get1,
++ .put = bmi_pb_volume_put1,
++ .private_value = 0xffab1,
++};
++
++//
++// LI (L1) Volume control
++//
++// PIM_AUDIO13
++static int bmi_li_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, CODEC_L_PGA(volume) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, CODEC_L_PGA(volume) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_input[IP_LINEIN] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_li_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_li_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_input[IP_LINEIN];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_li_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Linein Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_li_volume_info0,
++ .get = bmi_li_volume_get0,
++ .put = bmi_li_volume_put0,
++ .private_value = 0xffab3,
++};
++
++// PIM_AUDIO24
++static int bmi_li_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1L_LPGA, CODEC_L_PGA(volume) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L1R_RPGA, CODEC_L_PGA(volume) | CODEC_LX_PGA_PU))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_input[IP_LINEIN] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_li_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_li_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_input[IP_LINEIN];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_li_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Linein Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_li_volume_info1,
++ .get = bmi_li_volume_get1,
++ .put = bmi_li_volume_put1,
++ .private_value = 0xffab3,
++};
++
++//
++// MIC (L2) Volume control
++//
++// PIM_AUDIO13
++static int bmi_mic_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L2L_LPGA, CODEC_L_PGA(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L2R_RPGA, CODEC_L_PGA(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_input[IP_MIC] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_mic_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_mic_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_input[IP_MIC];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_mic_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Mic Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_mic_volume_info0,
++ .get = bmi_mic_volume_get0,
++ .put = bmi_mic_volume_put0,
++ .private_value = 0xffab4,
++};
++
++// PIM_AUDIO24
++static int bmi_mic_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L2L_LPGA, CODEC_L_PGA(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_L2R_RPGA, CODEC_L_PGA(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_input[IP_MIC] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_mic_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_mic_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_input[IP_MIC];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_mic_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Mic Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_mic_volume_info1,
++ .get = bmi_mic_volume_get1,
++ .put = bmi_mic_volume_put1,
++ .private_value = 0xffab4,
++};
++
++//
++// EMIC (L3) Volume control
++//
++// PIM_AUDIO13
++static int bmi_emic_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_M3_LPGA, CODEC_M3_PGA_R(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_M3_RPGA, CODEC_M3_PGA_R(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_input[IP_EMIC] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_emic_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_emic_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_input[IP_EMIC];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_emic_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Emic Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_emic_volume_info0,
++ .get = bmi_emic_volume_get0,
++ .put = bmi_emic_volume_put0,
++ .private_value = 0xffab5,
++};
++
++// PIM_AUDIO24
++static int bmi_emic_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++ volume = 8 - volume;
++ if (volume == 0)
++ volume = 0xF; // mute
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_M3_LPGA, CODEC_M3_PGA_R(volume)))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_M3_RPGA, CODEC_M3_PGA_R(volume)))
++ return -ENODEV;
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_input[IP_EMIC] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_emic_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 8;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_emic_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_input[IP_EMIC];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_emic_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Emic Capture Volume/Mute",
++ .index = 0x00,
++ .info = bmi_emic_volume_info1,
++ .get = bmi_emic_volume_get1,
++ .put = bmi_emic_volume_put1,
++ .private_value = 0xffab5,
++};
++
++//
++// HEADPHONE (HP[LR]OUT) Volume control
++//
++// PIM_AUDIO13
++static int bmi_hp_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_HPLOUT, 0x0)) // mute
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPROUT, 0x0)) // mute
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_HPLOUT, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPROUT, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_output[OP_HEADPHONE] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_hp_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_hp_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_output[OP_HEADPHONE];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_hp_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Headphone Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_hp_volume_info0,
++ .get = bmi_hp_volume_get0,
++ .put = bmi_hp_volume_put0,
++ .private_value = 0xffab4,
++};
++
++ // PIM_AUDIO24
++static int bmi_hp_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_HPLOUT, 0x0)) // mute
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPROUT, 0x0)) // mute
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_HPLOUT, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPROUT, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_output[OP_HEADPHONE] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_hp_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_hp_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_output[OP_HEADPHONE];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_hp_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Headphone Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_hp_volume_info1,
++ .get = bmi_hp_volume_get1,
++ .put = bmi_hp_volume_put1,
++ .private_value = 0xffab4,
++};
++
++//
++// Speaker (HP[LR]COM) Volume control
++//
++// PIM_AUDIO13
++static int bmi_spkr_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_HPLCOM, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPRCOM, 0x0))
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_HPLCOM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPRCOM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_output[OP_SPEAKER] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_spkr_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_spkr_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_output[OP_SPEAKER];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_spkr_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Speaker Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_spkr_volume_info0,
++ .get = bmi_spkr_volume_get0,
++ .put = bmi_spkr_volume_put0,
++ .private_value = 0xffab5,
++};
++
++// PIM_AUDIO24
++static int bmi_spkr_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_HPLCOM, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPRCOM, 0x0))
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_HPLCOM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_HPRCOM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_output[OP_SPEAKER] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_spkr_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_spkr_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_output[OP_SPEAKER];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_spkr_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Speaker Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_spkr_volume_info1,
++ .get = bmi_spkr_volume_get1,
++ .put = bmi_spkr_volume_put1,
++ .private_value = 0xffab5,
++};
++
++//
++// Line out ([LR]LOP) Volume control
++//
++// PIM_AUDIO13
++static int bmi_lo_volume_put0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[0].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[0].bdev);
++ } else if (bmi_audio[2].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[2].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_LLOPM, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_RLOPM, 0x0))
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_LLOPM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_RLOPM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ audio_mixer_control[0].vol_for_output[OP_LINEOUT] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++static int bmi_lo_volume_info0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_lo_volume_get0 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[0].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[0].vol_for_output[OP_LINEOUT];
++
++ up (&audio_mixer_control[0].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_lo_vol0 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Lineout Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_lo_volume_info0,
++ .get = bmi_lo_volume_get0,
++ .put = bmi_lo_volume_put0,
++ .private_value = 0xffab6,
++};
++
++// PIM_AUDIO24
++static int bmi_lo_volume_put1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ struct i2c_adapter *adap = 0;
++ int volume;
++
++ // calculate register value
++ volume = uvalue->value.integer.value[0];
++
++ // get I2C dapter
++ if (bmi_audio[1].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[1].bdev);
++ } else if (bmi_audio[3].active) {
++ adap = bmi_device_get_i2c_adapter (bmi_audio[3].bdev);
++ }
++
++#ifdef CODEC
++ // set volume
++ if (adap) {
++ // write page register
++ if (WriteByte_CODEC (adap, 0x0, 0x0))
++ return -ENODEV;
++ if (volume == 0) {
++ if (WriteByte_CODEC (adap, CODEC_LLOPM, 0x0))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_RLOPM, 0x0))
++ return -ENODEV;
++ } else {
++ if (WriteByte_CODEC (adap, CODEC_LLOPM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ if (WriteByte_CODEC (adap, CODEC_RLOPM, CODEC_HPX_LC(volume)
++ | CODEC_HPX_EN | CODEC_HPX_PD | CODEC_HPX_PC))
++ return -ENODEV;
++ }
++ } else {
++ return -1;
++ }
++#endif // CODEC
++
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ audio_mixer_control[1].vol_for_output[OP_LINEOUT] = uvalue->value.integer.value[0];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++static int bmi_lo_volume_info1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 9;
++ uinfo->value.integer.step = 1;
++ return 0;
++}
++
++static int bmi_lo_volume_get1 (struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *uvalue)
++{
++ if (down_interruptible (&audio_mixer_control[1].sem))
++ return -EINTR;
++
++ uvalue->value.integer.value[0] = audio_mixer_control[1].vol_for_output[OP_LINEOUT];
++
++ up (&audio_mixer_control[1].sem);
++
++ return 0;
++}
++
++struct snd_kcontrol_new bmi_control_lo_vol1 __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Lineout Playback Volume/Mute",
++ .index = 0x00,
++ .info = bmi_lo_volume_info1,
++ .get = bmi_lo_volume_get1,
++ .put = bmi_lo_volume_put1,
++ .private_value = 0xffab6,
++};
++
++/*
++ * This function registers the control components of ALSA Mixer
++ * It is called by ALSA PCM init.
++ *
++ * @param card pointer to the ALSA sound card structure.
++ * @param device SSI interface
++ *
++ * @return 0 on success, -ve otherwise.
++ */
++int bug_alsa_create_ctl (struct snd_card *card, void *p_value, int device)
++{
++ int rc = 0;
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_pb_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_pb_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_li_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_li_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_mic_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_mic_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_emic_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_emic_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_hp_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_hp_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_spkr_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_spkr_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ if (device == 0) {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_lo_vol0, p_value))) < 0)
++ return rc;
++ } else {
++ if ((rc =
++ snd_ctl_add (card, snd_ctl_new1 (&bmi_control_lo_vol1, p_value))) < 0)
++ return rc;
++ }
++
++ return 0;
++}
++
++/**************************************************************************
++ * Module initialization and termination functions.
++ *
++ * Note that if this code is compiled into the kernel, then the
++ * module_init() function will be called within the device_initcall()
++ * group.
++ **************************************************************************
++ */
++
++/*
++ * @name Audio Driver Loading/Unloading Functions
++ * These non-exported internal functions are used to support the audio
++ * device driver initialization and de-initialization operations.
++ */
++
++/*
++ * @brief This is the audio device driver initialization function.
++ *
++ * This function is called by the kernel when this device driver is first
++ * loaded.
++ */
++
++char const input_name0[MAX_STRG] = "bmi_audio_status_m1";
++char const input_name1[MAX_STRG] = "bmi_audio_status_m2";
++char const input_name2[MAX_STRG] = "bmi_audio_status_m3";
++char const input_name3[MAX_STRG] = "bmi_audio_status_m4";
++
++static int __init bmi_audio_init (void)
++{
++ int rc = 0;
++ dev_t dev_id;
++ int idn;
++ int iidn;
++ struct snd_card *card;
++ struct snd_card *card1;
++
++ printk (KERN_INFO "BMI Audio driver loading...\n");
++
++ // alloc char driver with 4 minor numbers
++ rc = alloc_chrdev_region (&dev_id, 0, 4, "BMI AUDIO Driver");
++ if (rc) {
++ printk (KERN_ERR "bmi_audio_init: Can't allocate chrdev region\n");
++ return -ENODEV;
++ }
++ major = MAJOR(dev_id);
++
++ // Allocate and Register input devices - bmi_audio_status_m[1234]
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++) {
++ bmi_audio[idn].input_dev = input_allocate_device();
++ if (!bmi_audio[idn].input_dev) {
++ for (iidn = BMI_AUDIO_M1; iidn < idn; iidn++)
++ input_unregister_device (bmi_audio[iidn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ printk (KERN_ERR "bmi_audio_init: Can't allocate input_dev[%d]\n", idn);
++ return -ENOMEM;
++ }
++
++ // set up input device
++ switch (idn) {
++ case BMI_AUDIO_M1:
++ bmi_audio[idn].input_dev->name = input_name0;
++ bmi_audio[idn].input_dev->phys = input_name0;
++ break;
++ case BMI_AUDIO_M2:
++ bmi_audio[idn].input_dev->name = input_name1;
++ bmi_audio[idn].input_dev->phys = input_name1;
++ break;
++ case BMI_AUDIO_M3:
++ bmi_audio[idn].input_dev->name = input_name2;
++ bmi_audio[idn].input_dev->phys = input_name2;
++ break;
++ case BMI_AUDIO_M4:
++ bmi_audio[idn].input_dev->name = input_name3;
++ bmi_audio[idn].input_dev->phys = input_name3;
++ break;
++ }
++ bmi_audio[idn].input_dev->id.bustype = BUS_BMI;
++ //bmi_audio[idn].input_dev->private = &bmi_audio[idn];
++ bmi_audio[idn].input_dev->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
++ bmi_audio[idn].input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
++
++ // register input device
++ if (input_register_device (bmi_audio[idn].input_dev)) {
++ printk (KERN_ERR "bmi_audio_init() - input_register_device failed.\n");
++ for (iidn = BMI_AUDIO_M1; iidn < idn; iidn++)
++ input_unregister_device (bmi_audio[iidn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++ }
++
++ // clear bmi devices and active bits
++ bmi_audio[0].bdev = NULL;
++ bmi_audio[1].bdev = NULL;
++ bmi_audio[2].bdev = NULL;
++ bmi_audio[3].bdev = NULL;
++ bmi_audio[0].active = 0;
++ bmi_audio[1].active = 0;
++ bmi_audio[2].active = 0;
++ bmi_audio[3].active = 0;
++
++ // allocate private structure
++ mxc_audio[0] = kcalloc (1, sizeof (mxc_bmi_audio_t), GFP_KERNEL);
++ if (mxc_audio[0] == NULL) {
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ // allocate private structure
++ mxc_audio[1] = kcalloc (1, sizeof (mxc_bmi_audio_t), GFP_KERNEL);
++ if (mxc_audio[1] == NULL) {
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ // register the soundcards
++ // modules 1 and 3
++ card = snd_card_new (1, id13, THIS_MODULE, sizeof (mxc_bmi_audio_t));
++ if (card == NULL) {
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ card->private_data = (void *) mxc_audio[0];
++ card->private_free = snd_mxc_audio_free;
++
++ // register pcm
++ mxc_audio[0]->card = card;
++ if ((rc = snd_card_mxc_audio_pcm (mxc_audio[0], 0)) < 0) {
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ // register mixer
++ if (0 == bug_alsa_create_ctl (card, (void *) &audio_mixer_control[0], 0))
++ printk (KERN_INFO "Control ALSA component registered\n");
++
++ spin_lock_init (&(mxc_audio[0]->s[0].dma_lock));
++ spin_lock_init (&(mxc_audio[0]->s[1].dma_lock));
++
++ strcpy (card->driver, "PIM_AUDIO13");
++ strcpy (card->shortname, "PIM13-audio");
++ sprintf (card->longname, "PIM13 Freescale MX31");
++
++ // register sound card
++ if ((rc = snd_card_register (card)) == 0) {
++ PRINTK(KERN_INFO "MXC PIM13 audio support initialized\n");
++ } else {
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ // modules 2 and 4
++ card1 = snd_card_new (2, id24, THIS_MODULE, sizeof (mxc_bmi_audio_t));
++ if (card1 == NULL) {
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ card1->private_data = (void *) mxc_audio[1];
++ card1->private_free = snd_mxc_audio_free;
++
++ // register pcm
++ mxc_audio[1]->card = card1;
++ if ((rc = snd_card_mxc_audio_pcm (mxc_audio[1], 1)) < 0) {
++ snd_card_free (card1);
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return -ENODEV;
++ }
++
++ // register mixer
++ if (0 == bug_alsa_create_ctl (card1, (void *) &audio_mixer_control[1], 1))
++ printk (KERN_INFO "Control ALSA component registered\n");
++
++ spin_lock_init (&(mxc_audio[1]->s[0].dma_lock));
++ spin_lock_init (&(mxc_audio[1]->s[1].dma_lock));
++
++ strcpy (card1->driver, "PIM_AUDIO24");
++ strcpy (card1->shortname, "PIM24-audio");
++ sprintf (card1->longname, "PIM24 Freescale MX31");
++
++ // register sound card
++ if ((rc = snd_card_register (card1)) == 0) {
++ PRINTK(KERN_INFO "MXC PIM24 audio support initialized\n");
++ } else {
++ snd_card_free (card1);
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ }
++
++ // register with BMI
++ rc = bmi_register_driver (&bmi_audio_driver);
++ if (rc) {
++ printk (KERN_ERR "bmi_audio.c: Can't register bmi_audio_driver\n");
++ snd_card_free (card1);
++ snd_card_free (card);
++ kfree (mxc_audio[1]);
++ kfree (mxc_audio[0]);
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++ unregister_chrdev_region (dev_id, 4);
++ return rc;
++ }
++
++ // turn on I2S transceiver
++ bmi_activate_audio_ports();
++
++ //configure DAM and SSI
++ configure_dam_bmi_master (0);
++ configure_dam_bmi_master (1);
++ configure_ssi_rx (0);
++ configure_ssi_rx (1);
++ configure_ssi_tx (0);
++ configure_ssi_tx (1);
++
++ printk (KERN_INFO "bmi_audio.c: BMI_AUDIO Driver v%s \n", BMIAUDIO_VERSION);
++ if(fcc_test)
++ printk (KERN_INFO "bmi_audio.c: FCC Test mode enabled\n");
++ if(output_ints)
++ printk (KERN_INFO "bmi_audio.c: Output Jack Interrupts enabled\n");
++ return 0;
++}
++
++/*
++ * @brief This is the audio device driver de-initialization function.
++ *
++ * This function is called by the kernel when this device driver is about
++ * to be unloaded.
++ */
++static void __exit bmi_audio_exit (void)
++{
++ dev_t dev_id;
++ int idn;
++
++ printk (KERN_INFO "BMI Audio driver unloading...\n");
++
++ // delete scheduled work
++ flush_scheduled_work ();
++
++ // remove bmi functionality
++ bmi_unregister_driver (&bmi_audio_driver);
++
++ // free sound cards
++ snd_card_free (mxc_audio[0]->card);
++ snd_card_free (mxc_audio[1]->card);
++
++ // free data structures
++ kfree (mxc_audio[0]);
++ kfree (mxc_audio[1]);
++
++ // remove input devices
++ for (idn = BMI_AUDIO_M1; idn < BMI_AUDIO_PIM_NUM; idn++)
++ input_unregister_device (bmi_audio[idn].input_dev);
++
++ // remove control cdev
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region (dev_id, 4);
++
++ // turn off I2S transceiver
++ bmi_inactivate_audio_ports();
++
++ printk (KERN_INFO "BMI Audio driver unloaded.\n");
++ return;
++}
++
++/*
++ * Module entry points and description information.
++ */
++
++module_init (bmi_audio_init);
++module_exit (bmi_audio_exit);
++
++module_param(fcc_test, ushort, S_IRUGO);
++MODULE_PARM_DESC(fcc_test, "FCC Test code enable");
++
++module_param(output_ints, ushort, S_IRUGO);
++MODULE_PARM_DESC(fcc_test, "Output Jack Interrupts enable");
++
++MODULE_DESCRIPTION("BMI driver for ALSA");
++MODULE_AUTHOR("EnCADIS Design, Inc. <p.giacomini@encadis.com>");
++MODULE_LICENSE("GPL");
++MODULE_SUPPORTED_DEVICE("PIM_AUDIO13");
++MODULE_SUPPORTED_DEVICE("PIM_AUDIO24");
++MODULE_SUPPORTED_DEVICE("bmi_audio_ctrl_m[1234]");
++MODULE_SUPPORTED_DEVICE("bmi_audio_status_m[1234]");
++
+--- /dev/null
++++ git/drivers/bmi/pims/vonhippel/Makefile
+@@ -0,0 +1,6 @@
++#
++# BMI PIMS
++#
++
++obj-$(CONFIG_BMI_VH) += bmi_vh.o
++
+--- /dev/null
++++ git/drivers/bmi/pims/vonhippel/bmi_vh.c
+@@ -0,0 +1,942 @@
++/*
++ * bmi_vh.c
++ *
++ * BMI von Hippel device driver basic functionality
++ *
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <mach/hardware.h>
++
++#include <linux/i2c.h>
++
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/bmi/bmi_vh.h>
++
++#define BMIVH_VERSION "1.0"
++#define RDAC_3_3V (0xAC) // 16.5K = 3.3V
++
++/*
++ * Global variables
++ */
++
++static struct i2c_board_info iox_info = {
++ I2C_BOARD_INFO("VH_IOX", BMI_IOX_I2C_ADDRESS),
++};
++
++static struct i2c_board_info rdac_info = {
++ I2C_BOARD_INFO("VH_RDAC", VH_RDAC_I2C_ADDRESS),
++};
++
++static struct i2c_board_info adc_info = {
++ I2C_BOARD_INFO("VH_ADC", VH_ADC_I2C_ADDRESS),
++};
++
++static struct i2c_board_info dac_info = {
++ I2C_BOARD_INFO("VH_DAC", VH_DAC_I2C_ADDRESS),
++};
++
++
++static ushort factory_test = 0;
++static ushort fcc_test = 0;
++static struct timer_list fcc_timer;
++static int fcc_state = 0x3;
++
++// private device structure
++struct bmi_vh
++{
++ struct bmi_device *bdev; // BMI device
++ struct cdev cdev; // control device
++ struct device *class_dev; // control class device
++ int open_flag; // single open flag
++ char int_name[20]; // interrupt name
++ struct i2c_client *iox;
++ struct i2c_client *rdac;
++ struct i2c_client *dac;
++ struct i2c_client *adc;
++ struct spi_device *spi; // SPI device
++ struct spi_board_info vh_spi_info;
++ char rbuf[BUF_MAX_SIZE]; // SPI read buffer
++ char wbuf[BUF_MAX_SIZE]; // SPI write buffer
++};
++
++static struct bmi_vh bmi_vh[4]; // per slot device structure
++static int major; // control device major
++
++/*
++ * BMI set up
++ */
++
++// BMI device ID table
++static struct bmi_device_id bmi_vh_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_VON_HIPPEL,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++MODULE_DEVICE_TABLE(bmi, bmi_vh_tbl);
++
++int bmi_vh_probe (struct bmi_device *bdev);
++void bmi_vh_remove (struct bmi_device *bdev);
++
++// BMI driver structure
++static struct bmi_driver bmi_vh_driver =
++{
++ .name = "bmi_vh",
++ .id_table = bmi_vh_tbl,
++ .probe = bmi_vh_probe,
++ .remove = bmi_vh_remove,
++};
++
++/*
++ * I2C set up
++ */
++
++// IOX
++// read byte from I2C IO expander
++static int ReadByte_IOX (struct i2c_client *client, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++
++ ret = i2c_master_send(client, &offset, 1);
++ if (ret == 1)
++ ret = i2c_master_recv(client, data, 1);
++ if (ret < 0)
++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++// write byte to I2C IO expander
++static int WriteByte_IOX (struct i2c_client *client, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ unsigned char msg[2];
++
++ msg[0] = offset;
++ msg[1] = data;
++ ret = i2c_master_send(client, msg, sizeof(msg));
++
++ if (ret < 0)
++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed...%d\n",ret);
++
++ return ret;
++}
++
++// RDAC
++// read byte from I2C LDO RDAC
++static int ReadByte_RDAC (struct i2c_client *client, unsigned char command, unsigned char *data)
++{
++ int ret = 0;
++
++ ret = i2c_master_send(client, &command, 1);
++
++ if (ret < 0)
++ {
++ printk (KERN_ERR "ReadByte_RDAC() - i2c_master_send() failed...%d\n",ret);
++ return ret;
++ }
++ ret = i2c_master_recv(client, data, 1);
++ if (ret < 0)
++ printk (KERN_ERR "ReadByte_RDAC() - i2c_master_recv() failed...%d\n",ret);
++ return ret;
++}
++
++// write byte to I2C LDO RDAC
++static int WriteByte_RDAC (struct i2c_client *client, unsigned char command,
++ unsigned char data, int send_data)
++{
++ int ret = 0;
++
++ unsigned char msg[2];
++
++ msg[0] = command;
++ msg[1] = data;
++
++ if (send_data)
++ ret = i2c_master_send(client, msg, 2);
++ else
++ ret = i2c_master_send(client, &msg[0], 1);
++ if (ret < 0)
++ printk (KERN_ERR "WriteByte_RDAC() - i2c_transfer() failed...%d\n",ret);
++
++ return ret;
++}
++
++// ADC
++// read data from I2C ADC
++static int ReadByte_ADC (struct i2c_client *client, unsigned char *data)
++{
++ int ret = 0;
++
++ ret = i2c_master_recv(client, data, 3);
++
++ if (ret < 0)
++ printk (KERN_ERR "ReadByte_ADC() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++// write command to I2C ADC
++static int WriteByte_ADC (struct i2c_client *client, unsigned char w1, unsigned char w2)
++{
++ int ret = 0;
++ unsigned char msg[2];
++
++ msg[0] = w1;
++ msg[1] = w2;
++ ret = i2c_master_send(client, msg, sizeof(msg));
++
++ if (ret < 0)
++ printk (KERN_ERR "WriteByte_ADC() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++// DAC
++// read data from I2C DAC
++static int ReadByte_DAC (struct i2c_client *client, unsigned char command, unsigned char *data)
++{
++ int ret = 0;
++
++ ret = i2c_master_send(client, &command, 1);
++ if (ret == 1)
++ ret = i2c_master_recv(client, data, 2);
++
++ if (ret < 0)
++ printk (KERN_ERR "ReadByte_DAC() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++// write command to I2C DAC
++static int WriteByte_DAC (struct i2c_client *client, unsigned char w1, unsigned char w2, int send_w2)
++{
++ int ret = 0;
++ unsigned char msg[2];
++
++ msg[0] = w1;
++ msg[1] = w2;
++ if (send_w2)
++ ret = i2c_master_send(client, msg, sizeof(msg));
++ else
++ ret = i2c_master_send(client, &msg[0], 1);
++
++ if (ret < 0)
++ printk (KERN_ERR "WriteByte_DAC() - i2c_transfer() failed...%d\n",ret);
++ return ret;
++}
++
++
++/*
++ * control device operations
++ */
++
++// open
++int cntl_open(struct inode *inode, struct file *file)
++{
++ struct bmi_vh *vh;
++
++ vh = container_of (inode->i_cdev, struct bmi_vh, cdev);
++
++ // Enforce single-open behavior
++
++ if (vh->open_flag) {
++ return -EBUSY;
++ }
++ vh->open_flag = 1;
++
++ // Save vh_dev pointer for later.
++
++ file->private_data = vh;
++ return 0;
++
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *file)
++{
++ struct bmi_vh *vh;
++
++ vh = (struct bmi_vh *)(file->private_data);
++ vh->open_flag = 0;
++ return 0;
++}
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ unsigned char iox_data;
++ unsigned char rdac_data;
++ // unsigned char buf[4];
++ int ret = 0;
++
++ struct bmi_vh *vh;
++ int slot;
++
++ vh = (struct bmi_vh *)(file->private_data);
++
++ // error if vh not present
++ if(vh->bdev == 0)
++ return -ENODEV;
++
++ slot = vh->bdev->slot->slotnum;
++ adap = vh->bdev->slot->adap;
++
++ // ioctl's
++ switch (cmd) {
++
++ case BMI_VH_RLEDOFF:
++ bmi_slot_gpio_set (slot, ~VH_GPIO_RED_LED); // Red LED=OFF
++ break;
++
++ case BMI_VH_RLEDON:
++ bmi_slot_gpio_set (slot, VH_GPIO_RED_LED); // Red LED=ON
++ break;
++
++ case BMI_VH_GLEDOFF:
++ bmi_slot_gpio_set (slot, ~VH_GPIO_GREEN_LED); // Green LED=OFF
++ break;
++
++ case BMI_VH_GLEDON:
++ bmi_slot_gpio_set (slot, VH_GPIO_GREEN_LED); // Green LED=ON
++ break;
++
++ case BMI_VH_GETSTAT:
++ {
++ int read_data;
++
++ if (ReadByte_IOX (vh->iox, IOX_INPUT_REG, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data | (bmi_slot_gpio_get(slot) << 8);
++
++ if (put_user (read_data, (int __user *) arg))
++ return -EFAULT;
++ }
++ break;
++
++ case BMI_VH_MKGPIO_OUT:
++ if ((arg < VH_GPIO_0) || (arg > VH_GPIO_RED_LED))
++ return -EINVAL;
++ //bmi_set_module_gpio_dir (slot, arg, BMI_GPIO_OUT);
++ break;
++
++ case BMI_VH_MKGPIO_IN:
++ if ((arg < VH_GPIO_0) || (arg > VH_GPIO_RED_LED))
++ return -EINVAL;
++ //bmi_set_module_gpio_dir (slot, arg, BMI_GPIO_IN);
++ break;
++
++ case BMI_VH_SETGPIO:
++ if ((arg < VH_GPIO_0) || (arg > VH_GPIO_RED_LED))
++ return -EINVAL;
++ //bmi_set_module_gpio_data (slot, arg, 0x1);
++ break;
++
++ case BMI_VH_CLRGPIO:
++ if ((arg < VH_GPIO_0) || (arg > VH_GPIO_RED_LED))
++ return -EINVAL;
++ //bmi_set_module_gpio_data (slot, arg, 0x0);
++ break;
++
++ case BMI_VH_MKIOX_OUT:
++ if ((arg < VH_IOX_B0) || (arg > VH_IOX_B5))
++ return -EINVAL;
++ {
++ unsigned char read_data;
++
++ if (ReadByte_IOX (vh->iox, IOX_CONTROL, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data & ~(0x1 << arg);
++
++ if (WriteByte_IOX (vh->iox, IOX_CONTROL, read_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_VH_MKIOX_IN:
++ if ((arg < VH_IOX_B0) || (arg > VH_IOX_B5))
++ return -EINVAL;
++ {
++ unsigned char read_data;
++
++ if (ReadByte_IOX (vh->iox, IOX_CONTROL, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data & (0x1 << arg);
++
++ if (WriteByte_IOX (vh->iox, IOX_CONTROL, read_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_VH_SETIOX:
++ if ((arg < VH_IOX_B0) || (arg > VH_IOX_USB_VEN))
++ return -EINVAL;
++ {
++ unsigned char read_data;
++
++ if (ReadByte_IOX (vh->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data | (0x1 << arg);
++
++ if (WriteByte_IOX (vh->iox, IOX_OUTPUT_REG, read_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_VH_CLRIOX:
++ if ((arg < VH_IOX_B0) || (arg > VH_IOX_USB_VEN))
++ return -EINVAL;
++ {
++ unsigned char read_data;
++
++ if (ReadByte_IOX (vh->iox, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++
++ read_data = iox_data & ~(0x1 << arg);
++
++ if (WriteByte_IOX (vh->iox, IOX_OUTPUT_REG, read_data))
++ return -ENODEV;
++ }
++ break;
++
++ case BMI_VH_SETRDAC:
++ rdac_data = (unsigned char) (arg & 0xFF);
++
++ if (WriteByte_RDAC (vh->rdac, VH_RD_CMD_RDAC, rdac_data, 1))
++ return -ENODEV;
++
++ if (WriteByte_RDAC (vh->rdac, VH_RD_CMD_EE, rdac_data, 1))
++ return -ENODEV;
++
++ break;
++
++ case BMI_VH_RDRDAC:
++
++ if (ReadByte_RDAC (vh->rdac, VH_RD_CMD_RDAC, &rdac_data))
++ return -ENODEV;
++
++ if(copy_to_user((unsigned int *) arg, &rdac_data, sizeof(int)))
++ ret = -EFAULT;
++ else
++ ret = 0;
++
++ break;
++
++ case BMI_VH_ADCWR:
++ {
++ struct vh_adc_wr *adc_wr = NULL;
++
++ if ((adc_wr = kmalloc(sizeof(struct vh_adc_wr), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(adc_wr, (struct vh_adc_wr *)arg, sizeof(struct vh_adc_wr))) {
++ kfree (adc_wr);
++ return -EFAULT;
++ }
++ if (WriteByte_ADC (vh->adc, adc_wr->w1, adc_wr->w2)) {
++ kfree (adc_wr);
++ return -ENODEV;
++ }
++ kfree (adc_wr);
++ }
++ break;
++
++ case BMI_VH_ADCRD:
++ {
++ unsigned char adc_data[3];
++ unsigned int ret_data;
++
++ if (ReadByte_ADC(vh->adc, adc_data)) // read ADC conversion
++ return -ENODEV;
++
++ ret_data = (unsigned int) ((adc_data[0] << 16) | (adc_data[1] << 8) | adc_data[2]);
++ if(copy_to_user((unsigned int *) arg, &ret_data, sizeof(int)))
++ ret = -EFAULT;
++ else
++ ret = 0;
++ }
++
++ break;
++
++ case BMI_VH_DACWR:
++ {
++ struct vh_dac_wr *dac_wr = NULL;
++
++ if ((dac_wr = kmalloc(sizeof(struct vh_dac_wr), GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++ if (copy_from_user(dac_wr, (struct vh_dac_wr *)arg, sizeof(struct vh_dac_wr))) {
++ kfree (dac_wr);
++ return -EFAULT;
++ }
++ if (dac_wr->w1 == VH_DAC_W1_UALL) {
++ if (WriteByte_DAC (vh->dac, dac_wr->w1, dac_wr->w2, 0)) {
++ kfree (dac_wr);
++ return -ENODEV;
++ }
++ } else {
++ if (WriteByte_DAC (vh->dac, dac_wr->w1, dac_wr->w2, 1)) {
++ kfree (dac_wr);
++ return -ENODEV;
++ }
++ }
++ kfree (dac_wr);
++ }
++ break;
++
++ case BMI_VH_DACRD:
++ {
++ unsigned char dac_data[2];
++ unsigned int command;
++ unsigned int ret_data;
++
++ if (copy_from_user(&command, (unsigned int *)arg, sizeof(int))) {
++ return -EFAULT;
++ }
++
++ if (!((command == VH_DAC_W1_RDA) || (command == VH_DAC_W1_RDB))) {
++ return -EINVAL;
++ }
++
++ if (ReadByte_DAC(vh->dac, (unsigned char) command, dac_data)) { // read DAC value
++ return -ENODEV;
++ }
++
++ ret_data = (unsigned int) ((dac_data[0] << 8) | dac_data[1]);
++ if(copy_to_user((unsigned int *) arg, &ret_data, sizeof(int))) {
++ ret = -EFAULT;
++ } else {
++ ret = 0;
++ }
++ }
++
++ break;
++
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++// control file operations
++struct file_operations cntl_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++/*
++ * PIM functions
++ */
++
++// FCC test timer
++void ftimer(unsigned long arg)
++{
++ struct bmi_vh *bmi_vh = (struct bmi_vh *) arg;
++ int slot = bmi_vh->bdev->slot->slotnum;
++
++ /* bmi_set_module_gpio_data (slot, VH_GPIO_RED_LED, (fcc_state & 0x2) >> 1);
++ bmi_set_module_gpio_data (slot, VH_GPIO_GREEN_LED, fcc_state & 0x1);*/
++ fcc_state = (fcc_state + 1) % 4;
++ del_timer (&fcc_timer);
++ fcc_timer.expires = jiffies + (2 * HZ);
++ add_timer (&fcc_timer);
++}
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ /*if (!factory_test) {
++ printk (KERN_ERR "Von Hippel USB power error - slot ");
++ switch (irq) {
++ case M1_IRQ:
++ printk (KERN_ERR "1 - powering off\n");
++ bmi_slot_power_off (0);
++ break;
++ case M2_IRQ:
++ printk (KERN_ERR "2 - powering off\n");
++ bmi_slot_power_off (1);
++ break;
++ case M3_IRQ:
++ printk (KERN_ERR "3 - powering off\n");
++ bmi_slot_power_off (2);
++ break;
++ case M4_IRQ:
++ printk (KERN_ERR "3 - powering off\n");
++ bmi_slot_power_off (3);
++ break;
++ }
++ }
++ disable_irq(irq);*/
++ return IRQ_HANDLED;
++}
++
++/*
++ * BMI functions
++ */
++
++// probe - insert PIM
++int bmi_vh_probe(struct bmi_device *bdev)
++{
++ int err;
++ int slot;
++ struct bmi_vh *vh;
++ struct i2c_adapter *adap;
++ struct cdev *cdev;
++ struct class *bmi_class;
++ dev_t dev_id;
++ int irq;
++ unsigned char rdac_data[1];
++ unsigned char adc_data[3];
++ unsigned char dac_data[2];
++ unsigned long speed = 1000000;
++ unsigned char mode = SPI_MODE_2; // von Hippel chip select must be low active
++ unsigned char bits_per_word = 32;
++ unsigned char iox_data;
++ unsigned char buf[4];
++ struct spi_xfer spi_xfer;
++ int gpio_int;
++
++ err = 0;
++ slot = bdev->slot->slotnum;
++ adap = bdev->slot->adap;
++ vh = &bmi_vh[slot];
++
++ vh->bdev = 0;
++ vh->open_flag = 0;
++
++ // Create 1 minor device
++ cdev = &vh->cdev;
++ cdev_init (cdev, &cntl_fops);
++
++ dev_id = MKDEV(major, slot);
++ err = cdev_add (cdev, dev_id, 1);
++ if (err) {
++ return err;
++ }
++
++ // Create class device
++ bmi_class = bmi_get_class ();
++ vh->class_dev = device_create (bmi_class, NULL, MKDEV (major, slot), NULL, "bmi_vh_control_m%i", slot+1);
++
++ if (IS_ERR(vh->class_dev)) {
++ printk (KERN_ERR "Unable to create "
++ "class_device for bmi_vh_m%i; errno = %ld\n",
++ slot+1, PTR_ERR(vh->class_dev));
++ vh->class_dev = NULL;
++ cdev_del (&vh->cdev);
++ return -ENODEV;
++ }
++
++ // bind driver and bmi_device
++ vh->bdev = bdev;
++
++
++ printk (KERN_INFO "bmi_vh.c: probe slot %d\n", slot);
++ vh->iox = i2c_new_device(bdev->slot->adap, &iox_info);
++ if (vh->iox == NULL)
++ printk(KERN_ERR "IOX NULL...\n");
++ vh->rdac = i2c_new_device(bdev->slot->adap, &rdac_info);
++ if (vh->rdac == NULL)
++ printk(KERN_ERR "RDAC NULL...\n");
++ vh->adc = i2c_new_device(bdev->slot->adap, &adc_info);
++ if (vh->adc == NULL)
++ printk(KERN_ERR "ADC NULL...\n");
++ vh->dac = i2c_new_device(bdev->slot->adap, &dac_info);
++ if (vh->dac == NULL)
++ printk(KERN_ERR "DAC NULL...\n");
++
++ // SPI
++ strcpy(vh->vh_spi_info.modalias, "spidev");
++ vh->vh_spi_info.max_speed_hz = speed;
++ vh->vh_spi_info.bus_num = bdev->slot->spi_bus_num;
++ vh->vh_spi_info.chip_select = bdev->slot->spi_cs;
++ vh->vh_spi_info.mode = mode;
++
++ vh->spi = spi_new_device(spi_busnum_to_master(vh->vh_spi_info.bus_num), &vh->vh_spi_info) ;
++ if (!vh->spi)
++ printk(KERN_WARNING "VH: spi_new_device failed\n");
++
++ bmi_device_set_drvdata (bdev, vh);
++ // configure IOX
++ if (factory_test) {
++ if (WriteByte_IOX(vh->iox, IOX_OUTPUT_REG, 0x55) < 0) { // all outputs high
++ goto err1;
++ }
++
++ if (WriteByte_IOX(vh->iox, IOX_CONTROL, 0xAA) < 0) { // IOX[7,5,3,1]=IN, IOX[6,4,2,0]=OUT
++ goto err1;
++ }
++ } else {
++ if (WriteByte_IOX(vh->iox, IOX_OUTPUT_REG, 0x7F) < 0) { // USB power on, other outputs high
++ goto err1;
++ }
++
++ if (WriteByte_IOX(vh->iox, IOX_CONTROL, 0x80) < 0) { // IOX[7]=IN, IOX[6:0]=OUT
++ goto err1;
++ }
++ }
++
++ mdelay(100);
++
++ // read RDAC
++ if (ReadByte_RDAC(vh->rdac, VH_RD_CMD_RDAC, rdac_data) < 0) { // read LDO RDAC register
++ goto err1;
++ }
++
++ printk (KERN_INFO "bmi_vh.c: probe RDAC = 0x%x\n", *rdac_data);
++
++ if (factory_test) {
++
++ mdelay(100); // RDAC recovery time
++
++ // set LDO voltage to 3.3V
++ *rdac_data = (unsigned char) RDAC_3_3V;
++
++ if (WriteByte_RDAC (vh->rdac, VH_RD_CMD_RDAC, *rdac_data, 1) < 0) {
++ goto err1;
++ }
++
++ mdelay(100);
++
++ if (WriteByte_RDAC (vh->rdac, VH_RD_CMD_EE, *rdac_data, 1) < 0) {
++ goto err1;
++ }
++
++ mdelay(100);
++
++ // read EEPROM
++ if (ReadByte_RDAC(vh->rdac, VH_RD_CMD_EE, rdac_data) < 0) { // read LDO EEPROM
++ goto err1;
++ }
++
++ printk (KERN_INFO "bmi_vh.c: probe EEPROM = 0x%x\n", *rdac_data);
++
++ mdelay(100);
++ }
++
++ // read ADC
++ if (ReadByte_ADC(vh->adc, adc_data) < 0) { // read initial ADC conversion
++ goto err1;
++ }
++
++ printk (KERN_INFO "bmi_vh.c: probe ADC = 0x%x%x%x\n", adc_data[0], adc_data[1], adc_data[2]);
++
++ if (factory_test) {
++
++ // power up DAC
++ if (WriteByte_DAC(vh->dac, VH_DAC_W1_EC, VH_DAC_BCH | VH_DAC_PU, 1) < 0) {
++ goto err1;
++ }
++
++ // Write DAC data
++ if (WriteByte_DAC(vh->dac, VH_DAC_W1_ALL | 0x0, 0xF0, 1) < 0) { // write A, B, inputs and update
++ goto err1;
++ }
++ }
++
++ // read DAC
++ if (ReadByte_DAC(vh->dac, VH_DAC_W1_RDA, dac_data) < 0) { // read initial DAC A value
++ goto err1;
++ }
++
++ printk (KERN_INFO "bmi_vh.c: probe DAC = 0x%x%x\n", dac_data[0], dac_data[1]);
++
++
++
++ // Initialize GPIOs (turn LED's on)
++ if (factory_test) {
++ bmi_slot_gpio_configure (slot, VH_GPIO_RED_LED); // (test I2S)
++ bmi_slot_gpio_configure (slot, VH_GPIO_GREEN_LED); // (test I2S)
++ bmi_slot_gpio_configure (slot, VH_GPIO_1); // (test I2S)
++ bmi_slot_gpio_configure (slot, VH_GPIO_0 | VH_GPIO_1); // (test interrupt)
++ } else {
++ bmi_slot_gpio_configure (slot, RED_LED |GREEN_LED ); // Red LED=ON
++ bmi_slot_gpio_set (slot, ~(RED_LED | GREEN_LED));
++ mdelay(200);
++
++ // turn LED's off
++ bmi_slot_gpio_set (slot, (RED_LED | GREEN_LED)); // Red, Green LED=OFF
++
++ if (WriteByte_IOX(vh->iox, IOX_OUTPUT_REG, 0x70) < 0) { // USB power on, IOX[3:0] low, other outputs high
++ printk (KERN_ERR "bmi_vh.c: probe() - write IOX failed\n");
++ //bmi_device_spi_cleanup(bdev);
++ goto err1;
++ }
++ }
++
++ // request PIM interrupt
++ irq = bdev->slot->status_irq;
++ sprintf (vh->int_name, "bmi_vh%d", slot);
++ if (request_irq(irq, &module_irq_handler, 0, vh->int_name, vh)) {
++ printk (KERN_ERR "bmi_vh.c: Can't allocate irq %d or find von Hippel in slot %d\n",
++ irq, slot);
++ //bmi_device_spi_cleanup(bdev);
++ goto err1;
++
++ //return -EBUSY;
++ }
++
++ if (fcc_test) {
++ init_timer (&fcc_timer);
++ fcc_timer.data = (unsigned long) &bmi_vh[slot];
++ fcc_timer.expires = jiffies + (2 * HZ);
++ fcc_timer.function = ftimer;
++ add_timer (&fcc_timer);
++ }
++
++
++ return 0;
++
++ err1:
++ vh->class_dev = NULL;
++ cdev_del (&vh->cdev);
++ device_destroy (bmi_class, MKDEV(major, slot));
++ bmi_device_set_drvdata (bdev, 0);
++ vh->bdev = 0;
++ i2c_unregister_device(vh->iox);
++ i2c_unregister_device(vh->rdac);
++ i2c_unregister_device(vh->adc);
++ i2c_unregister_device(vh->dac);
++ spi_unregister_device(vh->spi);
++ return -ENODEV;
++}
++
++// remove PIM
++void bmi_vh_remove(struct bmi_device *bdev)
++{
++ int slot;
++ struct bmi_vh *vh;
++ struct class *bmi_class;
++ int irq;
++
++ printk(KERN_INFO "bmi_vh: Module Removed...\n");
++ slot = bdev->slot->slotnum;
++ vh = &bmi_vh[slot];
++
++ i2c_unregister_device(vh->iox);
++ i2c_unregister_device(vh->rdac);
++ i2c_unregister_device(vh->adc);
++ i2c_unregister_device(vh->dac);
++ spi_unregister_device(vh->spi);
++
++ if (factory_test) {
++ // disable uart transceiver
++ bmi_slot_uart_disable (slot);
++ }
++
++ if (fcc_test)
++ del_timer (&fcc_timer);
++
++ irq = bdev->slot->status_irq;
++ free_irq (irq, vh);
++
++ bmi_slot_gpio_configure(slot, 0);
++ //bmi_device_spi_cleanup(bdev);
++
++ bmi_class = bmi_get_class ();
++ device_destroy (bmi_class, MKDEV(major, slot));
++
++ vh->class_dev = 0;
++
++ cdev_del (&vh->cdev);
++
++ // de-attach driver-specific struct from bmi_device structure
++ bmi_device_set_drvdata (bdev, 0);
++ vh->bdev = 0;
++
++ return;
++}
++
++/*
++ * module routines
++ */
++
++static void __exit bmi_vh_cleanup(void)
++{
++ dev_t dev_id;
++
++ bmi_unregister_driver (&bmi_vh_driver);
++
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region (dev_id, 4);
++ return;
++}
++
++static int __init bmi_vh_init(void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // alloc char driver with 4 minor numbers
++ retval = alloc_chrdev_region (&dev_id, 0, 4, "BMI VH Driver");
++ if (retval) {
++ return -ENODEV;
++ }
++
++ major = MAJOR(dev_id);
++ retval = bmi_register_driver (&bmi_vh_driver);
++ if (retval) {
++ unregister_chrdev_region(dev_id, 4);
++ return -ENODEV;
++ }
++
++ if(factory_test)
++ printk (KERN_INFO "bmi_vh.c: Factory Test mode enabled\n");
++
++ if(fcc_test)
++ printk (KERN_INFO "bmi_vh.c: FCC Test mode enabled\n");
++
++ printk (KERN_INFO "bmi_vh.c: BMI_VH Driver v%s \n", BMIVH_VERSION);
++
++ return 0;
++}
++
++
++module_init(bmi_vh_init);
++module_exit(bmi_vh_cleanup);
++
++module_param(factory_test, ushort, S_IRUGO);
++MODULE_PARM_DESC(factory_test, "Factory Test code enable");
++
++module_param(fcc_test, ushort, S_IRUGO);
++MODULE_PARM_DESC(fcc_test, "FCC Test code enable");
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Buglabs Inc.");
++MODULE_DESCRIPTION("BMI von Hippel device driver");
++MODULE_SUPPORTED_DEVICE("bmi_vh_control_mX");
++
+--- /dev/null
++++ git/drivers/bmi/pims/zb/Makefile
+@@ -0,0 +1,5 @@
++#
++# BMI PIMS ZigBee
++#
++bmi_zb-objs := bmi_zigbee.o bmi_zaccel.o bmi_zprotocol.o bmi_znetdev.o
++obj-$(CONFIG_BMI_ZB) += bmi_zb.o
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_zaccel.c
+@@ -0,0 +1,684 @@
++/*
++ *
++ * bmi_zaccel.c
++ *
++ * API to Zaccel device
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++#include <linux/delay.h>
++#include <linux/bmi/bmi_zb.h>
++#include "bmi_zigbee.h"
++#include "bmi_zaccel.h"
++
++int reset_count = 0;
++
++int zb_ReadConfiguration(struct bmi_zb *zb, unsigned char configId, unsigned char *buf)
++{
++ unsigned char data[128];
++ unsigned char i, len;
++
++ data[0] = 1;
++ data[1] = ZB_READ_CONFIG_REQ_0;
++ data[2] = ZB_READ_CONFIG_REQ_1;
++ data[3] = configId;
++
++ // Write to the device
++ if(zaccel_spi_req(zb, data, 128) < 0)
++ {
++ return -1;
++ }
++
++ /*
++ * Return value has format shown below.
++ * data[0] = Zaccetl return status
++ * data[1] = configID
++ * data[2] = len
++ * data[3-130] = value
++ */
++ len = data[0];
++
++ /*
++ * truncate output to 128 bytes if it is longer than 128 byte.
++ * Zaccel data sheet indicates 0-128 bytes value.
++ * Add 3 byte header to the total length
++ */
++ if(len > 128)
++ len = 128;
++
++ for(i = 0; i < (len + 3); i++)
++ {
++ buf[i] = data[i];
++ }
++
++ return(len);
++}
++
++unsigned char zb_WriteConfiguration(struct bmi_zb *zb, unsigned char configId, unsigned char len, unsigned char *value)
++{
++ unsigned char data[128];
++ int rc;
++
++ if(len > 128)
++ {
++ /* Len exceeds the max size */
++ rc = -1;
++ }
++ data[0] = 2 + len;
++ data[1] = ZB_WRITE_CONFIG_REQ_0;
++ data[2] = ZB_WRITE_CONFIG_REQ_1;
++ data[3] = configId;
++ data[4] = len;
++
++ memcpy((unsigned char *)(&data[5]),value,len);
++
++ /* Write to the device. */
++ zaccel_spi_req(zb, data, 128);
++
++ /* read return status */
++ rc = data[3];
++
++ return rc;
++}
++
++void zb_SoftReset(struct bmi_zb *zb)
++{
++ unsigned char data[8];
++
++ data[0] = 1;
++ data[1] = SYS_RESET_REQ_0;
++ data[2] = SYS_RESET_REQ_1;
++ data[3] = 0;
++
++ /* Write to the device. */
++ zaccel_spi_req(zb, data, 8);
++}
++
++void zb_sysVersion(struct bmi_zb *zb)
++{
++ unsigned char data[16];
++
++ /* SYS_VERSION command returns 5 bytes of data */
++
++ data[0] = 0;
++ data[1] = SYS_VER_0;
++ data[2] = SYS_VER_1;
++
++ /* Write to the device. */
++ zaccel_spi_req(zb, data, 16);
++}
++
++int zb_sysRFpowerAmp(struct bmi_zb *zb, unsigned char pa, unsigned char power)
++{
++ unsigned char data[32];
++ int rc = 0;
++
++ if(power > SYS_RF_PA_MIN)
++ {
++ return -EINVAL;
++ }
++
++ data[0] = 2;
++ data[1] = SYS_RF_POWER_AMP_0;
++ data[2] = SYS_RF_POWER_AMP_1;
++ data[3] = pa;
++ data[4] = power;
++
++ /* Write to the device */
++ zaccel_spi_req(zb, data, 32);
++
++ /* compare the return values */
++ if((data[3] != pa) || (data[4] != power))
++ {
++ rc = -1;
++ }
++
++ return rc;
++}
++
++unsigned char zb_device_info_len[] = {1, 8, 2, 2, 8, 1, 2, 8};
++
++int zb_GetDeviceInfo(struct bmi_zb *zb, unsigned char param,unsigned char *buf)
++{
++ unsigned char len;
++ unsigned char data[32];
++ unsigned char i;
++
++ if(param > ZB_DEVICE_LAST)
++ {
++ printk(KERN_WARNING "zb: invalid device info %d\n",param);
++ return -EINVAL;
++ }
++
++ data[0] = 1;
++ data[1] = ZB_GET_DEVICE_INFO_0;
++ data[2] = ZB_GET_DEVICE_INFO_1;
++ data[3] = param;
++
++ /* Write to the device. */
++ zaccel_spi_req(zb, data, 32);
++
++ /* data points to the value byte */
++ len = zb_device_info_len[param];
++ for(i = 0; i < len; i++)
++ {
++ buf[i] = data[i+4];
++ }
++
++ return(len);
++}
++
++void zb_FindDeviceRequest(struct bmi_zb *zb, unsigned char *searchKey)
++{
++ unsigned char data[16];
++
++ data[0] = 8;
++ data[1] = ZB_FIND_DEVICE_REQ_0;
++ data[2] = ZB_FIND_DEVICE_REQ_1;
++
++ memcpy(&data[3],searchKey,8);
++
++ /* Write to the device. */
++ zaccel_spi_req(zb, data, 16);
++}
++
++void zb_StartDevice(struct bmi_zb *zb, unsigned char option)
++{
++ zb_WriteConfiguration(zb,ZCD_NV_STARTUP_OPTION,1,&option);
++ zb_Reset(zb,ZB_RESET);
++ udelay(10);
++ zb_Reset(zb,ZB_RELEASE);
++}
++
++int zb_StartRequest(struct bmi_zb *zb)
++{
++ unsigned char data[8];
++
++ data[0] = 0;
++ data[1] = ZB_START_REQ_0;
++ data[2] = ZB_START_REQ_1;
++
++ zb->z_info.msg_flag &= ~START_CNF_BIT;
++
++ /* Write to the device */
++ zaccel_spi_req(zb, data, 8);
++
++ return 0;
++}
++
++unsigned char zb_PermitJoiningRequest(struct bmi_zb *zb, unsigned char *dest, unsigned char timeout)
++{
++ unsigned char data[8];
++ unsigned char rc;
++
++ data[0] = 3;
++ data[1] = ZB_PERMIT_JOINING_REQ_0;
++ data[2] = ZB_PERMIT_JOINING_REQ_1;
++ data[3] = dest[0]; /* LSB of short address */
++ data[4] = dest[1]; /* MSB of short address */
++ data[5] = timeout;
++
++ /* Write to the device */
++ zaccel_spi_req(zb, data, 8);
++
++ rc = data[3];
++
++ if(rc != Z_SUCCESS)
++ {
++ printk(KERN_WARNING "zb_PermitJoiningReques invalid 0x%x\n",rc);
++ }
++
++ return rc;
++}
++
++void zb_AllowBind(struct bmi_zb *zb, unsigned char timeout)
++{
++ unsigned char data[8];
++
++ data[0] = 1;
++ data[1] = ZB_ALLOW_BIND_0;
++ data[2] = ZB_ALLOW_BIND_1;
++ data[3] = timeout;
++
++ /* Write to the device */
++ zaccel_spi_req(zb, data, 8);
++}
++
++unsigned char zb_AppRegisterRequest(struct bmi_zb *zb, unsigned char len, unsigned char *app_info)
++{
++ unsigned char *data;
++ unsigned char rc;
++
++ data = kmalloc((len + ZCMD_HEADER), GFP_KERNEL);
++
++ data[0] = len;
++ data[1] = ZB_APP_REGISTER_REQ_0;
++ data[2] = ZB_APP_REGISTER_REQ_1;
++
++ memcpy(&data[3],app_info,len);
++
++ zaccel_spi_req(zb,data, (len + ZCMD_HEADER));
++
++ /* Read return status */
++ rc = data[3];
++ if(rc == Z_SUCCESS)
++ {
++ zb->z_info.app_type = SAPI_TYPE;
++ }
++
++ kfree(data);
++
++ return rc;
++
++}
++
++unsigned char zb_AFRegisterRequest(struct bmi_zb *zb, unsigned char len, unsigned char *app_info)
++{
++ unsigned char *data;
++ unsigned char rc;
++
++ data = kmalloc((len + ZCMD_HEADER), GFP_KERNEL);
++
++ data[0] = len;
++ data[1] = AF_REGISTER_0;
++ data[2] = AF_REGISTER_1;
++
++ memcpy(&data[3],app_info,len);
++
++ zaccel_spi_req(zb,data, (len + ZCMD_HEADER));
++
++ /* Read return status */
++ rc = data[3];
++ if(rc == Z_SUCCESS)
++ {
++ zb->z_info.app_type = AF_INTERFACE_TYPE;
++ }
++
++ kfree(data);
++
++ return rc;
++}
++
++void zb_BindRequest(struct bmi_zb *zb, unsigned char create, unsigned char *bind_info)
++{
++ unsigned char data[16];
++
++ data[0] = 0x0B;
++ data[1] = ZB_BIND_DEVICE_0;
++ data[2] = ZB_BIND_DEVICE_1;
++ data[3] = create;
++
++ memcpy(&data[4], bind_info, 10);
++
++ zaccel_spi_req(zb,data, 16);
++}
++
++int zb_SendDataRequest(struct bmi_zb *zb, unsigned char *buf, unsigned char len)
++{
++ unsigned char *data;
++
++ /*
++ * The user sends data to the remote ZigBee.
++ * Check if we use the SAPI or the AF send message.
++ * We expect that the user format the content of the
++ * message correctly.
++ */
++ data = kmalloc((len + ZCMD_HEADER),GFP_KERNEL);
++ data[0] = len;
++
++ if(zb->z_info.app_type == AF_INTERFACE_TYPE)
++ {
++ data[1] = AF_DATA_REQ_0;
++ data[2] = AF_DATA_REQ_1;
++ }
++ else
++ {
++ /* anything else will use SAPI */
++ data[1] = ZB_SEND_DATA_REQ_0;
++ data[2] = ZB_SEND_DATA_REQ_1;
++ }
++
++ memcpy((unsigned char *)(&data[3]), buf, len );
++
++ zaccel_spi_req(zb,data,(len + ZCMD_HEADER));
++ return 0;
++}
++
++int zb_SysTestLoopback(struct bmi_zb *zb)
++{
++ unsigned char *data;
++ unsigned char i, len;
++ unsigned char buf_len;
++ unsigned char pattern[32];
++ int rc;
++
++ len = 4;
++ buf_len = len + ZCMD_HEADER;
++ data = kmalloc(buf_len,GFP_KERNEL);
++
++ data[0] = len;
++ data[1] = SYS_TEST_LOOPBACK_REQ_0;
++ data[2] = SYS_TEST_LOOPBACK_REQ_1;
++
++ /* Prepare test pattern */
++ pattern[0] = 0xAA;
++ pattern[1] = 0x55;
++ pattern[2] = 0x07;
++ pattern[3] = 0x5A;
++ pattern[4] = 0x63;
++ pattern[5] = 0x58;
++ pattern[6] = 0x74;
++ pattern[7] = 0x55;
++ pattern[8] = 0x02;
++ pattern[9] = 0x04;
++ pattern[10] = 0x08;
++ pattern[11] = 0x10;
++ pattern[12] = 0x20;
++ pattern[13] = 0xAA;
++ pattern[14] = 0x55;
++
++ memcpy(&data[3],pattern,len);
++
++#define TEST_LOOPBACKx
++#ifdef TEST_LOOPBACK
++ printk("Loopback pattern: ");
++ for(i = 0; i < buf_len; i++)
++ {
++ printk("%x ",data[i]);
++ }
++ printk(KERN_DEBUG "\n");
++#endif
++
++ zaccel_spi_req(zb,data,buf_len);
++
++ /* Verify loopback results */
++ if((data[1] == (SYS_TEST_LOOPBACK_REQ_0 | RSPS_CMD)) &&
++ (data[2] == SYS_TEST_LOOPBACK_REQ_1))
++ {
++ if(data[0] == len)
++ {
++ rc = 0;
++ for(i = 0; i < len; i++)
++ {
++ if(data[ZCMD_HEADER + i] != pattern[i])
++ {
++ rc++;
++ printk(KERN_WARNING "error: zb test byte %d expects %x, gets %x\n",i,pattern[i],data[ZCMD_HEADER + i]);
++ }
++ }
++ }
++ else
++ {
++ rc = -2;
++ }
++ }
++ else
++ {
++ rc = -1;
++ }
++
++ return rc;
++}
++
++void zDeviceReport(struct bmi_zb *zb,unsigned char type, unsigned char len,unsigned char *buf)
++{
++ unsigned char *msg;
++
++ msg = kmalloc((ZCMD_HEADER + len),GFP_KERNEL);
++
++ msg[0] = len;
++ msg[1] = ZB_DEVICE_INFO_CHG_0;
++ msg[2] = ZB_DEVICE_INFO_CHG_0;
++ memcpy(&msg[3],buf,len);
++
++ len = ZCMD_HEADER + len;
++
++#ifdef VE_OUT
++ /* Send message to the application layer through control socket */
++ zb_rx(zb->netdev,msg,len,Z_CONTROL_SOCK);
++#endif
++
++ kfree(msg);
++}
++
++/*
++ * This routine send data originated by the user layer to
++ * the Z-Accel.
++ */
++void zaccel_xmt(struct work_struct *work)
++{
++ struct bmi_zb *zb;
++ struct zaccel_info *z_info;
++ struct zaccel_xmt_msg *msg;
++
++ zb = container_of(work, struct bmi_zb, xmt_work);
++ z_info = &zb->z_info;
++
++ while(!list_empty(&z_info->xmt_list))
++ {
++ msg = list_entry(z_info->xmt_list.next, struct zaccel_xmt_msg, list);
++
++ zb_SendDataRequest(zb, msg->buf, msg->len);
++
++ list_del(z_info->xmt_list.next);
++ kfree(msg);
++ }
++}
++
++/*
++ * zaccel_cmd_proc processes messages from the Zaccel.
++ */
++
++void zaccel_cmd_proc(struct bmi_zb *zb, unsigned char *buf)
++{
++ struct zaccel_info *z_info;
++ struct net_zb *priv;
++ unsigned char len;
++ unsigned short cmd;
++ int rc;
++
++ z_info = &zb->z_info;
++
++ len = buf[0] + ZCMD_HEADER;
++
++ /* process the message from Z-Accel */
++
++ cmd = ((((unsigned short)buf[1] << 8) & 0xFF00) |
++ ((unsigned short)buf[2] & 0x00FF));
++
++ switch(cmd)
++ {
++ case SYS_RESET_IND:
++
++ if(buf[3] == 2)
++ {
++ /* count number of reset by watch-dog */
++ reset_count++;
++ }
++
++ printk(KERN_INFO "zb%d SYS_RESET_IND %d \n",zb->slot,reset_count);
++ /* rcv Z-Accel reset indication. */
++ z_info->msg_flag |= RESET_IND_BIT;
++ wake_up_interruptible(&z_info->wait_queue);
++
++ zb_rx(zb->netdev,buf,len,Z_CONTROL_SOCK);
++ break;
++
++ case ZB_START_CONFIRM:
++ /*
++ * Z-Stack starts. Device is ready to run applicaton.
++ */
++ z_info->msg_flag |= START_CNF_BIT;
++ wake_up_interruptible(&z_info->wait_queue);
++ break;
++
++ case ZB_RCV_DATA_IND:
++ case AF_INCOMING_MSG:
++ /*
++ * Receive a packet from a remote device
++ * Send it to the user throught packet socket.
++ */
++ len = buf[0];
++
++ if(zb->netdev)
++ {
++ rc = zb_rx(zb->netdev,&buf[3],len,Z_PACKET_SOCK);
++ priv = netdev_priv(zb->netdev);
++ if(rc >= 0)
++ {
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += len;
++ }
++ else
++ {
++ priv->stats.rx_dropped++;
++ }
++ }
++ break;
++
++ case ZB_BIND_CONFIRM:
++ printk(KERN_DEBUG "Rec BIND CNF - cmd %x %x rc %x len %d\n",
++ buf[3],buf[4],buf[5],len);
++ zb_rx(zb->netdev,buf,len,Z_CONTROL_SOCK);
++ break;
++
++ case ZB_SEND_DATA_CONFIRM:
++ /* Return the results from zb_SendDataRequest */
++ if(zb->netdev)
++ {
++ priv = netdev_priv(zb->netdev);
++ if(buf[4] == Z_SUCCESS)
++ priv->stats.tx_packets++;
++ else
++ {
++ printk(KERN_WARNING "ZB: send data failed 0x%x\n",buf[4]);
++ priv->stats.tx_dropped++;
++ }
++ zb_rx(zb->netdev,buf,len,Z_CONTROL_SOCK);
++ }
++ break;
++
++ case ZDO_STATE_CHANGE_IND:
++ if((z_info->msg_flag & START_CNF_BIT) == 0)
++ {
++ z_info->msg_flag |= START_CNF_BIT;
++ wake_up_interruptible(&z_info->wait_queue);
++ }
++ break;
++
++ default:
++
++ /* send data to the user application */
++ zb_rx(zb->netdev,buf,len,Z_CONTROL_SOCK);
++ break;
++ }
++}
++
++int init_zaccel(struct bmi_zb *zb)
++{
++ struct zaccel_info *z_info;
++ int rc = 0;
++
++ z_info = &zb->z_info;
++ memset(z_info,0, sizeof(struct zaccel_info));
++
++ init_waitqueue_head(&z_info->wait_queue);
++
++ INIT_LIST_HEAD(&z_info->xmt_list);
++
++ INIT_WORK(&zb->xmt_work, zaccel_xmt);
++
++ z_info->msg_flag = 0;
++ z_info->app_type = NO_APP_TYPE;
++
++ /* Release Z-Accel */
++ zb_Reset(zb,ZB_RELEASE);
++
++ printk(KERN_DEBUG "wait for ZACCEL_RESET_IND\n");
++ /* Wait for the reset indication message from Z-Accel */
++ rc = wait_event_interruptible_timeout(z_info->wait_queue,
++ ((z_info->msg_flag & RESET_IND_BIT) != 0),Z_RESET_TIMEOUT);
++
++ /*
++ * Run Loopback test to test SPI Interface. If this test fails, and
++ * SPI interface is bad, we probably would not get the reset indication
++ * message that we were waiting for previously.
++ */
++
++ if(rc == 0)
++ {
++ printk(KERN_ERR "bmi_zaccel: Z-Accel device failed\n");
++ return -ENODEV;
++
++ }
++ else
++ {
++ /* a short delay to make sure that Z-Accel is done
++ * initializing. Advice from TI ZigBee Forum discussion.
++ */
++ mdelay(2000);
++ /* SPI loopback test */
++ rc = zb_SysTestLoopback(zb);
++ if(rc != 0)
++ {
++ printk(KERN_ERR "bmi_zaccel: SPI Loopback test FAILED %d\n",rc);
++ return -ENODEV;
++ }
++ }
++
++ /* print string for python factory test. Don't remove */
++ printk(KERN_INFO "bmi_zaccel: SPI Loopback test PASSED\n");
++
++ printk(KERN_INFO "bmi_zaccel: Z-Accel is ready\n");
++
++ return 0;
++}
++
++void remove_zaccel(struct bmi_zb *zb)
++{
++ /* hold Zaccel reset */
++ zb_Reset(zb,ZB_RESET);
++}
++
++
++void zaccel_getdev(struct bmi_zb *zb)
++{
++ struct zaccel_info *z_info;
++ struct zaccel_device zdev;
++
++ z_info = &zb->z_info;
++
++ zb_GetDeviceInfo(zb,ZB_DEVICE_STATE,
++ (unsigned char *)&zdev.state);
++ zb_GetDeviceInfo(zb,ZB_DEVICE_IEEE_ADDR,
++ (unsigned char *)&zdev.device_ieee);
++ zb_GetDeviceInfo(zb,ZB_DEVICE_SHORT_ADDR,
++ (unsigned char *)&zdev.device_short);
++ zb_GetDeviceInfo(zb,ZB_PARENT_SHORT_ADDR,
++ (unsigned char *)&zdev.parent_short);
++ zb_GetDeviceInfo(zb,ZB_PARENT_IEEE_ADDR,
++ (unsigned char *)&zdev.parent_ieee);
++ zb_GetDeviceInfo(zb,ZB_DEVICE_CHANNEL,
++ (unsigned char *)&zdev.channel);
++ zb_GetDeviceInfo(zb,ZB_DEVICE_PANID,
++ (unsigned char *)&zdev.panid);
++ zb_GetDeviceInfo(zb,ZB_DEVICE_EXT_PANID,
++ (unsigned char *)&zdev.ext_panid);
++
++ z_info->device.state = zdev.state;
++ memcpy(&z_info->device.device_ieee,&zdev.device_ieee,8);
++ memcpy(&z_info->device.device_short,&zdev.device_short,2);
++ memcpy(&z_info->device.parent_short,&zdev.parent_short,2);
++ memcpy(&z_info->device.parent_ieee,&zdev.parent_ieee,8);
++ z_info->device.channel = zdev.channel;
++ memcpy(&z_info->device.panid,&zdev.panid,2);
++ memcpy(&z_info->device.ext_panid,&zdev.ext_panid,8);
++}
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_zaccel.h
+@@ -0,0 +1,288 @@
++/*
++ * File: drivers/bmi/pims/zb/zaccel.h
++ * Author: V. Thavisri <v.thavisri@encadis.com>
++ *
++ * This is the header file for the CC2480 TI on
++ * ZigBee module. It is derived from the following source
++ *
++ */
++
++
++#ifndef _ZACCEL_H
++#define _ZACCEL_H
++
++#define RSPS_CMD 0x40
++/* SYS Interface commands */
++#define SYS_RESET_REQ_0 0x41
++#define SYS_RESET_REQ_1 0x00
++#define SYS_RESET_IND 0x4180
++#define SYS_VER_0 0x21
++#define SYS_VER_1 0x02
++#define SYS_OSAL_NV_READ 0x2108
++#define SYS_OSAL_NV_WRITE 0x2109
++#define SYS_OSAL_START_TIMER 0x210A
++#define SYS_OSAL_TIMER_EXPIRED 0x4181
++#define SYS_RANDOM 0X210C
++#define SYS_ADC_READ 0x210D
++#define SYS_GPIO 0x210E
++#define SYS_TEST_RF_0 0x41
++#define SYS_TEST_RF_1 0x40
++#define SYS_TEST_LOOPBACK_REQ 0x2141
++#define SYS_TEST_LOOPBACK_REQ_0 0x21
++#define SYS_TEST_LOOPBACK_REQ_1 0x41
++#define SYS_TEST_LOOPBACK_RSP 0x6141
++#define SYS_RF_POWER_AMP_0 0x21
++#define SYS_RF_POWER_AMP_1 0x10
++#define SYS_RF_POWER_AMP_RSP 0x6110
++
++/* Configuration Interface Commands */
++#define ZB_READ_CONFIG_REQ_0 0x26
++#define ZB_READ_CONFIG_REQ_1 0x04
++#define ZB_WRITE_CONFIG_REQ_0 0x26
++#define ZB_WRITE_CONFIG_REQ_1 0x05
++#define ZB_WRITE_CONFIG_RSP 0x6605
++
++/* ZigBee PIM specific commands */
++#define ZB_DEVICE_INFO_CHG_0 0xFF
++#define ZB_DEVICE_INFO_CHG_1 0x00
++
++// Simple API Interface
++#define ZB_APP_REGISTER_REQ_0 0x26
++#define ZB_APP_REGISTER_REQ_1 0x0A
++#define ZB_START_REQ_0 0x26
++#define ZB_START_REQ_1 0x00
++#define ZB_START_CONFIRM 0x4680
++#define ZB_PERMIT_JOINING_REQ_0 0x26
++#define ZB_PERMIT_JOINING_REQ_1 0x08
++#define ZB_BIND_DEVICE_0 0x26
++#define ZB_BIND_DEVICE_1 0x01
++#define ZB_BIND_CONFIRM 0x4681
++#define ZB_ALLOW_BIND_0 0x26
++#define ZB_ALLOW_BIND_1 0x02
++#define ZB_ALLOW_BIND_CONFIRM 0x4682
++#define ZB_SEND_DATA_REQ_0 0x26
++#define ZB_SEND_DATA_REQ_1 0x03
++#define ZB_SEND_DATA_CONFIRM 0x4683
++#define ZB_RCV_DATA_IND 0x4687
++#define ZB_GET_DEVICE_INFO_0 0x26
++#define ZB_GET_DEVICE_INFO_1 0x06
++#define ZB_FIND_DEVICE_REQ_0 0x26
++#define ZB_FIND_DEVICE_REQ_1 0x07
++#define ZB_FIND_DEVICE_CONFIRM 0X4685
++
++// AF Interface
++#define AF_REGISTER_0 0x24
++#define AF_REGISTER_1 0x00
++#define AF_DATA_REQ_0 0x24
++#define AF_DATA_REQ_1 0x01
++#define AF_DATA_CONFIRM 0x4480
++#define AF_INCOMING_MSG 0x4481
++
++// ZDO Interface
++#define ZDO_NWK_ADDR_REQ 0x2500
++#define ZDO_IEEE_ADDR_REQ 0x2501
++#define ZDO_NODE_DESC_REQ 0x2502
++#define ZDO_NODE_DESC_RES 0x2582
++#define ZDO_SIMPLE_DESC_REQ 0x2504
++#define ZDO_SIMPLE_DESC_RSP 0x4584
++#define ZDO_ACTIVE_EP_REQ 0x2505
++#define ZDO_ACTIVE_EP_RSP 0x4585
++#define ZDO_MATCH_DESC_REQ 0x2506
++#define ZDO_MATCH_DESC_RSP 0x4586
++#define ZDO_MATCH_DESC_RSP_SENT 0x45C2
++#define ZDO_USER_DESC_REQ 0x2508
++#define ZDO_USER_DESC_RSP 0x4588
++#define ZDO_USER_DESC_SET 0x250B
++#define ZDO_USER_DESC_CONF 0x4589
++#define ZDO_END_DEVICE_ANNCE 0x250A
++#define ZDO_END_DEVICE_ANNCE_IND 0x45C1
++#define ZDO_END_DEVICE_BIND_REQ 0x2520
++#define ZDO_END_DEVICE_BIND_RES_RSP 0x45A0
++#define ZDO_BIND_REQ 0x2521
++#define ZDO_BIND_RSP 0x45A1
++#define ZDO_UNBIND_REQ 0x2522
++#define ZDO_UNBIND_RSP 0x45A2
++#define ZDO_MGMT_LQI_REQ 0x2531
++#define ZDO_MGMT_LQI_RSP 0x45B1
++#define ZDO_MGMT_LEAVE_REQ 0x2534
++#define ZDO_MGMT_LEAVE_RSP 0x45B4
++#define ZDO_MGMT_PERMIT_JOIN_REQ 0x2536
++#define ZDO_MGMT_PERMIT_JOIN_RSP 0x45B6
++#define ZDO_STATE_CHANGE_IND 0x45C0
++
++// ZCD_NV_STARTUP_OPTION value
++#define ZCD_STARTOPT_DEFAULT_CONFIG 0x01
++#define ZCD_STARTOPT_DEFAULT_NETWORK 0x02
++#define ZCD_STARTOPT_AUTO_START 0x04
++#define ZCD_STARTOPT_VALID 0x02 // max valid option value
++#define ZCD_STARTOPT_MASK 0x03
++
++// ZCD_NV_LOGICAL_TYPE
++#define ZB_COORDINATOR 0x00
++#define ZB_ROUTER 0x01
++#define ZB_ENDDEVICE 0x02
++#define ZB_VALID_DEVICE 0x02
++#define ZB_DEVICE_MASK 0x03
++#define ZB_INVALID_DEVICE 0xFF
++
++// ZB_GET_DEVICE_INFO parameters
++#define ZB_DEVICE_STATE 0x00
++#define ZB_DEVICE_IEEE_ADDR 0x01
++#define ZB_DEVICE_SHORT_ADDR 0x02
++#define ZB_PARENT_SHORT_ADDR 0x03
++#define ZB_PARENT_IEEE_ADDR 0x04
++#define ZB_DEVICE_CHANNEL 0x05
++#define ZB_DEVICE_PANID 0x06
++#define ZB_DEVICE_EXT_PANID 0x07
++#define ZB_DEVICE_LAST 0x07
++
++/* Z-Accel command return value */
++#define Z_SUCCESS 0x00
++#define Z_FAILURE 0x01
++#define Z_INVALID_PARAM 0x02
++
++#define Z_ALLOW_BIND 0xFF
++#define Z_DENY_BIND 0x00
++
++#define Z_PERMIT_JOIN 0xFF
++#define Z_DENY_JOIN 0x00
++
++#define Z_BIND_CREATE 0x01
++#define Z_BIND_REMOVE 0x00
++
++#define Z_CONFIG_OFFSET 6
++
++#define SYS_RF_PA_MIN 25 /* valid power level 0 - 25 */
++
++// ZB_DEVICE_STATE definition
++typedef enum
++{
++ DEV_HOLD, // Initialized - not started automatically
++ DEV_INIT, // Initialized - not connected to anything
++ DEV_NWK_DISC, // Discovering PAN's to join
++ DEV_NWK_JOINING, // Joining a PAN
++ DEV_NWK_REJOIN, // ReJoining a PAN, only for end devices
++ DEV_END_DEVICE_UNAUTH, // Joined but not yet authenticated by trust center
++ DEV_END_DEVICE, // Started as device after authentication
++ DEV_ROUTER, // Device joined, authenticated and is a router
++ DEV_COORD_STARTING, // Started as Zigbee Coordinator
++ DEV_ZB_COORD, // Started as Zigbee Coordinator
++ DEV_NWK_ORPHAN // Device has lost information about its parent..
++} devStates_t;
++
++// zstate - Z-Accel device state
++#define ZACCEL_RESET 0
++#define ZACCEL_WAIT_RELEASE 1
++#define ZACCEL_RESET_IND 2
++#define ZACCEL_START_REQ 3
++#define ZACCEL_START_CNF 4
++#define ZACCEL_START_FAIL 5
++#define ZACCEL_APP_START 6
++#define ZACCEL_TERMINATE 7
++#define ZACCEL_POLL_DONE 8
++#define ZACCEL_UNDEFINE 0xFF
++
++/* periodic timer runs every 50 ms */
++#define Z_TIMER (50*HZ)/1000
++#define Z_RESET_TIMEOUT (20*HZ)
++#define Z_CNF_TIMEOUT (15*HZ)
++#define Z_POLL_TIMER (50*HZ)/1000
++#define Z_SRDY_TIMEOUT (4*HZ)
++
++/* frequency to update zbinfo sysfs = (Z_TIMER * UPDATE_TICKS) */
++#define UPDATE_TICKS 20
++
++/* Reset option for ioctl */
++#define Z_DONT_RESET 0
++#define Z_HW_RESET 1
++#define Z_SW_RESET 2
++
++#define ZCMD_BUF (256 + 3)
++#define ZCMD_HEADER 3
++
++struct zaccel_app_id
++{
++ unsigned char endpoint;
++ unsigned short profile_id;
++ unsigned short device_id;
++ unsigned char device_ver;
++ unsigned char unused;
++ unsigned char icmd_num;
++
++};
++struct zaccel_app_struct
++{
++ struct zaccel_app_id info;
++ unsigned char commands[1];
++};
++
++struct zaccel_version
++{
++ unsigned char transportRev;
++ unsigned char product;
++ unsigned char majorRel;
++ unsigned char minorRel;
++ unsigned char hwRev;
++};
++
++struct zaccel_config
++{
++ unsigned char device; // ZCD_NV_LOGICAL_TYPE
++ unsigned long chanlist;
++ unsigned short panid;
++};
++
++extern unsigned char zb_device_info_len[];
++#define ZDEVICE_INFO_NUM 8
++
++struct zaccel_device
++{
++ unsigned char state;
++ unsigned char device_ieee[8];
++ unsigned char device_short[2];
++ unsigned char parent_short[2];
++ unsigned char parent_ieee[8];
++ unsigned char channel;
++ unsigned char panid[2];
++ unsigned char ext_panid[8];
++};
++
++#define ZBIND_NUM_MAX 64
++struct zaccel_info
++{
++ unsigned char lastReset;
++ struct zaccel_version ver;
++ struct zaccel_device device;
++
++ struct list_head xmt_list;
++ wait_queue_head_t wait_queue;
++ unsigned short msg_flag;
++ unsigned short app_type;
++};
++
++#define NO_APP_TYPE 0
++#define SAPI_TYPE 1
++#define AF_INTERFACE_TYPE 2
++
++#define ZBUF_MAX_SIZE 150
++
++/* struct zaccel_info msg_flag bit definition */
++#define START_CNF_BIT 0x0001
++#define RESET_IND_BIT 0x0002
++
++/*
++ * XMT_MSG_SIZE = Maximum length of the ZB_SEND_DATA_REQUEST content.
++ * 2 bytes Destination, 2 bytes Command ID, 1 byte Handle
++ * 1 byte Ack, 1 byte Radius, 1 byte len, up to 84 bytes data.
++ */
++#define XMT_MSG_SIZE 92
++
++struct zaccel_xmt_msg
++{
++ struct list_head list;
++ unsigned char len;
++ unsigned char buf[XMT_MSG_SIZE];
++};
++
++
++#endif // _ZACCEL_H
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_zigbee.c
+@@ -0,0 +1,1296 @@
++/*
++ * bmi_zigbee.c
++ *
++ * BMI zigbee device driver
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/*
++ * Include files
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/cdev.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/if.h>
++#include <asm/uaccess.h>
++#include <linux/bmi/bmi_zb.h>
++#include "bmi_zigbee.h"
++#include "bmi_zaccel.h"
++
++#define BMIZIGBEE_VERSION "1.1"
++
++// Global variables
++
++static struct bmi_zb bmi_zb[4];
++static int major;
++
++/*
++ * BMI set up
++ */
++
++ // BMI device ID table
++static struct bmi_device_id bmi_zb_tbl[] =
++{
++ {
++ .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT,
++ .vendor = BMI_VENDOR_BUG_LABS,
++ .product = BMI_PRODUCT_ZIGBEE,
++ .revision = BMI_ANY,
++ },
++ { 0, }, /* terminate list */
++};
++
++MODULE_DEVICE_TABLE(bmi, bmi_zb_tbl);
++
++int bmi_zb_probe(struct bmi_device *bdev);
++void bmi_zb_remove(struct bmi_device *bdev);
++
++static struct semaphore spi_sem;
++
++// BMI driver structure
++static struct bmi_driver bmi_zb_driver =
++{
++ .name = "bmi_zb",
++ .id_table = bmi_zb_tbl,
++ .probe = bmi_zb_probe,
++ .remove = bmi_zb_remove,
++};
++
++// IOX
++// read byte from I2C IO expander
++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data)
++{
++ int ret = 0;
++ struct i2c_msg rmsg[2];
++ int num_msgs;
++
++
++ // Read Byte with Pointer
++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[0].flags = 0; // write
++ rmsg[0].len = 1;
++ rmsg[0].buf = &offset;
++
++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ rmsg[1].flags = I2C_M_RD; // read
++ rmsg[1].len = 1;
++ rmsg[1].buf = data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, rmsg, num_msgs);
++
++ if(ret == 2)
++ {
++ ret = 0;
++ }
++ else
++ {
++ printk(KERN_ERR "ReadByte_IOX() - i2c_transfer() zb failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// IOX
++// write byte from I2C IO expander
++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data)
++{
++ int ret = 0;
++ struct i2c_msg wmsg[2];
++ int num_msgs;
++
++ // Write Byte with Pointer
++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[0].flags = 0; // write
++ wmsg[0].len = 1;
++ wmsg[0].buf = &offset;
++
++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS;
++ wmsg[1].flags = 0; // write
++ wmsg[1].len = 1;
++ wmsg[1].buf = &data;
++
++ num_msgs = 2;
++ ret = i2c_transfer(adap, wmsg, num_msgs);
++
++ if(ret == 2)
++ {
++ ret = 0;
++ }
++ else
++ {
++ printk(KERN_ERR "WriteByte_IOX() - i2c_transfer() zb failed.\n");
++ ret = -1;
++ }
++ return ret;
++}
++
++// char device file operation controls the module LEDs and reset
++
++// open
++int cntl_open(struct inode *inode, struct file *file)
++{
++ struct bmi_zb *zb;
++
++ zb = container_of(inode->i_cdev, struct bmi_zb, cdev);
++
++ zb->open_flag++;
++
++ // Save zb pointer for later.
++ file->private_data = zb;
++ return 0;
++}
++
++// release
++int cntl_release(struct inode *inode, struct file *file)
++{
++ struct bmi_zb *zb;
++
++ zb = (struct bmi_zb *)(file->private_data);
++ zb->open_flag = 0;
++ return 0;
++}
++
++
++// ioctl
++int cntl_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct i2c_adapter *adap;
++ struct bmi_zb *zb;
++ unsigned char buf[80];
++ int slot;
++ int i;
++
++ zb = (struct bmi_zb *)(file->private_data);
++
++ // error if zb not present
++ if(zb->bdev == 0)
++ return -ENODEV;
++
++ slot = zb->slot;
++ adap = zb->adap;
++
++ zb->adap = adap;
++
++ switch(cmd)
++ {
++ case BMI_ZB_RLEDOFF:
++ bmi_slot_gpio_write_bit(slot, ZB_GPIO_RED_LED, ZB_GPIO_LED_OFF);
++ break;
++
++ case BMI_ZB_RLEDON:
++ bmi_slot_gpio_write_bit(slot, ZB_GPIO_RED_LED, ZB_GPIO_LED_ON);
++ break;
++
++ case BMI_ZB_GLEDOFF:
++ bmi_slot_gpio_write_bit(slot, ZB_GPIO_GREEN_LED, ZB_GPIO_LED_OFF);
++ break;
++
++ case BMI_ZB_GLEDON:
++ bmi_slot_gpio_write_bit(slot, ZB_GPIO_GREEN_LED, ZB_GPIO_LED_ON);
++ break;
++
++ /*
++ * Below are unpublished commands, used for testing only.
++ */
++
++ case BMI_ZB_RESET:
++ i = (__user arg) & 0xF;
++
++ if(i == 0)
++ {
++ printk("external reset\n");
++ zb_Reset(zb,ZB_RESET);
++ mdelay(10);
++ zb_Reset(zb,ZB_RELEASE);
++ }
++ else if (i == 1)
++ {
++ printk("soft reset\n");
++ zb_SoftReset(zb);
++ }
++ else if (i == 2)
++ {
++ printk("set startup option to default\n");
++ buf[0] = 3;
++ zb_WriteConfiguration(zb,ZCD_NV_STARTUP_OPTION,1,(unsigned char *)&buf[0]);
++ }
++
++ break;
++
++ case BMI_ZB_SPI_SIG:
++ zb_ReadSRDY(zb,1);
++ zb_ReadMRDY(zb);
++ break;
++
++ case BMI_ZB_LOOPBACK:
++ zb_SysTestLoopback(zb);
++ break;
++
++ case BMI_ZB_STARTREQ:
++ zb_StartRequest(zb);
++ break;
++
++ case BMI_ZB_UPDATE_STATE:
++ zaccel_getdev(zb);
++ break;
++
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++
++}
++
++struct file_operations zb_fops =
++{
++ .owner = THIS_MODULE,
++ .ioctl = cntl_ioctl,
++ .open = cntl_open,
++ .release = cntl_release,
++};
++
++
++void set_MRDY(struct bmi_zb *zb)
++{
++ /* Assert MRDY and SS pins */
++ bmi_slot_gpio_write_bit(zb->slot, ZB_GPIO_MRDY, 0);
++ bmi_slot_gpio_write_bit(zb->slot, ZB_GPIO_SS, 0);
++}
++
++
++void clr_MRDY(struct bmi_zb *zb)
++{
++ /* De-assert MRDY and SS pins */
++ bmi_slot_gpio_write_bit(zb->slot, ZB_GPIO_MRDY, 1);
++ bmi_slot_gpio_write_bit(zb->slot, ZB_GPIO_SS, 1);
++}
++
++static unsigned long jiff_interval(unsigned long start_time)
++{
++ unsigned long tick;
++
++ tick = jiffies;
++ if(tick >= start_time)
++ {
++ tick = tick - start_time;
++ }
++ else
++ {
++ tick = (0xFFFFFFFF - start_time) + tick;
++ }
++
++ return tick;
++}
++
++void zenable_irq(struct bmi_zb *zb)
++{
++ zb->enable = 1;
++#ifdef VE_OUT
++ printk("e-IRQ %d depth %d\n",zb->irq,zb->int_depth);
++#endif
++ if(zb->int_depth != 0)
++ {
++ zb->int_depth--;
++ enable_irq(zb->irq);
++ }
++ else
++ {
++ printk("zenable_irq: unbalance irq %d\n",zb->irq);
++ }
++}
++
++int wait_for_srdy(struct bmi_zb *zb,unsigned char type)
++{
++ int rc = 0;
++ int err = 0;
++
++ zb->srdy_state = ZB_SPI_WAIT_SRDY_H;
++ zb->start_time = jiffies;
++
++ /*
++ * Queue work to poll for SRDY high.
++ * From experimenting in the lab, I found that sometimes it took longer
++ * for the SRDY to go high when the host sent an SREQ command
++ * than when the host responded to the device AREQ (SPI_POLL_TYPE) command.
++ * So we delay the work to poll SRDY in SPI_REQ_TYPE.
++ * This delay is more of a fine tune process, and can be changed
++ * as long as it doesn't exceed the SPI transaction processing
++ * to over 1 second.
++ */
++
++ if(type == SPI_POLL_TYPE)
++ {
++ zb->delay = 0;
++ }
++ else if(type == SPI_REQ_TYPE)
++ {
++ zb->delay = SPI_CHK_SRDY_JIFFIES;
++ }
++
++ queue_delayed_work(zb->srdy_wq, &zb->srdy_work,zb->delay);
++
++ /*
++ * I use wait_event_interruptible instead of
++ * wait_event_interruptible_timeout here because we schedule
++ * work queue to poll SRDY. The work schedules another
++ * work queue, if SRDY has not been changed.
++ * Using wait_event_interruptible_timeout can cause a race
++ * condition if the wait_event_interrupt_timeout timeout occurs while
++ * the work queue is running.
++ *
++ * The code wakes up when SRDY is high or when the work queue
++ * decides that it has waited too long.
++ */
++ err = wait_event_interruptible(zb->srdy_queue,
++ ((zb->srdy_state == ZB_SPI_SRDY_HIGH) ||
++ (zb->srdy_state == ZB_SPI_SRDY_EXP)));
++
++ if(err != 0)
++ {
++ printk(KERN_WARNING "zb-%d wait_for_srdy err %d\n",zb->slot,err);
++ }
++
++ if(zb->srdy_state == ZB_SPI_SRDY_EXP)
++ {
++ rc = -1;
++ }
++
++ return rc;
++}
++
++void zaccel_spi_poll(struct bmi_zb *zb)
++{
++ struct spi_message msg;
++ unsigned char buf[ZCMD_HEADER + 256];
++ unsigned char len;
++#define AREQ_DEBUGx
++#ifdef AREQ_DEBUG
++ int i;
++#endif
++
++ struct spi_transfer t =
++ {
++ .len = SPI_MSG_HEADER_SIZE,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++
++ down(&spi_sem);
++ if(zb_ReadSRDY(zb,0) != 0)
++ {
++ /*
++ * check if SRDY is low. If not, don't run the routine.
++ *
++ * This routine is the IRQ bottom half, scheduled in the IRQ
++ * service routine.
++ * Sometimes, the SRDY goes high before the routine is executed.
++ * That happens when the zaccel_spi_req, which is scheduled to
++ * run on the same queue, is executed before
++ * zaccel_spi_poll is executed. Sometimes,
++ * the IRQ puts zaccel_spi_poll on the workqueue multiple times,
++ * each time when it sees SRDY low.
++ */
++#ifdef DEBUG_OUT
++ printk("zaccel_spi_poll SRDY high, depth %d\n",zb->int_depth);
++#endif
++
++ if(zb->int_depth != 0)
++ {
++ /* If the interrupt is disabled, enable it */
++ zenable_irq(zb);
++ }
++
++ up(&spi_sem);
++ return;
++ }
++
++ set_MRDY(zb);
++
++ buf[0] = 0;
++ buf[1] = 0;
++ buf[2] = 0;
++
++ t.tx_buf = (const void *)buf;
++ t.rx_buf = buf;
++ t.len = SPI_MSG_HEADER_SIZE;
++
++ /* Send three bytes of POLL command */
++ spi_message_init(&msg);
++ spi_message_add_tail(&t, &msg);
++
++ if((spi_sync(zb->spi, &msg) != 0) || (msg.status != 0))
++ {
++ /* error reading the data. */
++ printk(KERN_WARNING "send spi_sync error %d\n",msg.status);
++ clr_MRDY(zb);
++ up(&spi_sem);
++ zenable_irq(zb);
++ return;
++ }
++
++ if(wait_for_srdy(zb,SPI_POLL_TYPE) < 0)
++ {
++ /* time out */
++ printk(KERN_WARNING "%d - SRDY() high poll timeout\n",zb->slot);
++ clr_MRDY(zb);
++ up(&spi_sem);
++ zenable_irq(zb);
++ return;
++ }
++
++ /* Read three bytes to get the message length */
++ buf[0] = 0;
++ buf[1] = 0;
++ buf[2] = 0;
++
++ t.tx_buf = (const void *)buf;
++ t.rx_buf = buf;
++ t.len = SPI_MSG_HEADER_SIZE,
++ t.cs_change = 0,
++ t.delay_usecs = 0,
++
++ spi_message_init(&msg);
++ spi_message_add_tail(&t, &msg);
++
++ if((spi_sync(zb->spi, &msg) != 0) || (msg.status != 0))
++ {
++ /* error reading the data. */
++ printk(KERN_WARNING "rcv1 spi_sync error %d\n",msg.status);
++ clr_MRDY(zb);
++ up(&spi_sem);
++ zenable_irq(zb);
++ return;
++ }
++
++ /* buf[0] contains the length of the message */
++
++ if((buf[0] != 0) && (buf[0] != 0xFF))
++ {
++ /*
++ * Read the rest of the message, if length != 0 */
++ t.len = buf[0];
++
++ t.rx_buf = &buf[ZCMD_HEADER];
++ spi_message_init(&msg);
++
++ spi_message_add_tail(&t, &msg);
++ if((spi_sync(zb->spi, &msg) != 0) || (msg.status != 0))
++ {
++ // error reading the data. Set length to zero.
++ buf[0] = 0;
++ printk(KERN_WARNING "rcv2 spi_sync error %d\n",msg.status);
++ }
++ }
++
++ clr_MRDY(zb);
++ up(&spi_sem);
++ zenable_irq(zb);
++
++ /* buf[0] has message length */
++ len = buf[0];
++
++ if((buf[0] != 0xFF) && (buf[0] != 0))
++ {
++#ifdef AREQ_DEBUG
++ printk("AREQ-%d: ",zb->slot);
++ for(i = 0; i < (len + 3); i++)
++ {
++ printk("%x ",buf[i]);
++ }
++
++ printk("\n");
++#endif
++ }
++ else
++ {
++ if(buf[0] == 0xFF)
++ printk(KERN_WARNING "invalid 0xFF\n");
++ return;
++ }
++
++ zaccel_cmd_proc(zb,buf);
++ return;
++}
++
++void zaccel_chk_srdy(struct work_struct *work)
++{
++ struct bmi_zb *zb;
++
++ zb = container_of(work, struct bmi_zb, srdy_work);
++
++ /*
++ * check SRDY value. If it matches what we are waiting
++ * for, we wake up the work on the queue.
++ * If not, we check the timer for timeout.
++ * If the timer is not expired, queue another zb->srdy_work, to
++ * check for the signal next time.
++ * If the timer is expired, set srdy_state to indicate timeout
++ * and wake up the work.
++ */
++
++ if((zb_ReadSRDY(zb,0) == 0) && (zb->srdy_state == ZB_SPI_WAIT_SRDY_L))
++ {
++ zb->srdy_state = ZB_SPI_SRDY_LOW;
++ wake_up_interruptible(&zb->srdy_queue);
++ return;
++ }
++ else if((zb_ReadSRDY(zb,0) == 1) && (zb->srdy_state == ZB_SPI_WAIT_SRDY_H))
++ {
++ zb->srdy_state = ZB_SPI_SRDY_HIGH;
++ wake_up_interruptible(&zb->srdy_queue);
++ return;
++ }
++ else if(jiff_interval(zb->start_time) < SPI_SRDY_H_TIMEOUT)
++ {
++ queue_delayed_work(zb->srdy_wq, &zb->srdy_work,zb->delay);
++ }
++ else
++ {
++ zb_ReadSRDY(zb,1);
++ printk(KERN_WARNING "zaccel_chk_srdy state %d\n",zb->srdy_state);
++ zb->srdy_state = ZB_SPI_SRDY_EXP;
++ wake_up_interruptible(&zb->srdy_queue);
++ }
++
++}
++
++/* work handler to process Z-Accel request */
++void zaccel_poll_proc(struct work_struct *work)
++{
++ struct bmi_zb *zb;
++
++ zb = container_of(work, struct bmi_zb, spi_work);
++
++ zaccel_spi_poll(zb);
++}
++
++void zaccel_sreq_proc(struct work_struct *work)
++{
++ struct bmi_zb *zb;
++
++ unsigned char buf[320];
++ struct spi_transfer t =
++ {
++ .tx_buf = (const void *)buf,
++ .rx_buf = buf,
++ .cs_change = 0,
++ .delay_usecs = 0,
++ };
++
++ unsigned char *rbuf;
++ struct spi_message msg;
++ unsigned char type;
++ unsigned short len;
++ int i;
++ int rc = 0;
++
++ zb = container_of(work, struct bmi_zb, sreq_work);
++
++ down(&spi_sem);
++
++ rbuf = zb->sreq_buf;
++ len = (size_t)(rbuf[0] + ZCMD_HEADER);
++ type = rbuf[1] & SPI_CMD_TYPE_MASK;
++
++ t.len = len;
++ t.tx_buf = rbuf;
++
++#define SREQ_DEBUGx
++#ifdef SREQ_DEBUG
++ printk("SREQ-%d: ",zb->slot);
++
++ for(i = 0; i < len; i++)
++ {
++ printk("%x ",rbuf[i]);
++ }
++ printk("\n");
++
++#endif
++
++ set_MRDY(zb);
++
++ zb->srdy_state = ZB_SPI_WAIT_SRDY_L;
++
++ if(zb->enable == 1)
++ {
++ rc = wait_event_interruptible_timeout(zb->srdy_queue,zb->srdy_state == ZB_SPI_SRDY_LOW,SPI_SRDY_L_TIMEOUT);
++ if(rc == 0)
++ {
++ printk(KERN_WARNING "bmi_zb-%d: SRDY low timeout\n",zb->slot);
++ clr_MRDY(zb);
++ zb->srdy_state = ZB_SPI_POLL;
++ up(&spi_sem);
++ zb->sreq_ret = -1;
++ wake_up_interruptible(&zb->sreq_queue);
++ return;
++ }
++ }
++ else
++ {
++ /*
++ * The interrupt has been disabled, because SRDY is low
++ * prior to enter this routine. We proceed ahead with the
++ * SPI transaction.
++ */
++
++ if(zb_ReadSRDY(zb,0) != 0)
++ {
++ /* Double check that SRDY is low, if not, give warning */
++ printk(KERN_WARNING "zaccel_req_proc interrupt disable SRDY high\n");
++ }
++ }
++
++ i = 0;
++
++ spi_message_init(&msg);
++ spi_message_add_tail (&t, &msg);
++
++ if(spi_sync(zb->spi, &msg) != 0 || msg.status != 0)
++ {
++ printk(KERN_WARNING "bmi_zb: a - spi_sync error %d\n",msg.status);
++ zb->sreq_ret = -ENODEV;
++ goto done;
++ }
++
++ if(wait_for_srdy(zb,SPI_REQ_TYPE) < 0)
++ {
++ printk(KERN_WARNING "bmi_zb: SRDY wait to go high timeout\n");
++ zb->sreq_ret = -1;
++ goto done;
++ }
++
++ if(type == SPI_CMD_AREQ)
++ {
++ zb->sreq_ret = 0;
++ goto done;
++ }
++
++ buf[0] = 0; /* Poll command has zero byte */
++ buf[1] = 0; /* Poll command */
++ buf[2] = 0; /* Poll command */
++
++ t.tx_buf = buf;
++ t.len = SPI_MSG_HEADER_SIZE;
++
++ spi_message_init(&msg);
++
++ spi_message_add_tail(&t, &msg);
++ if(spi_sync(zb->spi, &msg) != 0 || msg.status != 0)
++ {
++ printk(KERN_WARNING "bmi_zb: b- spi_sync error %d\n",msg.status);
++ zb->sreq_ret = -ENODEV;
++ goto done;
++ }
++
++ /* Read the length of the data */
++ if(buf[0] != 0)
++ {
++ // Set len to the length of the message and offset
++ // the buffer to after the header field.
++ t.len = buf[0];
++
++ t.tx_buf = (unsigned char *)buf + SPI_MSG_HEADER_SIZE;
++ t.rx_buf = (unsigned char *)buf + SPI_MSG_HEADER_SIZE;
++ spi_message_init(&msg);
++
++ spi_message_add_tail(&t, &msg);
++
++ rc = spi_sync(zb->spi, &msg);
++ clr_MRDY(zb);
++
++ if(rc != 0 || msg.status != 0)
++ {
++ printk(KERN_WARNING "bmi_zb: c - spi_sync error %d\n",msg.status);
++ zb->sreq_ret = -ENODEV;
++ goto done;
++ }
++ }
++
++ clr_MRDY(zb);
++ up(&spi_sem);
++ zenable_irq(zb);
++
++ /*
++ * copy data back to the buffer. Make sure that we don't
++ * copy more data than the space available.
++ */
++
++ if(buf[0] != 0xFF)
++ {
++ /* copy data to the return buffer, as much as the length
++ * of the data or the buffer size (zb->sreq_len)
++ */
++ if(zb->sreq_len > (buf[0] + 3))
++ {
++ len = buf[0] + 3;
++ }
++ else
++ {
++ len = zb->sreq_len;
++ }
++ memcpy(rbuf,buf,len);
++ zb->sreq_ret = zb->sreq_len;
++ }
++ else
++ {
++ zb->sreq_ret = -2;
++ }
++
++ /* We're done. Wake up the SREQ work */
++ zb->srdy_state = ZB_SPI_POLL;
++ wake_up_interruptible(&zb->sreq_queue);
++
++#define SRSP_DEBUGx
++#ifdef SRSP_DEBUG
++ printk("SRSP-%d: ",zb->slot);
++ if(buf[0] != 0xFF)
++ {
++ for(i = 0; i < len; i++)
++ {
++ printk("%x ",buf[i]);
++ }
++ }
++ else
++ {
++ printk("Invalid length\n");
++ }
++ printk("\n");
++#endif
++
++ /*
++ * Sometimes, back-to-back write configuration
++ * can chock the Z-Accel, result in fail SPI transaction.
++ * Delay the return (wait_event_interruptible_timeout
++ * will timeout - no one wakes up the queue), to prevent the problem.
++ */
++ rc = 0;
++ wait_event_interruptible_timeout(zb->delay_queue,(rc != 0), 5);
++
++ return;
++
++done:
++ clr_MRDY(zb);
++ zb->srdy_state = ZB_SPI_POLL;
++ up(&spi_sem);
++ zenable_irq(zb);
++ wake_up_interruptible(&zb->sreq_queue);
++ return;
++}
++
++int config_ports(struct bmi_zb *zb)
++{
++ struct i2c_adapter *adap;
++ int slot;
++ unsigned char iox_data;
++
++ slot = zb->slot;
++ adap = zb->adap;
++
++ /*
++ * Configure GPIO_RED_LED and GPIO_GREEN_LED as output
++ * and set them to low -- LEDs on
++ */
++
++ bmi_slot_gpio_configure_as_output(slot,ZB_GPIO_RED_LED,0);
++ bmi_slot_gpio_configure_as_output(slot,ZB_GPIO_GREEN_LED,0);
++
++ /*
++ * Configure GPIO_SS and GPIO_MRDY as output
++ * and set them to high -- deassert
++ */
++
++ bmi_slot_gpio_configure_as_output(slot,ZB_GPIO_MRDY,1);
++ bmi_slot_gpio_configure_as_output(slot,ZB_GPIO_SS,1);
++
++ /*
++ * Set ZB_RST to output port.
++ * Set LSR_MRDY_IOX and LSR_SRDY_IOX to input port.
++ */
++
++ if(ReadByte_IOX(adap, IOX_CONTROL, &iox_data))
++ {
++ printk(KERN_ERR "Unable to ReadByte_IOX - zb slot %d\n",slot);
++ return -ENODEV;
++ }
++
++ /* Set SRDY and MRDY port to input and RST to output */
++ iox_data |= (ZB_IOX_SRDY | ZB_IOX_MRDY);
++ iox_data &= ~(ZB_IOX_RST);
++
++ if(WriteByte_IOX(adap, IOX_CONTROL, iox_data))
++ {
++ printk(KERN_ERR "Unable to WriteByte_IOX - zb slot %d\n",slot);
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++// interrupt handler
++static irqreturn_t module_irq_handler(int irq, void *dummy)
++{
++ struct bmi_zb *zb;
++
++ disable_irq_nosync(irq);
++
++ switch(irq)
++ {
++ case M1_IRQ:
++ zb = &bmi_zb[0];
++ break;
++ case M2_IRQ:
++ zb = &bmi_zb[1];
++ break;
++ case M3_IRQ:
++ zb = &bmi_zb[2];
++ break;
++ case M4_IRQ:
++ zb = &bmi_zb[3];
++ break;
++ default:
++ return IRQ_HANDLED;
++ }
++
++ zb->enable = 0;
++ zb->int_depth++;
++
++ if(zb->srdy_state == ZB_INT_WAIT_SRDY)
++ {
++ /*
++ * This interrupt is a part of host SREQ or AREQ.
++ * Set srdy flag to 0 to indicate that SRDY pin is asserted.
++ * Wake up the zb->spi_queue that is waiting for the event.
++ */
++ zb->srdy_state = ZB_INT_SRDY_LOW;
++ wake_up_interruptible(&zb->srdy_queue);
++ }
++ else
++ {
++ /*
++ * Z-Accel has an AREQ frame to send.
++ * Schedule SPI receive task to pull data out.
++ */
++ queue_work(zb->spi_wq, &zb->spi_work);
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * BMI functions
++ */
++
++int bmi_zb_probe(struct bmi_device *bdev)
++{
++ struct bmi_zb *zb;
++ struct i2c_adapter *adap;
++ struct class *bmi_class;
++ struct cdev *cdev;
++ struct net_device *netdev;
++ struct net_zb *priv;
++ dev_t dev_id;
++ int slot;
++ int irq;
++ int err;
++ char name[IFNAMSIZ];
++
++ err = 0;
++ slot = bmi_device_get_slot(bdev);
++ adap = bmi_device_get_i2c_adapter(bdev);
++
++ zb = &bmi_zb[slot];
++
++ zb->slot = slot;
++ zb->adap = adap;
++
++ dev_id = MKDEV(major, slot);
++
++ // Initialize GPIOs, turn on Red and Green LEDs.
++ if(config_ports(zb))
++ {
++ printk(KERN_ERR "Unable to configure ZB port pins slot %d\n",(slot+1));
++ return -EFAULT;
++ }
++
++ // Hold Z-Accel reset
++ zb_Reset(zb,ZB_RESET);
++
++ // setup SPI
++ printk(KERN_INFO "ZB SPI_MODE_2 clock %d\n",ZB_SPI_SPEED);
++ if(bmi_device_spi_setup(bdev, ZB_SPI_SPEED, SPI_MODE_2, ZB_SPI_BPW))
++ {
++ printk(KERN_ERR "Unable to setup spi\n");
++ return -EFAULT;
++ }
++ bmi_slot_spi_enable(slot);
++
++ zb->spi = &bdev->spi;
++ zb->srdy_state = ZB_SPI_POLL;
++
++ INIT_WORK(&zb->spi_work, zaccel_poll_proc);
++ INIT_WORK(&zb->sreq_work, zaccel_sreq_proc);
++ INIT_DELAYED_WORK(&zb->srdy_work, zaccel_chk_srdy);
++
++ init_waitqueue_head(&zb->sreq_queue);
++ init_waitqueue_head(&zb->srdy_queue);
++ init_waitqueue_head(&zb->delay_queue);
++
++ /*
++ * create a thread to handle SPI access.
++ * spi_sem allows one ZigBee module to perform and complete its
++ * SPI transaction before other Zigbee does its SPI.
++ */
++ if(slot == 0)
++ {
++ zb->spi_wq = create_singlethread_workqueue("zaccel_spi0");
++ zb->srdy_wq = create_singlethread_workqueue("zaccel_srdy0");
++ }
++ else if(slot == 1)
++ {
++ zb->spi_wq = create_singlethread_workqueue("zaccel_spi1");
++ zb->srdy_wq = create_singlethread_workqueue("zaccel_srdy1");
++ }
++ else if(slot == 2)
++ {
++ zb->spi_wq = create_singlethread_workqueue("zaccel_spi2");
++ zb->srdy_wq = create_singlethread_workqueue("zaccel_srdy2");
++ }
++ else if(slot == 3)
++ {
++ zb->spi_wq = create_singlethread_workqueue("zaccel_spi3");
++ zb->srdy_wq = create_singlethread_workqueue("zaccel_srdy3");
++ }
++
++
++ if((!zb->spi_wq) && (!zb->srdy_wq))
++ {
++ printk(KERN_ERR "ZB: create workqueue failed %d\n",slot);
++ if(zb->spi_wq)
++ {
++ destroy_workqueue(zb->spi_wq);
++ }
++
++ if(zb->srdy_wq)
++ {
++ destroy_workqueue(zb->srdy_wq);
++ }
++
++ bmi_slot_spi_disable(slot);
++ bmi_device_spi_cleanup(bdev);
++ return -ENOMEM;
++ }
++
++ // request PIM interrupt
++ irq = bmi_device_get_status_irq(bdev);
++ zb->irq = irq;
++ zb->int_depth = 0;
++
++ sprintf(zb->int_name, "bmi_zb%d", slot);
++ err = request_irq(irq, &module_irq_handler, 0, zb->int_name, zb);
++ if(err)
++ {
++ printk(KERN_ERR "bmi_zb.c: Can't allocate irq %d nor find ZB in slot %d \n", irq, slot);
++ destroy_workqueue(zb->spi_wq);
++ destroy_workqueue(zb->srdy_wq);
++ bmi_slot_spi_disable(slot);
++ bmi_device_spi_cleanup(bdev);
++ return -EBUSY;
++ }
++
++ printk(KERN_INFO "bmi_zb.c: ZIGBEE create class device\n");
++ bmi_class = bmi_get_bmi_class();
++ zb->class_dev = device_create(bmi_class, NULL, dev_id, zb,
++ "bmi_zb%i", slot + 1);
++
++ if(IS_ERR(zb->class_dev))
++ {
++ printk(KERN_ERR "Unable to create "
++ "class_device for bmi_zb_%i; errno = %ld\n",
++ slot+1, PTR_ERR(zb->class_dev));
++ zb->class_dev = NULL;
++ err = -ENODEV;
++ goto error;
++ }
++
++ /* Allocate network device */
++ sprintf(name, "zb%d",(slot+1));
++ netdev = alloc_netdev(sizeof(struct net_zb),name,zb_net_setup);
++ if(!netdev)
++ {
++ printk(KERN_ERR "zb%d: cannot register net device \n",slot);
++ err = -ENOMEM;
++ goto error0;
++
++ }
++
++ priv = netdev_priv(netdev);
++ priv->zb = zb;
++
++ err = init_zaccel(zb);
++ if(err < 0)
++ {
++ printk(KERN_ERR "zb%d: Z-Accel device not start\n",(slot+1));
++ goto error1;
++ }
++
++ err = register_netdev(netdev);
++ if(err < 0)
++ {
++ printk(KERN_WARNING "zb: cannot register net device\n");
++ goto error1;
++ }
++
++ zb_create_sysfs(netdev);
++
++ zb->netdev = netdev;
++
++ // bind driver and bmi_device
++ zb->bdev = bdev;
++ bmi_device_set_drvdata(bdev,zb);
++
++ cdev = &zb->cdev;
++ cdev_init(cdev, &zb_fops);
++ err = cdev_add(cdev, dev_id, 1);
++ if(err < 0)
++ {
++ printk(KERN_ERR "Unable to add cdev for ZigBee module\n");
++ goto error2;
++ }
++
++ /* turn LED's off */
++ bmi_set_module_gpio_data(slot, ZB_GPIO_RED_LED, ZB_GPIO_LED_OFF);
++ bmi_set_module_gpio_data(slot, ZB_GPIO_GREEN_LED, ZB_GPIO_LED_OFF);
++
++ return 0;
++
++error2:
++ zb_remove_sysfs(netdev);
++ zb->bdev = NULL;
++ bmi_device_set_drvdata(bdev,0);
++
++ zb->netdev = NULL;
++ unregister_netdev(netdev);
++
++error1:
++ remove_zaccel(zb);
++ free_netdev(netdev);
++
++error0:
++ zb->class_dev = NULL;
++ device_destroy(bmi_class,dev_id);
++
++error:
++
++ free_irq(irq, zb);
++ zb->irq = 0;
++ destroy_workqueue(zb->spi_wq);
++ destroy_workqueue(zb->srdy_wq);
++ bmi_slot_spi_disable(slot);
++ bmi_device_spi_cleanup(bdev);
++
++ printk(KERN_ERR "bmi_zb: modprobe error %d\n",err);
++ return err;
++}
++
++/* remove PIM */
++void bmi_zb_remove(struct bmi_device *bdev)
++{
++ int slot;
++ int irq;
++ struct bmi_zb *zb;
++ struct class *bmi_class;
++ struct net_device *netdev;
++
++ slot = bmi_device_get_slot(bdev);
++ zb = &bmi_zb[slot];
++
++ /* Free the interrupt first. This is to prevent stranded interrupt
++ * when we hold the Z-Accel reset.
++ */
++ irq = bmi_device_get_status_irq(bdev);
++ free_irq(irq, zb);
++
++ destroy_workqueue(zb->spi_wq);
++ destroy_workqueue(zb->srdy_wq);
++
++ remove_zaccel(zb);
++
++ cdev_del(&zb->cdev);
++
++ /* Unregister and deallocate net_device */
++ netdev = zb->netdev;
++ zb_remove_sysfs(netdev);
++ unregister_netdev(netdev);
++ free_netdev(netdev);
++ zb->netdev = NULL;
++
++ zb->irq = 0;
++ zb->spi = (struct spi_device *)NULL;
++ bmi_slot_spi_disable(slot);
++ bmi_device_spi_cleanup(bdev);
++
++ bmi_slot_gpio_configure_all_as_inputs(slot);
++
++ bmi_class = bmi_get_bmi_class();
++ device_destroy(bmi_class, MKDEV(major,slot));
++ zb->class_dev = 0;
++
++ /* de-attach driver-specific struct from bmi_device structure */
++ bmi_device_set_drvdata(bdev,0);
++ zb->bdev = 0;
++
++ printk(KERN_INFO "bmi_zb: remove completed\n");
++ return;
++}
++
++int zaccel_spi_req(struct bmi_zb *zb, unsigned char *rbuf, unsigned short buf_len)
++{
++ int err;
++
++ zb->sreq_buf = rbuf;
++ zb->sreq_len = buf_len;
++
++ queue_work(zb->spi_wq, &zb->sreq_work);
++ zb->sreq_ret = 0xFF;
++ err = wait_event_interruptible_timeout(zb->sreq_queue,zb->sreq_ret != 0xFF,(5*HZ));
++ if(err == 0)
++ {
++ printk(KERN_ERR "zaccel_spi_req timeout %d\n",zb->sreq_ret);
++ zb->sreq_ret = -ENODEV;
++ }
++
++ return zb->sreq_ret;
++}
++
++void zb_ReadMRDY(struct bmi_zb *zb)
++{
++ int mrdy;
++ int ss;
++
++ mrdy = bmi_slot_gpio_read_bit(zb->slot,ZB_GPIO_MRDY);
++ ss = bmi_slot_gpio_read_bit(zb->slot,ZB_GPIO_SS);
++ printk("zb-SPI: MRDY %d SS %d\n",mrdy,ss);
++}
++
++int zb_ReadSRDY(struct bmi_zb *zb, int print)
++{
++ int irq_pin;
++ int value;
++
++ irq_pin = bmi_slot_status_irq_state(zb->slot);
++
++ if(irq_pin == 1)
++ value = 0;
++ else
++ value = 1;
++
++ if(print == 1)
++ printk("zb-SPI: srdy %d\n",value);
++ return value;
++}
++
++/* Z-Accel hardware reset */
++int zb_Reset(struct bmi_zb *zb, unsigned char state)
++{
++ unsigned char iox_data;
++
++ if(ReadByte_IOX (zb->adap, IOX_OUTPUT_REG, &iox_data))
++ return -ENODEV;
++
++ if(state == ZB_RESET)
++ {
++ iox_data &= ~ZB_IOX_RST;
++ }
++ else if(state == ZB_RELEASE)
++ {
++ zb->z_info.msg_flag &= ~RESET_IND_BIT;
++ iox_data |= ZB_IOX_RST;
++ }
++
++ if(WriteByte_IOX (zb->adap, IOX_OUTPUT_REG, iox_data))
++ return -ENODEV;
++
++ return 0;
++}
++
++static void __exit bmi_zb_cleanup(void)
++{
++ dev_t dev_id;
++
++ bmi_unregister_driver(&bmi_zb_driver);
++
++ /* Unregister PF_ZACCEL socket */
++ z_sock_exit();
++
++ dev_id = MKDEV(major, 0);
++ unregister_chrdev_region(dev_id, 4);
++
++ return;
++}
++
++static int __init bmi_zb_init(void)
++{
++ dev_t dev_id;
++ int retval;
++
++ // allocate char device for the module control.
++ retval = alloc_chrdev_region(&dev_id, 0, 4, "BMI ZigBee Driver");
++ if(retval)
++ {
++ printk(KERN_ERR "Unable to allocate zb chardev_region\n");
++ return -1;
++ }
++ major = MAJOR(dev_id);
++
++ /* Register PF_ZACCEL protocol socket */
++ retval = z_sock_init();
++ if(retval)
++ {
++ unregister_chrdev_region(dev_id, 4);
++ printk(KERN_ERR "ZB: protocol register failed %d \n", retval);
++ return -1;
++ }
++
++ init_MUTEX(&spi_sem);
++
++ retval = bmi_register_driver(&bmi_zb_driver);
++ if(retval)
++ {
++ z_sock_exit();
++ unregister_chrdev_region(dev_id, 4);
++
++ printk(KERN_ERR "ZB: bmi_unregister_driver failed %d\n", retval);
++ return -1;
++ }
++
++ printk(KERN_INFO "bmi_zb.c: BMI_ZIGBEE Driver v%s 0x%x\n", BMI_ZB_VERSION,BMI_PRODUCT_ZIGBEE);
++
++ return 0;
++}
++
++
++module_init(bmi_zb_init);
++module_exit(bmi_zb_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("V. Thavisri <v.thavisri@encadis.com>");
++MODULE_DESCRIPTION("BMI ZigBee device driver");
++MODULE_SUPPORTED_DEVICE("bmi_zigbee_control");
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_zigbee.h
+@@ -0,0 +1,194 @@
++/*
++ * File:
++ * Author: V. Thavisri <v.thavisri@encadis.com>
++ *
++ * Header file for the ZB module on the MX31 BUG platform.
++ */
++#ifndef BMI_ZB_H
++#define BMI_ZB_H
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/cdev.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
++#include <linux/workqueue.h>
++#include <linux/netdevice.h>
++#include <linux/interrupt.h>
++#include <linux/bmi.h>
++#include <linux/bmi/bmi-control.h>
++#include <linux/bmi/bmi_ioctl.h>
++#include <linux/bmi/bmi_zb.h>
++#include "bmi_zaccel.h"
++
++#define BMI_ZB_VERSION "1.0"
++#define VE_DEBUG
++
++// GPIO
++#define ZB_GPIO_RED_LED 3
++#define ZB_GPIO_GREEN_LED 2
++#define ZB_GPIO_MRDY 1
++#define ZB_GPIO_SS 0
++
++#define ZB_GPIO_LED_ON 0
++#define ZB_GPIO_LED_OFF 1
++
++#define BMI_IOX_I2C_ADDRESS 0x71
++// I2C IOX register addressess
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++#define ZB_IOX_RST 0x1
++#define ZB_IOX_MRDY 0x2
++#define ZB_IOX_SRDY 0x4
++
++// SPI parameters
++#define ZB_SPI_SPEED 2000000
++#define ZB_SPI_BPW 8
++
++// SPI state
++// check the state when SRDY is asserted to determine which
++// SPI transaction the host wants to perform.
++#define ZB_SPI_POLL 0
++#define ZB_SPI_WAIT_SRDY_L 1
++#define ZB_SPI_SRDY_LOW 2
++#define ZB_SPI_WAIT_SRDY_H 3
++#define ZB_SPI_SRDY_HIGH 4
++#define ZB_SPI_TIME2POLL 5
++#define ZB_SPI_SRDY_EXP 6
++#define ZB_SPI_WAIT_SRDY_Q 7
++
++#define ZB_INT_POLL 0
++#define ZB_INT_WAIT_SRDY 1
++#define ZB_INT_SRDY_LOW 2
++
++#define SPI_POLL_TYPE 0
++#define SPI_REQ_TYPE 1
++
++#define ZB_RESET 0
++#define ZB_RELEASE 1
++
++#define SPI_BUF_MAX_SIZE ZBUF_MAX_SIZE
++#define SPI_MSG_HEADER_SIZE 3
++
++#define SPI_CMD_POLL 0x00
++#define SPI_CMD_SREQ 0x20
++#define SPI_CMD_AREQ 0x40
++#define SPI_CMD_TYPE_MASK (SPI_CMD_SREQ | SPI_CMD_AREQ)
++
++#define SPI_CHK_SRDY_JIFFIES 1
++#define SPI_CHK_SRDY_TIME 4000
++#define SPI_SRDY_L_TIMEOUT (HZ>>1)
++#define SPI_SRDY_H_TIMEOUT (HZ>>1)
++
++// Zigbee network private information
++struct net_zb
++{
++ struct net_device *dev;
++ struct bmi_zb *zb;
++ struct net_device_stats stats;
++ unsigned char net_open;
++ unsigned char socket[Z_NUM_SOCK];
++};
++
++struct bmi_zb
++{
++ struct bmi_device *bdev;
++ struct cdev cdev;
++ struct net_device *netdev;
++ struct device *class_dev;
++ struct i2c_adapter *adap;
++ struct spi_device *spi; /* SPI device */
++
++ struct work_struct spi_work; /* work to process Poll req */
++ struct work_struct xmt_work; /* work to xmt to device */
++ struct work_struct sreq_work; /* work to process sreq */
++ struct work_struct state_work; /* work to check device state */
++
++ struct delayed_work srdy_work; /* work to chk for SRDY */
++
++ unsigned long start_time;
++ unsigned long delay;
++
++ struct workqueue_struct *spi_wq;
++ struct workqueue_struct *srdy_wq;
++
++ wait_queue_head_t srdy_queue;
++ unsigned char srdy_state;
++ unsigned char enable;
++ unsigned char int_depth;
++
++ wait_queue_head_t sreq_queue;
++ unsigned char *sreq_buf;
++ unsigned short sreq_len;
++ int sreq_ret;
++
++ wait_queue_head_t delay_queue;
++
++ char int_name[20]; /* interrupt name */
++ int slot; /* base unit slot number */
++ int open_flag; /* single open flag */
++ int irq;
++ struct zaccel_info z_info;
++};
++
++extern int zb_Reset(struct bmi_zb *zb, unsigned char state);
++extern void zb_StartDevice(struct bmi_zb *zb, unsigned char option);
++extern int zb_StartRequest(struct bmi_zb *zb);
++extern void zb_spi_poll(void *arg);
++extern int zaccel_spi_req(struct bmi_zb *zb, unsigned char *data, unsigned short buf_len);
++extern int zaccel_SRDY_poll(struct bmi_zb *zb, unsigned char polarity);
++extern int zb_GetDeviceInfo(struct bmi_zb *zb, unsigned char param, unsigned char *buf);
++extern unsigned char zb_WriteConfiguration(struct bmi_zb *zb, unsigned char configId, unsigned char len, unsigned char *data);
++extern int zb_ReadConfiguration(struct bmi_zb *zb, unsigned char configId,
++ unsigned char *buf);
++extern int zb_zcommand(struct bmi_zb *zb, unsigned short cmd, unsigned char len,
++ unsigned char *buf);
++extern void zb_SoftReset(struct bmi_zb *zb);
++extern unsigned char zb_AppRegisterRequest(struct bmi_zb *zb, unsigned char len,
++ unsigned char *app_info);
++extern unsigned char zb_PermitJoiningRequest(struct bmi_zb *zb,
++ unsigned char *dest, unsigned char timeout);
++extern void zb_AllowBind(struct bmi_zb *zb, unsigned char timeout);
++extern void zb_BindRequest(struct bmi_zb *zb, unsigned char create,
++ unsigned char *bind_info);
++extern int zb_SendDataRequest(struct bmi_zb *zb, unsigned char *buf,
++ unsigned char len);
++extern void zb_FindDeviceRequest(struct bmi_zb *zb, unsigned char *searchKey);
++extern unsigned char zb_AFRegisterRequest(struct bmi_zb *zb, unsigned char len, unsigned char *app_info);
++extern int zb_sysRFpowerAmp(struct bmi_zb *zb, unsigned char pa, unsigned char power);
++
++extern void zaccel_cmd_proc(struct bmi_zb *zb,unsigned char *buf);
++extern int zb_rx(struct net_device *dev, unsigned char *buf,
++ unsigned char len, unsigned short type);
++extern int z_sock_init(void);
++extern int zdev_setopt(struct net_device *dev,int cmd, int len,
++ unsigned char *buf);
++extern int zdev_getopt(struct net_device *dev, int cmd, int *len,
++ unsigned char *buf);
++
++extern void zb_net_setup(struct net_device *dev);
++extern void zaccel_getdev(struct bmi_zb *zb);
++
++extern void z_sock_exit(void);
++extern int z_sock_init(void);
++extern void zb_create_sysfs(struct net_device *net);
++extern void zb_remove_sysfs(struct net_device *net);
++extern int init_zaccel(struct bmi_zb *zb);
++extern void remove_zaccel(struct bmi_zb *zb);
++extern int zb_ReadSRDY(struct bmi_zb *zb, int print);
++extern void zb_ReadMRDY(struct bmi_zb *zb);
++extern void zaccel_spi_poll(struct bmi_zb *zb);
++extern int zb_SysTestLoopback(struct bmi_zb *zb);
++extern void zb_sysVersion(struct bmi_zb *zb);
++extern int zaccel_get_chanlist(struct bmi_zb *zb);
++
++
++
++#endif // BMI_ZB_H
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_znetdev.c
+@@ -0,0 +1,977 @@
++/*
++ * bmi_znetdev.c
++ *
++ * This file contains the zaccel network device driver codes.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/if.h>
++#include <linux/sysfs.h>
++#include <linux/bmi/bmi_zb.h>
++#include "bmi_zigbee.h"
++#include "bmi_zaccel.h"
++
++static int zb_open(struct net_device *dev)
++{
++ struct bmi_zb *zb;
++ struct net_zb *priv;
++ struct zaccel_device *zdev;
++
++ printk(KERN_DEBUG "bmi_znetdev: zb_open\n");
++ priv = netdev_priv(dev);
++ zb = priv->zb;
++ zdev = &zb->z_info.device;
++
++ priv->net_open = 1;
++ netif_start_queue(dev);
++ return 0;
++}
++
++static int zb_close(struct net_device *dev)
++{
++ struct net_zb *priv;
++
++ printk(KERN_DEBUG "bmi_znetdev: zb_close\n");
++ priv = netdev_priv(dev);
++
++ priv->net_open = 0;
++ netif_stop_queue(dev);
++
++ return 0;
++}
++
++static int zb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++ unsigned char len_chk;
++ unsigned char offset;
++ struct net_zb *priv;
++ struct bmi_zb *zb;
++ struct zaccel_info *z_info;
++
++ unsigned char *zapp;
++ unsigned char buf[32];
++ unsigned short len;
++ unsigned char type;
++ unsigned char reason = 0;
++ unsigned char *user_pt;
++ unsigned char flag;
++ unsigned char state;
++ int i;
++ int rc = 0;
++
++ priv = netdev_priv(dev);
++ zb = priv->zb;
++ z_info = &zb->z_info;
++
++ switch(cmd)
++ {
++ case SIOCSRESET:
++ if(copy_from_user(buf, ifr->ifr_data, (2*sizeof(char))))
++ {
++ printk(KERN_ERR "BMI_ZB_ANY_REQ cannot get commands\n");
++ return -EFAULT;
++ }
++
++ switch(buf[0])
++ {
++ case Z_HW_RESET:
++ if(dev->flags & IFF_UP)
++ {
++ /* set flag to remember that IF is up previously */
++ flag = IFF_UP;
++ dev->flags &= ~IFF_UP;
++ netif_stop_queue(dev);
++ }
++
++ zb_Reset(zb,ZB_RESET);
++ udelay(10);
++ zb_Reset(zb,ZB_RELEASE);
++
++ break;
++
++ case Z_SW_RESET:
++ if(dev->flags & IFF_UP)
++ {
++ flag = IFF_UP;
++ dev->flags &= ~IFF_UP;
++ netif_stop_queue(dev);
++ }
++
++ zb_SoftReset(zb);
++ break;
++
++ case Z_DONT_RESET:
++ return 0;
++
++ default:
++ printk(KERN_WARNING "zb ioctl reset - unknow reset type %d\n",buf[1]);
++ return -EINVAL;
++ }
++
++ /*
++ * If reset the device, wait for it to come back and
++ * start Z-stack.
++ */
++ rc = wait_event_interruptible_timeout(z_info->wait_queue,
++ ((z_info->msg_flag & RESET_IND_BIT) != 0),Z_RESET_TIMEOUT);
++
++ if(rc == 0)
++ {
++ /* timeout and no indication received */
++ reason = 1;
++ printk(KERN_ERR "zb: wait for reset IND timeout\n");
++ rc = -EAGAIN;
++ }
++ else
++ {
++
++#ifdef VE_OUT
++ if(flag & IFF_UP)
++ {
++ netif_start_queue(dev);
++ dev->flags |= IFF_UP;
++ }
++#endif
++
++ rc = 0;
++ }
++
++ if(rc == -EAGAIN)
++ {
++ /* copy extra code to the user space */
++ if(copy_to_user(ifr->ifr_data,(void *)&reason,1))
++ {
++ return -EFAULT;
++ }
++ }
++
++ break;
++
++ case SIOCGDEVICEINFO:
++
++ if(copy_from_user(buf, ifr->ifr_data, 1))
++ {
++ printk(KERN_ERR "SIOCGDEVICEINFO cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ len = zb_GetDeviceInfo(zb,buf[0],buf);
++
++ if(copy_to_user(ifr->ifr_data, buf, len))
++ {
++ return -EFAULT;
++ }
++
++ rc = (int)len;
++ break;
++
++ case SIOCSAPPREGISTER:
++ if(copy_from_user(buf, ifr->ifr_data, sizeof(char)))
++ {
++ printk(KERN_ERR "SIOCSAPPREGISTER cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ len = (unsigned short)buf[0];
++
++ /*
++ * Input Format:
++ * 1-byte message length
++ * x-bytes message (see below comment for msg format.
++ */
++
++ zapp = kmalloc(len,GFP_KERNEL);
++ if(zapp == NULL)
++ {
++ printk(KERN_WARNING "zb_ioctl no buf for cmd 0x%x\n",cmd);
++ return -ENOMEM;
++ }
++
++ user_pt = (unsigned char *)ifr->ifr_data;
++ if(copy_from_user((void *)zapp, &user_pt[1], (unsigned long)len))
++ {
++ kfree(zapp);
++ return -EFAULT;
++ }
++
++ /*
++ * verify the length of the data.
++ * Format of message is (number in parenthesis = num of bytes)
++ *
++ * zapp[offset] content
++ * 0 appEndpoint(1)
++ * 1 appProfileID(2)
++ * 3 deviceId(2)
++ * 5 deviceVersion(1)
++ * 6 unused(1)
++ * 7 inputCommandNum(1)
++ * [8] [inputCommand(2),inputCommand(2), ...]
++ * 8 + (inputNum * 2) outputCommandNum(1)
++ * [outputCommand(2),outputCommand(2), ...]
++ */
++
++ /* 8 bytes between appEndpoint to inputCommandNum */
++ len_chk = 8;
++
++ /*
++ * Get the offset to outputCommandNum byte
++ * and add the number of inputCommand bytes and outputCommandNum
++ * byte to the len_chk.
++ */
++ offset = (zapp[7] << 1) + 8;
++ len_chk += (zapp[7] << 1) + 1;
++
++ /* Add the number of output command bytes */
++ len_chk += (zapp[offset] << 1);
++
++ if(len_chk != len)
++ {
++ /*
++ * The len of the input declared is less than the
++ * number of data required.
++ */
++ kfree(zapp);
++ printk(KERN_WARNING "SIOCSAPPREGISTER: inconsistence len %d %d\n",len_chk,len);
++ return -EINVAL;
++ }
++
++ buf[0] = zb_AppRegisterRequest(zb,len,zapp);
++
++ if(buf[0] != 0)
++ {
++ rc = -1;
++ }
++
++ if(copy_to_user(ifr->ifr_data,buf,1))
++ {
++ printk(KERN_WARNING "SIOCAPP result dropped\n");
++ }
++
++ kfree(zapp);
++
++ break;
++
++ case SIOCSALLOWBIND:
++ if(copy_from_user(buf, ifr->ifr_data, sizeof(char)))
++ {
++ printk(KERN_ERR "SIOCSALLOWBIND cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ /*
++ * Input format:\
++ * 1-bytes timeout
++ */
++
++ zb_AllowBind(zb,buf[0]);
++
++ break;
++
++ case SIOCSSTARTREQ:
++ zb_StartRequest(zb);
++ rc = wait_event_interruptible_timeout(z_info->wait_queue,
++ ((z_info->msg_flag & START_CNF_BIT) != 0),Z_CNF_TIMEOUT);
++
++ if(rc == 0)
++ {
++ /* timeout - We didn't receive START_CNF message nor
++ * ZDO_STATE_CHANGE_IND. This can happens if the
++ * end-device or router does not find a network.
++ * Check if the device state had changed from DEV_HOLD
++ * to anything else. If it does, the stack has started.
++ */
++ zb_GetDeviceInfo(zb,ZB_DEVICE_STATE,(unsigned char *)&state);
++ if((state != DEV_HOLD) || (state != DEV_INIT))
++ {
++ printk(KERN_DEBUG "stack starts, state %d\n",state);
++ rc = 0;
++ }
++ else
++ {
++ rc = -1;
++ printk(KERN_DEBUG "Stack fails to start\n");
++ }
++ }
++ else
++ {
++ printk(KERN_DEBUG "rcv ZB_START_CONFIRM\n");
++ rc = 0;
++ }
++
++ break;
++
++ case SIOCSPERMITJOINING:
++ if(copy_from_user(buf, ifr->ifr_data, 3))
++ {
++ printk(KERN_ERR "SIOCSPERMITJOINING: read error\n");
++ return -EFAULT;
++ }
++
++ /*
++ * Input format:
++ * 2-bytes 16-bit device address
++ * 1-bytes timeout
++ */
++#ifdef VE_OUT
++ printk(KERN_DEBUG "permitjoining address 0x%x timeout 0x%x\n",*(unsigned short *)buf,buf[2]);
++#endif
++
++ buf[0] = zb_PermitJoiningRequest(zb,&buf[0],buf[2]);
++
++ if(buf[0] != 0)
++ {
++ rc = -1;
++ }
++
++ if(copy_to_user(ifr->ifr_data,buf,1))
++ {
++ printk(KERN_WARNING "SIOCSPERMIT result dropped\n");
++ }
++
++ break;
++
++ case SIOCSBIND:
++ if(copy_from_user(buf, ifr->ifr_data, 12))
++ {
++ printk(KERN_ERR "SIOCSBIND cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ if((buf[0] != Z_BIND_CREATE) && (buf[0] != Z_BIND_REMOVE))
++ {
++ return -EINVAL;
++ }
++
++ zb_BindRequest(zb,buf[0],&buf[1]);
++
++ break;
++
++ case SIOCSFINDDEVICE:
++ if(copy_from_user(buf, ifr->ifr_data, 8))
++ {
++ printk(KERN_ERR "SIOCSFINDDEVICE cannot get parameter\n");
++ return -EFAULT;
++ }
++ zb_FindDeviceRequest(zb,buf);
++ break;
++
++ case SIOCSAFREGISTER:
++ if(copy_from_user(buf, ifr->ifr_data, sizeof(char)))
++ {
++ printk(KERN_ERR "SIOCSAPPREGISTER cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ len = (unsigned short)buf[0];
++
++ /*
++ * Input Format:
++ * 1-byte message length
++ * x-bytes message (see below comment for msg format.
++ */
++
++ zapp = kmalloc(len,GFP_KERNEL);
++ if(zapp == NULL)
++ {
++ printk(KERN_WARNING "zb_ioctl no buf for cmd 0x%x\n",cmd);
++ return -ENOMEM;
++ }
++
++ user_pt = (unsigned char *)ifr->ifr_data;
++ if(copy_from_user((void *)zapp, &user_pt[1], (unsigned long)len))
++ {
++ kfree(zapp);
++ return -EFAULT;
++ }
++
++ buf[0] = zb_AFRegisterRequest(zb,len,zapp);
++ if(buf[0] != 0)
++ {
++ rc = -1;
++ }
++
++ if(copy_to_user(ifr->ifr_data,buf,1))
++ {
++ printk(KERN_WARNING "SIOCAPP result dropped\n");
++ }
++
++ kfree(zapp);
++ break;
++
++ case SIOCSPOWERAMP:
++ if(copy_from_user(buf, ifr->ifr_data, 2))
++ {
++ printk(KERN_ERR "SIOCSPOWERAMP cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ rc = zb_sysRFpowerAmp(zb,buf[0],buf[1]);
++ break;
++
++ case SIOCSZCOMMAND:
++
++ /*
++ * This command passes any Z-Accel command to the device and
++ * returns the reply back to the user.
++ * Message format:
++ * 1-byte length of data field
++ * 2-bytes command
++ * 0-128 bytes data
++ */
++ if(copy_from_user(buf, ifr->ifr_data, 1))
++ {
++ printk(KERN_ERR "SIOCSZCOMMAND cannot get parameter\n");
++ return -EFAULT;
++ }
++
++ user_pt = (unsigned char *)ifr->ifr_data;
++ len = (unsigned short)buf[0] + 3;
++
++ if(len > ZCMD_BUF)
++ {
++ printk(KERN_WARNING "SIOCSZCOMMAND message is too long\n");
++ return -EINVAL;
++ }
++
++ zapp = kmalloc(ZCMD_BUF,GFP_KERNEL);
++ if(zapp == NULL)
++ {
++ printk(KERN_WARNING "SIOCSZCOMMAND no buf for the cmd\n");
++ return -ENOMEM;
++ }
++
++ if(copy_from_user(zapp, ifr->ifr_data, len))
++ {
++ printk(KERN_ERR "SIOCSZCOMMAND cannot get parameter\n");
++ return -EFAULT;
++ }
++ type = zapp[1] & SPI_CMD_TYPE_MASK;
++
++#define VE_DEBUG
++#ifdef VE_DEBUGx
++ printk("len %d: ",len);
++ for(i = 0; i < len; i++)
++ {
++ printk("%x ",zapp[i]);
++ }
++ printk("\n");
++#endif
++
++ zaccel_spi_req(zb,zapp,len);
++
++ /*
++ * read the length of the data, if it's SREQ command.
++ */
++
++ if(type != SPI_CMD_AREQ)
++ {
++ len = zapp[0];
++
++ if(copy_to_user(ifr->ifr_data,zapp,(len + 3)))
++ {
++ return -EFAULT;
++ }
++ }
++ rc = 0;
++
++ break;
++
++ default:
++ printk("zb_ioctl default cmd\n");
++ rc = -EINVAL;
++ break;
++
++ }
++
++ return rc;
++}
++
++/*
++ * zb_rx passes data from Z-Accel to the user via socket
++ */
++int zb_rx(struct net_device *dev, unsigned char *buf, unsigned char len, unsigned short type)
++{
++ struct sk_buff *skb;
++ struct net_zb *priv;
++
++ if(!dev)
++ return -EINVAL;
++
++
++ priv = netdev_priv(dev);
++
++ if(priv->socket[type] == Z_NO_SOCK)
++ {
++ return -EINVAL;
++ }
++
++ /*
++ * Check if the device is bound to a socket.
++ * If not, drop the message.
++ */
++
++ dev->last_rx = jiffies;
++
++ skb = dev_alloc_skb(len);
++ if(skb)
++ {
++ memcpy(skb_put(skb,len),buf,len);
++
++ /*
++ * Set the device to zigbee.
++ * Set protocol number to zero, so the kernel will not
++ * pass it through the protocol stack.
++ */
++
++ skb->dev = dev;
++ skb->protocol = type;
++
++ if(type == Z_PACKET_SOCK)
++ {
++ /*
++ * Increment packet count and notify kernel of
++ * the new packet.
++ */
++ priv->stats.rx_packets++;
++ }
++
++ netif_rx(skb);
++ }
++ else
++ {
++ if(type == Z_PACKET_SOCK)
++ priv->stats.rx_dropped++;
++ }
++
++ return 0;
++}
++
++int zb_tx(struct sk_buff *skb, struct net_device *dev)
++{
++ struct bmi_zb *zb;
++ struct net_zb *priv;
++ struct zaccel_xmt_msg *msg;
++ unsigned char *buf;
++
++ priv = netdev_priv(dev);
++ zb = priv->zb;
++
++ if(skb->len > XMT_MSG_SIZE)
++ {
++ dev_kfree_skb(skb);
++ return -EINVAL;
++ }
++
++ msg = (struct zaccel_xmt_msg *)kmalloc(sizeof(struct zaccel_xmt_msg), GFP_KERNEL);
++ buf = msg->buf;
++
++ memcpy(buf,skb->data,skb->len);
++
++ msg->len = skb->len;
++
++ /*
++ * zb_tx is called by dev_queue_xmit, which requires atomic
++ * operation. We cannot call zb_SendDataRequest directly here
++ * to schedule SPI transfer to the Z-Accel because
++ * it causes "BUG: scheduling while atomic exception."
++ * We put the data in a message queue and
++ * schedule a work queue to call zb_SendDataRequest later.
++ */
++
++ list_add_tail(&msg->list, &zb->z_info.xmt_list);
++ schedule_work(&zb->xmt_work);
++
++ /* Move this statistic to a real packet transmission location later */
++ priv->stats.tx_packets++;
++
++ dev->trans_start = jiffies;
++
++ /* Free sku buffer */
++ dev_kfree_skb(skb);
++
++ return 0;
++}
++
++struct net_device_stats *zb_stats(struct net_device *dev)
++{
++ struct net_zb *priv = netdev_priv(dev);
++
++ return &priv->stats;
++}
++
++void zb_net_setup(struct net_device *dev)
++{
++ struct net_zb *priv;
++
++ priv = netdev_priv(dev);
++
++ priv->dev = dev;
++ priv->socket[Z_PACKET_SOCK] = Z_NO_SOCK;
++ priv->socket[Z_CONTROL_SOCK] = Z_NO_SOCK;
++
++ dev->open = zb_open;
++ dev->stop = zb_close;
++ dev->hard_start_xmit = zb_tx;
++ dev->tx_queue_len = 32;
++ dev->get_stats = zb_stats;
++ dev->do_ioctl = zb_ioctl;
++ dev->flags = 0;
++}
++
++int zdev_setopt(struct net_device *dev,int cmd, int len, unsigned char *buf)
++{
++ struct net_zb *priv = netdev_priv(dev);
++ struct bmi_zb *zb;
++ int rc;
++
++ zb = priv->zb;
++ rc = (int)zb_WriteConfiguration(zb,(unsigned char)cmd,(unsigned char)len,buf);
++ return rc;
++}
++
++int zdev_getopt(struct net_device *dev, int cmd, int *len, unsigned char *buf)
++{
++ struct net_zb *priv = netdev_priv(dev);
++ struct bmi_zb *zb;
++
++ zb = priv->zb;
++
++ *len = (int)zb_ReadConfiguration(zb,(unsigned char)cmd,buf);
++ if(*len != 0)
++ {
++ return 0;
++ }
++ else
++ {
++ return -EFAULT;
++ }
++
++}
++
++static ssize_t show_device(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ int size = 0;
++ int rc;
++ unsigned char rbuf[8];
++
++ rc = zb_ReadConfiguration(zb,ZCD_NV_LOGICAL_TYPE,rbuf);
++ if(rc <= 0)
++ {
++ size = sprintf(buf,"Bad read. Try again\n");
++ }
++ switch(rbuf[Z_CONFIG_OFFSET])
++ {
++ case ZB_COORDINATOR:
++ size = sprintf(buf,"coordinator\n");
++ break;
++
++ case ZB_ROUTER:
++ size = sprintf(buf,"router\n");
++ break;
++
++ case ZB_ENDDEVICE:
++ size = sprintf(buf,"end-device\n");
++ break;
++
++ default:
++ size = sprintf(buf,"device-error\n");
++ break;
++ }
++ return size;
++}
++
++static ssize_t store_device(struct device *dev, struct device_attribute *attr, char *buf, size_t count)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ int size;
++ unsigned char device;
++
++ if(memcmp(buf, "coordinator",(count-1)) == 0)
++ {
++ printk(KERN_DEBUG "zb: config to coordinator\n");
++ device = ZB_COORDINATOR;
++ }
++ else if(memcmp(buf, "router",(count-1)) == 0)
++ {
++ printk(KERN_DEBUG "zb: config to router\n");
++ device = ZB_ROUTER;
++ }
++ else if(memcmp(buf, "end-device",(count-1)) == 0)
++ {
++ printk(KERN_DEBUG "zb: config to end-device\n");
++ device = ZB_ENDDEVICE;
++ }
++ else
++ {
++ printk(KERN_DEBUG "zb: invalid config\n");
++ size = sprintf(buf,"Invalid device. Try again\n");
++ return count;
++ }
++
++ if(zb_WriteConfiguration(zb,ZCD_NV_LOGICAL_TYPE,1,&device) != 0)
++ {
++ size = sprintf(buf,"Bad write. Try again\n");
++ }
++
++ return count;
++}
++
++static ssize_t store_chanlist(struct device *dev, struct device_attribute *attr, char *buf, size_t count)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ int size;
++ unsigned long chanlist;
++ unsigned char rbuf[4];
++
++ chanlist = simple_strtol(buf,NULL,16);
++ rbuf[0] = (unsigned char)(chanlist) & 0xFF;
++ rbuf[1] = (unsigned char)(chanlist >> 8) & 0xFF;
++ rbuf[2] = (unsigned char)(chanlist >> 16) & 0xFF;
++ rbuf[3] = (unsigned char)(chanlist >> 24) & 0xFF;
++
++ if(zb_WriteConfiguration(zb,ZCD_NV_CHANLIST,4,(unsigned char *)rbuf) != 0)
++ {
++ size = sprintf(buf,"Bad write. Try again\n");
++ }
++
++ return count;
++}
++
++static ssize_t show_chanlist(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ unsigned char rbuf[10];
++ int size = 0;
++ int rc;
++
++ rc = zb_ReadConfiguration(zb,ZCD_NV_CHANLIST,rbuf);
++ if(rc < 0)
++ {
++ size = sprintf(buf,"bad read. Try again\n");
++ }
++ else
++ {
++ size = sprintf(buf,"%0x ",rbuf[Z_CONFIG_OFFSET+3]);
++ size += sprintf((buf+size),"%0x ",rbuf[Z_CONFIG_OFFSET+2]);
++ size += sprintf((buf+size),"%0x ",rbuf[Z_CONFIG_OFFSET+1]);
++ size += sprintf((buf+size),"%0x\n",rbuf[Z_CONFIG_OFFSET]);
++ }
++ return size;
++}
++
++static ssize_t store_initop(struct device *dev, struct device_attribute *attr, char *buf, size_t count)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ unsigned char option;
++ int size;
++
++ option = (unsigned char)simple_strtol(buf,NULL,16);
++ option &= ZCD_STARTOPT_MASK;
++
++ if(zb_WriteConfiguration(zb,ZCD_NV_STARTUP_OPTION,1,(unsigned char *)&option) != 0)
++ {
++ size = sprintf(buf,"Bad write. Try again\n");
++ }
++
++ return count;
++}
++
++static ssize_t show_initop(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ unsigned char rbuf[10];
++ int size = 0;
++ int rc;
++
++ rc = zb_ReadConfiguration(zb,ZCD_NV_STARTUP_OPTION,(unsigned char *)&rbuf);
++ if(rc < 0)
++ {
++ size = sprintf(buf,"bad read. Try again\n");
++ }
++ else
++ {
++ size = sprintf(buf,"%0x\n",rbuf[Z_CONFIG_OFFSET]);
++ }
++
++ return size;
++}
++
++static ssize_t store_panid(struct device *dev, struct device_attribute *attr, char *buf, size_t count)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ unsigned short panid;
++ unsigned char rbuf[2];
++ int size;
++
++ panid = (unsigned short)simple_strtol(buf,NULL,16);
++ rbuf[0] = (unsigned char)(panid) & 0xFF;
++ rbuf[1] = (unsigned char)(panid >> 8) & 0xFF;
++
++ if(zb_WriteConfiguration(zb,ZCD_NV_PANID,2,(unsigned char *)rbuf) != 0)
++ {
++ size = sprintf(buf,"Bad write read. Try again\n");
++ }
++
++ printk(KERN_DEBUG "zb: config panid 0x%x\n",panid);
++ return count;
++}
++
++static ssize_t show_panid(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ unsigned char rbuf[10];
++ int size = 0;
++ int rc;
++
++ rc = zb_ReadConfiguration(zb,ZCD_NV_PANID,(unsigned char *)&rbuf);
++ if(rc < 0)
++ {
++ size = sprintf(buf,"bad read. Try again\n");
++ }
++ else
++ {
++ size = sprintf(buf,"%0x ",rbuf[Z_CONFIG_OFFSET+1]);
++ size += sprintf((buf+size),"%0x\n",rbuf[Z_CONFIG_OFFSET]);
++ }
++ return size;
++}
++
++static ssize_t show_zbinfo(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct net_device *net = to_net_dev(dev);
++ struct net_zb *priv = netdev_priv(net);
++ struct bmi_zb *zb = priv->zb;
++ struct zaccel_device *z_dev = &zb->z_info.device;
++ int size = 0;
++
++ zaccel_getdev(zb);
++
++ switch(z_dev->state)
++ {
++ case DEV_HOLD:
++ size = sprintf(buf,"DEV_HOLD\n");
++ break;
++
++ case DEV_INIT:
++ size = sprintf(buf,"DEV_INIT\n");
++ break;
++
++ case DEV_NWK_DISC:
++ size = sprintf(buf,"DEV_NWK_DISC\n");
++ break;
++
++ case DEV_NWK_JOINING:
++ size = sprintf(buf,"DEV_NWK_JOINING\n");
++ break;
++
++ case DEV_NWK_REJOIN:
++ size = sprintf(buf,"DEV_NWK_REJOIN\n");
++ break;
++
++ case DEV_END_DEVICE_UNAUTH:
++ size = sprintf(buf,"DEV_END_DEVICE_UNAUTH\n");
++ break;
++
++ case DEV_END_DEVICE:
++ size = sprintf(buf,"DEV_END_DEVICE\n");
++ break;
++
++ case DEV_ROUTER:
++ size = sprintf(buf,"DEV_ROUTER\n");
++ break;
++
++ case DEV_COORD_STARTING:
++ size = sprintf(buf,"DEV_COORD_STARTING\n");
++ break;
++
++ case DEV_ZB_COORD:
++ size = sprintf(buf,"DEV_ZB_COORD\n");
++ break;
++
++ case DEV_NWK_ORPHAN:
++ size = sprintf(buf,"DEV_NWK_ORHAN\n");
++ break;
++
++ default:
++ size = sprintf(buf,"UNKNOWN STATE %d\n",z_dev->state);
++ break;
++ }
++
++ size += sprintf((buf+size),"device IEEE address: %x:%x:%x:%x:%x:%x:%x:%x\n",
++ z_dev->device_ieee[7],z_dev->device_ieee[6],z_dev->device_ieee[5],
++ z_dev->device_ieee[4],z_dev->device_ieee[3],z_dev->device_ieee[2],
++ z_dev->device_ieee[1],z_dev->device_ieee[0]);
++ size += sprintf((buf+size),"device short address: 0x%x %x\n",
++ z_dev->device_short[1],z_dev->device_short[0]);
++ size += sprintf((buf+size),"parent short address: 0x%x %x\n",
++ z_dev->parent_short[1],z_dev->parent_short[0]);
++ size += sprintf((buf+size),"parent IEEE address: %x:%x:%x:%x:%x:%x:%x:%x\n",
++ z_dev->parent_ieee[7],z_dev->parent_ieee[6],z_dev->parent_ieee[5],
++ z_dev->parent_ieee[4],z_dev->parent_ieee[3],z_dev->parent_ieee[2],
++ z_dev->parent_ieee[1],z_dev->parent_ieee[0]);
++ size += sprintf((buf+size),"channel: 0x%0x\n",z_dev->channel);
++ size += sprintf((buf+size),"PAN ID: 0x%0x %0x\n",
++ z_dev->panid[1],z_dev->panid[0]);
++ size += sprintf((buf+size),"extended PAN ID: %x:%x:%x:%x:%x:%x:%x:%x\n",
++ z_dev->ext_panid[7],z_dev->ext_panid[6],z_dev->ext_panid[5],
++ z_dev->ext_panid[4],z_dev->ext_panid[3],z_dev->ext_panid[2],
++ z_dev->ext_panid[1],z_dev->ext_panid[0]);
++ return size;
++}
++
++
++DEVICE_ATTR(device, (S_IRUGO | S_IWUSR), show_device, store_device);
++DEVICE_ATTR(panid, (S_IRUGO | S_IWUSR), show_panid, store_panid);
++DEVICE_ATTR(chanlist, (S_IRUGO | S_IWUSR), show_chanlist, store_chanlist);
++DEVICE_ATTR(initop, (S_IRUGO | S_IWUSR), show_initop, store_initop);
++DEVICE_ATTR(zbinfo, S_IRUGO, show_zbinfo, NULL);
++
++void zb_create_sysfs(struct net_device *net)
++{
++ struct device *dev = &(net->dev);
++
++ if(device_create_file(dev,&dev_attr_device) < 0)
++ printk(KERN_WARNING "zb: failed to create device attribute\n");
++
++ if(device_create_file(dev,&dev_attr_panid) < 0)
++ printk(KERN_WARNING "zb: failed to create panid attribute\n");
++
++ if(device_create_file(dev,&dev_attr_chanlist) < 0)
++ printk(KERN_WARNING "zb: failed to create chanlist attribute\n");
++
++ if(device_create_file(dev,&dev_attr_initop) < 0)
++ printk(KERN_WARNING "zb: failed to create initop attribute\n");
++
++ if(device_create_file(dev,&dev_attr_zbinfo) < 0)
++ printk(KERN_WARNING "zb: failed to create zinfo attribute\n");
++}
++
++void zb_remove_sysfs(struct net_device *net)
++{
++ struct device *dev = &(net->dev);
++
++ device_remove_file(dev,&dev_attr_device);
++ device_remove_file(dev,&dev_attr_panid);
++ device_remove_file(dev,&dev_attr_chanlist);
++ device_remove_file(dev,&dev_attr_initop);
++ device_remove_file(dev,&dev_attr_zbinfo);
++}
++
+--- /dev/null
++++ git/drivers/bmi/pims/zb/bmi_zprotocol.c
+@@ -0,0 +1,619 @@
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/net.h>
++#include <linux/inet.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++
++#include <net/inet_common.h>
++#include <linux/bmi/bmi_zb.h>
++#include "bmi_zigbee.h"
++
++HLIST_HEAD(zaccel_list);
++DEFINE_RWLOCK(zaccel_list_lock);
++
++struct zaccel_sock {
++ struct sock sk;
++ struct packet_type zpacket_type;
++ spinlock_t bind_lock;
++ struct sockaddr_zb sockaddr;
++ struct net_device *dev;
++
++};
++
++static inline struct zaccel_sock *z_sk(struct sock *sk)
++{
++ return (struct zaccel_sock *)sk;
++}
++
++static void zaccel_sock_destruct(struct sock *sk)
++{
++ if(!sock_flag(sk,SOCK_DEAD)) {
++ printk("Attempt to release alive packet socket: %p\n",sk);
++ return;
++ }
++
++ sk_refcnt_debug_dec(sk);
++}
++
++static int z_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
++{
++ struct sock *sk;
++ struct zaccel_sock *zsock;
++ struct sockaddr_zb *zaddr;
++
++ printk("z_packet_getname\n");
++ zaddr = (struct sockaddr_zb *)uaddr;
++
++ sk = sock->sk;
++ zsock = z_sk(sk);
++
++ if(zsock->dev == 0)
++ {
++
++ printk(KERN_WARNING "sock not bound \n");
++ /* the socket is not bound */
++ return -ENODATA;
++ }
++
++ zaddr->z_family = AF_ZACCEL;
++ zaddr->z_ifindex = zsock->sockaddr.z_ifindex;
++ zaddr->z_protocol = zsock->sockaddr.z_protocol;
++ memcpy(&zaddr->z_name, &zsock->sockaddr.z_name, 15);
++
++ *uaddr_len = sizeof(struct sockaddr_zb);
++ return 0;
++
++}
++
++static struct proto zaccel_proto = {
++ .name = "Z_PACKET",
++ .owner = THIS_MODULE,
++ .obj_size = sizeof(struct zaccel_sock),
++};
++
++static int z_control_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
++{
++ struct sock *sk;
++
++ sk = pt->af_packet_priv;
++
++ /* put packet in receive queue */
++ if(sock_queue_rcv_skb(sk,skb) == 0)
++ {
++ return 0;
++ }
++
++ printk(KERN_WARNING "z_control_rcv drop\n");
++ kfree_skb(skb);
++ return 0;
++
++}
++
++static int z_packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
++{
++ struct sock *sk;
++
++ sk = pt->af_packet_priv;
++
++ /*
++ * put the packet in the receive queue.
++ */
++
++ if(sock_queue_rcv_skb(sk,skb) == 0)
++ {
++ return 0;
++ }
++
++ printk(KERN_WARNING "z_packet_rcv drop\n");
++ kfree_skb(skb);
++ return 0;
++}
++
++/*
++ * Pull a packet from our recieve queue and hand it to the user.
++ */
++
++static int z_recvmsg(struct kiocb *iocb, struct socket *sock,
++ struct msghdr *msg, size_t len, int flags)
++{
++ struct sock *sk;
++ struct sk_buff *skb;
++ int skb_len;
++ struct net_device *dev;
++ struct zaccel_sock *zsock;
++ int ifindex;
++ int err;
++
++ err = -EINVAL;
++ if(flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
++ {
++ goto out;
++ }
++
++ sk = sock->sk;
++
++ zsock = z_sk(sk);
++
++ ifindex = zsock->sockaddr.z_ifindex;
++
++ dev = dev_get_by_index(&init_net, ifindex);
++ if(dev == NULL)
++ {
++ printk(KERN_WARNING "bmi_zprotocol: dev not found\n");
++ return (-ENXIO);
++ }
++
++ if(!(dev->flags & IFF_UP))
++ {
++ printk("interface not up %d\n",(-ENETDOWN));
++ dev_put(dev);
++ return -ENETDOWN;
++ }
++
++ dev_put(dev);
++
++ /*
++ * Get a datagram skbuff
++ */
++ skb = skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
++
++ if(skb == NULL)
++ {
++ goto out;
++ }
++
++ /*
++ * If the input buffer is smaller than the message, truncate
++ * it. The user loses any data beyond it.
++ */
++ skb_len = skb->len;
++ if(skb_len > len)
++ {
++ skb_len = len;
++ msg->msg_flags |= MSG_TRUNC;
++ }
++
++ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, skb_len);
++ if(err)
++ goto out_free;
++
++ sock_recv_timestamp(msg, sk, skb);
++
++ /* err returns data length if the copy is successful */
++ err = skb_len;
++
++out_free:
++ skb_free_datagram(sk,skb);
++
++out:
++ return err;
++}
++
++static int z_sendmsg(struct kiocb *iocb, struct socket *sock,
++ struct msghdr *msg, size_t len)
++{
++ struct sock *sk = sock->sk;
++ struct sk_buff *skb;
++ struct net_device *dev;
++ struct zaccel_sock *zsock;
++ int ifindex;
++ int err;
++
++ zsock = z_sk(sk);
++
++ if(zsock->zpacket_type.type == Z_CONTROL_SOCK)
++ {
++ return -EPROTOTYPE;
++ }
++
++ ifindex = zsock->sockaddr.z_ifindex;
++
++ dev = dev_get_by_index(&init_net, ifindex);
++ if(dev == NULL)
++ {
++ printk(KERN_WARNING "bmi_zprotocol: dev not found\n");
++ dev_put(dev);
++ return (-ENXIO);
++ }
++
++ if(!(dev->flags & IFF_UP))
++ {
++ printk(KERN_WARNING "bmi_zprotocol: interface not up %d\n",(-ENETDOWN));
++ dev_put(dev);
++ return -ENETDOWN;
++ }
++
++ if(len > 92)
++ {
++ /* message is too long */
++ dev_put(dev);
++ return -EINVAL;
++ }
++
++ skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
++ if(skb == NULL)
++ {
++ dev_put(dev);
++ printk(KERN_WARNING "bmi_zprotocol: sock_allock_send_skb failed %d\n",err);
++ return -ENOMEM;
++ }
++
++ err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
++ if(err)
++ {
++ kfree_skb(skb);
++ dev_put(dev);
++ return -EFAULT;
++ }
++
++ skb->dev = dev;
++
++ /*
++ * dev_queue_xmit sends the packet directly to the driver.
++ */
++
++ err = dev_queue_xmit(skb);
++ if (err > 0)
++ {
++ kfree_skb(skb);
++ printk(KERN_WARNING "bmi_zprotocol: dev_queue_xmit failed %d\n",err);
++ dev_put(dev);
++ return(-ENETDOWN);
++ }
++
++ dev_put(dev);
++ return(len);
++}
++
++
++static int z_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
++{
++ struct sock *sk = sock->sk;
++ char name[15];
++ struct net_device *dev;
++ struct sockaddr_zb *z_addr;
++ struct zaccel_sock *zsock;
++ struct net_zb *priv;
++ unsigned char type;
++ int rc;
++
++ z_addr = (struct sockaddr_zb *)uaddr;
++
++ /* Get the name of the device */
++ strlcpy(name,z_addr->z_name,sizeof(name));
++
++ rc = (int)strlen(name);
++ if(rc > 3)
++ {
++ return -EINVAL;
++ }
++
++ if(memcmp(name,"zb",2))
++ {
++ printk(KERN_WARNING "bmi_zprotocol: invalid name %s\n",name);
++ return -EINVAL;
++ }
++
++ if((name[2] < 0x31) && (name[2] > 0x34))
++ {
++ printk(KERN_WARNING "bmi_zprotocol: invalid slot %c\n",name[2]);
++ return -EINVAL;
++ }
++
++
++ zsock = z_sk(sk);
++ type = zsock->zpacket_type.type;
++
++ /* search for the network interface by name */
++ dev = dev_get_by_name(&init_net, name);
++
++ /*
++ * check if the device has been bound to this socket type.
++ * If it has, return with error.
++ */
++
++ priv = netdev_priv(dev);
++ if(priv->socket[type] != Z_NO_SOCK)
++ {
++ dev_put(dev);
++ return -EISCONN;
++ }
++
++ if(dev)
++ {
++ lock_sock(sk);
++ spin_lock(&zsock->bind_lock);
++
++ if(zsock->dev && (zsock->dev != dev))
++ {
++ /* This socket was bound. Unbind it first. */
++ printk(KERN_INFO "unbound to previous device\n");
++ __sock_put(sk);
++
++ priv = netdev_priv(zsock->dev);
++ priv->socket[type] = Z_NO_SOCK;
++
++ zsock->dev = NULL;
++ spin_unlock(&zsock->bind_lock);
++ dev_remove_pack(&zsock->zpacket_type);
++ spin_lock(&zsock->bind_lock);
++ }
++
++ zsock->zpacket_type.dev = dev;
++ zsock->zpacket_type.af_packet_priv = sk;
++
++ /* socket-dev information used by sendmsg */
++ zsock->sockaddr.z_ifindex = dev->ifindex;
++ strlcpy(zsock->sockaddr.z_name,name,15);
++
++ zsock->dev = dev;
++
++ /* Add a packet handler to the networking stack. */
++ dev_add_pack(&zsock->zpacket_type);
++ /* increment sk_refcnt */
++ sock_hold(sk);
++
++ /* Tell the device that it is bound to a socket */
++ priv = netdev_priv(dev);
++ priv->socket[type] = 1;
++
++ spin_unlock(&zsock->bind_lock);
++ release_sock(sk);
++ dev_put(dev);
++ return 0;
++ }
++ else
++ {
++ printk(KERN_WARNING "zb: dev %s not found\n",name);
++ return -ENODEV;
++ }
++}
++
++static int z_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
++{
++ int rc;
++
++ switch(cmd)
++ {
++ case SIOCGIFFLAGS:
++ case SIOCGIFNAME:
++ case SIOCGIFMTU:
++ case SIOCGIFINDEX:
++ case SIOCETHTOOL:
++ case SIOCSIFNAME:
++ case SIOCSIFFLAGS:
++ case SIOCSIFMTU:
++ /*
++ * return -ENOIOCTLCMD to sock_ioctl
++ * sock_ioctl will call dev_ioctl to take care of these cmds.
++ */
++ rc = -ENOIOCTLCMD;
++ break;
++ default:
++ rc = 0;
++ break;
++ }
++
++ return rc;
++}
++
++static int z_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
++{
++ struct sock *sk = sock->sk;
++ struct zaccel_sock *zsock;
++ unsigned char buf[135]; /* 128 data + 6 fixed header + 1 just in case */
++
++ zsock = z_sk(sk);
++
++ if(!zsock->dev)
++ {
++ printk(KERN_WARNING "bmi_zprotocol: device not attached\n");
++ /*
++ * socket has no device attached
++ */
++ return -ENOTCONN;
++ }
++
++ if(level != SOL_ZACCEL)
++ {
++ return -ENOPROTOOPT;
++ }
++
++ if(optlen > 135)
++ {
++ return -EINVAL;
++ }
++
++ if(copy_from_user(buf,optval,optlen))
++ {
++ return -EFAULT;
++ }
++
++ if(zdev_setopt(zsock->dev,optname,optlen,buf))
++ {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int z_getsockopt(struct socket *sock, int level, int optname,
++ char __user *optval, int __user *optlen)
++
++{
++ struct sock *sk = sock->sk;
++ struct zaccel_sock *zsock;
++ unsigned char buf[135]; /* 128 data + 6 fixed header + 1 just in case */
++ int len;
++ int rc;
++
++ zsock = z_sk(sk);
++
++ if(!zsock->dev)
++ {
++ /* socket has no device attached */
++ return -ENOTCONN;
++ }
++
++ if(level != SOL_ZACCEL)
++ return -ENOPROTOOPT;
++
++ rc = zdev_getopt(zsock->dev,optname,&len,buf);
++
++ if(!rc)
++ {
++ if(put_user(len, optlen))
++ return -EFAULT;
++ /* Include 3 header bytes to the message */
++ if(copy_to_user(optval, buf, (len+3)))
++ return -EFAULT;
++ }
++
++ return rc;
++
++}
++
++static int z_release(struct socket *sock)
++{
++ struct sock *sk;
++ struct zaccel_sock *zsock;
++ struct net_zb *priv;
++
++ sk = sock->sk;
++
++ if(!sk)
++ return 0;
++
++ zsock = z_sk(sk);
++
++ write_lock_bh(&zaccel_list_lock);
++ sk_del_node_init(sk);
++ write_unlock_bh(&zaccel_list_lock);
++
++ if(zsock->dev)
++ {
++ priv = netdev_priv(zsock->dev);
++ priv->socket[zsock->zpacket_type.type] = Z_NO_SOCK;
++
++ /* remove protocol handler */
++ dev_remove_pack(&zsock->zpacket_type);
++ __sock_put(sk);
++ }
++
++ /* detach socket from process context */
++ sock_orphan(sk);
++ sock->sk = NULL;
++
++ /* Purge queues */
++ skb_queue_purge(&sk->sk_receive_queue);
++
++ sk_refcnt_debug_release(sk);
++
++ sock_put(sk);
++ return 0;
++}
++
++static const struct proto_ops z_protocol_ops = {
++ .family = PF_ZACCEL,
++ .owner = THIS_MODULE,
++ .release = z_release,
++ .bind = z_bind,
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .accept = sock_no_accept,
++ .getname = z_getname,
++ .poll = sock_no_poll,
++ .ioctl = z_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .setsockopt = z_setsockopt,
++ .getsockopt = z_getsockopt,
++ .sendmsg = z_sendmsg,
++ .recvmsg = z_recvmsg,
++ .mmap = sock_no_mmap,
++ .sendpage = sock_no_sendpage,
++};
++
++int z_protocol_create(struct net *net, struct socket *sock, int protocol)
++{
++ struct sock *sk;
++ struct zaccel_sock *zsock;
++
++ if (net != &init_net)
++ {
++ return -EAFNOSUPPORT;
++ }
++
++ sock->state = SS_UNCONNECTED;
++ if(sock->type != SOCK_RAW)
++ {
++ return -ESOCKTNOSUPPORT;
++ }
++
++ sock->ops = &z_protocol_ops;
++
++ sk = sk_alloc(net, AF_ZACCEL, GFP_KERNEL, &zaccel_proto);
++ if(sk == NULL)
++ {
++ return -ENOMEM;
++ }
++
++ sock_init_data(sock, sk);
++ sk->sk_protocol = protocol;
++ sk->sk_family = PF_ZACCEL;
++ sk->sk_destruct = zaccel_sock_destruct;
++ sk_refcnt_debug_inc(sk);
++
++ zsock = z_sk(sk);
++
++ spin_lock_init(&zsock->bind_lock);
++
++ if(protocol == Z_CONTROL_SOCK)
++ {
++ zsock->zpacket_type.func = z_control_rcv;
++ zsock->zpacket_type.type = Z_CONTROL_SOCK;
++ sk->sk_protocol = Z_CONTROL_SOCK;
++ }
++ else
++ {
++ zsock->zpacket_type.func = z_packet_rcv;
++ zsock->zpacket_type.type = Z_PACKET_SOCK;
++ sk->sk_protocol = Z_PACKET_SOCK;
++ }
++ zsock->zpacket_type.af_packet_priv = sk;
++ zsock->zpacket_type.dev = NULL;
++
++ zsock->dev = NULL;
++
++ /* Add a socket to the bound sockets list */
++ write_lock_bh(&zaccel_list_lock);
++ sk_add_node(sk,&zaccel_list);
++ write_unlock_bh(&zaccel_list_lock);
++
++ return 0;
++
++}
++
++static struct net_proto_family zaccel_family_ops = {
++ .family = PF_ZACCEL,
++ .create = z_protocol_create,
++ .owner = THIS_MODULE,
++};
++
++void z_sock_exit(void)
++{
++ sock_unregister(PF_ZACCEL);
++}
++
++int z_sock_init(void)
++{
++ int res;
++
++ res = sock_register(&zaccel_family_ops);
++ if(res) {
++ printk(KERN_WARNING "Failed to register PF_ZACCEL\n");
++ }
++
++ return res;
++}
+--- /dev/null
++++ git/drivers/bmi/slots/Kconfig
+@@ -0,0 +1,21 @@
++#
++# BMI Slot Drivers
++#
++
++menu "BMI Hardware Slot support"
++
++config BUG_SLOT
++ tristate "Buglabs BUGBase BMI Slots"
++ default 'n'
++ depends on BMI && MACH_BUG
++ help
++ If you say yes to this option, support will be included for the Buglabs BUGBase BMI Slot/Module Ports.
++
++config OMAP_SLOT
++ tristate "TI BeagBoard BMI Slots"
++ default 'n'
++ depends on BMI
++ help
++ If you say yes to this option, support will be included for the BeagleBoard Slot.
++
++endmenu
+--- /dev/null
++++ git/drivers/bmi/slots/Makefile
+@@ -0,0 +1,6 @@
++#
++# Makefile for BMI Slot drivers
++#
++
++obj-$(CONFIG_BUG_SLOT) += slots_bug.o
++obj-$(CONFIG_OMAP_SLOT) += slots_beagle.o
+--- /dev/null
++++ git/drivers/bmi/slots/slots_beagle.c
+@@ -0,0 +1,267 @@
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/gpio.h>
++#include <linux/irq.h>
++#include <linux/bmi.h>
++
++#include <mach/board.h>
++
++#define BMI_GPIO_0 139
++#define BMI_GPIO_1 158
++#define BMI_GPIO_2 137
++#define BMI_GPIO_3 136
++
++static int bl_present(struct bmi_slot* slot)
++{
++ unsigned gpio = irq_to_gpio(slot->present_irq);
++ if (gpio_get_value(gpio))
++ return 0;
++ else
++ return 1;
++}
++
++static void bl_power_on(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_power_off(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_gpio_config(struct bmi_slot* slot, int mask) /*Configure gpios as inputs/ouputs*/
++{
++ int i;
++
++ unsigned char *gpio = (unsigned char*) slot->slot_data;
++
++ for (i = 0; i < 4 ; i++)
++ {
++ if ((mask >> i) & 0x1)
++ gpio_direction_output(gpio[i], 0);
++ else
++ gpio_direction_input(gpio[i]);
++ }
++ return;
++}
++
++static int bl_gpio_get(struct bmi_slot* slot)
++{
++ int i;
++ unsigned char *gpio = (unsigned char*) slot->slot_data;
++ unsigned char ret = 0;
++
++ for (i = 3; i > -1 ; i--)
++ {
++ ret = (ret << 1) | gpio_get_value(gpio[i]);
++ }
++
++ return ret;
++}
++
++static void bl_gpio_set(struct bmi_slot* slot, int mask)
++{
++ int i;
++ unsigned char *gpio = (unsigned char*) slot->slot_data;
++
++ for (i = 0; i < 4 ; i++)
++ {
++ if ((mask >> i) & 0x1)
++ gpio_set_value(gpio[i], 1);
++ else
++ gpio_set_value(gpio[i], 0);
++ }
++ return;
++}
++
++static void bl_uart_enable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_uart_disable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_spi_enable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_spi_disable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_audio_enable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_audio_disable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_batt_enable(struct bmi_slot* slot)
++{
++ return;
++}
++
++static void bl_batt_disable(struct bmi_slot* slot)
++{
++ return;
++}
++
++
++struct slot_actions bl_actions = {
++ .present = bl_present,
++ .power_on = bl_power_on,
++ .power_off = bl_power_off,
++ .gpio_config = bl_gpio_config,
++ .gpio_get = bl_gpio_get,
++ .gpio_set = bl_gpio_set,
++ .uart_enable = bl_uart_enable,
++ .uart_disable = bl_uart_disable,
++ .spi_enable = bl_spi_enable,
++ .spi_disable = bl_spi_disable,
++ .audio_enable = bl_audio_enable,
++ .audio_disable = bl_audio_disable,
++ .batt_enable = bl_batt_enable,
++ .batt_disable = bl_batt_disable,
++};
++
++static int omapbmi_slot_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ return 0;
++}
++
++static int omapbmi_slot_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static int omapbmi_slot_probe(struct platform_device *pdev)
++{
++ struct bmi_slot *slot;
++ struct resource *irq_pres, *irq_stat;
++ // struct omap_bmi_platform_data *bmi_plat_data = pdev->dev.platform_data;
++ int ret = 0;
++ unsigned char* gpio;
++
++ printk(KERN_INFO "Buglabs BeagleBUG Slots Driver...\n");
++ irq_pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!irq_pres) {
++ dev_err(&pdev->dev, "No presence irq resource...\n");
++ return -ENODEV;
++ }
++ irq_stat = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
++ if (!irq_stat) {
++ dev_err(&pdev->dev, "No status irq resource...\n");
++ return -ENODEV;
++ }
++
++ slot = kzalloc(sizeof(struct bmi_slot), GFP_KERNEL);
++ if (!slot) {
++ ret = -ENOMEM;
++ goto err_release;
++ }
++
++ ret = gpio_request(irq_stat->start, "BMI SINT");
++ if (ret) {
++ printk(KERN_ERR "slots_beagle: GPIO %d request failed...\n",irq_stat->start);
++ goto err_release;
++ }
++ ret = gpio_request(irq_pres->start, "BMI PINT");
++ if (ret) {
++ printk(KERN_ERR "slots_beagle: GPIO %d request failed...\n",irq_pres->start);
++ goto err_release;
++ }
++
++ ret = gpio_direction_input(irq_pres->start);
++
++ gpio = kmalloc(4, GFP_KERNEL);
++ gpio_request(139,"BMI_0");
++ gpio_request(158,"BMI_1");
++ gpio_request(137,"BMI_2");
++ gpio_request(136,"BMI_3");
++
++ gpio[0] = 139;
++ gpio[1] = 158;
++ gpio[2] = 137;
++ gpio[3] = 136;
++
++ slot->slot_data = (void*)gpio;
++ slot->present_irq = gpio_to_irq(irq_pres->start);
++ slot->status_irq = gpio_to_irq(irq_stat->start);
++ slot->owner = THIS_MODULE;
++ slot->name = "omap_bug_slot";
++ slot->slotdev.parent = &pdev->dev;
++ slot->adap = i2c_get_adapter(3);
++ slot->actions = &bl_actions;
++ slot->spi_bus_num = 3;
++ slot->spi_cs = 0;
++
++
++ ret = bmi_add_slot(slot);
++ if (ret) {
++ printk(KERN_ERR "slots_beagle: Trouble instantiating slot...%d\n", ret);
++ goto err_release;
++ }
++ return 0;
++ err_release:
++ kfree(slot->slot_data);
++ kfree(slot);
++ return ret;
++}
++
++static int omapbmi_slot_remove(struct platform_device *pdev)
++{
++ struct bmi_slot *slot = platform_get_drvdata(pdev);
++ //int id = pdev->id;
++
++ bmi_del_slot(slot);
++ platform_set_drvdata(pdev, NULL);
++ kfree(slot->slot_data);
++ kfree(slot);
++ return 0;
++}
++
++
++static struct platform_driver omapbmi_slot_driver = {
++ .driver = {
++ .name = "omap_bmi_slot",
++ .owner = THIS_MODULE,
++ },
++ .probe = omapbmi_slot_probe,
++ .remove = omapbmi_slot_remove,
++ .suspend = omapbmi_slot_suspend,
++ .resume = omapbmi_slot_resume,
++};
++
++static int __init omap_bmi_slot_init(void)
++{
++ /* Register the device driver structure. */
++ return platform_driver_register(&omapbmi_slot_driver);
++}
++
++/*!
++ * This function is used to cleanup all resources before the driver exits.
++ */
++static void __exit omap_bmi_slot_exit(void)
++{
++ platform_driver_unregister(&omapbmi_slot_driver);
++}
++
++module_init(omap_bmi_slot_init);
++module_exit(omap_bmi_slot_exit);
++
++MODULE_AUTHOR("Matt Isaacs");
++MODULE_DESCRIPTION("OMAP BMI Slot Driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/drivers/bmi/slots/slots_bug.c
+@@ -0,0 +1,231 @@
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/bmi.h>
++
++#include <mach/mx31bug_cpld.h>
++//#include <mach/mx31bug_gpio.h>
++#include <mach/board-bugbase.h>
++
++static int bl_present(struct bmi_slot* slot)
++{
++ int status;
++
++ status = cpld_read_module_present_status(slot->slotnum);
++ if (status & 0x04)
++ return 1;
++ else
++ return 0;
++}
++
++static void bl_power_on(struct bmi_slot* slot)
++{
++ //gpio_power_on_slot (slot->slotnum);
++ return;
++}
++
++static void bl_power_off(struct bmi_slot* slot)
++{
++ //gpio_power_off_slot (slot->slotnum);
++ return;
++}
++
++static void bl_gpio_config(struct bmi_slot* slot, int mask) /*Configure gpios as inputs/ouputs*/
++{
++ int i;
++ for (i = 0; i < 4; i++) {
++ cpld_set_module_gpio_dir(slot->slotnum, i, (mask & 0x1));
++ mask = mask >> 1;
++ }
++ return;
++}
++
++static int bl_gpio_get(struct bmi_slot* slot)
++{
++ return cpld_read_gpio_data_reg(slot->slotnum);
++}
++
++static void bl_gpio_set(struct bmi_slot* slot, int mask)
++{
++ int i;
++ for (i = 0; i < 4; i++) {
++ cpld_set_module_gpio_data(slot->slotnum, i, (mask & 0x1));
++ mask = mask >> 1;
++ }
++ return;
++}
++
++static void bl_uart_enable(struct bmi_slot* slot)
++{
++ cpld_uart_active(slot->slotnum);
++ return;
++}
++
++static void bl_uart_disable(struct bmi_slot* slot)
++{
++ cpld_uart_inactive(slot->slotnum);
++ return;
++}
++
++static void bl_spi_enable(struct bmi_slot* slot)
++{
++ //REVIST:
++ cpld_spi_active(0);
++ return;
++}
++
++static void bl_spi_disable(struct bmi_slot* slot)
++{
++ //REVIST:
++ cpld_spi_inactive(0);
++ return;
++}
++
++static void bl_audio_enable(struct bmi_slot* slot)
++{
++ cpld_activate_audio_ports();
++ return;
++}
++
++static void bl_audio_disable(struct bmi_slot* slot)
++{
++ cpld_inactivate_audio_ports();
++ return;
++}
++
++static void bl_batt_enable(struct bmi_slot* slot)
++{
++ cpld_set_module_battery_enable(slot->slotnum);
++ return;
++}
++
++static void bl_batt_disable(struct bmi_slot* slot)
++{
++ cpld_set_module_battery_disable(slot->slotnum);
++ return;
++}
++
++/*
++static int mxcbmi_probe(struct platform_device *pdev);
++static int mxcbmi_slot_remove(struct platform_device *pdev);
++static int mxcbmi_suspend(struct platform_device *pdev, pm_message_t state);
++static int mxcbmi_resume(struct platform_device *pdev);
++*/
++
++struct slot_actions bl_actions = {
++ .present = bl_present,
++ .power_on = bl_power_on,
++ .power_off = bl_power_off,
++ .gpio_config = bl_gpio_config,
++ .gpio_get = bl_gpio_get,
++ .gpio_set = bl_gpio_set,
++ .uart_enable = bl_uart_enable,
++ .uart_disable = bl_uart_disable,
++ .spi_enable = bl_spi_enable,
++ .spi_disable = bl_spi_disable,
++ .audio_enable = bl_audio_enable,
++ .audio_disable = bl_audio_disable,
++ .batt_enable = bl_batt_enable,
++ .batt_disable = bl_batt_disable,
++};
++
++static int mxcbmi_slot_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ return 0;
++}
++
++static int mxcbmi_slot_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static int mxcbmi_slot_probe(struct platform_device *pdev)
++{
++ struct bmi_slot *slot;
++ struct resource *res, *irq_pres, *irq_stat;
++ struct mxc_bmi_platform_data *bmi_plat_data = pdev->dev.platform_data;
++ int ret = 0;
++
++ printk(KERN_INFO "Buglabs BUGBase Slots Driver...\n");
++ irq_pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!irq_pres) {
++ dev_err(&pdev->dev, "No presence irq resource...\n");
++ return -ENODEV;
++ }
++ irq_stat = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
++ if (!irq_stat) {
++ dev_err(&pdev->dev, "No status irq resource...\n");
++ return -ENODEV;
++ }
++
++ slot = kzalloc(sizeof(struct bmi_slot), GFP_KERNEL);
++ if (!slot) {
++ ret = -ENOMEM;
++ goto err_release;
++ }
++
++
++ slot->present_irq = irq_pres->start;
++ slot->status_irq = irq_stat->start;
++ slot->owner = THIS_MODULE;
++ slot->name = "mxc_bug_slot";
++ slot->slotdev.parent = &pdev->dev;
++ slot->adap = i2c_get_adapter(2 + pdev->id);
++ slot->actions = &bl_actions;
++ slot->spi_bus_num = 1;
++ slot->spi_cs = pdev->id;
++ ret = bmi_add_slot(slot);
++ if (ret) {
++ printk(KERN_ERR "slots_bug: Trouble instantiating slot...%d\n", ret);
++ goto err_release;
++ }
++ ret = 0;
++ err_release:
++ return ret;
++}
++
++static int mxcbmi_slot_remove(struct platform_device *pdev)
++{
++ struct bmi_slot *slot = platform_get_drvdata(pdev);
++ //int id = pdev->id;
++
++ bmi_del_slot(slot);
++ platform_set_drvdata(pdev, NULL);
++ kfree(slot);
++ return 0;
++}
++
++
++static struct platform_driver mxcbmi_slot_driver = {
++ .driver = {
++ .name = "mxc_bmi_slot",
++ .owner = THIS_MODULE,
++ },
++ .probe = mxcbmi_slot_probe,
++ .remove = mxcbmi_slot_remove,
++ .suspend = mxcbmi_slot_suspend,
++ .resume = mxcbmi_slot_resume,
++};
++
++static int __init mxc_bmi_slot_init(void)
++{
++ /* Register the device driver structure. */
++ return platform_driver_register(&mxcbmi_slot_driver);
++}
++
++/*!
++ * This function is used to cleanup all resources before the driver exits.
++ */
++static void __exit mxc_bmi_slot_exit(void)
++{
++ platform_driver_unregister(&mxcbmi_slot_driver);
++}
++
++module_init(mxc_bmi_slot_init);
++module_exit(mxc_bmi_slot_exit);
++
++MODULE_AUTHOR("Matt Isaacs");
++MODULE_DESCRIPTION("MXC BMI Slot Driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ git/include/linux/bmi-ids.h
+@@ -0,0 +1,30 @@
++/*
++ * BMI Vendor and Product IDs
++ *
++ * Please keep sorted.
++ */
++
++/* BMI vendors */
++
++#define BMI_VENDOR_ILLEGAL_0 0x0
++#define BMI_VENDOR_BUG_LABS 0x1
++#define BMI_VENDOR_ILLEGAL_F 0xFFFF
++
++
++/* BMI products */
++
++#define BMI_PRODUCT_ILLEGAL_0 0x0000
++#define BMI_PRODUCT_GPS_J32 0x0001
++#define BMI_PRODUCT_MOT_ACCEL 0x0002
++#define BMI_PRODUCT_LCD_SHARP_320X240 0x0003
++#define BMI_PRODUCT_CAMERA_VS6624 0x0004
++#define BMI_PRODUCT_CAMERA_OV2640 0x0005
++#define BMI_PRODUCT_FACTORY_TEST 0x0006
++#define BMI_PRODUCT_VON_HIPPEL 0x0007
++#define BMI_PRODUCT_WIFI 0x0008
++#define BMI_PRODUCT_ZIGBEE 0x0009
++#define BMI_PRODUCT_AUDIO 0x000A
++#define BMI_PRODUCT_GSM 0x000B
++#define BMI_PRODUCT_PROJECTOR 0x000C
++#define BMI_PRODUCT_ILLEGAL_F 0xFFFF
++
+--- /dev/null
++++ git/include/linux/bmi.h
+@@ -0,0 +1,142 @@
++#ifndef __LINUX_BMI_H
++#define __LINUX_BMI_H
++
++#include <linux/bmi-ids.h>
++#include <linux/bmi/bmi-eeprom.h>
++#include <linux/bmi/bmi-slot.h>
++#include <linux/device.h>
++#include <linux/i2c.h>
++#include <linux/mod_devicetable.h>
++#include <linux/mutex.h>
++#include <linux/spi/spi.h>
++
++
++/* BMI bus device table constants */
++#define BMI_ANY 0x0
++
++#define RED_LED 8
++#define GREEN_LED 4
++#define GPIO_1 2
++#define GPIO_0 1
++
++struct bmi_slot;
++
++struct slot_actions {
++ int (*present)(struct bmi_slot*);
++ void (*power_on)(struct bmi_slot*);
++ void (*power_off)(struct bmi_slot*);
++ void (*gpio_config)(struct bmi_slot*, int mask); /*Configure gpios as inputs/ouputs*/
++ int (*gpio_get)(struct bmi_slot*);
++ void (*gpio_set)(struct bmi_slot*, int mask);
++ void (*uart_enable)(struct bmi_slot*);
++ void (*uart_disable)(struct bmi_slot*);
++ void (*spi_enable)(struct bmi_slot*);
++ void (*spi_disable)(struct bmi_slot*);
++ void (*audio_enable)(struct bmi_slot*);
++ void (*audio_disable)(struct bmi_slot*);
++ void (*batt_enable)(struct bmi_slot*);
++ void (*batt_disable)(struct bmi_slot*);
++};
++
++struct bmi_slot {
++ int slotnum;
++ char* name;
++ struct bmi_device *bdev;
++ struct module *owner;
++ struct device slotdev;
++ struct kref kref;
++ struct mutex pres_mutex;
++ struct list_head event_list;
++ unsigned int event_bits[1];
++
++ int present;
++ struct i2c_adapter *adap;
++ struct i2c_client *eeprom;
++
++
++ // struct spi_device spi;
++ int spi_bus_num;
++ int spi_cs;
++
++ int present_irq;
++ int status_irq;
++ struct delayed_work work;
++ struct slot_actions* actions;
++
++ void* slot_data;
++
++};
++
++
++/* BMI Device */
++
++struct bmi_device {
++ int devnum;
++
++ struct device dev;
++
++ struct mutex lock;
++
++
++ int present_irq_cnt;
++ int state; /* Make this an enum */
++
++ struct bmi_slot *slot;
++
++ struct bmi_eeprom_data ident;
++ unsigned short vendor;
++ unsigned short product;
++ unsigned short revision;
++
++ struct bmi_driver *driver; /* which driver has allocated this device */
++
++};
++
++#define to_bmi_device(n) container_of(n, struct bmi_device, dev);
++#define work_to_slot(w) container_of(container_of(w, \
++ struct delayed_work, \
++ work), \
++ struct bmi_slot, \
++ work)
++
++
++static inline void *bmi_device_get_drvdata (struct bmi_device *bdev)
++{
++ return dev_get_drvdata (&bdev->dev);
++}
++
++static inline void bmi_device_set_drvdata (struct bmi_device *bdev, void *data)
++{
++ dev_set_drvdata(&bdev->dev, data);
++}
++
++
++/* BMI Driver */
++
++struct bmi_driver {
++
++ char *name;
++ struct bmi_device_id *id_table;
++ struct device_driver driver;
++ int (*probe)(struct bmi_device *dev);
++ void (*remove)(struct bmi_device *dev);
++};
++
++extern struct bus_type bmi_bus_type;
++
++#define to_bmi_driver(drv) container_of(drv,struct bmi_driver, driver)
++
++int __must_check __bmi_register_driver(struct bmi_driver *, struct module *);
++static inline int __must_check bmi_register_driver(struct bmi_driver *driver)
++{
++ return __bmi_register_driver(driver, THIS_MODULE);
++}
++
++void bmi_unregister_driver(struct bmi_driver *drv);
++
++struct bmi_device *bmi_alloc_dev(struct bmi_slot *slot);
++struct class* bmi_get_class (void);
++int bmi_add_slot(struct bmi_slot *slot);
++int bmi_del_slot(struct bmi_slot *slot);
++
++#endif
+--- /dev/null
++++ git/include/linux/bmi/at24c02.h
+@@ -0,0 +1,26 @@
++#include <linux/semaphore.h>
++#include <linux/i2c.h>
++
++/*--------------------------------
++ *
++ * AT24C02 I2C Eeprom Device
++ *
++ *--------------------------------
++ */
++
++
++struct at24c02 {
++
++ unsigned char addr;
++ struct i2c_adapter *adap;
++};
++
++void at24c02_init (struct at24c02 *dev, u8 addr, struct i2c_adapter *adap);
++
++int at24c02_read_byte ( struct at24c02 *dev, u8 offset, u8 *data);
++int at24c02_write_byte ( struct at24c02 *dev, u8 offset, u8 data);
++int at24c02_read ( struct at24c02 *dev, u8 offset, u8 *data, int size);
++int at24c02_write_page ( struct at24c02 *dev, u8 offset, u8 *data, int size);
++
++
++
+--- /dev/null
++++ git/include/linux/bmi/bmi-bus.h
+@@ -0,0 +1,21 @@
++#ifndef BMI_BUS_H
++#define BMI_BUS_H
++
++#include <linux/bmi.h>
++
++#define BMI_MAX_SLOTS 1
++
++struct bmi_bus {
++
++ struct bmi_device slot[BMI_MAX_SLOTS];
++};
++
++
++
++extern struct bus_type bmi_bus_type;
++
++struct bmi_device* bmi_get_bmi_device (int slot_num);
++
++
++#endif /* BMI_BUS_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi-control.h
+@@ -0,0 +1,303 @@
++/*
++ * Copyright 2007 EnCADIS Design, Inc. All Rights Reserved.
++ * Copyright 2007 Bug-Labs, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++#ifndef _BMI_CONTROL_H
++#define _BMI_CONTROL_H
++
++#define BMI_M1 (0x0)
++#define BMI_M2 (0x1)
++#define BMI_M3 (0x2)
++#define BMI_M4 (0x3)
++#define BMI_GPIO_IN (0x0)
++#define BMI_GPIO_OUT (0x1)
++#define BMI_GPIO_ON (0x1)
++#define BMI_GPIO_OFF (0x0)
++
++/*!
++ * This function configures the UART function for the IOMUX pins.
++ *
++ * @param port a UART port number (0-5)
++ * @param no_irda configure UART port for IRDA
++ */
++void bmi_gpio_uart_active(int port, int no_irda);
++
++/*!
++ * This function configures the UART function in the BMI.
++ *
++ * @param port a UART port number (0-5)
++ */
++void bmi_uart_active(int port);
++
++/*!
++ * This function configures the UART function in the BMI.
++ *
++ * @param port a UART port number (0-5)
++ */
++void bmi_uart_inactive(int port);
++
++/*!
++ * Setup GPIO for a CSPI device to be active
++ *
++ * @param cspi_mod an CSPI device
++ */
++void bmi_gpio_spi_active(int cspi_mod);
++
++/*!
++ * Setup BMI for a CSPI device to be active
++ *
++ * @param cspi_mod an CSPI device
++ */
++void bmi_spi_active(int cspi_mod);
++
++/*!
++ * Setup BMI for a CSPI device to be inactive
++ *
++ * @param cspi_mod an CSPI device
++ */
++void bmi_spi_inactive(int cspi_mod);
++
++/*!
++ * Setup GPIO for an I2C device to be active
++ *
++ * @param i2c_num an I2C device
++ */
++void bmi_gpio_i2c_active(int i2c_num);
++
++/*!
++ * Setup BMI for an I2C device to be active
++ */
++void bmi_i2c_active(void);
++
++/*!
++ * Setup BMI for an I2C device to be inactive
++ */
++void bmi_i2c_inactive(void);
++
++/*
++ * Setup GPIO for an I2S device to be active
++ */
++void bmi_gpio_activate_audio_ports(void);
++
++/*!
++ * Setup CPLD for an I2S device to be active
++ */
++void bmi_activate_audio_ports(void);
++
++/*!
++ * Setup CPLD for an I2S device to be inactive
++ */
++void bmi_inactivate_audio_ports(void);
++
++/*!
++ * Setup GPIO for the plug-in module LCD interface to be active
++ */
++void bmi_gpio_lcd_active(void);
++
++/*!
++ * Setup BMI for plug-in module LCD to be active
++ *
++ * @param port LCD serializer (0 or 1)
++ * @param pllc LCD serializer PLL divisor (0-7)
++ * @param mode LCD serializer bus mode (LCD_MODE_I80 or LCD_MODE_M68)
++ *
++ */
++void bmi_lcd_active(int port, int pllc, int mode);
++
++/*!
++ * Setup BMI for plug-in module LCD chip select to be active
++ *
++ * @param cs LCD chip select (LCD_MxCS x = 1,2,3,4)
++ *
++ */
++void bmi_lcd_cs_active(int cs);
++
++/*!
++ * Setup BMI for plug-in module LCD to be inactive
++ *
++ * @param port LCD serializer (0 or 1)
++ *
++ */
++void bmi_lcd_inactive(int port);
++
++/*!
++ * Setup BMI for plug-in module LCD chip select to be inactive
++ *
++ * @param cs LCD chip select (LCD_MxCS x = 1,2,3,4)
++ *
++ */
++void bmi_lcd_cs_inactive(int cs);
++
++/*!
++ * Setup pins for SLCD to be active
++ *
++ */
++void bmi_slcd_gpio_config(void);
++
++/*!
++ * Setup GPIO for sensor to be active
++ *
++ */
++void bmi_gpio_sensor_active(void);
++
++/*!
++ * Setup BMI for sensor to be active
++ *
++ * @param rclk_r pixclk edge (CAM_CLK_RISE or CAM_CLK_FALL)
++ */
++void bmi_sensor_active(int rclk_r);
++
++/*!
++ * Setup BMI for sensor to be inactive
++ */
++void bmi_sensor_inactive(void);
++
++/*!
++ * read BMI for sensor lock status
++ *
++ * @return camera serializer lock status (1 == locked)
++ */
++int bmi_sensor_lock_status(void);
++
++/*
++ * USB Host 2 GPIO config
++ *
++ * @return 0
++ */
++int bmi_gpio_usbh2_active(void);
++
++/*
++ * USB Host 2 BMI config
++ *
++ * @param mtt - number of MTT's enabled in hub (USB_HUB_1_MTT or USB_HUB_4_MTT)
++ */
++void bmi_usbh2_active(int mtt);
++
++/*
++ * USB Host 2 BMI config inactive
++ */
++void bmi_usbh2_inactive(void);
++
++/*
++ * configure BMI Module GPIO direction
++ *
++ * @param module plug-in module (BMI, x= 1,2,3,4)
++ * @param bit GPIO bit (0-3)
++ * @param dir GPIO bit (BMI_GPIO_IN or BMI_GPIO_OUT)
++ */
++void bmi_set_module_gpio_dir(int module, int bit, int dir);
++
++/*
++ * read BMI GPIO Direction register
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @return module GPIO direction (4 LSB)
++ */
++int bmi_read_gpio_direction_reg(int module);
++
++/*
++ * set BMI Module GPIO data
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @param bit GPIO bit (0-3)
++ * @param value GPIO bit (0x0 or 0x1)
++ */
++void bmi_set_module_gpio_data(int module, int bit, int value);
++
++/*
++ * read BMI GPIO Data register
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @return module GPIO data (4 LSB)
++ */
++int bmi_read_gpio_data_reg(int module);
++
++/*
++ * set BMI Module battery enable
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ */
++void bmi_set_module_battery_enable(int module);
++
++/*
++ * set BMI Module battery disable
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ */
++void bmi_set_module_battery_disable(int module);
++
++/*
++ * read BMI module battery status
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @return state of module battery status bit
++ */
++int bmi_read_module_battery_status(int module);
++
++/*
++ * set BMI interrupt enable
++ *
++ * @param interrupt interrupt (INT_BUGRTC .. INT_M4_PRES) (defined in mx31bug.h)
++ */
++void bmi_interrupt_enable(int interrupt);
++
++/*
++ * set BMI interrupt disable
++ *
++ * @param interrupt interrupt (INT_BUGRTC .. INT_M4_PRES) (defined in mx31bug.h)
++ */
++void bmi_interrupt_disable(int interrupt);
++
++/*
++ * get BMI interrupt status
++ *
++ * @param interrupt interrupt (INT_BUGRTC .. INT_M4_PRES) (defined in mx31bug.h)
++ * @return 1 if set, 0 otherwise
++ */
++int bmi_interrupt_status(int interrupt);
++
++/*
++ * clear BMI module present interrupt bit
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ */
++void bmi_clear_module_present_interrupt(int module);
++
++/*
++ * enable I2C switches in BMI
++ */
++void bmi_i2c_sw_enable(void);
++
++/*
++ * disable I2C switches in BMI
++ */
++void bmi_i2c_sw_disable(void);
++
++/*
++ * read BMI module present status
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @return module present status (3 LSB = (OUT, IN, STATE_CHANGED))
++ */
++int bmi_read_module_present_status(int module);
++
++/*
++ * BMI module present
++ *
++ * @param module plug-in module (BMI_Mx, x= 1,2,3,4)
++ * @return module present (1 = present, 0 = not present )
++ */
++int bmi_module_present (struct bmi_device *bdev);
++
++
++#endif // _BMI_CONTROL_H
++
+--- /dev/null
++++ git/include/linux/bmi/bmi-eeprom-data.h
+@@ -0,0 +1,83 @@
++#ifndef BMI_EEPROM_DATA_H
++#define BMI_EEPROM_DATA_H
++
++#include <linux/types.h>
++
++union _bmi_vendor {
++ __u16 vendor;
++ __u8 vendor_msb;
++ __u8 vendor_lsb;
++};
++
++union _bmi_product {
++ __u16 product;
++ __u8 product_msb;
++ __u8 product_lsb;
++};
++
++union _bmi_revision {
++ __u16 revision;
++ __u8 revision_msb;
++ __u8 revision_lsb;
++};
++
++struct bmi_eeprom_raw
++{
++ __u8 format; /* byte 0x00 */
++ __u8 vendor_msb; /* byte 0x01 */
++ __u8 vendor_lsb; /* byte 0x02 */
++ __u8 product_msb; /* byte 0x03 */
++ __u8 product_lsb; /* byte 0x04 */
++ __u8 revision_msb; /* byte 0x05 */
++ __u8 revision_lsb; /* byte 0x06 */
++ __u8 bus_usage; /* byte 0x07 */
++ __u8 gpio_usage; /* byte 0x08 */
++ __u8 power_use; /* byte 0x09 */
++ __u8 power_charging; /* byte 0x0A */
++ __u8 memory_size_msb; /* byte 0x0B */
++ __u8 memory_size_lsb; /* byte 0x0C */
++ __u8 serial_num_loc; /* byte 0x0D */
++ __u8 serial_num_year; /* byte 0x0E */
++ __u8 serial_num_week; /* byte 0x0F */
++ __u8 serial_num_seq_msb; /* byte 0x10 */
++ __u8 serial_num_seq_mid; /* byte 0x11 */
++ __u8 serial_num_seq_lsb; /* byte 0x12 */
++ __s8 description[108]; /* byte 0x13-0x7E */
++ __u8 checksum; /* byte 0x7F */
++};
++
++
++#ifdef __KERNEL__
++
++struct bmi_eeprom_id
++{
++ __u16 vendor;
++ __u16 product;
++ __u16 revision;
++};
++
++
++enum {
++ BMI_EPSTATE_UNKNOWN = 0,
++ BMI_EPSTATE_I2C_READ_ERROR,
++ BMI_EPSTATE_CHECKSUM_ERROR,
++ BMI_EPSTATE_VALID,
++};
++
++extern void bmi_eeprom_get_id (struct bmi_eeprom_raw *raw, struct bmi_eeprom_id *epid);
++extern int bmi_eeprom_checksum_validate ( struct bmi_eeprom_raw *raw );
++#endif /* __KERNEL__ */
++
++static inline __u8 bmi_eeprom_checksum ( struct bmi_eeprom_raw *raw )
++{
++ int i;
++ __u8 sum = 0;
++ __u8 *buf = (__u8*)raw;
++
++ for (i = 0; i < (sizeof (struct bmi_eeprom_raw) - 1); i++) {
++ sum ^= *buf++;
++ }
++ return sum;
++}
++
++#endif /* BMI_EEPROM_DATA_H */
+--- /dev/null
++++ git/include/linux/bmi/bmi-eeprom-driver.h
+@@ -0,0 +1,113 @@
++#ifndef BMI_EEPROM_DRIVER_H
++#define BMI_EEPROM_DRIVER_H
++
++/*******************************************************************************
++ * Driver description:
++ *
++ * This driver provides operations that allow an application program to
++ * read and write the inventory eeprom on Bug Labs Bug PlugIn peripheral
++ * hardware modules.
++ *
++ * This driver is a character driver.
++ *
++ * Supported system calls
++ *
++ * This driver supports the following system calls:
++ *
++ * open()
++ *
++ * During the open() call, only driver initialization and house keeping
++ * are performed. The hardware is not touched.
++ *
++ * close()
++ *
++ * During the close() system call, only driver house keeping is performed.
++ * The hardware is not touched.
++ *
++ * ioctl()
++ *
++ * All of the ioctl() calls for this driver take 2 or 3 parameters.
++ * They are:
++ * file descriptor - obtained from open() call.
++ * ioctl command number - described below.
++ * void pointer to struct - ioctl command specific.
++
++ * ioctl() return values:
++ *
++ * On success, all ioctl() calls return zero.
++ *
++ * On error, all ioctl() calls return -1 and errno is set appropriatly.
++ * Additional error information may be returned in the ioctl command
++ * structure. See the ioctl command structure declarations for more
++ * information.
++ *
++ *******************************************************************************
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++/*
++ * Include the standard type definitions.
++ * The file to include depends on whether or not we are doing a kernel or
++ * application build.
++ */
++#ifdef __KERNEL__
++ #include <linux/types.h>
++#else
++ #include <sys/types.h>
++ #include <stdint.h>
++#endif /* __KERNEL__ */
++
++
++#ifdef __cplusplus
++}
++#endif
++
++//REWORK: Add documentation.
++
++//REWORK: Where should this file live so that applications can #include it ?
++
++
++/* bmi_eeprom_request
++
++ offset: 0 - 255
++ size: 1- 256
++ offset + size must be <= 256
++
++ */
++struct bmi_eeprom_request {
++ int return_code;
++ int xfer_count;
++ int size;
++ int offset;
++ __u8 data[256];
++};
++
++
++/*******************************************************************************
++ * Ioctl type definition:
++ *
++ * The ioctl type (magic) number for this driver is BUG_EEPROM_IOC_TYPE
++ *
++ *******************************************************************************
++ */
++
++#define BUG_EEPROM_IOC_TYPE 0xFE
++
++/*******************************************************************************
++ * Ioctl command definitions:
++ *
++ * The ioctl calls supported by this driver are:
++ *
++ *******************************************************************************
++ */
++
++#define BUG_EEPROM_READ \
++ _IOR (BUG_EEPROM_IOC_TYPE, 0, struct bmi_eeprom_request)
++
++#define BUG_EEPROM_WRITE \
++ _IOW (BUG_EEPROM_IOC_TYPE, 0, struct bmi_eeprom_request)
++
++#endif
+--- /dev/null
++++ git/include/linux/bmi/bmi-eeprom.h
+@@ -0,0 +1,75 @@
++#ifndef BMI_EEPROM_H
++#define BMI_EEPROM_H
++
++#include <linux/types.h>
++
++union _bmi_vendor {
++ __u16 vendor;
++ __u8 vendor_msb;
++ __u8 vendor_lsb;
++};
++
++union _bmi_product {
++ __u16 product;
++ __u8 product_msb;
++ __u8 product_lsb;
++};
++
++union _bmi_revision {
++ __u16 revision;
++ __u8 revision_msb;
++ __u8 revision_lsb;
++};
++
++struct bmi_eeprom_data
++{
++ __u8 format; /* byte 0x00 */
++ __u8 vendor_msb; /* byte 0x01 */
++ __u8 vendor_lsb; /* byte 0x02 */
++ __u8 product_msb; /* byte 0x03 */
++ __u8 product_lsb; /* byte 0x04 */
++ __u8 revision_msb; /* byte 0x05 */
++ __u8 revision_lsb; /* byte 0x06 */
++/* __u16 vendor; */
++/* __u16 product; */
++/* __u16 revision; */
++ __u8 bus_usage; /* byte 0x07 */
++ __u8 gpio_usage; /* byte 0x08 */
++ __u8 power_use; /* byte 0x09 */
++ __u8 power_charging; /* byte 0x0A */
++ __u8 memory_size_msb; /* byte 0x0B */
++ __u8 memory_size_lsb; /* byte 0x0C */
++ __u8 serial_num_loc; /* byte 0x0D */
++ __u8 serial_num_year; /* byte 0x0E */
++ __u8 serial_num_week; /* byte 0x0F */
++ __u8 serial_num_seq_msb; /* byte 0x10 */
++ __u8 serial_num_seq_mid; /* byte 0x11 */
++ __u8 serial_num_seq_lsb; /* byte 0x12 */
++ __s8 description[108]; /* byte 0x13-0x7E */
++ __u8 checksum; /* byte 0x7F */
++};
++
++
++struct bmi_eeprom_id
++{
++ __u16 vendor;
++ __u16 product;
++ __u16 revision;
++};
++
++
++enum {
++ BMI_EPSTATE_UNKNOWN = 0,
++ BMI_EPSTATE_I2C_READ_ERROR,
++ BMI_EPSTATE_CHECKSUM_ERROR,
++ BMI_EPSTATE_VALID,
++};
++
++
++//__u8 bmi_eeprom_checksum ( struct bmi_eeprom_data *raw );
++int bmi_eeprom_checksum_validate ( struct bmi_eeprom_data *raw );
++//extern void bmi_eeprom_get_id (struct bmi_eeprom_data *raw, struct bmi_eeprom_id *epid);
++//extern int bmi_eeprom_checksum_validate ( struct bmi_eeprom_data *raw );
++
++
++#endif /* BMI_EEPROM_H */
+--- /dev/null
++++ git/include/linux/bmi/bmi-slot.h
+@@ -0,0 +1,29 @@
++#ifndef BMI_SLOT_H
++#define BMI_SLOT_H
++
++//void bmi_slot_resrc_init(void);
++
++void bmi_slot_power_on (int num);
++void bmi_slot_power_off (int num);
++
++void bmi_slot_gpio_configure (int num, int gpio);
++int bmi_slot_gpio_get (int num);
++
++void bmi_slot_gpio_set (int num, int data);
++void bmi_slot_uart_enable (int num);
++void bmi_slot_uart_disable (int num);
++
++void bmi_slot_spi_enable (int num);
++void bmi_slot_spi_disable (int num);
++
++void bmi_slot_audio_enable (int num);
++void bmi_slot_audio_disable (int num);
++
++void bmi_slot_battery_enable (int num);
++void bmi_slot_battery_disable (int num);
++
++int bmi_slot_module_present (int num);
++//int bmi_slot_status_irq_state (int num);
++
++
++#endif
+--- /dev/null
++++ git/include/linux/bmi/bmi_audio.h
+@@ -0,0 +1,449 @@
++/*
++ * File: include/linux/bmi/bmi_audio.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus audio plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_AUDIO_H
++#define BMI_AUDIO_H
++
++#include <linux/bmi/bmi_ioctl.h>
++
++// GPIO defines
++typedef enum {
++ GPIO_SPARE, // unused
++ GPIO_RESET, // CODEC reset
++ GPIO_GREEN, // green LED
++ GPIO_RED, // red LED
++} BMI_AUDIO_GPIO;
++
++// GETSTAT defines
++typedef enum {
++ GETSTAT_AMP = 0x001, // IOX bit 0 - amplifier off (O - low active)
++ GETSTAT_ISPARE = 0x002, // IOX bit 1 - spare
++ GETSTAT_VOLP = 0x004, // IOX bit 2 - VOLP (I - interrupt)
++ GETSTAT_VOLD = 0x008, // IOX bit 3 - VOLD (I - interrupt)
++ GETSTAT_HP_INS = 0x010, // IOX bit 4 - HP_INS (I - interrupt)
++ GETSTAT_MIC_INS = 0x020, // IOX bit 5 - MIC_INS (I - interrupt)
++ GETSTAT_LI_INS = 0x040, // IOX bit 6 - LI_INS (I - interrupt)
++ GETSTAT_LO_INS = 0x080, // IOX bit 7 - LO_INS (I - interrupt)
++ GETSTAT_GSPARE = 0x100, // unused
++ GETSTAT_RESET = 0x200, // CODEC reset
++ GETSTAT_GREEN = 0x400, // green LED
++ GETSTAT_RED = 0x800, // red LED
++} BMI_AUDIO_GETSTAT;
++
++// input event bit defintions
++typedef enum {
++ HEADPHONE_INSERTED = 0x001, // Detected headphone insertion
++ MICROPHONE_INSERTED = 0x002, // Detected microphone insertion
++ LINEOUT_INSERTED = 0x004, // Detected line out insertion
++ LINEIN_INSERTED = 0x008, // Detected line in insertion
++ VOLUME_DOWN = 0x010, // volume down button pressed
++ VOLUME_UP = 0x020, // volume up button pressed
++} BMI_AUDIO_EVENT;
++
++// module numbers
++typedef enum {
++ BMI_AUDIO_M1, // PIM 1
++ BMI_AUDIO_M2, // PIM 2
++ BMI_AUDIO_M3, // PIM 3
++ BMI_AUDIO_M4, // PIM 4
++ BMI_AUDIO_PIM_NUM, // Number of PIMs
++} BMI_MODULE_NUMBERS;
++
++// TI '3105 CODEC registers
++// Page 0
++#define CODEC_PAGE_SEL 0x0 // page select
++#define CODEC_RESET 0x1 // reset (self-clearing)
++ #define CODEC_RESET_RESET 0x1 // reset (self-clearing)
++#define CODEC_SAMPLE_RATE 0x2 // ADC/DAC sample rate
++ #define CODEC_SR1 0x0 // ADC/DAC sample rate
++ #define CODEC_SR1_5 0x1 // ADC/DAC sample rate
++ #define CODEC_SR2 0x2 // ADC/DAC sample rate
++ #define CODEC_SR2_5 0x3 // ADC/DAC sample rate
++ #define CODEC_SR3 0x4 // ADC/DAC sample rate
++ #define CODEC_SR3_5 0x5 // ADC/DAC sample rate
++ #define CODEC_SR4 0x6 // ADC/DAC sample rate
++ #define CODEC_SR4_5 0x7 // ADC/DAC sample rate
++ #define CODEC_SR5 0x8 // ADC/DAC sample rate
++ #define CODEC_SR5_5 0x9 // ADC/DAC sample rate
++ #define CODEC_SR6 0xA // ADC/DAC sample rate
++ #define CODEC_SR_SHIFT (4) // ADC shift
++#define CODEC_PLLA 0x3 // PLL Programming A
++ #define CODEC_PLLA_EN 0x80 // PLL enabled
++ #define CODEC_PLLA_DIS 0x00 // PLL disabled
++ #define CODEC_PLLA_Q(x) (((x) & 0xF) << 3) // PLL Q
++ #define CODEC_PLLA_P(x) ((x) & 0x7) // PLL P
++#define CODEC_PLLB 0x4 // PLL Programming B
++ #define CODEC_PLLB_J(x) (((x) & 0x3F) << 2) // PLL J
++#define CODEC_PLLC_DMSB 0x5 // PLL D MSB
++#define CODEC_PLLD_DLSB 0x6 // PLL D LSB
++ #define CODEC_PLLD_D(x) (((x) & 0x3F) << 2) // PLL D LSB
++#define CODEC_DATAPATH 0x7 // Datapath set up
++ #define CODEC_DP_48 (0x00) // 48 kHz
++ #define CODEC_DP_44 (0x80) // 44.1 kHz
++ #define CODEC_ADR_DIS (0x00) // ADC Dual Rate
++ #define CODEC_ADR_EN (0x40) // ADC Dual Rate
++ #define CODEC_DDR_DIS (0x00) // DAC Dual Rate
++ #define CODEC_DDR_EN (0x20) // DAC Dual Rate
++ #define CODEC_DP_MUTED (0x00) // DAC Data Path
++ #define CODEC_DP_NORMAL (0x01) // DAC Data Path
++ #define CODEC_DP_REVERSE (0x02) // DAC Data Path
++ #define CODEC_DP_MONO (0x03) // DAC Data Path
++ #define CODEC_DP_L(x) ((x) << 3) // DAC Data Path Left
++ #define CODEC_DP_R(x) ((x) << 1) // DAC Data Path Right
++#define CODEC_AIFA 0x8 // Audio serial data IF control
++ #define CODEC_AIFA_BCLK_S 0x00 // BCLK is input
++ #define CODEC_AIFA_BCLK_M 0x80 // BCLK is output
++ #define CODEC_AIFA_WCLK_S 0x00 // WCLK is input
++ #define CODEC_AIFA_WCLK_M 0x40 // WCLK is output
++ #define CODEC_AIFA_DOUT_N 0x00 // Dout not tri-state
++ #define CODEC_AIFA_DOUT_TS 0x20 // Dout tri-states
++ #define CODEC_AIFA_CLK_G 0x00 // CLKs gated (Master mode only)
++ #define CODEC_AIFA_CLK_F 0x10 // CLKs free run (Master mode only)
++ #define CODEC_AIFA_FX_OFF 0x00 // disable 3-D EFX
++ #define CODEC_AIFA_FX_ON 0x04 // enable 3-D EFX
++#define CODEC_AIFB 0x9 // Audio serial data IF control
++ #define CODEC_AIFB_I2S 0x00 // MODE = I2S
++ #define CODEC_AIFB_DSP 0x40 // MODE = DSP
++ #define CODEC_AIFB_RJ 0x80 // MODE = Right Justified
++ #define CODEC_AIFB_LJ 0xC0 // MODE = Left Justified
++ #define CODEC_AIFB_16 0x00 // World Length = 16 bits
++ #define CODEC_AIFB_20 0x10 // World Length = 20 bits
++ #define CODEC_AIFB_24 0x20 // World Length = 24 bits
++ #define CODEC_AIFB_32 0x30 // World Length = 32 bits
++ #define CODEC_AIFB_256S 0x08 // 256-clock transfer mode (TDM)
++ #define CODEC_AIFB_DSYNC 0x04 // DAC resync
++ #define CODEC_AIFB_ASYNC 0x02 // ADC resync
++ #define CODEC_AIFB_MSYNC 0x01 // resync with soft-mute
++#define CODEC_AIF_WORD_OFFSET 0xA // data bit offset in frame
++#define CODEC_OVERFLOW 0xB // Overflow flags
++ #define CODEC_OF_LADC 0x80 // Left ADC
++ #define CODEC_OF_RADC 0x40 // Right ADC
++ #define CODEC_OF_LDAC 0x20 // Left DAC
++ #define CODEC_OF_RDAC 0x10 // Right DAC
++ #define CODEC_OF_PLLR(x) ((x) & 0xF) // PLL R
++#define CODEC_FILT_CONTROL 0xC // Filter Control
++ #define CODEC_FC_LADC_HP45 0x40 // Left ADC Filter Control
++ #define CODEC_FC_LADC_HP125 0x80 // Left ADC Filter Control
++ #define CODEC_FC_LADC_HP25 0xC0 // Left ADC Filter Control
++ #define CODEC_FC_RADC_HP45 0x10 // Right ADC Filter Control
++ #define CODEC_FC_RADC_HP125 0x20 // Right ADC Filter Control
++ #define CODEC_FC_RADC_HP25 0x30 // Right ADC Filter Control
++#define CODEC_HS 0xE // Headset/Button
++ #define CODEC_HS_COUPLED 0x80 // HP outputs AC-Coupled
++ #define CODEC_HS_ADIFF 0x40 // Output A differential
++ #define CODEC_HS_HSDET 0x10 // headset detected
++ #define CODEC_HS_BDIFF 0x08 // Output B differential
++#define CODEC_LADC_PGA 0xF // Left ADC PGA
++#define CODEC_RADC_PGA 0x10 // Right ADC PGA
++ #define CODEC_ADC_PGA_MUTE 0x80 // muted
++ #define CODEC_ADC_PGA_G(x) ((x) & 0x7F) // gain (0 to 59.5 dB)
++#define CODEC_M3_LPGA 0x11 // MIC3 -> LADC PGA
++#define CODEC_M3_RPGA 0x12 // MIC3 -> RADC PGA
++ #define CODEC_M3_PGA_LOFF (0xF << 4) // L input off
++ #define CODEC_M3_PGA_ROFF (0xF ) // R input off
++ #define CODEC_M3_PGA_L(x) (((x) & 0xF) << 4) // L input level (0 to -12 dB)
++ #define CODEC_M3_PGA_R(x) ((x) & 0xF) // R input level (0 to -12 dB)
++#define CODEC_L1L_LPGA 0x13 // L1 Left -> LADC PGA
++#define CODEC_L2L_LPGA 0x14 // L2 Left -> LADC PGA
++#define CODEC_L1R_LPGA 0x15 // L1 Right -> LADC PGA
++#define CODEC_L1R_RPGA 0x16 // R1 Right -> RADC PGA
++#define CODEC_L2R_RPGA 0x17 // L2 Right -> RADC PGA
++#define CODEC_L1L_RPGA 0x18 // L1 Left -> RADC PGA
++ #define CODEC_L_PGA(x) (((x) & 0xF) << 3) // input level (0 to -12 dB)
++ #define CODEC_LX_PGA_PU 0x04 // L1 power up
++ #define CODEC_L1L_PGA_SS(x) ((x) & 0x3) // L1 soft stepping
++ #define CODEC_L2L_LPGA_BIASED 0x04 // L2 Left weak bias
++#define CODEC_MIC_BIAS 0x19 // Mic Bias
++ #define CODEC_MIC_BIAS_PD 0x00 // powered down
++ #define CODEC_MIC_BIAS_2V 0x40 // 2V
++ #define CODEC_MIC_BIAS_2P5V 0x80 // 2.5V
++ #define CODEC_MIC_BIAS_AVDD 0xC0 // AVDD
++#define CODEC_MIC_LAGC_A 0x1A // L AGC A
++#define CODEC_MIC_RAGC_A 0x1D // R AGC A
++ #define CODEC_MIC_AGC_EN 0x80 // enable
++ #define CODEC_MIC_AGC_TL(x) (((x) & 0x7) << 4) // target level (-5.5 to -24 dB)
++ #define CODEC_MIC_AGC_AT(x) (((x) & 0x3) << 2) // attack time (8 to 20 ms)
++ #define CODEC_MIC_AGC_DT(x) ((x) & 0x3) // decay time (100 to 500 ms)
++#define CODEC_MIC_LAGC_B 0x1B // L AGC B
++#define CODEC_MIC_RAGC_B 0x1E // R AGC B
++ #define CODEC_MIC_AGC_MG(x) (((x) & 0x7F) << 1) // max gain (0 to 59.5 dB)
++#define CODEC_MIC_LAGC_C 0x1C // L AGC C
++#define CODEC_MIC_RAGC_C 0x1F // R AGC C
++ #define CODEC_MIC_AGC_H(x) (((x) & 0x3) << 6) // NG hysteresis (1 to 3 dB, off)
++ #define CODEC_MIC_AGC_T(x) (((x) & 0x3) << 6) // NG Threshold (off to -90 dB)
++ #define CODEC_MIC_AGC_SC 0x1 // clip stepping enable
++#define CODEC_MIC_LAGC_GAIN 0x20 // L AGC gain (-12 tp 59.5 dB)
++#define CODEC_MIC_RAGC_GAIN 0x21 // R AGC gain (-12 tp 59.5 dB)
++#define CODEC_MIC_LAGC_NGD 0x22 // L AGC NG debounce
++#define CODEC_MIC_RAGC_NGD 0x23 // R AGC NG debounce
++ #define CODEC_MIC_AGC_NGD_D(x) (((x) & 0x1F) << 3) // detect(0 to 1536 ms)
++ #define CODEC_MIC_AGC_NGD_C(x) ((x) & 0x7) // control (0 to 32 ms)
++#define CODEC_ADC_FLAG 0x24 // ADC flag
++ #define CODEC_ADC_FLAG_LPGA_S 0x80 // L ADC PGA gain equal
++ #define CODEC_ADC_FLAG_LPWR_S 0x40 // L ADC powered-up
++ #define CODEC_ADC_FLAG_LSIGD 0x20 // L AGC signal detected
++ #define CODEC_ADC_FLAG_LSAT 0x10 // L AGC saturation detected
++ #define CODEC_ADC_FLAG_RPGA_S 0x08 // R ADC PGA gain equal
++ #define CODEC_ADC_FLAG_RPWR_S 0x04 // R ADC powered-up
++ #define CODEC_ADC_FLAG_RSIGD 0x02 // R AGC signal detected
++ #define CODEC_ADC_FLAG_RSAT 0x01 // R AGC saturation detected
++#define CODEC_DAC_PWR 0x25 // DAC power and output driver
++#define CODEC_DAC_HPWR 0x26 // high-power output driver
++ #define CODEC_DAC_PWR_L_EN 0x80 // L power up
++ #define CODEC_DAC_PWR_R_EN 0x40 // R power up
++ #define CODEC_DAC_PWR_HP_DIFF 0x00 // differential of HPLOUT
++ #define CODEC_DAC_PWR_HP_VCM 0x10 // constant VCM
++ #define CODEC_DAC_PWR_HP_ISE 0x20 // independant single ended
++ #define CODEC_DAC_HPWR_HPL_DIFF 0x18 // short circuit protection
++ #define CODEC_DAC_HPWR_SS 0x04 // short circuit protection
++ #define CODEC_DAC_HPWR_SS_C 0x00 // limit current
++ #define CODEC_DAC_HPWR_SS_P 0x02 // power down
++#define CODEC_DAC_HPOS 0x28 // high-power output stage
++ #define CODEC_DAC_HPOS_CM1P35 0x00 // common mode = 1.35V
++ #define CODEC_DAC_HPOS_CM1P5 0x40 // common mode = 1.5V
++ #define CODEC_DAC_HPOS_CM1P65 0x80 // common mode = 1.65V
++ #define CODEC_DAC_HPOS_CM1P8 0xC0 // common mode = 1.8V
++ #define CODEC_DAC_HPOS_L2L_BYP 0x00 // L2 L bypass disabled
++ #define CODEC_DAC_HPOS_L2L_SE 0x10 // L2 L bypass = L2LP
++ #define CODEC_DAC_HPOS_L2L_BYP 0x00 // L2 R bypass disabled
++ #define CODEC_DAC_HPOS_L2R_SE 0x04 // L2 R bypass = L2RP
++ #define CODEC_DAC_HPOS_FS 0x00 // soft stepping: 1 / fs
++ #define CODEC_DAC_HPOS_2FS 0x01 // soft stepping: 1 / 2 fs
++ #define CODEC_DAC_HPOS_SS_DIS 0x02 // soft stepping disabled
++#define CODEC_DAC_OS 0x29 // output switching
++ #define CODEC_DAC_OS_L1 0x00 // L = L1
++ #define CODEC_DAC_OS_L3 0x40 // L = L3
++ #define CODEC_DAC_OS_L2 0x80 // L = L2
++ #define CODEC_DAC_OS_R1 0x00 // R = R1
++ #define CODEC_DAC_OS_R3 0x10 // R = R3
++ #define CODEC_DAC_OS_R2 0x20 // R = R2
++ #define CODEC_DAC_OS_VOL_S 0x00 // volume separate
++ #define CODEC_DAC_OS_VOL_R 0x01 // L follows R
++ #define CODEC_DAC_OS_VOL_L 0x02 // R follows L
++#define CODEC_DAC_PR 0x2A // pop reduction
++ #define CODEC_DAC_PR_DEL(x) (((x) & 0xF) << 4) // delay (0 us to 4 s)
++ #define CODEC_DAC_PR_RU(x) (((x) & 0x3) << 2) // ramp up (0 to 4 ms)
++ #define CODEC_DAC_CM_AVDD 0x00 // common mode from AVDD
++ #define CODEC_DAC_CM_BG 0x02 // common mode from band gap
++#define CODEC_DAC_LVOL 0x2B // Left volume
++#define CODEC_DAC_RVOL 0x2C // Right volume
++ #define CODEC_DAC_VOL_MUTE 0x80 // muted
++ #define CODEC_DAC_VOL(x) ((x) & 0x7F) // volume (0 to -63.5 dB)
++#define CODEC_L2L_HPL 0x2D // L2L -> HPLOUT
++#define CODEC_PGAL_HPL 0x2E // PGAL -> HPLOUT
++#define CODEC_DACL1_HPL 0x2F // DACL1 -> HPLOUT
++#define CODEC_L2R_HPL 0x30 // L2R -> HPLOUT
++#define CODEC_PGAR_HPL 0x31 // PGAR -> HPLOUT
++#define CODEC_DACR1_HPL 0x32 // DACLR -> HPLOUT
++#define CODEC_L2L_HPLCOM 0x34 // L2L -> HPLCOM
++#define CODEC_PGAL_HPLCOM 0x35 // PGAL -> HPLCOM
++#define CODEC_DACL1_HPLCOM 0x36 // DACL1 -> HPLCOM
++#define CODEC_L2R_HPLCOM 0x37 // L2R -> HPLCOM
++#define CODEC_PGAR_HPLCOM 0x38 // PGAR -> HPLCOM
++#define CODEC_DACR1_HPLCOM 0x39 // DACR1 -> HPLCOM
++#define CODEC_L2L_HPR 0x3B // L2L -> HPROUT
++#define CODEC_PGAL_HPR 0x3C // PGAL -> HPROUT
++#define CODEC_DACL1_HPR 0x3D // DACL1 -> HPROUT
++#define CODEC_L2R_HPR 0x3E // L2R -> HPROUT
++#define CODEC_PGAR_HPR 0x3F // PGAR -> HPROUT
++#define CODEC_DACR1_HPR 0x40 // DACLR -> HPROUT
++#define CODEC_L2L_HPRCOM 0x42 // L2L -> HPRCOM
++#define CODEC_PGAL_HPRCOM 0x43 // PGAL -> HPRCOM
++#define CODEC_DACL1_HPRCOM 0x44 // DACL1 -> HPRCOM
++#define CODEC_L2R_HPRCOM 0x45 // L2R -> HPRCOM
++#define CODEC_PGAR_HPRCOM 0x46 // PGAR -> HPRCOM
++#define CODEC_DACR1_HPRCOM 0x47 // DACLR -> HPRCOM
++#define CODEC_L2L_LLOPM 0x50
++#define CODEC_PGAL_LLOPM 0x51
++#define CODEC_DACL1_LLOPM 0x52
++#define CODEC_L2R_LLOPM 0x53
++#define CODEC_PGAR_LLOPM 0x54
++#define CODEC_DACR1_LLOPM 0x55
++#define CODEC_L2L_RLOPM 0x57
++#define CODEC_PGA_RLOPM 0x58
++#define CODEC_DACL1_RLOPM 0x59
++#define CODEC_L2R_RLOPM 0x5A
++#define CODEC_PGAR_RLOPM 0x5B
++#define CODEC_DACR1_RLOPM 0x5C
++ #define CODEC_HP_EN 0x80 // enabled
++ #define CODEC_HP_VOL(x) ((x) & 0x7F) // see datasheet Table 6
++#define CODEC_HPLOUT 0x33 // HPLOUT output level
++#define CODEC_HPLCOM 0x3A // HPLCOM output level
++#define CODEC_HPROUT 0x41 // HPROUT output level
++#define CODEC_HPRCOM 0x48 // HPRCOM output level
++#define CODEC_LLOPM 0x56 // LLOPM output level
++#define CODEC_RLOPM 0x5D // RLOPM output level
++ #define CODEC_HPX_LC(x) (((x) & 0xF) << 4) // output level
++ #define CODEC_HPX_EN 0x08 // not muted
++ #define CODEC_HPX_PD 0x04 // power down enable
++ #define CODEC_HPX_STAT 0x02 // gain not applied
++ #define CODEC_HPX_PC 0x01 // fully powered up
++#define CODEC_PSR 0x5E // Power Status
++ #define CODEC_PSR_LDPS 0x80 // L DAC
++ #define CODEC_PSR_DDPS 0x40 // R DAC
++ #define CODEC_PSR_LLOPM 0x10 // L LOPM
++ #define CODEC_PSR_RLOPM 0x08 // R LOPM
++ #define CODEC_PSR_HPLOUT 0x04 // HPLOUT
++ #define CODEC_PSR_HPLCOM 0x02 // HPLCOM
++#define CODEC_SS 0x5F // driver short circuit
++ #define CODEC_SS_HPLOUT 0x80
++ #define CODEC_SS_HPROUT 0x40
++ #define CODEC_SS_HPLCOM 0x20
++ #define CODEC_SS_HPRCOM 0x10
++ #define CODEC_SS_HPLCOM_PS 0x08
++ #define CODEC_SS_HPRCOM_PS 0x04
++#define CODEC_S_INT 0x60 // sticky interrupt
++#define CODEC_RT_INT 0x61 // real-time interrupt
++ #define CODEC_INT_HPLOUT_SS 0x80
++ #define CODEC_INT_HPROUT_SS 0x40
++ #define CODEC_INT_HPLCOM_SS 0x20
++ #define CODEC_INT_HPRCOM_SS 0x10
++ #define CODEC_INT_HS_DET 0x04
++ #define CODEC_INT_LAGC_NG 0x02
++ #define CODEC_INT_RAGC_NG 0x01
++#define CODEC_CLK 0x65 // clock source
++ #define CODEC_CLK_PLLDIV 0x00
++ #define CODEC_CLK_CLKDIV 0x01
++#define CODEC_CLKGEN 0x66 // clock generation
++ #define CODEC_CLKGEN_C_M 0x02 // MCLK -> CLK
++ #define CODEC_CLKGEN_C_G 0x42 // GPIO2 -> CLK
++ #define CODEC_CLKGEN_C_B 0x82 // BCLK -> CLK
++ #define CODEC_CLKGEN_P_M 0x02 // MCLK -> PLL
++ #define CODEC_CLKGEN_P_G 0x12 // GPIO2 -> PLL
++ #define CODEC_CLKGEN_P_B 0x22 // BCLK -> PLL
++#define CODEC_LAGC_ATT 0x67 // L AGC Attack
++#define CODEC_RAGC_ATT 0x69 // R AGC Attack
++ #define CODEC_AGC_ATT_R26 0x00 // source reg 36
++ #define CODEC_AGC_ATT_R103 0x80 // source reg 103
++ #define CODEC_AGC_ATT_T(x) (((x) & 0x3) << 5) // time
++ #define CODEC_AGC_ATT_M(x) (((x) & 0xF) << 2) // multiplication
++#define CODEC_LAGC_DEC 0x68 // L AGC Decay
++#define CODEC_RAGC_DEC 0x6A // R AGC Decay
++ #define CODEC_AGC_DEC_R26 0x00 // source reg 36
++ #define CODEC_AGC_DEC_R104 0x80 // source reg 104
++ #define CODEC_AGC_DEC_T(x) (((x) & 0x3) << 5) // time
++ #define CODEC_AGC_DEC_M(x) (((x) & 0xF) << 2) // multiplication
++#define CODEC_DP_I2C 0x6B // digital path and I2C
++ #define CODEC_DP_I2C_LHPF_EN 0x80
++ #define CODEC_DP_I2C_RHPF_EN 0x40
++ #define CODEC_ADC_DFLDRD 0x00
++ #define CODEC_ADC_DFLDRA 0x10
++ #define CODEC_ADC_DFLARD 0x20
++ #define CODEC_ADC_DFLARA 0x30
++ #define CODEC_ADC_F_EN 0x08
++ #define CODEC_I2C_ERR_DIS 0x04
++ #define CODEC_I2C_HANG 0x01
++#define CODEC_PASB 0x6C // passive analog bypass
++ #define CODEC_PASB_L2RP_RLOP 0x40
++ #define CODEC_PASB_L1RP_RLOP 0x10
++ #define CODEC_PASB_L2LP_LLOP 0x04
++ #define CODEC_PASB_L1LP_LLOP 0x01
++#define CODEC_DAC_QCA 0x6D // DAC current adjust
++#define CODEC_DAC_QCA_50 0x40
++#define CODEC_DAC_QCA_100 0xC0
++// Page 1
++#define CODEC_EF_LN0M 0x1
++#define CODEC_EF_LN0L 0x2
++#define CODEC_EF_LN1M 0x3
++#define CODEC_EF_LN1L 0x4
++#define CODEC_EF_LN2M 0x5
++#define CODEC_EF_LN2L 0x6
++#define CODEC_EF_LN3M 0x7
++#define CODEC_EF_LN3L 0x8
++#define CODEC_EF_LN4M 0x9
++#define CODEC_EF_LN4L 0xA
++#define CODEC_EF_LN5M 0xB
++#define CODEC_EF_LN5L 0xC
++
++#define CODEC_EF_LD1M 0xD
++#define CODEC_EF_LD1L 0xE
++#define CODEC_EF_LD2M 0xF
++#define CODEC_EF_LD2L 0x10
++#define CODEC_EF_LD4M 0x11
++#define CODEC_EF_LD4L 0x12
++#define CODEC_EF_LD5M 0x13
++#define CODEC_EF_LD5L 0x14
++
++#define CODEC_DF_LN0M 0x15
++#define CODEC_DF_LN0L 0x16
++#define CODEC_DF_LN1M 0x17
++#define CODEC_DF_LN1L 0x18
++
++#define CODEC_DF_LD1M 0x19
++#define CODEC_DF_LD1L 0x1A
++
++#define CODEC_EF_RN0M 0x1B
++#define CODEC_EF_RN0L 0x1C
++#define CODEC_EF_RN1M 0x1D
++#define CODEC_EF_RN1L 0x1E
++#define CODEC_EF_RN2M 0x1F
++#define CODEC_EF_RN2L 0x20
++#define CODEC_EF_RN3M 0x21
++#define CODEC_EF_RN3L 0x22
++#define CODEC_EF_RN4M 0x23
++#define CODEC_EF_RN4L 0x24
++#define CODEC_EF_RN5M 0x25
++#define CODEC_EF_RN5L 0x26
++
++#define CODEC_EF_RD1M 0x27
++#define CODEC_EF_RD1L 0x28
++#define CODEC_EF_RD2M 0x29
++#define CODEC_EF_RD2L 0x2A
++#define CODEC_EF_RD4M 0x2B
++#define CODEC_EF_RD4L 0x2C
++#define CODEC_EF_RD5M 0x2D
++#define CODEC_EF_RD5L 0x2E
++
++#define CODEC_DF_RN0M 0x2F
++#define CODEC_DF_RN0L 0x30
++#define CODEC_DF_RN1M 0x31
++#define CODEC_DF_RN1L 0x32
++
++#define CODEC_DF_RD1M 0x33
++#define CODEC_DF_RD1L 0x34
++
++#define CODEC_3DAM 0x35
++#define CODEC_3DAL 0x36
++
++#define CODEC_LHPN0M 0x41
++#define CODEC_LHPN0L 0x42
++#define CODEC_LHPN1M 0x43
++#define CODEC_LHPN1L 0x44
++#define CODEC_LHPD1M 0x45
++#define CODEC_LHPD1L 0x46
++
++#define CODEC_RHPN0M 0x47
++#define CODEC_RHPN0L 0x48
++#define CODEC_RHPN1M 0x49
++#define CODEC_RHPN1L 0x4A
++#define CODEC_RHPD1M 0x4B
++#define CODEC_RHPD1L 0x4C
++
++struct codec_xfer {
++ unsigned char page;
++ unsigned char reg;
++ unsigned char data;
++} codec_xfer;
++
++// IOCTL commands for BMI AUDIO driver
++#define BMI_AUDIO_RLEDOFF _IO(BMI_AUDIO_IOCTL, 0x1) // Turn off red LED
++#define BMI_AUDIO_RLEDON _IO(BMI_AUDIO_IOCTL, 0x2) // Turn on red LED
++#define BMI_AUDIO_GLEDOFF _IO(BMI_AUDIO_IOCTL, 0x3) // Turn off green LED
++#define BMI_AUDIO_GLEDON _IO(BMI_AUDIO_IOCTL, 0x4) // Turn on green LED
++#define BMI_AUDIO_SPKOFF _IO(BMI_AUDIO_IOCTL, 0x5) // Turn off speaker
++#define BMI_AUDIO_SPKON _IO(BMI_AUDIO_IOCTL, 0x6) // Turn on speaker
++#define BMI_AUDIO_GETSTAT _IOR(BMI_AUDIO_IOCTL, 0x9, unsigned int *) // READ IOX register
++#define BMI_AUDIO_SETRST _IO(BMI_AUDIO_IOCTL, 0xA) // Set RESET to '0'
++#define BMI_AUDIO_CLRRST _IO(BMI_AUDIO_IOCTL, 0xB) // Set RESET to '1'
++#define BMI_AUDIO_ACTIVATE _IO(BMI_AUDIO_IOCTL, 0xC) // Activate a module for audio capture
++#define BMI_AUDIO_DEACTIVATE _IO(BMI_AUDIO_IOCTL, 0xD) // Deactivate a module for audio capture
++#define BMI_AUDIO_WCODEC _IOW(BMI_AUDIO_IOCTL, 0xE, struct codec_xfer *) // write CODEC register
++#define BMI_AUDIO_RCODEC _IOR(BMI_AUDIO_IOCTL, 0xF, struct codec_xfer *) // read CODEC register
++
++#endif /* BMI_AUDIO_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_camera.h
+@@ -0,0 +1,36 @@
++/*
++ * File: include/linux/bmi/bmi_camera.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus camera plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_CAMERA_A_H
++#define BMI_CAMERA_A_H
++
++#include <linux/input.h>
++#include <linux/bmi/bmi_ioctl.h>
++
++ // IOCTL commands for BMI Camera driver
++
++#define BMI_CAM_FLASH_HIGH_BEAM _IOW(BMI_CAMERA_IOCTL, 0x1, __u32)
++#define BMI_CAM_FLASH_LOW_BEAM _IOW(BMI_CAMERA_IOCTL, 0x2, __u32)
++#define BMI_CAM_FLASH_LED_OFF _IOW(BMI_CAMERA_IOCTL, 0x3, __u32)
++#define BMI_CAM_FLASH_LED_ON _IOW(BMI_CAMERA_IOCTL, 0x4, __u32)
++
++#define BMI_CAM_RED_LED_OFF _IOW(BMI_CAMERA_IOCTL, 0x5, __u32) // Turn off red LED
++#define BMI_CAM_RED_LED_ON _IOW(BMI_CAMERA_IOCTL, 0x6, __u32) // Turn on red LED
++#define BMI_CAM_GREEN_LED_OFF _IOW(BMI_CAMERA_IOCTL, 0x7, __u32) // Turn off green LED
++#define BMI_CAM_GREEN_LED_ON _IOW(BMI_CAMERA_IOCTL, 0x8, __u32) // Turn on green LED
++
++#define BMI_CAM_SELECT _IOW(BMI_CAMERA_IOCTL, 0x9, __u32) // Select camera module
++#define BMI_CAM_GET_SELECTED _IOR(BMI_CAMERA_IOCTL, 0xA, __u32) // return selected camera module
++
++ // input event definitions
++#define BN_SHUTTER BTN_0
++#define BN_ZOOMIN BTN_1
++#define BN_ZOOMOUT BTN_2
++
++#endif /* BMI_CAMERA_A_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_gps.h
+@@ -0,0 +1,30 @@
++/*
++ * File: include/linux/bmi/bmi_gps.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus gps plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_GPS_H
++#define BMI_GPS_H
++
++#include <linux/bmi/bmi_ioctl.h>
++
++ // IOCTL commands for BMI GPS driver
++#define BMI_GPS_RLEDOFF _IOW(BMI_GPS_IOCTL, 0x1, unsigned int) // Turn off red LED
++#define BMI_GPS_RLEDON _IOW(BMI_GPS_IOCTL, 0x2, unsigned int) // Turn on red LED
++#define BMI_GPS_GLEDOFF _IOW(BMI_GPS_IOCTL, 0x3, unsigned int) // Turn off green LED
++#define BMI_GPS_GLEDON _IOW(BMI_GPS_IOCTL, 0x4, unsigned int) // Turn on green LED
++#define BMI_GPS_SETBOOT _IOW(BMI_GPS_IOCTL, 0x5, unsigned int) // Set BOOT to '1'
++#define BMI_GPS_CLRBOOT _IOW(BMI_GPS_IOCTL, 0x6, unsigned int) // Set BOOT to '0'
++#define BMI_GPS_SETWAKE _IOW(BMI_GPS_IOCTL, 0x7, unsigned int) // Set WAKE to '1'
++#define BMI_GPS_CLRWAKE _IOW(BMI_GPS_IOCTL, 0x8, unsigned int) // Set WAKE to '0'
++#define BMI_GPS_GETSTAT _IOR(BMI_GPS_IOCTL, 0x9, unsigned int *) // READ IOX register
++#define BMI_GPS_SETRST _IOW(BMI_GPS_IOCTL, 0xA, unsigned int) // Set RESET to '0'
++#define BMI_GPS_CLRRST _IOW(BMI_GPS_IOCTL, 0xB, unsigned int) // Set RESET to '1'
++#define BMI_GPS_ACTIVE_ANT _IOW(BMI_GPS_IOCTL, 0xC, unsigned int) // Select Active Antenna
++#define BMI_GPS_PASSIVE_ANT _IOW(BMI_GPS_IOCTL, 0xD, unsigned int) // Select Passive Antenna
++
++#endif /* BMI_GPS_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_gsm.h
+@@ -0,0 +1,33 @@
++/*
++ * File: include/linux/bmi/bmi_gsm.h
++ * Author: Matt Isaacs <izzy@buglabs.net>
++ *
++ * This is the application header file for the BMI bus GSM/UMTS plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_GSM_H
++#define BMI_GSM_H
++
++#include <linux/bmi/bmi_ioctl.h>
++
++// GPIO
++#define GSM_GPIO_RED_LED 3 // default to input
++#define GSM_GPIO_GREEN_LED 2 // default to input
++#define GSM_GPIO_1 1 // default to input
++#define GSM_GPIO_0 0 // default to input
++
++#define GSM_GPIO_LED_ON 0
++#define GSM_GPIO_LED_OFF 1
++
++
++// von hippel driver ioctl definitions
++#define BMI_GSM_RLEDOFF _IOW(BMI_GSM_IOCTL, 0x1, unsigned int) // Turn off red LED
++#define BMI_GSM_RLEDON _IOW(BMI_GSM_IOCTL, 0x2, unsigned int) // Turn on red LED
++#define BMI_GSM_GLEDOFF _IOW(BMI_GSM_IOCTL, 0x3, unsigned int) // Turn off green LED
++#define BMI_GSM_GLEDON _IOW(BMI_GSM_IOCTL, 0x4, unsigned int) // Turn on green LED
++#define BMI_GSM_GETSTAT _IOR(BMI_GSM_IOCTL, 0x5, unsigned int *) // READ IOX register
++
++
++#endif /* BMI_GSM_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_ioctl.h
+@@ -0,0 +1,27 @@
++/*
++ * File: include/linux/bmi/bmi_ioctl.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the header file for the BMI ioctl definitions
++ */
++
++#ifndef BMI_IOCTL_H
++#define BMI_IOCTL_H
++
++ // IOCTL Magic Numbers
++#define BMI_CAMERA_IOCTL ('c')
++#define BMI_LCD_IOCTL ('l')
++#define BMI_GPS_IOCTL ('g')
++#define BMI_MDACC_IOCTL ('m')
++#define BMI_AUDIO_IOCTL ('a')
++#define BMI_VH_IOCTL ('v')
++#define BMI_WIFI_IOCTL ('W')
++#define BMI_ZIGBEE_IOCTL ('Z')
++#define BMI_GSM_IOCTL ('G')
++#define BMI_PROJECTOR_IOCTL ('p')
++#define BMI_SENSOR_IOCTL ('s')
++#define BMI_LCD2X_IOCTL ('x')
++#define BMI_RFID_IOCTL ('r')
++
++#endif /* BMI_IOCTL_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_lcd.h
+@@ -0,0 +1,71 @@
++/*
++ * File: include/linux/bmi/bmi_lcd.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus lcd plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_LCD_H
++#define BMI_LCD_H
++
++#include <linux/input.h>
++#include <linux/bmi/bmi_ioctl.h>
++
++ // IOCTL commands for BMI LCD driver
++#define BMI_LCD_RLEDOFF _IOW(BMI_LCD_IOCTL, 0x1, __u32) // turn off Red LED
++#define BMI_LCD_RLEDON _IOW(BMI_LCD_IOCTL, 0x2, __u32) // turn on Red LED
++#define BMI_LCD_GLEDOFF _IOW(BMI_LCD_IOCTL, 0x3, __u32) // turn off Green LED
++#define BMI_LCD_GLEDON _IOW(BMI_LCD_IOCTL, 0x4, __u32) // turn on Green LED
++#define BMI_LCD_VSYNC_DIS _IOW(BMI_LCD_IOCTL, 0x5, __u32) // Enable VSYNC output buffer
++#define BMI_LCD_VSYNC_EN _IOW(BMI_LCD_IOCTL, 0x6, __u32) // Disable VSYNC output buffer
++#define BMI_LCD_EN _IOW(BMI_LCD_IOCTL, 0x7, __u32) // Enable LCD component
++#define BMI_LCD_DIS _IOW(BMI_LCD_IOCTL, 0x8, __u32) // Disable LCD component
++#define BMI_LCD_SER_EN _IOW(BMI_LCD_IOCTL, 0x9, __u32) // Enable Seriallizer component
++#define BMI_LCD_SER_DIS _IOW(BMI_LCD_IOCTL, 0xa, __u32) // Disable Seriallizer component
++#define BMI_LCD_SETRST _IOW(BMI_LCD_IOCTL, 0xb, __u32) // Disable entire module
++#define BMI_LCD_CLRRST _IOW(BMI_LCD_IOCTL, 0xc, __u32) // Enable entire module
++#define BMI_LCD_SET_BL _IOW(BMI_LCD_IOCTL, 0xd, __u32) // Set IOX backlight bits [2:0]
++#define BMI_LCD_GETSTAT _IOR(BMI_LCD_IOCTL, 0xe, __u32) // Get IOX state
++#define BMI_LCD_ACTIVATE _IOW(BMI_LCD_IOCTL, 0xf, __u32) // Activate SER, TS, ACCEL
++#define BMI_LCD_DEACTIVATE _IOW(BMI_LCD_IOCTL, 0x10, __u32) // Deactivate SER, TS, ACCEL
++#define BMI_LCD_SUSPEND _IOW(BMI_LCD_IOCTL, 0x11, __u32) // Power down module
++#define BMI_LCD_RESUME _IOW(BMI_LCD_IOCTL, 0x12, __u32) // Power up module
++
++/*Izzy Additions*/
++#define BMI_LCD_MIN_XC 0
++#define BMI_LCD_MAX_XC 0x3fff
++#define BMI_LCD_MIN_YC 0
++#define BMI_LCD_MAX_YC 0x3fff
++
++/*struct lcd_ctl
++{
++ int slot;
++ struct cdev cdev;
++ struct device *class_dev;
++};
++*/
++
++//
++// Orientation - location of module 1-3 shorter edge (when facing LCD side)
++// when not FACEUP or FACEDOWN
++//
++// Note that orientation is only reported through bmi_lcd_ts[0-3]
++//
++#define ACC_PITCH_MSK (0xFFFF0000)
++#define ACC_ROLL_MSK (0xFFFF)
++
++ // touch screen input devices
++enum {
++ BMI_TS_M1, // bmi_lcd_ts0 - slot 0
++ BMI_TS_M2, // bmi_lcd_ts1 - slot 1
++ BMI_TS_M3, // bmi_lcd_ts2 - slot 2
++ BMI_TS_M4, // bmi_lcd_ts3 - slot 3
++ BMI_TS_M13, // bmi_lcd_ts4 - slot 0 and 2
++ BMI_TS_M24, // bmi_lcd_ts5 - slot 1 and 3
++ BMI_TS_M1234, // bmi_lcd_ts6 - slot 0-3
++ BMI_TS_NUM,
++} lcd_ts_t;
++
++#endif /* BMI_LCD_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_mdacc.h
+@@ -0,0 +1,518 @@
++/*-----------------------------------------------------------------------------
++ *
++ * File: include/linux/bmi/bug_mdacc.h
++ *
++ *-----------------------------------------------------------------------------
++ * This file contains information needed by application programs that use the
++ * Bug Motion Detector Accelerometer (MDACC) Plug-In Module.
++ *
++ * The Bug Motion Detector Accelerometer (MDACC) Plug-In Module is a circuit
++ * board that contains the following devices:
++ *
++ * a motion sensor,
++ * a 3-axis accelerometer
++ * a micro-controller.
++ * 1 Red LED
++ * 1 Green LED
++ *
++ * The micro-controller behaves as an SPI-slave device. The host controls
++ * the operation of the micro-controller by issuing sequences of SPI messages.
++ * The micro-controller periodically samples the motion sensor and the
++ * accelerometer. The micro-controller generates an interrupts to the host
++ * processor. The micro-controller provides data to the host in response
++ * to received SPI messages.
++ *
++ * Application software can the MDACC Plug-in modules using the following
++ * device drivers:
++ *
++ * BMI MDACC Control Driver
++ * BMI MDACC Motion Detector Driver
++ * BMI MDACC Accelerometer Driver
++ *
++ * These drivers allow for independent operation of MDACC peripheral devices.
++ *
++ * This file contains the interface definition for all 3 device drivers.
++ *
++ * ---------------------------------------------------------------------------
++ *
++ * Default Device Names:
++ *
++ * The following device nodes are created for each MDACC card present in the
++ * system.
++ *
++ * /dev/bmi_mdacc_ctl_mX where X = 1,2,3,4 (bmi connector number)
++ * /dev/bmi_mdacc_mot_mX where X = 1,2,3,4 (bmi connector number)
++ * /dev/bmi_mdacc_acc_mX where X = 1,2,3,4 (bmi connector number)
++ *
++ * If the MDACC is not present in a given slot, the corresponding device nodes
++ * are not created.
++ *
++ *----------------------------------------------------------------------------
++ *
++ * BMI MDACC Control Driver
++ *
++ *----------------------------------------------------------------------------
++ *
++ * This character driver provides access to the Red and Green LEDs via
++ * via the ioctl() system call.
++ *
++ * Supported system calls: open(), close(), ioctl().
++ *
++ * The following IOCTL commands are defined for this driver.
++ *
++ * BMI_MDACC_CTL_RED_LED_OFF
++ * BMI_MDACC_CTL_RED_LED_ON
++ * BMI_MDACC_CTL_GREEN_LED_OFF
++ * BMI_MDACC_CTL_GREEN_LED_ON
++ *
++ * Note that the 3rd argument to the ioctl system call are not used by the
++ * ioctl commands listed above.
++ *----------------------------------------------------------------------------
++ */
++
++/*----------------------------------------------------------------------------
++ *
++ * BMI MDACC Motion Detector Driver
++ *
++ *----------------------------------------------------------------------------
++ *
++ * This character driver provides access to the motion sensor via the SPI
++ * interface. This driver enforces single-open and stop-on-close behaviors.
++ *
++ *
++ * Supported system calls: open(), close(), ioctl(). read(), select().
++ *
++ * BMI MDACC Motion Detector ioctl() interface
++ *--------------------------------------------
++ *
++ * The following IOCTL commands are defined for this driver.
++ *
++ * BMI_MDACC_MOTION_DETECTOR_GET_STATUS
++ * BMI_MDACC_MOTION_DETECTOR_RUN
++ * BMI_MDACC_MOTION_DETECTOR_STOP
++ *
++ *
++ * The BMI_MDACC_MOTION_DETECTOR_RUN command sends an SPI message to the
++ * microcontroller to enable sampling of the motion detector status pin.
++ * This command does not use the 3rd parameter to the ioctl system call.
++ *
++ * The BMI_MDACC_MOTION_DETECTOR_STOP command sends an SPI message to the
++ * microcontroller to halt sampling of the motion detector status pin.
++ * This command does not use the 3rd parameter to the ioctl system call.
++ *
++ * The BMI_MDACC_MOTION_DETECTOR_GET_STATUS command gets the motion detector
++ * status byte that is maintained by the motion detector driver.
++ * The third argument to the ioctl system call should be the address of a
++ * the receive buffer that is 1 byte in size.
++ *
++ * Motion Detect Status Bit Descriptions
++ * ---------------------------------------
++ *
++ * The Motion Detect Status byte is returned by the system calls to the
++ * MDACC Motion Detector driver:
++ *
++ * ioctl(BMI_MDACC_MOTION_GET_STATUS)
++ * read()
++ *
++ * The following bits are defined in the status byte.
++ *
++ * BMI_MOTION_DETECT_STATUS
++ *
++ * This bit is the present status of the the motion detector status pin.
++ * A value of 1 indicates that motion is being detected.
++ * A value of 0 indicates that motion is not being detected.
++ *
++ *
++ * BMI_MOTION_DETECT_LATCHED_STATUS
++ *
++ * This bit is the latched status of the motion sensor. This bit is set to 1
++ * when the BMI_MOTION_DETECT_STATUS bit changes from 0 to 1. This bit will
++ * be cleared as the result of an "ioctl(BMI_MDACC_MOTION_GET_STATUS)" or a
++ * read() system call.
++ *
++ * BMI_MOTION_DETECT_DELTA
++ *
++ * This bit indicates that the motion detector status has changed from 1 to 0
++ * or has changed from 0 to 1. This bit will be cleared as the result of an
++ * "ioctl(BMI_MDACC_MOTION_GET_STATUS)" or read() system calls.
++ *
++ *
++ * BMI_MOTION_DETECT_ENABLED
++ *
++ * This bits is the state of the motion detector sampling and status reporting
++ * mechanism. A value of 1 indicates that the motion detector is enabled. A
++ * value of 0 indicates that the motion detector is disabled.
++ *
++ *
++ * Motion Detect read() system call
++ * --------------------------------
++ *
++ * The read() call for this driver allows the application program to read the
++ * motion detector status only when the status has changed.
++ *
++ * Prior to issuing a read() to this driver, the application must enabled the
++ * motion detector using the "ioctl(BMI_MDACC_MOTION_DETECTOR_RUN)" command.
++ *
++ * read parameters:
++ *
++ * buffer: status byte destination address.
++ * size: 1
++ *
++ * Motion Detect blocking read() behavior
++ * --------------------------------------
++ *
++ * If the motion detector status HAS NOT changed, then the driver will sleep
++ * waiting for the motion detect status to change.
++ *
++ * If the driver is awoken by a Motion Detect status change interrupt, the
++ * underlying hardware will be accessed (for a second time) and the motion
++ * detect status will be updated.
++ *
++ * The status data byte will be copied to the user-supplied buffer. The
++ * following bits will then be cleared in the motion detect status byte:
++ *
++ * BMI_MOTION_DETECT_LATCHED_STATUS
++ * BMI_MOTION_DETECT_DELTA
++ *
++ * The driver will then be marked as "not-ready-to-read".
++ *
++ * If the the driver is awoken by a signal, the driver will return failure (-1)
++ * and errno will be set to ERESTARTSYS.
++ *
++ *
++ * Motion Detect non-blocking read() behavior
++ * ------------------------------------------
++ * If the motion detector status HAS NOT changed prior to the non-blocking
++ * read() system call, then the driver will return failure (-1) and errno will
++ * be set to EAGAIN.
++ *
++ * If the motion detector status HAS changed prior to the non-blocking read()
++ * system call, the underlying hardware will be accessed and the motion detect
++ * status will be updated. The status data byte will be copied to the user
++ * supplied buffer. The following bits will then be cleared in the motion
++ * detect status byte:
++ *
++ * BMI_MOTION_DETECT_LATCHED_STATUS
++ * BMI_MOTION_DETECT_DELTA
++ *
++ * The driver will then be marked as "not-ready-to-read".
++ *
++ *
++ * Motion Detect select() system call
++ * -----------------------------------
++ *
++ * This driver supports select() for read only. Select for write and
++ * exception is not supported.
++ *
++ * When a Motion Detect interrupt occurs, the file descriptor corresponding
++ * to the Motion Detector driver will be marked as "ready for read".
++ *
++ * ---------------------------------------------------------------------------
++ */
++
++
++/*----------------------------------------------------------------------------
++ *
++ * BMI MDACC Accelerometer Driver
++ *
++ *----------------------------------------------------------------------------
++ *
++ * This character driver provides access to the accelerometer data via an SPI
++ * interface. This driver enforces single-open and stop-on-close behaviors.
++ *
++ * Supported system calls: open(), close(), ioctl(). read(), select().
++ *
++ *
++ * MDACC Accelerometer Driver Configuration
++ * -----------------------------------------
++ *
++ * The micro-controller on the MDACC Plug-In module uses an internal 10 bit A/D
++ * converter to sample the 3 analog output channels of the accelerometer
++ * device. The analog channels are sampled periodically at a rate that can be
++ * configured by an application program. When a set of 3 channel samples has
++ * been acquired, the micro-controller generates an interrupt to the host
++ * processor. The host processor then issues SPI messages to the
++ * micro-controller to obtain the 3 channel sample set.
++ *
++ * The MDACC Accelerometer Driver provides a read queue to store sample data
++ * until it can be read by the application program. The size of the read queue
++ * and a read-queue "ready" threshold can both be specified by the application
++ * program.
++ *
++ *
++ * MDACC Accelerometer Driver ioctl() interface
++ * --------------------------------------------
++
++ * The following IOCTL commands are defined for this driver.
++ *
++ * BMI_MDACC_ACCELEROMETER_SET_CONFIG
++ * BMI_MDACC_ACCELEROMETER_GET_CONFIG
++ * BMI_MDACC_ACCELEROMETER_RUN
++ * BMI_MDACC_ACCELEROMETER_STOP
++ *
++ *
++ * BMI_MDACC_ACCELEROMETER_SET_CONFIG
++ *
++ * This ioctl command transfers an mdacc_accel_config structure from the
++ * application program to the MDACC Accelerometer Driver.
++ * The third argument to this ioctl system call is the address of the an
++ * mdacc_accel_config structure.
++ *
++ * In the mdacc_accel_config structure, if the delay_mode field is 0,
++ * the values of the delay and delay resolution fields are ignored and
++ * and a default delay value of 4 milliseconds is used.
++ *
++ * BMI_MDACC_ACCELEROMETER_GET_CONFIG
++ *
++ * This ioctl command transfers an mdacc_accel_config structure from the
++ * MDACC Accelerometer Drive to the application program.
++ * The third argument to this ioctl system call is the address of the an
++ * mdacc_accel_config structure.
++ *
++ *
++ * BMI_MDACC_ACCELEROMETER_RUN
++ *
++ * This ioctl command will enable the accelerometer data aquistion in the MDACC
++ * Accelerometer Driver and in the MDACC micro-controller. The behavior of this
++ * ioctl command can also be invoked by an
++
++ * "ioctl(BMI_MDACC_ACCELEROMETER_SET_CONFIG)" system call with
++ * "mdacc_accel_config.run = 1".
++ *
++ * BMI_MDACC_ACCELEROMETER_STOP
++ *
++ * This ioctl command will disable the accelerometer data aquistion in the MDACC
++ * Accelerometer Driver and in the MDACC micro-controller. The behavior of this
++ * ioctl command can also be invoked by an
++ *
++ * "ioctl(BMI_MDACC_ACCELEROMETER_SET_CONFIG)" system call with
++ * "mdacc_accel_config.run = 0".
++ *
++ * Note that this behavior is also invoked in the close() system call if the
++ * accelerometer had previously been enabled.
++ *
++ *
++ * MDACC Accelerometer Driver read() interface
++ * -------------------------------------------
++ *
++ * The read() call for this driver allows the application program to read
++ * motion detector status only when the status has changed.
++ *
++ * Prior to issuing a read() to this driver, the application must enabled the
++ * motion detector using the "ioctl(BMI_MDACC_MOTION_DETECTOR_RUN)" command.
++ *
++ * read parameters:
++ *
++ * buffer: address of an array of mdacc_accel_sample structures.
++ * size: size of the mdacc_accel_sample array in bytes.
++ *
++ * Accelerometer blocking read() behavior
++ * --------------------------------------
++ *
++ * If the accelerometer read queue DOES NOT contain at least "read-threshold"
++ * number of sample set entries, then the driver will sleep.
++ *
++ * If the the driver is awoken by a signal, the driver will return failure (-1)
++ * and errno will be set to ERESTARTSYS.
++
++ * Otherwise, the requested number of sample sets are removed from the driver
++ * read queue and copied to user space. The number of bytes transfers will be
++ * returned to the application.
++ *
++ * At the end of the transfer, if the number of read queue entries is below the
++ * read-threshold, the the driver will then be marked as "not-ready-to-read".
++ *
++ *
++ * Accelerometer non-blocking read() behavior
++ * ------------------------------------------
++ * If the accelerometer read queue DOES NOT contain at least "read-threshold"
++ * number of sample set entries, then the driver will return failure (-1) and
++ * errno will be set to EAGAIN.
++ *
++ * Otherwise, the requested number of sample sets are removed from the driver
++ * read queue and copied to user space. The number of bytes transfers will be
++ * returned to the application.
++ *
++ * At the end of the transfer, if the number of read queue entries is below the
++ * read-threshold, the the driver will then be marked as "not-ready-to-read".
++ *
++ *
++ * Accelerometer select() system call
++ * -----------------------------------
++ *
++ * This driver supports select() for read only. Select for write and
++ * exception is not supported.
++ *
++ * When a data arrives and is inserted into the read queue and the number of
++ * queue entries meets or exceeds the read-threshold, the file descriptor
++ * corresponding to the Accelerometer driver will be marked as
++ * "ready for read".
++ * ---------------------------------------------------------------------------
++ *
++ * Accelerometer Data Samples
++ * ---------------------------
++ *
++ * The accelerometer analog outputs are sampled with a 10 bit A/D converter
++ * using 2.9V as a reference.
++ *
++ * An accelerometer output of 1.45V corresponds to "0g".
++ *
++ * The accelerometer outputs are scaled by the sensitivity settings.
++ *
++ * sensitivity scale factor
++ * ---------------------------
++ * 0 = 2.5G, 421 mV/G
++ * 1 = 3.3G, 316 mV/G
++ * 2 = 6.7G, 158 mV/G
++ * 3 = 10G, 105 mV/G
++ *
++ * The following equation converts an A/D sample to a G-Force value.
++ *
++ * G-force = ( ((digital sample) * (X mV/bit)) - 1450 mV) / (scale factor )
++ *
++ * ---------------------------------------------------------------------------
++ *
++ * Accelerometer Coordinate System.
++ *
++ *
++ * z axis: perpendicular to PCB.
++ * y axis: parallel to the long edge of the connector.
++ * x axis: perpendicular to the short edge of the connector.
++ *
++ *
++ * Top View Side View
++ *
++ * +--------------------------------------+ +-+
++ * | +x LEDS | | |
++ * | +------------------------+ | | +-----+
++ * | -y | connector underneath | +y | | |
++ * | +------------------------+ | | +-----+
++ * | ____ | | |
++ * | / \ | | |
++ * | | | | -z | | +z
++ * | \ ____ / | | |
++ * | | | |
++ * | motion sensor on top | | |
++ * | | | |
++ * | -x | | |
++ * +--------------------------------------+ +-+
++ *
++ * ---------------------------------------------------------------------------
++ */
++#ifndef LINUX_BMI_BMI_MDACC_H
++#define LINUX_BMI_BMI_MDACC_H
++
++#include <linux/bmi/bmi_ioctl.h>
++
++/* -------------------------
++ *
++ * MDACC Control Driver
++ *
++ *--------------------------
++ */
++#define BMI_MDACC_CTL_RED_LED_OFF \
++ _IOW(BMI_MDACC_IOCTL, 0, char) // Turn off red LED
++
++#define BMI_MDACC_CTL_RED_LED_ON \
++ _IOW(BMI_MDACC_IOCTL, 1, char) // Turn on red LED
++
++#define BMI_MDACC_CTL_GREEN_LED_OFF \
++ _IOW(BMI_MDACC_IOCTL, 2, char) // Turn off green LED
++
++#define BMI_MDACC_CTL_GREEN_LED_ON \
++ _IOW(BMI_MDACC_IOCTL, 3, char) // Turn on green LED
++
++
++/* -------------------------------
++ *
++ * MDACC Motion Detector Driver
++ *
++ *--------------------------------
++ */
++
++/* Status Byte Bit Definitions */
++
++#define BMI_MOTION_DETECT_STATUS (1<<3)
++#define BMI_MOTION_DETECT_LATCHED_STATUS (1<<2)
++#define BMI_MOTION_DETECT_DELTA (1<<1)
++#define BMI_MOTION_DETECT_ENABLED (1<<0)
++
++/* Ioctl Commands */
++
++#define BMI_MDACC_MOTION_DETECTOR_GET_STATUS \
++ _IOR (BMI_MDACC_IOCTL, 4, char)
++
++#define BMI_MDACC_MOTION_DETECTOR_RUN \
++ _IOW (BMI_MDACC_IOCTL, 5, char)
++
++#define BMI_MDACC_MOTION_DETECTOR_STOP \
++ _IOW (BMI_MDACC_IOCTL, 6, char)
++
++
++/* -------------------------------
++ *
++ * MDACC Accelerometer Driver
++ *
++ *--------------------------------
++ */
++struct mdacc_accel_sample {
++
++ unsigned short adc_0; //accelerometer channel Z, 10 bit, left justified
++ //referenced to VCC = 2.9V
++
++ unsigned short adc_1; //accelerometer channel Y, 10 bit, left justified.
++ //referenced to VCC = 2.9V.
++
++ unsigned short adc_2; //accelerometer channel X, 10 bit, left justified.
++ //referenced to VCC = 2.9 V.
++};
++
++
++struct mdacc_accel_config {
++
++ int read_queue_size; // number of 6-byte sample sets.
++
++ int read_queue_threshold; // number of 6-byte sample sets to queue
++ // before ready.
++
++ unsigned short delay; // timer ticks between the start of 2
++ // sucessive sample sets.
++
++ unsigned char delay_resolution; // timer tick resolution
++ // 1 = 1 usec,
++ // 2 = 8 usec,
++ // 3 = 64 usec,
++ // 4 = 256 usec,
++ // 5 = 1024 usec
++
++ unsigned char delay_mode; //0 = default delay = 5 millisecond,
++ // ignore delay and delay_resolution
++ //1 = configured delay
++
++ unsigned char run; //0 = sampling disabled
++ //1 = sampling enabled
++
++ unsigned char sensitivity; // 0 = 2.5G, 421 mV/G
++ // 1 = 3.3G, 316 mV/G
++ // 2 = 6.7G, 158 mV/G
++ // 3 = 10G, 105 mV/G
++
++};
++
++
++
++#define BMI_MDACC_ACCELEROMETER_SET_CONFIG \
++ _IOW (BMI_MDACC_IOCTL, 7, struct mdacc_accel_config)
++
++#define BMI_MDACC_ACCELEROMETER_GET_CONFIG \
++ _IOR (BMI_MDACC_IOCTL, 8, struct mdacc_accel_config)
++
++
++#define BMI_MDACC_ACCELEROMETER_RUN \
++ _IOW (BMI_MDACC_IOCTL, 9, char)
++
++#define BMI_MDACC_ACCELEROMETER_STOP \
++ _IOW (BMI_MDACC_IOCTL, 10, char)
++
++#define BMI_MDACC_LAST_USED (10)
++#endif
+--- /dev/null
++++ git/include/linux/bmi/bmi_projector.h
+@@ -0,0 +1,33 @@
++/*
++ * File: include/linux/bmi/bmi_projector.h
++ * Author: Suresh Rao
++ *
++ * This is the application header file for the BMI bus projector plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_PROJECTOR_H
++#define BMI_PROJECTOR_H
++
++#include <linux/input.h>
++#include <linux/bmi/bmi_ioctl.h>
++
++// IOCTL commands for BMI PROJECTOR driver
++#define BMI_PROJECTOR_ON _IOW(BMI_PROJECTOR_IOCTL, 0x1, __u32) // turn on projector
++#define BMI_PROJECTOR_MODE _IOW(BMI_PROJECTOR_IOCTL, 0x2, __u32) // turn on projector
++#define BMI_PROJECTOR_OFF _IOW(BMI_PROJECTOR_IOCTL, 0x3, __u32) // turn off projector
++#define BMI_PROJECTOR_BATTERY _IOW(BMI_PROJECTOR_IOCTL, 0x4, __u32) // Battery charger on to bug from projector
++
++// IOCTL commands for Encoder control
++#define BMI_PROJECTOR_HUE _IOW(BMI_PROJECTOR_IOCTL, 0x5, __u32) // Hue control in Encoder
++#define BMI_PROJECTOR_SATURATION _IOW(BMI_PROJECTOR_IOCTL, 0x6, __u32) // Saturation control in Encoder
++#define BMI_PROJECTOR_BRIGHTNESS _IOW(BMI_PROJECTOR_IOCTL, 0x7, __u32) // Brightness control in Encoder
++#define BMI_PROJECTOR_SHARPNESS _IOW(BMI_PROJECTOR_IOCTL, 0x8, __u32) // Sharpness control in Encoder
++#define BMI_PROJECTOR_CONTRAST _IOW(BMI_PROJECTOR_IOCTL, 0x9, __u32) // Contrast control in Encoder
++
++/* BMI_PROJECTOR_MODE settings */
++#define PROJECTOR_ECONOMY_MODE 0x0
++#define PROJECTOR_BRIGHT_MODE 0x1
++
++#endif /* BMI_PROJECTOR_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_sensor.h
+@@ -0,0 +1,673 @@
++/*
++ * File: include/linux/bmi/bmi_sensor.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus sensor plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_SENSOR_H
++#define BMI_SENSOR_H
++
++#include <linux/types.h>
++#include <linux/bmi/bmi_ioctl.h>
++
++// GPIO
++#define SENSOR_GPIO_RED_LED 3 // output
++#define SENSOR_GPIO_GREEN_LED 2 // output
++#define SENSOR_GPIO_PDOUT 1 // input - aproximity detector state
++#define SENSOR_GPIO_MOT_DET 0 // input - motion detector state
++
++#define SENSOR_GPIO_LED_ON 0
++#define SENSOR_GPIO_LED_OFF 1
++
++// I2C
++// I2C Slave Addresses
++#define BMI_MEE_I2C_ADDRESS 0x51 // 7-bit address - Module specific EEPROM
++#define BMI_IOX_I2C_ADDRESS 0x74 // 7-bit address - 2 banks I2C IO expander
++#define BMI_ADC_I2C_ADDRESS 0x48 // 7-bit address - ADC - humidity/acompass/sound/alight/aproximity
++#define BMI_PL_I2C_ADDRESS 0x44 // 7-bit address - digital proximity/light
++#define BMI_DLIGHT_I2C_ADDRESS 0x44 // 7-bit address - digital light
++#define BMI_TEMP_I2C_ADDRESS 0x4C // 7-bit address - temperature
++#define BMI_ACCEL_I2C_ADDRESS 0x1D // 7-bit address - accelerometer
++#define BMI_DCOMP_I2C_ADDRESS 0x1C // 7-bit address - digital compass
++
++// I2C IOX register addresses
++#define IOX_INPUT0_REG 0x0
++#define IOX_INPUT1_REG 0x1
++#define IOX_OUTPUT0_REG 0x2
++#define IOX_OUTPUT1_REG 0x3
++#define IOX_POLARITY0_REG 0x4
++#define IOX_POLARITY1_REG 0x5
++#define IOX_CONTROL0_REG 0x6
++#define IOX_CONTROL1_REG 0x7
++
++// IOX bit definitions
++// bank 0
++#define SENSOR_IOX_ACC_INT1 0 // Input - Accelerometer interrupt 1
++#define SENSOR_IOX_ACC_INT2 1 // Input - Accelerometer interrupt 2
++#define SENSOR_IOX_USB_FL_N 2 // Input - USB power interrupt
++#define SENSOR_IOX_USB_EN 3 // Output - USB power enable
++#define SENSOR_IOX_HUM_EN 4 // Output - Humidity sensor power enable
++#define SENSOR_IOX_MOT_DET 5 // Input - Motion Detector interrupt
++#define SENSOR_IOX_MOT_EN 6 // Output - Motion Detector interrupt enable
++#define SENSOR_IOX_COMP_RS_N 7 // Output - A/D Compass Reset (see Honeywell AN213)
++// bank 1
++#define SENSOR_IOX_PROX_RST_N 0 // Output - Analog Proximity sensor reset
++#define SENSOR_IOX_PROX_EN_N 1 // Output - Analog Proximity sensor enable
++#define SENSOR_IOX_PROX_OUT 2 // Input - Analog Proximity sensor output
++#define SENSOR_IOX_S_PK_CLR_N 3 // Output - Sound peak detector clear
++#define SENSOR_IOX_TEMP_INT 4 // Input - Termperature interrupt
++#define SENSOR_IOX_PL_INT 5 // Input - Proximity/Light interrupt
++#define SENSOR_IOX_MIC_EN 6 // Output - Sound power enanle
++#define SENSOR_IOX_DCOMP_INT 7 // Input - Digital Compass Interrupt
++
++// EEPROM contents
++struct sensor_eeprom_raw
++{
++ __u8 xsf_msb; /* byte 0x00 */ // analog and digital compass
++ __u8 xsf_lsb; /* byte 0x01 */ // analog and digital compass
++ __u8 ysf_msb; /* byte 0x02 */ // analog and digital compass
++ __u8 ysf_lsb; /* byte 0x03 */ // analog and digital compass
++ __u8 zsf_msb; /* byte 0x04 */ // analog and digital compass
++ __u8 zsf_lsb; /* byte 0x05 */ // analog and digital compass
++ __u8 xoff_msb; /* byte 0x06 */ // analog and digital compass
++ __u8 xoff_lsb; /* byte 0x07 */ // analog and digital compass
++ __u8 yoff_msb; /* byte 0x08 */ // analog and digital compass
++ __u8 yoff_lsb; /* byte 0x09 */ // analog and digital compass
++ __u8 zoff_msb; /* byte 0x0A */ // analog and digital compass
++ __u8 zoff_lsb; /* byte 0x0B */ // analog and digital compass
++ __u8 xdac; /* byte 0x0C */ // digital compass
++ __u8 ydac; /* byte 0x0D */ // digital compass
++ __u8 zdac; /* byte 0x0E */ // digital compass
++ __u8 adc_present; /* byte 0x0F - 0x1 == present */ // TI/Burr-Brown ADS7828
++ __u8 humidity_present; /* byte 0x10 - 0x1 == present */ // Honeywell HIH3030
++ __u8 acompass_present; /* byte 0x11 - 0x1 == present */ // Honeywell HMC6042/HMC1041Z
++ __u8 light_proximity_present; /* byte 0x12 - 0x1 == present */ // Intersil ISL29018
++ __u8 sound_present; /* byte 0x13 - 0x1 == present */ // discrete components
++ __u8 temperature_present; /* byte 0x14 - 0x1 == present */ // National LM95235
++ __u8 motion_present; /* byte 0x15 - 0x1 == present */ // Panasonic AMN44121
++ __u8 accel_present; /* byte 0x16 - 0x1 == present */ // Analog Devices ADXL345
++ __u8 dcompass_present; /* byte 0x17 - 0x1 == present */ // AsahiKASEI AK8973
++ __u8 aproximity_present; /* byte 0x18 - 0x1 == present */ // Avago APDS-9700
++ __u8 alight_present; /* byte 0x19 - 0x1 == present */ // Avago APDS-9002
++ __u8 dlight_present; /* byte 0x1A - 0x1 == present */ // Intersil ISL29003
++ __u8 acc302_present; /* byte 0x1B - 0x1 == present */ // ST LIS302DL
++};
++#define SENSOR_DEVICE_NOT_PRESENT (0x0)
++#define SENSOR_DEVICE_PRESENT (0x1)
++#define SENSOR_EE_SF_START (0x00)
++#define SENSOR_EE_OFF_START (0x06)
++#define SENSOR_EE_XDAC (0x0C)
++#define SENSOR_EE_YDAC (0x0D)
++#define SENSOR_EE_ZDAC (0x0E)
++#define SENSOR_PRESENT_START (0x0F)
++#define SENSOR_PRESENT_END (0x1B)
++
++struct sensor_comp_cal
++{
++ unsigned int xsf;
++ unsigned int ysf;
++ unsigned int zsf;
++ unsigned int xoff;
++ unsigned int yoff;
++ unsigned int zoff;
++};
++
++struct sensor_comp_dac
++{
++ unsigned char xdac;
++ unsigned char ydac;
++ unsigned char zdac;
++};
++
++// ADC (ADS7828) - humidity/acompass/sound/alight/aproximity
++// command write
++#define SENSOR_ADC_D10P (0x00 << 4) // positive diff - ch0 & ch1
++#define SENSOR_ADC_D23P (0x01 << 4) // positive diff - ch2 & ch3
++#define SENSOR_ADC_D45P (0x02 << 4) // positive diff - ch4 & ch5
++#define SENSOR_ADC_D67P (0x03 << 4) // positive diff - ch6 & ch7
++#define SENSOR_ADC_D10N (0x04 << 4) // negative diff - ch0 & ch1
++#define SENSOR_ADC_D23N (0x05 << 4) // negative diff - ch2 & ch3
++#define SENSOR_ADC_D45N (0x06 << 4) // negative diff - ch4 & ch5
++#define SENSOR_ADC_D67N (0x07 << 4) // negative diff - ch6 & ch7
++#define SENSOR_ADC_CH0 (0x08 << 4) // single ended ch0
++#define SENSOR_ADC_CH2 (0x09 << 4) // single ended ch2
++#define SENSOR_ADC_CH4 (0x0A << 4) // single ended ch4
++#define SENSOR_ADC_CH6 (0x0B << 4) // single ended ch6
++#define SENSOR_ADC_CH1 (0x0C << 4) // single ended ch1
++#define SENSOR_ADC_CH3 (0x0D << 4) // single ended ch3
++#define SENSOR_ADC_CH5 (0x0E << 4) // single ended ch5
++#define SENSOR_ADC_CH7 (0x0F << 4) // single ended ch7
++#define SENSOR_ADC_PD_OFF (0x00 << 2) // full power down
++#define SENSOR_ADC_PD_IR (0x01 << 2) // power down internal reference
++#define SENSOR_ADC_PD_ADC (0x02 << 2) // power down ADC
++#define SENSOR_ADC_PD_ON (0x03 << 2) // power up ADC
++// data read
++#define SENSOR_ADC_DATA_MSB (0x0F)
++#define SENSOR_ADC_DATA_LSB (0xFF)
++
++// ADC mapping
++#define SENSOR_ADC_SOUND_PEAK SENSOR_ADC_CH7
++#define SENSOR_ADC_SOUND_AVG SENSOR_ADC_CH6
++#define SENSOR_ADC_APROXIMITY SENSOR_ADC_CH5 // Analog proximity
++#define SENSOR_ADC_HUMIDITY SENSOR_ADC_CH4
++#define SENSOR_ADC_LIGHT SENSOR_ADC_CH3 // Analog light
++#define SENSOR_ADC_ACOMPASS_Z SENSOR_ADC_CH2 // Analog compass
++#define SENSOR_ADC_ACOMPASS_Y SENSOR_ADC_CH1 // Analog compass
++#define SENSOR_ADC_ACOMPASS_X SENSOR_ADC_CH0 // Analog compass
++
++// Light/Proximity
++#define SENSOR_PL_CMD1 (0x00) // command I
++ #define SENSOR_PL_CMD1_PD (0x00 << 5) // power down
++ #define SENSOR_PL_CMD1_ALS_1X (0x01 << 5) // ALS once
++ #define SENSOR_PL_CMD1_IR_1X (0x02 << 5) // IR once
++ #define SENSOR_PL_CMD1_PROX_1X (0x03 << 5) // Proximity once
++ #define SENSOR_PL_CMD1_ALS_CONT (0x05 << 5) // ALS continuous
++ #define SENSOR_PL_CMD1_IR_CONT (0x06 << 5) // IR continuous
++ #define SENSOR_PL_CMD1_PROX_CONT (0x07 << 5) // Proximity continuous
++ #define SENSOR_PL_CMD1_INT_TIMING (0x00) // Proximity continuous
++ #define SENSOR_PL_CMD1_EXT_TIMING (0x10) // Proximity continuous
++ #define SENSOR_PL_CMD1_DATA_ADC (0x00) // data is ADC value
++ #define SENSOR_PL_CMD1_DATA_TIMING (0x08) // data is ADC value
++ #define SENSOR_PL_CMD1_INT_STAT (0x04) // interrupt status
++ #define SENSOR_PL_CMD1_INT_1MS (0x00) // interrupt persist = 1 ms
++ #define SENSOR_PL_CMD1_INT_4MS (0x01) // interrupt persist = 4 ms
++ #define SENSOR_PL_CMD1_INT_8MS (0x02) // interrupt persist = 8 ms
++ #define SENSOR_PL_CMD1_INT_16MS (0x03) // interrupt persist = 16 ms
++#define SENSOR_PL_CMD2 (0x01) // command II
++ #define SENSOR_PL_CMD2_IR_LED_A (0x00) // sense IR from LED and ambient
++ #define SENSOR_PL_CMD2_IR_LED (0x80) // sense IR from LED only
++ #define SENSOR_PL_CMD2_MOD_DC (0x00) // IR LED modulation = DC
++ #define SENSOR_PL_CMD2_MOD_327K (0x40) // IR LED modulation = 327.7 kHz
++ #define SENSOR_PL_CMD2_DRIVE_12M (0x00 << 4) // IR drive current = 12.5 mA
++ #define SENSOR_PL_CMD2_DRIVE_25M (0x01 << 4) // IR drive current = 25 mA
++ #define SENSOR_PL_CMD2_DRIVE_50M (0x02 << 4) // IR drive current = 50 mA
++ #define SENSOR_PL_CMD2_DRIVE_100M (0x03 << 4) // IR drive current = 100 mA
++ #define SENSOR_PL_CMD2_ADC_RES_16 (0x00 << 2) // ADC resolution = 16 bits
++ #define SENSOR_PL_CMD2_ADC_RES_12 (0x01 << 2) // ADC resolution = 12 bits
++ #define SENSOR_PL_CMD2_ADC_RES_8 (0x02 << 2) // ADC resolution = 8 bits
++ #define SENSOR_PL_CMD2_ADC_RES_4 (0x03 << 2) // ADC resolution = 4 bits
++ #define SENSOR_PL_CMD2_ALS_RNG_1 (0x00) // ALS sensing = 1000 LUX
++ #define SENSOR_PL_CMD2_ALS_RNG_4 (0x01) // ALS sensing = 4000 LUX
++ #define SENSOR_PL_CMD2_ALS_RNG_16 (0x02) // ALS sensing = 16000 LUX
++ #define SENSOR_PL_CMD2_ALS_RNG_64 (0x03) // ALS sensing = 64000 LUX
++#define SENSOR_PL_DATA_LSB (0x02) // Data
++#define SENSOR_PL_DATA_MSB (0x03) // Data
++#define SENSOR_PL_INT_LT_LSB (0x04) // Low interrupt threshold LSB
++#define SENSOR_PL_INT_LT_MSB (0x05) // Low interrupt threshold MSB
++#define SENSOR_PL_INT_HT_LSB (0x06) // High interrupt threshold LSB
++#define SENSOR_PL_INT_HT_MSB (0x07) // High interrupt threshold MSB
++#define SENSOR_PL_EXT_SYNC (0x80) // write address to restart ADC integration
++
++struct sensor_pl_rw { // see the datasheet
++ unsigned char cmd1;
++ unsigned char cmd2;
++ unsigned char dl;
++ unsigned char dm;
++ unsigned char int_lt_lsb;
++ unsigned char int_lt_msb;
++ unsigned char int_ht_lsb;
++ unsigned char int_ht_msb;
++};
++
++// Digital Light
++#define SENSOR_DL_CMD (0x00) // command
++ #define SENSOR_DL_CMD_ADC_EN (0x80) // enable ADC core
++ #define SENSOR_DL_CMD_ADC_DIS (0x00) // disable ADC core
++ #define SENSOR_DL_CMD_PD (0x40) // power down
++ #define SENSOR_DL_CMD_EXT_SYNC (0x20) // external sync
++ #define SENSOR_DL_CMD_MODE_D1 (0x00) // ADC work mode = Diode 1, 16 bits
++ #define SENSOR_DL_CMD_MODE_D2 (0x04) // ADC work mode = Diode 2, 16 bits
++ #define SENSOR_DL_CMD_MODE_DIFF (0x08) // ADC work mode = I1-I2, 15 bits
++ #define SENSOR_DL_CMD_W16 (0x00) // 2^16 cycles
++ #define SENSOR_DL_CMD_W12 (0x01) // 2^12 cycles
++ #define SENSOR_DL_CMD_W8 (0x02) // 2^8 cycles
++ #define SENSOR_DL_CMD_W4 (0x03) // 2^4 cycles
++#define SENSOR_DL_CONT (0x01) // control
++ #define SENSOR_DL_CONT_INT (0x20) // interrupt status
++ #define SENSOR_DL_G1 (0x00) // gain < 1000 LUX
++ #define SENSOR_DL_G4 (0x04) // gain < 4000 LUX
++ #define SENSOR_DL_G16 (0x08) // gain < 16000 LUX
++ #define SENSOR_DL_G64 (0x0C) // gain < 64000 LUX
++ #define SENSOR_DL_IP1 (0x00) // interrupt persistence = 1 cycle
++ #define SENSOR_DL_IP4 (0x01) // interrupt persistence = 4 cycle
++ #define SENSOR_DL_IP8 (0x02) // interrupt persistence = 8 cycle
++ #define SENSOR_DL_IP16 (0x03) // interrupt persistence = 16 cycle
++#define SENSOR_DL_INT_THI (0x02) //
++#define SENSOR_DL_INT_TLO (0x03) //
++#define SENSOR_DL_SENSOR_LSB (0x04) //
++#define SENSOR_DL_SENSOR_MSB (0x05) //
++#define SENSOR_DL_TIMER_LSB (0x06) //
++#define SENSOR_DL_TIMER_MSB (0x07) //
++#define SENSOR_DL_EXT_SYNC (0x80) //
++#define SENSOR_DL_INT_CLR (0x40) //
++
++struct sensor_dl_rw { // see the datasheet
++ unsigned char cmd;
++ unsigned char control;
++ unsigned char int_thi;
++ unsigned char int_tlo;
++ unsigned int sensor_data;
++};
++
++// Temperature
++#define SENSOR_TEMP_LOC_MSB (0x00) // Local temperature MSB
++#define SENSOR_TEMP_ROFF_HIGH (0x11) // Remote offset high
++ // 10-bit plus sign format
++ #define SENSOR_TEMP_LOC_MSB_10B_SIGN (0x80) // Sign
++ #define SENSOR_TEMP_LOC_MSB_10B_64 (0x40)
++ #define SENSOR_TEMP_LOC_MSB_10B_32 (0x20)
++ #define SENSOR_TEMP_LOC_MSB_10B_16 (0x10)
++ #define SENSOR_TEMP_LOC_MSB_10B_8 (0x08)
++ #define SENSOR_TEMP_LOC_MSB_10B_4 (0x04)
++ #define SENSOR_TEMP_LOC_MSB_10B_2 (0x02)
++ #define SENSOR_TEMP_LOC_MSB_10B_1 (0x01)
++#define SENSOR_TEMP_LOC_LSB (0x30) // Local temperature LSB
++#define SENSOR_TEMP_ROFF_LOW (0x12) // Remote offset low
++ // 10-bit plus sign format
++ #define SENSOR_TEMP_LOC_LSB_10B_P5 (0x80)
++ #define SENSOR_TEMP_LOC_LSB_10B_P25 (0x40)
++ #define SENSOR_TEMP_LOC_LSB_10B_P125 (0x20)
++#define SENSOR_TEMP_REM_MSB (0x01) // Remote temperature MSB
++ // 12-bit plus sign format
++ #define SENSOR_TEMP_REM_MSB_12B_SIGN (0x80) // Sign
++ #define SENSOR_TEMP_REM_MSB_12B_64 (0x40)
++ #define SENSOR_TEMP_REM_MSB_12B_32 (0x20)
++ #define SENSOR_TEMP_REM_MSB_12B_16 (0x10)
++ #define SENSOR_TEMP_REM_MSB_12B_8 (0x08)
++ #define SENSOR_TEMP_REM_MSB_12B_4 (0x04)
++ #define SENSOR_TEMP_REM_MSB_12B_2 (0x02)
++ #define SENSOR_TEMP_REM_MSB_12B_1 (0x01)
++#define SENSOR_TEMP_REM_LSB (0x10) // Remote temperature LSB
++ // 12-bit plus sign format with filter off
++ #define SENSOR_TEMP_REM_LSB_12B_P5 (0x80)
++ #define SENSOR_TEMP_REM_LSB_12B_P25 (0x40)
++ #define SENSOR_TEMP_REM_LSB_12B_P125 (0x20)
++ // 12-bit plus sign format with filter on
++ #define SENSOR_TEMP_REM_LSB_12B_P0625 (0x10)
++ #define SENSOR_TEMP_REM_LSB_12B_P03125 (0x04)
++#define SENSOR_TEMP_UREM_MSB (0x31) // Remote unsigned temperature MSB
++ // 13-bit usigned format
++ #define SENSOR_TEMP_UREM_MSB_12B_128 (0x80)
++ #define SENSOR_TEMP_UREM_MSB_12B_64 (0x40)
++ #define SENSOR_TEMP_UREM_MSB_12B_32 (0x20)
++ #define SENSOR_TEMP_UREM_MSB_12B_16 (0x10)
++ #define SENSOR_TEMP_UREM_MSB_12B_8 (0x08)
++ #define SENSOR_TEMP_UREM_MSB_12B_4 (0x04)
++ #define SENSOR_TEMP_UREM_MSB_12B_2 (0x02)
++ #define SENSOR_TEMP_UREM_MSB_12B_1 (0x01)
++#define SENSOR_TEMP_UREM_LSB (0x32) // Remote unsigned temperature LSB
++ // 13-bit usigned format with filter off
++ #define SENSOR_TEMP_UREM_LSB_12B_P5 (0x80)
++ #define SENSOR_TEMP_UREM_LSB_12B_P25 (0x40)
++ #define SENSOR_TEMP_UREM_LSB_12B_P125 (0x20)
++ // 13-bit usigned format with filter on
++ #define SENSOR_TEMP_UREM_LSB_12B_P0625 (0x10)
++ #define SENSOR_TEMP_UREM_LSB_12B_P03125 (0x04)
++#define SENSOR_TEMP_CONF2 (0xBF) // Diode configuration
++ #define SENSOR_TEMP_CONF2_A0 (0x40) // A0 pin function
++ #define SENSOR_TEMP_CONF2_OS (0x00) // A0 pin function
++ #define SENSOR_TEMP_CONF2_OS_ON (0x20) // OS fault mask on
++ #define SENSOR_TEMP_CONF2_OS_OFF (0x00) // OS fault mask off
++ #define SENSOR_TEMP_CONF2_TCRIT_ON (0x10) // TCRIT fault mask on
++ #define SENSOR_TEMP_CONF2_TCRIT_OFF (0x00) // TCRIT fault mask off
++ #define SENSOR_TEMP_CONF2_DMOD1 (0x00) // Diode model 1
++ #define SENSOR_TEMP_CONF2_DMOD2 (0x08) // Diode model 1
++ #define SENSOR_TEMP_CONF2_FILT_OFF (0x00 << 1) // Filter off
++ #define SENSOR_TEMP_CONF2_FILT_ON (0x03 << 1) // Filter on
++#define SENSOR_TEMP_CONF1_RD (0x03) // General configuration
++#define SENSOR_TEMP_CONF1_WR (0x09) // General configuration
++ #define SENSOR_TEMP_CONF1_RUN (0x00) // Active/Converting
++ #define SENSOR_TEMP_CONF1_STOP (0x40) // Standby
++ #define SENSOR_TEMP_R_TCRIT_MASK_OFF (0x00) // Remote TCRIT
++ #define SENSOR_TEMP_R_TCRIT_MASK_ON (0x10) // Remote TCRIT
++ #define SENSOR_TEMP_R_OS_MASK_OFF (0x00) // Remote OS
++ #define SENSOR_TEMP_R_OS_MASK_ON (0x08) // Remote OS
++ #define SENSOR_TEMP_L_TCRIT_MASK_OFF (0x00) // Local TCRIT
++ #define SENSOR_TEMP_L_TCRIT_MASK_ON (0x04) // Local TCRIT
++ #define SENSOR_TEMP_L_OS_MASK_OFF (0x00) // Local OS
++ #define SENSOR_TEMP_L_OS_MASK_ON (0x02) // Local OS
++#define SENSOR_TEMP_CONV_RD (0x04) // Conversion rate
++#define SENSOR_TEMP_CONV_WR (0x0A) // Conversion rate
++ #define SENSOR_TEMP_CONV_CONT (0x00) // Continuous
++ #define SENSOR_TEMP_CONV_P364 (0x01) // .364 seconds
++ #define SENSOR_TEMP_CONV_1 (0x02) // 1 second
++ #define SENSOR_TEMP_CONV_2P5 (0x03) // 2.5 seconds
++#define SENSOR_TEMP_ONE_SHOT (0x0F) // Remote offset low
++#define SENSOR_TEMP_STAT1 (0x02) // Status 1
++ #define SENSOR_TEMP_STAT1_BUSY (0x80) // Converting
++ #define SENSOR_TEMP_STAT1_ROS (0x10) // Remote OS
++ #define SENSOR_TEMP_STAT1_DFAULT (0x04) // Diode Fault
++ #define SENSOR_TEMP_STAT1_RTCRIT (0x02) // Remote TCRIT
++ #define SENSOR_TEMP_STAT1_LOC (0x01) // Local OS & TCRIT
++#define SENSOR_TEMP_STAT2 (0x33) // Status 2
++ #define SENSOR_TEMP_STAT2_NR (0x80) // Not Ready - 30 ms power-up
++ #define SENSOR_TEMP_STAT2_TT (0x40) // TruTherm Diode detected
++#define SENSOR_TEMP_REM_OS_LIM_RD (0x07) // Remote OS limit
++#define SENSOR_TEMP_REM_OS_LIM_WR (0x0D) // Remote OS limit
++#define SENSOR_TEMP_LOC_OS_LIM (0x20) // Local OS limit
++#define SENSOR_TEMP_REM_TCRIT_LIM (0x19) // Remote T_Crit limit
++ #define SENSOR_TEMP_LIM_128 (0x80)
++ #define SENSOR_TEMP_LIM_64 (0x40)
++ #define SENSOR_TEMP_LIM_32 (0x20)
++ #define SENSOR_TEMP_LIM_16 (0x10)
++ #define SENSOR_TEMP_LIM_8 (0x08)
++ #define SENSOR_TEMP_LIM_4 (0x04)
++ #define SENSOR_TEMP_LIM_2 (0x02)
++ #define SENSOR_TEMP_LIM_1 (0x01)
++#define SENSOR_TEMP_HYSTERESIS (0x21) // Common hysteresis
++ #define SENSOR_TEMP_HYS_16 (0x10)
++ #define SENSOR_TEMP_HYS_8 (0x08)
++ #define SENSOR_TEMP_HYS_4 (0x04)
++ #define SENSOR_TEMP_HYS_2 (0x02)
++ #define SENSOR_TEMP_HYS_1 (0x01)
++#define SENSOR_TEMP_MAN_ID (0xFE) // Manufacture ID
++ #define SENSOR_TEMP_MAN_ID_DATA (0x01) // Manufacture ID
++#define SENSOR_TEMP_REV_ID (0xFF) // Revision ID
++ #define SENSOR_TEMP_REV_ID_DATA (0xB1) // Revision ID
++
++struct sensor_temp_rw { // see the datasheet
++ unsigned char address;
++ unsigned char d1;
++};
++
++// accelerometer
++// ADXL345
++#define SENSOR_ACC_ID (0x00) // Device ID
++ #define SENSOR_ACC_ID_DATA (0xE5) // Device ID
++#define SENSOR_ACC_TT (0x1D) // Tap threshold (62.5 mg/LSB)
++#define SENSOR_ACC_OFSX (0x1E) // X axis offset (15.6 mg/LSB)
++#define SENSOR_ACC_OFSY (0x1F) // Y axis offset (15.6 mg/LSB)
++#define SENSOR_ACC_OFSZ (0x20) // Z axis offset (15.6 mg/LSB)
++#define SENSOR_ACC_DUR (0x21) // Tap duration (625 us/LSB)
++#define SENSOR_ACC_LAT (0x22) // Tap latency (1.25 ms/LSB)
++#define SENSOR_ACC_WIN (0x23) // Tap window (1.25 ms/LSB)
++#define SENSOR_ACC_TAT (0x24) // Activity threshold (62.5 mg/LSB)
++#define SENSOR_ACC_TINAT (0x25) // Inactivity threshold (62.5 mg/LSB)
++#define SENSOR_ACC_TIM_INAT (0x26) // Inactivity time (1 s/LSB)
++#define SENSOR_ACC_AT_CONTROL (0x27) // Activity/Inactivity control
++ #define SENSOR_ACC_ATC_DC (0x00) // Active DC coupled
++ #define SENSOR_ACC_ATC_AC (0x80) // Active AC coupled
++ #define SENSOR_ACC_ATC_XE (0x40) // Active X enable
++ #define SENSOR_ACC_YTC_XE (0x20) // Active X enable
++ #define SENSOR_ACC_ZTC_XE (0x10) // Active X enable
++ #define SENSOR_ACC_ITC_DC (0x00) // Inactive DC coupled
++ #define SENSOR_ACC_ITC_AC (0x08) // Inactive AC coupled
++ #define SENSOR_ACC_ITC_XE (0x04) // Inactive X enable
++ #define SENSOR_ACC_ITC_YE (0x02) // Inactive Y enable
++ #define SENSOR_ACC_ITC_ZE (0x01) // Inactive Z enable
++#define SENSOR_ACC_T_FF (0x28) // Freefall Threshold (62.5 mg/LSB)
++#define SENSOR_ACC_TIM_FF (0x29) // Freefall Time (5 ms/LSB)
++#define SENSOR_ACC_TAP_AXES (0x2A) // Tap Axis control
++ #define SENSOR_ACC_TA_SUPRESS (0x08) // Supress Double Tap
++ #define SENSOR_ACC_TA_XYZE (0x07) // X,Y,Z Tap Enable
++ #define SENSOR_ACC_TA_XE (0x04) // X Tap Enable
++ #define SENSOR_ACC_TA_YE (0x02) // Y Tap Enable
++ #define SENSOR_ACC_TA_ZE (0x01) // Z Tap Enable
++#define SENSOR_ACC_TAP_STAT (0x2B) // Tap Status
++ #define SENSOR_ACC_TS_XA (0x40) // X Activity
++ #define SENSOR_ACC_TS_YA (0x20) // Y Activity
++ #define SENSOR_ACC_TS_ZA (0x10) // Z Activity
++ #define SENSOR_ACC_TS_XT (0x04) // X Tap
++ #define SENSOR_ACC_TS_YT (0x02) // Y Tap
++ #define SENSOR_ACC_TS_ZT (0x01) // Z Tap
++#define SENSOR_ACC_RATE (0x2C) // Data Rate control
++ #define SENSOR_ACC_RATE_LP (0x10) // Low Power Mode
++ #define SENSOR_ACC_RC_3200_1600 (0x0F) // _OUTPUT-DATA_BANDWIDTH
++ #define SENSOR_ACC_RC_1600_800 (0x0E)
++ #define SENSOR_ACC_RC_800_400 (0x0D)
++ #define SENSOR_ACC_RC_400_200 (0x0C)
++ #define SENSOR_ACC_RC_200_100 (0x0B)
++ #define SENSOR_ACC_RC_100_50 (0x0A)
++ #define SENSOR_ACC_RC_50_25 (0x09)
++ #define SENSOR_ACC_RC_25_12P5 (0x08)
++ #define SENSOR_ACC_RC_12P5_6P25 (0x07)
++ #define SENSOR_ACC_RC_6P25_3P125 (0x06)
++ #define SENSOR_ACC_RC_3P125_1P563 (0x05)
++ #define SENSOR_ACC_RC_1P563_P782 (0x04)
++ #define SENSOR_ACC_RC_P782_P39 (0x03)
++ #define SENSOR_ACC_RC_P39_P195 (0x02)
++ #define SENSOR_ACC_RC_P195_P098 (0x01)
++ #define SENSOR_ACC_RC_P098_P048 (0x00)
++#define SENSOR_ACC_POWER (0x2D) // Power control
++ #define SENSOR_ACC_P_LINK (0x20) // Activity/Inactivity Link mode
++ #define SENSOR_ACC_P_APM (0x10) // Auto Low Power
++ #define SENSOR_ACC_P_SM (0x00) // Standby
++ #define SENSOR_ACC_P_NORM (0x08) // Powered Up
++ #define SENSOR_ACC_P_SLEEP_NORM (0x00) // Not Sleep
++ #define SENSOR_ACC_P_SLEEP (0x04) // Sleep
++ #define SENSOR_ACC_P_W8 (0x00) // wakeup Frequency = 8 Hz
++ #define SENSOR_ACC_P_W4 (0x01) // wakeup Frequency = 4 Hz
++ #define SENSOR_ACC_P_W2 (0x02) // wakeup Frequency = 2 Hz
++ #define SENSOR_ACC_P_W1 (0x03) // wakeup Frequency = 1 Hz
++#define SENSOR_ACC_IE (0x2E) // Interrupt Enable
++#define SENSOR_ACC_IM (0x2F) // Interrupt Map
++#define SENSOR_ACC_IS (0x30) // Interrupt Source
++ #define SENSOR_ACC_I_DR (0x80) // Data Ready
++ #define SENSOR_ACC_I_ST (0x40) // Single Tap
++ #define SENSOR_ACC_I_DT (0x20) // Double Tap
++ #define SENSOR_ACC_I_A (0x10) // Activity
++ #define SENSOR_ACC_I_I (0x08) // Inactivity
++ #define SENSOR_ACC_I_FF (0x04) // Freefall
++ #define SENSOR_ACC_I_WM (0x02) // Watermark
++ #define SENSOR_ACC_I_OR (0x01) // Overrun
++#define SENSOR_ACC_DF (0x31) // Data Format
++ #define SENSOR_ACC_DF_SELF_TEST (0x80) // Self Test
++ #define SENSOR_ACC_DF_SPI_MODE4 (0x00) // SPI 4-Wire
++ #define SENSOR_ACC_DF_SPI_MODE3 (0x40) // SPI 3-Wire
++ #define SENSOR_ACC_DF_INT_INVERT (0x20) // Interrupt Active Low
++ #define SENSOR_ACC_DF_LENGTH (0x08) // 13-bit, 16g Enable
++ #define SENSOR_ACC_DF_POS (0x04) // MSB Left Justified
++ #define SENSOR_ACC_DF_R2 (0x00) // 2g
++ #define SENSOR_ACC_DF_R4 (0x01) // 4g
++ #define SENSOR_ACC_DF_R8 (0x02) // 8g
++ #define SENSOR_ACC_DF_R16 (0x03) // 16g
++#define SENSOR_ACC_DX0 (0x32) // Data X axis 0 (LSB)
++#define SENSOR_ACC_DX1 (0x33) // Data X axis 1 (MSB)
++#define SENSOR_ACC_DY0 (0x34) // Data Y axis 0 (LSB)
++#define SENSOR_ACC_DY1 (0x35) // Data Y axis 1 (MSB)
++#define SENSOR_ACC_DZ0 (0x36) // Data Z axis 0 (LSB)
++#define SENSOR_ACC_DZ1 (0x37) // Data Z axis 1 (MSB)
++#define SENSOR_ACC_FC (0x38) // FIFO Control
++ #define SENSOR_ACC_FC_BYP (0x00 << 6) // Bypass
++ #define SENSOR_ACC_FC_HOLD (0x01 << 6) // Hold after 32
++ #define SENSOR_ACC_FC_OF (0x02 << 6) // Discard after 32
++ #define SENSOR_ACC_FC_TRIG (0x03 << 6) // Hold on TRIGGER
++ #define SENSOR_ACC_FC_TRIG1 (0x00) // TRIGGER = INT1
++ #define SENSOR_ACC_FC_TRIG2 (0x20) // TRIGGER = INT2
++ #define SENSOR_ACC_FC_SAMP(x) (x) // See ADXL345 datasheet
++#define SENSOR_ACC_FS (0x39) // FIFO Status
++ #define SENSOR_ACC_FS_TRIG (0x80) // TRIGGER occurred
++ #define SENSOR_ACC_FS_ENTRIES_MSK (0x1F) // See ADXL345 datasheet
++
++// ST LIS302DL
++#define SENSOR_A3_WAI (0x0F) // Device ID
++ #define SENSOR_A3_WAI_ID (0x3B) // Device ID
++#define SENSOR_A3_CTRL1 (0x20) // Control Register
++ #define SENSOR_A3_CTRL1_DR100 (0x00) // sample data rate = 100 Hz
++ #define SENSOR_A3_CTRL1_DR400 (0x80) // sample data rate = 400 Hz
++ #define SENSOR_A3_CTRL1_PD (0x00) // power down
++ #define SENSOR_A3_CTRL1_PU (0x40) // power up
++ #define SENSOR_A3_CTRL1_FS (0x20) // See data sheet
++ #define SENSOR_A3_CTRL1_STP (0x10) // See data sheet
++ #define SENSOR_A3_CTRL1_STM (0x08) // See data sheet
++ #define SENSOR_A3_CTRL1_XYZEN (0x07) // X,Y,Z axis enable
++ #define SENSOR_A3_CTRL1_ZEN (0x04) // Z axis enable
++ #define SENSOR_A3_CTRL1_YEN (0x02) // Y axis enable
++ #define SENSOR_A3_CTRL1_XEN (0x01) // X axis enable
++#define SENSOR_A3_CTRL2 (0x21) // Control Register
++ #define SENSOR_A3_CTRL2_SIM (0x80) // SPI mode
++ #define SENSOR_A3_CTRL2_BOOT (0x40) // copy calibration from FLASH
++ #define SENSOR_A3_CTRL2_FILT_OFF (0x00) // internal filter bypassed
++ #define SENSOR_A3_CTRL2_FILT_ON (0x10) // internal filter enabled
++ #define SENSOR_A3_CTRL2_F2 (0x08) // WU2 filter enable
++ #define SENSOR_A3_CTRL2_F1 (0x04) // WU1 filter enable
++ #define SENSOR_A3_CTRL2_COEFF(x) (x & 0x3) // See data sheet
++#define SENSOR_A3_CTRL3 (0x22) // Control Register
++ #define SENSOR_A3_CTRL3_IH (0x00) // Interrupt active high
++ #define SENSOR_A3_CTRL3_IL (0x80) // Interrupt active low
++ #define SENSOR_A3_CTRL3_IPP (0x00) // Interrupt push/pull
++ #define SENSOR_A3_CTRL3_IOD (0x40) // Interrupt open drain
++ #define SENSOR_A3_CTRL3_I2C(x) ((x&0x7) << 3) // I2 config - See data sheet
++ #define SENSOR_A3_CTRL3_I1C(x) ((x&0x7)) // I1 config - See data sheet
++#define SENSOR_A3_HPF_RST (0x23) // High Pass Filter Reset - See data sheet
++#define SENSOR_A3_STAT (0x27) // Status
++ #define SENSOR_A3_STAT_ZYXOR (0x80) // ZYX overrun
++ #define SENSOR_A3_STAT_ZOR (0x40) // Z overrun
++ #define SENSOR_A3_STAT_YOR (0x20) // Y overrun
++ #define SENSOR_A3_STAT_XOR (0x10) // X overrun
++ #define SENSOR_A3_STAT_ZYXDA (0x08) // ZYX data available
++ #define SENSOR_A3_STAT_ZDA (0x04) // Z data available
++ #define SENSOR_A3_STAT_YDA (0x02) // Y data available
++ #define SENSOR_A3_STAT_XDA (0x01) // X data available
++#define SENSOR_A3_OUTX (0x29) // X Output
++#define SENSOR_A3_OUTY (0x2B) // Y Output
++#define SENSOR_A3_OUTZ (0x2D) // Z Output
++#define SENSOR_A3_CFG1 (0x30) // Configuration
++#define SENSOR_A3_CFG2 (0x34) // Configuration
++ #define SENSOR_A3_CFG_AOI (0x80) // AND/OR interrupts
++ #define SENSOR_A3_CFG_LIR (0x40) // latch interrupts into SRC
++ #define SENSOR_A3_CFG_ZHIE (0x20) // Z high enable
++ #define SENSOR_A3_CFG_ZLIE (0x10) // Z low enable
++ #define SENSOR_A3_CFG_YHIE (0x08) // Y high enable
++ #define SENSOR_A3_CFG_YLIE (0x04) // Y low enable
++ #define SENSOR_A3_CFG_XHIE (0x02) // X high enable
++ #define SENSOR_A3_CFG_XLIE (0x01) // X low enable
++#define SENSOR_A3_SRC1 (0x31) // Source
++#define SENSOR_A3_SRC2 (0x35) // Source
++ #define SENSOR_A3_SRC_IA (0x40) // interrupt active
++ #define SENSOR_A3_SRC_ZH (0x20) // Z high
++ #define SENSOR_A3_SRC_ZL (0x10) // Z low
++ #define SENSOR_A3_SRC_YH (0x08) // Y high
++ #define SENSOR_A3_SRC_YL (0x04) // Y low
++ #define SENSOR_A3_SRC_XH (0x02) // X high
++ #define SENSOR_A3_SRC_XL (0x01) // X low
++#define SENSOR_A3_THS1 (0x32) // Threshold
++#define SENSOR_A3_THS2 (0x36) // Threshold
++ #define SENSOR_A3_THS_DCRM (0x80) // Resetting mode - See data sheet
++ #define SENSOR_A3_THS_THS(x) (x & 0x7F) // FF/wakeup threshold
++#define SENSOR_A3_DUR1 (0x33) // Duration - See data sheet
++#define SENSOR_A3_DUR2 (0x37) // Duration - See data sheet
++#define SENSOR_A3_CCFG (0x38) // Click Configuration
++#define SENSOR_A3_CSRC (0x39) // Click Source
++ #define SENSOR_A3_CCS_LIR (0x40) // latch interrupt into SRC
++ #define SENSOR_A3_CCS_DZ (0x20) // double Z enable
++ #define SENSOR_A3_CCS_SZ (0x10) // single Z enable
++ #define SENSOR_A3_CCS_DY (0x08) // double Y enable
++ #define SENSOR_A3_CCS_SY (0x04) // single Y enable
++ #define SENSOR_A3_CCS_DX (0x02) // double X enable
++ #define SENSOR_A3_CCS_SX (0x01) // single X enable
++#define SENSOR_A3_CTHXY (0x3B) // Click X, Y Threshold
++ #define SENSOR_A3_CTHYX_Y(x) ((x&0xF) << 4) // Y Threshold
++ #define SENSOR_A3_CTHYX_X(x) (x&0xF) // X Threshold
++#define SENSOR_A3_CTHZ (0x3C) // Click Z Threshold
++ #define SENSOR_A3_CTHYX_Z(x) (x&0xF) // Z Threshold
++#define SENSOR_A3_CTL (0x3D) // Click Time Limit
++#define SENSOR_A3_CLAT (0x3E) // Click Latency
++#define SENSOR_A3_CWIN (0x3F) // Click Window
++
++// count always = 1 for LIS302DL
++struct sensor_acc_rw { // see the datasheets
++ unsigned char address;
++ unsigned int count; // number of bytes to read (1 or 2)
++ unsigned char data[2];
++};
++
++// digital compass
++#define SENSOR_DCOMP_ST (0xC0) // Status (RO)
++ #define SENSOR_DCOMP_ST_INT (0x01) // Interrupt
++ #define SENSOR_DCOMP_ST_EERW (0x02) // EEPROM R/W
++#define SENSOR_DCOMP_TMPS (0xC1) // Temperature(C) = 35+(120-TMPS)/1.6
++#define SENSOR_DCOMP_H1X (0xC2) // X Heading
++#define SENSOR_DCOMP_H1Y (0xC3) // Y Heading
++#define SENSOR_DCOMP_H1Z (0xC4) // Z Heading
++#define SENSOR_DCOMP_MS1 (0xE0) // Mode
++ #define SENSOR_DCOMP_MS1_SENSOR (0x0) // sensor mode
++ #define SENSOR_DCOMP_MS1_EEPROM (0x2) // EEPROM R/W
++ #define SENSOR_DCOMP_MS1_PD (0x3) // power down
++ #define SENSOR_DCOMP_MS1_EEWEN (0xA8) // EEPROM Write Enable
++#define SENSOR_DCOMP_HXDA (0xE1) // X DAC offset - see table 3 in datasheet
++#define SENSOR_DCOMP_HYDA (0xE2) // Y DAC offset - see table 3 in datasheet
++#define SENSOR_DCOMP_HZDA (0xE3) // Z DAC offset - see table 3 in datasheet
++#define SENSOR_DCOMP_HXGA (0xE4) // X gain - see table 4 in datasheet
++#define SENSOR_DCOMP_HYGA (0xE5) // Y gain - see table 4 in datasheet
++#define SENSOR_DCOMP_HZGA (0xE6) // Z gain - see table 4 in datasheet
++#define SENSOR_DCOMP_TS1 (0x5D) // FACTORY TEST - DO NOT USE
++#define SENSOR_DCOMP_EE_WRAL1 (0x60) // EE - batch write adress
++#define SENSOR_DCOMP_EE_ETS (0x62) // EE - temperature offset
++#define SENSOR_DCOMP_EE_EVIR (0x63) // EE - VREF/IREF adjustment
++#define SENSOR_DCOMP_EE_EIHE (0x64) // EE - HE drive/OSC
++#define SENSOR_DCOMP_EE_ETST (0x65) // EE - test
++#define SENSOR_DCOMP_EE_EHXGA (0x66) // EE - X gain adjustment
++#define SENSOR_DCOMP_EE_EHYGA (0x67) // EE - Y gain adjustment
++#define SENSOR_DCOMP_EE_EHZGA (0x68) // EE - Z gain adjustment
++
++// generic address/data byte R/W
++struct sensor_rw {
++ unsigned char address;
++ unsigned char data;
++};
++
++// Sensor driver ioctl definitions
++#define BMI_SENSOR_ON (1)
++#define BMI_SENSOR_OFF (0)
++#define BMI_SENSOR_RLEDOFF _IOW(BMI_SENSOR_IOCTL, 0x1, unsigned int) // Turn off red LED
++#define BMI_SENSOR_RLEDON _IOW(BMI_SENSOR_IOCTL, 0x2, unsigned int) // Turn on red LED
++#define BMI_SENSOR_GLEDOFF _IOW(BMI_SENSOR_IOCTL, 0x3, unsigned int) // Turn off green LED
++#define BMI_SENSOR_GLEDON _IOW(BMI_SENSOR_IOCTL, 0x4, unsigned int) // Turn on green LED
++#define BMI_SENSOR_GETSTAT _IOR(BMI_SENSOR_IOCTL, 0x5, unsigned int *) // Read IOX/GPIO (== GPIO<<16 | IOX1<<8 | IOX0)
++#define BMI_SENSOR_ADCWR _IOW(BMI_SENSOR_IOCTL, 0x6, unsigned int) // write ADC
++#define BMI_SENSOR_ADCRD _IOR(BMI_SENSOR_IOCTL, 0x7, unsigned int *) // read ADC
++#define BMI_SENSOR_HUMRD _IOR(BMI_SENSOR_IOCTL, 0x8, unsigned int *) // read ADC - Humidity sensor
++#define BMI_SENSOR_ACOMPRST _IO(BMI_SENSOR_IOCTL, 0x9) // analog Compass reset (toggle off/on)
++#define BMI_SENSOR_ACOMPXRD _IOR(BMI_SENSOR_IOCTL, 0xa, unsigned int *) // read ADC - Compass X axis
++#define BMI_SENSOR_ACOMPYRD _IOR(BMI_SENSOR_IOCTL, 0xb, unsigned int *) // read ADC - Compass Y axis
++#define BMI_SENSOR_ACOMPZRD _IOR(BMI_SENSOR_IOCTL, 0xc, unsigned int *) // read ADC - Compass Z axis
++#define BMI_SENSOR_PLWR _IOW(BMI_SENSOR_IOCTL, 0xd, struct sensor_pl_rw *) // write Proximity/Light sensor
++#define BMI_SENSOR_PLRD _IOR(BMI_SENSOR_IOCTL, 0xe, struct sensor_pl_rw *) // read Proximity/Light sensor
++#define BMI_SENSOR_PL_SYNC _IO(BMI_SENSOR_IOCTL, 0xf) // generate external SYNC for Proximity/Light or Digital Light
++#define BMI_SENSOR_PL_IWAIT _IOR(BMI_SENSOR_IOCTL, 0x10, struct sensor_pl_rw *) // wait for Proximity/Light interrupt - application sets up INT configuration
++#define BMI_SENSOR_SNDARD _IOR(BMI_SENSOR_IOCTL, 0x11, unsigned int *) // read ADC - Sound Average level
++#define BMI_SENSOR_SNDPRD _IOR(BMI_SENSOR_IOCTL, 0x12, unsigned int *) // read ADC - Sound Peak level read/clear
++#define BMI_SENSOR_SNDIRD _IOR(BMI_SENSOR_IOCTL, 0x13, unsigned int *) // read ADC - Instantaneous level read/clear
++#define BMI_SENSOR_TEMPWR _IOW(BMI_SENSOR_IOCTL, 0x14, struct sensor_temp_rw *) // write Temperature sensor
++#define BMI_SENSOR_TEMPRD _IOR(BMI_SENSOR_IOCTL, 0x15, struct sensor_temp_rw *) // read Temperature sensor
++#define BMI_SENSOR_TEMPRD_SL _IOR(BMI_SENSOR_IOCTL, 0x16, unsigned int *) // Read signed local
++#define BMI_SENSOR_TEMPRD_SR _IOR(BMI_SENSOR_IOCTL, 0x17, unsigned int *) // Read signed remote
++#define BMI_SENSOR_TEMPRD_UR _IOR(BMI_SENSOR_IOCTL, 0x18, unsigned int *) // Read unsigned remote
++#define BMI_SENSOR_TEMP_IWAIT _IO(BMI_SENSOR_IOCTL, 0x19) // wait for Temperature interrupt - application sets up INT configuration
++#define BMI_SENSOR_MOTRD _IOR(BMI_SENSOR_IOCTL, 0x1a, unsigned int *) // read real-time Motion state
++#define BMI_SENSOR_MOT_IWAIT _IOR(BMI_SENSOR_IOCTL, 0x1b, unsigned int *) // wait for Motion interrupt
++#define BMI_SENSOR_ACCWR _IOW(BMI_SENSOR_IOCTL, 0x1c, struct sensor_acc_rw *) // write Accelerometer
++#define BMI_SENSOR_ACCRD _IOR(BMI_SENSOR_IOCTL, 0x1d, struct sensor_acc_rw *) // read Accelerometer
++#define BMI_SENSOR_ACCXRD _IOR(BMI_SENSOR_IOCTL, 0x1e, unsigned int *) // read Accelerometer X
++#define BMI_SENSOR_ACCYRD _IOR(BMI_SENSOR_IOCTL, 0x1f, unsigned int *) // read Accelerometer Y
++#define BMI_SENSOR_ACCZRD _IOR(BMI_SENSOR_IOCTL, 0x20, unsigned int *) // read Accelerometer Z
++#define BMI_SENSOR_ACC_I1WAIT _IO(BMI_SENSOR_IOCTL, 0x21) // wait for Accelerometer interrupt 1 - application sets up INT configuration
++#define BMI_SENSOR_ACC_I2WAIT _IO(BMI_SENSOR_IOCTL, 0x22) // wait for Accelerometer interrupt 2 - application sets up INT configuration
++#define BMI_SENSOR_EEWR _IOW(BMI_SENSOR_IOCTL, 0x23, struct sensor_rw *) // write EEPROM
++#define BMI_SENSOR_EERD _IOR(BMI_SENSOR_IOCTL, 0x24, struct sensor_rw *) // read EEPROM
++#define BMI_SENSOR_MOT_IE _IOW(BMI_SENSOR_IOCTL, 0x25, unsigned int) // Motion interrupt enable (on = BMI_SENSOR_ON)
++#define BMI_SENSOR_USB_IWAIT _IO(BMI_SENSOR_IOCTL, 0x26) // wait for USB power flag interrupt
++#define BMI_SENSOR_USB_PWR_EN _IOW(BMI_SENSOR_IOCTL, 0x27, unsigned int) // USB power enable (on = BMI_SENSOR_ON)
++#define BMI_SENSOR_HUM_PWR_EN _IOW(BMI_SENSOR_IOCTL, 0x28, unsigned int) // Humidity power enable (on = BMI_SENSOR_ON)
++#define BMI_SENSOR_DCOM_RST _IOW(BMI_SENSOR_IOCTL, 0x29, unsigned int) // Digital Compass Reset (on = BMI_SENSOR_ON)
++#define BMI_SENSOR_COM_GCAL _IOR(BMI_SENSOR_IOCTL, 0x2a, struct sensor_comp_cal *) // Get compass calibation
++#define BMI_SENSOR_COM_SCAL _IOW(BMI_SENSOR_IOCTL, 0x2b, struct sensor_comp_cal *) // Set compass calibation
++#define BMI_SENSOR_DCWR _IOW(BMI_SENSOR_IOCTL, 0x2c, struct sensor_rw *) // write digital compass
++#define BMI_SENSOR_DCRD _IOR(BMI_SENSOR_IOCTL, 0x2d, struct sensor_rw *) // read digital compass
++#define BMI_SENSOR_DC_GDAC _IOR(BMI_SENSOR_IOCTL, 0x2e, struct sensor_comp_dac *) // Get digital compass DAC settings
++#define BMI_SENSOR_DC_SDAC _IOW(BMI_SENSOR_IOCTL, 0x2f, struct sensor_comp_dac *) // Set digital compass DAC settings
++#define BMI_SENSOR_DC_IWAIT _IO(BMI_SENSOR_IOCTL, 0x30) // wait for digital compass interrupt - application sets up INT configuration
++#define BMI_SENSOR_APROX_DUR _IOW(BMI_SENSOR_IOCTL, 0x31, unsigned int) // Analog Proximity LED burst time (in ms 2 <= arg <= 100)
++#define BMI_SENSOR_APROXRD _IOR(BMI_SENSOR_IOCTL, 0x32, unsigned int *) // read Analog proximity = (PDOUT << 16) | ADC_DATA
++#define BMI_SENSOR_ALIGHTRD _IOR(BMI_SENSOR_IOCTL, 0x33, unsigned int *) // read Analog Light
++#define BMI_SENSOR_DLIGHTWR _IOW(BMI_SENSOR_IOCTL, 0x34, struct sensor_dl_rw *) // write Digital Light sensor
++#define BMI_SENSOR_DLIGHTRD _IOR(BMI_SENSOR_IOCTL, 0x35, unsigned int) // read Digital Light sensor
++#define BMI_SENSOR_DLIGHT_IC _IO(BMI_SENSOR_IOCTL, 0x36) // Digital Light interrupt clear
++#define BMI_SENSOR_DLIGHT_IWAIT _IOR(BMI_SENSOR_IOCTL, 0x37, struct sensor_dl_rw *) // wait for Digital Light interrupt - application sets up INT configuration
++#define BMI_SENSOR_MIC_EN _IOW(BMI_SENSOR_IOCTL, 0x38, unsigned int) // Sound power enable (on = BMI_SENSOR_ON)
++
++#endif /* BMI_SENSOR_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_vh.h
+@@ -0,0 +1,135 @@
++/*
++ * File: include/linux/bmi/bmi_vh.h
++ * Author: Peter Giacomini <p.giacomini@encadis.com>
++ *
++ * This is the application header file for the BMI bus voh Hippel plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_VH_H
++#define BMI_VH_H
++
++#include <linux/bmi/bmi_ioctl.h>
++
++// GPIO
++#define VH_GPIO_RED_LED 3 // default to input
++#define VH_GPIO_GREEN_LED 2 // default to input
++#define VH_GPIO_1 1 // default to input
++#define VH_GPIO_0 0 // default to input
++
++#define VH_GPIO_LED_ON 0
++#define VH_GPIO_LED_OFF 1
++
++// I2C
++// I2C Slave Addresses
++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address
++#define VH_RDAC_I2C_ADDRESS 0x18 // 7-bit address
++#define VH_ADC_I2C_ADDRESS 0x24 // 7-bit address
++#define VH_DAC_I2C_ADDRESS 0x58 // 7-bit address
++
++// I2C IOX register addresses
++#define IOX_INPUT_REG 0x0
++#define IOX_OUTPUT_REG 0x1
++#define IOX_POLARITY_REG 0x2
++#define IOX_CONTROL 0x3
++
++#define VH_IOX_USB_FLG_N 7 // Input - H=normal, L=fault
++#define VH_IOX_USB_VEN 6 // output - H=power on, L=power off
++#define VH_IOX_B5 5 // set to output driven high to prevent interrupts
++#define VH_IOX_B4 4 // set to output driven high to prevent interrupts
++#define VH_IOX_B3 3 // set to output driven high to prevent interrupts
++#define VH_IOX_B2 2 // set to output driven high to prevent interrupts
++#define VH_IOX_B1 1 // set to output driven high to prevent interrupts
++#define VH_IOX_B0 0 // set to output driven high to prevent interrupts
++
++// programmable LDO digital resistor
++#define VH_RD_CMD_RDAC 0x00 // RDAC interface
++#define VH_RD_CMD_EE 0x20 // EEPROM interface
++ #define VH_TOL_HA 0x1E // Tolerance MSB
++ #define VH_TOL_LA 0x1F // Tolerance LSB
++#define VH_RD_CMD_WP 0x40 // EEPROM write protect
++#define VH_RD_CMD_NOP 0x80 // NOP
++#define VH_RD_CMD_ETOR 0xA0 // EEPROM -> RDAC
++#define VH_RD_CMD_RTOE 0xC0 // RDAC -> EEPROM
++
++// ADC
++#define VH_ADC_W1_EN 0xA0 // Word 1 Enable
++#define VH_ADC_W1_CH01 0x00 // diff - 0, 1
++#define VH_ADC_W1_CH23 0x01 // diff - 2, 3
++#define VH_ADC_W1_CH10 0x08 // diff - 1, 0
++#define VH_ADC_W1_CH32 0x09 // diff - 3, 2
++#define VH_ADC_W1_CH0 0x10 // single-ended - 0
++#define VH_ADC_W1_CH1 0x18 // single-ended - 1
++#define VH_ADC_W1_CH2 0x11 // single-ended - 2
++#define VH_ADC_W1_CH3 0x19 // single-ended - 3
++#define VH_ADC_W2_EN 0x80 // Word 2 Enable
++#define VH_ADC_W2_IM 0x40 // internal temp
++#define VH_ADC_W2_F(x) (((x) % 0x3) << 4) // rejection mode
++#define VH_ADC_W2_SPD 0x08 // speed 2X
++#define VH_ADC_W2_G(x) ((x) % 0x7) // gain
++
++struct vh_adc_wr { // see the datasheet
++ unsigned char w1; // VH_ADC_W1_*
++ unsigned char w2; // VH_ADC_W2_*
++};
++
++// DAC
++#define VH_DAC_W1_UA 0x00 // update DAC A output
++#define VH_DAC_W1_UB 0x10 // update DAC B output
++#define VH_DAC_W1_LA 0x40 // load DAC A input
++#define VH_DAC_W1_LB 0x50 // load DAC B input
++#define VH_DAC_W1_ALLA 0x80 // load DAC A input, update all outputs
++#define VH_DAC_W1_ALLB 0x90 // load DAC B input, update all outputs
++#define VH_DAC_W1_ALL 0xC0 // load all inputs, update all outputs
++#define VH_DAC_W1_ALLI 0xD0 // load all inputs
++#define VH_DAC_W1_UALL 0xE0 // update all - don't send data
++#define VH_DAC_W1_EC 0xF0 // Extended command
++ #define VH_DAC_BCH 0x0C // both channel A & B
++ #define VH_DAC_CHB 0x08 // channel B
++ #define VH_DAC_CHA 0x04 // channel A
++ #define VH_DAC_PD100K 0x03 // power down - 100K pull down
++ #define VH_DAC_PD1K 0x02 // power down - 1K pull down
++ #define VH_DAC_PDF 0x01 // power down - float
++ #define VH_DAC_PU 0x00 // power up
++#define VH_DAC_W1_RDA 0xF1 // Read A
++#define VH_DAC_W1_RDB 0xF2 // Read B
++
++struct vh_dac_wr {
++ unsigned char w1; // cmd | d[7:3]
++ unsigned char w2; // (d[3:0] << 4) || (VH_DAC_CH* | VH_DAC_P*)
++};
++
++// SPI
++#define BUF_MAX_SIZE (20)
++
++// SPI transfer structure
++struct spi_xfer {
++ unsigned char addr;
++ unsigned char data[2];
++} spi_xfer;
++
++// von hippel driver ioctl definitions
++#define BMI_VH_RLEDOFF _IOW(BMI_VH_IOCTL, 0x1, unsigned int) // Turn off red LED
++#define BMI_VH_RLEDON _IOW(BMI_VH_IOCTL, 0x2, unsigned int) // Turn on red LED
++#define BMI_VH_GLEDOFF _IOW(BMI_VH_IOCTL, 0x3, unsigned int) // Turn off green LED
++#define BMI_VH_GLEDON _IOW(BMI_VH_IOCTL, 0x4, unsigned int) // Turn on green LED
++#define BMI_VH_GETSTAT _IOR(BMI_VH_IOCTL, 0x5, unsigned int *) // READ IOX register
++#define BMI_VH_MKGPIO_OUT _IOW(BMI_VH_IOCTL, 0x6, unsigned int) // make a GPIO bit an output
++#define BMI_VH_MKGPIO_IN _IOW(BMI_VH_IOCTL, 0x7, unsigned int) // make a GPIO bit an input
++#define BMI_VH_SETGPIO _IOW(BMI_VH_IOCTL, 0x8, unsigned int) // set a GPIO output to 1
++#define BMI_VH_CLRGPIO _IOW(BMI_VH_IOCTL, 0x9, unsigned int) // set a GPIO output to 0
++#define BMI_VH_MKIOX_OUT _IOW(BMI_VH_IOCTL, 0xa, unsigned int) // make a IOX bit an output
++#define BMI_VH_MKIOX_IN _IOW(BMI_VH_IOCTL, 0xb, unsigned int) // make a IOX bit an input
++#define BMI_VH_SETIOX _IOW(BMI_VH_IOCTL, 0xc, unsigned int) // set a IOX output to 1
++#define BMI_VH_CLRIOX _IOW(BMI_VH_IOCTL, 0xd, unsigned int) // set a IOX output to 0
++#define BMI_VH_SETRDAC _IOW(BMI_VH_IOCTL, 0xe, unsigned int) // set LDO RDAC resistance
++#define BMI_VH_RDRDAC _IOW(BMI_VH_IOCTL, 0xf, unsigned int *) // read LDO RDAC resistance
++#define BMI_VH_ADCWR _IOW(BMI_VH_IOCTL, 0x10, struct vh_adc_wr *) // write ADC
++#define BMI_VH_ADCRD _IOW(BMI_VH_IOCTL, 0x11, unsigned int *) // read ADC
++#define BMI_VH_DACWR _IOW(BMI_VH_IOCTL, 0x12, struct vh_dac_wr *) // write DAC
++#define BMI_VH_DACRD _IOW(BMI_VH_IOCTL, 0x13, unsigned int *) // read DAC
++#define BMI_VH_READ_SPI _IOR(BMI_VH_IOCTL, 0x14, struct spi_xfer *) // read SPI - requires SPI EEPROM
++#define BMI_VH_WRITE_SPI _IOR(BMI_VH_IOCTL, 0x15, struct spi_xfer *) // write SPI - requires SPI EEPROM
++
++#endif /* BMI_VH_H */
++
+--- /dev/null
++++ git/include/linux/bmi/bmi_zb.h
+@@ -0,0 +1,83 @@
++/*
++ * File: include/linux/bmi/bmi_gps.h
++ * Author: V. Thavisri <v.thavisri@encadis.com
++ *
++ * This is the application header file for the BMI ZigBee plug-in
++ * module on the MX31 BUG platform.
++ */
++
++#ifndef BMI_ZBCNTL_H
++#define BMI_ZBCNTL_H
++
++#include <linux/bmi/bmi_ioctl.h>
++#include <linux/sockios.h>
++
++/* IOCTL commands for BMI ZB driver - char device portion */
++
++#define BMI_ZB_RLEDOFF _IO(BMI_ZIGBEE_IOCTL, 0x1)
++#define BMI_ZB_RLEDON _IO(BMI_ZIGBEE_IOCTL, 0x2)
++#define BMI_ZB_GLEDOFF _IO(BMI_ZIGBEE_IOCTL, 0x3)
++#define BMI_ZB_GLEDON _IO(BMI_ZIGBEE_IOCTL, 0x4)
++#define BMI_ZB_RESET _IO(BMI_ZIGBEE_IOCTL, 0x5)
++#define BMI_ZB_SPI_SIG _IO(BMI_ZIGBEE_IOCTL, 0x6)
++#define BMI_ZB_LOOPBACK _IO(BMI_ZIGBEE_IOCTL, 0x7)
++#define BMI_ZB_STARTREQ _IO(BMI_ZIGBEE_IOCTL, 0x8)
++#define BMI_ZB_UPDATE_STATE _IO(BMI_ZIGBEE_IOCTL, 0x9)
++
++
++/* IOCTL commands for BMI ZB driver - network device portion */
++
++#define SIOCSAPPREGISTER (SIOCDEVPRIVATE + 1)
++#define SIOCSALLOWBIND (SIOCDEVPRIVATE + 2)
++#define SIOCSPERMITJOINING (SIOCDEVPRIVATE + 3)
++#define SIOCGDEVICEINFO (SIOCDEVPRIVATE + 4)
++#define SIOCSRESET (SIOCDEVPRIVATE + 5)
++#define SIOCSBIND (SIOCDEVPRIVATE + 6)
++#define SIOCSZCOMMAND (SIOCDEVPRIVATE + 7)
++#define SIOCSSTARTREQ (SIOCDEVPRIVATE + 8)
++#define SIOCSFINDDEVICE (SIOCDEVPRIVATE + 9)
++#define SIOCSAFREGISTER (SIOCDEVPRIVATE + 10)
++#define SIOCSPOWERAMP (SIOCDEVPRIVATE + 11)
++#define SIOCDEBUG (SIOCDEVPRIVATE + 15)
++
++struct sockaddr_zb
++{
++ unsigned short z_family;
++ int z_ifindex;
++ unsigned char z_name[15];
++ unsigned short z_protocol;
++};
++
++/* move this #define to include/linux/socket.h */
++#define SOL_ZACCEL 275
++
++#define Z_PACKET_SOCK 0
++#define Z_CONTROL_SOCK 1
++#define Z_NUM_SOCK 2
++#define Z_NO_SOCK 0xFF
++
++/* Device-Specification Configuration Parameters */
++#define ZCD_NV_STARTUP_OPTION 0x03
++#define ZCD_NV_LOGICAL_TYPE 0x87
++#define ZCD_NV_POLL_RATE 0x24
++#define ZCD_NV_QUEUED_POLL_RATE 0x25
++#define ZCD_NV_RESPONSE_POLL_RATE 0x26
++#define ZCD_NV_POLL_FAILURE_RETRIES 0x29
++#define ZCD_NV_INDIRECT_MSG_TIMEOUT 0x2B
++#define ZCD_NV_APS_FRAME_RETRIES 0x43
++#define ZCD_NV_APS_ACK_WAIT_DURATION 0x44
++#define ZCD_NV_BINDING_TIME 0x46
++#define ZCD_NV_USERDESC 0x81
++
++// Network-Specification Configuration Parameters
++#define ZCD_NV_PANID 0x83
++#define ZCD_NV_CHANLIST 0x84
++#define ZCD_NV_PRECFGKEY 0x62
++#define ZCD_NV_PRECFGKEYS_ENABLE 0x63
++#define ZCD_NV_SECURITY_MODE 0x64
++#define ZCD_NV_BCAST_RETRIES 0x2E
++#define ZCD_NV_PASSIVE_ACK_TIMEOUT 0x2F
++#define ZCD_NV_BCAST_DELIVERY_TIME 0x30
++#define ZCD_NV_ROUTE_EXPIRY_TIME 0x2C
++
++#endif /* BMI_ZBCNTL_H */
+--- git.orig/include/linux/mod_devicetable.h
++++ git/include/linux/mod_devicetable.h
+@@ -341,10 +341,23 @@ struct eisa_device_id {
+ kernel_ulong_t driver_data;
+ };
+
+ #define EISA_DEVICE_MODALIAS_FMT "eisa:s%s"
+
++/* Bug Labs BeagleBug */
++
++struct bmi_device_id {
++ __u16 match_flags;
++ __u16 vendor;
++ __u16 product;
++ __u16 revision;
++};
++
++#define BMI_DEVICE_ID_MATCH_VENDOR (1)
++#define BMI_DEVICE_ID_MATCH_PRODUCT (2)
++#define BMI_DEVICE_ID_MATCH_REVISION (4)
++
+ struct parisc_device_id {
+ __u8 hw_type; /* 5 bits used */
+ __u8 hversion_rev; /* 4 bits */
+ __u16 hversion; /* 12 bits */
+ __u32 sversion; /* 20 bits */
+--- git.orig/scripts/mod/file2alias.c
++++ git/scripts/mod/file2alias.c
+@@ -286,10 +286,26 @@ static int do_pci_entry(const char *file
+ ADD(alias, "i", interface_mask == 0xFF, interface);
+ add_wildcard(alias);
+ return 1;
+ }
+
++/* Looks like: bmi:vNpNrN. */
++static int do_bmi_entry(const char *filename,
++ struct bmi_device_id *id, char *alias)
++{
++ id->match_flags = TO_NATIVE(id->match_flags);
++ id->vendor = TO_NATIVE(id->vendor);
++ id->product = TO_NATIVE(id->product);
++ id->revision = TO_NATIVE(id->revision);
++
++ strcpy(alias, "bmi:");
++ ADD(alias, "v", id->match_flags & BMI_DEVICE_ID_MATCH_VENDOR, id->vendor);
++ ADD(alias, "p", id->match_flags & BMI_DEVICE_ID_MATCH_PRODUCT, id->product);
++ ADD(alias, "r", id->match_flags & BMI_DEVICE_ID_MATCH_REVISION, id->revision);
++ return 1;
++}
++
+ /* looks like: "ccw:tNmNdtNdmN" */
+ static int do_ccw_entry(const char *filename,
+ struct ccw_device_id *id, char *alias)
+ {
+ id->match_flags = TO_NATIVE(id->match_flags);
+@@ -779,10 +795,14 @@ void handle_moddevtable(struct module *m
+ do_hid_entry, mod);
+ else if (sym_is(symname, "__mod_ieee1394_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct ieee1394_device_id), "ieee1394",
+ do_ieee1394_entry, mod);
++ else if (sym_is(symname, "__mod_bmi_device_table"))
++ do_table(symval, sym->st_size,
++ sizeof(struct bmi_device_id), "bmi",
++ do_bmi_entry, mod);
+ else if (sym_is(symname, "__mod_ccw_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct ccw_device_id), "ccw",
+ do_ccw_entry, mod);
+ else if (sym_is(symname, "__mod_ap_device_table"))
diff --git a/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch
new file mode 100644
index 0000000000..9da374041c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch
@@ -0,0 +1,169 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line
+Date: Wed, 2 Sep 2009 20:19:58 +0300
+Lines: 92
+Approved: news@gmane.org
+Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name>
+References: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1MiqiI-0003K3-An
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 14:20:23 +0000
+Original-Received: by bwz22 with SMTP id 22so788877bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT)
+X-Mailer: git-send-email 1.6.4.2
+In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04
+X-CRM114-Status: UNSURE ( 9.59 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.2 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -1.6 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025>
+
+Optimized version of copy_page() was written with assumption that cache
+line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes.
+
+This patch tries to generalize copy_page() to work with any cache line
+size if cache line size is multiple of 16 and page size is multiple of
+two cache line size.
+
+After this optimization we've got ~25% speedup on OMAP3(tested in
+userspace).
+
+There is test for kernelspace which trigger copy-on-write after fork():
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+ #define BUF_SIZE (10000*4096)
+ #define NFORK 200
+
+ int main(int argc, char **argv)
+ {
+ char *buf = malloc(BUF_SIZE);
+ int i;
+
+ memset(buf, 0, BUF_SIZE);
+
+ for(i = 0; i < NFORK; i++) {
+ if (fork()) {
+ wait(NULL);
+ } else {
+ int j;
+
+ for(j = 0; j < BUF_SIZE; j+= 4096)
+ buf[j] = (j & 0xFF) + 1;
+ break;
+ }
+ }
+
+ free(buf);
+ return 0;
+ }
+
+Before optimization this test takes ~66 seconds, after optimization
+takes ~56 seconds.
+
+Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com>
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/lib/copy_page.S | 16 ++++++++--------
+ 1 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
+index 6ae04db..6ee2f67 100644
+--- a/arch/arm/lib/copy_page.S
++++ b/arch/arm/lib/copy_page.S
+@@ -12,8 +12,9 @@
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+ #include <asm/asm-offsets.h>
++#include <asm/cache.h>
+
+-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 ))
+
+ .text
+ .align 5
+@@ -26,17 +27,16 @@
+ ENTRY(copy_page)
+ stmfd sp!, {r4, lr} @ 2
+ PLD( pld [r1, #0] )
+- PLD( pld [r1, #32] )
++ PLD( pld [r1, #L1_CACHE_BYTES] )
+ mov r2, #COPY_COUNT @ 1
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+-1: PLD( pld [r1, #64] )
+- PLD( pld [r1, #96] )
+-2: stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
+- stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
++1: PLD( pld [r1, #2 * L1_CACHE_BYTES])
++ PLD( pld [r1, #3 * L1_CACHE_BYTES])
++2:
++ .rept (2 * L1_CACHE_BYTES / 16 - 1)
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
++ .endr
+ subs r2, r2, #1 @ 1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmgtia r1!, {r3, r4, ip, lr} @ 4
+--
+1.6.4.2
diff --git a/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch b/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch
new file mode 100644
index 0000000000..e58d49c7a3
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch
@@ -0,0 +1,115 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line
+ size
+Date: Wed, 2 Sep 2009 19:11:52 +0300
+Lines: 39
+Approved: news@gmane.org
+Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1Mipeu-0000ZH-G2
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 13:12:04 +0000
+Original-Received: by bwz22 with SMTP id 22so735896bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT)
+X-Mailer: git-send-email 1.6.3.4
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2
+X-CRM114-Status: UNSURE ( 8.83 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.6 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.6 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -2.0 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017>
+
+Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5.
+It's not true at least for CPUs based on Cortex-A8.
+
+List of CPUs with cache line size != 32 should be expanded later.
+
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/include/asm/cache.h | 2 +-
+ arch/arm/mm/Kconfig | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
+index feaa75f..2ee7743 100644
+--- a/arch/arm/include/asm/cache.h
++++ b/arch/arm/include/asm/cache.h
+@@ -4,7 +4,7 @@
+ #ifndef __ASMARM_CACHE_H
+ #define __ASMARM_CACHE_H
+
+-#define L1_CACHE_SHIFT 5
++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT)
+ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+ /*
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index 83c025e..3c37d4c 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -771,3 +771,8 @@ config CACHE_XSC3L2
+ select OUTER_CACHE
+ help
+ This option enables the L2 cache on XScale3.
++
++config ARM_L1_CACHE_SHIFT
++ int
++ default 6 if ARCH_OMAP3
++ default 5
+--
+1.6.3.4
diff --git a/recipes/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch b/recipes/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch
deleted file mode 100644
index 902f87943d..0000000000
--- a/recipes/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch
+++ /dev/null
@@ -1,153 +0,0 @@
-From 742cc1e62f0d04333c51630f3020da000aeb6de1 Mon Sep 17 00:00:00 2001
-From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
-Date: Mon, 2 Mar 2009 19:36:26 +0200
-Subject: [PATCH] omap3: Add base address definitions and resources for OMAP 3 ISP
-
-This replaces earlier patch from Sergio Aguirre titled "[REVIEW PATCH 03/14]
-OMAP34XX: CAM: Resources fixes".
-
-Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
----
- arch/arm/mach-omap2/devices.c | 66 ++++++++++++++++++++++++---
- arch/arm/plat-omap/include/mach/omap34xx.h | 28 +++++++++++-
- 2 files changed, 85 insertions(+), 9 deletions(-)
-
-diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
-index dad4528..2568b0c 100644
---- a/arch/arm/mach-omap2/devices.c
-+++ b/arch/arm/mach-omap2/devices.c
-@@ -56,10 +56,60 @@ static inline void omap_init_camera(void)
-
- #elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
-
--static struct resource cam_resources[] = {
-+static struct resource omap3isp_resources[] = {
-+ {
-+ .start = OMAP3430_ISP_BASE,
-+ .end = OMAP3430_ISP_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_CBUFF_BASE,
-+ .end = OMAP3430_ISP_CBUFF_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_CCP2_BASE,
-+ .end = OMAP3430_ISP_CCP2_END,
-+ .flags = IORESOURCE_MEM,
-+ },
- {
-- .start = OMAP34XX_CAMERA_BASE,
-- .end = OMAP34XX_CAMERA_BASE + 0x1B70,
-+ .start = OMAP3430_ISP_CCDC_BASE,
-+ .end = OMAP3430_ISP_CCDC_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_HIST_BASE,
-+ .end = OMAP3430_ISP_HIST_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_H3A_BASE,
-+ .end = OMAP3430_ISP_H3A_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_PREV_BASE,
-+ .end = OMAP3430_ISP_PREV_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_RESZ_BASE,
-+ .end = OMAP3430_ISP_RESZ_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_SBL_BASE,
-+ .end = OMAP3430_ISP_SBL_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_CSI2A_BASE,
-+ .end = OMAP3430_ISP_CSI2A_END,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = OMAP3430_ISP_CSI2PHY_BASE,
-+ .end = OMAP3430_ISP_CSI2PHY_END,
- .flags = IORESOURCE_MEM,
- },
- {
-@@ -68,16 +118,16 @@ static struct resource cam_resources[] = {
- }
- };
-
--static struct platform_device omap_cam_device = {
-- .name = "omap34xxcam",
-+static struct platform_device omap3isp_device = {
-+ .name = "omap3isp",
- .id = -1,
-- .num_resources = ARRAY_SIZE(cam_resources),
-- .resource = cam_resources,
-+ .num_resources = ARRAY_SIZE(omap3isp_resources),
-+ .resource = omap3isp_resources,
- };
-
- static inline void omap_init_camera(void)
- {
-- platform_device_register(&omap_cam_device);
-+ platform_device_register(&omap3isp_device);
- }
- #else
- static inline void omap_init_camera(void)
-diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h
-index 27a1e45..3bfbdf7 100644
---- a/arch/arm/plat-omap/include/mach/omap34xx.h
-+++ b/arch/arm/plat-omap/include/mach/omap34xx.h
-@@ -49,6 +49,33 @@
- #define OMAP343X_CTRL_BASE OMAP343X_SCM_BASE
-
- #define OMAP34XX_IC_BASE 0x48200000
-+
-+#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000)
-+#define OMAP3430_ISP_CBUFF_BASE (OMAP3430_ISP_BASE + 0x0100)
-+#define OMAP3430_ISP_CCP2_BASE (OMAP3430_ISP_BASE + 0x0400)
-+#define OMAP3430_ISP_CCDC_BASE (OMAP3430_ISP_BASE + 0x0600)
-+#define OMAP3430_ISP_HIST_BASE (OMAP3430_ISP_BASE + 0x0A00)
-+#define OMAP3430_ISP_H3A_BASE (OMAP3430_ISP_BASE + 0x0C00)
-+#define OMAP3430_ISP_PREV_BASE (OMAP3430_ISP_BASE + 0x0E00)
-+#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000)
-+#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200)
-+#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400)
-+#define OMAP3430_ISP_CSI2A_BASE (OMAP3430_ISP_BASE + 0x1800)
-+#define OMAP3430_ISP_CSI2PHY_BASE (OMAP3430_ISP_BASE + 0x1970)
-+
-+#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F)
-+#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077)
-+#define OMAP3430_ISP_CCP2_END (OMAP3430_ISP_CCP2_BASE + 0x1EF)
-+#define OMAP3430_ISP_CCDC_END (OMAP3430_ISP_CCDC_BASE + 0x0A7)
-+#define OMAP3430_ISP_HIST_END (OMAP3430_ISP_HIST_BASE + 0x047)
-+#define OMAP3430_ISP_H3A_END (OMAP3430_ISP_H3A_BASE + 0x05F)
-+#define OMAP3430_ISP_PREV_END (OMAP3430_ISP_PREV_BASE + 0x09F)
-+#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB)
-+#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB)
-+#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F)
-+#define OMAP3430_ISP_CSI2A_END (OMAP3430_ISP_CSI2A_BASE + 0x16F)
-+#define OMAP3430_ISP_CSI2PHY_END (OMAP3430_ISP_CSI2PHY_BASE + 0x007)
-+
- #define OMAP34XX_IVA_INTC_BASE 0x40000000
- #define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000)
- #define OMAP34XX_HSUSB_HOST_BASE (L4_34XX_BASE + 0x64000)
-@@ -56,7 +83,6 @@
- #define OMAP34XX_SR1_BASE 0x480C9000
- #define OMAP34XX_SR2_BASE 0x480CB000
-
--#define OMAP34XX_CAMERA_BASE (L4_34XX_BASE + 0xBC000)
- #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000)
-
-
---
-1.5.6.5
-
diff --git a/recipes/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch b/recipes/linux/linux-omap-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
index f796ce8346..3390599292 100644
--- a/recipes/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch
+++ b/recipes/linux/linux-omap-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
@@ -1,99 +1,97 @@
-From 3041daa54b49bcb6ab444c7b9e14bc6a1ade6236 Mon Sep 17 00:00:00 2001
-From: Vaibhav Hiremath <hvaibhav@ti.com>
-Date: Fri, 13 Feb 2009 14:44:20 +0530
-Subject: [PATCH 1/2] Resizer and Previewer driver added to commit
+From 38f3cd5564a466e5251fc2ff47e0504148922304 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:18:56 +0530
+Subject: [PATCH 23/26] OMAP-Resizer: Basic Resizer refreshed with latest gitorious tree
-The Resizer and Previewer driver added to the commit
-from the patch submitted by Sergio on 12 Dec 2008.
+This is same resizer driver patch posted by Sergio onto
+mailing list quite a some time back. This commit refreshes
+the same patch on top of latest gitorious.org tree.
-The new WTBU code base and Nokia fixes package doesn't contain
-standalone resizer driver support.
+List of New/Modified files:
+ modified: drivers/media/video/Kconfig
+ modified: drivers/media/video/isp/Makefile
+ modified: drivers/media/video/isp/isp.c
+ modified: drivers/media/video/isp/ispreg.h
+ new file: drivers/media/video/isp/omap_resizer.c
+ new file: include/linux/omap_resizer.h
-Following major changes done -
-
- - Added stand-alone resizer driver support
- in isp.c file.
- - Seperate Kconfig file created
- - hardware access of resizer module fixed as per new
- isp.c
-
-Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+TODO:
+ - Resizer driver needs to be independent from camera and ISP
+ - Custom patches implemented ontop of PSP1.0.2 release
+ to fix some V4L2-buf layer issues.
+ -
---
- drivers/media/video/Kconfig | 5 +-
- drivers/media/video/isp/Kconfig | 16 +
- drivers/media/video/isp/Makefile | 7 +
- drivers/media/video/isp/isp.c | 12 +
- drivers/media/video/isp/ispmmu.c | 1 +
- drivers/media/video/isp/omap_previewer.c | 825 +++++++++++++++
- drivers/media/video/isp/omap_previewer.h | 162 +++
- drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++
- include/linux/omap_resizer.h | 136 +++
- 9 files changed, 2794 insertions(+), 4 deletions(-)
- create mode 100644 drivers/media/video/isp/Kconfig
- create mode 100644 drivers/media/video/isp/omap_previewer.c
- create mode 100644 drivers/media/video/isp/omap_previewer.h
+ drivers/media/video/Kconfig | 7 +
+ drivers/media/video/isp/Makefile | 4 +
+ drivers/media/video/isp/isp.c | 15 +
+ drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++++
+ include/linux/omap_resizer.h | 136 +++
+ 5 files changed, 1796 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/video/isp/omap_resizer.c
create mode 100644 include/linux/omap_resizer.h
-diff --git a/drivers/media/video/isp/Kconfig b/drivers/media/video/isp/Kconfig
-new file mode 100644
-index 0000000..acda63b
---- /dev/null
-+++ b/drivers/media/video/isp/Kconfig
-@@ -0,0 +1,16 @@
-+# Kconfig for OMAP3 ISP driver
-+
-+config VIDEO_OMAP3_ISP
-+ tristate
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 3cdb5a4..d2b4ae1 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -720,6 +720,13 @@ config VIDEO_OMAP3
+ ---help---
+ Driver for an OMAP 3 camera controller.
+
++config VIDEO_OMAP34XX_ISP_RESIZER
++ tristate "OMAP ISP Resizer"
++ depends on VIDEO_V4L2 && ARCH_OMAP34XX
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_SG
++ select OMAP_IOMMU
+
-+config VIDEO_OMAP34XX_ISP_PREVIEWER
-+ tristate "OMAP ISP Previewer"
-+ depends on !ARCH_OMAP3410
-+ select VIDEO_OMAP3_ISP
-+
-+config VIDEO_OMAP34XX_ISP_RESIZER
-+ tristate "OMAP ISP Resizer"
-+ depends on !ARCH_OMAP3410
-+ select VIDEO_OMAP3_ISP
+ config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA
diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
-index 0f9301c..ed10a51 100644
+index f14d617..d171fb9 100644
--- a/drivers/media/video/isp/Makefile
+++ b/drivers/media/video/isp/Makefile
-@@ -7,6 +7,13 @@ else
+@@ -7,6 +7,10 @@ else
isp-mod-objs += \
isp.o ispccdc.o ispmmu.o \
isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
+
-+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER) += \
-+ omap_previewer.o
-+
+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
+ omap_resizer.o
+
endif
- obj-$(CONFIG_VIDEO_OMAP3_ISP) += isp-mod.o
+ obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
-index 6034a56..09a1792 100644
+index 54c839b..f1f92b4 100644
--- a/drivers/media/video/isp/isp.c
+++ b/drivers/media/video/isp/isp.c
-@@ -521,6 +521,13 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
- OMAP3_ISP_IOMEM_MAIN,
- ISP_IRQ0ENABLE);
+@@ -505,6 +505,12 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ IRQ0ENABLE_PRV_DONE_IRQ);
break;
+ case CBK_RESZ_DONE:
-+ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
-+ ISP_IRQ0STATUS);
-+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE) |
-+ IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
-+ ISP_IRQ0ENABLE);
++ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_RSZ_DONE_IRQ);
+ break;
default:
break;
}
-@@ -996,6 +1003,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
+@@ -556,6 +562,10 @@ int isp_unset_callback(enum isp_callback_type type)
+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ ~IRQ0ENABLE_PRV_DONE_IRQ);
+ break;
++ case CBK_RESZ_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_RSZ_DONE_IRQ);
++ break;
+ default:
+ break;
+ }
+@@ -938,6 +948,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
if (!ispresizer_busy())
ispresizer_config_shadow_registers();
isp_buf_process(bufs);
@@ -105,1017 +103,6 @@ index 6034a56..09a1792 100644
}
}
-diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
-index 076aea1..b943d5b 100644
---- a/drivers/media/video/isp/ispmmu.c
-+++ b/drivers/media/video/isp/ispmmu.c
-@@ -289,6 +289,7 @@ int ispmmu_get_mapeable_space(void)
- return (L2P_TABLE_NR - no_of_l2p_alloted) * ISPMMU_TTB_ENTRIES_NR *
- ISPMMU_L2D_ENTRIES_NR;
- }
-+EXPORT_SYMBOL_GPL(ispmmu_get_mapeable_space);
-
- /**
- * ispmmu_map - Map a physically contiguous buffer to ISP space.
-diff --git a/drivers/media/video/isp/omap_previewer.c b/drivers/media/video/isp/omap_previewer.c
-new file mode 100644
-index 0000000..634a056
---- /dev/null
-+++ b/drivers/media/video/isp/omap_previewer.c
-@@ -0,0 +1,825 @@
-+/*
-+ * drivers/media/video/isp/omap_previewer.c
-+ *
-+ * Wrapper for Preview module in TI's OMAP3430 ISP
-+ *
-+ * Copyright (C) 2008 Texas Instruments, Inc.
-+ *
-+ * Contributors:
-+ * Leonides Martinez <leonides.martinez@ti.com>
-+ * Sergio Aguirre <saaguirre@ti.com>
-+ *
-+ * This package is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-+ */
-+
-+#include <linux/mutex.h>
-+#include <linux/cdev.h>
-+#include <linux/device.h>
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/uaccess.h>
-+#include <linux/io.h>
-+#include <media/v4l2-dev.h>
-+#include <asm/cacheflush.h>
-+
-+#include "isp.h"
-+#include "ispmmu.h"
-+#include "ispreg.h"
-+#include "omap_previewer.h"
-+
-+#define OMAP_PREV_NAME "omap-previewer"
-+
-+static int prev_major = -1;
-+static struct device *prev_dev;
-+static struct class *prev_class;
-+static struct prev_device *prevdevice;
-+static struct platform_driver omap_previewer_driver;
-+
-+static u32 prev_bufsize;
-+
-+/**
-+ * prev_calculate_crop - Calculate crop size according to device parameters
-+ * @device: Structure containing ISP preview wrapper global information
-+ * @crop: Structure containing crop size
-+ *
-+ * This function is used to calculate frame size reduction depending on
-+ * the features enabled by the application.
-+ **/
-+static void prev_calculate_crop(struct prev_device *device,
-+ struct prev_cropsize *crop)
-+{
-+ dev_dbg(prev_dev, "prev_calculate_crop E\n");
-+
-+ if (!device || !crop) {
-+ dev_err(prev_dev, "\nErron in argument");
-+ return;
-+ }
-+
-+ isppreview_try_size(device->params->size_params.hsize,
-+ device->params->size_params.vsize,
-+ &crop->hcrop, &crop->vcrop);
-+ crop->hcrop &= PREV_16PIX_ALIGN_MASK;
-+ dev_dbg(prev_dev, "prev_calculate_crop L\n");
-+}
-+
-+/**
-+ * prev_get_status - Get status of ISP preview module
-+ * @status: Structure containing the busy state.
-+ *
-+ * Checks if the ISP preview module is busy.
-+ *
-+ * Returns 0 if successful, or -EINVAL if the status parameter is invalid.
-+ **/
-+static int prev_get_status(struct prev_status *status)
-+{
-+ if (!status) {
-+ dev_err(prev_dev, "get_status: invalid parameter\n");
-+ return -EINVAL;
-+ }
-+ status->hw_busy = (char)isppreview_busy();
-+ return 0;
-+}
-+
-+/**
-+ * prev_hw_setup - Stores the desired configuration in the proper HW registers
-+ * @config: Structure containing the desired configuration for ISP preview
-+ * module.
-+ *
-+ * Reads the structure sent, and modifies the desired registers.
-+ *
-+ * Always returns 0.
-+ **/
-+static int prev_hw_setup(struct prev_params *config)
-+{
-+ dev_dbg(prev_dev, "prev_hw_setup E\n");
-+
-+ if (config->features & PREV_AVERAGER)
-+ isppreview_config_averager(config->average);
-+ else
-+ isppreview_config_averager(0);
-+
-+ if (config->features & PREV_INVERSE_ALAW)
-+ isppreview_enable_invalaw(1);
-+ else
-+ isppreview_enable_invalaw(0);
-+
-+ if (config->features & PREV_HORZ_MEDIAN_FILTER) {
-+ isppreview_config_hmed(config->hmf_params);
-+ isppreview_enable_hmed(1);
-+ } else
-+ isppreview_enable_hmed(0);
-+
-+ if (config->features & PREV_DARK_FRAME_SUBTRACT) {
-+ isppreview_set_darkaddr(config->drkf_params.addr);
-+ isppreview_config_darklineoffset(config->drkf_params.offset);
-+ isppreview_enable_drkframe(1);
-+ } else
-+ isppreview_enable_drkframe(0);
-+
-+ if (config->features & PREV_LENS_SHADING) {
-+ isppreview_config_drkf_shadcomp(config->lens_shading_shift);
-+ isppreview_enable_shadcomp(1);
-+ } else
-+ isppreview_enable_shadcomp(0);
-+
-+ dev_dbg(prev_dev, "prev_hw_setup L\n");
-+ return 0;
-+}
-+
-+/**
-+ * prev_validate_params - Validate configuration parameters for Preview Wrapper
-+ * @params: Structure containing configuration parameters
-+ *
-+ * Validate configuration parameters for Preview Wrapper
-+ *
-+ * Returns 0 if successful, or -EINVAL if a parameter value is invalid.
-+ **/
-+static int prev_validate_params(struct prev_params *params)
-+{
-+ if (!params) {
-+ dev_err(prev_dev, "validate_params: error in argument");
-+ goto err_einval;
-+ }
-+
-+ if ((params->features & PREV_AVERAGER) == PREV_AVERAGER) {
-+ if ((params->average != NO_AVE)
-+ && (params->average != AVE_2_PIX)
-+ && (params->average != AVE_4_PIX)
-+ && (params->average != AVE_8_PIX)) {
-+ dev_err(prev_dev, "validate_params: wrong pix "
-+ "average\n");
-+ goto err_einval;
-+ } else if (((params->average == AVE_2_PIX)
-+ && (params->size_params.hsize % 2))
-+ || ((params->average == AVE_4_PIX)
-+ && (params->size_params.hsize % 4))
-+ || ((params->average == AVE_8_PIX)
-+ && (params->size_params.hsize % 8))) {
-+ dev_err(prev_dev, "validate_params: "
-+ "wrong pix average for input size\n");
-+ goto err_einval;
-+ }
-+ }
-+
-+ if ((params->size_params.pixsize != PREV_INWIDTH_8BIT)
-+ && (params->size_params.pixsize
-+ != PREV_INWIDTH_10BIT)) {
-+ dev_err(prev_dev, "validate_params: wrong pixsize\n");
-+ goto err_einval;
-+ }
-+
-+ if (params->size_params.hsize > MAX_IMAGE_WIDTH
-+ || params->size_params.hsize < 0) {
-+ dev_err(prev_dev, "validate_params: wrong hsize\n");
-+ goto err_einval;
-+ }
-+
-+ if ((params->pix_fmt != YCPOS_YCrYCb)
-+ && (YCPOS_YCbYCr != params->pix_fmt)
-+ && (YCPOS_CbYCrY != params->pix_fmt)
-+ && (YCPOS_CrYCbY != params->pix_fmt)) {
-+ dev_err(prev_dev, "validate_params: wrong pix_fmt");
-+ goto err_einval;
-+ }
-+
-+ if ((params->features & PREV_DARK_FRAME_SUBTRACT)
-+ && (params->features
-+ & PREV_DARK_FRAME_CAPTURE)) {
-+ dev_err(prev_dev, "validate_params: DARK FRAME CAPTURE and "
-+ "SUBSTRACT cannot be enabled "
-+ "at same time\n");
-+ goto err_einval;
-+ }
-+
-+ if (params->features & PREV_DARK_FRAME_SUBTRACT)
-+ if (!params->drkf_params.addr
-+ || (params->drkf_params.offset % 32)) {
-+ dev_err(prev_dev, "validate_params: dark frame "
-+ "address\n");
-+ goto err_einval;
-+ }
-+
-+ if (params->features & PREV_LENS_SHADING)
-+ if ((params->lens_shading_shift > 7)
-+ || !params->drkf_params.addr
-+ || (params->drkf_params.offset % 32)) {
-+ dev_err(prev_dev, "validate_params: lens shading "
-+ "shift\n");
-+ goto err_einval;
-+ }
-+
-+ if ((params->size_params.in_pitch <= 0)
-+ || (params->size_params.in_pitch % 32)) {
-+ params->size_params.in_pitch =
-+ (params->size_params.hsize * 2) & 0xFFE0;
-+ dev_err(prev_dev, "\nError in in_pitch; new value = %d",
-+ params->size_params.in_pitch);
-+ }
-+
-+ return 0;
-+err_einval:
-+ return -EINVAL;
-+}
-+
-+/**
-+ * preview_isr - Callback from ISP driver for ISP Preview Interrupt
-+ * @status: ISP IRQ0STATUS register value
-+ * @arg1: Structure containing ISP preview wrapper global information
-+ * @arg2: Currently not used
-+ **/
-+static void preview_isr(unsigned long status, isp_vbq_callback_ptr arg1,
-+ void *arg2)
-+{
-+ struct prev_device *device = (struct prev_device *)arg1;
-+
-+ if ((status & PREV_DONE) != PREV_DONE)
-+ return;
-+
-+ if (device)
-+ complete(&device->wfc);
-+}
-+
-+/**
-+ * prev_do_preview - Performs the Preview process
-+ * @device: Structure containing ISP preview wrapper global information
-+ * @arg: Currently not used
-+ *
-+ * Returns 0 if successful, or -EINVAL if the sent parameters are invalid.
-+ **/
-+static int prev_do_preview(struct prev_device *device, int *arg)
-+{
-+ int bpp, size;
-+ int ret = 0;
-+ u32 out_hsize, out_vsize, out_line_offset;
-+
-+ dev_dbg(prev_dev, "prev_do_preview E\n");
-+
-+ if (!device) {
-+ dev_err(prev_dev, "preview: invalid parameters\n");
-+ return -EINVAL;
-+ }
-+
-+ if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT)
-+ bpp = 1;
-+ else
-+ bpp = 2;
-+
-+ size = device->params->size_params.hsize *
-+ device->params->size_params.vsize * bpp;
-+
-+ ret = isppreview_set_inaddr(device->isp_addr_read);
-+ if (ret)
-+ goto out;
-+
-+ ret = isppreview_set_outaddr(device->isp_addr_read);
-+ if (ret)
-+ goto out;
-+
-+ isppreview_try_size(device->params->size_params.hsize,
-+ device->params->size_params.vsize,
-+ &out_hsize, &out_vsize);
-+
-+ ret = isppreview_config_inlineoffset(device->params->size_params.hsize
-+ * bpp);
-+ if (ret)
-+ goto out;
-+
-+ out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK;
-+
-+ ret = isppreview_config_outlineoffset(out_line_offset);
-+ if (ret)
-+ goto out;
-+
-+ ret = isppreview_config_size(device->params->size_params.hsize,
-+ device->params->size_params.vsize,
-+ out_hsize, out_vsize);
-+ if (ret)
-+ goto out;
-+
-+ isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM);
-+
-+ ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device,
-+ (void *)NULL);
-+ if (ret) {
-+ dev_err(prev_dev, "ERROR while setting Previewer callback!\n");
-+ goto out;
-+ }
-+ isppreview_enable(1);
-+
-+ wait_for_completion_interruptible(&device->wfc);
-+
-+ if (device->isp_addr_read) {
-+ ispmmu_vunmap(device->isp_addr_read);
-+ device->isp_addr_read = 0;
-+ }
-+
-+ ret = isp_unset_callback(CBK_PREV_DONE);
-+
-+ dev_dbg(prev_dev, "prev_do_preview L\n");
-+out:
-+ return ret;
-+}
-+
-+/**
-+ * previewer_vbq_release - Videobuffer queue release
-+ * @q: Structure containing the videobuffer queue.
-+ * @vb: Structure containing the videobuffer used for previewer processing.
-+ **/
-+static void previewer_vbq_release(struct videobuf_queue *q,
-+ struct videobuf_buffer *vb)
-+{
-+ struct prev_fh *fh = q->priv_data;
-+ struct prev_device *device = fh->device;
-+
-+ ispmmu_vunmap(device->isp_addr_read);
-+ device->isp_addr_read = 0;
-+ spin_lock(&device->vbq_lock);
-+ vb->state = VIDEOBUF_NEEDS_INIT;
-+ spin_unlock(&device->vbq_lock);
-+ dev_dbg(prev_dev, "previewer_vbq_release\n");
-+}
-+
-+/**
-+ * previewer_vbq_setup - Sets up the videobuffer size and validates count.
-+ * @q: Structure containing the videobuffer queue.
-+ * @cnt: Number of buffers requested
-+ * @size: Size in bytes of the buffer used for previewing
-+ *
-+ * Always returns 0.
-+ **/
-+static int previewer_vbq_setup(struct videobuf_queue *q,
-+ unsigned int *cnt,
-+ unsigned int *size)
-+{
-+ struct prev_fh *fh = q->priv_data;
-+ struct prev_device *device = fh->device;
-+ u32 bpp = 1;
-+
-+ spin_lock(&device->vbq_lock);
-+ if (*cnt <= 0)
-+ *cnt = VIDEO_MAX_FRAME;
-+
-+ if (*cnt > VIDEO_MAX_FRAME)
-+ *cnt = VIDEO_MAX_FRAME;
-+
-+ if (!device->params->size_params.hsize ||
-+ !device->params->size_params.vsize) {
-+ dev_err(prev_dev, "Can't setup buffer size\n");
-+ spin_unlock(&device->vbq_lock);
-+ return -EINVAL;
-+ }
-+
-+ if (device->params->size_params.pixsize == PREV_INWIDTH_10BIT)
-+ bpp = 2;
-+ *size = prev_bufsize = bpp * device->params->size_params.hsize
-+ * device->params->size_params.vsize;
-+ spin_unlock(&device->vbq_lock);
-+ dev_dbg(prev_dev, "previewer_vbq_setup\n");
-+ return 0;
-+}
-+
-+/**
-+ * previewer_vbq_prepare - Videobuffer is prepared and mmapped.
-+ * @q: Structure containing the videobuffer queue.
-+ * @vb: Structure containing the videobuffer used for previewer processing.
-+ * @field: Type of field to set in videobuffer device.
-+ *
-+ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
-+ * -EIO if the ISP MMU mapping fails
-+ **/
-+static int previewer_vbq_prepare(struct videobuf_queue *q,
-+ struct videobuf_buffer *vb,
-+ enum v4l2_field field)
-+{
-+ struct prev_fh *fh = q->priv_data;
-+ struct prev_device *device = fh->device;
-+ int err = -EINVAL;
-+ unsigned int isp_addr;
-+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-+
-+ dev_dbg(prev_dev, "previewer_vbq_prepare E\n");
-+ spin_lock(&device->vbq_lock);
-+ if (vb->baddr) {
-+ vb->size = prev_bufsize;
-+ vb->bsize = prev_bufsize;
-+ } else {
-+ spin_unlock(&device->vbq_lock);
-+ dev_err(prev_dev, "No user buffer allocated\n");
-+ goto out;
-+ }
-+
-+ vb->width = device->params->size_params.hsize;
-+ vb->height = device->params->size_params.vsize;
-+ vb->field = field;
-+ spin_unlock(&device->vbq_lock);
-+
-+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
-+ err = videobuf_iolock(q, vb, NULL);
-+ if (!err) {
-+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
-+ if (!isp_addr)
-+ err = -EIO;
-+ else
-+ device->isp_addr_read = isp_addr;
-+ }
-+ }
-+
-+ if (!err) {
-+ vb->state = VIDEOBUF_PREPARED;
-+ flush_cache_user_range(NULL, vb->baddr,
-+ (vb->baddr + vb->bsize));
-+ } else
-+ previewer_vbq_release(q, vb);
-+
-+ dev_dbg(prev_dev, "previewer_vbq_prepare L\n");
-+out:
-+ return err;
-+}
-+
-+static void previewer_vbq_queue(struct videobuf_queue *q,
-+ struct videobuf_buffer *vb)
-+{
-+ return;
-+}
-+
-+/**
-+ * previewer_open - Initializes and opens the Preview Wrapper
-+ * @inode: Inode structure associated with the Preview Wrapper
-+ * @filp: File structure associated with the Preview Wrapper
-+ *
-+ * Returns 0 if successful, -EACCES if its unable to initialize default config,
-+ * -EBUSY if its already opened or the ISP module is not available, or -ENOMEM
-+ * if its unable to allocate the device in kernel space memory.
-+ **/
-+static int previewer_open(struct inode *inode, struct file *filp)
-+{
-+ int ret = 0;
-+ struct prev_device *device = prevdevice;
-+ struct prev_params *config = isppreview_get_config();
-+ struct prev_fh *fh;
-+
-+ if (config == NULL) {
-+ dev_err(prev_dev, "Unable to initialize default config "
-+ "from isppreviewer\n\n");
-+ return -EACCES;
-+ }
-+
-+ if (device->opened || (filp->f_flags & O_NONBLOCK)) {
-+ dev_err(prev_dev, "previewer_open: device is already "
-+ "opened\n");
-+ return -EBUSY;
-+ }
-+
-+ fh = kzalloc(sizeof(struct prev_fh), GFP_KERNEL);
-+ if (NULL == fh)
-+ return -ENOMEM;
-+
-+ isp_get();
-+ ret = isppreview_request();
-+ if (ret) {
-+ isp_put();
-+ dev_err(prev_dev, "Can't acquire isppreview\n");
-+ return ret;
-+ }
-+
-+ device->params = config;
-+ device->opened = 1;
-+
-+ filp->private_data = fh;
-+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+ fh->device = device;
-+
-+ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
-+ &device->vbq_lock, fh->type,
-+ V4L2_FIELD_NONE,
-+ sizeof(struct videobuf_buffer), fh);
-+
-+ init_completion(&device->wfc);
-+ device->wfc.done = 0;
-+ mutex_init(&device->prevwrap_mutex);
-+
-+ return 0;
-+}
-+
-+/**
-+ * previewer_release - Releases Preview Wrapper and frees up allocated memory
-+ * @inode: Inode structure associated with the Preview Wrapper
-+ * @filp: File structure associated with the Preview Wrapper
-+ *
-+ * Always returns 0.
-+ **/
-+static int previewer_release(struct inode *inode, struct file *filp)
-+{
-+ struct prev_fh *fh = filp->private_data;
-+ struct prev_device *device = fh->device;
-+ struct videobuf_queue *q = &fh->vbq;
-+
-+ device->opened = 0;
-+ device->params = NULL;
-+ isppreview_free();
-+ videobuf_mmap_free(q);
-+ isp_put();
-+ prev_bufsize = 0;
-+ filp->private_data = NULL;
-+ kfree(fh);
-+
-+ dev_dbg(prev_dev, "previewer_release\n");
-+ return 0;
-+}
-+
-+/**
-+ * previewer_mmap - Memory maps the Preview Wrapper module.
-+ * @file: File structure associated with the Preview Wrapper
-+ * @vma: Virtual memory area structure.
-+ *
-+ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
-+ * function.
-+ **/
-+static int previewer_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct prev_fh *fh = file->private_data;
-+ dev_dbg(prev_dev, "previewer_mmap\n");
-+
-+ return videobuf_mmap_mapper(&fh->vbq, vma);
-+}
-+
-+/**
-+ * previewer_ioctl - I/O control function for Preview Wrapper
-+ * @inode: Inode structure associated with the Preview Wrapper.
-+ * @file: File structure associated with the Preview Wrapper.
-+ * @cmd: Type of command to execute.
-+ * @arg: Argument to send to requested command.
-+ *
-+ * Returns 0 if successful, -1 if bad command passed or access is denied,
-+ * -EFAULT if copy_from_user() or copy_to_user() fails, -EINVAL if parameter
-+ * validation fails or parameter structure is not present
-+ **/
-+static int previewer_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret = 0;
-+ struct prev_params params;
-+ struct prev_fh *fh = file->private_data;
-+ struct prev_device *device = fh->device;
-+
-+ dev_dbg(prev_dev, "Entering previewer_ioctl()\n");
-+
-+ if ((_IOC_TYPE(cmd) != PREV_IOC_BASE)
-+ || (_IOC_NR(cmd) > PREV_IOC_MAXNR)) {
-+ dev_err(prev_dev, "Bad command Value \n");
-+ goto err_minusone;
-+ }
-+
-+ if (_IOC_DIR(cmd) & _IOC_READ)
-+ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
-+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
-+ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
-+ if (ret) {
-+ dev_err(prev_dev, "access denied\n");
-+ goto err_minusone;
-+ }
-+
-+ switch (cmd) {
-+ case PREV_REQBUF:
-+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
-+ goto err_eintr;
-+ ret = videobuf_reqbufs(&fh->vbq, (void *)arg);
-+ mutex_unlock(&device->prevwrap_mutex);
-+ break;
-+
-+ case PREV_QUERYBUF:
-+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
-+ goto err_eintr;
-+ ret = videobuf_querybuf(&fh->vbq, (void *)arg);
-+ mutex_unlock(&device->prevwrap_mutex);
-+ break;
-+
-+ case PREV_QUEUEBUF:
-+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
-+ goto err_eintr;
-+ ret = videobuf_qbuf(&fh->vbq, (void *)arg);
-+ mutex_unlock(&device->prevwrap_mutex);
-+ break;
-+
-+ case PREV_SET_PARAM:
-+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
-+ goto err_eintr;
-+ if (copy_from_user(&params, (struct prev_params *)arg,
-+ sizeof(struct prev_params))) {
-+ mutex_unlock(&device->prevwrap_mutex);
-+ return -EFAULT;
-+ }
-+ ret = prev_validate_params(&params);
-+ if (ret < 0) {
-+ dev_err(prev_dev, "Error validating parameters!\n");
-+ mutex_unlock(&device->prevwrap_mutex);
-+ goto out;
-+ }
-+ if (device->params)
-+ memcpy(device->params, &params,
-+ sizeof(struct prev_params));
-+ else {
-+ mutex_unlock(&device->prevwrap_mutex);
-+ return -EINVAL;
-+ }
-+
-+ ret = prev_hw_setup(device->params);
-+ mutex_unlock(&device->prevwrap_mutex);
-+ break;
-+
-+ case PREV_GET_PARAM:
-+ if (copy_to_user((struct prev_params *)arg, device->params,
-+ sizeof(struct prev_params)))
-+ ret = -EFAULT;
-+ break;
-+
-+ case PREV_GET_STATUS:
-+ ret = prev_get_status((struct prev_status *)arg);
-+ break;
-+
-+ case PREV_PREVIEW:
-+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
-+ goto err_eintr;
-+ ret = prev_do_preview(device, (int *)arg);
-+ mutex_unlock(&device->prevwrap_mutex);
-+ break;
-+
-+ case PREV_GET_CROPSIZE:
-+ {
-+ struct prev_cropsize outputsize;
-+ prev_calculate_crop(device, &outputsize);
-+ if (copy_to_user((struct prev_cropsize *)arg, &outputsize,
-+ sizeof(struct prev_cropsize)))
-+ ret = -EFAULT;
-+ }
-+ break;
-+
-+ default:
-+ dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n");
-+ ret = -EINVAL;
-+ }
-+out:
-+ return ret;
-+err_minusone:
-+ return -1;
-+err_eintr:
-+ return -EINTR;
-+}
-+
-+/**
-+ * previewer_platform_release - Acts when Reference count is zero
-+ * @device: Structure containing ISP preview wrapper global information
-+ *
-+ * This is called when the reference count goes to zero
-+ **/
-+static void previewer_platform_release(struct device *device)
-+{
-+ dev_dbg(prev_dev, "previewer_platform_release()\n");
-+}
-+
-+static struct file_operations prev_fops = {
-+ .owner = THIS_MODULE,
-+ .open = previewer_open,
-+ .release = previewer_release,
-+ .mmap = previewer_mmap,
-+ .ioctl = previewer_ioctl,
-+};
-+
-+static struct platform_device omap_previewer_device = {
-+ .name = OMAP_PREV_NAME,
-+ .id = -1,
-+ .dev = {
-+ .release = previewer_platform_release,
-+ }
-+};
-+
-+/**
-+ * previewer_probe - Checks for device presence
-+ * @pdev: Structure containing details of the current device.
-+ *
-+ * Always returns 0
-+ **/
-+static int __init previewer_probe(struct platform_device *pdev)
-+{
-+ return 0;
-+}
-+
-+/**
-+ * previewer_remove - Handles the removal of the driver
-+ * @pdev: Structure containing details of the current device.
-+ *
-+ * Always returns 0.
-+ **/
-+static int previewer_remove(struct platform_device *pdev)
-+{
-+ dev_dbg(prev_dev, "previewer_remove()\n");
-+
-+ platform_device_unregister(&omap_previewer_device);
-+ platform_driver_unregister(&omap_previewer_driver);
-+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
-+ return 0;
-+}
-+
-+static struct platform_driver omap_previewer_driver = {
-+ .probe = previewer_probe,
-+ .remove = previewer_remove,
-+ .driver = {
-+ .owner = THIS_MODULE,
-+ .name = OMAP_PREV_NAME,
-+ },
-+};
-+
-+/**
-+ * omap_previewer_init - Initialization of Preview Wrapper
-+ *
-+ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
-+ * could not register the wrapper as a character device, or other errors if the
-+ * device or driver can't register.
-+ **/
-+static int __init omap_previewer_init(void)
-+{
-+ int ret;
-+ struct prev_device *device;
-+
-+ device = kzalloc(sizeof(struct prev_device), GFP_KERNEL);
-+ if (!device) {
-+ dev_err(prev_dev, OMAP_PREV_NAME ": could not allocate"
-+ " memory\n");
-+ return -ENOMEM;
-+ }
-+ prev_major = register_chrdev(0, OMAP_PREV_NAME, &prev_fops);
-+
-+ if (prev_major < 0) {
-+ dev_err(prev_dev, OMAP_PREV_NAME ": initialization "
-+ "failed. could not register character "
-+ "device\n");
-+ return -ENODEV;
-+ }
-+
-+ ret = platform_driver_register(&omap_previewer_driver);
-+ if (ret) {
-+ dev_err(prev_dev, OMAP_PREV_NAME
-+ ": failed to register platform driver!\n");
-+ goto fail2;
-+ }
-+ ret = platform_device_register(&omap_previewer_device);
-+ if (ret) {
-+ dev_err(prev_dev, OMAP_PREV_NAME
-+ ": failed to register platform device!\n");
-+ goto fail3;
-+ }
-+
-+ prev_class = class_create(THIS_MODULE, OMAP_PREV_NAME);
-+ if (!prev_class)
-+ goto fail4;
-+
-+ prev_dev = device_create(prev_class, prev_dev,
-+ (MKDEV(prev_major, 0)), NULL,
-+ OMAP_PREV_NAME);
-+ dev_dbg(prev_dev, OMAP_PREV_NAME ": Registered Previewer Wrapper\n");
-+ device->opened = 0;
-+
-+ device->vbq_ops.buf_setup = previewer_vbq_setup;
-+ device->vbq_ops.buf_prepare = previewer_vbq_prepare;
-+ device->vbq_ops.buf_release = previewer_vbq_release;
-+ device->vbq_ops.buf_queue = previewer_vbq_queue;
-+ spin_lock_init(&device->vbq_lock);
-+
-+ prevdevice = device;
-+ return 0;
-+
-+fail4:
-+ platform_device_unregister(&omap_previewer_device);
-+fail3:
-+ platform_driver_unregister(&omap_previewer_driver);
-+fail2:
-+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
-+
-+ return ret;
-+}
-+
-+/**
-+ * omap_previewer_exit - Close of Preview Wrapper
-+ **/
-+static void __exit omap_previewer_exit(void)
-+{
-+ previewer_remove(&omap_previewer_device);
-+ kfree(prevdevice);
-+ prev_major = -1;
-+}
-+
-+module_init(omap_previewer_init);
-+module_exit(omap_previewer_exit);
-+
-+MODULE_AUTHOR("Texas Instruments");
-+MODULE_DESCRIPTION("OMAP ISP Previewer");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/media/video/isp/omap_previewer.h b/drivers/media/video/isp/omap_previewer.h
-new file mode 100644
-index 0000000..0bb31cd
---- /dev/null
-+++ b/drivers/media/video/isp/omap_previewer.h
-@@ -0,0 +1,162 @@
-+/*
-+ * drivers/media/video/isp/omap_previewer.h
-+ *
-+ * Header file for Preview module wrapper in TI's OMAP3430 ISP
-+ *
-+ * Copyright (C) 2008 Texas Instruments, Inc.
-+ *
-+ * Contributors:
-+ * Leonides Martinez <leonides.martinez@ti.com>
-+ * Sergio Aguirre <saaguirre@ti.com>
-+ *
-+ * This package is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-+ */
-+
-+#include "isppreview.h"
-+
-+#ifndef OMAP_ISP_PREVIEW_WRAP_H
-+#define OMAP_ISP_PREVIEW_WRAP_H
-+
-+#define PREV_IOC_BASE 'P'
-+#define PREV_REQBUF _IOWR(PREV_IOC_BASE, 1,\
-+ struct v4l2_requestbuffers)
-+#define PREV_QUERYBUF _IOWR(PREV_IOC_BASE, 2,\
-+ struct v4l2_buffer)
-+#define PREV_SET_PARAM _IOW(PREV_IOC_BASE, 3,\
-+ struct prev_params)
-+#define PREV_GET_PARAM _IOWR(PREV_IOC_BASE, 4,\
-+ struct prev_params)
-+#define PREV_PREVIEW _IOR(PREV_IOC_BASE, 5, int)
-+#define PREV_GET_STATUS _IOR(PREV_IOC_BASE, 6, char)
-+#define PREV_GET_CROPSIZE _IOR(PREV_IOC_BASE, 7,\
-+ struct prev_cropsize)
-+#define PREV_QUEUEBUF _IOWR(PREV_IOC_BASE, 8,\
-+ struct v4l2_buffer)
-+#define PREV_IOC_MAXNR 8
-+
-+#define LUMA_TABLE_SIZE 128
-+#define GAMMA_TABLE_SIZE 1024
-+#define CFA_COEFF_TABLE_SIZE 576
-+#define NOISE_FILTER_TABLE_SIZE 256
-+
-+#define MAX_IMAGE_WIDTH 3300
-+
-+#define PREV_INWIDTH_8BIT 0 /* pixel width of 8 bits */
-+#define PREV_INWIDTH_10BIT 1 /* pixel width of 10 bits */
-+
-+#define PREV_32BYTES_ALIGN_MASK 0xFFFFFFE0
-+#define PREV_16PIX_ALIGN_MASK 0xFFFFFFF0
-+
-+/**
-+ * struct prev_rgbblending - Structure for RGB2RGB blending parameters
-+ * @blending: Color correlation 3x3 matrix.
-+ * @offset: Color correlation offsets.
-+ */
-+struct prev_rgbblending {
-+ short blending[RGB_MAX][RGB_MAX]; /* color correlation 3x3
-+ * matrix.
-+ */
-+ short offset[RGB_MAX]; /* color correlation offsets */
-+};
-+
-+/**
-+ * struct prev_cfa_coeffs - Structure for CFA coefficients
-+ * @hthreshold: Horizontal threshold.
-+ * @vthreshold: Vertical threshold.
-+ * @coeffs: CFA coefficients
-+ */
-+struct prev_cfa_coeffs {
-+ char hthreshold, vthreshold;
-+ int coeffs[CFA_COEFF_TABLE_SIZE];
-+};
-+
-+/**
-+ * struct prev_gamma_coeffs - Structure for Gamma Coefficients
-+ * @red: Table of gamma correction values for red color.
-+ * @green: Table of gamma correction values for green color.
-+ * @blue: Table of gamma correction values for blue color.
-+ */
-+struct prev_gamma_coeffs {
-+ unsigned char red[GAMMA_TABLE_SIZE];
-+ unsigned char green[GAMMA_TABLE_SIZE];
-+ unsigned char blue[GAMMA_TABLE_SIZE];
-+};
-+
-+/**
-+ * struct prev_noiseflt_coeffs - Structure for Noise Filter Coefficients.
-+ * @noise: Noise filter table.
-+ * @strength: Used to find out weighted average.
-+ */
-+struct prev_noiseflt_coeffs {
-+ unsigned char noise[NOISE_FILTER_TABLE_SIZE];
-+ unsigned char strength;
-+};
-+
-+/**
-+ * struct prev_chroma_spr - Structure for Chroma Suppression.
-+ * @hpfy: High passed version of Y or normal Y.
-+ * @threshold: Threshold for chroma suppress.
-+ * @gain: Chroma suppression gain
-+ */
-+struct prev_chroma_spr {
-+ unsigned char hpfy;
-+ char threshold;
-+ unsigned char gain;
-+};
-+
-+/**
-+ * struct prev_status - Structure to know status of the hardware
-+ * @hw_busy: Flag to indicate if Hardware is Busy.
-+ */
-+struct prev_status {
-+ char hw_busy;
-+};
-+
-+/**
-+ * struct prev_cropsize - Structure to know crop size.
-+ * @hcrop: Horizontal size of crop window.
-+ * @vcrop: Vertical size of crop window.
-+ */
-+struct prev_cropsize {
-+ int hcrop;
-+ int vcrop;
-+};
-+
-+/**
-+ * struct prev_device - Global device information structure.
-+ * @params: Pointer to structure containing preview parameters.
-+ * @opened: State of the device.
-+ * @wfc: Wait for completion. Used for locking operations.
-+ * @prevwrap_mutex: Mutex for preview wrapper use.
-+ * @vbq_lock: Spinlock for videobuf queues.
-+ * @vbq_ops: Videobuf queue operations
-+ * @isp_addr_read: Input/Output address
-+ */
-+struct prev_device {
-+ struct prev_params *params;
-+ unsigned char opened;
-+ struct completion wfc;
-+ struct mutex prevwrap_mutex; /* For generic internal use */
-+ spinlock_t vbq_lock; /* For videobuffer queue handling */
-+ struct videobuf_queue_ops vbq_ops;
-+ dma_addr_t isp_addr_read;
-+};
-+
-+/**
-+ * struct prev_fh - Per-filehandle data structure
-+ * @type: Used buffer type.
-+ * @vbq: Videobuffer queue.
-+ * @device: Pointer to device information structure.
-+ */
-+struct prev_fh {
-+ enum v4l2_buf_type type;
-+ struct videobuf_queue vbq;
-+ struct prev_device *device;
-+};
-+#endif
diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
new file mode 100644
index 0000000..54bc425
@@ -1450,11 +437,11 @@ index 0000000..54bc425
+ }
+
+ if (fh->isp_addr_read) {
-+ ispmmu_vunmap(fh->isp_addr_read);
++ ispmmu_unmap(fh->isp_addr_read);
+ fh->isp_addr_read = 0;
+ }
+ if (fh->isp_addr_write) {
-+ ispmmu_vunmap(fh->isp_addr_write);
++ ispmmu_unmap(fh->isp_addr_write);
+ fh->isp_addr_write = 0;
+ }
+
@@ -2128,8 +1115,8 @@ index 0000000..54bc425
+ videobuf_dma_free(dma);
+ }
+
-+ ispmmu_vunmap(fh->isp_addr_read);
-+ ispmmu_vunmap(fh->isp_addr_write);
++ ispmmu_unmap(fh->isp_addr_read);
++ ispmmu_unmap(fh->isp_addr_write);
+ fh->isp_addr_read = 0;
+ fh->isp_addr_write = 0;
+ spin_lock(&fh->vbq_lock);
@@ -2231,7 +1218,7 @@ index 0000000..54bc425
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+ err = videobuf_iolock(q, vb, NULL);
+ if (!err) {
-+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
+ if (!isp_addr)
+ err = -EIO;
+ else {
@@ -2899,17 +1886,5 @@ index 0000000..5ac0c88
+
+#endif
--
-1.6.0.3
+1.6.2.4
---- /tmp/Kconfig 2009-04-06 10:56:27.000000000 +0200
-+++ git/drivers/media/video/Kconfig 2009-04-06 10:57:25.000000000 +0200
-@@ -711,6 +711,9 @@
- CMOS camera controller. This is the controller found on first-
- generation OLPC systems.
-
-+
-+source "drivers/media/video/isp/Kconfig"
-+
- config VIDEO_OMAP3
- tristate "OMAP 3 Camera support"
- select VIDEOBUF_GEN
diff --git a/recipes/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch b/recipes/linux/linux-omap-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
index 631b05f417..2c3023643e 100644
--- a/recipes/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch
+++ b/recipes/linux/linux-omap-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
@@ -1,15 +1,14 @@
-From 20d79137ecaa6c7dad007d9ea1d7be5550db4839 Mon Sep 17 00:00:00 2001
-From: Vaibhav Hiremath <hvaibhav@ti.com>
-Date: Fri, 13 Feb 2009 15:40:25 +0530
-Subject: [PATCH 2/2] Resizer bug fixes on top of 1.0.2 release
+From ad3bbadb7fc39a946dfd0cdac19e2ec8647b2c2c Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:20:27 +0530
+Subject: [PATCH 24/26] OMAP3-Resizer: V4L2-buf layer issues fixed
-This commit contains resizer bug fixes on top of
- PSP1.0.2 release -
- - 4096 aligned address constraint
- - workaround for extra page allocation for page aligned
- size buffers
+V4L2-Buffer layer issues fixed under this commit.
+This patch is same as available with PSP1.0.2 release
-Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+The discussion is initiated on this with V4L2 mailing list.
+
+Please note that this patch is not being tested.
---
drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++--------
include/linux/omap_resizer.h | 3 +-
@@ -125,11 +124,11 @@ index 54bc425..8059c70 100644
}
- if (fh->isp_addr_read) {
-- ispmmu_vunmap(fh->isp_addr_read);
+- ispmmu_unmap(fh->isp_addr_read);
- fh->isp_addr_read = 0;
- }
- if (fh->isp_addr_write) {
-- ispmmu_vunmap(fh->isp_addr_write);
+- ispmmu_unmap(fh->isp_addr_write);
- fh->isp_addr_write = 0;
- }
-
@@ -270,11 +269,11 @@ index 54bc425..8059c70 100644
+ dma = videobuf_to_dma(q->bufs[vb->i]);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
-+ ispmmu_vunmap(fh->config->buf_address[vb->i]);
++ ispmmu_unmap(fh->config->buf_address[vb->i]);
+ fh->config->buf_address[vb->i] = 0;
-- ispmmu_vunmap(fh->isp_addr_read);
-- ispmmu_vunmap(fh->isp_addr_write);
+- ispmmu_unmap(fh->isp_addr_read);
+- ispmmu_unmap(fh->isp_addr_write);
- fh->isp_addr_read = 0;
- fh->isp_addr_write = 0;
spin_lock(&fh->vbq_lock);
@@ -429,7 +428,7 @@ index 54bc425..8059c70 100644
if (vb->state == VIDEOBUF_NEEDS_INIT) {
- err = videobuf_iolock(q, vb, NULL);
- if (!err) {
-- isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
- if (!isp_addr)
- err = -EIO;
- else {
@@ -491,7 +490,7 @@ index 54bc425..8059c70 100644
+ goto buf_release;
+ spin_unlock(&fh->vbq_lock);
+ }
-+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
+ if (!isp_addr)
+ err = -EIO;
+ else {
@@ -726,5 +725,5 @@ index 5ac0c88..47b8dd8 100644
#define RSZ_INTYPE_YCBCR422_16BIT 0
#define RSZ_INTYPE_PLANAR_8BIT 1
--
-1.6.0.3
+1.6.2.4
diff --git a/recipes/linux/linux-omap-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch b/recipes/linux/linux-omap-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
new file mode 100644
index 0000000000..143a846e3c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
@@ -0,0 +1,36 @@
+From 9fec955e98b4ef7922f629e3a81d2d1af216e028 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 18:12:42 +0530
+Subject: [PATCH 25/26] OMAP3-Resizer: Build issues fixed
+
+There were some building issues with latest gitorious tree,
+fixed them.
+---
+ drivers/media/video/isp/omap_resizer.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+index 8059c70..dd90b24 100644
+--- a/drivers/media/video/isp/omap_resizer.c
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -1033,7 +1033,7 @@ static void rsz_vbq_release(struct videobuf_queue *q,
+ dma = videobuf_to_dma(q->bufs[vb->i]);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+- ispmmu_unmap(fh->config->buf_address[vb->i]);
++ ispmmu_vunmap(fh->config->buf_address[vb->i]);
+ fh->config->buf_address[vb->i] = 0;
+
+ spin_lock(&fh->vbq_lock);
+@@ -1293,7 +1293,7 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+ goto buf_release;
+ spin_unlock(&fh->vbq_lock);
+ }
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
+ if (!isp_addr)
+ err = -EIO;
+ else {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch
new file mode 100644
index 0000000000..f6d522e352
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch
@@ -0,0 +1,677 @@
+From 0b60175d1b7db1301e2ad3ad4d64fb0c8d121c0a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sat, 11 Apr 2009 13:05:21 -0700
+Subject: [PATCH] MMA7455L driver.
+
+---
+ drivers/input/misc/Kconfig | 9 +
+ drivers/input/misc/Makefile | 1 +
+ drivers/input/misc/mma7455l.c | 614 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/mma7455l.h | 11 +
+ 4 files changed, 635 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index 6fa9e38..05dca18 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -237,4 +237,13 @@ config INPUT_PCF50633_PMU
+ Say Y to include support for delivering PMU events via input
+ layer on NXP PCF50633.
+
++config INPUT_MMA7455L
++ tristate "Freescale MMA7455L 3-axis accelerometer"
++ depends on SPI_MASTER
++ help
++ SPI driver for the Freescale MMA7455L 3-axis accelerometer.
++
++ The userspace interface is a 3-axis (X/Y/Z) relative movement
++ Linux input device, reporting REL_[XYZ] events.
++
+ endif
+diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
+index 2fabcdb..e355d82 100644
+--- a/drivers/input/misc/Makefile
++++ b/drivers/input/misc/Makefile
+@@ -23,3 +23,4 @@ obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
+ obj-$(CONFIG_INPUT_APANEL) += apanel.o
+ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
+ obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
++obj-$(CONFIG_INPUT_MMA7455L) += mma7455l.o
+diff --git a/drivers/input/misc/mma7455l.c b/drivers/input/misc/mma7455l.c
+new file mode 100644
+index 0000000..b33c513
+--- /dev/null
++++ b/drivers/input/misc/mma7455l.c
+@@ -0,0 +1,614 @@
++/* Linux kernel driver for the Freescale MMA7455L 3-axis accelerometer
++ *
++ * Copyright (C) 2009 by Always Innovating, Inc.
++ * Author: Gregoire Gentil <gregoire@gentil.com>
++ * Author: Tim Yamin <plasm@roo.me.uk>
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ */
++
++/*
++ * What this driver doesn't yet support:
++ *
++ * - I2C
++ * - INT2 handling
++ * - Pulse detection (and the sysctls to control it)
++ * - 10-bit measurement
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/sysfs.h>
++#include <linux/gpio.h>
++
++#include <linux/mma7455l.h>
++#include <linux/spi/spi.h>
++
++#define MMA7455L_WHOAMI_MAGIC 0x55
++
++enum mma7455l_reg {
++ MMA7455L_REG_XOUTL = 0x00,
++ MMA7455L_REG_XOUTH = 0x01,
++ MMA7455L_REG_YOUTL = 0x02,
++ MMA7455L_REG_YOUTH = 0x03,
++ MMA7455L_REG_ZOUTL = 0x04,
++ MMA7455L_REG_ZOUTH = 0x05,
++ MMA7455L_REG_XOUT8 = 0x06,
++ MMA7455L_REG_YOUT8 = 0x07,
++ MMA7455L_REG_ZOUT8 = 0x08,
++ MMA7455L_REG_STATUS = 0x09,
++ MMA7455L_REG_DETSRC = 0x0a,
++ MMA7455L_REG_TOUT = 0x0b,
++ MMA7455L_REG_RESERVED1 = 0x0c,
++ MMA7455L_REG_I2CAD = 0x0d,
++ MMA7455L_REG_USRINF = 0x0e,
++ MMA7455L_REG_WHOAMI = 0x0f,
++ MMA7455L_REG_XOFFL = 0x10,
++ MMA7455L_REG_XOFFH = 0x11,
++ MMA7455L_REG_YOFFL = 0x12,
++ MMA7455L_REG_YOFFH = 0x13,
++ MMA7455L_REG_ZOFFL = 0x14,
++ MMA7455L_REG_ZOFFH = 0x15,
++ MMA7455L_REG_MCTL = 0x16,
++ MMA7455L_REG_INTRST = 0x17,
++ MMA7455L_REG_CTL1 = 0x18,
++ MMA7455L_REG_CTL2 = 0x19,
++ MMA7455L_REG_LDTH = 0x1a,
++ MMA7455L_REG_PDTH = 0x1b,
++ MMA7455L_REG_PW = 0x1c,
++ MMA7455L_REG_LT = 0x1d,
++ MMA7455L_REG_TW = 0x1e,
++ MMA7455L_REG_RESERVED2 = 0x1f,
++};
++
++enum mma7455l_reg_status {
++ MMA7455L_STATUS_XDA = 0x08,
++ MMA7455L_STATUS_YDA = 0x10,
++ MMA7455L_STATUS_ZDA = 0x20,
++};
++
++enum mma7455l_mode {
++ MMA7455L_MODE_STANDBY = 0,
++ MMA7455L_MODE_MEASUREMENT = 1,
++ MMA7455L_MODE_LEVELDETECTION = 0x42, /* Set DRPD to on */
++ MMA7455L_MODE_PULSEDETECTION = 0x43, /* Set DRPD to on */
++ MMA7455L_MODE_MASK = 0x43,
++};
++
++enum mma7455l_gselect {
++ MMA7455L_GSELECT_8 = 0x0,
++ MMA7455L_GSELECT_2 = 0x4,
++ MMA7455L_GSELECT_4 = 0x8,
++ MMA7455L_GSELECT_MASK = 0xC,
++};
++
++/* FIXME */
++#define MMA7455L_F_FS 0x0020 /* ADC full scale */
++
++struct mma7455l_info {
++ struct spi_device *spi_dev;
++ struct input_dev *input_dev;
++ struct mutex lock;
++ struct delayed_work work;
++
++ u8 mode;
++ u8 gSelect;
++
++ u8 flags;
++ u8 working;
++};
++
++/* lowlevel register access functions */
++
++#define WRITE_BIT (1 << 7)
++#define ADDR_SHIFT 1
++
++static inline u_int8_t __reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++ int rc;
++ u_int8_t cmd;
++
++ cmd = ((reg & 0x3f) << ADDR_SHIFT);
++ rc = spi_w8r8(mma->spi_dev, cmd);
++
++ return rc;
++}
++
++static u_int8_t reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++ u_int8_t ret;
++
++ mutex_lock(&mma->lock);
++ ret = __reg_read(mma, reg);
++ mutex_unlock(&mma->lock);
++
++ return ret;
++}
++
++static s16 __reg_read_10(struct mma7455l_info *mma, u8 reg1, u8 reg2)
++{
++ u8 v1, v2;
++
++ v1 = __reg_read(mma, reg1);
++ v2 = __reg_read(mma, reg2);
++
++ return (v2 & 0x4) << 13 | (v2 & 0x3) << 8 | v1;
++}
++
++static inline int __reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++ u_int8_t buf[2];
++
++ buf[0] = ((reg & 0x3f) << ADDR_SHIFT) | WRITE_BIT;
++ buf[1] = val;
++
++ return spi_write(mma->spi_dev, buf, sizeof(buf));
++}
++
++static int reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++ int ret;
++
++ mutex_lock(&mma->lock);
++ ret = __reg_write(mma, reg, val);
++ mutex_unlock(&mma->lock);
++
++ return ret;
++}
++
++static s16 __reg_write_10(struct mma7455l_info *mma, u8 reg1, u8 reg2, s16 value)
++{
++ int ret;
++ u8 v1, v2;
++
++ v1 = value & 0xFF;
++ if(value < 0)
++ v2 = ((value >> 8) & 0x3) | 0x4;
++ else
++ v2 = 0;
++
++ ret = __reg_write(mma, reg1, v1);
++ ret = __reg_write(mma, reg2, v2);
++ return ret;
++}
++
++static void mma7455l_work(struct work_struct *work)
++{
++ struct mma7455l_info *mma =
++ container_of(work, struct mma7455l_info, work.work);
++
++ s8 val;
++ mma->working = 1;
++
++ /* FIXME: 10 bit accuracy? */
++ if (!(mma->flags & MMA7455L_STATUS_XDA)) {
++ val = reg_read(mma, MMA7455L_REG_XOUT8);
++ input_report_abs(mma->input_dev, ABS_X, val);
++ }
++ if (!(mma->flags & MMA7455L_STATUS_YDA)) {
++ val = reg_read(mma, MMA7455L_REG_YOUT8);
++ input_report_abs(mma->input_dev, ABS_Y, val);
++ }
++ if (!(mma->flags & MMA7455L_STATUS_ZDA)) {
++ val = reg_read(mma, MMA7455L_REG_ZOUT8);
++ input_report_abs(mma->input_dev, ABS_Z, val);
++ }
++
++ mma->working = 0;
++ input_sync(mma->input_dev);
++ put_device(&mma->spi_dev->dev);
++
++ /* Enable IRQ and clear out interrupt */
++ reg_write(mma, MMA7455L_REG_INTRST, 0x3);
++ reg_write(mma, MMA7455L_REG_INTRST, 0x0);
++ enable_irq(mma->spi_dev->irq);
++}
++
++static void mma7455l_schedule_work(struct mma7455l_info *mma)
++{
++ int status;
++
++ get_device(&mma->spi_dev->dev);
++ status = schedule_delayed_work(&mma->work, HZ / 10);
++}
++
++static irqreturn_t mma7455l_interrupt(int irq, void *_mma)
++{
++ struct mma7455l_info *mma = _mma;
++ mma7455l_schedule_work(mma);
++
++ /* Disable any further interrupts until we have processed
++ * the current one */
++ disable_irq(mma->spi_dev->irq);
++ return IRQ_HANDLED;
++}
++
++/* sysfs */
++
++static void get_mode(struct mma7455l_info *mma, u8 *mode, u8 *gSelect)
++{
++ u8 tmp = reg_read(mma, MMA7455L_REG_MCTL);
++
++ *mode = tmp & MMA7455L_MODE_MASK;
++ *gSelect = tmp & MMA7455L_GSELECT_MASK;
++}
++
++static void set_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++ reg_write(mma, MMA7455L_REG_MCTL, mode | gSelect);
++}
++
++static void update_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++ mma->mode = mode;
++ mma->gSelect = gSelect;
++
++ reg_write(mma, MMA7455L_REG_MCTL, mma->mode | mma->gSelect);
++}
++
++static ssize_t show_measure(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++ s8 x, y, z;
++ u8 old_Mode, old_gSelect;
++
++ get_mode(mma, &old_Mode, &old_gSelect);
++ set_mode(mma, MMA7455L_MODE_MEASUREMENT, MMA7455L_GSELECT_2);
++
++ while (reg_read(mma, MMA7455L_REG_STATUS) == 0) {
++ msleep(10);
++ }
++
++ x = reg_read(mma, MMA7455L_REG_XOUT8);
++ y = reg_read(mma, MMA7455L_REG_YOUT8);
++ z = reg_read(mma, MMA7455L_REG_ZOUT8);
++
++ set_mode(mma, old_Mode, old_gSelect);
++ return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t show_mode(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ switch(mma->mode)
++ {
++ case MMA7455L_MODE_STANDBY:
++ return sprintf(buf, "Standby\n");
++ break;
++ case MMA7455L_MODE_MEASUREMENT:
++ return sprintf(buf, "Measurement\n");
++ break;
++ case MMA7455L_MODE_LEVELDETECTION:
++ return sprintf(buf, "Level Detection\n");
++ break;
++ case MMA7455L_MODE_PULSEDETECTION:
++ return sprintf(buf, "Pulse Detection\n");
++ break;
++ }
++
++ return sprintf(buf, "Unknown mode!\n");
++}
++
++static ssize_t show_gSelect(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ switch(mma->gSelect)
++ {
++ case MMA7455L_GSELECT_8:
++ return sprintf(buf, "8\n");
++ break;
++ case MMA7455L_GSELECT_4:
++ return sprintf(buf, "4\n");
++ break;
++ case MMA7455L_GSELECT_2:
++ return sprintf(buf, "2\n");
++ break;
++ }
++
++ return sprintf(buf, "Unknown gSelect!\n");
++}
++
++static ssize_t show_level_threshold(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", reg_read(mma, MMA7455L_REG_LDTH));
++}
++
++static ssize_t show_calibration(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ s16 x, y, z;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ mutex_lock(&mma->lock);
++ x = __reg_read_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH);
++ y = __reg_read_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH);
++ z = __reg_read_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH);
++ mutex_unlock(&mma->lock);
++
++ return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t write_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if (!strncmp(buf, "Standby", count))
++ update_mode(mma, MMA7455L_MODE_STANDBY, mma->gSelect);
++ else if (!strncmp(buf, "Measurement", count))
++ update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++ else if (!strncmp(buf, "Level Detection", count))
++ update_mode(mma, MMA7455L_MODE_LEVELDETECTION, mma->gSelect);
++ else if (!strncmp(buf, "Pulse Detection", count))
++ update_mode(mma, MMA7455L_MODE_PULSEDETECTION, mma->gSelect);
++
++ return count;
++}
++
++static ssize_t write_gSelect(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long v;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if(strict_strtoul(buf, 10, &v) == 0)
++ {
++ switch(v)
++ {
++ case 8:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_8);
++ break;
++ case 4:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_4);
++ break;
++ case 2:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_2);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++ return count;
++ }
++
++ return -EINVAL;
++}
++
++static ssize_t write_level_threshold(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long v;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if(strict_strtoul(buf, 10, &v) == 0)
++ {
++ if(v <= 0xFF) {
++ reg_write(mma, MMA7455L_REG_LDTH, v);
++ return count;
++ } else
++ return -EINVAL;
++ }
++
++ return -EINVAL;
++}
++
++static ssize_t write_calibration(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ int x, y, z;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if (sscanf(buf, "%d %d %d", &x, &y, &z) == 3)
++ {
++ mutex_lock(&mma->lock);
++ __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, x);
++ __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, y);
++ __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, z);
++ mutex_unlock(&mma->lock);
++
++ return count;
++ }
++
++ return -EINVAL;
++}
++
++static DEVICE_ATTR(measure, S_IRUGO, show_measure, NULL);
++static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, write_mode);
++static DEVICE_ATTR(gSelect, S_IRUGO | S_IWUGO, show_gSelect, write_gSelect);
++static DEVICE_ATTR(level_threshold, S_IRUGO | S_IWUGO, show_level_threshold, write_level_threshold);
++static DEVICE_ATTR(calibration, S_IRUGO | S_IWUGO, show_calibration, write_calibration);
++
++static struct attribute *mma7455l_sysfs_entries[] = {
++ &dev_attr_measure.attr,
++ &dev_attr_mode.attr,
++ &dev_attr_gSelect.attr,
++ &dev_attr_level_threshold.attr,
++ &dev_attr_calibration.attr,
++ NULL
++};
++
++static struct attribute_group mma7455l_attr_group = {
++ .attrs = mma7455l_sysfs_entries,
++};
++
++/* input device handling and driver core interaction */
++static int mma7455l_input_open(struct input_dev *inp)
++{
++ struct mma7455l_info *mma = input_get_drvdata(inp);
++ if(mma->mode == MMA7455L_MODE_STANDBY)
++ update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++
++ return 0;
++}
++
++static void mma7455l_input_close(struct input_dev *inp)
++{
++ struct mma7455l_info *mma = input_get_drvdata(inp);
++ update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++}
++
++static int __devinit mma7455l_probe(struct spi_device *spi)
++{
++ int rc;
++ struct mma7455l_info *mma;
++ struct mma7455l_platform_data *pdata = spi->dev.platform_data;
++ u_int8_t wai;
++
++ mma = kzalloc(sizeof(*mma), GFP_KERNEL);
++ if (!mma)
++ return -ENOMEM;
++
++ mutex_init(&mma->lock);
++ INIT_DELAYED_WORK(&mma->work, mma7455l_work);
++ mma->spi_dev = spi;
++ mma->flags = mma->working = 0;
++
++ spi_set_drvdata(spi, mma);
++
++ rc = spi_setup(spi);
++ if (rc < 0) {
++ printk(KERN_ERR "mma7455l error durign spi_setup of mma7455l driver\n");
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++ return rc;
++ }
++
++ wai = reg_read(mma, MMA7455L_REG_WHOAMI);
++ if (wai != MMA7455L_WHOAMI_MAGIC) {
++ printk(KERN_ERR "mma7455l unknown whoami signature 0x%02x\n", wai);
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++ return -ENODEV;
++ }
++
++ rc = request_irq(mma->spi_dev->irq, mma7455l_interrupt, IRQF_TRIGGER_HIGH,
++ "mma7455l", mma);
++ if (rc < 0) {
++ dev_err(&spi->dev, "mma7455l error requesting IRQ %d\n",
++ mma->spi_dev->irq);
++ /* FIXME */
++ return rc;
++ }
++
++ rc = sysfs_create_group(&spi->dev.kobj, &mma7455l_attr_group);
++ if (rc) {
++ dev_err(&spi->dev, "error creating sysfs group\n");
++ return rc;
++ }
++
++ /* initialize input layer details */
++ mma->input_dev = input_allocate_device();
++ if (!mma->input_dev) {
++ dev_err(&spi->dev, "mma7455l Unable to allocate input device\n");
++ /* FIXME */
++ }
++
++ set_bit(EV_ABS, mma->input_dev->evbit);
++ set_bit(ABS_X, mma->input_dev->absbit);
++ set_bit(ABS_Y, mma->input_dev->absbit);
++ set_bit(ABS_Z, mma->input_dev->absbit);
++
++ input_set_drvdata(mma->input_dev, mma);
++ mma->input_dev->name = "MMA7455L";
++ mma->input_dev->open = mma7455l_input_open;
++ mma->input_dev->close = mma7455l_input_close;
++
++ rc = input_register_device(mma->input_dev);
++ if(!rc)
++ {
++ update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++ mutex_lock(&mma->lock);
++ __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, pdata->calibration_x);
++ __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, pdata->calibration_y);
++ __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, pdata->calibration_z);
++ mutex_unlock(&mma->lock);
++
++ return 0;
++ }
++
++ input_free_device(mma->input_dev);
++ return rc;
++}
++
++static int __devexit mma7455l_remove(struct spi_device *spi)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++
++ sysfs_remove_group(&spi->dev.kobj, &mma7455l_attr_group);
++ input_unregister_device(mma->input_dev);
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int mma7455l_suspend(struct spi_device *spi, pm_message_t message)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++ get_mode(mma, &mma->mode, &mma->gSelect);
++ set_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++ return 0;
++}
++
++static int mma7455l_resume(struct spi_device *spi)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++ update_mode(mma, mma->mode, mma->gSelect);
++
++ return 0;
++}
++#else
++#define mma7455l_suspend NULL
++#define mma7455l_resume NULL
++#endif
++
++static struct spi_driver mma7455l_driver = {
++ .driver = {
++ .name = "mma7455l",
++ .owner = THIS_MODULE,
++ },
++
++ .probe = mma7455l_probe,
++ .remove = __devexit_p(mma7455l_remove),
++ .suspend = mma7455l_suspend,
++ .resume = mma7455l_resume,
++};
++
++static int __init mma7455l_init(void)
++{
++ return spi_register_driver(&mma7455l_driver);
++}
++
++static void __exit mma7455l_exit(void)
++{
++ spi_unregister_driver(&mma7455l_driver);
++}
++
++MODULE_AUTHOR("Gregoire Gentil <gregoire@gentil.com>");
++MODULE_LICENSE("GPL");
++
++module_init(mma7455l_init);
++module_exit(mma7455l_exit);
+diff --git a/include/linux/mma7455l.h b/include/linux/mma7455l.h
+new file mode 100644
+index 0000000..12ab50a
+--- /dev/null
++++ b/include/linux/mma7455l.h
+@@ -0,0 +1,11 @@
++#ifndef _LINUX_MMA7455L_H
++#define _LINUX_MMA7455L_H
++
++struct mma7455l_platform_data {
++ /* Calibration offsets */
++ s16 calibration_x;
++ s16 calibration_y;
++ s16 calibration_z;
++};
++
++#endif /* _LINUX_MMA7455L_H */
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch
new file mode 100644
index 0000000000..57bb4196dd
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch
@@ -0,0 +1,64 @@
+--- a/arch/arm/mach-omap2/devices.c 2009-02-17 21:15:12.000000000 -0800
++++ b/arch/arm/mach-omap2/devices.c 2009-02-17 22:30:26.000000000 -0800
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
++#include <linux/spi/spi_gpio.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -347,6 +348,37 @@
+ .platform_data = &omap2_mcspi4_config,
+ },
+ };
++
++static struct spi_gpio_platform_data spi3_gpio_platform_data = {
++ .miso = 132,
++ .mosi = 131,
++ .sck = 130,
++ .num_chipselect = 1,
++};
++
++static struct platform_device spi3_gpio = {
++ .name = "spi_gpio",
++ .id = 3,
++ .dev = {
++ .platform_data = &spi3_gpio_platform_data,
++ },
++};
++
++static struct spi_gpio_platform_data spi4_gpio_platform_data = {
++ .miso = 159,
++ .mosi = 158,
++ .sck = 156,
++ .num_chipselect = 1,
++};
++
++static struct platform_device spi4_gpio = {
++ .name = "spi_gpio",
++ .id = 4,
++ .dev = {
++ .platform_data = &spi4_gpio_platform_data,
++ },
++};
++
+ #endif
+
+ static void omap_init_mcspi(void)
+--- a/drivers/input/touchscreen/ads7846.c 2009-04-07 10:04:12.000000000 -0700
++++ b/drivers/input/touchscreen/ads7846.c 2009-04-11 12:39:51.000000000 -0700
+@@ -887,13 +919,6 @@
+ return 0;
+ }
+
+- err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+- if (err) {
+- dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
+- pdata->gpio_pendown);
+- return err;
+- }
+-
+ ts->gpio_pendown = pdata->gpio_pendown;
+ return 0;
+ }
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-1.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-1.patch
new file mode 100644
index 0000000000..3b54e71791
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-1.patch
@@ -0,0 +1,35 @@
+aufs2 kbuild patch for linux-2.6.29
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 93945dd..75156dd 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -222,6 +222,7 @@ source "fs/qnx4/Kconfig"
+ source "fs/romfs/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
++source "fs/aufs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff --git a/fs/Makefile b/fs/Makefile
+index dc20db3..a4e9a65 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -124,3 +124,4 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_BTRFS_FS) += btrfs/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_AUFS_FS) += aufs/
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 106c3ba..d0c7262 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -34,6 +34,7 @@ header-y += atmppp.h
+ header-y += atmsap.h
+ header-y += atmsvc.h
+ header-y += atm_zatm.h
++header-y += aufs_type.h
+ header-y += auto_fs4.h
+ header-y += ax25.h
+ header-y += b1lli.h
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-2.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-2.patch
new file mode 100644
index 0000000000..bc3d5d8795
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-2.patch
@@ -0,0 +1,285 @@
+aufs2 standalone patch for linux-2.6.29
+
+diff --git a/fs/namei.c b/fs/namei.c
+index bbc15c2..f446c65 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -335,6 +335,9 @@ int deny_write_access(struct file * file)
+
+ return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(deny_write_access);
++#endif
+
+ /**
+ * path_get - get a reference to a path
+@@ -1196,7 +1199,7 @@ out:
+ * needs parent already locked. Doesn't follow mounts.
+ * SMP-safe.
+ */
+-static struct dentry *lookup_hash(struct nameidata *nd)
++struct dentry *lookup_hash(struct nameidata *nd)
+ {
+ int err;
+
+@@ -1205,8 +1208,11 @@ static struct dentry *lookup_hash(struct nameidata *nd)
+ return ERR_PTR(err);
+ return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(lookup_hash);
++#endif
+
+-static int __lookup_one_len(const char *name, struct qstr *this,
++int __lookup_one_len(const char *name, struct qstr *this,
+ struct dentry *base, int len)
+ {
+ unsigned long hash;
+@@ -1227,6 +1233,9 @@ static int __lookup_one_len(const char *name, struct qstr *this,
+ this->hash = end_name_hash(hash);
+ return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(__lookup_one_len);
++#endif
+
+ /**
+ * lookup_one_len - filesystem helper to lookup single pathname component
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 06f8e63..dcdc4ff 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -37,6 +37,9 @@
+
+ /* spinlock for vfsmount related operations, inplace of dcache_lock */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
++#if defined(CONFIG_AUFS_FS_MODULE) && defined(CONFIG_AUFS_EXPORT)
++EXPORT_SYMBOL(vfsmount_lock);
++#endif
+
+ static int event;
+ static DEFINE_IDA(mnt_id_ida);
+diff --git a/fs/open.c b/fs/open.c
+index a3a78ce..7d70245 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -220,6 +220,9 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ return err;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_truncate);
++#endif
+
+ static long do_sys_truncate(const char __user *pathname, loff_t length)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index 4ed0ba4..a110d76 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -888,8 +888,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ int ret;
+
+@@ -908,13 +908,16 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_from);
++#endif
+
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ int ret;
+
+@@ -930,6 +933,9 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+
+ return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_to);
++#endif
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/fs/super.c b/fs/super.c
+index 6ce5014..95eefb9 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -287,6 +287,9 @@ int fsync_super(struct super_block *sb)
+ __fsync_super(sb);
+ return sync_blockdev(sb->s_bdev);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(fsync_super);
++#endif
+
+ /**
+ * generic_shutdown_super - common helper for ->kill_sb()
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 23bf02f..49e5b47 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -58,7 +58,7 @@ enum lock_usage_bit
+ #define LOCKF_USED_IN_IRQ_READ \
+ (LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ)
+
+-#define MAX_LOCKDEP_SUBCLASSES 8UL
++#define MAX_LOCKDEP_SUBCLASSES 12UL
+
+ /*
+ * Lock-classes are keyed via unique addresses, by embedding the
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index fc2e035..182d43b 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -75,6 +75,9 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
+ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+ extern void release_open_intent(struct nameidata *);
+
++extern struct dentry *lookup_hash(struct nameidata *nd);
++extern int __lookup_one_len(const char *name, struct qstr *this,
++ struct dentry *base, int len);
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+ extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
+
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 528dcb9..5123bc6 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -71,4 +71,10 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
+
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
++
+ #endif
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 3aacd0f..76c8876 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -507,6 +507,9 @@ acc_check:
+
+ return -EPERM;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(devcgroup_inode_permission);
++#endif
+
+ int devcgroup_inode_mknod(int mode, dev_t dev)
+ {
+diff --git a/security/security.c b/security/security.c
+index c3586c0..f8798f8 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -389,6 +389,9 @@ int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+ return 0;
+ return security_ops->path_mkdir(path, dentry, mode);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_mkdir);
++#endif
+
+ int security_path_rmdir(struct path *path, struct dentry *dentry)
+ {
+@@ -396,6 +399,9 @@ int security_path_rmdir(struct path *path, struct dentry *dentry)
+ return 0;
+ return security_ops->path_rmdir(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rmdir);
++#endif
+
+ int security_path_unlink(struct path *path, struct dentry *dentry)
+ {
+@@ -403,6 +409,9 @@ int security_path_unlink(struct path *path, struct dentry *dentry)
+ return 0;
+ return security_ops->path_unlink(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_unlink);
++#endif
+
+ int security_path_symlink(struct path *path, struct dentry *dentry,
+ const char *old_name)
+@@ -411,6 +420,9 @@ int security_path_symlink(struct path *path, struct dentry *dentry,
+ return 0;
+ return security_ops->path_symlink(path, dentry, old_name);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_symlink);
++#endif
+
+ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ struct dentry *new_dentry)
+@@ -419,6 +431,9 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ return 0;
+ return security_ops->path_link(old_dentry, new_dir, new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_link);
++#endif
+
+ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ struct path *new_dir, struct dentry *new_dentry)
+@@ -429,6 +444,9 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ return security_ops->path_rename(old_dir, old_dentry, new_dir,
+ new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rename);
++#endif
+
+ int security_path_truncate(struct path *path, loff_t length,
+ unsigned int time_attrs)
+@@ -437,6 +455,9 @@ int security_path_truncate(struct path *path, loff_t length,
+ return 0;
+ return security_ops->path_truncate(path, length, time_attrs);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_truncate);
++#endif
+ #endif
+
+ int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+@@ -506,6 +527,9 @@ int security_inode_readlink(struct dentry *dentry)
+ return 0;
+ return security_ops->inode_readlink(dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_readlink);
++#endif
+
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+@@ -520,6 +544,9 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return security_ops->inode_permission(inode, mask);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_permission);
++#endif
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-3.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-3.patch
new file mode 100644
index 0000000000..34a035a037
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-3.patch
@@ -0,0 +1,23604 @@
+diff -Naur a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs
+--- a/Documentation/ABI/testing/debugfs-aufs 1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/debugfs-aufs 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,40 @@
++What: /debug/aufs/si_<id>/
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ Under /debug/aufs, a directory named si_<id> is created
++ per aufs mount, where <id> is a unique id generated
++ internally.
++
++What: /debug/aufs/si_<id>/xib
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xib (External Inode Number
++ Bitmap), its block size and file size.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
++
++What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xino (External Inode Number
++ Translation Table), its link count, block size and file
++ size.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
++
++What: /debug/aufs/si_<id>/xigen
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xigen (External Inode
++ Generation Table), its block size and file size.
++ If CONFIG_AUFS_EXPORT is disabled, this entry will not
++ be created.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs
+--- a/Documentation/ABI/testing/sysfs-aufs 1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/sysfs-aufs 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,25 @@
++What: /sys/fs/aufs/si_<id>/
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ Under /sys/fs/aufs, a directory named si_<id> is created
++ per aufs mount, where <id> is a unique id generated
++ internally.
++
++What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the abolute path of a member directory (which
++ is called branch) in aufs, and its permission.
++
++What: /sys/fs/aufs/si_<id>/xi_path
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the abolute path of XINO (External Inode Number
++ Bitmap, Translation Table and Generation Table) file
++ even if it is the default path.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/fs/aufs/aufs.h b/fs/aufs/aufs.h
+--- a/fs/aufs/aufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/aufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * all header files
++ */
++
++#ifndef __AUFS_H__
++#define __AUFS_H__
++
++#ifdef __KERNEL__
++
++#include "debug.h"
++
++#include "branch.h"
++#include "cpup.h"
++#include "dcsub.h"
++#include "dbgaufs.h"
++#include "dentry.h"
++#include "dir.h"
++#include "file.h"
++#include "fstype.h"
++#include "inode.h"
++#include "loop.h"
++#include "module.h"
++#include "opts.h"
++#include "rwsem.h"
++#include "spl.h"
++#include "super.h"
++#include "sysaufs.h"
++#include "vfsub.h"
++#include "whout.h"
++#include "wkq.h"
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_H__ */
+diff -Naur a/fs/aufs/branch.c b/fs/aufs/branch.c
+--- a/fs/aufs/branch.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,956 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * branch management
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++/*
++ * free a single branch
++ */
++static void au_br_do_free(struct au_branch *br)
++{
++ int i;
++ struct au_wbr *wbr;
++
++ if (br->br_xino.xi_file)
++ fput(br->br_xino.xi_file);
++ mutex_destroy(&br->br_xino.xi_nondir_mtx);
++
++ AuDebugOn(atomic_read(&br->br_count));
++
++ wbr = br->br_wbr;
++ if (wbr) {
++ for (i = 0; i < AuBrWh_Last; i++)
++ dput(wbr->wbr_wh[i]);
++ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
++ au_rwsem_destroy(&wbr->wbr_wh_rwsem);
++ }
++
++ /* some filesystems acquire extra lock */
++ lockdep_off();
++ mntput(br->br_mnt);
++ lockdep_on();
++
++ kfree(wbr);
++ kfree(br);
++}
++
++/*
++ * frees all branches
++ */
++void au_br_free(struct au_sbinfo *sbinfo)
++{
++ aufs_bindex_t bmax;
++ struct au_branch **br;
++
++ bmax = sbinfo->si_bend + 1;
++ br = sbinfo->si_branch;
++ while (bmax--)
++ au_br_do_free(*br++);
++}
++
++/*
++ * find the index of a branch which is specified by @br_id.
++ */
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (au_sbr_id(sb, bindex) == br_id)
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * add a branch
++ */
++
++static int test_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ if (unlikely(h_d1 == h_d2))
++ return 1;
++ return !!au_test_subdir(h_d1, h_d2)
++ || !!au_test_subdir(h_d2, h_d1)
++ || au_test_loopback_overlap(sb, h_d1, h_d2)
++ || au_test_loopback_overlap(sb, h_d2, h_d1);
++}
++
++/*
++ * returns a newly allocated branch. @new_nbranch is a number of branches
++ * after adding a branch.
++ */
++static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
++ int perm)
++{
++ struct au_branch *add_branch;
++ struct dentry *root;
++
++ root = sb->s_root;
++ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
++ if (unlikely(!add_branch))
++ goto out;
++
++ add_branch->br_wbr = NULL;
++ if (au_br_writable(perm)) {
++ /* may be freed separately at changing the branch permission */
++ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
++ GFP_NOFS);
++ if (unlikely(!add_branch->br_wbr))
++ goto out_br;
++ }
++
++ if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
++ || au_di_realloc(au_di(root), new_nbranch)
++ || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
++ goto out_wbr;
++ return add_branch; /* success */
++
++ out_wbr:
++ kfree(add_branch->br_wbr);
++ out_br:
++ kfree(add_branch);
++ out:
++ return ERR_PTR(-ENOMEM);
++}
++
++/*
++ * test if the branch permission is legal or not.
++ */
++static int test_br(struct inode *inode, int brperm, char *path)
++{
++ int err;
++
++ err = 0;
++ if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
++ AuErr("write permission for readonly mount or inode, %s\n",
++ path);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++/*
++ * returns:
++ * 0: success, the caller will add it
++ * plus: success, it is already unified, the caller should ignore it
++ * minus: error
++ */
++static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct dentry *root;
++ struct inode *inode, *h_inode;
++
++ root = sb->s_root;
++ bend = au_sbend(sb);
++ if (unlikely(bend >= 0
++ && au_find_dbindex(root, add->path.dentry) >= 0)) {
++ err = 1;
++ if (!remount) {
++ err = -EINVAL;
++ AuErr("%s duplicated\n", add->pathname);
++ }
++ goto out;
++ }
++
++ err = -ENOSPC; /* -E2BIG; */
++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
++ || AUFS_BRANCH_MAX - 1 <= bend)) {
++ AuErr("number of branches exceeded %s\n", add->pathname);
++ goto out;
++ }
++
++ err = -EDOM;
++ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
++ AuErr("bad index %d\n", add->bindex);
++ goto out;
++ }
++
++ inode = add->path.dentry->d_inode;
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink)) {
++ AuErr("no existence %s\n", add->pathname);
++ goto out;
++ }
++
++ err = -EINVAL;
++ if (unlikely(inode->i_sb == sb)) {
++ AuErr("%s must be outside\n", add->pathname);
++ goto out;
++ }
++
++ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
++ AuErr("unsupported filesystem, %s (%s)\n",
++ add->pathname, au_sbtype(inode->i_sb));
++ goto out;
++ }
++
++ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
++ if (unlikely(err))
++ goto out;
++
++ if (bend < 0)
++ return 0; /* success */
++
++ err = -EINVAL;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(test_overlap(sb, add->path.dentry,
++ au_h_dptr(root, bindex)))) {
++ AuErr("%s is overlapped\n", add->pathname);
++ goto out;
++ }
++
++ err = 0;
++ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
++ h_inode = au_h_dptr(root, 0)->d_inode;
++ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
++ || h_inode->i_uid != inode->i_uid
++ || h_inode->i_gid != inode->i_gid)
++ AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++ add->pathname,
++ inode->i_uid, inode->i_gid,
++ (inode->i_mode & S_IALLUGO),
++ h_inode->i_uid, h_inode->i_gid,
++ (h_inode->i_mode & S_IALLUGO));
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * initialize or clean the whiteouts for an adding branch
++ */
++static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
++ int new_perm, struct dentry *h_root)
++{
++ int err, old_perm;
++ aufs_bindex_t bindex;
++ struct mutex *h_mtx;
++ struct au_wbr *wbr;
++ struct au_hinode *hdir;
++
++ wbr = br->br_wbr;
++ old_perm = br->br_perm;
++ br->br_perm = new_perm;
++ hdir = NULL;
++ h_mtx = NULL;
++ bindex = au_br_index(sb, br->br_id);
++ if (0 <= bindex) {
++ hdir = au_hi(sb->s_root->d_inode, bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ } else {
++ h_mtx = &h_root->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
++ }
++ if (!wbr)
++ err = au_wh_init(h_root, br, sb);
++ else {
++ wbr_wh_write_lock(wbr);
++ err = au_wh_init(h_root, br, sb);
++ wbr_wh_write_unlock(wbr);
++ }
++ if (hdir)
++ au_hin_imtx_unlock(hdir);
++ else
++ mutex_unlock(h_mtx);
++ br->br_perm = old_perm;
++
++ if (!err && wbr && !au_br_writable(new_perm)) {
++ kfree(wbr);
++ br->br_wbr = NULL;
++ }
++
++ return err;
++}
++
++static int au_wbr_init(struct au_branch *br, struct super_block *sb,
++ int perm, struct path *path)
++{
++ int err;
++ struct au_wbr *wbr;
++
++ wbr = br->br_wbr;
++ init_rwsem(&wbr->wbr_wh_rwsem);
++ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
++ atomic_set(&wbr->wbr_wh_running, 0);
++ wbr->wbr_bytes = 0;
++
++ err = au_br_init_wh(sb, br, perm, path->dentry);
++
++ return err;
++}
++
++/* intialize a new branch */
++static int au_br_init(struct au_branch *br, struct super_block *sb,
++ struct au_opt_add *add)
++{
++ int err;
++
++ err = 0;
++ memset(&br->br_xino, 0, sizeof(br->br_xino));
++ mutex_init(&br->br_xino.xi_nondir_mtx);
++ br->br_perm = add->perm;
++ br->br_mnt = add->path.mnt; /* set first, mntget() later */
++ atomic_set(&br->br_count, 0);
++ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
++ atomic_set(&br->br_xino_running, 0);
++ br->br_id = au_new_br_id(sb);
++
++ if (au_br_writable(add->perm)) {
++ err = au_wbr_init(br, sb, add->perm, &add->path);
++ if (unlikely(err))
++ goto out;
++ }
++
++ if (au_opt_test(au_mntflags(sb), XINO)) {
++ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
++ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
++ if (unlikely(err)) {
++ AuDebugOn(br->br_xino.xi_file);
++ goto out;
++ }
++ }
++
++ sysaufs_br_init(br);
++ mntget(add->path.mnt);
++
++ out:
++ return err;
++}
++
++static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
++ struct au_branch *br, aufs_bindex_t bend,
++ aufs_bindex_t amount)
++{
++ struct au_branch **brp;
++
++ brp = sbinfo->si_branch + bindex;
++ memmove(brp + 1, brp, sizeof(*brp) * amount);
++ *brp = br;
++ sbinfo->si_bend++;
++ if (unlikely(bend < 0))
++ sbinfo->si_bend = 0;
++}
++
++static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
++ aufs_bindex_t bend, aufs_bindex_t amount)
++{
++ struct au_hdentry *hdp;
++
++ hdp = dinfo->di_hdentry + bindex;
++ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
++ au_h_dentry_init(hdp);
++ dinfo->di_bend++;
++ if (unlikely(bend < 0))
++ dinfo->di_bstart = 0;
++}
++
++static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
++ aufs_bindex_t bend, aufs_bindex_t amount)
++{
++ struct au_hinode *hip;
++
++ hip = iinfo->ii_hinode + bindex;
++ memmove(hip + 1, hip, sizeof(*hip) * amount);
++ hip->hi_inode = NULL;
++ au_hin_init(hip, NULL);
++ iinfo->ii_bend++;
++ if (unlikely(bend < 0))
++ iinfo->ii_bstart = 0;
++}
++
++static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
++ struct au_branch *br, aufs_bindex_t bindex)
++{
++ struct dentry *root;
++ struct inode *root_inode;
++ aufs_bindex_t bend, amount;
++
++ root = sb->s_root;
++ root_inode = root->d_inode;
++ au_plink_block_maintain(sb);
++ bend = au_sbend(sb);
++ amount = bend + 1 - bindex;
++ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
++ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
++ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
++ au_set_h_dptr(root, bindex, dget(h_dentry));
++ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
++ /*flags*/0);
++}
++
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
++{
++ int err;
++ unsigned long long maxb;
++ aufs_bindex_t bend, add_bindex;
++ struct dentry *root, *h_dentry;
++ struct inode *root_inode;
++ struct au_branch *add_branch;
++
++ root = sb->s_root;
++ root_inode = root->d_inode;
++ IMustLock(root_inode);
++ err = test_add(sb, add, remount);
++ if (unlikely(err < 0))
++ goto out;
++ if (err) {
++ err = 0;
++ goto out; /* success */
++ }
++
++ bend = au_sbend(sb);
++ add_branch = au_br_alloc(sb, bend + 2, add->perm);
++ err = PTR_ERR(add_branch);
++ if (IS_ERR(add_branch))
++ goto out;
++
++ err = au_br_init(add_branch, sb, add);
++ if (unlikely(err)) {
++ au_br_do_free(add_branch);
++ goto out;
++ }
++
++ add_bindex = add->bindex;
++ h_dentry = add->path.dentry;
++ if (!remount)
++ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++ else {
++ sysaufs_brs_del(sb, add_bindex);
++ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++ sysaufs_brs_add(sb, add_bindex);
++ }
++
++ if (!add_bindex)
++ au_cpup_attr_all(root_inode, /*force*/1);
++ else
++ au_add_nlink(root_inode, h_dentry->d_inode);
++ maxb = h_dentry->d_sb->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++
++ /*
++ * this test/set prevents aufs from handling unnecesary inotify events
++ * of xino files, in a case of re-adding a writable branch which was
++ * once detached from aufs.
++ */
++ if (au_xino_brid(sb) < 0
++ && au_br_writable(add_branch->br_perm)
++ && !au_test_fs_bad_xino(h_dentry->d_sb)
++ && add_branch->br_xino.xi_file
++ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
++ au_xino_brid_set(sb, add_branch->br_id);
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * delete a branch
++ */
++
++/* to show the line number, do not make it inlined function */
++#define AuVerbose(do_info, fmt, args...) do { \
++ if (do_info) \
++ AuInfo(fmt, ##args); \
++} while (0)
++
++/*
++ * test if the branch is deletable or not.
++ */
++static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
++ unsigned int sigen)
++{
++ int err, i, j, ndentry;
++ aufs_bindex_t bstart, bend;
++ unsigned char verbose;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry *d;
++ struct inode *inode;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ ndentry = dpage->ndentry;
++ for (j = 0; !err && j < ndentry; j++) {
++ d = dpage->dentries[j];
++ AuDebugOn(!atomic_read(&d->d_count));
++ inode = d->d_inode;
++ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
++ di_read_lock_child(d, AuLock_IR);
++ else {
++ di_write_lock_child(d);
++ err = au_reval_dpath(d, sigen);
++ if (!err)
++ di_downgrade_lock(d, AuLock_IR);
++ else {
++ di_write_unlock(d);
++ break;
++ }
++ }
++
++ bstart = au_dbstart(d);
++ bend = au_dbend(d);
++ if (bstart <= bindex
++ && bindex <= bend
++ && au_h_dptr(d, bindex)
++ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
++ err = -EBUSY;
++ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
++ }
++ di_read_unlock(d, AuLock_IR);
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
++ unsigned int sigen)
++{
++ int err;
++ struct inode *i;
++ aufs_bindex_t bstart, bend;
++ unsigned char verbose;
++
++ err = 0;
++ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
++ AuDebugOn(!atomic_read(&i->i_count));
++ if (!list_empty(&i->i_dentry))
++ continue;
++
++ if (au_iigen(i) == sigen)
++ ii_read_lock_child(i);
++ else {
++ ii_write_lock_child(i);
++ err = au_refresh_hinode_self(i, /*do_attr*/1);
++ if (!err)
++ ii_downgrade_lock(i);
++ else {
++ ii_write_unlock(i);
++ break;
++ }
++ }
++
++ bstart = au_ibstart(i);
++ bend = au_ibend(i);
++ if (bstart <= bindex
++ && bindex <= bend
++ && au_h_iptr(i, bindex)
++ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
++ err = -EBUSY;
++ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
++ ii_read_unlock(i);
++ break;
++ }
++ ii_read_unlock(i);
++ }
++
++ return err;
++}
++
++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
++{
++ int err;
++ unsigned int sigen;
++
++ sigen = au_sigen(root->d_sb);
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ err = test_dentry_busy(root, bindex, sigen);
++ if (!err)
++ err = test_inode_busy(root->d_sb, bindex, sigen);
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ return err;
++}
++
++static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
++ const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_branch **brp, **p;
++
++ brp = sbinfo->si_branch + bindex;
++ if (bindex < bend)
++ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
++ sbinfo->si_branch[0 + bend] = NULL;
++ sbinfo->si_bend--;
++
++ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ sbinfo->si_branch = p;
++}
++
++static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_hdentry *hdp, *p;
++
++ hdp = dinfo->di_hdentry + bindex;
++ if (bindex < bend)
++ memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
++ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
++ dinfo->di_bend--;
++
++ p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ dinfo->di_hdentry = p;
++}
++
++static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_hinode *hip, *p;
++
++ hip = iinfo->ii_hinode + bindex;
++ if (bindex < bend)
++ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
++ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
++ au_hin_init(iinfo->ii_hinode + bend, NULL);
++ iinfo->ii_bend--;
++
++ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ iinfo->ii_hinode = p;
++}
++
++static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_branch *br)
++{
++ aufs_bindex_t bend;
++ struct au_sbinfo *sbinfo;
++ struct dentry *root;
++ struct inode *inode;
++
++ root = sb->s_root;
++ inode = root->d_inode;
++ au_plink_block_maintain(sb);
++ sbinfo = au_sbi(sb);
++ bend = sbinfo->si_bend;
++
++ dput(au_h_dptr(root, bindex));
++ au_hiput(au_hi(inode, bindex));
++ au_br_do_free(br);
++
++ au_br_do_del_brp(sbinfo, bindex, bend);
++ au_br_do_del_hdp(au_di(root), bindex, bend);
++ au_br_do_del_hip(au_ii(inode), bindex, bend);
++}
++
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
++{
++ int err, rerr, i;
++ unsigned int mnt_flags;
++ aufs_bindex_t bindex, bend, br_id;
++ unsigned char do_wh, verbose;
++ struct au_branch *br;
++ struct au_wbr *wbr;
++
++ err = 0;
++ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
++ if (bindex < 0) {
++ if (remount)
++ goto out; /* success */
++ err = -ENOENT;
++ AuErr("%s no such branch\n", del->pathname);
++ goto out;
++ }
++ AuDbg("bindex b%d\n", bindex);
++
++ err = -EBUSY;
++ mnt_flags = au_mntflags(sb);
++ verbose = !!au_opt_test(mnt_flags, VERBOSE);
++ bend = au_sbend(sb);
++ if (unlikely(!bend)) {
++ AuVerbose(verbose, "no more branches left\n");
++ goto out;
++ }
++ br = au_sbr(sb, bindex);
++ i = atomic_read(&br->br_count);
++ if (unlikely(i)) {
++ AuVerbose(verbose, "%d file(s) opened\n", i);
++ goto out;
++ }
++
++ wbr = br->br_wbr;
++ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
++ if (do_wh) {
++ for (i = 0; i < AuBrWh_Last; i++) {
++ dput(wbr->wbr_wh[i]);
++ wbr->wbr_wh[i] = NULL;
++ }
++ }
++
++ err = test_children_busy(sb->s_root, bindex);
++ if (unlikely(err)) {
++ if (do_wh)
++ goto out_wh;
++ goto out;
++ }
++
++ err = 0;
++ br_id = br->br_id;
++ if (!remount)
++ au_br_do_del(sb, bindex, br);
++ else {
++ sysaufs_brs_del(sb, bindex);
++ au_br_do_del(sb, bindex, br);
++ sysaufs_brs_add(sb, bindex);
++ }
++
++ if (!bindex)
++ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
++ else
++ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
++ if (au_opt_test(mnt_flags, PLINK))
++ au_plink_half_refresh(sb, br_id);
++
++ if (sb->s_maxbytes == del->h_path.dentry->d_sb->s_maxbytes) {
++ bend--;
++ sb->s_maxbytes = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ unsigned long long maxb;
++
++ maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++ }
++ }
++
++ if (au_xino_brid(sb) == br->br_id)
++ au_xino_brid_set(sb, -1);
++ goto out; /* success */
++
++ out_wh:
++ /* revert */
++ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
++ if (rerr)
++ AuWarn("failed re-creating base whiteout, %s. (%d)\n",
++ del->pathname, rerr);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * change a branch permission
++ */
++
++static int do_need_sigen_inc(int a, int b)
++{
++ return au_br_whable(a) && !au_br_whable(b);
++}
++
++static int need_sigen_inc(int old, int new)
++{
++ return do_need_sigen_inc(old, new)
++ || do_need_sigen_inc(new, old);
++}
++
++static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ unsigned long n, ul, bytes, files;
++ aufs_bindex_t bstart;
++ struct file *file, *hf, **a;
++ const int step_bytes = 1024, /* memory allocation unit */
++ step_files = step_bytes / sizeof(*a);
++
++ err = -ENOMEM;
++ n = 0;
++ bytes = step_bytes;
++ files = step_files;
++ a = kmalloc(bytes, GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ /* no need file_list_lock() since sbinfo is locked? defered? */
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
++ if (special_file(file->f_dentry->d_inode->i_mode))
++ continue;
++
++ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
++ fi_read_lock(file);
++ if (unlikely(au_test_mmapped(file))) {
++ err = -EBUSY;
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ goto out_free;
++ }
++
++ bstart = au_fbstart(file);
++ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE)
++ || bstart != bindex) {
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ continue;
++ }
++
++ hf = au_h_fptr(file, bstart);
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++
++ if (n < files)
++ a[n++] = hf;
++ else {
++ void *p;
++
++ err = -ENOMEM;
++ bytes += step_bytes;
++ files += step_files;
++ p = krealloc(a, bytes, GFP_NOFS);
++ if (p) {
++ a = p;
++ a[n++] = hf;
++ } else
++ goto out_free;
++ }
++ }
++
++ err = 0;
++ for (ul = 0; ul < n; ul++) {
++ /* todo: already flushed? */
++ /* cf. fs/super.c:mark_files_ro() */
++ hf = a[ul];
++ hf->f_mode &= ~FMODE_WRITE;
++ if (!file_check_writeable(hf)) {
++ file_release_write(hf);
++ mnt_drop_write(hf->f_vfsmnt);
++ }
++ }
++
++ out_free:
++ kfree(a);
++ out:
++ return err;
++}
++
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++ int *do_update)
++{
++ int err, rerr;
++ aufs_bindex_t bindex;
++ struct dentry *root;
++ struct au_branch *br;
++
++ root = sb->s_root;
++ au_plink_block_maintain(sb);
++ bindex = au_find_dbindex(root, mod->h_root);
++ if (bindex < 0) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ AuErr("%s no such branch\n", mod->path);
++ goto out;
++ }
++ AuDbg("bindex b%d\n", bindex);
++
++ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
++ if (unlikely(err))
++ goto out;
++
++ br = au_sbr(sb, bindex);
++ if (br->br_perm == mod->perm)
++ return 0; /* success */
++
++ if (au_br_writable(br->br_perm)) {
++ /* remove whiteout base */
++ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
++ if (unlikely(err))
++ goto out;
++
++ if (!au_br_writable(mod->perm)) {
++ /* rw --> ro, file might be mmapped */
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ err = au_br_mod_files_ro(sb, bindex);
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++
++ if (unlikely(err)) {
++ rerr = -ENOMEM;
++ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
++ GFP_NOFS);
++ if (br->br_wbr)
++ rerr = au_br_init_wh
++ (sb, br, br->br_perm,
++ mod->h_root);
++ if (unlikely(rerr)) {
++ AuIOErr("nested error %d (%d)\n",
++ rerr, err);
++ br->br_perm = mod->perm;
++ }
++ }
++ }
++ } else if (au_br_writable(mod->perm)) {
++ /* ro --> rw */
++ err = -ENOMEM;
++ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
++ if (br->br_wbr) {
++ struct path path = {
++ .mnt = br->br_mnt,
++ .dentry = mod->h_root
++ };
++
++ err = au_wbr_init(br, sb, mod->perm, &path);
++ if (unlikely(err)) {
++ kfree(br->br_wbr);
++ br->br_wbr = NULL;
++ }
++ }
++ }
++
++ if (!err) {
++ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++ br->br_perm = mod->perm;
++ }
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/branch.h b/fs/aufs/branch.h
+--- a/fs/aufs/branch.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,215 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * branch filesystems and xino for them
++ */
++
++#ifndef __AUFS_BRANCH_H__
++#define __AUFS_BRANCH_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "super.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* a xino file */
++struct au_xino_file {
++ struct file *xi_file;
++ struct mutex xi_nondir_mtx;
++
++ /* todo: make xino files an array to support huge inode number */
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *xi_dbgaufs;
++#endif
++};
++
++/* members for writable branch only */
++enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
++struct au_wbr {
++ struct rw_semaphore wbr_wh_rwsem;
++ struct dentry *wbr_wh[AuBrWh_Last];
++ atomic_t wbr_wh_running;
++#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
++#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
++#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
++
++ /* mfs mode */
++ unsigned long long wbr_bytes;
++};
++
++/* protected by superblock rwsem */
++struct au_branch {
++ struct au_xino_file br_xino;
++
++ aufs_bindex_t br_id;
++
++ int br_perm;
++ struct vfsmount *br_mnt;
++ atomic_t br_count;
++
++ struct au_wbr *br_wbr;
++
++ /* xino truncation */
++ blkcnt_t br_xino_upper; /* watermark in blocks */
++ atomic_t br_xino_running;
++
++#ifdef CONFIG_SYSFS
++ /* an entry under sysfs per mount-point */
++ char br_name[8];
++ struct attribute br_attr;
++#endif
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* branch permission and attribute */
++enum {
++ AuBrPerm_RW, /* writable, linkable wh */
++ AuBrPerm_RO, /* readonly, no wh */
++ AuBrPerm_RR, /* natively readonly, no wh */
++
++ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
++
++ AuBrPerm_ROWH, /* whiteout-able */
++ AuBrPerm_RRWH, /* whiteout-able */
++
++ AuBrPerm_Last
++};
++
++static inline int au_br_writable(int brperm)
++{
++ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
++}
++
++static inline int au_br_whable(int brperm)
++{
++ return brperm == AuBrPerm_RW
++ || brperm == AuBrPerm_ROWH
++ || brperm == AuBrPerm_RRWH;
++}
++
++static inline int au_br_rdonly(struct au_branch *br)
++{
++ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
++ || !au_br_writable(br->br_perm))
++ ? -EROFS : 0;
++}
++
++static inline int au_br_hinotifyable(int brperm __maybe_unused)
++{
++#ifdef CONFIG_AUFS_HINOTIFY
++ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
++#else
++ return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* branch.c */
++struct au_sbinfo;
++void au_br_free(struct au_sbinfo *sinfo);
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
++struct au_opt_add;
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
++struct au_opt_del;
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
++struct au_opt_mod;
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++ int *do_update);
++
++/* xino.c */
++static const loff_t au_loff_max = LLONG_MAX;
++
++int au_xib_trunc(struct super_block *sb);
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos);
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos);
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
++ino_t au_xino_new_ino(struct super_block *sb);
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino);
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino);
++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t *ino);
++int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
++ struct file *base_file, int do_test);
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
++
++struct au_opt_xino;
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
++void au_xino_clr(struct super_block *sb);
++struct file *au_xino_def(struct super_block *sb);
++int au_xino_path(struct seq_file *seq, struct file *file);
++
++/* ---------------------------------------------------------------------- */
++
++/* Superblock to branch */
++static inline
++aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_id;
++}
++
++static inline
++struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_mnt;
++}
++
++static inline
++struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr_mnt(sb, bindex)->mnt_sb;
++}
++
++static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
++{
++ atomic_dec(&au_sbr(sb, bindex)->br_count);
++}
++
++static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_perm;
++}
++
++static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_br_whable(au_sbr_perm(sb, bindex));
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * wbr_wh_read_lock, wbr_wh_write_lock
++ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
++ */
++AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_BRANCH_H__ */
+diff -Naur a/fs/aufs/cpup.c b/fs/aufs/cpup.c
+--- a/fs/aufs/cpup.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1039 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * copy-up functions, see wbr_policy.c for copy-down
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src)
++{
++ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
++ | S_NOATIME | S_NOCMTIME;
++
++ dst->i_flags |= src->i_flags & ~mask;
++ if (au_test_fs_notime(dst->i_sb))
++ dst->i_flags |= S_NOATIME | S_NOCMTIME;
++}
++
++void au_cpup_attr_timesizes(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ fsstack_copy_attr_times(inode, h_inode);
++ vfsub_copy_inode_size(inode, h_inode);
++}
++
++void au_cpup_attr_nlink(struct inode *inode, int force)
++{
++ struct inode *h_inode;
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend;
++
++ sb = inode->i_sb;
++ bindex = au_ibstart(inode);
++ h_inode = au_h_iptr(inode, bindex);
++ if (!force
++ && !S_ISDIR(h_inode->i_mode)
++ && au_opt_test(au_mntflags(sb), PLINK)
++ && au_plink_test(inode))
++ return;
++
++ inode->i_nlink = h_inode->i_nlink;
++
++ /*
++ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
++ * it may includes whplink directory.
++ */
++ if (S_ISDIR(h_inode->i_mode)) {
++ bend = au_ibend(inode);
++ for (bindex++; bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode)
++ au_add_nlink(inode, h_inode);
++ }
++ }
++}
++
++void au_cpup_attr_changeable(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ inode->i_mode = h_inode->i_mode;
++ inode->i_uid = h_inode->i_uid;
++ inode->i_gid = h_inode->i_gid;
++ au_cpup_attr_timesizes(inode);
++ au_cpup_attr_flags(inode, h_inode);
++}
++
++void au_cpup_igen(struct inode *inode, struct inode *h_inode)
++{
++ struct au_iinfo *iinfo = au_ii(inode);
++
++ iinfo->ii_higen = h_inode->i_generation;
++ iinfo->ii_hsb1 = h_inode->i_sb;
++}
++
++void au_cpup_attr_all(struct inode *inode, int force)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ au_cpup_attr_changeable(inode);
++ if (inode->i_nlink > 0)
++ au_cpup_attr_nlink(inode, force);
++ inode->i_rdev = h_inode->i_rdev;
++ inode->i_blkbits = h_inode->i_blkbits;
++ au_cpup_igen(inode, h_inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
++
++/* keep the timestamps of the parent dir when cpup */
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++ struct path *h_path)
++{
++ struct inode *h_inode;
++
++ dt->dt_dentry = dentry;
++ dt->dt_h_path = *h_path;
++ h_inode = h_path->dentry->d_inode;
++ dt->dt_atime = h_inode->i_atime;
++ dt->dt_mtime = h_inode->i_mtime;
++ /* smp_mb(); */
++}
++
++void au_dtime_revert(struct au_dtime *dt)
++{
++ struct iattr attr;
++ int err;
++
++ attr.ia_atime = dt->dt_atime;
++ attr.ia_mtime = dt->dt_mtime;
++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
++ | ATTR_ATIME | ATTR_ATIME_SET;
++
++ err = vfsub_notify_change(&dt->dt_h_path, &attr);
++ if (unlikely(err))
++ AuWarn("restoring timestamps failed(%d). ignored\n", err);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static noinline_for_stack
++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
++{
++ int err, sbits;
++ struct iattr ia;
++ struct path h_path;
++ struct inode *h_isrc;
++
++ h_path.dentry = au_h_dptr(dst, bindex);
++ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
++ h_isrc = h_src->d_inode;
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
++ | ATTR_ATIME | ATTR_MTIME
++ | ATTR_ATIME_SET | ATTR_MTIME_SET;
++ ia.ia_mode = h_isrc->i_mode;
++ ia.ia_uid = h_isrc->i_uid;
++ ia.ia_gid = h_isrc->i_gid;
++ ia.ia_atime = h_isrc->i_atime;
++ ia.ia_mtime = h_isrc->i_mtime;
++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++ au_cpup_attr_flags(h_path.dentry->d_inode, h_isrc);
++ err = vfsub_notify_change(&h_path, &ia);
++
++ /* is this nfs only? */
++ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++ ia.ia_mode = h_isrc->i_mode;
++ err = vfsub_notify_change(&h_path, &ia);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
++ char *buf, unsigned long blksize)
++{
++ int err;
++ size_t sz, rbytes, wbytes;
++ unsigned char all_zero;
++ char *p, *zp;
++ struct mutex *h_mtx;
++ /* reduce stack usage */
++ struct iattr *ia;
++
++ zp = page_address(ZERO_PAGE(0));
++ if (unlikely(!zp))
++ return -ENOMEM; /* possible? */
++
++ err = 0;
++ all_zero = 0;
++ while (len) {
++ AuDbg("len %lld\n", len);
++ sz = blksize;
++ if (len < blksize)
++ sz = len;
++
++ rbytes = 0;
++ /* todo: signal_pending? */
++ while (!rbytes || err == -EAGAIN || err == -EINTR) {
++ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
++ err = rbytes;
++ }
++ if (unlikely(err < 0))
++ break;
++
++ all_zero = 0;
++ if (len >= rbytes && rbytes == blksize)
++ all_zero = !memcmp(buf, zp, rbytes);
++ if (!all_zero) {
++ wbytes = rbytes;
++ p = buf;
++ while (wbytes) {
++ size_t b;
++
++ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
++ err = b;
++ /* todo: signal_pending? */
++ if (unlikely(err == -EAGAIN || err == -EINTR))
++ continue;
++ if (unlikely(err < 0))
++ break;
++ wbytes -= b;
++ p += b;
++ }
++ } else {
++ loff_t res;
++
++ AuLabel(hole);
++ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
++ err = res;
++ if (unlikely(res < 0))
++ break;
++ }
++ len -= rbytes;
++ err = 0;
++ }
++
++ /* the last block may be a hole */
++ if (!err && all_zero) {
++ AuLabel(last hole);
++
++ err = 1;
++ if (au_test_nfs(dst->f_dentry->d_sb)) {
++ /* nfs requires this step to make last hole */
++ /* is this only nfs? */
++ do {
++ /* todo: signal_pending? */
++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ if (err == 1)
++ dst->f_pos--;
++ }
++
++ if (err == 1) {
++ ia = (void *)buf;
++ ia->ia_size = dst->f_pos;
++ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
++ ia->ia_file = dst;
++ h_mtx = &dst->f_dentry->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
++ err = vfsub_notify_change(&dst->f_path, ia);
++ mutex_unlock(h_mtx);
++ }
++ }
++
++ return err;
++}
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len)
++{
++ int err;
++ unsigned long blksize;
++ unsigned char do_kfree;
++ char *buf;
++
++ err = -ENOMEM;
++ blksize = dst->f_dentry->d_sb->s_blocksize;
++ if (!blksize || PAGE_SIZE < blksize)
++ blksize = PAGE_SIZE;
++ AuDbg("blksize %lu\n", blksize);
++ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
++ if (do_kfree)
++ buf = kmalloc(blksize, GFP_NOFS);
++ else
++ buf = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!buf))
++ goto out;
++
++ if (len > (1 << 22))
++ AuDbg("copying a large file %lld\n", (long long)len);
++
++ src->f_pos = 0;
++ dst->f_pos = 0;
++ err = au_do_copy_file(dst, src, len, buf, blksize);
++ if (do_kfree)
++ kfree(buf);
++ else
++ free_page((unsigned long)buf);
++
++ out:
++ return err;
++}
++
++/*
++ * to support a sparse file which is opened with O_APPEND,
++ * we need to close the file.
++ */
++static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len)
++{
++ int err, i;
++ enum { SRC, DST };
++ struct {
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ struct dentry *dentry;
++ struct file *file;
++ void *label, *label_file;
++ } *f, file[] = {
++ {
++ .bindex = bsrc,
++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out,
++ .label_file = &&out_src
++ },
++ {
++ .bindex = bdst,
++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out_src,
++ .label_file = &&out_dst
++ }
++ };
++ struct super_block *sb;
++
++ /* bsrc branch can be ro/rw. */
++ sb = dentry->d_sb;
++ f = file;
++ for (i = 0; i < 2; i++, f++) {
++ f->dentry = au_h_dptr(dentry, f->bindex);
++ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
++ err = PTR_ERR(f->file);
++ if (IS_ERR(f->file))
++ goto *f->label;
++ err = -EINVAL;
++ if (unlikely(!f->file->f_op))
++ goto *f->label_file;
++ }
++
++ /* try stopping to update while we copyup */
++ IMustLock(file[SRC].dentry->d_inode);
++ err = au_copy_file(file[DST].file, file[SRC].file, len);
++
++ out_dst:
++ fput(file[DST].file);
++ au_sbr_put(sb, file[DST].bindex);
++ out_src:
++ fput(file[SRC].file);
++ au_sbr_put(sb, file[SRC].bindex);
++ out:
++ return err;
++}
++
++static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len,
++ struct inode *h_dir, struct path *h_path)
++{
++ int err, rerr;
++ loff_t l;
++
++ err = 0;
++ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
++ if (len == -1 || l < len)
++ len = l;
++ if (len)
++ err = au_cp_regular(dentry, bdst, bsrc, len);
++ if (!err)
++ goto out; /* success */
++
++ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
++ if (rerr) {
++ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
++ AuDLNPair(h_path->dentry), err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ return err;
++}
++
++static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
++ struct inode *h_dir)
++{
++ int err, symlen;
++ mm_segment_t old_fs;
++ char *sym;
++
++ err = -ENOSYS;
++ if (unlikely(!h_src->d_inode->i_op->readlink))
++ goto out;
++
++ err = -ENOMEM;
++ sym = __getname();
++ if (unlikely(!sym))
++ goto out;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
++ PATH_MAX);
++ err = symlen;
++ set_fs(old_fs);
++
++ if (symlen > 0) {
++ sym[symlen] = 0;
++ err = vfsub_symlink(h_dir, h_path, sym);
++ }
++ __putname(sym);
++
++ out:
++ return err;
++}
++
++/* return with the lower dst inode is locked */
++static noinline_for_stack
++int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err;
++ umode_t mode;
++ unsigned int mnt_flags;
++ unsigned char isdir;
++ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
++ struct au_dtime dt;
++ struct path h_path;
++ struct dentry *h_src, *h_dst, *h_parent;
++ struct inode *h_inode, *h_dir;
++ struct super_block *sb;
++
++ /* bsrc branch can be ro/rw. */
++ h_src = au_h_dptr(dentry, bsrc);
++ h_inode = h_src->d_inode;
++ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
++
++ /* try stopping to be referenced while we are creating */
++ h_dst = au_h_dptr(dentry, bdst);
++ h_parent = h_dst->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++ AuDebugOn(h_parent != h_dst->d_parent);
++
++ sb = dentry->d_sb;
++ h_path.mnt = au_sbr_mnt(sb, bdst);
++ if (do_dt) {
++ h_path.dentry = h_parent;
++ au_dtime_store(&dt, dst_parent, &h_path);
++ }
++ h_path.dentry = h_dst;
++
++ isdir = 0;
++ mode = h_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ /* try stopping to update while we are referencing */
++ IMustLock(h_inode);
++ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
++ if (!err)
++ err = au_do_cpup_regular
++ (dentry, bdst, bsrc, len,
++ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ err = vfsub_mkdir(h_dir, &h_path, mode);
++ if (!err) {
++ /*
++ * strange behaviour from the users view,
++ * particularry setattr case
++ */
++ if (au_ibstart(dst_parent->d_inode) == bdst)
++ au_cpup_attr_nlink(dst_parent->d_inode,
++ /*force*/1);
++ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
++ }
++ break;
++ case S_IFLNK:
++ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
++ break;
++ case S_IFCHR:
++ case S_IFBLK:
++ AuDebugOn(!capable(CAP_MKNOD));
++ /*FALLTHROUGH*/
++ case S_IFIFO:
++ case S_IFSOCK:
++ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
++ break;
++ default:
++ AuIOErr("Unknown inode type 0%o\n", mode);
++ err = -EIO;
++ }
++
++ mnt_flags = au_mntflags(sb);
++ if (!au_opt_test(mnt_flags, UDBA_NONE)
++ && !isdir
++ && au_opt_test(mnt_flags, XINO)
++ && h_inode->i_nlink == 1
++ /* todo: unnecessary? */
++ /* && dentry->d_inode->i_nlink == 1 */
++ && bdst < bsrc
++ && !au_ftest_cpup(flags, KEEPLINO))
++ au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
++ /* ignore this error */
++
++ if (do_dt)
++ au_dtime_revert(&dt);
++ return err;
++}
++
++/*
++ * copyup the @dentry from @bsrc to @bdst.
++ * the caller must set the both of lower dentries.
++ * @len is for truncating when it is -1 copyup the entire file.
++ * in link/rename cases, @dst_parent may be different from the real one.
++ */
++static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err, rerr;
++ aufs_bindex_t old_ibstart;
++ unsigned char isdir, plink;
++ struct au_dtime dt;
++ struct path h_path;
++ struct dentry *h_src, *h_dst, *h_parent;
++ struct inode *dst_inode, *h_dir, *inode;
++ struct super_block *sb;
++
++ AuDebugOn(bsrc <= bdst);
++
++ sb = dentry->d_sb;
++ h_path.mnt = au_sbr_mnt(sb, bdst);
++ h_dst = au_h_dptr(dentry, bdst);
++ h_parent = h_dst->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ h_src = au_h_dptr(dentry, bsrc);
++ inode = dentry->d_inode;
++
++ if (!dst_parent)
++ dst_parent = dget_parent(dentry);
++ else
++ dget(dst_parent);
++
++ plink = !!au_opt_test(au_mntflags(sb), PLINK);
++ dst_inode = au_h_iptr(inode, bdst);
++ if (dst_inode) {
++ if (unlikely(!plink)) {
++ err = -EIO;
++ AuIOErr("i%lu exists on a upper branch "
++ "but plink is disabled\n", inode->i_ino);
++ goto out;
++ }
++
++ if (dst_inode->i_nlink) {
++ const int do_dt = au_ftest_cpup(flags, DTIME);
++
++ h_src = au_plink_lkup(inode, bdst);
++ err = PTR_ERR(h_src);
++ if (IS_ERR(h_src))
++ goto out;
++ if (unlikely(!h_src->d_inode)) {
++ err = -EIO;
++ AuIOErr("i%lu exists on a upper branch "
++ "but plink is broken\n", inode->i_ino);
++ dput(h_src);
++ goto out;
++ }
++
++ if (do_dt) {
++ h_path.dentry = h_parent;
++ au_dtime_store(&dt, dst_parent, &h_path);
++ }
++ h_path.dentry = h_dst;
++ err = vfsub_link(h_src, h_dir, &h_path);
++ if (do_dt)
++ au_dtime_revert(&dt);
++ dput(h_src);
++ goto out;
++ } else
++ /* todo: cpup_wh_file? */
++ /* udba work */
++ au_update_brange(inode, 1);
++ }
++
++ old_ibstart = au_ibstart(inode);
++ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
++ if (unlikely(err))
++ goto out;
++ dst_inode = h_dst->d_inode;
++ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
++
++ err = cpup_iattr(dentry, bdst, h_src);
++ isdir = S_ISDIR(dst_inode->i_mode);
++ if (!err) {
++ if (bdst < old_ibstart)
++ au_set_ibstart(inode, bdst);
++ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
++ au_hi_flags(inode, isdir));
++ mutex_unlock(&dst_inode->i_mutex);
++ if (!isdir
++ && h_src->d_inode->i_nlink > 1
++ && plink)
++ au_plink_append(inode, bdst, h_dst);
++ goto out; /* success */
++ }
++
++ /* revert */
++ h_path.dentry = h_parent;
++ mutex_unlock(&dst_inode->i_mutex);
++ au_dtime_store(&dt, dst_parent, &h_path);
++ h_path.dentry = h_dst;
++ if (!isdir)
++ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ else
++ rerr = vfsub_rmdir(h_dir, &h_path);
++ au_dtime_revert(&dt);
++ if (rerr) {
++ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ dput(dst_parent);
++ return err;
++}
++
++struct au_cpup_single_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst, bsrc;
++ loff_t len;
++ unsigned int flags;
++ struct dentry *dst_parent;
++};
++
++static void au_call_cpup_single(void *args)
++{
++ struct au_cpup_single_args *a = args;
++ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
++ a->flags, a->dst_parent);
++}
++
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err, wkq_err;
++ umode_t mode;
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bsrc);
++ mode = h_dentry->d_inode->i_mode & S_IFMT;
++ if ((mode != S_IFCHR && mode != S_IFBLK)
++ || capable(CAP_MKNOD))
++ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
++ dst_parent);
++ else {
++ struct au_cpup_single_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .bsrc = bsrc,
++ .len = len,
++ .flags = flags,
++ .dst_parent = dst_parent
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++/*
++ * copyup the @dentry from the first active lower branch to @bdst,
++ * using au_cpup_single().
++ */
++static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err;
++ aufs_bindex_t bsrc, bend;
++
++ bend = au_dbend(dentry);
++ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
++ if (au_h_dptr(dentry, bsrc))
++ break;
++
++ err = au_lkup_neg(dentry, bdst);
++ if (!err) {
++ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
++ if (!err)
++ return 0; /* success */
++
++ /* revert */
++ au_set_h_dptr(dentry, bdst, NULL);
++ au_set_dbstart(dentry, bsrc);
++ }
++
++ return err;
++}
++
++struct au_cpup_simple_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void au_call_cpup_simple(void *args)
++{
++ struct au_cpup_simple_args *a = args;
++ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
++}
++
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err, wkq_err;
++ unsigned char do_sio;
++ struct dentry *parent;
++ struct inode *h_dir;
++
++ parent = dget_parent(dentry);
++ h_dir = au_h_iptr(parent->d_inode, bdst);
++ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio) {
++ /*
++ * testing CAP_MKNOD is for generic fs,
++ * but CAP_FSETID is for xfs only, currently.
++ */
++ umode_t mode = dentry->d_inode->i_mode;
++ do_sio = (((mode & (S_IFCHR | S_IFBLK))
++ && !capable(CAP_MKNOD))
++ || ((mode & (S_ISUID | S_ISGID))
++ && !capable(CAP_FSETID)));
++ }
++ if (!do_sio)
++ err = au_cpup_simple(dentry, bdst, len, flags);
++ else {
++ struct au_cpup_simple_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .flags = flags
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * copyup the deleted file for writing.
++ */
++static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *wh_dentry, struct file *file,
++ loff_t len)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct dentry *h_d_dst, *h_d_start;
++
++ dinfo = au_di(dentry);
++ bstart = dinfo->di_bstart;
++ h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
++ dinfo->di_bstart = bdst;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
++ h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
++ if (file)
++ dinfo->di_hdentry[0 + bstart].hd_dentry
++ = au_h_fptr(file, au_fbstart(file))->f_dentry;
++ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
++ /*h_parent*/NULL);
++ if (!err && file) {
++ err = au_reopen_nondir(file);
++ dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
++ }
++ dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
++ dinfo->di_bstart = bstart;
++
++ return err;
++}
++
++static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file)
++{
++ int err;
++ struct au_dtime dt;
++ struct dentry *parent, *h_parent, *wh_dentry;
++ struct au_branch *br;
++ struct path h_path;
++
++ br = au_sbr(dentry->d_sb, bdst);
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bdst);
++ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ h_path.dentry = h_parent;
++ h_path.mnt = br->br_mnt;
++ au_dtime_store(&dt, parent, &h_path);
++ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
++ if (unlikely(err))
++ goto out_wh;
++
++ dget(wh_dentry);
++ h_path.dentry = wh_dentry;
++ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
++ if (unlikely(err)) {
++ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
++ AuDLNPair(wh_dentry), err);
++ err = -EIO;
++ }
++ au_dtime_revert(&dt);
++ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ dput(parent);
++ return err;
++}
++
++struct au_cpup_wh_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ struct file *file;
++};
++
++static void au_call_cpup_wh(void *args)
++{
++ struct au_cpup_wh_args *a = args;
++ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
++}
++
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file)
++{
++ int err, wkq_err;
++ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
++ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
++ struct au_wbr *wbr;
++
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ h_orph = NULL;
++ h_parent = NULL;
++ h_dir = au_igrab(au_h_iptr(dir, bdst));
++ h_tmpdir = h_dir;
++ if (!h_dir->i_nlink) {
++ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
++ h_orph = wbr->wbr_orph;
++
++ h_parent = dget(au_h_dptr(parent, bdst));
++ au_set_h_dptr(parent, bdst, NULL);
++ au_set_h_dptr(parent, bdst, dget(h_orph));
++ h_tmpdir = h_orph->d_inode;
++ au_set_h_iptr(dir, bdst, NULL, 0);
++ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
++
++ /* this temporary unlock is safe */
++ if (file)
++ h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
++ else
++ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
++ h_inode = h_dentry->d_inode;
++ IMustLock(h_inode);
++ mutex_unlock(&h_inode->i_mutex);
++ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT2);
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ }
++
++ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
++ err = au_cpup_wh(dentry, bdst, len, file);
++ else {
++ struct au_cpup_wh_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .file = file
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ if (h_orph) {
++ mutex_unlock(&h_tmpdir->i_mutex);
++ au_set_h_iptr(dir, bdst, NULL, 0);
++ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
++ au_set_h_dptr(parent, bdst, NULL);
++ au_set_h_dptr(parent, bdst, h_parent);
++ }
++ iput(h_dir);
++ dput(parent);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generic routine for both of copy-up and copy-down.
++ */
++/* cf. revalidate function in file.c */
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg),
++ void *arg)
++{
++ int err;
++ struct au_pin pin;
++ struct dentry *d, *parent, *h_parent, *real_parent;
++
++ err = 0;
++ parent = dget_parent(dentry);
++ if (IS_ROOT(parent))
++ goto out;
++
++ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
++ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
++
++ /* do not use au_dpage */
++ real_parent = parent;
++ while (1) {
++ dput(parent);
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bdst);
++ if (h_parent)
++ goto out; /* success */
++
++ /* find top dir which is necessary to cpup */
++ do {
++ d = parent;
++ dput(parent);
++ parent = dget_parent(d);
++ di_read_lock_parent3(parent, !AuLock_IR);
++ h_parent = au_h_dptr(parent, bdst);
++ di_read_unlock(parent, !AuLock_IR);
++ } while (!h_parent);
++
++ if (d != real_parent)
++ di_write_lock_child3(d);
++
++ /* somebody else might create while we were sleeping */
++ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
++ if (au_h_dptr(d, bdst))
++ au_update_dbstart(d);
++
++ au_pin_set_dentry(&pin, d);
++ err = au_do_pin(&pin);
++ if (!err) {
++ err = cp(d, bdst, h_parent, arg);
++ au_unpin(&pin);
++ }
++ }
++
++ if (d != real_parent)
++ di_write_unlock(d);
++ if (unlikely(err))
++ break;
++ }
++
++ out:
++ dput(parent);
++ return err;
++}
++
++static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent __maybe_unused ,
++ void *arg __maybe_unused)
++{
++ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
++}
++
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
++}
++
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *dir;
++
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ err = 0;
++ if (au_h_iptr(dir, bdst))
++ goto out;
++
++ di_read_unlock(parent, AuLock_IR);
++ di_write_lock_parent(parent);
++ /* someone else might change our inode while we were sleeping */
++ if (!au_h_iptr(dir, bdst))
++ err = au_cpup_dirs(dentry, bdst);
++ di_downgrade_lock(parent, AuLock_IR);
++
++ out:
++ dput(parent);
++ return err;
++}
+diff -Naur a/fs/aufs/cpup.h b/fs/aufs/cpup.h
+--- a/fs/aufs/cpup.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * copy-up/down functions
++ */
++
++#ifndef __AUFS_CPUP_H__
++#define __AUFS_CPUP_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/time.h>
++#include <linux/aufs_type.h>
++
++struct inode;
++struct file;
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src);
++void au_cpup_attr_timesizes(struct inode *inode);
++void au_cpup_attr_nlink(struct inode *inode, int force);
++void au_cpup_attr_changeable(struct inode *inode);
++void au_cpup_igen(struct inode *inode, struct inode *h_inode);
++void au_cpup_attr_all(struct inode *inode, int force);
++
++/* ---------------------------------------------------------------------- */
++
++/* cpup flags */
++#define AuCpup_DTIME 1 /* do dtime_store/revert */
++#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
++ for link(2) */
++#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
++#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
++#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len);
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent);
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file);
++
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg),
++ void *arg);
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++/* keep timestamps when copyup */
++struct au_dtime {
++ struct dentry *dt_dentry;
++ struct path dt_h_path;
++ struct timespec dt_atime, dt_mtime;
++};
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++ struct path *h_path);
++void au_dtime_revert(struct au_dtime *dt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_CPUP_H__ */
+diff -Naur a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
+--- a/fs/aufs/dbgaufs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,313 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debugfs interface
++ */
++
++#include <linux/debugfs.h>
++#include "aufs.h"
++
++#ifndef CONFIG_SYSFS
++#error DEBUG_FS depends upon SYSFS
++#endif
++
++static struct dentry *dbgaufs;
++static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
++
++/* 20 is max digits length of ulong 64 */
++struct dbgaufs_arg {
++ int n;
++ char a[20 * 4];
++};
++
++/*
++ * common function for all XINO files
++ */
++static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ kfree(file->private_data);
++ return 0;
++}
++
++static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
++{
++ int err;
++ struct kstat st;
++ struct dbgaufs_arg *p;
++
++ err = -ENOMEM;
++ p = kmalloc(sizeof(*p), GFP_NOFS);
++ if (unlikely(!p))
++ goto out;
++
++ err = 0;
++ p->n = 0;
++ file->private_data = p;
++ if (!xf)
++ goto out;
++
++ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
++ if (!err) {
++ if (do_fcnt)
++ p->n = snprintf
++ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
++ (long)file_count(xf), st.blocks, st.blksize,
++ (long long)st.size);
++ else
++ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
++ st.blocks, st.blksize,
++ (long long)st.size);
++ AuDebugOn(p->n >= sizeof(p->a));
++ } else {
++ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
++ err = 0;
++ }
++
++ out:
++ return err;
++
++}
++
++static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct dbgaufs_arg *p;
++
++ p = file->private_data;
++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int dbgaufs_xib_open(struct inode *inode, struct file *file)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
++ si_read_unlock(sb);
++ return err;
++}
++
++static const struct file_operations dbgaufs_xib_fop = {
++ .open = dbgaufs_xib_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define DbgaufsXi_PREFIX "xi"
++
++static int dbgaufs_xino_open(struct inode *inode, struct file *file)
++{
++ int err;
++ long l;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++ struct file *xf;
++ struct qstr *name;
++
++ err = -ENOENT;
++ xf = NULL;
++ name = &file->f_dentry->d_name;
++ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
++ || memcmp(name->name, DbgaufsXi_PREFIX,
++ sizeof(DbgaufsXi_PREFIX) - 1)))
++ goto out;
++ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
++ if (unlikely(err))
++ goto out;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ if (l <= au_sbend(sb)) {
++ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
++ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
++ } else
++ err = -ENOENT;
++ si_read_unlock(sb);
++
++ out:
++ return err;
++}
++
++static const struct file_operations dbgaufs_xino_fop = {
++ .open = dbgaufs_xino_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ aufs_bindex_t bend;
++ struct au_branch *br;
++ struct au_xino_file *xi;
++
++ if (!au_sbi(sb)->si_dbgaufs)
++ return;
++
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ xi = &br->br_xino;
++ if (xi->xi_dbgaufs) {
++ debugfs_remove(xi->xi_dbgaufs);
++ xi->xi_dbgaufs = NULL;
++ }
++ }
++}
++
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ struct au_sbinfo *sbinfo;
++ struct dentry *parent;
++ struct au_branch *br;
++ struct au_xino_file *xi;
++ aufs_bindex_t bend;
++ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
++
++ sbinfo = au_sbi(sb);
++ parent = sbinfo->si_dbgaufs;
++ if (!parent)
++ return;
++
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
++ br = au_sbr(sb, bindex);
++ xi = &br->br_xino;
++ AuDebugOn(xi->xi_dbgaufs);
++ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
++ sbinfo, &dbgaufs_xino_fop);
++ /* ignore an error */
++ if (unlikely(!xi->xi_dbgaufs))
++ AuWarn1("failed %s under debugfs\n", name);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
++ si_read_unlock(sb);
++ return err;
++}
++
++static const struct file_operations dbgaufs_xigen_fop = {
++ .open = dbgaufs_xigen_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++
++ err = -EIO;
++ sbinfo->si_dbgaufs_xigen = debugfs_create_file
++ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++ &dbgaufs_xigen_fop);
++ if (sbinfo->si_dbgaufs_xigen)
++ err = 0;
++
++ return err;
++}
++#else
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++ return 0;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++ debugfs_remove_recursive(sbinfo->si_dbgaufs);
++ sbinfo->si_dbgaufs = NULL;
++ kobject_put(&sbinfo->si_kobj);
++}
++
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++ char name[SysaufsSiNameLen];
++
++ err = -ENOENT;
++ if (!dbgaufs) {
++ AuErr1("/debug/aufs is uninitialized\n");
++ goto out;
++ }
++
++ err = -EIO;
++ sysaufs_name(sbinfo, name);
++ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
++ if (unlikely(!sbinfo->si_dbgaufs))
++ goto out;
++ kobject_get(&sbinfo->si_kobj);
++
++ sbinfo->si_dbgaufs_xib = debugfs_create_file
++ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++ &dbgaufs_xib_fop);
++ if (unlikely(!sbinfo->si_dbgaufs_xib))
++ goto out_dir;
++
++ err = dbgaufs_xigen_init(sbinfo);
++ if (!err)
++ goto out; /* success */
++
++ out_dir:
++ dbgaufs_si_fin(sbinfo);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_fin(void)
++{
++ debugfs_remove(dbgaufs);
++}
++
++int __init dbgaufs_init(void)
++{
++ int err;
++
++ err = -EIO;
++ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
++ if (dbgaufs)
++ err = 0;
++ return err;
++}
+diff -Naur a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
+--- a/fs/aufs/dbgaufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debugfs interface
++ */
++
++#ifndef __DBGAUFS_H__
++#define __DBGAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/init.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++struct au_sbinfo;
++
++#ifdef CONFIG_DEBUG_FS
++/* dbgaufs.c */
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
++int dbgaufs_si_init(struct au_sbinfo *sbinfo);
++void dbgaufs_fin(void);
++int __init dbgaufs_init(void);
++
++#else
++
++static inline
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* empty */
++}
++
++static inline
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* empty */
++}
++
++static inline
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++ /* empty */
++}
++
++static inline
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ return 0;
++}
++
++#define dbgaufs_fin() do {} while (0)
++
++static inline
++int __init dbgaufs_init(void)
++{
++ return 0;
++}
++#endif /* CONFIG_DEBUG_FS */
++
++#endif /* __KERNEL__ */
++#endif /* __DBGAUFS_H__ */
+diff -Naur a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
+--- a/fs/aufs/dcsub.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,223 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#include "aufs.h"
++
++static void au_dpage_free(struct au_dpage *dpage)
++{
++ int i;
++ struct dentry **p;
++
++ p = dpage->dentries;
++ for (i = 0; i < dpage->ndentry; i++)
++ dput(*p++);
++ free_page((unsigned long)dpage->dentries);
++}
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
++{
++ int err;
++ void *p;
++
++ err = -ENOMEM;
++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
++ if (unlikely(!dpages->dpages))
++ goto out;
++
++ p = (void *)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out_dpages;
++
++ dpages->dpages[0].ndentry = 0;
++ dpages->dpages[0].dentries = p;
++ dpages->ndpage = 1;
++ return 0; /* success */
++
++ out_dpages:
++ kfree(dpages->dpages);
++ out:
++ return err;
++}
++
++void au_dpages_free(struct au_dcsub_pages *dpages)
++{
++ int i;
++ struct au_dpage *p;
++
++ p = dpages->dpages;
++ for (i = 0; i < dpages->ndpage; i++)
++ au_dpage_free(p++);
++ kfree(dpages->dpages);
++}
++
++static int au_dpages_append(struct au_dcsub_pages *dpages,
++ struct dentry *dentry, gfp_t gfp)
++{
++ int err, sz;
++ struct au_dpage *dpage;
++ void *p;
++
++ dpage = dpages->dpages + dpages->ndpage - 1;
++ sz = PAGE_SIZE / sizeof(dentry);
++ if (unlikely(dpage->ndentry >= sz)) {
++ AuLabel(new dpage);
++ err = -ENOMEM;
++ sz = dpages->ndpage * sizeof(*dpages->dpages);
++ p = au_kzrealloc(dpages->dpages, sz,
++ sz + sizeof(*dpages->dpages), gfp);
++ if (unlikely(!p))
++ goto out;
++
++ dpages->dpages = p;
++ dpage = dpages->dpages + dpages->ndpage;
++ p = (void *)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out;
++
++ dpage->ndentry = 0;
++ dpage->dentries = p;
++ dpages->ndpage++;
++ }
++
++ dpage->dentries[dpage->ndentry++] = dget(dentry);
++ return 0; /* success */
++
++ out:
++ return err;
++}
++
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg)
++{
++ int err;
++ struct dentry *this_parent = root;
++ struct list_head *next;
++ struct super_block *sb = root->d_sb;
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ repeat:
++ next = this_parent->d_subdirs.next;
++ resume:
++ if (this_parent->d_sb == sb
++ && !IS_ROOT(this_parent)
++ && atomic_read(&this_parent->d_count)
++ && this_parent->d_inode
++ && (!test || test(this_parent, arg))) {
++ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++
++ while (next != &this_parent->d_subdirs) {
++ struct list_head *tmp = next;
++ struct dentry *dentry = list_entry(tmp, struct dentry,
++ d_u.d_child);
++ next = tmp->next;
++ if (/*d_unhashed(dentry) || */!dentry->d_inode)
++ continue;
++ if (!list_empty(&dentry->d_subdirs)) {
++ this_parent = dentry;
++ goto repeat;
++ }
++ if (dentry->d_sb == sb
++ && atomic_read(&dentry->d_count)
++ && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ }
++
++ if (this_parent != root) {
++ next = this_parent->d_u.d_child.next;
++ this_parent = this_parent->d_parent; /* dcache_lock is locked */
++ goto resume;
++ }
++ out:
++ spin_unlock(&dcache_lock);
++ return err;
++}
++
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++ int do_include, au_dpages_test test, void *arg)
++{
++ int err;
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ if (do_include && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ while (!IS_ROOT(dentry)) {
++ dentry = dentry->d_parent; /* dcache_lock is locked */
++ if (!test || test(dentry, arg)) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ break;
++ }
++ }
++
++ out:
++ spin_unlock(&dcache_lock);
++
++ return err;
++}
++
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
++{
++ struct dentry *trap, **dentries;
++ int err, i, j;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++
++ trap = ERR_PTR(-ENOMEM);
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ trap = d1;
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ for (j = 0; !err && j < dpage->ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ err = (d == d2);
++ if (!err)
++ trap = d;
++ }
++ }
++ if (!err)
++ trap = NULL;
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return trap;
++}
+diff -Naur a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
+--- a/fs/aufs/dcsub.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#ifndef __AUFS_DCSUB_H__
++#define __AUFS_DCSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++
++struct dentry;
++
++struct au_dpage {
++ int ndentry;
++ struct dentry **dentries;
++};
++
++struct au_dcsub_pages {
++ int ndpage;
++ struct au_dpage *dpages;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
++void au_dpages_free(struct au_dcsub_pages *dpages);
++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg);
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++ int do_include, au_dpages_test test, void *arg);
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DCSUB_H__ */
+diff -Naur a/fs/aufs/debug.c b/fs/aufs/debug.c
+--- a/fs/aufs/debug.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,427 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debug print functions
++ */
++
++#include <linux/module.h>
++#include <linux/vt_kern.h>
++#include "aufs.h"
++
++int aufs_debug;
++MODULE_PARM_DESC(debug, "debug print");
++module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
++
++char *au_plevel = KERN_DEBUG;
++#define dpri(fmt, arg...) do { \
++ if (au_debug_test()) \
++ printk("%s" fmt, au_plevel, ##arg); \
++} while (0)
++
++/* ---------------------------------------------------------------------- */
++
++void au_dpri_whlist(struct au_nhash *whlist)
++{
++ unsigned long ul, n;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (ul = 0; ul < n; ul++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ dpri("b%d, %.*s, %d\n",
++ tpos->wh_bindex,
++ tpos->wh_str.len, tpos->wh_str.name,
++ tpos->wh_str.len);
++ head++;
++ }
++}
++
++void au_dpri_vdir(struct au_vdir *vdir)
++{
++ unsigned long ul;
++ union au_vdir_deblk_p p;
++ unsigned char *o;
++
++ if (!vdir || IS_ERR(vdir)) {
++ dpri("err %ld\n", PTR_ERR(vdir));
++ return;
++ }
++
++ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
++ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
++ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
++ for (ul = 0; ul < vdir->vd_nblk; ul++) {
++ p.deblk = vdir->vd_deblk[ul];
++ o = p.deblk;
++ dpri("[%lu]: %p\n", ul, o);
++ }
++}
++
++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
++ struct dentry *wh)
++{
++ char *n = NULL;
++ int l = 0;
++
++ if (!inode || IS_ERR(inode)) {
++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
++ return -1;
++ }
++
++ /* the type of i_blocks depends upon CONFIG_LSF */
++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
++ && sizeof(inode->i_blocks) != sizeof(u64));
++ if (wh) {
++ n = (void *)wh->d_name.name;
++ l = wh->d_name.len;
++ }
++
++ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
++ " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
++ bindex,
++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
++ i_size_read(inode), (unsigned long long)inode->i_blocks,
++ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
++ inode->i_mapping ? inode->i_mapping->nrpages : 0,
++ inode->i_state, inode->i_flags, inode->i_generation,
++ l ? ", wh " : "", l, n);
++ return 0;
++}
++
++void au_dpri_inode(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_inode(-1, inode, NULL);
++ if (err || !au_test_aufs(inode->i_sb))
++ return;
++
++ iinfo = au_ii(inode);
++ if (!iinfo)
++ return;
++ dpri("i-1: bstart %d, bend %d, gen %d\n",
++ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
++ if (iinfo->ii_bstart < 0)
++ return;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
++ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
++ iinfo->ii_hinode[0 + bindex].hi_whdentry);
++}
++
++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
++{
++ struct dentry *wh = NULL;
++
++ if (!dentry || IS_ERR(dentry)) {
++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
++ return -1;
++ }
++ /* do not call dget_parent() here */
++ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
++ bindex,
++ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
++ atomic_read(&dentry->d_count), dentry->d_flags);
++ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
++ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
++ if (iinfo)
++ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
++ }
++ do_pri_inode(bindex, dentry->d_inode, wh);
++ return 0;
++}
++
++void au_dpri_dentry(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_dentry(-1, dentry);
++ if (err || !au_test_aufs(dentry->d_sb))
++ return;
++
++ dinfo = au_di(dentry);
++ if (!dinfo)
++ return;
++ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
++ dinfo->di_bstart, dinfo->di_bend,
++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
++ if (dinfo->di_bstart < 0)
++ return;
++ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
++ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
++}
++
++static int do_pri_file(aufs_bindex_t bindex, struct file *file)
++{
++ char a[32];
++
++ if (!file || IS_ERR(file)) {
++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
++ return -1;
++ }
++ a[0] = 0;
++ if (bindex < 0
++ && file->f_dentry
++ && au_test_aufs(file->f_dentry->d_sb)
++ && au_fi(file))
++ snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
++ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
++ bindex, file->f_mode, file->f_flags, (long)file_count(file),
++ file->f_pos, a);
++ if (file->f_dentry)
++ do_pri_dentry(bindex, file->f_dentry);
++ return 0;
++}
++
++void au_dpri_file(struct file *file)
++{
++ struct au_finfo *finfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_file(-1, file);
++ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
++ return;
++
++ finfo = au_fi(file);
++ if (!finfo)
++ return;
++ if (finfo->fi_bstart < 0)
++ return;
++ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
++ struct au_hfile *hf;
++
++ hf = finfo->fi_hfile + bindex;
++ do_pri_file(bindex, hf ? hf->hf_file : NULL);
++ }
++}
++
++static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
++{
++ struct vfsmount *mnt;
++ struct super_block *sb;
++
++ if (!br || IS_ERR(br))
++ goto out;
++ mnt = br->br_mnt;
++ if (!mnt || IS_ERR(mnt))
++ goto out;
++ sb = mnt->mnt_sb;
++ if (!sb || IS_ERR(sb))
++ goto out;
++
++ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
++ "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
++ "xino %d\n",
++ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
++ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
++ sb->s_flags, sb->s_count - S_BIAS,
++ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
++ return 0;
++
++ out:
++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
++ return -1;
++}
++
++void au_dpri_sb(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ aufs_bindex_t bindex;
++ int err;
++ /* to reuduce stack size */
++ struct {
++ struct vfsmount mnt;
++ struct au_branch fake;
++ } *a;
++
++ /* this function can be called from magic sysrq */
++ a = kzalloc(sizeof(*a), GFP_ATOMIC);
++ if (unlikely(!a)) {
++ dpri("no memory\n");
++ return;
++ }
++
++ a->mnt.mnt_sb = sb;
++ a->fake.br_perm = 0;
++ a->fake.br_mnt = &a->mnt;
++ a->fake.br_xino.xi_file = NULL;
++ atomic_set(&a->fake.br_count, 0);
++ smp_mb(); /* atomic_set */
++ err = do_pri_br(-1, &a->fake);
++ kfree(a);
++ dpri("dev 0x%x\n", sb->s_dev);
++ if (err || !au_test_aufs(sb))
++ return;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++ dpri("nw %d, gen %u, kobj %d\n",
++ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
++ atomic_read(&sbinfo->si_kobj.kref.refcount));
++ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_sleep_jiffy(int jiffy)
++{
++ while (jiffy)
++ jiffy = schedule_timeout_uninterruptible(jiffy);
++}
++
++void au_dbg_iattr(struct iattr *ia)
++{
++#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
++ dpri(#name "\n")
++ AuBit(MODE);
++ AuBit(UID);
++ AuBit(GID);
++ AuBit(SIZE);
++ AuBit(ATIME);
++ AuBit(MTIME);
++ AuBit(CTIME);
++ AuBit(ATIME_SET);
++ AuBit(MTIME_SET);
++ AuBit(FORCE);
++ AuBit(ATTR_FLAG);
++ AuBit(KILL_SUID);
++ AuBit(KILL_SGID);
++ AuBit(FILE);
++ AuBit(KILL_PRIV);
++ AuBit(OPEN);
++ AuBit(TIMES_SET);
++#undef AuBit
++ dpri("ia_file %p\n", ia->ia_file);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
++{
++ struct dentry *parent;
++
++ parent = dget_parent(dentry);
++ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
++ || IS_ROOT(dentry)
++ || au_digen(parent) != sigen);
++ dput(parent);
++}
++
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
++{
++ struct dentry *parent;
++
++ parent = dget_parent(dentry);
++ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
++ || au_digen(parent) != sigen);
++ dput(parent);
++}
++
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++ int err, i, j;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ AuDebugOn(err);
++ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
++ AuDebugOn(err);
++ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
++ AuDebugOn(au_digen(dentries[j]) != sigen);
++ }
++ au_dpages_free(&dpages);
++}
++
++void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++ struct au_hfile *hf;
++ aufs_bindex_t bend, bindex;
++
++ if (finfo->fi_bstart >= 0) {
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
++ hf = finfo->fi_hfile + bindex;
++ AuDebugOn(hf->hf_file || hf->hf_br);
++ }
++ }
++}
++
++void au_dbg_verify_kthread(void)
++{
++ if (au_test_wkq(current)) {
++ au_dbg_blocked();
++ BUG();
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
++{
++#ifdef AuForceNoPlink
++ au_opt_clr(sbinfo->si_mntflags, PLINK);
++#endif
++#ifdef AuForceNoXino
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++#endif
++#ifdef AuForceNoRefrof
++ au_opt_clr(sbinfo->si_mntflags, REFROF);
++#endif
++#ifdef AuForceHinotify
++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
++#endif
++}
++
++int __init au_debug_init(void)
++{
++ aufs_bindex_t bindex;
++ struct au_vdir_destr destr;
++
++ bindex = -1;
++ AuDebugOn(bindex >= 0);
++
++ destr.len = -1;
++ AuDebugOn(destr.len < NAME_MAX);
++
++#ifdef CONFIG_4KSTACKS
++ AuWarn("CONFIG_4KSTACKS is defined.\n");
++#endif
++
++#ifdef AuForceNoBrs
++ sysaufs_brs = 0;
++#endif
++
++ return 0;
++}
+diff -Naur a/fs/aufs/debug.h b/fs/aufs/debug.h
+--- a/fs/aufs/debug.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,260 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debug print functions
++ */
++
++#ifndef __AUFS_DEBUG_H__
++#define __AUFS_DEBUG_H__
++
++#ifdef __KERNEL__
++
++#include <linux/bug.h>
++/* #include <linux/err.h> */
++/* #include <linux/init.h> */
++/* #include <linux/kernel.h> */
++#include <linux/delay.h>
++/* #include <linux/kd.h> */
++/* #include <linux/vt_kern.h> */
++#include <linux/sysrq.h>
++#include <linux/aufs_type.h>
++
++#ifdef CONFIG_AUFS_DEBUG
++#define AuDebugOn(a) BUG_ON(a)
++
++/* module parameter */
++extern int aufs_debug;
++static inline void au_debug(int n)
++{
++ aufs_debug = n;
++ smp_mb();
++}
++
++static inline int au_debug_test(void)
++{
++ return aufs_debug;
++}
++#else
++#define AuDebugOn(a) do {} while (0)
++#define au_debug() do {} while (0)
++static inline int au_debug_test(void)
++{
++ return 0;
++}
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++/* debug print */
++
++#define AuDpri(lvl, fmt, arg...) \
++ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
++ __func__, __LINE__, current->comm, current->pid, ##arg)
++#define AuDbg(fmt, arg...) do { \
++ if (au_debug_test()) \
++ AuDpri(KERN_DEBUG, fmt, ##arg); \
++} while (0)
++#define AuLabel(l) AuDbg(#l "\n")
++#define AuInfo(fmt, arg...) AuDpri(KERN_INFO, fmt, ##arg)
++#define AuWarn(fmt, arg...) AuDpri(KERN_WARNING, fmt, ##arg)
++#define AuErr(fmt, arg...) AuDpri(KERN_ERR, fmt, ##arg)
++#define AuIOErr(fmt, arg...) AuErr("I/O Error, " fmt, ##arg)
++#define AuWarn1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuWarn(fmt, ##arg); \
++} while (0)
++
++#define AuErr1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuErr(fmt, ##arg); \
++} while (0)
++
++#define AuIOErr1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuIOErr(fmt, ##arg); \
++} while (0)
++
++#define AuUnsupportMsg "This operation is not supported." \
++ " Please report this application to aufs-users ML."
++#define AuUnsupport(fmt, args...) do { \
++ AuErr(AuUnsupportMsg "\n" fmt, ##args); \
++ dump_stack(); \
++} while (0)
++
++#define AuTraceErr(e) do { \
++ if (unlikely((e) < 0)) \
++ AuDbg("err %d\n", (int)(e)); \
++} while (0)
++
++#define AuTraceErrPtr(p) do { \
++ if (IS_ERR(p)) \
++ AuDbg("err %ld\n", PTR_ERR(p)); \
++} while (0)
++
++/* dirty macros for debug print, use with "%.*s" and caution */
++#define AuLNPair(qstr) (qstr)->len, (qstr)->name
++#define AuDLNPair(d) AuLNPair(&(d)->d_name)
++
++/* ---------------------------------------------------------------------- */
++
++struct au_sbinfo;
++struct au_finfo;
++struct dentry;
++#ifdef CONFIG_AUFS_DEBUG
++extern char *au_plevel;
++struct au_nhash;
++void au_dpri_whlist(struct au_nhash *whlist);
++struct au_vdir;
++void au_dpri_vdir(struct au_vdir *vdir);
++struct inode;
++void au_dpri_inode(struct inode *inode);
++void au_dpri_dentry(struct dentry *dentry);
++struct file;
++void au_dpri_file(struct file *filp);
++struct super_block;
++void au_dpri_sb(struct super_block *sb);
++
++void au_dbg_sleep_jiffy(int jiffy);
++struct iattr;
++void au_dbg_iattr(struct iattr *ia);
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
++void au_dbg_verify_hf(struct au_finfo *finfo);
++void au_dbg_verify_kthread(void);
++
++int __init au_debug_init(void);
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
++#define AuDbgWhlist(w) do { \
++ AuDbg(#w "\n"); \
++ au_dpri_whlist(w); \
++} while (0)
++
++#define AuDbgVdir(v) do { \
++ AuDbg(#v "\n"); \
++ au_dpri_vdir(v); \
++} while (0)
++
++#define AuDbgInode(i) do { \
++ AuDbg(#i "\n"); \
++ au_dpri_inode(i); \
++} while (0)
++
++#define AuDbgDentry(d) do { \
++ AuDbg(#d "\n"); \
++ au_dpri_dentry(d); \
++} while (0)
++
++#define AuDbgFile(f) do { \
++ AuDbg(#f "\n"); \
++ au_dpri_file(f); \
++} while (0)
++
++#define AuDbgSb(sb) do { \
++ AuDbg(#sb "\n"); \
++ au_dpri_sb(sb); \
++} while (0)
++
++#define AuDbgSleep(sec) do { \
++ AuDbg("sleep %d sec\n", sec); \
++ ssleep(sec); \
++} while (0)
++
++#define AuDbgSleepJiffy(jiffy) do { \
++ AuDbg("sleep %d jiffies\n", jiffy); \
++ au_dbg_sleep_jiffy(jiffy); \
++} while (0)
++
++#define AuDbgIAttr(ia) do { \
++ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
++ au_dbg_iattr(ia); \
++} while (0)
++#else
++static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
++ unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
++ unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_kthread(void)
++{
++ /* empty */
++}
++
++static inline int au_debug_init(void)
++{
++ return 0;
++}
++static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
++{
++ /* empty */
++}
++#define AuDbgWhlist(w) do {} while (0)
++#define AuDbgVdir(v) do {} while (0)
++#define AuDbgInode(i) do {} while (0)
++#define AuDbgDentry(d) do {} while (0)
++#define AuDbgFile(f) do {} while (0)
++#define AuDbgSb(sb) do {} while (0)
++#define AuDbgSleep(sec) do {} while (0)
++#define AuDbgSleepJiffy(jiffy) do {} while (0)
++#define AuDbgIAttr(ia) do {} while (0)
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_MAGIC_SYSRQ
++int __init au_sysrq_init(void);
++void au_sysrq_fin(void);
++
++#ifdef CONFIG_HW_CONSOLE
++#define au_dbg_blocked() do { \
++ WARN_ON(1); \
++ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
++} while (0)
++#else
++#define au_dbg_blocked() do {} while (0)
++#endif
++
++#else
++static inline int au_sysrq_init(void)
++{
++ return 0;
++}
++#define au_sysrq_fin() do {} while (0)
++#define au_dbg_blocked() do {} while (0)
++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DEBUG_H__ */
+diff -Naur a/fs/aufs/dentry.c b/fs/aufs/dentry.c
+--- a/fs/aufs/dentry.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#include <linux/namei.h>
++#include "aufs.h"
++
++static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
++{
++ if (nd) {
++ *h_nd = *nd;
++
++ /*
++ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
++ * due to whiteout and branch permission.
++ */
++ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
++ | LOOKUP_FOLLOW);
++ /* unnecessary? */
++ h_nd->intent.open.file = NULL;
++ } else
++ memset(h_nd, 0, sizeof(*h_nd));
++}
++
++struct au_lkup_one_args {
++ struct dentry **errp;
++ struct qstr *name;
++ struct dentry *h_parent;
++ struct au_branch *br;
++ struct nameidata *nd;
++};
++
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++ struct au_branch *br, struct nameidata *nd)
++{
++ struct dentry *h_dentry;
++ int err;
++ struct nameidata h_nd;
++
++ if (au_test_fs_null_nd(h_parent->d_sb))
++ return vfsub_lookup_one_len(name->name, h_parent, name->len);
++
++ au_h_nd(&h_nd, nd);
++ h_nd.path.dentry = h_parent;
++ h_nd.path.mnt = br->br_mnt;
++
++ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
++ h_dentry = ERR_PTR(err);
++ if (!err) {
++ path_get(&h_nd.path);
++ h_dentry = vfsub_lookup_hash(&h_nd);
++ path_put(&h_nd.path);
++ }
++
++ return h_dentry;
++}
++
++static void au_call_lkup_one(void *args)
++{
++ struct au_lkup_one_args *a = args;
++ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
++}
++
++#define AuLkup_ALLOW_NEG 1
++#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
++#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
++#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
++
++struct au_do_lookup_args {
++ unsigned int flags;
++ mode_t type;
++ struct nameidata *nd;
++};
++
++/*
++ * returns positive/negative dentry, NULL or an error.
++ * NULL means whiteout-ed or not-found.
++ */
++static struct dentry*
++au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
++ aufs_bindex_t bindex, struct qstr *wh_name,
++ struct au_do_lookup_args *args)
++{
++ struct dentry *h_dentry;
++ struct inode *h_inode, *inode;
++ struct qstr *name;
++ struct au_branch *br;
++ int wh_found, opq;
++ unsigned char wh_able;
++ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
++
++ name = &dentry->d_name;
++ wh_found = 0;
++ br = au_sbr(dentry->d_sb, bindex);
++ wh_able = !!au_br_whable(br->br_perm);
++ if (wh_able)
++ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
++ h_dentry = ERR_PTR(wh_found);
++ if (!wh_found)
++ goto real_lookup;
++ if (unlikely(wh_found < 0))
++ goto out;
++
++ /* We found a whiteout */
++ /* au_set_dbend(dentry, bindex); */
++ au_set_dbwh(dentry, bindex);
++ if (!allow_neg)
++ return NULL; /* success */
++
++ real_lookup:
++ h_dentry = au_lkup_one(name, h_parent, br, args->nd);
++ if (IS_ERR(h_dentry))
++ goto out;
++
++ h_inode = h_dentry->d_inode;
++ if (!h_inode) {
++ if (!allow_neg)
++ goto out_neg;
++ } else if (wh_found
++ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
++ goto out_neg;
++
++ if (au_dbend(dentry) <= bindex)
++ au_set_dbend(dentry, bindex);
++ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++ au_set_dbstart(dentry, bindex);
++ au_set_h_dptr(dentry, bindex, h_dentry);
++
++ inode = dentry->d_inode;
++ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
++ || (inode && !S_ISDIR(inode->i_mode)))
++ goto out; /* success */
++
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ opq = au_diropq_test(h_dentry, br);
++ mutex_unlock(&h_inode->i_mutex);
++ if (opq > 0)
++ au_set_dbdiropq(dentry, bindex);
++ else if (unlikely(opq < 0)) {
++ au_set_h_dptr(dentry, bindex, NULL);
++ h_dentry = ERR_PTR(opq);
++ }
++ goto out;
++
++ out_neg:
++ dput(h_dentry);
++ h_dentry = NULL;
++ out:
++ return h_dentry;
++}
++
++static int au_test_shwh(struct super_block *sb, const struct qstr *name)
++{
++ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
++ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ return -EPERM;
++ return 0;
++}
++
++/*
++ * returns the number of lower positive dentries,
++ * otherwise an error.
++ * can be called at unlinking with @type is zero.
++ */
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++ struct nameidata *nd)
++{
++ int npositive, err;
++ aufs_bindex_t bindex, btail, bdiropq;
++ unsigned char isdir;
++ struct qstr whname;
++ struct au_do_lookup_args args = {
++ .flags = 0,
++ .type = type,
++ .nd = nd
++ };
++ const struct qstr *name = &dentry->d_name;
++ struct dentry *parent;
++ struct inode *inode;
++
++ parent = dget_parent(dentry);
++ err = au_test_shwh(dentry->d_sb, name);
++ if (unlikely(err))
++ goto out;
++
++ err = au_wh_name_alloc(&whname, name);
++ if (unlikely(err))
++ goto out;
++
++ inode = dentry->d_inode;
++ isdir = !!(inode && S_ISDIR(inode->i_mode));
++ if (!type)
++ au_fset_lkup(args.flags, ALLOW_NEG);
++
++ npositive = 0;
++ btail = au_dbtaildir(parent);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ struct dentry *h_parent, *h_dentry;
++ struct inode *h_inode, *h_dir;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry) {
++ if (h_dentry->d_inode)
++ npositive++;
++ if (type != S_IFDIR)
++ break;
++ continue;
++ }
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent)
++ continue;
++ h_dir = h_parent->d_inode;
++ if (!h_dir || !S_ISDIR(h_dir->i_mode))
++ continue;
++
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
++ &args);
++ mutex_unlock(&h_dir->i_mutex);
++ err = PTR_ERR(h_dentry);
++ if (IS_ERR(h_dentry))
++ goto out_wh;
++ au_fclr_lkup(args.flags, ALLOW_NEG);
++
++ if (au_dbwh(dentry) >= 0)
++ break;
++ if (!h_dentry)
++ continue;
++ h_inode = h_dentry->d_inode;
++ if (!h_inode)
++ continue;
++ npositive++;
++ if (!args.type)
++ args.type = h_inode->i_mode & S_IFMT;
++ if (args.type != S_IFDIR)
++ break;
++ else if (isdir) {
++ /* the type of lower may be different */
++ bdiropq = au_dbdiropq(dentry);
++ if (bdiropq >= 0 && bdiropq <= bindex)
++ break;
++ }
++ }
++
++ if (npositive) {
++ AuLabel(positive);
++ au_update_dbstart(dentry);
++ }
++ err = npositive;
++ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++ && au_dbstart(dentry) < 0))
++ /* both of real entry and whiteout found */
++ err = -EIO;
++
++ out_wh:
++ kfree(whname.name);
++ out:
++ dput(parent);
++ return err;
++}
++
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++ struct au_branch *br)
++{
++ struct dentry *dentry;
++ int wkq_err;
++
++ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
++ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
++ else {
++ struct au_lkup_one_args args = {
++ .errp = &dentry,
++ .name = name,
++ .h_parent = parent,
++ .br = br,
++ .nd = NULL
++ };
++
++ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
++ if (unlikely(wkq_err))
++ dentry = ERR_PTR(wkq_err);
++ }
++
++ return dentry;
++}
++
++/*
++ * lookup @dentry on @bindex which should be negative.
++ */
++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct dentry *parent, *h_parent, *h_dentry;
++ struct qstr *name;
++
++ name = &dentry->d_name;
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bindex);
++ h_dentry = au_sio_lkup_one(name, h_parent,
++ au_sbr(dentry->d_sb, bindex));
++ err = PTR_ERR(h_dentry);
++ if (IS_ERR(h_dentry))
++ goto out;
++ if (unlikely(h_dentry->d_inode)) {
++ err = -EIO;
++ AuIOErr("b%d %.*s should be negative.\n",
++ bindex, AuDLNPair(h_dentry));
++ dput(h_dentry);
++ goto out;
++ }
++
++ if (bindex < au_dbstart(dentry))
++ au_set_dbstart(dentry, bindex);
++ if (au_dbend(dentry) < bindex)
++ au_set_dbend(dentry, bindex);
++ au_set_h_dptr(dentry, bindex, h_dentry);
++ err = 0;
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* subset of struct inode */
++struct au_iattr {
++ unsigned long i_ino;
++ /* unsigned int i_nlink; */
++ uid_t i_uid;
++ gid_t i_gid;
++ u64 i_version;
++/*
++ loff_t i_size;
++ blkcnt_t i_blocks;
++*/
++ umode_t i_mode;
++};
++
++static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
++{
++ ia->i_ino = h_inode->i_ino;
++ /* ia->i_nlink = h_inode->i_nlink; */
++ ia->i_uid = h_inode->i_uid;
++ ia->i_gid = h_inode->i_gid;
++ ia->i_version = h_inode->i_version;
++/*
++ ia->i_size = h_inode->i_size;
++ ia->i_blocks = h_inode->i_blocks;
++*/
++ ia->i_mode = (h_inode->i_mode & S_IFMT);
++}
++
++static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
++{
++ return ia->i_ino != h_inode->i_ino
++ /* || ia->i_nlink != h_inode->i_nlink */
++ || ia->i_uid != h_inode->i_uid
++ || ia->i_gid != h_inode->i_gid
++ || ia->i_version != h_inode->i_version
++/*
++ || ia->i_size != h_inode->i_size
++ || ia->i_blocks != h_inode->i_blocks
++*/
++ || ia->i_mode != (h_inode->i_mode & S_IFMT);
++}
++
++static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
++ struct au_branch *br)
++{
++ int err;
++ struct au_iattr ia;
++ struct inode *h_inode;
++ struct dentry *h_d;
++ struct super_block *h_sb;
++
++ err = 0;
++ memset(&ia, -1, sizeof(ia));
++ h_sb = h_dentry->d_sb;
++ h_inode = h_dentry->d_inode;
++ if (h_inode)
++ au_iattr_save(&ia, h_inode);
++ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
++ /* nfs d_revalidate may return 0 for negative dentry */
++ /* fuse d_revalidate always return 0 for negative dentry */
++ goto out;
++
++ /* main purpose is namei.c:cached_lookup() and d_revalidate */
++ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
++ err = PTR_ERR(h_d);
++ if (IS_ERR(h_d))
++ goto out;
++
++ err = 0;
++ if (unlikely(h_d != h_dentry
++ || h_d->d_inode != h_inode
++ || (h_inode && au_iattr_test(&ia, h_inode))))
++ err = au_busy_or_stale();
++ dput(h_d);
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++ struct dentry *h_parent, struct au_branch *br)
++{
++ int err;
++
++ err = 0;
++ if (udba == AuOpt_UDBA_REVAL) {
++ IMustLock(h_dir);
++ err = (h_dentry->d_parent->d_inode != h_dir);
++ } else if (udba == AuOpt_UDBA_HINOTIFY)
++ err = au_h_verify_dentry(h_dentry, h_parent, br);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
++ struct dentry *parent)
++{
++ struct dentry *h_d, *h_dp;
++ struct au_hdentry tmp, *q;
++ struct super_block *sb;
++ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
++
++ bend = dinfo->di_bend;
++ bwh = dinfo->di_bwh;
++ bdiropq = dinfo->di_bdiropq;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
++ h_d = p->hd_dentry;
++ if (!h_d)
++ continue;
++
++ h_dp = dget_parent(h_d);
++ if (h_dp == au_h_dptr(parent, bindex)) {
++ dput(h_dp);
++ continue;
++ }
++
++ new_bindex = au_find_dbindex(parent, h_dp);
++ dput(h_dp);
++ if (dinfo->di_bwh == bindex)
++ bwh = new_bindex;
++ if (dinfo->di_bdiropq == bindex)
++ bdiropq = new_bindex;
++ if (new_bindex < 0) {
++ au_hdput(p);
++ p->hd_dentry = NULL;
++ continue;
++ }
++
++ /* swap two lower dentries, and loop again */
++ q = dinfo->di_hdentry + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hd_dentry) {
++ bindex--;
++ p--;
++ }
++ }
++
++ sb = parent->d_sb;
++ dinfo->di_bwh = -1;
++ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
++ dinfo->di_bwh = bwh;
++
++ dinfo->di_bdiropq = -1;
++ if (bdiropq >= 0
++ && bdiropq <= au_sbend(sb)
++ && au_sbr_whable(sb, bdiropq))
++ dinfo->di_bdiropq = bdiropq;
++
++ bend = au_dbend(parent);
++ p = dinfo->di_hdentry;
++ for (bindex = 0; bindex <= bend; bindex++, p++)
++ if (p->hd_dentry) {
++ dinfo->di_bstart = bindex;
++ break;
++ }
++
++ p = dinfo->di_hdentry + bend;
++ for (bindex = bend; bindex >= 0; bindex--, p--)
++ if (p->hd_dentry) {
++ dinfo->di_bend = bindex;
++ break;
++ }
++}
++
++/*
++ * returns the number of found lower positive dentries,
++ * otherwise an error.
++ */
++int au_refresh_hdentry(struct dentry *dentry, mode_t type)
++{
++ int npositive, err;
++ unsigned int sigen;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct super_block *sb;
++ struct dentry *parent;
++
++ sb = dentry->d_sb;
++ AuDebugOn(IS_ROOT(dentry));
++ sigen = au_sigen(sb);
++ parent = dget_parent(dentry);
++ AuDebugOn(au_digen(parent) != sigen
++ || au_iigen(parent->d_inode) != sigen);
++
++ dinfo = au_di(dentry);
++ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
++ npositive = err;
++ if (unlikely(err))
++ goto out;
++ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
++ parent);
++
++ npositive = 0;
++ bstart = au_dbstart(parent);
++ if (type != S_IFDIR && dinfo->di_bstart == bstart)
++ goto out_dgen; /* success */
++
++ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
++ if (npositive < 0)
++ goto out;
++ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
++ d_drop(dentry);
++
++ out_dgen:
++ au_update_digen(dentry);
++ out:
++ dput(parent);
++ AuTraceErr(npositive);
++ return npositive;
++}
++
++static noinline_for_stack
++int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
++ struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err, valid;
++ int (*reval)(struct dentry *, struct nameidata *);
++
++ err = 0;
++ reval = NULL;
++ if (h_dentry->d_op)
++ reval = h_dentry->d_op->d_revalidate;
++ if (!reval)
++ goto out;
++
++ AuDbg("b%d\n", bindex);
++ if (au_test_fs_null_nd(h_dentry->d_sb))
++ /* it may return tri-state */
++ valid = reval(h_dentry, NULL);
++ else {
++ struct nameidata h_nd;
++ int locked;
++ struct dentry *parent;
++
++ au_h_nd(&h_nd, nd);
++ parent = nd->path.dentry;
++ locked = (nd && nd->path.dentry != dentry);
++ if (locked)
++ di_read_lock_parent(parent, AuLock_IR);
++ BUG_ON(bindex > au_dbend(parent));
++ h_nd.path.dentry = au_h_dptr(parent, bindex);
++ BUG_ON(!h_nd.path.dentry);
++ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
++ path_get(&h_nd.path);
++ valid = reval(h_dentry, &h_nd);
++ path_put(&h_nd.path);
++ if (locked)
++ di_read_unlock(parent, AuLock_IR);
++ }
++
++ if (unlikely(valid < 0))
++ err = valid;
++ else if (!valid)
++ err = -EINVAL;
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++/* todo: remove this */
++static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
++ struct nameidata *nd, int do_udba)
++{
++ int err;
++ umode_t mode, h_mode;
++ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
++ unsigned char plus, unhashed, is_root, h_plus;
++ struct inode *first, *h_inode, *h_cached_inode;
++ struct dentry *h_dentry;
++ struct qstr *name, *h_name;
++
++ err = 0;
++ plus = 0;
++ mode = 0;
++ first = NULL;
++ ibs = -1;
++ ibe = -1;
++ unhashed = !!d_unhashed(dentry);
++ is_root = !!IS_ROOT(dentry);
++ name = &dentry->d_name;
++
++ /*
++ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
++ * But inotify doesn't fire some necessary events,
++ * IN_ATTRIB for atime/nlink/pageio
++ * IN_DELETE for NFS dentry
++ * Let's do REVAL test too.
++ */
++ if (do_udba && inode) {
++ mode = (inode->i_mode & S_IFMT);
++ plus = (inode->i_nlink > 0);
++ first = au_h_iptr(inode, au_ibstart(inode));
++ ibs = au_ibstart(inode);
++ ibe = au_ibend(inode);
++ }
++
++ bstart = au_dbstart(dentry);
++ btail = bstart;
++ if (inode && S_ISDIR(inode->i_mode))
++ btail = au_dbtaildir(dentry);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++
++ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
++ h_name = &h_dentry->d_name;
++ if (unlikely(do_udba
++ && !is_root
++ && (unhashed != !!d_unhashed(h_dentry)
++ || name->len != h_name->len
++ || memcmp(name->name, h_name->name, name->len))
++ )) {
++ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
++ unhashed, d_unhashed(h_dentry),
++ AuDLNPair(dentry), AuDLNPair(h_dentry));
++ goto err;
++ }
++
++ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
++ if (unlikely(err))
++ /* do not goto err, to keep the errno */
++ break;
++
++ /* todo: plink too? */
++ if (!do_udba)
++ continue;
++
++ /* UDBA tests */
++ h_inode = h_dentry->d_inode;
++ if (unlikely(!!inode != !!h_inode))
++ goto err;
++
++ h_plus = plus;
++ h_mode = mode;
++ h_cached_inode = h_inode;
++ if (h_inode) {
++ h_mode = (h_inode->i_mode & S_IFMT);
++ h_plus = (h_inode->i_nlink > 0);
++ }
++ if (inode && ibs <= bindex && bindex <= ibe)
++ h_cached_inode = au_h_iptr(inode, bindex);
++
++ if (unlikely(plus != h_plus
++ || mode != h_mode
++ || h_cached_inode != h_inode))
++ goto err;
++ continue;
++
++ err:
++ err = -EINVAL;
++ break;
++ }
++
++ return err;
++}
++
++static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++ return 0;
++
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++ AuDebugOn(au_digen(parent) != sigen
++ || au_iigen(parent->d_inode) != sigen);
++ au_dbg_verify_gen(parent, sigen);
++
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, dentry);
++
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ return err;
++}
++
++int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct dentry *d, *parent;
++ struct inode *inode;
++
++ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
++ return simple_reval_dpath(dentry, sigen);
++
++ /* slow loop, keep it simple and stupid */
++ /* cf: au_cpup_dirs() */
++ err = 0;
++ parent = NULL;
++ while (au_digen(dentry) != sigen
++ || au_iigen(dentry->d_inode) != sigen) {
++ d = dentry;
++ while (1) {
++ dput(parent);
++ parent = dget_parent(d);
++ if (au_digen(parent) == sigen
++ && au_iigen(parent->d_inode) == sigen)
++ break;
++ d = parent;
++ }
++
++ inode = d->d_inode;
++ if (d != dentry)
++ di_write_lock_child(d);
++
++ /* someone might update our dentry while we were sleeping */
++ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
++ di_read_lock_parent(parent, AuLock_IR);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, d);
++ di_read_unlock(parent, AuLock_IR);
++ }
++
++ if (d != dentry)
++ di_write_unlock(d);
++ dput(parent);
++ if (unlikely(err))
++ break;
++ }
++
++ return err;
++}
++
++/*
++ * if valid returns 1, otherwise 0.
++ */
++static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
++{
++ int valid, err;
++ unsigned int sigen;
++ unsigned char do_udba;
++ struct super_block *sb;
++ struct inode *inode;
++
++ err = -EINVAL;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
++ sigen = au_sigen(sb);
++ if (au_digen(dentry) != sigen) {
++ AuDebugOn(IS_ROOT(dentry));
++ if (inode)
++ err = au_reval_dpath(dentry, sigen);
++ if (unlikely(err))
++ goto out_dgrade;
++ AuDebugOn(au_digen(dentry) != sigen);
++ }
++ if (inode && au_iigen(inode) != sigen) {
++ AuDebugOn(IS_ROOT(dentry));
++ err = au_refresh_hinode(inode, dentry);
++ if (unlikely(err))
++ goto out_dgrade;
++ AuDebugOn(au_iigen(inode) != sigen);
++ }
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ AuDebugOn(au_digen(dentry) != sigen);
++ AuDebugOn(inode && au_iigen(inode) != sigen);
++ err = -EINVAL;
++ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
++ if (do_udba && inode) {
++ aufs_bindex_t bstart = au_ibstart(inode);
++
++ if (bstart >= 0
++ && au_test_higen(inode, au_h_iptr(inode, bstart)))
++ goto out;
++ }
++
++ err = h_d_revalidate(dentry, inode, nd, do_udba);
++ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
++ /* both of real entry and whiteout found */
++ err = -EIO;
++ goto out;
++
++ out_dgrade:
++ di_downgrade_lock(dentry, AuLock_IR);
++ out:
++ au_store_oflag(nd, inode);
++ aufs_read_unlock(dentry, AuLock_IR);
++ AuTraceErr(err);
++ valid = !err;
++ if (!valid)
++ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
++ return valid;
++}
++
++static void aufs_d_release(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ aufs_bindex_t bend, bindex;
++
++ dinfo = dentry->d_fsdata;
++ if (!dinfo)
++ return;
++
++ /* dentry may not be revalidated */
++ bindex = dinfo->di_bstart;
++ if (bindex >= 0) {
++ struct au_hdentry *p;
++
++ bend = dinfo->di_bend;
++ p = dinfo->di_hdentry + bindex;
++ while (bindex++ <= bend) {
++ if (p->hd_dentry)
++ au_hdput(p);
++ p++;
++ }
++ }
++ kfree(dinfo->di_hdentry);
++ au_rwsem_destroy(&dinfo->di_rwsem);
++ au_cache_free_dinfo(dinfo);
++ au_hin_di_reinit(dentry);
++}
++
++struct dentry_operations aufs_dop = {
++ .d_revalidate = aufs_d_revalidate,
++ .d_release = aufs_d_release
++};
+diff -Naur a/fs/aufs/dentry.h b/fs/aufs/dentry.h
+--- a/fs/aufs/dentry.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,221 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#ifndef __AUFS_DENTRY_H__
++#define __AUFS_DENTRY_H__
++
++#ifdef __KERNEL__
++
++#include <linux/dcache.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++/* make a single member structure for future use */
++/* todo: remove this structure */
++struct au_hdentry {
++ struct dentry *hd_dentry;
++};
++
++struct au_dinfo {
++ atomic_t di_generation;
++
++ struct rw_semaphore di_rwsem;
++ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
++ struct au_hdentry *di_hdentry;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry.c */
++extern struct dentry_operations aufs_dop;
++struct au_branch;
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++ struct au_branch *br, struct nameidata *nd);
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++ struct au_branch *br);
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++ struct dentry *h_parent, struct au_branch *br);
++
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++ struct nameidata *nd);
++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
++int au_refresh_hdentry(struct dentry *dentry, mode_t type);
++int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
++
++/* dinfo.c */
++int au_alloc_dinfo(struct dentry *dentry);
++int au_di_realloc(struct au_dinfo *dinfo, int nbr);
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
++void di_read_unlock(struct dentry *d, int flags);
++void di_downgrade_lock(struct dentry *d, int flags);
++void di_write_lock(struct dentry *d, unsigned int lsc);
++void di_write_unlock(struct dentry *d);
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
++aufs_bindex_t au_dbtail(struct dentry *dentry);
++aufs_bindex_t au_dbtaildir(struct dentry *dentry);
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++void au_update_digen(struct dentry *dentry);
++void au_update_dbrange(struct dentry *dentry, int do_put_zero);
++void au_update_dbstart(struct dentry *dentry);
++void au_update_dbend(struct dentry *dentry);
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_dinfo *au_di(struct dentry *dentry)
++{
++ return dentry->d_fsdata;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for dinfo */
++enum {
++ AuLsc_DI_CHILD, /* child first */
++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_DI_CHILD3, /* copyup dirs */
++ AuLsc_DI_PARENT,
++ AuLsc_DI_PARENT2,
++ AuLsc_DI_PARENT3
++};
++
++/*
++ * di_read_lock_child, di_write_lock_child,
++ * di_read_lock_child2, di_write_lock_child2,
++ * di_read_lock_child3, di_write_lock_child3,
++ * di_read_lock_parent, di_write_lock_parent,
++ * di_read_lock_parent2, di_write_lock_parent2,
++ * di_read_lock_parent3, di_write_lock_parent3,
++ */
++#define AuReadLockFunc(name, lsc) \
++static inline void di_read_lock_##name(struct dentry *d, int flags) \
++{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void di_write_lock_##name(struct dentry *d) \
++{ di_write_lock(d, AuLsc_DI_##lsc); }
++
++#define AuRWLockFuncs(name, lsc) \
++ AuReadLockFunc(name, lsc) \
++ AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: memory barrier? */
++static inline unsigned int au_digen(struct dentry *d)
++{
++ return atomic_read(&au_di(d)->di_generation);
++}
++
++static inline void au_h_dentry_init(struct au_hdentry *hdentry)
++{
++ hdentry->hd_dentry = NULL;
++}
++
++static inline void au_hdput(struct au_hdentry *hd)
++{
++ dput(hd->hd_dentry);
++}
++
++static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bstart;
++}
++
++static inline aufs_bindex_t au_dbend(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bend;
++}
++
++static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bwh;
++}
++
++static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bdiropq;
++}
++
++/* todo: hard/soft set? */
++static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bstart = bindex;
++}
++
++static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bend = bindex;
++}
++
++static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ /* dbwh can be outside of bstart - bend range */
++ au_di(dentry)->di_bwh = bindex;
++}
++
++static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bdiropq = bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_digen_dec(struct dentry *d)
++{
++ atomic_dec(&au_di(d)->di_generation);
++}
++
++static inline void au_hin_di_reinit(struct dentry *dentry)
++{
++ dentry->d_fsdata = NULL;
++}
++#else
++static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
++{
++ /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DENTRY_H__ */
+diff -Naur a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
+--- a/fs/aufs/dinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,360 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * dentry private data
++ */
++
++#include "aufs.h"
++
++int au_alloc_dinfo(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ struct super_block *sb;
++ int nbr;
++
++ dinfo = au_cache_alloc_dinfo();
++ if (unlikely(!dinfo))
++ goto out;
++
++ sb = dentry->d_sb;
++ nbr = au_sbend(sb) + 1;
++ if (nbr <= 0)
++ nbr = 1;
++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
++ if (unlikely(!dinfo->di_hdentry))
++ goto out_dinfo;
++
++ atomic_set(&dinfo->di_generation, au_sigen(sb));
++ /* smp_mb(); */ /* atomic_set */
++ init_rwsem(&dinfo->di_rwsem);
++ down_write_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
++ dinfo->di_bstart = -1;
++ dinfo->di_bend = -1;
++ dinfo->di_bwh = -1;
++ dinfo->di_bdiropq = -1;
++
++ dentry->d_fsdata = dinfo;
++ dentry->d_op = &aufs_dop;
++ return 0; /* success */
++
++ out_dinfo:
++ au_cache_free_dinfo(dinfo);
++ out:
++ return -ENOMEM;
++}
++
++int au_di_realloc(struct au_dinfo *dinfo, int nbr)
++{
++ int err, sz;
++ struct au_hdentry *hdp;
++
++ err = -ENOMEM;
++ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
++ if (!sz)
++ sz = sizeof(*hdp);
++ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
++ if (hdp) {
++ dinfo->di_hdentry = hdp;
++ err = 0;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_write_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_write_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_write_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_write_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_write_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_write_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_read_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_read_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_read_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_read_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_read_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_read_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
++{
++ down_read_nested(&au_di(d)->di_rwsem, lsc);
++ if (d->d_inode) {
++ if (au_ftest_lock(flags, IW))
++ do_ii_write_lock(d->d_inode, lsc);
++ else if (au_ftest_lock(flags, IR))
++ do_ii_read_lock(d->d_inode, lsc);
++ }
++}
++
++void di_read_unlock(struct dentry *d, int flags)
++{
++ if (d->d_inode) {
++ if (au_ftest_lock(flags, IW))
++ ii_write_unlock(d->d_inode);
++ else if (au_ftest_lock(flags, IR))
++ ii_read_unlock(d->d_inode);
++ }
++ up_read(&au_di(d)->di_rwsem);
++}
++
++void di_downgrade_lock(struct dentry *d, int flags)
++{
++ downgrade_write(&au_di(d)->di_rwsem);
++ if (d->d_inode && au_ftest_lock(flags, IR))
++ ii_downgrade_lock(d->d_inode);
++}
++
++void di_write_lock(struct dentry *d, unsigned int lsc)
++{
++ down_write_nested(&au_di(d)->di_rwsem, lsc);
++ if (d->d_inode)
++ do_ii_write_lock(d->d_inode, lsc);
++}
++
++void di_write_unlock(struct dentry *d)
++{
++ if (d->d_inode)
++ ii_write_unlock(d->d_inode);
++ up_write(&au_di(d)->di_rwsem);
++}
++
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ AuDebugOn(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir && au_test_subdir(d1, d2)) {
++ di_write_lock_child(d1);
++ di_write_lock_child2(d2);
++ } else {
++ /* there should be no races */
++ di_write_lock_child(d2);
++ di_write_lock_child2(d1);
++ }
++}
++
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ AuDebugOn(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir && au_test_subdir(d1, d2)) {
++ di_write_lock_parent(d1);
++ di_write_lock_parent2(d2);
++ } else {
++ /* there should be no races */
++ di_write_lock_parent(d2);
++ di_write_lock_parent2(d1);
++ }
++}
++
++void di_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock(d1);
++ if (d1->d_inode == d2->d_inode)
++ up_write(&au_di(d2)->di_rwsem);
++ else
++ di_write_unlock(d2);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ struct dentry *d;
++
++ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++ return NULL;
++ AuDebugOn(bindex < 0);
++ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
++ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
++ return d;
++}
++
++aufs_bindex_t au_dbtail(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bwh;
++
++ bend = au_dbend(dentry);
++ if (0 <= bend) {
++ bwh = au_dbwh(dentry);
++ if (!bwh)
++ return bwh;
++ if (0 < bwh && bwh < bend)
++ return bwh - 1;
++ }
++ return bend;
++}
++
++aufs_bindex_t au_dbtaildir(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bopq;
++
++ bend = au_dbtail(dentry);
++ if (0 <= bend) {
++ bopq = au_dbdiropq(dentry);
++ if (0 <= bopq && bopq < bend)
++ bend = bopq;
++ }
++ return bend;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
++
++ if (hd->hd_dentry)
++ au_hdput(hd);
++ hd->hd_dentry = h_dentry;
++}
++
++void au_update_digen(struct dentry *dentry)
++{
++ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++void au_update_dbrange(struct dentry *dentry, int do_put_zero)
++{
++ struct au_dinfo *dinfo;
++ struct dentry *h_d;
++
++ dinfo = au_di(dentry);
++ if (!dinfo || dinfo->di_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex, bend;
++
++ bend = dinfo->di_bend;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
++ h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
++ if (h_d && !h_d->d_inode)
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++ }
++
++ dinfo->di_bstart = -1;
++ while (++dinfo->di_bstart <= dinfo->di_bend)
++ if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
++ break;
++ if (dinfo->di_bstart > dinfo->di_bend) {
++ dinfo->di_bstart = -1;
++ dinfo->di_bend = -1;
++ return;
++ }
++
++ dinfo->di_bend++;
++ while (0 <= --dinfo->di_bend)
++ if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
++ break;
++ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
++}
++
++void au_update_dbstart(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bend;
++ struct dentry *h_dentry;
++
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ if (h_dentry->d_inode) {
++ au_set_dbstart(dentry, bindex);
++ return;
++ }
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++}
++
++void au_update_dbend(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bstart;
++ struct dentry *h_dentry;
++
++ bstart = au_dbstart(dentry);
++ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ if (h_dentry->d_inode) {
++ au_set_dbend(dentry, bindex);
++ return;
++ }
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++}
++
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
++ if (au_h_dptr(dentry, bindex) == h_dentry)
++ return bindex;
++ return -1;
++}
+diff -Naur a/fs/aufs/dir.c b/fs/aufs/dir.c
+--- a/fs/aufs/dir.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,532 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * directory operations
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include "aufs.h"
++
++void au_add_nlink(struct inode *dir, struct inode *h_dir)
++{
++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++ dir->i_nlink += h_dir->i_nlink - 2;
++ if (h_dir->i_nlink < 2)
++ dir->i_nlink += 2;
++}
++
++void au_sub_nlink(struct inode *dir, struct inode *h_dir)
++{
++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++ dir->i_nlink -= h_dir->i_nlink - 2;
++ if (h_dir->i_nlink < 2)
++ dir->i_nlink -= 2;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int reopen_dir(struct file *file)
++{
++ int err;
++ unsigned int flags;
++ aufs_bindex_t bindex, btail, bstart;
++ struct dentry *dentry, *h_dentry;
++ struct file *h_file;
++
++ /* open all lower dirs */
++ dentry = file->f_dentry;
++ bstart = au_dbstart(dentry);
++ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbstart(file, bstart);
++
++ btail = au_dbtaildir(dentry);
++ for (bindex = au_fbend(file); btail < bindex; bindex--)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbend(file, btail);
++
++ flags = file->f_flags;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ h_file = au_h_fptr(file, bindex);
++ if (h_file)
++ continue;
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out; /* close all? */
++ au_set_h_fptr(file, bindex, h_file);
++ }
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ err = 0;
++
++ out:
++ return err;
++}
++
++static int do_open_dir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex, btail;
++ struct dentry *dentry, *h_dentry;
++ struct file *h_file;
++
++ err = 0;
++ dentry = file->f_dentry;
++ au_set_fvdir_cache(file, NULL);
++ au_fi(file)->fi_maintain_plink = 0;
++ file->f_version = dentry->d_inode->i_version;
++ bindex = au_dbstart(dentry);
++ au_set_fbstart(file, bindex);
++ btail = au_dbtaildir(dentry);
++ au_set_fbend(file, btail);
++ for (; !err && bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ if (IS_ERR(h_file)) {
++ err = PTR_ERR(h_file);
++ break;
++ }
++ au_set_h_fptr(file, bindex, h_file);
++ }
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ if (!err)
++ return 0; /* success */
++
++ /* close all */
++ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbstart(file, -1);
++ au_set_fbend(file, -1);
++ return err;
++}
++
++static int aufs_open_dir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ return au_do_open(file, do_open_dir);
++}
++
++static int aufs_release_dir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ struct au_vdir *vdir_cache;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ sb = file->f_dentry->d_sb;
++ si_noflush_read_lock(sb);
++ fi_write_lock(file);
++ vdir_cache = au_fvdir_cache(file);
++ if (vdir_cache)
++ au_vdir_free(vdir_cache);
++ if (au_fi(file)->fi_maintain_plink) {
++ sbinfo = au_sbi(sb);
++ au_fclr_si(sbinfo, MAINTAIN_PLINK);
++ wake_up_all(&sbinfo->si_plink_wq);
++ }
++ fi_write_unlock(file);
++ au_finfo_fin(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct inode *inode;
++ struct super_block *sb;
++
++ err = 0;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
++ struct path h_path;
++ struct inode *h_inode;
++
++ if (au_test_ro(sb, bindex, inode))
++ continue;
++ h_path.dentry = au_h_dptr(dentry, bindex);
++ if (!h_path.dentry)
++ continue;
++ h_inode = h_path.dentry->d_inode;
++ if (!h_inode)
++ continue;
++
++ /* no mnt_want_write() */
++ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
++ /* todo: inotiry fired? */
++ h_path.mnt = au_sbr_mnt(sb, bindex);
++ mutex_lock(&h_inode->i_mutex);
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ AuDebugOn(!h_inode->i_fop);
++ if (!err && h_inode->i_fop->fsync)
++ err = h_inode->i_fop->fsync(NULL, h_path.dentry,
++ datasync);
++ if (!err)
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ if (!err)
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++ mutex_unlock(&h_inode->i_mutex);
++ }
++
++ return err;
++}
++
++static int au_do_fsync_dir(struct file *file, int datasync)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct file *h_file;
++ struct super_block *sb;
++ struct inode *inode;
++ struct mutex *h_mtx;
++
++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ sb = file->f_dentry->d_sb;
++ inode = file->f_dentry->d_inode;
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++ h_file = au_h_fptr(file, bindex);
++ if (!h_file || au_test_ro(sb, bindex, inode))
++ continue;
++
++ err = vfs_fsync(h_file, h_file->f_dentry, datasync);
++ if (!err) {
++ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
++ mutex_lock(h_mtx);
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ mutex_unlock(h_mtx);
++ }
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * @file may be NULL
++ */
++static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct super_block *sb;
++
++ IMustLock(dentry->d_inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ si_noflush_read_lock(sb);
++ if (file)
++ err = au_do_fsync_dir(file, datasync);
++ else {
++ di_write_lock_child(dentry);
++ err = au_do_fsync_dir_no_file(dentry, datasync);
++ }
++ au_cpup_attr_timesizes(dentry->d_inode);
++ di_write_unlock(dentry);
++ if (file)
++ fi_write_unlock(file);
++
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++ err = au_vdir_init(file);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ if (!au_test_nfsd(current)) {
++ err = au_vdir_fill_de(file, dirent, filldir);
++ fsstack_copy_attr_atime(inode,
++ au_h_iptr(inode, au_ibstart(inode)));
++ } else {
++ /*
++ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
++ * encode_fh() and others.
++ */
++ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
++
++ di_read_unlock(dentry, AuLock_IR);
++ si_read_unlock(sb);
++ lockdep_off();
++ err = au_vdir_fill_de(file, dirent, filldir);
++ lockdep_on();
++ fsstack_copy_attr_atime(inode, h_inode);
++ fi_write_unlock(file);
++
++ AuTraceErr(err);
++ return err;
++ }
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuTestEmpty_WHONLY 1
++#define AuTestEmpty_CALLED (1 << 1)
++#define AuTestEmpty_SHWH (1 << 2)
++#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
++#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
++#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuTestEmpty_SHWH
++#define AuTestEmpty_SHWH 0
++#endif
++
++struct test_empty_arg {
++ struct au_nhash whlist;
++ unsigned int flags;
++ int err;
++ aufs_bindex_t bindex;
++};
++
++static int test_empty_cb(void *__arg, const char *__name, int namelen,
++ loff_t offset __maybe_unused, u64 ino,
++ unsigned int d_type)
++{
++ struct test_empty_arg *arg = __arg;
++ char *name = (void *)__name;
++
++ arg->err = 0;
++ au_fset_testempty(arg->flags, CALLED);
++ /* smp_mb(); */
++ if (name[0] == '.'
++ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
++ goto out; /* success */
++
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (au_ftest_testempty(arg->flags, WHONLY)
++ && !au_nhash_test_known_wh(&arg->whlist, name, namelen))
++ arg->err = -ENOTEMPTY;
++ goto out;
++ }
++
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ if (!au_nhash_test_known_wh(&arg->whlist, name, namelen))
++ arg->err = au_nhash_append_wh
++ (&arg->whlist, name, namelen, ino, d_type, arg->bindex,
++ au_ftest_testempty(arg->flags, SHWH));
++
++ out:
++ /* smp_mb(); */
++ AuTraceErr(arg->err);
++ return arg->err;
++}
++
++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err;
++ struct file *h_file;
++
++ h_file = au_h_open(dentry, arg->bindex,
++ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
++ /*file*/NULL);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out;
++
++ err = 0;
++ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++ && !h_file->f_dentry->d_inode->i_nlink)
++ goto out_put;
++
++ do {
++ arg->err = 0;
++ au_fclr_testempty(arg->flags, CALLED);
++ /* smp_mb(); */
++ err = vfsub_readdir(h_file, test_empty_cb, arg);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && au_ftest_testempty(arg->flags, CALLED));
++
++ out_put:
++ fput(h_file);
++ au_sbr_put(dentry->d_sb, arg->bindex);
++ out:
++ return err;
++}
++
++struct do_test_empty_args {
++ int *errp;
++ struct dentry *dentry;
++ struct test_empty_arg *arg;
++};
++
++static void call_do_test_empty(void *args)
++{
++ struct do_test_empty_args *a = args;
++ *a->errp = do_test_empty(a->dentry, a->arg);
++}
++
++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err, wkq_err;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, arg->bindex);
++ h_inode = h_dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
++ mutex_unlock(&h_inode->i_mutex);
++ if (!err)
++ err = do_test_empty(dentry, arg);
++ else {
++ struct do_test_empty_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .arg = arg
++ };
++ unsigned int flags = arg->flags;
++
++ wkq_err = au_wkq_wait(call_do_test_empty, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ arg->flags = flags;
++ }
++
++ return err;
++}
++
++int au_test_empty_lower(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bindex, bstart, btail;
++ struct test_empty_arg arg;
++
++ err = au_nhash_alloc(&arg.whlist, au_sbi(dentry->d_sb)->si_rdhash,
++ GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++
++ bstart = au_dbstart(dentry);
++ arg.flags = 0;
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++ au_fset_testempty(arg.flags, SHWH);
++ arg.bindex = bstart;
++ err = do_test_empty(dentry, &arg);
++ if (unlikely(err))
++ goto out_whlist;
++
++ au_fset_testempty(arg.flags, WHONLY);
++ btail = au_dbtaildir(dentry);
++ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry && h_dentry->d_inode) {
++ arg.bindex = bindex;
++ err = do_test_empty(dentry, &arg);
++ }
++ }
++
++ out_whlist:
++ au_nhash_wh_free(&arg.whlist);
++ out:
++ return err;
++}
++
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
++{
++ int err;
++ struct test_empty_arg arg;
++ aufs_bindex_t bindex, btail;
++
++ err = 0;
++ arg.whlist = *whlist;
++ arg.flags = AuTestEmpty_WHONLY;
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++ au_fset_testempty(arg.flags, SHWH);
++ btail = au_dbtaildir(dentry);
++ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry && h_dentry->d_inode) {
++ arg.bindex = bindex;
++ err = sio_test_empty(dentry, &arg);
++ }
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_dir_fop = {
++ .read = generic_read_dir,
++ .readdir = aufs_readdir,
++ .unlocked_ioctl = aufs_ioctl_dir,
++ .open = aufs_open_dir,
++ .release = aufs_release_dir,
++ .flush = aufs_flush,
++ .fsync = aufs_fsync_dir
++};
+diff -Naur a/fs/aufs/dir.h b/fs/aufs/dir.h
+--- a/fs/aufs/dir.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * directory operations
++ */
++
++#ifndef __AUFS_DIR_H__
++#define __AUFS_DIR_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* need to be faster and smaller */
++
++struct au_nhash {
++ unsigned int nh_num;
++ struct hlist_head *nh_head;
++};
++
++struct au_vdir_destr {
++ unsigned char len;
++ unsigned char name[0];
++} __packed;
++
++struct au_vdir_dehstr {
++ struct hlist_node hash;
++ struct au_vdir_destr *str;
++};
++
++struct au_vdir_de {
++ ino_t de_ino;
++ unsigned char de_type;
++ /* caution: packed */
++ struct au_vdir_destr de_str;
++} __packed;
++
++struct au_vdir_wh {
++ struct hlist_node wh_hash;
++#ifdef CONFIG_AUFS_SHWH
++ ino_t wh_ino;
++ aufs_bindex_t wh_bindex;
++ unsigned char wh_type;
++#else
++ aufs_bindex_t wh_bindex;
++#endif
++ /* caution: packed */
++ struct au_vdir_destr wh_str;
++} __packed;
++
++union au_vdir_deblk_p {
++ unsigned char *deblk;
++ struct au_vdir_de *de;
++};
++
++struct au_vdir {
++ unsigned char **vd_deblk;
++ unsigned long vd_nblk;
++ struct {
++ unsigned long ul;
++ union au_vdir_deblk_p p;
++ } vd_last;
++
++ unsigned long vd_version;
++ unsigned int vd_deblk_sz;
++ unsigned long vd_jiffy;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dir.c */
++extern const struct file_operations aufs_dir_fop;
++void au_add_nlink(struct inode *dir, struct inode *h_dir);
++void au_sub_nlink(struct inode *dir, struct inode *h_dir);
++int au_test_empty_lower(struct dentry *dentry);
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
++
++/* vdir.c */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
++void au_nhash_wh_free(struct au_nhash *whlist);
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++ int limit);
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++ unsigned int d_type, aufs_bindex_t bindex,
++ unsigned char shwh);
++void au_vdir_free(struct au_vdir *vdir);
++int au_vdir_init(struct file *file);
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
++
++/* ioctl.c */
++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DIR_H__ */
+diff -Naur a/fs/aufs/export.c b/fs/aufs/export.c
+--- a/fs/aufs/export.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/export.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * export via nfs
++ */
++
++#include <linux/exportfs.h>
++#include <linux/file.h>
++#include <linux/mnt_namespace.h>
++#include <linux/namei.h>
++#include <linux/random.h>
++#include "aufs.h"
++
++union conv {
++#ifdef CONFIG_AUFS_INO_T_64
++ __u32 a[2];
++#else
++ __u32 a[1];
++#endif
++ ino_t ino;
++};
++
++static ino_t decode_ino(__u32 *a)
++{
++ union conv u;
++
++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
++ u.a[0] = a[0];
++#ifdef CONFIG_AUFS_INO_T_64
++ u.a[1] = a[1];
++#endif
++ return u.ino;
++}
++
++static void encode_ino(__u32 *a, ino_t ino)
++{
++ union conv u;
++
++ u.ino = ino;
++ a[0] = u.a[0];
++#ifdef CONFIG_AUFS_INO_T_64
++ a[1] = u.a[1];
++#endif
++}
++
++/* NFS file handle */
++enum {
++ Fh_br_id,
++ Fh_sigen,
++#ifdef CONFIG_AUFS_INO_T_64
++ /* support 64bit inode number */
++ Fh_ino1,
++ Fh_ino2,
++ Fh_dir_ino1,
++ Fh_dir_ino2,
++#else
++ Fh_ino1,
++ Fh_dir_ino1,
++#endif
++ Fh_igen,
++ Fh_h_type,
++ Fh_tail,
++
++ Fh_ino = Fh_ino1,
++ Fh_dir_ino = Fh_dir_ino1
++};
++
++static int au_test_anon(struct dentry *dentry)
++{
++ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
++}
++
++/* ---------------------------------------------------------------------- */
++/* inode generation external table */
++
++int au_xigen_inc(struct inode *inode)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ __u32 igen;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ sb = inode->i_sb;
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ goto out;
++
++ pos = inode->i_ino;
++ pos *= sizeof(igen);
++ igen = inode->i_generation + 1;
++ sbinfo = au_sbi(sb);
++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
++ sizeof(igen), &pos);
++ if (sz == sizeof(igen))
++ goto out; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xigen error (%zd)\n", sz);
++ }
++
++ out:
++ return err;
++}
++
++int au_xigen_new(struct inode *inode)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ err = 0;
++ /* todo: dirty, at mount time */
++ if (inode->i_ino == AUFS_ROOT_INO)
++ goto out;
++ sb = inode->i_sb;
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ goto out;
++
++ err = -EFBIG;
++ pos = inode->i_ino;
++ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
++ AuIOErr1("too large i%lld\n", pos);
++ goto out;
++ }
++ pos *= sizeof(inode->i_generation);
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ file = sbinfo->si_xigen;
++ BUG_ON(!file);
++
++ if (i_size_read(file->f_dentry->d_inode)
++ < pos + sizeof(inode->i_generation)) {
++ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
++ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
++ sizeof(inode->i_generation), &pos);
++ } else
++ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
++ sizeof(inode->i_generation), &pos);
++ if (sz == sizeof(inode->i_generation))
++ goto out; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xigen error (%zd)\n", sz);
++ }
++
++ out:
++ return err;
++}
++
++int au_xigen_set(struct super_block *sb, struct file *base)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ sbinfo = au_sbi(sb);
++ file = au_xino_create2(base, sbinfo->si_xigen);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ err = 0;
++ if (sbinfo->si_xigen)
++ fput(sbinfo->si_xigen);
++ sbinfo->si_xigen = file;
++
++ out:
++ return err;
++}
++
++void au_xigen_clr(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (sbinfo->si_xigen) {
++ fput(sbinfo->si_xigen);
++ sbinfo->si_xigen = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry, *d;
++ struct inode *inode;
++ unsigned int sigen;
++
++ dentry = NULL;
++ inode = ilookup(sb, ino);
++ if (!inode)
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ sigen = au_sigen(sb);
++ if (unlikely(is_bad_inode(inode)
++ || IS_DEADDIR(inode)
++ || sigen != au_iigen(inode)))
++ goto out_iput;
++
++ dentry = NULL;
++ if (!dir_ino || S_ISDIR(inode->i_mode))
++ dentry = d_find_alias(inode);
++ else {
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias)
++ if (!au_test_anon(d)
++ && d->d_parent->d_inode->i_ino == dir_ino) {
++ dentry = dget_locked(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ }
++ if (unlikely(dentry && sigen != au_digen(dentry))) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++
++ out_iput:
++ iput(inode);
++ out:
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: dirty? */
++/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
++static struct vfsmount *au_mnt_get(struct super_block *sb)
++{
++ struct mnt_namespace *ns;
++ struct vfsmount *pos, *mnt;
++
++ spin_lock(&vfsmount_lock);
++ /* no get/put ?? */
++ AuDebugOn(!current->nsproxy);
++ ns = current->nsproxy->mnt_ns;
++ AuDebugOn(!ns);
++ mnt = NULL;
++ /* the order (reverse) will not be a problem */
++ list_for_each_entry(pos, &ns->list, mnt_list)
++ if (pos->mnt_sb == sb) {
++ mnt = mntget(pos);
++ break;
++ }
++ spin_unlock(&vfsmount_lock);
++ AuDebugOn(!mnt);
++
++ return mnt;
++}
++
++struct au_nfsd_si_lock {
++ const unsigned int sigen;
++ const aufs_bindex_t br_id;
++ unsigned char force_lock;
++};
++
++static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ aufs_bindex_t bindex;
++
++ si_read_lock(sb, AuLock_FLUSH);
++
++ /* branch id may be wrapped around */
++ bindex = au_br_index(sb, nsi_lock->br_id);
++ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
++ goto out; /* success */
++
++ if (!nsi_lock->force_lock)
++ si_read_unlock(sb);
++ bindex = -1;
++
++ out:
++ return bindex;
++}
++
++struct find_name_by_ino {
++ int called, found;
++ ino_t ino;
++ char *name;
++ int namelen;
++};
++
++static int
++find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
++ u64 ino, unsigned int d_type)
++{
++ struct find_name_by_ino *a = arg;
++
++ a->called++;
++ if (a->ino != ino)
++ return 0;
++
++ memcpy(a->name, name, namelen);
++ a->namelen = namelen;
++ a->found = 1;
++ return 1;
++}
++
++static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry, *parent;
++ struct file *file;
++ struct inode *dir;
++ struct find_name_by_ino arg;
++ int err;
++
++ parent = path->dentry;
++ if (nsi_lock)
++ si_read_unlock(parent->d_sb);
++ path_get(path);
++ file = dentry_open(parent, path->mnt, au_dir_roflags, current_cred());
++ dentry = (void *)file;
++ if (IS_ERR(file))
++ goto out;
++
++ dentry = ERR_PTR(-ENOMEM);
++ arg.name = __getname();
++ if (unlikely(!arg.name))
++ goto out_file;
++ arg.ino = ino;
++ arg.found = 0;
++ do {
++ arg.called = 0;
++ /* smp_mb(); */
++ err = vfsub_readdir(file, find_name_by_ino, &arg);
++ } while (!err && !arg.found && arg.called);
++ dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_name;
++ dentry = ERR_PTR(-ENOENT);
++ if (!arg.found)
++ goto out_name;
++
++ /* do not call au_lkup_one() */
++ dir = parent->d_inode;
++ mutex_lock(&dir->i_mutex);
++ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
++ mutex_unlock(&dir->i_mutex);
++ AuTraceErrPtr(dentry);
++ if (IS_ERR(dentry))
++ goto out_name;
++ AuDebugOn(au_test_anon(dentry));
++ if (unlikely(!dentry->d_inode)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ENOENT);
++ }
++
++ out_name:
++ __putname(arg.name);
++ out_file:
++ fput(file);
++ out:
++ if (unlikely(nsi_lock
++ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
++ if (!IS_ERR(dentry)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry;
++ struct path path;
++
++ if (dir_ino != AUFS_ROOT_INO) {
++ path.dentry = decode_by_ino(sb, dir_ino, 0);
++ dentry = path.dentry;
++ if (!path.dentry || IS_ERR(path.dentry))
++ goto out;
++ AuDebugOn(au_test_anon(path.dentry));
++ } else
++ path.dentry = dget(sb->s_root);
++
++ path.mnt = au_mnt_get(sb);
++ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
++ path_put(&path);
++
++ out:
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_acceptable(void *expv, struct dentry *dentry)
++{
++ return 1;
++}
++
++static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
++ char *buf, int len, struct super_block *sb)
++{
++ char *p;
++ int n;
++ struct path path;
++
++ p = d_path(h_rootpath, buf, len);
++ if (IS_ERR(p))
++ goto out;
++ n = strlen(p);
++
++ path.mnt = h_rootpath->mnt;
++ path.dentry = h_parent;
++ p = d_path(&path, buf, len);
++ if (IS_ERR(p))
++ goto out;
++ if (n != 1)
++ p += n;
++
++ path.mnt = au_mnt_get(sb);
++ path.dentry = sb->s_root;
++ p = d_path(&path, buf, len - strlen(p));
++ mntput(path.mnt);
++ if (IS_ERR(p))
++ goto out;
++ if (n != 1)
++ p[strlen(p)] = '/';
++
++ out:
++ AuTraceErrPtr(p);
++ return p;
++}
++
++static
++struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
++ ino_t ino, __u32 *fh, int fh_len,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry, *h_parent, *root;
++ struct super_block *h_sb;
++ char *pathname, *p;
++ struct vfsmount *h_mnt;
++ struct au_branch *br;
++ int err;
++ struct path path;
++
++ br = au_sbr(sb, bindex);
++ /* au_br_get(br); */
++ h_mnt = br->br_mnt;
++ h_sb = h_mnt->mnt_sb;
++ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
++ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
++ fh_len - Fh_tail, fh[Fh_h_type],
++ h_acceptable, /*context*/NULL);
++ dentry = h_parent;
++ if (unlikely(!h_parent || IS_ERR(h_parent))) {
++ AuWarn1("%s decode_fh failed, %ld\n",
++ au_sbtype(h_sb), PTR_ERR(h_parent));
++ goto out;
++ }
++ dentry = NULL;
++ if (unlikely(au_test_anon(h_parent))) {
++ AuWarn1("%s decode_fh returned a disconnected dentry\n",
++ au_sbtype(h_sb));
++ goto out_h_parent;
++ }
++
++ dentry = ERR_PTR(-ENOMEM);
++ pathname = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!pathname))
++ goto out_h_parent;
++
++ root = sb->s_root;
++ path.mnt = h_mnt;
++ di_read_lock_parent(root, !AuLock_IR);
++ path.dentry = au_h_dptr(root, bindex);
++ di_read_unlock(root, !AuLock_IR);
++ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
++ dentry = (void *)p;
++ if (IS_ERR(p))
++ goto out_pathname;
++
++ si_read_unlock(sb);
++ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
++ dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_relock;
++
++ dentry = ERR_PTR(-ENOENT);
++ AuDebugOn(au_test_anon(path.dentry));
++ if (unlikely(!path.dentry->d_inode))
++ goto out_path;
++
++ if (ino != path.dentry->d_inode->i_ino)
++ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
++ else
++ dentry = dget(path.dentry);
++
++ out_path:
++ path_put(&path);
++ out_relock:
++ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
++ if (!IS_ERR(dentry)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ out_pathname:
++ free_page((unsigned long)pathname);
++ out_h_parent:
++ dput(h_parent);
++ out:
++ /* au_br_put(br); */
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *
++aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
++ int fh_type)
++{
++ struct dentry *dentry;
++ __u32 *fh = fid->raw;
++ ino_t ino, dir_ino;
++ aufs_bindex_t bindex;
++ struct au_nfsd_si_lock nsi_lock = {
++ .sigen = fh[Fh_sigen],
++ .br_id = fh[Fh_br_id],
++ .force_lock = 0
++ };
++
++ AuDebugOn(fh_len < Fh_tail);
++
++ dentry = ERR_PTR(-ESTALE);
++ /* branch id may be wrapped around */
++ bindex = si_nfsd_read_lock(sb, &nsi_lock);
++ if (unlikely(bindex < 0))
++ goto out;
++ nsi_lock.force_lock = 1;
++
++ /* is this inode still cached? */
++ ino = decode_ino(fh + Fh_ino);
++ AuDebugOn(ino == AUFS_ROOT_INO);
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ dentry = decode_by_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (dentry)
++ goto accept;
++
++ /* is the parent dir cached? */
++ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (dentry)
++ goto accept;
++
++ /* lookup path */
++ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (unlikely(!dentry))
++ /* todo?: make it ESTALE */
++ goto out_unlock;
++
++ accept:
++ if (dentry->d_inode->i_generation == fh[Fh_igen])
++ goto out_unlock; /* success */
++
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ out_unlock:
++ si_read_unlock(sb);
++ out:
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++#if 0 /* reserved for future use */
++/* support subtreecheck option */
++static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
++ int fh_len, int fh_type)
++{
++ struct dentry *parent;
++ __u32 *fh = fid->raw;
++ ino_t dir_ino;
++
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ parent = decode_by_ino(sb, dir_ino, 0);
++ if (IS_ERR(parent))
++ goto out;
++ if (!parent)
++ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
++ dir_ino, fh, fh_len);
++
++ out:
++ AuTraceErrPtr(parent);
++ return parent;
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
++ int connectable)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb, *h_sb;
++ struct inode *inode;
++ struct dentry *parent, *h_parent;
++ struct au_branch *br;
++
++ AuDebugOn(au_test_anon(dentry));
++
++ parent = NULL;
++ err = -ENOSPC;
++ if (unlikely(*max_len <= Fh_tail)) {
++ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
++ goto out;
++ }
++
++ err = FILEID_ROOT;
++ if (IS_ROOT(dentry)) {
++ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
++ goto out;
++ }
++
++ err = -EIO;
++ h_parent = NULL;
++ sb = dentry->d_sb;
++ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, !AuLock_IR);
++ inode = dentry->d_inode;
++ AuDebugOn(!inode);
++#ifdef CONFIG_AUFS_DEBUG
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ AuWarn1("NFS-exporting requires xino\n");
++#endif
++
++ bend = au_dbtaildir(parent);
++ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (h_parent) {
++ dget(h_parent);
++ break;
++ }
++ }
++ if (unlikely(!h_parent))
++ goto out_unlock;
++
++ err = -EPERM;
++ br = au_sbr(sb, bindex);
++ h_sb = br->br_mnt->mnt_sb;
++ if (unlikely(!h_sb->s_export_op)) {
++ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
++ goto out_dput;
++ }
++
++ fh[Fh_br_id] = br->br_id;
++ fh[Fh_sigen] = au_sigen(sb);
++ encode_ino(fh + Fh_ino, inode->i_ino);
++ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
++ fh[Fh_igen] = inode->i_generation;
++
++ *max_len -= Fh_tail;
++ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
++ max_len,
++ /*connectable or subtreecheck*/0);
++ err = fh[Fh_h_type];
++ *max_len += Fh_tail;
++ /* todo: macros? */
++ if (err != 255)
++ err = 99;
++ else
++ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
++
++ out_dput:
++ dput(h_parent);
++ out_unlock:
++ di_read_unlock(parent, !AuLock_IR);
++ dput(parent);
++ aufs_read_unlock(dentry, AuLock_IR);
++ out:
++ if (unlikely(err < 0))
++ err = 255;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct export_operations aufs_export_op = {
++ .fh_to_dentry = aufs_fh_to_dentry,
++ /* .fh_to_parent = aufs_fh_to_parent, */
++ .encode_fh = aufs_encode_fh
++};
++
++void au_export_init(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ __u32 u;
++
++ sb->s_export_op = &aufs_export_op;
++ sbinfo = au_sbi(sb);
++ sbinfo->si_xigen = NULL;
++ get_random_bytes(&u, sizeof(u));
++ BUILD_BUG_ON(sizeof(u) != sizeof(int));
++ atomic_set(&sbinfo->si_xigen_next, u);
++}
+diff -Naur a/fs/aufs/file.c b/fs/aufs/file.c
+--- a/fs/aufs/file.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,568 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * handling file/dir, and address_space operation
++ */
++
++#include <linux/file.h>
++#include <linux/fsnotify.h>
++#include <linux/namei.h>
++#include <linux/pagemap.h>
++#include "aufs.h"
++
++/*
++ * a dirty trick for handling deny_write_access().
++ * because FMODE_EXEC flag is not passed to f_op->open(),
++ * set it to file->private_data temporary.
++ */
++void au_store_oflag(struct nameidata *nd, struct inode *inode)
++{
++ if (nd
++ /* && !(nd->flags & LOOKUP_CONTINUE) */
++ && (nd->flags & LOOKUP_OPEN)
++ && (nd->intent.open.flags & vfsub_fmode_to_uint(FMODE_EXEC))
++ && inode
++ && S_ISREG(inode->i_mode)) {
++ /* suppress a warning in lp64 */
++ unsigned long flags = nd->intent.open.flags;
++ nd->intent.open.file->private_data = (void *)flags;
++ /* smp_mb(); */
++ }
++}
++
++/* drop flags for writing */
++unsigned int au_file_roflags(unsigned int flags)
++{
++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
++ flags |= O_RDONLY | O_NOATIME;
++ return flags;
++}
++
++/* common functions to regular file and dir */
++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++ struct file *file)
++{
++ struct file *h_file;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ /* a race condition can happen between open and unlink/rmdir */
++ h_file = ERR_PTR(-ENOENT);
++ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
++ || !h_inode))
++ goto out;
++
++ sb = dentry->d_sb;
++ br = au_sbr(sb, bindex);
++ h_file = ERR_PTR(-EACCES);
++ if (file && (file->f_mode & FMODE_EXEC)
++ && (br->br_mnt->mnt_flags & MNT_NOEXEC))
++ goto out;
++
++ /* drop flags for writing */
++ if (au_test_ro(sb, bindex, dentry->d_inode))
++ flags = au_file_roflags(flags);
++ flags &= ~O_CREAT;
++ atomic_inc(&br->br_count);
++ h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags,
++ current_cred());
++ if (IS_ERR(h_file))
++ goto out_br;
++
++ if (file && (file->f_mode & FMODE_EXEC)) {
++ h_file->f_mode |= FMODE_EXEC;
++ err = deny_write_access(h_file);
++ if (unlikely(err)) {
++ fput(h_file);
++ h_file = ERR_PTR(err);
++ goto out_br;
++ }
++ }
++ fsnotify_open(h_dentry);
++ goto out; /* success */
++
++ out_br:
++ atomic_dec(&br->br_count);
++ out:
++ return h_file;
++}
++
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
++{
++ int err;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_finfo_init(file);
++ if (unlikely(err))
++ goto out;
++
++ di_read_lock_child(dentry, AuLock_IR);
++ err = open(file, file->f_flags);
++ di_read_unlock(dentry, AuLock_IR);
++
++ fi_write_unlock(file);
++ if (unlikely(err))
++ au_finfo_fin(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++int au_reopen_nondir(struct file *file)
++{
++ int err;
++ aufs_bindex_t bstart, bindex, bend;
++ struct dentry *dentry;
++ struct file *h_file, *h_file_tmp;
++
++ dentry = file->f_dentry;
++ bstart = au_dbstart(dentry);
++ h_file_tmp = NULL;
++ if (au_fbstart(file) == bstart) {
++ h_file = au_h_fptr(file, bstart);
++ if (file->f_mode == h_file->f_mode)
++ return 0; /* success */
++ h_file_tmp = h_file;
++ get_file(h_file_tmp);
++ au_set_h_fptr(file, bstart, NULL);
++ }
++ AuDebugOn(au_fbstart(file) < bstart
++ || au_fi(file)->fi_hfile[0 + bstart].hf_file);
++
++ h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out; /* todo: close all? */
++
++ err = 0;
++ au_set_fbstart(file, bstart);
++ au_set_h_fptr(file, bstart, h_file);
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++
++ /* close lower files */
++ bend = au_fbend(file);
++ for (bindex = bstart + 1; bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbend(file, bstart);
++
++ out:
++ if (h_file_tmp)
++ fput(h_file_tmp);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
++ struct dentry *hi_wh)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct dentry *h_dentry;
++
++ dinfo = au_di(file->f_dentry);
++ bstart = dinfo->di_bstart;
++ dinfo->di_bstart = btgt;
++ h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
++ dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
++ err = au_reopen_nondir(file);
++ dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
++ dinfo->di_bstart = bstart;
++
++ return err;
++}
++
++static int au_ready_to_write_wh(struct file *file, loff_t len,
++ aufs_bindex_t bcpup)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *dentry, *hi_wh;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ hi_wh = au_hi_wh(inode, bcpup);
++ if (!hi_wh)
++ err = au_sio_cpup_wh(dentry, bcpup, len, file);
++ else
++ /* already copied-up after unlink */
++ err = au_reopen_wh(file, bcpup, hi_wh);
++
++ sb = dentry->d_sb;
++ if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
++ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
++
++ return err;
++}
++
++/*
++ * prepare the @file for writing.
++ */
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
++{
++ int err;
++ aufs_bindex_t bstart, bcpup;
++ struct dentry *dentry, *parent, *h_dentry;
++ struct inode *h_inode, *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ bstart = au_fbstart(file);
++ inode = dentry->d_inode;
++ err = au_test_ro(sb, bstart, inode);
++ if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
++ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
++ goto out;
++ }
++
++ /* need to cpup */
++ parent = dget_parent(dentry);
++ di_write_lock_parent(parent);
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ bcpup = err;
++ if (unlikely(err < 0))
++ goto out_dgrade;
++ err = 0;
++
++ if (!au_h_dptr(parent, bcpup)) {
++ err = au_cpup_dirs(dentry, bcpup);
++ if (unlikely(err))
++ goto out_dgrade;
++ }
++
++ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out_dgrade;
++
++ h_dentry = au_h_fptr(file, bstart)->f_dentry;
++ h_inode = h_dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
++ /* || !h_inode->i_nlink */) {
++ err = au_ready_to_write_wh(file, len, bcpup);
++ di_downgrade_lock(parent, AuLock_IR);
++ } else {
++ di_downgrade_lock(parent, AuLock_IR);
++ if (!au_h_dptr(dentry, bcpup))
++ err = au_sio_cpup_simple(dentry, bcpup, len,
++ AuCpup_DTIME);
++ if (!err)
++ err = au_reopen_nondir(file);
++ }
++ mutex_unlock(&h_inode->i_mutex);
++
++ if (!err) {
++ au_pin_set_parent_lflag(pin, /*lflag*/0);
++ goto out_dput; /* success */
++ }
++ au_unpin(pin);
++ goto out_unlock;
++
++ out_dgrade:
++ di_downgrade_lock(parent, AuLock_IR);
++ out_unlock:
++ di_read_unlock(parent, AuLock_IR);
++ out_dput:
++ dput(parent);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_pin pin;
++ struct au_finfo *finfo;
++ struct dentry *dentry, *parent, *hi_wh;
++ struct inode *inode;
++ struct super_block *sb;
++
++ err = 0;
++ finfo = au_fi(file);
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ bstart = au_ibstart(inode);
++ if (bstart == finfo->fi_bstart)
++ goto out;
++
++ parent = dget_parent(dentry);
++ if (au_test_ro(sb, bstart, inode)) {
++ di_read_lock_parent(parent, !AuLock_IR);
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ bstart = err;
++ di_read_unlock(parent, !AuLock_IR);
++ if (unlikely(err < 0))
++ goto out_parent;
++ err = 0;
++ }
++
++ di_read_lock_parent(parent, AuLock_IR);
++ hi_wh = au_hi_wh(inode, bstart);
++ if (au_opt_test(au_mntflags(sb), PLINK)
++ && au_plink_test(inode)
++ && !d_unhashed(dentry)) {
++ err = au_test_and_cpup_dirs(dentry, bstart);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* always superio. */
++ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (!err)
++ err = au_sio_cpup_simple(dentry, bstart, -1,
++ AuCpup_DTIME);
++ au_unpin(&pin);
++ } else if (hi_wh) {
++ /* already copied-up after unlink */
++ err = au_reopen_wh(file, bstart, hi_wh);
++ *need_reopen = 0;
++ }
++
++ out_unlock:
++ di_read_unlock(parent, AuLock_IR);
++ out_parent:
++ dput(parent);
++ out:
++ return err;
++}
++
++static void au_do_refresh_file(struct file *file)
++{
++ aufs_bindex_t bindex, bend, new_bindex, brid;
++ struct au_hfile *p, tmp, *q;
++ struct au_finfo *finfo;
++ struct super_block *sb;
++
++ sb = file->f_dentry->d_sb;
++ finfo = au_fi(file);
++ p = finfo->fi_hfile + finfo->fi_bstart;
++ brid = p->hf_br->br_id;
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
++ if (!p->hf_file)
++ continue;
++
++ new_bindex = au_br_index(sb, p->hf_br->br_id);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) {
++ au_set_h_fptr(file, bindex, NULL);
++ continue;
++ }
++
++ /* swap two lower inode, and loop again */
++ q = finfo->fi_hfile + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hf_file) {
++ bindex--;
++ p--;
++ }
++ }
++
++ p = finfo->fi_hfile;
++ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
++ bend = au_sbend(sb);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p, file);
++ }
++ } else {
++ bend = au_br_index(sb, brid);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file)
++ au_hfput(p, file);
++ bend = au_sbend(sb);
++ }
++
++ p = finfo->fi_hfile + bend;
++ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
++ finfo->fi_bend--, p--)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p, file);
++ }
++ AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
++}
++
++/*
++ * after branch manipulating, refresh the file.
++ */
++static int refresh_file(struct file *file, int (*reopen)(struct file *file))
++{
++ int err, need_reopen;
++ struct dentry *dentry;
++ aufs_bindex_t bend, bindex;
++
++ dentry = file->f_dentry;
++ err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
++ if (unlikely(err))
++ goto out;
++ au_do_refresh_file(file);
++
++ err = 0;
++ need_reopen = 1;
++ if (!au_test_mmapped(file))
++ err = au_file_refresh_by_inode(file, &need_reopen);
++ if (!err && need_reopen && !d_unhashed(dentry))
++ err = reopen(file);
++ if (!err) {
++ au_update_figen(file);
++ return 0; /* success */
++ }
++
++ /* error, close all lower files */
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++
++ out:
++ return err;
++}
++
++/* common function to regular file and dir */
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++ int wlock)
++{
++ int err;
++ unsigned int sigen, figen;
++ aufs_bindex_t bstart;
++ unsigned char pseudo_link;
++ struct dentry *dentry;
++
++ err = 0;
++ dentry = file->f_dentry;
++ sigen = au_sigen(dentry->d_sb);
++ fi_write_lock(file);
++ figen = au_figen(file);
++ di_write_lock_child(dentry);
++ bstart = au_dbstart(dentry);
++ pseudo_link = (bstart != au_ibstart(dentry->d_inode));
++ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
++ if (!wlock) {
++ di_downgrade_lock(dentry, AuLock_IR);
++ fi_downgrade_lock(file);
++ }
++ goto out; /* success */
++ }
++
++ AuDbg("sigen %d, figen %d\n", sigen, figen);
++ if (sigen != au_digen(dentry)
++ || sigen != au_iigen(dentry->d_inode)) {
++ err = au_reval_dpath(dentry, sigen);
++ if (unlikely(err < 0))
++ goto out;
++ AuDebugOn(au_digen(dentry) != sigen
++ || au_iigen(dentry->d_inode) != sigen);
++ }
++
++ err = refresh_file(file, reopen);
++ if (!err) {
++ if (!wlock) {
++ di_downgrade_lock(dentry, AuLock_IR);
++ fi_downgrade_lock(file);
++ }
++ } else {
++ di_write_unlock(dentry);
++ fi_write_unlock(file);
++ }
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* cf. aufs_nopage() */
++/* for madvise(2) */
++static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
++{
++ unlock_page(page);
++ return 0;
++}
++
++/* they will never be called. */
++#ifdef CONFIG_AUFS_DEBUG
++static int aufs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned copied,
++ struct page *page, void *fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_writepage(struct page *page, struct writeback_control *wbc)
++{ AuUnsupport(); return 0; }
++static void aufs_sync_page(struct page *page)
++{ AuUnsupport(); }
++
++static int aufs_set_page_dirty(struct page *page)
++{ AuUnsupport(); return 0; }
++static void aufs_invalidatepage(struct page *page, unsigned long offset)
++{ AuUnsupport(); }
++static int aufs_releasepage(struct page *page, gfp_t gfp)
++{ AuUnsupport(); return 0; }
++static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs)
++{ AuUnsupport(); return 0; }
++#endif /* CONFIG_AUFS_DEBUG */
++
++struct address_space_operations aufs_aop = {
++ .readpage = aufs_readpage,
++#ifdef CONFIG_AUFS_DEBUG
++ .writepage = aufs_writepage,
++ .sync_page = aufs_sync_page,
++ .set_page_dirty = aufs_set_page_dirty,
++ .write_begin = aufs_write_begin,
++ .write_end = aufs_write_end,
++ .invalidatepage = aufs_invalidatepage,
++ .releasepage = aufs_releasepage,
++ .direct_IO = aufs_direct_IO,
++#endif /* CONFIG_AUFS_DEBUG */
++};
+diff -Naur a/fs/aufs/file.h b/fs/aufs/file.h
+--- a/fs/aufs/file.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file operations
++ */
++
++#ifndef __AUFS_FILE_H__
++#define __AUFS_FILE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct au_branch;
++struct au_hfile {
++ struct file *hf_file;
++ struct au_branch *hf_br;
++};
++
++struct au_vdir;
++struct au_finfo {
++ atomic_t fi_generation;
++
++ struct rw_semaphore fi_rwsem;
++ struct au_hfile *fi_hfile;
++ aufs_bindex_t fi_bstart, fi_bend;
++
++ union {
++ /* non-dir only */
++ struct {
++ struct vm_operations_struct *fi_h_vm_ops;
++ struct vm_operations_struct *fi_vm_ops;
++ };
++
++ /* dir only */
++ struct {
++ struct au_vdir *fi_vdir_cache;
++ int fi_maintain_plink;
++ };
++ };
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* file.c */
++extern struct address_space_operations aufs_aop;
++void au_store_oflag(struct nameidata *nd, struct inode *inode);
++unsigned int au_file_roflags(unsigned int flags);
++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++ struct file *file);
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
++int au_reopen_nondir(struct file *file);
++struct au_pin;
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++ int wlock);
++
++/* f_op.c */
++extern const struct file_operations aufs_file_fop;
++int aufs_flush(struct file *file, fl_owner_t id);
++
++/* finfo.c */
++void au_hfput(struct au_hfile *hf, struct file *file);
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
++ struct file *h_file);
++
++void au_update_figen(struct file *file);
++
++void au_finfo_fin(struct file *file);
++int au_finfo_init(struct file *file);
++int au_fi_realloc(struct au_finfo *finfo, int nbr);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_finfo *au_fi(struct file *file)
++{
++ return file->private_data;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * fi_read_lock, fi_write_lock,
++ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
++ */
++AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
++
++#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: hard/soft set? */
++static inline aufs_bindex_t au_fbstart(struct file *file)
++{
++ return au_fi(file)->fi_bstart;
++}
++
++static inline aufs_bindex_t au_fbend(struct file *file)
++{
++ return au_fi(file)->fi_bend;
++}
++
++static inline struct au_vdir *au_fvdir_cache(struct file *file)
++{
++ return au_fi(file)->fi_vdir_cache;
++}
++
++static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
++{
++ au_fi(file)->fi_bstart = bindex;
++}
++
++static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
++{
++ au_fi(file)->fi_bend = bindex;
++}
++
++static inline void au_set_fvdir_cache(struct file *file,
++ struct au_vdir *vdir_cache)
++{
++ au_fi(file)->fi_vdir_cache = vdir_cache;
++}
++
++static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
++{
++ return au_fi(file)->fi_hfile[0 + bindex].hf_file;
++}
++
++/* todo: memory barrier? */
++static inline unsigned int au_figen(struct file *f)
++{
++ return atomic_read(&au_fi(f)->fi_generation);
++}
++
++static inline int au_test_mmapped(struct file *f)
++{
++ return !!(au_fi(f)->fi_h_vm_ops);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FILE_H__ */
+diff -Naur a/fs/aufs/finfo.c b/fs/aufs/finfo.c
+--- a/fs/aufs/finfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/finfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file private data
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++void au_hfput(struct au_hfile *hf, struct file *file)
++{
++ if (file->f_mode & FMODE_EXEC)
++ allow_write_access(hf->hf_file);
++ fput(hf->hf_file);
++ hf->hf_file = NULL;
++ atomic_dec(&hf->hf_br->br_count);
++ hf->hf_br = NULL;
++}
++
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
++{
++ struct au_finfo *finfo = au_fi(file);
++ struct au_hfile *hf;
++
++ hf = finfo->fi_hfile + bindex;
++ if (hf->hf_file)
++ au_hfput(hf, file);
++ if (val) {
++ hf->hf_file = val;
++ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
++ }
++}
++
++void au_update_figen(struct file *file)
++{
++ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_finfo_fin(struct file *file)
++{
++ struct au_finfo *finfo;
++ aufs_bindex_t bindex, bend;
++
++ fi_write_lock(file);
++ bend = au_fbend(file);
++ bindex = au_fbstart(file);
++ if (bindex >= 0)
++ /*
++ * calls fput() instead of filp_close(),
++ * since no dnotify or lock for the lower file.
++ */
++ for (; bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++
++ finfo = au_fi(file);
++ au_dbg_verify_hf(finfo);
++ kfree(finfo->fi_hfile);
++ fi_write_unlock(file);
++ au_rwsem_destroy(&finfo->fi_rwsem);
++ au_cache_free_finfo(finfo);
++}
++
++int au_finfo_init(struct file *file)
++{
++ struct au_finfo *finfo;
++ struct dentry *dentry;
++ unsigned long ul;
++
++ dentry = file->f_dentry;
++ finfo = au_cache_alloc_finfo();
++ if (unlikely(!finfo))
++ goto out;
++
++ finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
++ sizeof(*finfo->fi_hfile), GFP_NOFS);
++ if (unlikely(!finfo->fi_hfile))
++ goto out_finfo;
++
++ init_rwsem(&finfo->fi_rwsem);
++ down_write(&finfo->fi_rwsem);
++ finfo->fi_bstart = -1;
++ finfo->fi_bend = -1;
++ atomic_set(&finfo->fi_generation, au_digen(dentry));
++ /* smp_mb(); */ /* atomic_set */
++
++ /* cf. au_store_oflag() */
++ /* suppress a warning in lp64 */
++ ul = (unsigned long)file->private_data;
++ file->f_mode |= (vfsub_uint_to_fmode(ul) & FMODE_EXEC);
++ file->private_data = finfo;
++ return 0; /* success */
++
++ out_finfo:
++ au_cache_free_finfo(finfo);
++ out:
++ return -ENOMEM;
++}
++
++int au_fi_realloc(struct au_finfo *finfo, int nbr)
++{
++ int err, sz;
++ struct au_hfile *hfp;
++
++ err = -ENOMEM;
++ sz = sizeof(*hfp) * (finfo->fi_bend + 1);
++ if (!sz)
++ sz = sizeof(*hfp);
++ hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
++ if (hfp) {
++ finfo->fi_hfile = hfp;
++ err = 0;
++ }
++
++ return err;
++}
+diff -Naur a/fs/aufs/f_op.c b/fs/aufs/f_op.c
+--- a/fs/aufs/f_op.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/f_op.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,648 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file and vm operations
++ */
++
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/poll.h>
++#include "aufs.h"
++
++/* common function to regular file and dir */
++int aufs_flush(struct file *file, fl_owner_t id)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct dentry *dentry;
++ struct file *h_file;
++
++ dentry = file->f_dentry;
++ si_noflush_read_lock(dentry->d_sb);
++ fi_read_lock(file);
++ di_read_lock_child(dentry, AuLock_IW);
++
++ err = 0;
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++ h_file = au_h_fptr(file, bindex);
++ if (!h_file || !h_file->f_op || !h_file->f_op->flush)
++ continue;
++
++ err = h_file->f_op->flush(h_file, id);
++ if (!err)
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ }
++ au_cpup_attr_timesizes(dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IW);
++ fi_read_unlock(file);
++ si_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int do_open_nondir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct au_finfo *finfo;
++
++ err = 0;
++ dentry = file->f_dentry;
++ finfo = au_fi(file);
++ finfo->fi_h_vm_ops = NULL;
++ finfo->fi_vm_ops = NULL;
++ bindex = au_dbstart(dentry);
++ /* O_TRUNC is processed already */
++ BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
++ && (flags & O_TRUNC));
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ if (IS_ERR(h_file))
++ err = PTR_ERR(h_file);
++ else {
++ au_set_fbstart(file, bindex);
++ au_set_fbend(file, bindex);
++ au_set_h_fptr(file, bindex, h_file);
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ }
++ return err;
++}
++
++static int aufs_open_nondir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ return au_do_open(file, do_open_nondir);
++}
++
++static int aufs_release_nondir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++
++ si_noflush_read_lock(sb);
++ kfree(au_fi(file)->fi_vm_ops);
++ au_finfo_fin(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct file *h_file;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ err = vfsub_read_u(h_file, buf, count, ppos);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++static ssize_t aufs_write(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ aufs_bindex_t bstart;
++ struct au_pin pin;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *h_file;
++ char __user *buf = (char __user *)ubuf;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ mutex_lock(&inode->i_mutex);
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ bstart = au_fbstart(file);
++ h_file = au_h_fptr(file, bstart);
++ au_unpin(&pin);
++ err = vfsub_write_u(h_file, buf, count, ppos);
++ au_cpup_attr_timesizes(inode);
++ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
++
++static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ ssize_t err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (au_test_loopback_kthread()) {
++ file->f_mapping = h_file->f_mapping;
++ smp_mb(); /* unnecessary? */
++ }
++ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
++ /* todo: necessasry? */
++ /* file->f_ra = h_file->f_ra; */
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++static ssize_t
++aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
++ size_t len, unsigned int flags)
++{
++ ssize_t err;
++ struct au_pin pin;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *h_file;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ mutex_lock(&inode->i_mutex);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ au_unpin(&pin);
++ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
++ au_cpup_attr_timesizes(inode);
++ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct file *au_safe_file(struct vm_area_struct *vma)
++{
++ struct file *file;
++
++ file = vma->vm_file;
++ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
++ return file;
++ return NULL;
++}
++
++static void au_reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ vma->vm_file = file;
++ /* smp_mb(); */ /* flush vm_file */
++}
++
++static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ int err;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ /* todo: non-robr mode, user vm_file as it is? */
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ /* do not revalidate, no si lock */
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ err = finfo->fi_h_vm_ops->fault(vma, vmf);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++#if 0 /* def CONFIG_SMP */
++ /* wake_up_nr(&wq, online_cpu - 1); */
++ wake_up_all(&wq);
++#else
++ wake_up(&wq);
++#endif
++
++ return err;
++}
++
++static int aufs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
++{
++ int err;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ err = finfo->fi_h_vm_ops->page_mkwrite(vma, page);
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++ wake_up(&wq);
++
++ return err;
++}
++
++static void aufs_vm_close(struct vm_area_struct *vma)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ finfo->fi_h_vm_ops->close(vma);
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++ wake_up(&wq);
++}
++
++static struct vm_operations_struct aufs_vm_ops = {
++ /* .close and .page_mkwrite are not set by default */
++ .fault = aufs_fault,
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct vm_operations_struct *au_vm_ops(struct file *h_file,
++ struct vm_area_struct *vma)
++{
++ struct vm_operations_struct *vm_ops;
++ int err;
++
++ vm_ops = ERR_PTR(-ENODEV);
++ if (!h_file->f_op || !h_file->f_op->mmap)
++ goto out;
++
++ err = h_file->f_op->mmap(h_file, vma);
++ vm_ops = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ vm_ops = vma->vm_ops;
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (unlikely(err)) {
++ AuIOErr("failed internal unmapping %.*s, %d\n",
++ AuDLNPair(h_file->f_dentry), err);
++ vm_ops = ERR_PTR(-EIO);
++ }
++
++ out:
++ return vm_ops;
++}
++
++static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
++{
++ int err;
++ struct vm_operations_struct *h_ops;
++
++ err = 0;
++ h_ops = finfo->fi_h_vm_ops;
++ AuDebugOn(!h_ops);
++ if ((!h_ops->page_mkwrite && !h_ops->close)
++ || finfo->fi_vm_ops)
++ goto out;
++
++ err = -ENOMEM;
++ finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
++ if (unlikely(!finfo->fi_vm_ops))
++ goto out;
++
++ err = 0;
++ if (h_ops->page_mkwrite)
++ finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
++ if (h_ops->close)
++ finfo->fi_vm_ops->close = aufs_vm_close;
++
++ vma->vm_ops = finfo->fi_vm_ops;
++
++ out:
++ return err;
++}
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err;
++ unsigned char wlock, mmapped;
++ struct dentry *dentry;
++ struct super_block *sb;
++ struct file *h_file;
++ struct vm_operations_struct *vm_ops;
++
++ dentry = file->f_dentry;
++ mmapped = !!au_test_mmapped(file); /* can be harmless race condition */
++ wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped);
++ if (unlikely(err))
++ goto out;
++
++ if (wlock) {
++ struct au_pin pin;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++ au_unpin(&pin);
++ } else if (!mmapped)
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
++ /*
++ * by this assignment, f_mapping will differs from aufs inode
++ * i_mapping.
++ * if someone else mixes the use of f_dentry->d_inode and
++ * f_mapping->host, then a problem may arise.
++ */
++ file->f_mapping = h_file->f_mapping;
++ }
++
++ vm_ops = NULL;
++ if (!mmapped) {
++ vm_ops = au_vm_ops(h_file, vma);
++ err = PTR_ERR(vm_ops);
++ if (IS_ERR(vm_ops))
++ goto out_unlock;
++ }
++
++ /*
++ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
++ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
++ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
++ * both of the aufs file and the lower file is deny_write_access()-ed.
++ * finally I hope we can skip handlling MAP_DENYWRITE here.
++ */
++ err = generic_file_mmap(file, vma);
++ if (unlikely(err))
++ goto out_unlock;
++
++ vma->vm_ops = &aufs_vm_ops;
++ /* test again */
++ if (!au_test_mmapped(file))
++ au_fi(file)->fi_h_vm_ops = vm_ops;
++
++ err = au_custom_vm_ops(au_fi(file), vma);
++ if (unlikely(err))
++ goto out_unlock;
++
++ vfsub_file_accessed(h_file);
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ if (!wlock && mmapped)
++ fi_read_unlock(file);
++ else
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static unsigned int aufs_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask;
++ int err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ /* We should pretend an error happened. */
++ mask = POLLERR /* | POLLIN | POLLOUT */;
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ /* it is not an error if h_file has no operation */
++ mask = DEFAULT_POLLMASK;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->poll)
++ mask = h_file->f_op->poll(h_file, wait);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ AuTraceErr((int)mask);
++ return mask;
++}
++
++static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct au_pin pin;
++ struct inode *inode;
++ struct file *h_file;
++ struct super_block *sb;
++
++ inode = dentry->d_inode;
++ IMustLock(file->f_mapping->host);
++ if (inode != file->f_mapping->host) {
++ mutex_unlock(&file->f_mapping->host->i_mutex);
++ mutex_lock(&inode->i_mutex);
++ }
++ IMustLock(inode);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = 0; /* -EBADF; */ /* posix? */
++ if (unlikely(!(file->f_mode & FMODE_WRITE)))
++ goto out;
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++ au_unpin(&pin);
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->fsync) {
++ struct dentry *h_d;
++ struct mutex *h_mtx;
++
++ /*
++ * no filemap_fdatawrite() since aufs file has no its own
++ * mapping, but dir.
++ */
++ h_d = h_file->f_dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = h_file->f_op->fsync(h_file, h_d, datasync);
++ if (!err)
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ au_cpup_attr_timesizes(inode);
++ mutex_unlock(h_mtx);
++ }
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ if (inode != file->f_mapping->host) {
++ mutex_unlock(&inode->i_mutex);
++ mutex_lock(&file->f_mapping->host->i_mutex);
++ }
++ return err;
++}
++
++static int aufs_fasync(int fd, struct file *file, int flag)
++{
++ int err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->fasync)
++ err = h_file->f_op->fasync(fd, h_file, flag);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_file_fop = {
++ /*
++ * while generic_file_llseek/_unlocked() don't use BKL,
++ * don't use it since it operates file->f_mapping->host.
++ * in aufs, it may be a real file and may confuse users by UDBA.
++ */
++ /* .llseek = generic_file_llseek, */
++
++ .read = aufs_read,
++ .write = aufs_write,
++ .poll = aufs_poll,
++ .mmap = aufs_mmap,
++ .open = aufs_open_nondir,
++ .flush = aufs_flush,
++ .release = aufs_release_nondir,
++ .fsync = aufs_fsync_nondir,
++ .fasync = aufs_fasync,
++ .splice_write = aufs_splice_write,
++ .splice_read = aufs_splice_read
++};
+diff -Naur a/fs/aufs/fstype.h b/fs/aufs/fstype.h
+--- a/fs/aufs/fstype.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/fstype.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,474 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * judging filesystem type
++ */
++
++#ifndef __AUFS_FSTYPE_H__
++#define __AUFS_FSTYPE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/cramfs_fs.h>
++#include <linux/fs.h>
++#include <linux/magic.h>
++#include <linux/romfs_fs.h>
++#include <linux/aufs_type.h>
++
++static inline int au_test_aufs(struct super_block *sb)
++{
++ return sb->s_magic == AUFS_SUPER_MAGIC;
++}
++
++static inline const char *au_sbtype(struct super_block *sb)
++{
++ return sb->s_type->name;
++}
++
++static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
++ return sb->s_magic == ROMFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_romfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
++ return sb->s_magic == ISOFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
++ return sb->s_magic == CRAMFS_MAGIC;
++#endif
++ return 0;
++}
++
++static inline int au_test_nfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++ return sb->s_magic == NFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_fuse(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
++ return sb->s_magic == FUSE_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_xfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
++ return sb->s_magic == XFS_SB_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_TMPFS
++ return sb->s_magic == TMPFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "ecryptfs");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
++ return sb->s_magic == SMB_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
++ return sb->s_magic == OCFS2_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
++ return sb->s_magic == DLMFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_coda(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
++ return sb->s_magic == CODA_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
++ return sb->s_magic == V9FS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ext4(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
++ return sb->s_magic == EXT4_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_sysv(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "sysv");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ramfs(struct super_block *sb)
++{
++ return sb->s_magic == RAMFS_MAGIC;
++}
++
++static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
++ return sb->s_magic == UBIFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_procfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_PROC_FS
++ return sb->s_magic == PROC_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SYSFS
++ return sb->s_magic == SYSFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_configfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
++ return sb->s_magic == CONFIGFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_minix(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
++ return sb->s_magic == MINIX3_SUPER_MAGIC
++ || sb->s_magic == MINIX2_SUPER_MAGIC
++ || sb->s_magic == MINIX2_SUPER_MAGIC2
++ || sb->s_magic == MINIX_SUPER_MAGIC
++ || sb->s_magic == MINIX_SUPER_MAGIC2;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_cifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
++ return sb->s_magic == CIFS_MAGIC_NUMBER;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_fat(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
++ return sb->s_magic == MSDOS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_msdos(struct super_block *sb)
++{
++ return au_test_fat(sb);
++}
++
++static inline int au_test_vfat(struct super_block *sb)
++{
++ return au_test_fat(sb);
++}
++
++static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SECURITYFS
++ return sb->s_magic == SECURITYFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
++ return sb->s_magic == SQUASHFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
++ return sb->s_magic == BTRFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
++ return sb->s_magic == XENFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_DEBUG_FS
++ return sb->s_magic == DEBUGFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * they can't be an aufs branch.
++ */
++static inline int au_test_fs_unsuppoted(struct super_block *sb)
++{
++ return
++#ifndef CONFIG_AUFS_BR_RAMFS
++ au_test_ramfs(sb) ||
++#endif
++ au_test_procfs(sb)
++ || au_test_sysfs(sb)
++ || au_test_configfs(sb)
++ || au_test_debugfs(sb)
++ || au_test_securityfs(sb)
++ || au_test_xenfs(sb)
++ /* || !strcmp(au_sbtype(sb), "unionfs") */
++ || au_test_aufs(sb); /* will be supported in next version */
++}
++
++/*
++ * If the filesystem supports NFS-export, then it has to support NULL as
++ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
++ * We can apply this principle when we handle a lower filesystem.
++ */
++static inline int au_test_fs_null_nd(struct super_block *sb)
++{
++ return !!sb->s_export_op;
++}
++
++static inline int au_test_fs_remote(struct super_block *sb)
++{
++ return !au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ && !au_test_ramfs(sb)
++#endif
++ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * Note: these functions (below) are created after reading ->getattr() in all
++ * filesystems under linux/fs. it means we have to do so in every update...
++ */
++
++/*
++ * some filesystems require getattr to refresh the inode attributes before
++ * referencing.
++ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
++ * and leave the work for d_revalidate()
++ */
++static inline int au_test_fs_refresh_iattr(struct super_block *sb)
++{
++ return au_test_nfs(sb)
++ || au_test_fuse(sb)
++ /* || au_test_smbfs(sb) */ /* untested */
++ /* || au_test_ocfs2(sb) */ /* untested */
++ /* || au_test_btrfs(sb) */ /* untested */
++ /* || au_test_coda(sb) */ /* untested */
++ /* || au_test_v9fs(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which don't maintain i_size or i_blocks.
++ */
++static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
++{
++ return au_test_xfs(sb)
++ /* || au_test_ext4(sb) */ /* untested */
++ /* || au_test_ocfs2(sb) */ /* untested */
++ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
++ /* || au_test_sysv(sb) */ /* untested */
++ /* || au_test_ubifs(sb) */ /* untested */
++ /* || au_test_minix(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which don't store the correct value in some of their inode
++ * attributes.
++ */
++static inline int au_test_fs_bad_iattr(struct super_block *sb)
++{
++ return au_test_fs_bad_iattr_size(sb)
++ /* || au_test_cifs(sb) */ /* untested */
++ || au_test_fat(sb)
++ || au_test_msdos(sb)
++ || au_test_vfat(sb);
++}
++
++/* they don't check i_nlink in link(2) */
++static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
++{
++ return au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ || au_test_ramfs(sb)
++#endif
++ || au_test_ubifs(sb);
++}
++
++/*
++ * filesystems which sets S_NOATIME and S_NOCMTIME.
++ */
++static inline int au_test_fs_notime(struct super_block *sb)
++{
++ return au_test_nfs(sb)
++ || au_test_fuse(sb)
++ || au_test_ubifs(sb)
++ /* || au_test_cifs(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which requires replacing i_mapping.
++ */
++static inline int au_test_fs_bad_mapping(struct super_block *sb)
++{
++ return au_test_fuse(sb)
++ || au_test_ubifs(sb);
++}
++
++/* temporary support for i#1 in cramfs */
++static inline int au_test_fs_unique_ino(struct inode *inode)
++{
++ if (au_test_cramfs(inode->i_sb))
++ return inode->i_ino != 1;
++ return 1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the filesystem where the xino files placed must support i/o after unlink and
++ * maintain i_size and i_blocks.
++ */
++static inline int au_test_fs_bad_xino(struct super_block *sb)
++{
++ return au_test_fs_remote(sb)
++ || au_test_fs_bad_iattr_size(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
++#else
++ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
++#endif
++ /* don't want unnecessary work for xino */
++ || au_test_aufs(sb)
++ || au_test_ecryptfs(sb);
++}
++
++static inline int au_test_fs_trunc_xino(struct super_block *sb)
++{
++ return au_test_tmpfs(sb)
++ || au_test_ramfs(sb);
++}
++
++/*
++ * test if the @sb is real-readonly.
++ */
++static inline int au_test_fs_rr(struct super_block *sb)
++{
++ return au_test_squashfs(sb)
++ || au_test_iso9660(sb)
++ || au_test_cramfs(sb)
++ || au_test_romfs(sb);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FSTYPE_H__ */
+diff -Naur a/fs/aufs/hinotify.c b/fs/aufs/hinotify.c
+--- a/fs/aufs/hinotify.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/hinotify.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,755 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inotify for the lower directories
++ */
++
++#include "aufs.h"
++
++static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
++static struct inotify_handle *au_hin_handle;
++
++AuCacheFuncs(hinotify, HINOTIFY);
++
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++ struct inode *h_inode)
++{
++ int err;
++ struct au_hinotify *hin;
++ s32 wd;
++
++ err = -ENOMEM;
++ hin = au_cache_alloc_hinotify();
++ if (hin) {
++ AuDebugOn(hinode->hi_notify);
++ hinode->hi_notify = hin;
++ hin->hin_aufs_inode = inode;
++
++ inotify_init_watch(&hin->hin_watch);
++ wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
++ AuHinMask);
++ if (wd >= 0)
++ return 0; /* success */
++
++ err = wd;
++ put_inotify_watch(&hin->hin_watch);
++ au_cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++
++ return err;
++}
++
++void au_hin_free(struct au_hinode *hinode)
++{
++ int err;
++ struct au_hinotify *hin;
++
++ hin = hinode->hi_notify;
++ if (hin) {
++ err = 0;
++ if (atomic_read(&hin->hin_watch.count))
++ err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
++ if (unlikely(err))
++ /* it means the watch is already removed */
++ AuWarn("failed inotify_rm_watch() %d\n", err);
++ au_cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_hin_ctl(struct au_hinode *hinode, int do_set)
++{
++ struct inode *h_inode;
++ struct inotify_watch *watch;
++
++ if (!hinode->hi_notify)
++ return;
++
++ h_inode = hinode->hi_inode;
++ IMustLock(h_inode);
++
++ /* todo: try inotify_find_update_watch()? */
++ watch = &hinode->hi_notify->hin_watch;
++ mutex_lock(&h_inode->inotify_mutex);
++ /* mutex_lock(&watch->ih->mutex); */
++ if (do_set) {
++ AuDebugOn(watch->mask & AuHinMask);
++ watch->mask |= AuHinMask;
++ } else {
++ AuDebugOn(!(watch->mask & AuHinMask));
++ watch->mask &= ~AuHinMask;
++ }
++ /* mutex_unlock(&watch->ih->mutex); */
++ mutex_unlock(&h_inode->inotify_mutex);
++}
++
++void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ aufs_bindex_t bindex, bend;
++ struct inode *hi;
++ struct dentry *iwhdentry;
++
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++ hi = au_h_iptr(inode, bindex);
++ if (!hi)
++ continue;
++
++ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
++ iwhdentry = au_hi_wh(inode, bindex);
++ if (iwhdentry)
++ dget(iwhdentry);
++ au_igrab(hi);
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ au_set_h_iptr(inode, bindex, au_igrab(hi),
++ flags & ~AuHi_XINO);
++ iput(hi);
++ dput(iwhdentry);
++ /* mutex_unlock(&hi->i_mutex); */
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int hin_xino(struct inode *inode, struct inode *h_inode)
++{
++ int err;
++ aufs_bindex_t bindex, bend, bfound, bstart;
++ struct inode *h_i;
++
++ err = 0;
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("branch root dir was changed\n");
++ goto out;
++ }
++
++ bfound = -1;
++ bend = au_ibend(inode);
++ bstart = au_ibstart(inode);
++#if 0 /* reserved for future use */
++ if (bindex == bend) {
++ /* keep this ino in rename case */
++ goto out;
++ }
++#endif
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (au_h_iptr(inode, bindex) == h_inode) {
++ bfound = bindex;
++ break;
++ }
++ }
++ if (bfound < 0)
++ goto out;
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ h_i = au_h_iptr(inode, bindex);
++ if (!h_i)
++ continue;
++
++ err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino, 0);
++ /* ignore this error */
++ /* bad action? */
++ }
++
++ /* children inode number will be broken */
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int hin_gen_tree(struct dentry *dentry)
++{
++ int err, i, j, ndentry;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ for (i = 0; i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ if (IS_ROOT(d))
++ continue;
++
++ d_drop(d);
++ au_digen_dec(d);
++ if (d->d_inode)
++ /* todo: reset children xino?
++ cached children only? */
++ au_iigen_dec(d->d_inode);
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++
++ /* discard children */
++ dentry_unhash(dentry);
++ dput(dentry);
++ out:
++ return err;
++}
++
++/*
++ * return 0 if processed.
++ */
++static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
++ const unsigned int isdir)
++{
++ int err;
++ struct dentry *d;
++ struct qstr *dname;
++
++ err = 1;
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("branch root dir was changed\n");
++ err = 0;
++ goto out;
++ }
++
++ if (!isdir) {
++ AuDebugOn(!name);
++ au_iigen_dec(inode);
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias) {
++ dname = &d->d_name;
++ if (dname->len != nlen
++ && memcmp(dname->name, name, nlen))
++ continue;
++ err = 0;
++ spin_lock(&d->d_lock);
++ __d_drop(d);
++ au_digen_dec(d);
++ spin_unlock(&d->d_lock);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ } else {
++ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
++ d = d_find_alias(inode);
++ if (!d) {
++ au_iigen_dec(inode);
++ goto out;
++ }
++
++ dname = &d->d_name;
++ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
++ err = hin_gen_tree(d);
++ dput(d);
++ }
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
++{
++ int err;
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (IS_ROOT(dentry)
++ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
++ ) {
++ AuWarn("branch root dir was changed\n");
++ return 0;
++ }
++
++ err = 0;
++ if (!isdir) {
++ d_drop(dentry);
++ au_digen_dec(dentry);
++ if (inode)
++ au_iigen_dec(inode);
++ } else {
++ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
++ if (inode)
++ err = hin_gen_tree(dentry);
++ }
++
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* hinotify job flags */
++#define AuHinJob_XINO0 1
++#define AuHinJob_GEN (1 << 1)
++#define AuHinJob_DIRENT (1 << 2)
++#define AuHinJob_ISDIR (1 << 3)
++#define AuHinJob_TRYXINO0 (1 << 4)
++#define AuHinJob_MNTPNT (1 << 5)
++#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name)
++#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; }
++#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; }
++
++struct hin_job_args {
++ unsigned int flags;
++ struct inode *inode, *h_inode, *dir, *h_dir;
++ struct dentry *dentry;
++ char *h_name;
++ int h_nlen;
++};
++
++static int hin_job(struct hin_job_args *a)
++{
++ const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
++
++ /* reset xino */
++ if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
++ hin_xino(a->inode, a->h_inode); /* ignore this error */
++
++ if (au_ftest_hinjob(a->flags, TRYXINO0)
++ && a->inode
++ && a->h_inode) {
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ if (!a->h_inode->i_nlink)
++ hin_xino(a->inode, a->h_inode); /* ignore this error */
++ mutex_unlock(&a->h_inode->i_mutex);
++ }
++
++ /* make the generation obsolete */
++ if (au_ftest_hinjob(a->flags, GEN)) {
++ int err = -1;
++ if (a->inode)
++ err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
++ isdir);
++ if (err && a->dentry)
++ hin_gen_by_name(a->dentry, isdir);
++ /* ignore this error */
++ }
++
++ /* make dir entries obsolete */
++ if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
++ struct au_vdir *vdir;
++
++ vdir = au_ivdir(a->inode);
++ if (vdir)
++ vdir->vd_jiffy = 0;
++ /* IMustLock(a->inode); */
++ /* a->inode->i_version++; */
++ }
++
++ /* can do nothing but warn */
++ if (au_ftest_hinjob(a->flags, MNTPNT)
++ && a->dentry
++ && d_mountpoint(a->dentry))
++ AuWarn("mount-point %.*s is removed or renamed\n",
++ AuDLNPair(a->dentry));
++
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static char *in_name(u32 mask)
++{
++#ifdef CONFIG_AUFS_DEBUG
++#define test_ret(flag) if (mask & flag) \
++ return #flag;
++ test_ret(IN_ACCESS);
++ test_ret(IN_MODIFY);
++ test_ret(IN_ATTRIB);
++ test_ret(IN_CLOSE_WRITE);
++ test_ret(IN_CLOSE_NOWRITE);
++ test_ret(IN_OPEN);
++ test_ret(IN_MOVED_FROM);
++ test_ret(IN_MOVED_TO);
++ test_ret(IN_CREATE);
++ test_ret(IN_DELETE);
++ test_ret(IN_DELETE_SELF);
++ test_ret(IN_MOVE_SELF);
++ test_ret(IN_UNMOUNT);
++ test_ret(IN_Q_OVERFLOW);
++ test_ret(IN_IGNORED);
++ return "";
++#undef test_ret
++#else
++ return "??";
++#endif
++}
++
++static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
++ struct inode *dir)
++{
++ struct dentry *dentry, *d, *parent;
++ struct qstr *dname;
++
++ parent = d_find_alias(dir);
++ if (!parent)
++ return NULL;
++
++ dentry = NULL;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
++ /* AuDbg("%.*s\n", AuDLNPair(d)); */
++ dname = &d->d_name;
++ if (dname->len != nlen || memcmp(dname->name, name, nlen))
++ continue;
++ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
++ spin_lock(&d->d_lock);
++ __d_drop(d);
++ spin_unlock(&d->d_lock);
++ continue;
++ }
++
++ dentry = dget(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ dput(parent);
++
++ if (dentry)
++ di_write_lock_child(dentry);
++
++ return dentry;
++}
++
++static struct inode *lookup_wlock_by_ino(struct super_block *sb,
++ aufs_bindex_t bindex, ino_t h_ino)
++{
++ struct inode *inode;
++ ino_t ino;
++ int err;
++
++ inode = NULL;
++ err = au_xino_read(sb, bindex, h_ino, &ino);
++ if (!err && ino)
++ inode = ilookup(sb, ino);
++ if (!inode)
++ goto out;
++
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("wrong root branch\n");
++ iput(inode);
++ inode = NULL;
++ goto out;
++ }
++
++ ii_write_lock_child(inode);
++
++ out:
++ return inode;
++}
++
++enum { CHILD, PARENT };
++struct postproc_args {
++ struct inode *h_dir, *dir, *h_child_inode;
++ u32 mask;
++ unsigned int flags[2];
++ unsigned int h_child_nlen;
++ char h_child_name[];
++};
++
++static void postproc(void *_args)
++{
++ struct postproc_args *a = _args;
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend, bfound;
++ unsigned char xino, try_iput;
++ int err;
++ struct inode *inode;
++ ino_t h_ino;
++ struct hin_job_args args;
++ struct dentry *dentry;
++ struct au_sbinfo *sbinfo;
++
++ AuDebugOn(!_args);
++ AuDebugOn(!a->h_dir);
++ AuDebugOn(!a->dir);
++ AuDebugOn(!a->mask);
++ AuDbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++
++ inode = NULL;
++ dentry = NULL;
++ /*
++ * do not lock a->dir->i_mutex here
++ * because of d_revalidate() may cause a deadlock.
++ */
++ sb = a->dir->i_sb;
++ AuDebugOn(!sb);
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!sbinfo);
++ /* big aufs lock */
++ si_noflush_write_lock(sb);
++
++ ii_read_lock_parent(a->dir);
++ bfound = -1;
++ bend = au_ibend(a->dir);
++ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
++ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
++ bfound = bindex;
++ break;
++ }
++ ii_read_unlock(a->dir);
++ if (unlikely(bfound < 0))
++ goto out;
++
++ xino = !!au_opt_test(au_mntflags(sb), XINO);
++ h_ino = 0;
++ if (a->h_child_inode)
++ h_ino = a->h_child_inode->i_ino;
++
++ if (a->h_child_nlen
++ && (au_ftest_hinjob(a->flags[CHILD], GEN)
++ || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
++ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
++ a->dir);
++ try_iput = 0;
++ if (dentry)
++ inode = dentry->d_inode;
++ if (xino && !inode && h_ino
++ && (au_ftest_hinjob(a->flags[CHILD], XINO0)
++ || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
++ || au_ftest_hinjob(a->flags[CHILD], GEN))) {
++ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
++ try_iput = 1;
++ }
++
++ args.flags = a->flags[CHILD];
++ args.dentry = dentry;
++ args.inode = inode;
++ args.h_inode = a->h_child_inode;
++ args.dir = a->dir;
++ args.h_dir = a->h_dir;
++ args.h_name = a->h_child_name;
++ args.h_nlen = a->h_child_nlen;
++ err = hin_job(&args);
++ if (dentry) {
++ if (dentry->d_fsdata)
++ di_write_unlock(dentry);
++ dput(dentry);
++ }
++ if (inode && try_iput) {
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++
++ ii_write_lock_parent(a->dir);
++ args.flags = a->flags[PARENT];
++ args.dentry = NULL;
++ args.inode = a->dir;
++ args.h_inode = a->h_dir;
++ args.dir = NULL;
++ args.h_dir = NULL;
++ args.h_name = NULL;
++ args.h_nlen = 0;
++ err = hin_job(&args);
++ ii_write_unlock(a->dir);
++
++ out:
++ au_nwt_done(&sbinfo->si_nowait);
++ si_write_unlock(sb);
++
++ iput(a->h_child_inode);
++ iput(a->h_dir);
++ iput(a->dir);
++ kfree(a);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
++ u32 mask, u32 cookie __maybe_unused,
++ const char *h_child_name, struct inode *h_child_inode)
++{
++ struct au_hinotify *hinotify;
++ struct postproc_args *args;
++ int len, wkq_err;
++ unsigned char isdir, isroot, wh;
++ char *p;
++ struct inode *dir;
++ unsigned int flags[2];
++
++ /* if IN_UNMOUNT happens, there must be another bug */
++ AuDebugOn(mask & IN_UNMOUNT);
++ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++ put_inotify_watch(watch);
++ return;
++ }
++#ifdef AuDbgHinotify
++ au_debug(1);
++ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
++ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
++ " hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++ WARN_ON(1);
++ }
++ au_debug(0);
++#endif
++
++ hinotify = container_of(watch, struct au_hinotify, hin_watch);
++ AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
++ dir = igrab(hinotify->hin_aufs_inode);
++ if (!dir)
++ return;
++
++ isroot = (dir->i_ino == AUFS_ROOT_INO);
++ len = 0;
++ wh = 0;
++ if (h_child_name) {
++ len = strlen(h_child_name);
++ if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ h_child_name += AUFS_WH_PFX_LEN;
++ len -= AUFS_WH_PFX_LEN;
++ wh = 1;
++ }
++ }
++
++ isdir = 0;
++ if (h_child_inode)
++ isdir = !!S_ISDIR(h_child_inode->i_mode);
++ flags[PARENT] = AuHinJob_ISDIR;
++ flags[CHILD] = 0;
++ if (isdir)
++ flags[CHILD] = AuHinJob_ISDIR;
++ switch (mask & IN_ALL_EVENTS) {
++ case IN_MOVED_FROM:
++ case IN_MOVED_TO:
++ AuDebugOn(!h_child_name || !h_child_inode);
++ au_fset_hinjob(flags[CHILD], GEN);
++ au_fset_hinjob(flags[CHILD], XINO0);
++ au_fset_hinjob(flags[CHILD], MNTPNT);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ break;
++
++ case IN_CREATE:
++ AuDebugOn(!h_child_name || !h_child_inode);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ au_fset_hinjob(flags[CHILD], GEN);
++ break;
++
++ case IN_DELETE:
++ /*
++ * aufs never be able to get this child inode.
++ * revalidation should be in d_revalidate()
++ * by checking i_nlink, i_generation or d_unhashed().
++ */
++ AuDebugOn(!h_child_name);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ au_fset_hinjob(flags[CHILD], GEN);
++ au_fset_hinjob(flags[CHILD], TRYXINO0);
++ au_fset_hinjob(flags[CHILD], MNTPNT);
++ break;
++
++ default:
++ AuDebugOn(1);
++ }
++
++ if (wh)
++ h_child_inode = NULL;
++
++ /* iput() and kfree() will be called in postproc() */
++ /*
++ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
++ * iprune_mutex. strange.
++ */
++ lockdep_off();
++ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
++ lockdep_on();
++ if (unlikely(!args)) {
++ AuErr1("no memory\n");
++ iput(dir);
++ return;
++ }
++ args->flags[PARENT] = flags[PARENT];
++ args->flags[CHILD] = flags[CHILD];
++ args->mask = mask;
++ args->dir = dir;
++ args->h_dir = igrab(watch->inode);
++ if (h_child_inode)
++ h_child_inode = igrab(h_child_inode); /* can be NULL */
++ args->h_child_inode = h_child_inode;
++ args->h_child_nlen = len;
++ if (len) {
++ p = (void *)args;
++ p += sizeof(*args);
++ memcpy(p, h_child_name, len + 1);
++ }
++
++ lockdep_off();
++ wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
++ lockdep_on();
++ if (unlikely(wkq_err))
++ AuErr("wkq %d\n", wkq_err);
++}
++
++static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
++{
++ return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++ .handle_event = aufs_inotify,
++ .destroy_watch = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++static void au_hin_destroy_cache(void)
++{
++ kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
++ au_cachep[AuCache_HINOTIFY] = NULL;
++}
++
++int __init au_hinotify_init(void)
++{
++ int err;
++
++ err = -ENOMEM;
++ au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
++ if (au_cachep[AuCache_HINOTIFY]) {
++ err = 0;
++ au_hin_handle = inotify_init(&aufs_inotify_ops);
++ if (IS_ERR(au_hin_handle)) {
++ err = PTR_ERR(au_hin_handle);
++ au_hin_destroy_cache();
++ }
++ }
++ AuTraceErr(err);
++ return err;
++}
++
++void au_hinotify_fin(void)
++{
++ inotify_destroy(au_hin_handle);
++ if (au_cachep[AuCache_HINOTIFY])
++ au_hin_destroy_cache();
++}
+diff -Naur a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
+--- a/fs/aufs/iinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/iinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,271 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode private data
++ */
++
++#include "aufs.h"
++
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct inode *h_inode;
++
++ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++ return h_inode;
++}
++
++/* todo: hard/soft set? */
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct au_iinfo *iinfo = au_ii(inode);
++ struct inode *h_inode;
++
++ iinfo->ii_bstart = bindex;
++ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
++ if (h_inode)
++ au_cpup_igen(inode, h_inode);
++}
++
++void au_hiput(struct au_hinode *hinode)
++{
++ au_hin_free(hinode);
++ dput(hinode->hi_whdentry);
++ iput(hinode->hi_inode);
++}
++
++unsigned int au_hi_flags(struct inode *inode, int isdir)
++{
++ unsigned int flags;
++ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
++
++ flags = 0;
++ if (au_opt_test(mnt_flags, XINO))
++ au_fset_hi(flags, XINO);
++ if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
++ au_fset_hi(flags, HINOTIFY);
++ return flags;
++}
++
++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags)
++{
++ struct au_hinode *hinode;
++ struct inode *hi;
++ struct au_iinfo *iinfo = au_ii(inode);
++
++ hinode = iinfo->ii_hinode + bindex;
++ hi = hinode->hi_inode;
++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++ AuDebugOn(h_inode && hi);
++
++ if (hi)
++ au_hiput(hinode);
++ hinode->hi_inode = h_inode;
++ if (h_inode) {
++ int err;
++ struct super_block *sb = inode->i_sb;
++ struct au_branch *br;
++
++ if (bindex == iinfo->ii_bstart)
++ au_cpup_igen(inode, h_inode);
++ br = au_sbr(sb, bindex);
++ hinode->hi_id = br->br_id;
++ if (au_ftest_hi(flags, XINO)) {
++ err = au_xino_write(sb, bindex, h_inode->i_ino,
++ inode->i_ino);
++ if (unlikely(err))
++ AuIOErr1("failed au_xino_write() %d\n", err);
++ }
++
++ if (au_ftest_hi(flags, HINOTIFY)
++ && au_br_hinotifyable(br->br_perm)) {
++ err = au_hin_alloc(hinode, inode, h_inode);
++ if (unlikely(err))
++ AuIOErr1("au_hin_alloc() %d\n", err);
++ }
++ }
++}
++
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_wh)
++{
++ struct au_hinode *hinode;
++
++ hinode = au_ii(inode)->ii_hinode + bindex;
++ AuDebugOn(hinode->hi_whdentry);
++ hinode->hi_whdentry = h_wh;
++}
++
++void au_update_iigen(struct inode *inode)
++{
++ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++/* it may be called at remount time, too */
++void au_update_brange(struct inode *inode, int do_put_zero)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = au_ii(inode);
++ if (!iinfo || iinfo->ii_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex;
++
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++) {
++ struct inode *h_i;
++
++ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
++ if (h_i && !h_i->i_nlink)
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ }
++ }
++
++ iinfo->ii_bstart = -1;
++ while (++iinfo->ii_bstart <= iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
++ break;
++ if (iinfo->ii_bstart > iinfo->ii_bend) {
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ return;
++ }
++
++ iinfo->ii_bend++;
++ while (0 <= --iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
++ break;
++ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_iinfo_init(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++ struct super_block *sb;
++ int nbr, i;
++
++ sb = inode->i_sb;
++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++ nbr = au_sbend(sb) + 1;
++ if (unlikely(nbr <= 0))
++ nbr = 1;
++ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
++ if (iinfo->ii_hinode) {
++ for (i = 0; i < nbr; i++)
++ iinfo->ii_hinode[i].hi_id = -1;
++
++ atomic_set(&iinfo->ii_generation, au_sigen(sb));
++ /* smp_mb(); */ /* atomic_set */
++ init_rwsem(&iinfo->ii_rwsem);
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ iinfo->ii_vdir = NULL;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
++{
++ int err, sz;
++ struct au_hinode *hip;
++
++ err = -ENOMEM;
++ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
++ if (!sz)
++ sz = sizeof(*hip);
++ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
++ if (hip) {
++ iinfo->ii_hinode = hip;
++ err = 0;
++ }
++
++ return err;
++}
++
++static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
++ ino_t ino)
++{
++ int err;
++ aufs_bindex_t bindex;
++ unsigned char locked;
++
++ err = 0;
++ locked = !!si_noflush_read_trylock(sb);
++ bindex = au_br_index(sb, hinode->hi_id);
++ if (bindex >= 0)
++ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
++ /* error action? */
++ if (locked)
++ si_read_unlock(sb);
++ return err;
++}
++
++void au_iinfo_fin(struct inode *inode)
++{
++ ino_t ino;
++ aufs_bindex_t bend;
++ unsigned char unlinked = !inode->i_nlink;
++ struct au_iinfo *iinfo;
++ struct au_hinode *hi;
++ struct super_block *sb;
++
++ if (unlinked) {
++ int err = au_xigen_inc(inode);
++ if (unlikely(err))
++ AuWarn1("failed resetting i_generation, %d\n", err);
++ }
++
++ iinfo = au_ii(inode);
++ /* bad_inode case */
++ if (!iinfo)
++ return;
++
++ if (iinfo->ii_vdir)
++ au_vdir_free(iinfo->ii_vdir);
++
++ if (iinfo->ii_bstart >= 0) {
++ sb = inode->i_sb;
++ ino = 0;
++ if (unlinked)
++ ino = inode->i_ino;
++ hi = iinfo->ii_hinode + iinfo->ii_bstart;
++ bend = iinfo->ii_bend;
++ while (iinfo->ii_bstart++ <= bend) {
++ if (hi->hi_inode) {
++ if (unlinked || !hi->hi_inode->i_nlink) {
++ au_iinfo_write0(sb, hi, ino);
++ /* ignore this error */
++ ino = 0;
++ }
++ au_hiput(hi);
++ }
++ hi++;
++ }
++ }
++
++ kfree(iinfo->ii_hinode);
++ au_rwsem_destroy(&iinfo->ii_rwsem);
++}
+diff -Naur a/fs/aufs/inode.c b/fs/aufs/inode.c
+--- a/fs/aufs/inode.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,376 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode functions
++ */
++
++#include "aufs.h"
++
++struct inode *au_igrab(struct inode *inode)
++{
++ if (inode) {
++ AuDebugOn(!atomic_read(&inode->i_count));
++ atomic_inc(&inode->i_count);
++ }
++ return inode;
++}
++
++static void au_refresh_hinode_attr(struct inode *inode, int do_version)
++{
++ au_cpup_attr_all(inode, /*force*/0);
++ au_update_iigen(inode);
++ if (do_version)
++ inode->i_version++;
++}
++
++int au_refresh_hinode_self(struct inode *inode, int do_attr)
++{
++ int err;
++ aufs_bindex_t bindex, new_bindex;
++ unsigned char update;
++ struct inode *first;
++ struct au_hinode *p, *q, tmp;
++ struct super_block *sb;
++ struct au_iinfo *iinfo;
++
++ update = 0;
++ sb = inode->i_sb;
++ iinfo = au_ii(inode);
++ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
++ if (unlikely(err))
++ goto out;
++
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ err = 0;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++, p++) {
++ if (!p->hi_inode)
++ continue;
++
++ new_bindex = au_br_index(sb, p->hi_id);
++ if (new_bindex == bindex)
++ continue;
++
++ if (new_bindex < 0) {
++ update++;
++ au_hiput(p);
++ p->hi_inode = NULL;
++ continue;
++ }
++
++ if (new_bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = new_bindex;
++ if (iinfo->ii_bend < new_bindex)
++ iinfo->ii_bend = new_bindex;
++ /* swap two lower inode, and loop again */
++ q = iinfo->ii_hinode + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hi_inode) {
++ bindex--;
++ p--;
++ }
++ }
++ au_update_brange(inode, /*do_put_zero*/0);
++ if (do_attr)
++ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
++
++ out:
++ return err;
++}
++
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
++{
++ int err, update;
++ unsigned int flags;
++ aufs_bindex_t bindex, bend;
++ unsigned char isdir;
++ struct inode *first;
++ struct au_hinode *p;
++ struct au_iinfo *iinfo;
++
++ err = au_refresh_hinode_self(inode, /*do_attr*/0);
++ if (unlikely(err))
++ goto out;
++
++ update = 0;
++ iinfo = au_ii(inode);
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ isdir = S_ISDIR(inode->i_mode);
++ flags = au_hi_flags(inode, isdir);
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++ struct inode *h_i;
++ struct dentry *h_d;
++
++ h_d = au_h_dptr(dentry, bindex);
++ if (!h_d || !h_d->d_inode)
++ continue;
++
++ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
++ h_i = au_h_iptr(inode, bindex);
++ if (h_i) {
++ if (h_i == h_d->d_inode)
++ continue;
++ err = -EIO;
++ break;
++ }
++ }
++ if (bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = bindex;
++ if (iinfo->ii_bend < bindex)
++ iinfo->ii_bend = bindex;
++ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
++ update = 1;
++ }
++ au_update_brange(inode, /*do_put_zero*/0);
++
++ if (unlikely(err))
++ goto out;
++
++ au_refresh_hinode_attr(inode, update && isdir);
++
++ out:
++ return err;
++}
++
++static int set_inode(struct inode *inode, struct dentry *dentry)
++{
++ int err;
++ unsigned int flags;
++ umode_t mode;
++ aufs_bindex_t bindex, bstart, btail;
++ unsigned char isdir;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct au_iinfo *iinfo;
++
++ err = 0;
++ isdir = 0;
++ bstart = au_dbstart(dentry);
++ h_inode = au_h_dptr(dentry, bstart)->d_inode;
++ mode = h_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_iop;
++ inode->i_fop = &aufs_file_fop;
++ inode->i_mapping->a_ops = &aufs_aop;
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ btail = au_dbtaildir(dentry);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ break;
++ case S_IFLNK:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_symlink_iop;
++ break;
++ case S_IFBLK:
++ case S_IFCHR:
++ case S_IFIFO:
++ case S_IFSOCK:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_iop;
++ init_special_inode(inode, mode, h_inode->i_rdev);
++ break;
++ default:
++ AuIOErr("Unknown file type 0%o\n", mode);
++ err = -EIO;
++ goto out;
++ }
++
++ /* do not set inotify for whiteouted dirs (SHWH mode) */
++ flags = au_hi_flags(inode, isdir);
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
++ && au_ftest_hi(flags, HINOTIFY)
++ && dentry->d_name.len > AUFS_WH_PFX_LEN
++ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
++ au_fclr_hi(flags, HINOTIFY);
++ iinfo = au_ii(inode);
++ iinfo->ii_bstart = bstart;
++ iinfo->ii_bend = btail;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry)
++ au_set_h_iptr(inode, bindex,
++ au_igrab(h_dentry->d_inode), flags);
++ }
++ au_cpup_attr_all(inode, /*force*/1);
++
++ out:
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct inode *h_inode, *h_dinode;
++
++ *matched = 0;
++
++ /*
++ * before this function, if aufs got any iinfo lock, it must be only
++ * one, the parent dir.
++ * it can happen by UDBA and the obsoleted inode number.
++ */
++ err = -EIO;
++ if (unlikely(inode->i_ino == parent_ino(dentry)))
++ goto out;
++
++ err = 0;
++ ii_write_lock_new_child(inode);
++ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode && h_inode == h_dinode) {
++ *matched = 1;
++ err = 0;
++ if (au_iigen(inode) != au_digen(dentry))
++ err = au_refresh_hinode(inode, dentry);
++ break;
++ }
++ }
++
++ if (unlikely(err))
++ ii_write_unlock(inode);
++ out:
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++/* todo: return with unlocked? */
++struct inode *au_new_inode(struct dentry *dentry, int must_new)
++{
++ struct inode *inode;
++ struct dentry *h_dentry;
++ struct super_block *sb;
++ ino_t h_ino, ino;
++ int err, match;
++ aufs_bindex_t bstart;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ h_dentry = au_h_dptr(dentry, bstart);
++ h_ino = h_dentry->d_inode->i_ino;
++ err = au_xino_read(sb, bstart, h_ino, &ino);
++ inode = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++ new_ino:
++ if (!ino) {
++ ino = au_xino_new_ino(sb);
++ if (unlikely(!ino)) {
++ inode = ERR_PTR(-EIO);
++ goto out;
++ }
++ }
++
++ AuDbg("i%lu\n", (unsigned long)ino);
++ inode = au_iget_locked(sb, ino);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++
++ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
++ if (inode->i_state & I_NEW) {
++ ii_write_lock_new_child(inode);
++ err = set_inode(inode, dentry);
++ unlock_new_inode(inode);
++ if (!err)
++ goto out; /* success */
++
++ iget_failed(inode);
++ ii_write_unlock(inode);
++ goto out_iput;
++ } else if (!must_new) {
++ err = reval_inode(inode, dentry, &match);
++ if (!err)
++ goto out; /* success */
++ else if (match)
++ goto out_iput;
++ }
++
++ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
++ AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
++ " b%d, %s, %.*s, hi%lu, i%lu.\n",
++ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
++ (unsigned long)h_ino, (unsigned long)ino);
++ ino = 0;
++ err = au_xino_write0(sb, bstart, h_ino, 0);
++ if (!err) {
++ iput(inode);
++ goto new_ino;
++ }
++
++ out_iput:
++ iput(inode);
++ inode = ERR_PTR(err);
++ out:
++ return inode;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode)
++{
++ int err;
++
++ err = au_br_rdonly(au_sbr(sb, bindex));
++
++ /* pseudo-link after flushed may happen out of bounds */
++ if (!err
++ && inode
++ && au_ibstart(inode) <= bindex
++ && bindex <= au_ibend(inode)) {
++ /*
++ * permission check is unnecessary since vfsub routine
++ * will be called later
++ */
++ struct inode *hi = au_h_iptr(inode, bindex);
++ if (hi)
++ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
++ }
++
++ return err;
++}
++
++int au_test_h_perm(struct inode *h_inode, int mask)
++{
++ if (!current_fsuid())
++ return 0;
++ return inode_permission(h_inode, mask);
++}
++
++int au_test_h_perm_sio(struct inode *h_inode, int mask)
++{
++ if (au_test_nfs(h_inode->i_sb)
++ && (mask & MAY_WRITE)
++ && S_ISDIR(h_inode->i_mode))
++ mask |= MAY_READ; /* force permission check */
++ return au_test_h_perm(h_inode, mask);
++}
+diff -Naur a/fs/aufs/inode.h b/fs/aufs/inode.h
+--- a/fs/aufs/inode.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,473 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations
++ */
++
++#ifndef __AUFS_INODE_H__
++#define __AUFS_INODE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/inotify.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct vfsmount;
++
++struct au_hinotify {
++#ifdef CONFIG_AUFS_HINOTIFY
++ struct inotify_watch hin_watch;
++ struct inode *hin_aufs_inode; /* no get/put */
++#endif
++};
++
++struct au_hinode {
++ struct inode *hi_inode;
++ aufs_bindex_t hi_id;
++#ifdef CONFIG_AUFS_HINOTIFY
++ struct au_hinotify *hi_notify;
++#endif
++
++ /* reference to the copied-up whiteout with get/put */
++ struct dentry *hi_whdentry;
++};
++
++struct au_vdir;
++struct au_iinfo {
++ atomic_t ii_generation;
++ struct super_block *ii_hsb1; /* no get/put */
++
++ struct rw_semaphore ii_rwsem;
++ aufs_bindex_t ii_bstart, ii_bend;
++ __u32 ii_higen;
++ struct au_hinode *ii_hinode;
++ struct au_vdir *ii_vdir;
++};
++
++struct au_icntnr {
++ struct au_iinfo iinfo;
++ struct inode vfs_inode;
++};
++
++/* au_pin flags */
++#define AuPin_DI_LOCKED 1
++#define AuPin_MNT_WRITE (1 << 1)
++#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
++#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
++#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
++
++struct au_pin {
++ /* input */
++ struct dentry *dentry;
++ unsigned int udba;
++ unsigned char lsc_di, lsc_hi, flags;
++ aufs_bindex_t bindex;
++
++ /* output */
++ struct dentry *parent;
++ struct au_hinode *hdir;
++ struct vfsmount *h_mnt;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_iinfo *au_ii(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++ if (iinfo->ii_hinode)
++ return iinfo;
++ return NULL; /* debugging bad_inode case */
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* inode.c */
++struct inode *au_igrab(struct inode *inode);
++int au_refresh_hinode_self(struct inode *inode, int do_attr);
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
++struct inode *au_new_inode(struct dentry *dentry, int must_new);
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode);
++int au_test_h_perm(struct inode *h_inode, int mask);
++int au_test_h_perm_sio(struct inode *h_inode, int mask);
++
++/* i_op.c */
++extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
++
++/* au_wr_dir flags */
++#define AuWrDir_ADD_ENTRY 1
++#define AuWrDir_ISDIR (1 << 1)
++#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
++#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
++#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
++
++struct au_wr_dir_args {
++ aufs_bindex_t force_btgt;
++ unsigned char flags;
++};
++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++ struct au_wr_dir_args *args);
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin);
++void au_pin_init(struct au_pin *pin, struct dentry *dentry,
++ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++ unsigned int udba, unsigned char flags);
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int udba, unsigned char flags) __must_check;
++int au_do_pin(struct au_pin *pin) __must_check;
++void au_unpin(struct au_pin *pin);
++
++/* i_op_add.c */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir);
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd);
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry);
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++
++/* i_op_del.c */
++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir);
++int aufs_unlink(struct inode *dir, struct dentry *dentry);
++int aufs_rmdir(struct inode *dir, struct dentry *dentry);
++
++/* i_op_ren.c */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry);
++
++/* iinfo.c */
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
++void au_hiput(struct au_hinode *hinode);
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_wh);
++unsigned int au_hi_flags(struct inode *inode, int isdir);
++
++/* hinode flags */
++#define AuHi_XINO 1
++#define AuHi_HINOTIFY (1 << 1)
++#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
++#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
++#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuHi_HINOTIFY
++#define AuHi_HINOTIFY 0
++#endif
++
++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags);
++
++void au_update_iigen(struct inode *inode);
++void au_update_brange(struct inode *inode, int do_put_zero);
++
++int au_iinfo_init(struct inode *inode);
++void au_iinfo_fin(struct inode *inode);
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
++
++/* plink.c */
++void au_plink_block_maintain(struct super_block *sb);
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb);
++#else
++static inline void au_plink_list(struct super_block *sb)
++{
++ /* nothing */
++}
++#endif
++int au_plink_test(struct inode *inode);
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++void au_plink_put(struct super_block *sb);
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for iinfo */
++enum {
++ AuLsc_II_CHILD, /* child first */
++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_II_CHILD3, /* copyup dirs */
++ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
++ AuLsc_II_PARENT2,
++ AuLsc_II_PARENT3, /* copyup dirs */
++ AuLsc_II_NEW_CHILD
++};
++
++/*
++ * ii_read_lock_child, ii_write_lock_child,
++ * ii_read_lock_child2, ii_write_lock_child2,
++ * ii_read_lock_child3, ii_write_lock_child3,
++ * ii_read_lock_parent, ii_write_lock_parent,
++ * ii_read_lock_parent2, ii_write_lock_parent2,
++ * ii_read_lock_parent3, ii_write_lock_parent3,
++ * ii_read_lock_new_child, ii_write_lock_new_child,
++ */
++#define AuReadLockFunc(name, lsc) \
++static inline void ii_read_lock_##name(struct inode *i) \
++{ \
++ down_read_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void ii_write_lock_##name(struct inode *i) \
++{ \
++ down_write_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuRWLockFuncs(name, lsc) \
++ AuReadLockFunc(name, lsc) \
++ AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++AuRWLockFuncs(new_child, NEW_CHILD);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++/*
++ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
++ */
++AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
++
++#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++static inline unsigned int au_iigen(struct inode *inode)
++{
++ return atomic_read(&au_ii(inode)->ii_generation);
++}
++
++/* tiny test for inode number */
++/* tmpfs generation is too rough */
++static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = au_ii(inode);
++ return !(iinfo->ii_hsb1 == h_inode->i_sb
++ && iinfo->ii_higen == h_inode->i_generation);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
++}
++
++static inline aufs_bindex_t au_ibstart(struct inode *inode)
++{
++ return au_ii(inode)->ii_bstart;
++}
++
++static inline aufs_bindex_t au_ibend(struct inode *inode)
++{
++ return au_ii(inode)->ii_bend;
++}
++
++static inline struct au_vdir *au_ivdir(struct inode *inode)
++{
++ return au_ii(inode)->ii_vdir;
++}
++
++static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
++}
++
++static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
++{
++ au_ii(inode)->ii_bend = bindex;
++}
++
++static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
++{
++ au_ii(inode)->ii_vdir = vdir;
++}
++
++static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode + bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_pinned_parent(struct au_pin *pin)
++{
++ if (pin)
++ return pin->parent;
++ return NULL;
++}
++
++static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
++{
++ if (pin && pin->hdir)
++ return pin->hdir->hi_inode;
++ return NULL;
++}
++
++static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
++{
++ if (pin)
++ return pin->hdir;
++ return NULL;
++}
++
++static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
++{
++ if (pin)
++ pin->dentry = dentry;
++}
++
++static inline void au_pin_set_parent_lflag(struct au_pin *pin,
++ unsigned char lflag)
++{
++ if (pin) {
++ /* dirty macros require brackets */
++ if (lflag) {
++ au_fset_pin(pin->flags, DI_LOCKED);
++ } else {
++ au_fclr_pin(pin->flags, DI_LOCKED);
++ }
++ }
++}
++
++static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
++{
++ if (pin) {
++ dput(pin->parent);
++ pin->parent = dget(parent);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++/* hinotify.c */
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++ struct inode *h_inode);
++void au_hin_free(struct au_hinode *hinode);
++void au_hin_ctl(struct au_hinode *hinode, int do_set);
++void au_reset_hinotify(struct inode *inode, unsigned int flags);
++
++int __init au_hinotify_init(void);
++void au_hinotify_fin(void);
++
++static inline
++void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
++{
++ hinode->hi_notify = val;
++}
++
++static inline void au_iigen_dec(struct inode *inode)
++{
++ atomic_dec(&au_ii(inode)->ii_generation);
++}
++
++#else
++static inline
++int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
++ struct inode *inode __maybe_unused,
++ struct inode *h_inode __maybe_unused)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
++ int do_set __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
++ unsigned int flags __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline int au_hinotify_init(void)
++{
++ return 0;
++}
++
++#define au_hinotify_fin() do {} while (0)
++
++static inline
++void au_hin_init(struct au_hinode *hinode __maybe_unused,
++ struct au_hinotify *val __maybe_unused)
++{
++ /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++static inline void au_hin_suspend(struct au_hinode *hdir)
++{
++ au_hin_ctl(hdir, /*do_set*/0);
++}
++
++static inline void au_hin_resume(struct au_hinode *hdir)
++{
++ au_hin_ctl(hdir, /*do_set*/1);
++}
++
++static inline void au_hin_imtx_lock(struct au_hinode *hdir)
++{
++ mutex_lock(&hdir->hi_inode->i_mutex);
++ au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
++ unsigned int sc __maybe_unused)
++{
++ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
++ au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
++{
++ au_hin_resume(hdir);
++ mutex_unlock(&hdir->hi_inode->i_mutex);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_INODE_H__ */
+diff -Naur a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c
+--- a/fs/aufs/ioctl.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/ioctl.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,68 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * ioctl
++ * currently plink-management only.
++ */
++
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++long aufs_ioctl_dir(struct file *file, unsigned int cmd,
++ unsigned long arg __maybe_unused)
++{
++ long err;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ err = -EACCES;
++ if (!capable(CAP_SYS_ADMIN))
++ goto out;
++
++ err = 0;
++ sb = file->f_dentry->d_sb;
++ sbinfo = au_sbi(sb);
++ switch (cmd) {
++ case AUFS_CTL_PLINK_MAINT:
++ /*
++ * pseudo-link maintenance mode,
++ * cleared by aufs_release_dir()
++ */
++ si_write_lock(sb);
++ if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
++ au_fset_si(sbinfo, MAINTAIN_PLINK);
++ au_fi(file)->fi_maintain_plink = 1;
++ } else
++ err = -EBUSY;
++ si_write_unlock(sb);
++ break;
++ case AUFS_CTL_PLINK_CLEAN:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) {
++ aufs_write_lock(sb->s_root);
++ au_plink_put(sb);
++ aufs_write_unlock(sb->s_root);
++ }
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
+--- a/fs/aufs/i_op_add.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_add.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,638 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (add entry)
++ */
++
++#include "aufs.h"
++
++/*
++ * final procedure of adding a new entry, except link(2).
++ * remove whiteout, instantiate, copyup the parent dir's times and size
++ * and update version.
++ * if it failed, re-create the removed whiteout.
++ */
++static int epilog(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct dentry *dentry)
++{
++ int err, rerr;
++ aufs_bindex_t bwh;
++ struct path h_path;
++ struct inode *inode, *h_dir;
++ struct dentry *wh;
++
++ bwh = -1;
++ if (wh_dentry) {
++ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(h_dir);
++ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
++ bwh = au_dbwh(dentry);
++ h_path.dentry = wh_dentry;
++ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
++ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
++ dentry);
++ if (unlikely(err))
++ goto out;
++ }
++
++ inode = au_new_inode(dentry, /*must_new*/1);
++ if (!IS_ERR(inode)) {
++ d_instantiate(dentry, inode);
++ dir = dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(dir);
++ if (au_ibstart(dir) == au_dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++ return 0; /* success */
++ }
++
++ err = PTR_ERR(inode);
++ if (!wh_dentry)
++ goto out;
++
++ /* revert */
++ /* dir inode is locked */
++ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
++ rerr = PTR_ERR(wh);
++ if (IS_ERR(wh)) {
++ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ } else
++ dput(wh);
++
++ out:
++ return err;
++}
++
++/*
++ * simple tests for the adding inode operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir)
++{
++ int err;
++ umode_t h_mode;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ if (!dentry->d_inode) {
++ err = -EEXIST;
++ if (unlikely(h_inode))
++ goto out;
++ } else {
++ /* rename(2) case */
++ err = -EIO;
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++
++ h_mode = h_inode->i_mode;
++ if (!isdir) {
++ err = -EISDIR;
++ if (unlikely(S_ISDIR(h_mode)))
++ goto out;
++ } else if (unlikely(!S_ISDIR(h_mode))) {
++ err = -ENOTDIR;
++ goto out;
++ }
++ }
++
++ err = -EIO;
++ /* expected parent dir is locked */
++ if (unlikely(h_parent != h_dentry->d_parent))
++ goto out;
++ err = 0;
++
++ out:
++ return err;
++}
++
++/*
++ * initial procedure of adding a new entry.
++ * prepare writable branch and the parent dir, lock it,
++ * and lookup whiteout for the new entry.
++ */
++static struct dentry*
++lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
++ struct dentry *src_dentry, struct au_pin *pin,
++ struct au_wr_dir_args *wr_dir_args)
++{
++ struct dentry *wh_dentry, *h_parent;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++ unsigned int udba;
++ aufs_bindex_t bcpup;
++
++ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
++ bcpup = err;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ sb = dentry->d_sb;
++ udba = au_opt_udba(sb);
++ err = au_pin(pin, dentry, bcpup, udba,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ h_parent = au_pinned_h_parent(pin);
++ if (udba != AuOpt_UDBA_NONE
++ && au_dbstart(dentry) == bcpup) {
++ err = au_may_add(dentry, bcpup, h_parent,
++ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_unpin;
++ }
++
++ br = au_sbr(sb, bcpup);
++ if (dt) {
++ struct path tmp = {
++ .dentry = h_parent,
++ .mnt = br->br_mnt
++ };
++ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
++ }
++
++ wh_dentry = NULL;
++ if (bcpup != au_dbwh(dentry))
++ goto out; /* success */
++
++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++
++ out_unpin:
++ if (IS_ERR(wh_dentry))
++ au_unpin(pin);
++ out:
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++enum { Mknod, Symlink, Creat };
++struct simple_arg {
++ int type;
++ union {
++ struct {
++ int mode;
++ struct nameidata *nd;
++ } c;
++ struct {
++ const char *symname;
++ } s;
++ struct {
++ int mode;
++ dev_t dev;
++ } m;
++ } u;
++};
++
++static int add_simple(struct inode *dir, struct dentry *dentry,
++ struct simple_arg *arg)
++{
++ int err;
++ aufs_bindex_t bstart;
++ unsigned char created;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *wh_dentry, *parent;
++ struct inode *h_dir;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ IMustLock(dir);
++
++ parent = dentry->d_parent; /* dir inode is locked */
++ aufs_read_lock(dentry, AuLock_DW);
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ bstart = au_dbstart(dentry);
++ h_path.dentry = au_h_dptr(dentry, bstart);
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ h_dir = au_pinned_h_dir(&pin);
++ switch (arg->type) {
++ case Creat:
++ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
++ break;
++ case Symlink:
++ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
++ break;
++ case Mknod:
++ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
++ break;
++ default:
++ BUG();
++ }
++ created = !err;
++ if (!err)
++ err = epilog(dir, bstart, wh_dentry, dentry);
++
++ /* revert */
++ if (unlikely(created && err && h_path.dentry->d_inode)) {
++ int rerr;
++ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ if (rerr) {
++ AuIOErr("%.*s revert failure(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ au_dtime_revert(&dt);
++ d_drop(dentry);
++ }
++
++ au_unpin(&pin);
++ dput(wh_dentry);
++
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
++
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++ struct simple_arg arg = {
++ .type = Mknod,
++ .u.m = {
++ .mode = mode,
++ .dev = dev
++ }
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++ struct simple_arg arg = {
++ .type = Symlink,
++ .u.s.symname = symname
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ struct simple_arg arg = {
++ .type = Creat,
++ .u.c = {
++ .mode = mode,
++ .nd = nd
++ }
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_link_args {
++ aufs_bindex_t bdst, bsrc;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *src_parent, *parent;
++};
++
++static int au_cpup_before_link(struct dentry *src_dentry,
++ struct au_link_args *a)
++{
++ int err;
++ struct dentry *h_src_dentry;
++ struct mutex *h_mtx;
++
++ di_read_lock_parent(a->src_parent, AuLock_IR);
++ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
++ if (unlikely(err))
++ goto out;
++
++ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
++ h_mtx = &h_src_dentry->d_inode->i_mutex;
++ err = au_pin(&a->pin, src_dentry, a->bdst,
++ au_opt_udba(src_dentry->d_sb),
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
++ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
++ mutex_unlock(h_mtx);
++ au_unpin(&a->pin);
++
++ out:
++ di_read_unlock(a->src_parent, AuLock_IR);
++ return err;
++}
++
++static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
++{
++ int err;
++ unsigned char plink;
++ struct inode *h_inode, *inode;
++ struct dentry *h_src_dentry;
++ struct super_block *sb;
++
++ plink = 0;
++ h_inode = NULL;
++ sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ if (au_ibstart(inode) <= a->bdst)
++ h_inode = au_h_iptr(inode, a->bdst);
++ if (!h_inode || !h_inode->i_nlink) {
++ /* copyup src_dentry as the name of dentry. */
++ au_set_dbstart(src_dentry, a->bdst);
++ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
++ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
++ AuCpup_KEEPLINO, a->parent);
++ mutex_unlock(&h_inode->i_mutex);
++ au_set_h_dptr(src_dentry, a->bdst, NULL);
++ au_set_dbstart(src_dentry, a->bsrc);
++ } else {
++ /* the inode of src_dentry already exists on a.bdst branch */
++ h_src_dentry = d_find_alias(h_inode);
++ if (!h_src_dentry && au_plink_test(inode)) {
++ plink = 1;
++ h_src_dentry = au_plink_lkup(inode, a->bdst);
++ err = PTR_ERR(h_src_dentry);
++ if (IS_ERR(h_src_dentry))
++ goto out;
++
++ if (unlikely(!h_src_dentry->d_inode)) {
++ dput(h_src_dentry);
++ h_src_dentry = NULL;
++ }
++
++ }
++ if (h_src_dentry) {
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ dput(h_src_dentry);
++ } else {
++ AuIOErr("no dentry found for hi%lu on b%d\n",
++ h_inode->i_ino, a->bdst);
++ err = -EIO;
++ }
++ }
++
++ if (!err && !plink)
++ au_plink_append(inode, a->bdst, a->h_path.dentry);
++
++out:
++ return err;
++}
++
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err, rerr;
++ struct au_dtime dt;
++ struct au_link_args *a;
++ struct dentry *wh_dentry, *h_src_dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct au_wr_dir_args wr_dir_args = {
++ /* .force_btgt = -1, */
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ IMustLock(dir);
++ inode = src_dentry->d_inode;
++ IMustLock(inode);
++
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink))
++ goto out;
++
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ a->parent = dentry->d_parent; /* dir inode is locked */
++ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
++ a->src_parent = dget_parent(src_dentry);
++ wr_dir_args.force_btgt = au_dbstart(src_dentry);
++
++ di_write_lock_parent(a->parent);
++ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_unlock;
++
++ err = 0;
++ sb = dentry->d_sb;
++ a->bdst = au_dbstart(dentry);
++ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
++ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
++ a->bsrc = au_dbstart(src_dentry);
++ if (au_opt_test(au_mntflags(sb), PLINK)) {
++ if (a->bdst < a->bsrc
++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
++ err = au_cpup_or_link(src_dentry, a);
++ else {
++ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ }
++ } else {
++ /*
++ * copyup src_dentry to the branch we process,
++ * and then link(2) to it.
++ */
++ if (a->bdst < a->bsrc
++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
++ au_unpin(&a->pin);
++ di_write_unlock(a->parent);
++ err = au_cpup_before_link(src_dentry, a);
++ if (!err) {
++ di_write_lock_parent(a->parent);
++ err = au_pin(&a->pin, dentry, a->bdst,
++ au_opt_udba(sb),
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out_wh;
++ }
++ }
++ if (!err) {
++ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ }
++ }
++ if (unlikely(err))
++ goto out_unpin;
++
++ if (wh_dentry) {
++ a->h_path.dentry = wh_dentry;
++ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
++ dentry);
++ if (unlikely(err))
++ goto out_revert;
++ }
++
++ dir->i_version++;
++ if (au_ibstart(dir) == au_dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ inc_nlink(inode);
++ inode->i_ctime = dir->i_ctime;
++ if (!d_unhashed(a->h_path.dentry))
++ d_instantiate(dentry, au_igrab(inode));
++ else
++ /* some filesystem calls d_drop() */
++ d_drop(dentry);
++ goto out_unpin; /* success */
++
++ out_revert:
++ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
++ if (!rerr)
++ goto out_dt;
++ AuIOErr("%.*s reverting failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ out_dt:
++ d_drop(dentry);
++ au_dtime_revert(&dt);
++ out_unpin:
++ au_unpin(&a->pin);
++ out_wh:
++ dput(wh_dentry);
++ out_unlock:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(a->parent);
++ dput(a->src_parent);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ kfree(a);
++ out:
++ return err;
++}
++
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err, rerr;
++ aufs_bindex_t bindex;
++ unsigned char diropq;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *wh_dentry, *parent, *opq_dentry;
++ struct mutex *h_mtx;
++ struct super_block *sb;
++ struct au_dtime dt;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
++ };
++
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AuLock_DW);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dentry->d_sb;
++ bindex = au_dbstart(dentry);
++ h_path.dentry = au_h_dptr(dentry, bindex);
++ h_path.mnt = au_sbr_mnt(sb, bindex);
++ err = vfsub_mkdir(au_pinned_h_dir(&pin), &h_path, mode);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* make the dir opaque */
++ diropq = 0;
++ h_mtx = &h_path.dentry->d_inode->i_mutex;
++ if (wh_dentry
++ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ opq_dentry = au_diropq_create(dentry, bindex);
++ mutex_unlock(h_mtx);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out_dir;
++ dput(opq_dentry);
++ diropq = 1;
++ }
++
++ err = epilog(dir, bindex, wh_dentry, dentry);
++ if (!err) {
++ inc_nlink(dir);
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (diropq) {
++ AuLabel(revert opq);
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(dentry, bindex);
++ mutex_unlock(h_mtx);
++ if (rerr) {
++ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ }
++
++ out_dir:
++ AuLabel(revert dir);
++ rerr = vfsub_rmdir(au_pinned_h_dir(&pin), &h_path);
++ if (rerr) {
++ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ d_drop(dentry);
++ au_dtime_revert(&dt);
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
+diff -Naur a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+--- a/fs/aufs/i_op.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,874 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (except add/del/rename)
++ */
++
++#include <linux/device_cgroup.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++static int h_permission(struct inode *h_inode, int mask,
++ struct vfsmount *h_mnt, int brperm)
++{
++ int err;
++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++
++ err = -EACCES;
++ if ((write_mask && IS_IMMUTABLE(h_inode))
++ || ((mask & MAY_EXEC)
++ && S_ISREG(h_inode->i_mode)
++ && ((h_mnt->mnt_flags & MNT_NOEXEC)
++ || !(h_inode->i_mode & S_IXUGO))))
++ goto out;
++
++ /*
++ * - skip the lower fs test in the case of write to ro branch.
++ * - nfs dir permission write check is optimized, but a policy for
++ * link/rename requires a real check.
++ */
++ if ((write_mask && !au_br_writable(brperm))
++ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
++ && write_mask && !(mask & MAY_READ))
++ || !h_inode->i_op->permission) {
++ /* AuLabel(generic_permission); */
++ err = generic_permission(h_inode, mask, NULL);
++ } else {
++ /* AuLabel(h_inode->permission); */
++ err = h_inode->i_op->permission(h_inode, mask);
++ AuTraceErr(err);
++ }
++
++ if (!err)
++ err = devcgroup_inode_permission(h_inode, mask);
++ if (!err)
++ err = security_inode_permission
++ (h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
++ | MAY_APPEND));
++
++ out:
++ return err;
++}
++
++static int aufs_permission(struct inode *inode, int mask)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ const unsigned char isdir = !!S_ISDIR(inode->i_mode);
++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++ struct inode *h_inode;
++ struct super_block *sb;
++ struct au_branch *br;
++
++ sb = inode->i_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ ii_read_lock_child(inode);
++
++ if (!isdir || write_mask) {
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ AuDebugOn(!h_inode
++ || ((h_inode->i_mode & S_IFMT)
++ != (inode->i_mode & S_IFMT)));
++ err = 0;
++ bindex = au_ibstart(inode);
++ br = au_sbr(sb, bindex);
++ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
++
++ if (write_mask && !err) {
++ /* test whether the upper writable branch exists */
++ err = -EROFS;
++ for (; bindex >= 0; bindex--)
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = 0;
++ break;
++ }
++ }
++ goto out;
++ }
++
++ /* non-write to dir */
++ err = 0;
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode) {
++ AuDebugOn(!S_ISDIR(h_inode->i_mode));
++ br = au_sbr(sb, bindex);
++ err = h_permission(h_inode, mask, br->br_mnt,
++ br->br_perm);
++ }
++ }
++
++ out:
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ struct dentry *ret, *parent;
++ struct inode *inode, *h_inode;
++ struct mutex *mtx;
++ struct super_block *sb;
++ int err, npositive;
++ aufs_bindex_t bstart;
++
++ /* temporary workaround for a bug in NFSD readdir */
++ if (!au_test_nfsd(current))
++ IMustLock(dir);
++ else
++ WARN_ONCE(!mutex_is_locked(&dir->i_mutex),
++ "a known problem of NFSD readdir since 2.6.28\n");
++
++ sb = dir->i_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_alloc_dinfo(dentry);
++ ret = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_read_lock_parent(parent, AuLock_IR);
++ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
++ di_read_unlock(parent, AuLock_IR);
++ err = npositive;
++ ret = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out_unlock;
++
++ inode = NULL;
++ if (npositive) {
++ bstart = au_dbstart(dentry);
++ h_inode = au_h_dptr(dentry, bstart)->d_inode;
++ if (!S_ISDIR(h_inode->i_mode)) {
++ /*
++ * stop 'race'-ing between hardlinks under different
++ * parents.
++ */
++ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
++ mutex_lock(mtx);
++ inode = au_new_inode(dentry, /*must_new*/0);
++ mutex_unlock(mtx);
++ } else
++ inode = au_new_inode(dentry, /*must_new*/0);
++ ret = (void *)inode;
++ }
++ if (IS_ERR(inode))
++ goto out_unlock;
++
++ ret = d_splice_alias(inode, dentry);
++ if (unlikely(IS_ERR(ret) && inode))
++ ii_write_unlock(inode);
++ au_store_oflag(nd, inode);
++
++ out_unlock:
++ di_write_unlock(dentry);
++ out:
++ si_read_unlock(sb);
++ return ret;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
++ const unsigned char add_entry, aufs_bindex_t bcpup,
++ aufs_bindex_t bstart)
++{
++ int err;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++
++ if (add_entry) {
++ au_update_dbstart(dentry);
++ IMustLock(parent->d_inode);
++ } else
++ di_write_lock_parent(parent);
++
++ err = 0;
++ if (!au_h_dptr(parent, bcpup)) {
++ if (bstart < bcpup)
++ err = au_cpdown_dirs(dentry, bcpup);
++ else
++ err = au_cpup_dirs(dentry, bcpup);
++ }
++ if (!err && add_entry) {
++ h_parent = au_h_dptr(parent, bcpup);
++ h_dir = h_parent->d_inode;
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ err = au_lkup_neg(dentry, bcpup);
++ /* todo: no unlock here */
++ mutex_unlock(&h_dir->i_mutex);
++ if (bstart < bcpup && au_dbstart(dentry) < 0) {
++ au_set_dbstart(dentry, 0);
++ au_update_dbrange(dentry, /*do_put_zero*/0);
++ }
++ }
++
++ if (!add_entry)
++ di_write_unlock(parent);
++ if (!err)
++ err = bcpup; /* success */
++
++ return err;
++}
++
++/*
++ * decide the branch and the parent dir where we will create a new entry.
++ * returns new bindex or an error.
++ * copyup the parent dir if needed.
++ */
++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++ struct au_wr_dir_args *args)
++{
++ int err;
++ aufs_bindex_t bcpup, bstart, src_bstart;
++ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
++ ADD_ENTRY);
++ struct super_block *sb;
++ struct dentry *parent;
++ struct au_sbinfo *sbinfo;
++
++ sb = dentry->d_sb;
++ sbinfo = au_sbi(sb);
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(dentry);
++ bcpup = bstart;
++ if (args->force_btgt < 0) {
++ if (src_dentry) {
++ src_bstart = au_dbstart(src_dentry);
++ if (src_bstart < bstart)
++ bcpup = src_bstart;
++ } else if (add_entry) {
++ err = AuWbrCreate(sbinfo, dentry,
++ au_ftest_wrdir(args->flags, ISDIR));
++ bcpup = err;
++ }
++
++ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
++ if (add_entry)
++ err = AuWbrCopyup(sbinfo, dentry);
++ else {
++ if (!IS_ROOT(dentry)) {
++ di_read_lock_parent(parent, !AuLock_IR);
++ err = AuWbrCopyup(sbinfo, dentry);
++ di_read_unlock(parent, !AuLock_IR);
++ } else
++ err = AuWbrCopyup(sbinfo, dentry);
++ }
++ bcpup = err;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ bcpup = args->force_btgt;
++ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
++ }
++ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
++ if (bstart < bcpup)
++ au_update_dbrange(dentry, /*do_put_zero*/1);
++
++ err = bcpup;
++ if (bcpup == bstart)
++ goto out; /* success */
++
++ /* copyup the new parent into the branch we process */
++ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin)
++{
++ if (pin && pin->parent)
++ return au_h_dptr(pin->parent, pin->bindex);
++ return NULL;
++}
++
++void au_unpin(struct au_pin *p)
++{
++ if (au_ftest_pin(p->flags, MNT_WRITE))
++ mnt_drop_write(p->h_mnt);
++ if (!p->hdir)
++ return;
++
++ au_hin_imtx_unlock(p->hdir);
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_unlock(p->parent, AuLock_IR);
++ iput(p->hdir->hi_inode);
++ dput(p->parent);
++ p->parent = NULL;
++ p->hdir = NULL;
++ p->h_mnt = NULL;
++}
++
++int au_do_pin(struct au_pin *p)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *h_dentry, *h_parent;
++ struct au_branch *br;
++ struct inode *h_dir;
++
++ err = 0;
++ sb = p->dentry->d_sb;
++ br = au_sbr(sb, p->bindex);
++ if (IS_ROOT(p->dentry)) {
++ if (au_ftest_pin(p->flags, MNT_WRITE)) {
++ p->h_mnt = br->br_mnt;
++ err = mnt_want_write(p->h_mnt);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_err;
++ }
++ }
++ goto out;
++ }
++
++ h_dentry = NULL;
++ if (p->bindex <= au_dbend(p->dentry))
++ h_dentry = au_h_dptr(p->dentry, p->bindex);
++
++ p->parent = dget_parent(p->dentry);
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
++
++ h_dir = NULL;
++ h_parent = au_h_dptr(p->parent, p->bindex);
++ p->hdir = au_hi(p->parent->d_inode, p->bindex);
++ if (p->hdir)
++ h_dir = p->hdir->hi_inode;
++
++ /* udba case */
++ if (unlikely(!p->hdir || !h_dir)) {
++ err = au_busy_or_stale();
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_unlock(p->parent, AuLock_IR);
++ dput(p->parent);
++ p->parent = NULL;
++ goto out_err;
++ }
++
++ au_igrab(h_dir);
++ au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
++
++ if (h_dentry) {
++ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_unpin;
++ }
++ }
++
++ if (au_ftest_pin(p->flags, MNT_WRITE)) {
++ p->h_mnt = br->br_mnt;
++ err = mnt_want_write(p->h_mnt);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_unpin;
++ }
++ }
++ goto out; /* success */
++
++ out_unpin:
++ au_unpin(p);
++ out_err:
++ AuErr("err %d\n", err);
++ err = au_busy_or_stale();
++ out:
++ return err;
++}
++
++void au_pin_init(struct au_pin *p, struct dentry *dentry,
++ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++ unsigned int udba, unsigned char flags)
++{
++ p->dentry = dentry;
++ p->udba = udba;
++ p->lsc_di = lsc_di;
++ p->lsc_hi = lsc_hi;
++ p->flags = flags;
++ p->bindex = bindex;
++
++ p->parent = NULL;
++ p->hdir = NULL;
++ p->h_mnt = NULL;
++}
++
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int udba, unsigned char flags)
++{
++ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
++ udba, flags);
++ return au_do_pin(pin);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuIcpup_DID_CPUP 1
++#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
++#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
++#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
++
++struct au_icpup_args {
++ unsigned char flags;
++ unsigned char pin_flags;
++ aufs_bindex_t btgt;
++ struct au_pin pin;
++ struct path h_path;
++ struct inode *h_inode;
++};
++
++static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
++ struct au_icpup_args *a)
++{
++ int err;
++ unsigned int udba;
++ loff_t sz;
++ aufs_bindex_t bstart;
++ struct dentry *hi_wh, *parent;
++ struct inode *inode;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = 0
++ };
++
++ di_write_lock_child(dentry);
++ bstart = au_dbstart(dentry);
++ inode = dentry->d_inode;
++ if (S_ISDIR(inode->i_mode))
++ au_fset_wrdir(wr_dir_args.flags, ISDIR);
++ /* plink or hi_wh() case */
++ if (bstart != au_ibstart(inode))
++ wr_dir_args.force_btgt = au_ibstart(inode);
++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
++ if (unlikely(err < 0))
++ goto out_dentry;
++ a->btgt = err;
++ if (err != bstart)
++ au_fset_icpup(a->flags, DID_CPUP);
++
++ err = 0;
++ a->pin_flags = AuPin_MNT_WRITE;
++ parent = NULL;
++ if (!IS_ROOT(dentry)) {
++ au_fset_pin(a->pin_flags, DI_LOCKED);
++ parent = dget_parent(dentry);
++ di_write_lock_parent(parent);
++ }
++
++ udba = au_opt_udba(dentry->d_sb);
++ if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
++ udba = AuOpt_UDBA_NONE;
++ err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
++ if (unlikely(err)) {
++ if (parent) {
++ di_write_unlock(parent);
++ dput(parent);
++ }
++ goto out_dentry;
++ }
++ a->h_path.dentry = au_h_dptr(dentry, bstart);
++ a->h_inode = a->h_path.dentry->d_inode;
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ sz = -1;
++ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
++ sz = ia->ia_size;
++
++ hi_wh = NULL;
++ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
++ hi_wh = au_hi_wh(inode, a->btgt);
++ if (!hi_wh) {
++ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
++ if (unlikely(err))
++ goto out_unlock;
++ hi_wh = au_hi_wh(inode, a->btgt);
++ /* todo: revalidate hi_wh? */
++ }
++ }
++
++ if (parent) {
++ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
++ di_downgrade_lock(parent, AuLock_IR);
++ dput(parent);
++ }
++ if (!au_ftest_icpup(a->flags, DID_CPUP))
++ goto out; /* success */
++
++ if (!d_unhashed(dentry)) {
++ err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
++ if (!err)
++ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++ } else if (!hi_wh)
++ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++ else
++ a->h_path.dentry = hi_wh; /* do not dget here */
++
++ out_unlock:
++ mutex_unlock(&a->h_inode->i_mutex);
++ a->h_inode = a->h_path.dentry->d_inode;
++ if (!err) {
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ goto out; /* success */
++ }
++
++ au_unpin(&a->pin);
++
++ out_dentry:
++ di_write_unlock(dentry);
++ out:
++ return err;
++}
++
++static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *file;
++ struct au_icpup_args *a;
++
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ file = NULL;
++ if (ia->ia_valid & ATTR_FILE) {
++ /* currently ftruncate(2) only */
++ file = ia->ia_file;
++ fi_write_lock(file);
++ ia->ia_file = au_h_fptr(file, au_fbstart(file));
++ }
++
++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
++ ia->ia_valid &= ~ATTR_MODE;
++
++ err = au_lock_and_icpup(dentry, ia, a);
++ if (unlikely(err < 0))
++ goto out_si;
++ if (au_ftest_icpup(a->flags, DID_CPUP)) {
++ ia->ia_file = NULL;
++ ia->ia_valid &= ~ATTR_FILE;
++ }
++
++ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
++ if (ia->ia_valid & ATTR_SIZE) {
++ struct file *f;
++
++ if (ia->ia_size < i_size_read(inode)) {
++ /* unmap only */
++ err = vmtruncate(inode, ia->ia_size);
++ if (unlikely(err))
++ goto out_unlock;
++ }
++
++ f = NULL;
++ if (ia->ia_valid & ATTR_FILE)
++ f = ia->ia_file;
++ mutex_unlock(&a->h_inode->i_mutex);
++ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ } else
++ err = vfsub_notify_change(&a->h_path, ia);
++ if (!err)
++ au_cpup_attr_changeable(inode);
++
++ out_unlock:
++ mutex_unlock(&a->h_inode->i_mutex);
++ au_unpin(&a->pin);
++ di_write_unlock(dentry);
++ out_si:
++ if (file) {
++ fi_write_unlock(file);
++ ia->ia_file = file;
++ ia->ia_valid |= ATTR_FILE;
++ }
++ si_read_unlock(sb);
++ kfree(a);
++ out:
++ return err;
++}
++
++static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *parent;
++
++ err = 0;
++ inode = dentry->d_inode;
++ di_write_lock_child(dentry);
++ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++ if (err > 0)
++ err = au_refresh_hinode(inode, dentry);
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ if (unlikely(!err))
++ err = -EIO;
++ }
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ return err;
++}
++
++static void au_refresh_iattr(struct inode *inode, struct kstat *st,
++ unsigned int nlink)
++{
++ inode->i_mode = st->mode;
++ inode->i_uid = st->uid;
++ inode->i_gid = st->gid;
++ inode->i_atime = st->atime;
++ inode->i_mtime = st->mtime;
++ inode->i_ctime = st->ctime;
++
++ au_cpup_attr_nlink(inode, /*force*/0);
++ if (S_ISDIR(inode->i_mode)) {
++ inode->i_nlink -= nlink;
++ inode->i_nlink += st->nlink;
++ }
++
++ spin_lock(&inode->i_lock);
++ inode->i_blocks = st->blocks;
++ i_size_write(inode, st->size);
++ spin_unlock(&inode->i_lock);
++}
++
++static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
++ struct dentry *dentry, struct kstat *st)
++{
++ int err;
++ unsigned int mnt_flags;
++ aufs_bindex_t bindex;
++ unsigned char udba_none, positive, did_lock;
++ struct super_block *sb, *h_sb;
++ struct inode *inode;
++ struct vfsmount *h_mnt;
++ struct dentry *h_dentry;
++
++ err = 0;
++ did_lock = 0;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ si_read_lock(sb, AuLock_FLUSH);
++ if (IS_ROOT(dentry)) {
++ /* lock free root dinfo */
++ h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
++ h_mnt = au_sbr_mnt(sb, 0);
++ goto getattr;
++ }
++
++ did_lock = 1;
++ mnt_flags = au_mntflags(sb);
++ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
++
++ /* support fstat(2) */
++ if (!d_unhashed(dentry) && !udba_none) {
++ unsigned int sigen = au_sigen(sb);
++ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++ di_read_lock_child(dentry, AuLock_IR);
++ else {
++ err = au_getattr_lock_reval(dentry, sigen);
++ if (unlikely(err))
++ goto out;
++ }
++ } else
++ di_read_lock_child(dentry, AuLock_IR);
++
++ bindex = au_ibstart(inode);
++ h_mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_mnt->mnt_sb;
++ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
++ goto out_fill; /* success */
++
++ if (au_dbstart(dentry) == bindex)
++ h_dentry = dget(au_h_dptr(dentry, bindex));
++ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
++ h_dentry = au_plink_lkup(inode, bindex);
++ if (IS_ERR(h_dentry))
++ goto out_fill; /* pretending success */
++ } else
++ /* illegally overlapped or something */
++ goto out_fill; /* pretending success */
++
++ getattr:
++ positive = !!h_dentry->d_inode;
++ if (positive)
++ err = vfs_getattr(h_mnt, h_dentry, st);
++ dput(h_dentry);
++ if (!err) {
++ if (positive)
++ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
++ goto out_fill; /* success */
++ }
++ goto out;
++
++ out_fill:
++ generic_fillattr(inode, st);
++ out:
++ if (did_lock)
++ di_read_unlock(dentry, AuLock_IR);
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *h_dentry;
++
++ err = -EINVAL;
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (unlikely(/* !h_dentry
++ || !h_dentry->d_inode
++ || !h_dentry->d_inode->i_op
++ || */ !h_dentry->d_inode->i_op->readlink))
++ goto out;
++
++ err = security_inode_readlink(h_dentry);
++ if (unlikely(err))
++ goto out;
++
++ sb = dentry->d_sb;
++ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
++ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
++ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
++ }
++ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
++
++ out:
++ return err;
++}
++
++static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
++{
++ int err;
++
++ aufs_read_lock(dentry, AuLock_IR);
++ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
++ aufs_read_unlock(dentry, AuLock_IR);
++
++ return err;
++}
++
++static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ int err;
++ char *buf;
++ mm_segment_t old_fs;
++
++ err = -ENOMEM;
++ buf = __getname();
++ if (unlikely(!buf))
++ goto out;
++
++ aufs_read_lock(dentry, AuLock_IR);
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
++ PATH_MAX);
++ set_fs(old_fs);
++ aufs_read_unlock(dentry, AuLock_IR);
++
++ if (err >= 0) {
++ buf[err] = 0;
++ /* will be freed by put_link */
++ nd_set_link(nd, buf);
++ return NULL; /* success */
++ }
++ __putname(buf);
++
++ out:
++ path_put(&nd->path);
++ AuTraceErr(err);
++ return ERR_PTR(err);
++}
++
++static void aufs_put_link(struct dentry *dentry __maybe_unused,
++ struct nameidata *nd, void *cookie __maybe_unused)
++{
++ __putname(nd_get_link(nd));
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_truncate_range(struct inode *inode __maybe_unused,
++ loff_t start __maybe_unused,
++ loff_t end __maybe_unused)
++{
++ AuUnsupport();
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct inode_operations aufs_symlink_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr,
++ .readlink = aufs_readlink,
++ .follow_link = aufs_follow_link,
++ .put_link = aufs_put_link
++};
++
++struct inode_operations aufs_dir_iop = {
++ .create = aufs_create,
++ .lookup = aufs_lookup,
++ .link = aufs_link,
++ .unlink = aufs_unlink,
++ .symlink = aufs_symlink,
++ .mkdir = aufs_mkdir,
++ .rmdir = aufs_rmdir,
++ .mknod = aufs_mknod,
++ .rename = aufs_rename,
++
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr
++};
++
++struct inode_operations aufs_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr,
++ .truncate_range = aufs_truncate_range
++};
+diff -Naur a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
+--- a/fs/aufs/i_op_del.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_del.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,466 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (del entry)
++ */
++
++#include "aufs.h"
++
++/*
++ * decide if a new whiteout for @dentry is necessary or not.
++ * when it is necessary, prepare the parent dir for the upper branch whose
++ * branch index is @bcpup for creation. the actual creation of the whiteout will
++ * be done by caller.
++ * return value:
++ * 0: wh is unnecessary
++ * plus: wh is necessary
++ * minus: error
++ */
++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
++{
++ int need_wh, err;
++ aufs_bindex_t bstart;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ if (*bcpup < 0) {
++ *bcpup = bstart;
++ if (au_test_ro(sb, bstart, dentry->d_inode)) {
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ *bcpup = err;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else
++ AuDebugOn(bstart < *bcpup
++ || au_test_ro(sb, *bcpup, dentry->d_inode));
++ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
++
++ if (*bcpup != bstart) {
++ err = au_cpup_dirs(dentry, *bcpup);
++ if (unlikely(err))
++ goto out;
++ need_wh = 1;
++ } else {
++ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
++
++ old_bend = au_dbend(dentry);
++ if (isdir) {
++ bdiropq = au_dbdiropq(dentry);
++ au_set_dbdiropq(dentry, -1);
++ }
++ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
++ /*nd*/NULL);
++ err = need_wh;
++ if (isdir)
++ au_set_dbdiropq(dentry, bdiropq);
++ if (unlikely(err < 0))
++ goto out;
++ new_bend = au_dbend(dentry);
++ if (!need_wh && old_bend != new_bend) {
++ au_set_h_dptr(dentry, new_bend, NULL);
++ au_set_dbend(dentry, old_bend);
++ }
++ }
++ AuDbg("need_wh %d\n", need_wh);
++ err = need_wh;
++
++ out:
++ return err;
++}
++
++/*
++ * simple tests for the del-entry operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir)
++{
++ int err;
++ umode_t h_mode;
++ struct dentry *h_dentry, *h_latest;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ if (dentry->d_inode) {
++ err = -ENOENT;
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++
++ h_mode = h_inode->i_mode;
++ if (!isdir) {
++ err = -EISDIR;
++ if (unlikely(S_ISDIR(h_mode)))
++ goto out;
++ } else if (unlikely(!S_ISDIR(h_mode))) {
++ err = -ENOTDIR;
++ goto out;
++ }
++ } else {
++ /* rename(2) case */
++ err = -EIO;
++ if (unlikely(h_inode))
++ goto out;
++ }
++
++ err = -ENOENT;
++ /* expected parent dir is locked */
++ if (unlikely(h_parent != h_dentry->d_parent))
++ goto out;
++ err = 0;
++
++ /*
++ * rmdir a dir may break the consistency on some filesystem.
++ * let's try heavy test.
++ */
++ err = -EACCES;
++ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
++ goto out;
++
++ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
++ au_sbr(dentry->d_sb, bindex));
++ err = -EIO;
++ if (IS_ERR(h_latest))
++ goto out;
++ if (h_latest == h_dentry)
++ err = 0;
++ dput(h_latest);
++
++ out:
++ return err;
++}
++
++/*
++ * decide the branch where we operate for @dentry. the branch index will be set
++ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
++ * dir for reverting.
++ * when a new whiteout is necessary, create it.
++ */
++static struct dentry*
++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
++ struct au_dtime *dt, struct au_pin *pin)
++{
++ struct dentry *wh_dentry;
++ struct super_block *sb;
++ struct path h_path;
++ int err, need_wh;
++ unsigned int udba;
++ aufs_bindex_t bcpup;
++
++ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
++ wh_dentry = ERR_PTR(need_wh);
++ if (unlikely(need_wh < 0))
++ goto out;
++
++ sb = dentry->d_sb;
++ udba = au_opt_udba(sb);
++ bcpup = *rbcpup;
++ err = au_pin(pin, dentry, bcpup, udba,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ h_path.dentry = au_pinned_h_parent(pin);
++ if (udba != AuOpt_UDBA_NONE
++ && au_dbstart(dentry) == bcpup) {
++ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_unpin;
++ }
++
++ h_path.mnt = au_sbr_mnt(sb, bcpup);
++ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
++ wh_dentry = NULL;
++ if (!need_wh)
++ goto out; /* success, no need to create whiteout */
++
++ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
++ if (!IS_ERR(wh_dentry))
++ goto out; /* success */
++ /* returns with the parent is locked and wh_dentry is dget-ed */
++
++ out_unpin:
++ au_unpin(pin);
++ out:
++ return wh_dentry;
++}
++
++/*
++ * when removing a dir, rename it to a unique temporary whiteout-ed name first
++ * in order to be revertible and save time for removing many child whiteouts
++ * under the dir.
++ * returns 1 when there are too many child whiteout and caller should remove
++ * them asynchronously. returns 0 when the number of children is enough small to
++ * remove now or the branch fs is a remote fs.
++ * otherwise return an error.
++ */
++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
++ struct au_nhash *whlist, struct inode *dir)
++{
++ int rmdir_later, err, dirwh;
++ struct dentry *h_dentry;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ h_dentry = au_h_dptr(dentry, bindex);
++ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
++ if (unlikely(err))
++ goto out;
++
++ /* stop monitoring */
++ au_hin_free(au_hi(dentry->d_inode, bindex));
++
++ if (!au_test_fs_remote(h_dentry->d_sb)) {
++ dirwh = au_sbi(sb)->si_dirwh;
++ rmdir_later = (dirwh <= 1);
++ if (!rmdir_later)
++ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
++ dirwh);
++ if (rmdir_later)
++ return rmdir_later;
++ }
++
++ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
++ if (unlikely(err)) {
++ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
++ AuDLNPair(h_dentry), bindex, err);
++ err = 0;
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * final procedure for deleting a entry.
++ * maintain dentry and iattr.
++ */
++static void epilog(struct inode *dir, struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ d_drop(dentry);
++ inode->i_ctime = dir->i_ctime;
++
++ if (atomic_read(&dentry->d_count) == 1) {
++ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
++ au_update_dbstart(dentry);
++ }
++ if (au_ibstart(dir) == bindex)
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++}
++
++/*
++ * when an error happened, remove the created whiteout and revert everything.
++ */
++static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
++ struct dentry *wh_dentry, struct dentry *dentry,
++ struct au_dtime *dt)
++{
++ int rerr;
++ struct path h_path = {
++ .dentry = wh_dentry,
++ .mnt = au_sbr_mnt(dir->i_sb, bwh)
++ };
++
++ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
++ if (!rerr) {
++ au_set_dbwh(dentry, bwh);
++ au_dtime_revert(dt);
++ return 0;
++ }
++
++ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ struct inode *inode, *h_dir;
++ struct dentry *parent, *wh_dentry;
++
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; /* possible? */
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AuLock_DW);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++
++ bstart = au_dbstart(dentry);
++ bwh = au_dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ h_path.dentry = au_h_dptr(dentry, bstart);
++ dget(h_path.dentry);
++ if (bindex == bstart) {
++ h_dir = au_pinned_h_dir(&pin);
++ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ } else {
++ /* dir inode is locked */
++ h_dir = wh_dentry->d_parent->d_inode;
++ IMustLock(h_dir);
++ err = 0;
++ }
++
++ if (!err) {
++ drop_nlink(inode);
++ epilog(dir, dentry, bindex);
++
++ /* update target timestamps */
++ if (bindex == bstart) {
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
++ } else
++ /* todo: this timestamp may be reverted later */
++ inode->i_ctime = h_dir->i_ctime;
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (wh_dentry) {
++ int rerr;
++
++ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ dput(h_path.dentry);
++ out:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
++
++int aufs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err, rmdir_later;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct inode *inode;
++ struct dentry *parent, *wh_dentry, *h_dentry;
++ struct au_whtmp_rmdir *args;
++
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ err = -ENOENT; /* possible? */
++ if (unlikely(!inode))
++ goto out;
++ IMustLock(inode);
++
++ err = -ENOMEM;
++ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
++ if (unlikely(!args))
++ goto out;
++
++ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++ err = au_test_empty(dentry, &args->whlist);
++ if (unlikely(err))
++ goto out_args;
++
++ bstart = au_dbstart(dentry);
++ bwh = au_dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_args;
++
++ h_dentry = au_h_dptr(dentry, bstart);
++ dget(h_dentry);
++ rmdir_later = 0;
++ if (bindex == bstart) {
++ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
++ if (err > 0) {
++ rmdir_later = err;
++ err = 0;
++ }
++ } else {
++ /* stop monitoring */
++ au_hin_free(au_hi(inode, bstart));
++
++ /* dir inode is locked */
++ IMustLock(wh_dentry->d_parent->d_inode);
++ err = 0;
++ }
++
++ if (!err) {
++ clear_nlink(inode);
++ au_set_dbdiropq(dentry, -1);
++ epilog(dir, dentry, bindex);
++
++ if (rmdir_later) {
++ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
++ args = NULL;
++ }
++
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ AuLabel(revert);
++ if (wh_dentry) {
++ int rerr;
++
++ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ dput(h_dentry);
++ out_args:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ if (args)
++ au_whtmp_rmdir_free(args);
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
+--- a/fs/aufs/i_op_ren.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_ren.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,942 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operation (rename entry)
++ * todo: this is crazy monster
++ */
++
++#include "aufs.h"
++
++enum { AuSRC, AuDST, AuSrcDst };
++enum { AuPARENT, AuCHILD, AuParentChild };
++
++#define AuRen_ISDIR 1
++#define AuRen_ISSAMEDIR (1 << 1)
++#define AuRen_WHSRC (1 << 2)
++#define AuRen_WHDST (1 << 3)
++#define AuRen_MNT_WRITE (1 << 4)
++#define AuRen_DT_DSTDIR (1 << 5)
++#define AuRen_DIROPQ (1 << 6)
++#define AuRen_CPUP (1 << 7)
++#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
++#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
++#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
++
++struct au_ren_args {
++ struct {
++ struct dentry *dentry, *h_dentry, *parent, *h_parent,
++ *wh_dentry;
++ struct inode *dir, *inode;
++ struct au_hinode *hdir;
++ struct au_dtime dt[AuParentChild];
++ aufs_bindex_t bstart;
++ } sd[AuSrcDst];
++
++#define src_dentry sd[AuSRC].dentry
++#define src_dir sd[AuSRC].dir
++#define src_inode sd[AuSRC].inode
++#define src_h_dentry sd[AuSRC].h_dentry
++#define src_parent sd[AuSRC].parent
++#define src_h_parent sd[AuSRC].h_parent
++#define src_wh_dentry sd[AuSRC].wh_dentry
++#define src_hdir sd[AuSRC].hdir
++#define src_h_dir sd[AuSRC].hdir->hi_inode
++#define src_dt sd[AuSRC].dt
++#define src_bstart sd[AuSRC].bstart
++
++#define dst_dentry sd[AuDST].dentry
++#define dst_dir sd[AuDST].dir
++#define dst_inode sd[AuDST].inode
++#define dst_h_dentry sd[AuDST].h_dentry
++#define dst_parent sd[AuDST].parent
++#define dst_h_parent sd[AuDST].h_parent
++#define dst_wh_dentry sd[AuDST].wh_dentry
++#define dst_hdir sd[AuDST].hdir
++#define dst_h_dir sd[AuDST].hdir->hi_inode
++#define dst_dt sd[AuDST].dt
++#define dst_bstart sd[AuDST].bstart
++
++ struct dentry *h_trap;
++ struct au_branch *br;
++ struct au_hinode *src_hinode;
++ struct path h_path;
++ struct au_nhash whlist;
++ aufs_bindex_t btgt;
++
++ unsigned int flags;
++
++ struct au_whtmp_rmdir *thargs;
++ struct dentry *h_dst;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * functions for reverting.
++ * when an error happened in a single rename systemcall, we should revert
++ * everything as if nothing happend.
++ * we don't need to revert the copied-up/down the parent dir since they are
++ * harmless.
++ */
++
++#define RevertFailure(fmt, args...) do { \
++ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
++ ##args, err, rerr); \
++ err = -EIO; \
++} while (0)
++
++static void au_ren_rev_diropq(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(a->src_dentry, a->btgt);
++ au_hin_imtx_unlock(a->src_hinode);
++ if (rerr)
++ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
++}
++
++
++static void au_ren_rev_rename(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
++ a->br, /*nd*/NULL);
++ rerr = PTR_ERR(a->h_path.dentry);
++ if (IS_ERR(a->h_path.dentry)) {
++ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
++ return;
++ }
++
++ rerr = vfsub_rename(a->dst_h_dir,
++ au_h_dptr(a->src_dentry, a->btgt),
++ a->src_h_dir, &a->h_path);
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
++ if (rerr)
++ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
++}
++
++static void au_ren_rev_cpup(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = a->dst_h_dentry;
++ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
++ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
++ au_set_dbstart(a->src_dentry, a->src_bstart);
++ if (rerr)
++ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
++}
++
++
++static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
++ a->br, /*nd*/NULL);
++ rerr = PTR_ERR(a->h_path.dentry);
++ if (IS_ERR(a->h_path.dentry)) {
++ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
++ return;
++ }
++ if (a->h_path.dentry->d_inode) {
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ return;
++ }
++
++ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ if (!rerr) {
++ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
++ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
++ } else
++ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
++}
++
++static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = a->src_wh_dentry;
++ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
++ if (rerr)
++ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
++}
++
++static void au_ren_rev_drop(struct au_ren_args *a)
++{
++ struct dentry *d, *h_d;
++ int i;
++ aufs_bindex_t bend, bindex;
++
++ for (i = 0; i < AuSrcDst; i++) {
++ d = a->sd[i].dentry;
++ d_drop(d);
++ bend = au_dbend(d);
++ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
++ h_d = au_h_dptr(d, bindex);
++ if (h_d)
++ d_drop(h_d);
++ }
++ }
++
++ au_update_dbstart(a->dst_dentry);
++ if (a->thargs)
++ d_drop(a->h_dst);
++}
++#undef RevertFailure
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * when we have to copyup the renaming entry, do it with the rename-target name
++ * in order to minimize the cost (the later actual rename is unnecessary).
++ * otherwise rename it on the target branch.
++ */
++static int au_ren_or_cpup(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d;
++
++ d = a->src_dentry;
++ if (au_dbstart(d) == a->btgt) {
++ a->h_path.dentry = a->dst_h_dentry;
++ if (au_ftest_ren(a->flags, DIROPQ)
++ && au_dbdiropq(d) == a->btgt)
++ au_fclr_ren(a->flags, DIROPQ);
++ AuDebugOn(au_dbstart(d) != a->btgt);
++ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
++ a->dst_h_dir, &a->h_path);
++ } else {
++ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++ au_fset_ren(a->flags, CPUP);
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_set_dbstart(d, a->btgt);
++ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
++ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
++ !AuCpup_DTIME, a->dst_parent);
++ if (unlikely(err)) {
++ au_set_h_dptr(d, a->btgt, NULL);
++ au_set_dbstart(d, a->src_bstart);
++ }
++ mutex_unlock(h_mtx);
++ }
++
++ return err;
++}
++
++/* cf. aufs_rmdir() */
++static int au_ren_del_whtmp(struct au_ren_args *a)
++{
++ int err;
++ struct inode *dir;
++
++ dir = a->dst_dir;
++ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
++ au_sbi(dir->i_sb)->si_dirwh)
++ || au_test_fs_remote(a->h_dst->d_sb)) {
++ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
++ if (unlikely(err))
++ AuWarn("failed removing whtmp dir %.*s (%d), "
++ "ignored.\n", AuDLNPair(a->h_dst), err);
++ } else {
++ au_nhash_wh_free(&a->thargs->whlist);
++ a->thargs->whlist = a->whlist;
++ a->whlist.nh_num = 0;
++ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
++ dput(a->h_dst);
++ a->thargs = NULL;
++ }
++
++ return 0;
++}
++
++/* make it 'opaque' dir. */
++static int au_ren_diropq(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *diropq;
++
++ err = 0;
++ a->src_hinode = au_hi(a->src_inode, a->btgt);
++ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++ diropq = au_diropq_create(a->src_dentry, a->btgt);
++ au_hin_imtx_unlock(a->src_hinode);
++ if (IS_ERR(diropq))
++ err = PTR_ERR(diropq);
++ dput(diropq);
++
++ return err;
++}
++
++static int do_rename(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d, *h_d;
++
++ /* prepare workqueue args for asynchronous rmdir */
++ h_d = a->dst_h_dentry;
++ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
++ err = -ENOMEM;
++ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
++ if (unlikely(!a->thargs))
++ goto out;
++ a->h_dst = dget(h_d);
++ }
++
++ /* create whiteout for src_dentry */
++ if (au_ftest_ren(a->flags, WHSRC)) {
++ a->src_wh_dentry
++ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
++ err = PTR_ERR(a->src_wh_dentry);
++ if (IS_ERR(a->src_wh_dentry))
++ goto out_thargs;
++ }
++
++ /* lookup whiteout for dentry */
++ if (au_ftest_ren(a->flags, WHDST)) {
++ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
++ a->br);
++ err = PTR_ERR(h_d);
++ if (IS_ERR(h_d))
++ goto out_whsrc;
++ if (!h_d->d_inode)
++ dput(h_d);
++ else
++ a->dst_wh_dentry = h_d;
++ }
++
++ /* rename dentry to tmpwh */
++ if (a->thargs) {
++ err = au_whtmp_ren(a->dst_h_dentry, a->br);
++ if (unlikely(err))
++ goto out_whdst;
++
++ d = a->dst_dentry;
++ au_set_h_dptr(d, a->btgt, NULL);
++ err = au_lkup_neg(d, a->btgt);
++ if (unlikely(err))
++ goto out_whtmp;
++ a->dst_h_dentry = au_h_dptr(d, a->btgt);
++ }
++
++ /* cpup src */
++ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
++ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
++ !AuCpup_DTIME);
++ mutex_unlock(h_mtx);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++
++ /* rename by vfs_rename or cpup */
++ d = a->dst_dentry;
++ if (au_ftest_ren(a->flags, ISDIR)
++ && (a->dst_wh_dentry
++ || au_dbdiropq(d) == a->btgt
++ /* hide the lower to keep xino */
++ || a->btgt < au_dbend(d)
++ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
++ au_fset_ren(a->flags, DIROPQ);
++ err = au_ren_or_cpup(a);
++ if (unlikely(err))
++ /* leave the copied-up one */
++ goto out_whtmp;
++
++ /* make dir opaque */
++ if (au_ftest_ren(a->flags, DIROPQ)) {
++ err = au_ren_diropq(a);
++ if (unlikely(err))
++ goto out_rename;
++ }
++
++ /* update target timestamps */
++ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
++ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
++ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
++
++ /* remove whiteout for dentry */
++ if (a->dst_wh_dentry) {
++ a->h_path.dentry = a->dst_wh_dentry;
++ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
++ a->dst_dentry);
++ if (unlikely(err))
++ goto out_diropq;
++ }
++
++ /* remove whtmp */
++ if (a->thargs)
++ au_ren_del_whtmp(a); /* ignore this error */
++
++ err = 0;
++ goto out_success;
++
++ out_diropq:
++ if (au_ftest_ren(a->flags, DIROPQ))
++ au_ren_rev_diropq(err, a);
++ out_rename:
++ if (!au_ftest_ren(a->flags, CPUP))
++ au_ren_rev_rename(err, a);
++ else
++ au_ren_rev_cpup(err, a);
++ out_whtmp:
++ if (a->thargs)
++ au_ren_rev_whtmp(err, a);
++ out_whdst:
++ dput(a->dst_wh_dentry);
++ a->dst_wh_dentry = NULL;
++ out_whsrc:
++ if (a->src_wh_dentry)
++ au_ren_rev_whsrc(err, a);
++ au_ren_rev_drop(a);
++ out_success:
++ dput(a->src_wh_dentry);
++ dput(a->dst_wh_dentry);
++ out_thargs:
++ if (a->thargs) {
++ dput(a->h_dst);
++ au_whtmp_rmdir_free(a->thargs);
++ a->thargs = NULL;
++ }
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if @dentry dir can be rename destination or not.
++ * success means, it is a logically empty dir.
++ */
++static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
++{
++ return au_test_empty(dentry, whlist);
++}
++
++/*
++ * test if @dentry dir can be rename source or not.
++ * if it can, return 0 and @children is filled.
++ * success means,
++ * - it is a logically empty dir.
++ * - or, it exists on writable branch and has no children including whiteouts
++ * on the lower branch.
++ */
++static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ int err;
++ aufs_bindex_t bstart;
++
++ bstart = au_dbstart(dentry);
++ if (bstart != btgt) {
++ struct au_nhash whlist;
++
++ err = au_nhash_alloc(&whlist, au_sbi(dentry->d_sb)->si_rdhash,
++ GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_test_empty(dentry, &whlist);
++ au_nhash_wh_free(&whlist);
++ goto out;
++ }
++
++ if (bstart == au_dbtaildir(dentry))
++ return 0; /* success */
++
++ err = au_test_empty_lower(dentry);
++
++ out:
++ if (err == -ENOTEMPTY) {
++ AuWarn1("renaming dir who has child(ren) on multiple branches,"
++ " is not supported\n");
++ err = -EXDEV;
++ }
++ return err;
++}
++
++/* side effect: sets whlist and h_dentry */
++static int au_ren_may_dir(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d;
++
++ d = a->dst_dentry;
++ err = au_nhash_alloc(&a->whlist, au_sbi(d->d_sb)->si_rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++
++ err = 0;
++ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
++ au_set_dbstart(d, a->dst_bstart);
++ err = may_rename_dstdir(d, &a->whlist);
++ au_set_dbstart(d, a->btgt);
++ }
++ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
++ if (unlikely(err))
++ goto out;
++
++ d = a->src_dentry;
++ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
++ if (au_ftest_ren(a->flags, ISDIR)) {
++ err = may_rename_srcdir(d, a->btgt);
++ if (unlikely(err)) {
++ au_nhash_wh_free(&a->whlist);
++ a->whlist.nh_num = 0;
++ }
++ }
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * simple tests for rename.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++static int au_may_ren(struct au_ren_args *a)
++{
++ int err, isdir;
++ struct inode *h_inode;
++
++ if (a->src_bstart == a->btgt) {
++ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
++ au_ftest_ren(a->flags, ISDIR));
++ if (unlikely(err))
++ goto out;
++ err = -EINVAL;
++ if (unlikely(a->src_h_dentry == a->h_trap))
++ goto out;
++ }
++
++ err = 0;
++ if (a->dst_bstart != a->btgt)
++ goto out;
++
++ err = -EIO;
++ h_inode = a->dst_h_dentry->d_inode;
++ isdir = !!au_ftest_ren(a->flags, ISDIR);
++ if (!a->dst_dentry->d_inode) {
++ if (unlikely(h_inode))
++ goto out;
++ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
++ isdir);
++ } else {
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
++ isdir);
++ if (unlikely(err))
++ goto out;
++ err = -ENOTEMPTY;
++ if (unlikely(a->dst_h_dentry == a->h_trap))
++ goto out;
++ err = 0;
++ }
++
++ out:
++ if (unlikely(err == -ENOENT || err == -EEXIST))
++ err = -EIO;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * locking order
++ * (VFS)
++ * - src_dir and dir by lock_rename()
++ * - inode if exitsts
++ * (aufs)
++ * - lock all
++ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
++ * + si_read_lock
++ * + di_write_lock2_child()
++ * + di_write_lock_child()
++ * + ii_write_lock_child()
++ * + di_write_lock_child2()
++ * + ii_write_lock_child2()
++ * + src_parent and parent
++ * + di_write_lock_parent()
++ * + ii_write_lock_parent()
++ * + di_write_lock_parent2()
++ * + ii_write_lock_parent2()
++ * + lower src_dir and dir by vfsub_lock_rename()
++ * + verify the every relationships between child and parent. if any
++ * of them failed, unlock all and return -EBUSY.
++ */
++static void au_ren_unlock(struct au_ren_args *a)
++{
++ struct super_block *sb;
++
++ sb = a->dst_dentry->d_sb;
++ if (au_ftest_ren(a->flags, MNT_WRITE))
++ mnt_drop_write(a->br->br_mnt);
++ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
++ a->dst_h_parent, a->dst_hdir);
++}
++
++static int au_ren_lock(struct au_ren_args *a)
++{
++ int err;
++ unsigned int udba;
++
++ err = 0;
++ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
++ a->src_hdir = au_hi(a->src_dir, a->btgt);
++ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
++ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
++ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
++ a->dst_h_parent, a->dst_hdir);
++ udba = au_opt_udba(a->src_dentry->d_sb);
++ if (au_dbstart(a->src_dentry) == a->btgt)
++ err = au_h_verify(a->src_h_dentry, udba,
++ a->src_h_parent->d_inode, a->src_h_parent,
++ a->br);
++ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
++ err = au_h_verify(a->dst_h_dentry, udba,
++ a->dst_h_parent->d_inode, a->dst_h_parent,
++ a->br);
++ if (!err) {
++ err = mnt_want_write(a->br->br_mnt);
++ if (unlikely(err))
++ goto out_unlock;
++ au_fset_ren(a->flags, MNT_WRITE);
++ goto out; /* success */
++ }
++
++ err = au_busy_or_stale();
++
++ out_unlock:
++ au_ren_unlock(a);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_ren_refresh_dir(struct au_ren_args *a)
++{
++ struct inode *dir;
++
++ dir = a->dst_dir;
++ dir->i_version++;
++ if (au_ftest_ren(a->flags, ISDIR)) {
++ /* is this updating defined in POSIX? */
++ au_cpup_attr_timesizes(a->src_inode);
++ au_cpup_attr_nlink(dir, /*force*/1);
++ if (a->dst_inode) {
++ clear_nlink(a->dst_inode);
++ au_cpup_attr_timesizes(a->dst_inode);
++ }
++ }
++ if (au_ibstart(dir) == a->btgt)
++ au_cpup_attr_timesizes(dir);
++
++ if (au_ftest_ren(a->flags, ISSAMEDIR))
++ return;
++
++ dir = a->src_dir;
++ dir->i_version++;
++ if (au_ftest_ren(a->flags, ISDIR))
++ au_cpup_attr_nlink(dir, /*force*/1);
++ if (au_ibstart(dir) == a->btgt)
++ au_cpup_attr_timesizes(dir);
++}
++
++static void au_ren_refresh(struct au_ren_args *a)
++{
++ aufs_bindex_t bend, bindex;
++ struct dentry *d, *h_d;
++ struct inode *i, *h_i;
++ struct super_block *sb;
++
++ d = a->src_dentry;
++ au_set_dbwh(d, -1);
++ bend = au_dbend(d);
++ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++ h_d = au_h_dptr(d, bindex);
++ if (h_d)
++ au_set_h_dptr(d, bindex, NULL);
++ }
++ au_set_dbend(d, a->btgt);
++
++ sb = d->d_sb;
++ i = a->src_inode;
++ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
++ return; /* success */
++
++ bend = au_ibend(i);
++ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++ h_i = au_h_iptr(i, bindex);
++ if (h_i) {
++ au_xino_write0(sb, bindex, h_i->i_ino, 0);
++ /* ignore this error */
++ au_set_h_iptr(i, bindex, NULL, 0);
++ }
++ }
++ au_set_ibend(i, a->btgt);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* mainly for link(2) and rename(2) */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ aufs_bindex_t bdiropq, bwh;
++ struct dentry *parent;
++ struct au_branch *br;
++
++ parent = dentry->d_parent;
++ IMustLock(parent->d_inode); /* dir is locked */
++
++ bdiropq = au_dbdiropq(parent);
++ bwh = au_dbwh(dentry);
++ br = au_sbr(dentry->d_sb, btgt);
++ if (au_br_rdonly(br)
++ || (0 <= bdiropq && bdiropq < btgt)
++ || (0 <= bwh && bwh < btgt))
++ btgt = -1;
++
++ AuDbg("btgt %d\n", btgt);
++ return btgt;
++}
++
++/* sets src_bstart, dst_bstart and btgt */
++static int au_ren_wbr(struct au_ren_args *a)
++{
++ int err;
++ struct au_wr_dir_args wr_dir_args = {
++ /* .force_btgt = -1, */
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ a->src_bstart = au_dbstart(a->src_dentry);
++ a->dst_bstart = au_dbstart(a->dst_dentry);
++ if (au_ftest_ren(a->flags, ISDIR))
++ au_fset_wrdir(wr_dir_args.flags, ISDIR);
++ wr_dir_args.force_btgt = a->src_bstart;
++ if (a->dst_inode && a->dst_bstart < a->src_bstart)
++ wr_dir_args.force_btgt = a->dst_bstart;
++ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
++ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
++ a->btgt = err;
++
++ return err;
++}
++
++static void au_ren_dt(struct au_ren_args *a)
++{
++ a->h_path.dentry = a->src_h_parent;
++ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
++ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
++ a->h_path.dentry = a->dst_h_parent;
++ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
++ }
++
++ au_fclr_ren(a->flags, DT_DSTDIR);
++ if (!au_ftest_ren(a->flags, ISDIR))
++ return;
++
++ a->h_path.dentry = a->src_h_dentry;
++ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
++ if (a->dst_h_dentry->d_inode) {
++ au_fset_ren(a->flags, DT_DSTDIR);
++ a->h_path.dentry = a->dst_h_dentry;
++ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
++ }
++}
++
++static void au_ren_rev_dt(int err, struct au_ren_args *a)
++{
++ struct dentry *h_d;
++ struct mutex *h_mtx;
++
++ au_dtime_revert(a->src_dt + AuPARENT);
++ if (!au_ftest_ren(a->flags, ISSAMEDIR))
++ au_dtime_revert(a->dst_dt + AuPARENT);
++
++ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
++ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_dtime_revert(a->src_dt + AuCHILD);
++ mutex_unlock(h_mtx);
++
++ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
++ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_dtime_revert(a->dst_dt + AuCHILD);
++ mutex_unlock(h_mtx);
++ }
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
++ struct inode *_dst_dir, struct dentry *_dst_dentry)
++{
++ int err;
++ /* reduce stack space */
++ struct au_ren_args *a;
++
++ IMustLock(_src_dir);
++ IMustLock(_dst_dir);
++
++ err = -ENOMEM;
++ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ a->src_dir = _src_dir;
++ a->src_dentry = _src_dentry;
++ a->src_inode = a->src_dentry->d_inode;
++ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
++ a->dst_dir = _dst_dir;
++ a->dst_dentry = _dst_dentry;
++ a->dst_inode = a->dst_dentry->d_inode;
++ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
++ if (a->dst_inode) {
++ IMustLock(a->dst_inode);
++ au_igrab(a->dst_inode);
++ }
++
++ err = -ENOTDIR;
++ if (S_ISDIR(a->src_inode->i_mode)) {
++ au_fset_ren(a->flags, ISDIR);
++ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
++ goto out_free;
++ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++ AuLock_DIR | AuLock_FLUSH);
++ } else
++ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++ AuLock_FLUSH);
++
++ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
++ di_write_lock_parent(a->dst_parent);
++
++ /* which branch we process */
++ err = au_ren_wbr(a);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
++ a->h_path.mnt = a->br->br_mnt;
++
++ /* are they available to be renamed */
++ err = au_ren_may_dir(a);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* prepare the writable parent dir on the same branch */
++ if (a->dst_bstart == a->btgt) {
++ au_fset_ren(a->flags, WHDST);
++ } else {
++ err = au_cpup_dirs(a->dst_dentry, a->btgt);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ if (a->src_dir != a->dst_dir) {
++ /*
++ * this temporary unlock is safe,
++ * because both dir->i_mutex are locked.
++ */
++ di_write_unlock(a->dst_parent);
++ di_write_lock_parent(a->src_parent);
++ err = au_wr_dir_need_wh(a->src_dentry,
++ au_ftest_ren(a->flags, ISDIR),
++ &a->btgt);
++ di_write_unlock(a->src_parent);
++ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
++ au_fclr_ren(a->flags, ISSAMEDIR);
++ } else
++ err = au_wr_dir_need_wh(a->src_dentry,
++ au_ftest_ren(a->flags, ISDIR),
++ &a->btgt);
++ if (unlikely(err < 0))
++ goto out_children;
++ if (err)
++ au_fset_ren(a->flags, WHSRC);
++
++ /* lock them all */
++ err = au_ren_lock(a);
++ if (unlikely(err))
++ goto out_children;
++
++ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) {
++ err = au_may_ren(a);
++ if (unlikely(err))
++ goto out_hdir;
++ }
++
++ /* store timestamps to be revertible */
++ au_ren_dt(a);
++
++ /* here we go */
++ err = do_rename(a);
++ if (unlikely(err))
++ goto out_dt;
++
++ /* update dir attributes */
++ au_ren_refresh_dir(a);
++
++ /* dput/iput all lower dentries */
++ au_ren_refresh(a);
++
++ goto out_hdir; /* success */
++
++ out_dt:
++ au_ren_rev_dt(err, a);
++ out_hdir:
++ au_ren_unlock(a);
++ out_children:
++ au_nhash_wh_free(&a->whlist);
++ out_unlock:
++ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
++ au_update_dbstart(a->dst_dentry);
++ d_drop(a->dst_dentry);
++ }
++ if (!err)
++ d_move(a->src_dentry, a->dst_dentry);
++ if (au_ftest_ren(a->flags, ISSAMEDIR))
++ di_write_unlock(a->dst_parent);
++ else
++ di_write_unlock2(a->src_parent, a->dst_parent);
++ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
++ out_free:
++ iput(a->dst_inode);
++ if (a->thargs)
++ au_whtmp_rmdir_free(a->thargs);
++ kfree(a);
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/Kconfig b/fs/aufs/Kconfig
+--- a/fs/aufs/Kconfig 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Kconfig 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,117 @@
++config AUFS_FS
++ tristate "Aufs (Advanced multi layered unification filesystem) support"
++ depends on EXPERIMENTAL
++ help
++ Aufs is a stackable unification filesystem such as Unionfs,
++ which unifies several directories and provides a merged single
++ directory.
++ In the early days, aufs was entirely re-designed and
++ re-implemented Unionfs Version 1.x series. Introducing many
++ original ideas, approaches and improvements, it becomes totally
++ different from Unionfs while keeping the basic features.
++
++if AUFS_FS
++choice
++ prompt "Maximum number of branches"
++ default AUFS_BRANCH_MAX_127
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_127
++ bool "127"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_511
++ bool "511"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_1023
++ bool "1023"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_32767
++ bool "32767"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++endchoice
++
++config AUFS_HINOTIFY
++ bool "Use inotify to detect actions on a branch"
++ depends on INOTIFY
++ help
++ If you want to modify files on branches directly, eg. bypassing aufs,
++ and want aufs to detect the changes of them fully, then enable this
++ option and use 'udba=inotify' mount option.
++ It will have a negative impact to the performance.
++ See detail in aufs.5.
++
++config AUFS_EXPORT
++ bool "NFS-exportable aufs"
++ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
++ help
++ If you want to export your mounted aufs via NFS, then enable this
++ option. There are several requirements for this configuration.
++ See detail in aufs.5.
++
++config AUFS_SHWH
++ bool "Show whiteouts"
++ help
++ If you want to make the whiteouts in aufs visible, then enable
++ this option and specify 'shwh' mount option. Although it may
++ sounds like philosophy or something, but in technically it
++ simply shows the name of whiteout with keeping its behaviour.
++
++config AUFS_BR_RAMFS
++ bool "Ramfs (initramfs/rootfs) as an aufs branch"
++ help
++ If you want to use ramfs as an aufs branch fs, then enable this
++ option. Generally tmpfs is recommended.
++ Aufs prohibited them to be a branch fs by default, because
++ initramfs becomes unusable after switch_root or something
++ generally. If you sets initramfs as an aufs branch and boot your
++ system by switch_root, you will meet a problem easily since the
++ files in initramfs may be inaccessible.
++ Unless you are going to use ramfs as an aufs branch fs without
++ switch_root or something, leave it N.
++
++config AUFS_DEBUG
++ bool "Debug aufs"
++ help
++ Enable this to compile aufs internal debug code.
++ It will have a negative impact to the performance.
++
++config AUFS_MAGIC_SYSRQ
++ bool
++ depends on AUFS_DEBUG && MAGIC_SYSRQ
++ default y
++ help
++ Automatic configuration for internal use.
++ When aufs supports Magic SysRq, enabled automatically.
++
++config AUFS_BDEV_LOOP
++ bool
++ depends on BLK_DEV_LOOP
++ default y
++ help
++ Automatic configuration for internal use.
++ Convert =[ym] into =y.
++
++config AUFS_INO_T_64
++ bool
++ depends on AUFS_EXPORT
++ depends on 64BIT && !(ALPHA || S390)
++ default y
++ help
++ Automatic configuration for internal use.
++ /* typedef unsigned long/int __kernel_ino_t */
++ /* alpha and s390x are int */
++endif
+diff -Naur a/fs/aufs/loop.c b/fs/aufs/loop.c
+--- a/fs/aufs/loop.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * support for loopback block device as a branch
++ */
++
++#include <linux/loop.h>
++#include "aufs.h"
++
++/*
++ * test if two lower dentries have overlapping branches.
++ */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ struct inode *h_inode;
++ struct loop_device *l;
++
++ h_inode = h_d1->d_inode;
++ if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
++ return 0;
++
++ l = h_inode->i_sb->s_bdev->bd_disk->private_data;
++ h_d1 = l->lo_backing_file->f_dentry;
++ /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
++ if (unlikely(h_d1->d_sb == sb))
++ return 1;
++ return !!au_test_subdir(h_d1, h_d2);
++}
++
++/* true if a kernel thread named 'loop[0-9].*' accesses a file */
++int au_test_loopback_kthread(void)
++{
++ const char c = current->comm[4];
++
++ return current->mm == NULL
++ && '0' <= c && c <= '9'
++ && strncmp(current->comm, "loop", 4) == 0;
++}
+diff -Naur a/fs/aufs/loop.h b/fs/aufs/loop.h
+--- a/fs/aufs/loop.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * support for loopback mount as a branch
++ */
++
++#ifndef __AUFS_LOOP_H__
++#define __AUFS_LOOP_H__
++
++#ifdef __KERNEL__
++
++struct dentry;
++struct super_block;
++
++#ifdef CONFIG_AUFS_BDEV_LOOP
++/* loop.c */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2);
++int au_test_loopback_kthread(void);
++#else
++static inline
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ return 0;
++}
++
++static inline int au_test_loopback_kthread(void)
++{
++ return 0;
++}
++#endif /* BLK_DEV_LOOP */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_LOOP_H__ */
+diff -Naur a/fs/aufs/magic.mk b/fs/aufs/magic.mk
+--- a/fs/aufs/magic.mk 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/magic.mk 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,52 @@
++
++# defined in ${srctree}/fs/fuse/inode.c
++# tristate
++ifdef CONFIG_FUSE_FS
++ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
++endif
++
++# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
++# tristate
++ifdef CONFIG_OCFS2_FS
++ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
++endif
++
++# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
++# tristate
++ifdef CONFIG_OCFS2_FS_O2CB
++ccflags-y += -DDLMFS_MAGIC=0x76a9f425
++endif
++
++# defined in ${srctree}/fs/ramfs/inode.c
++# always true
++ccflags-y += -DRAMFS_MAGIC=0x858458f6
++
++# defined in ${srctree}/fs/cifs/cifsfs.c
++# tristate
++ifdef CONFIG_CIFS_FS
++ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
++endif
++
++# defined in ${srctree}/fs/xfs/xfs_sb.h
++# tristate
++ifdef CONFIG_XFS_FS
++ccflags-y += -DXFS_SB_MAGIC=0x58465342
++endif
++
++# defined in ${srctree}/fs/configfs/mount.c
++# tristate
++ifdef CONFIG_CONFIGFS_FS
++ccflags-y += -DCONFIGFS_MAGIC=0x62656570
++endif
++
++# defined in ${srctree}/fs/9p/v9fs.h
++# tristate
++ifdef CONFIG_9P_FS
++ccflags-y += -DV9FS_MAGIC=0x01021997
++endif
++
++# defined in ${srctree}/fs/ubifs/ubifs.h
++# tristate
++ifdef CONFIG_UBIFS_FS
++ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
++endif
+diff -Naur a/fs/aufs/Makefile b/fs/aufs/Makefile
+--- a/fs/aufs/Makefile 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Makefile 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,22 @@
++
++include ${src}/magic.mk
++-include ${src}/priv_def.mk
++
++obj-$(CONFIG_AUFS_FS) += aufs.o
++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
++ wkq.o vfsub.o dcsub.o \
++ cpup.o whout.o plink.o wbr_policy.o \
++ dinfo.o dentry.o \
++ finfo.o file.o f_op.o \
++ dir.o vdir.o \
++ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
++ ioctl.o
++
++# all are boolean
++aufs-$(CONFIG_SYSFS) += sysfs.o
++aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
++aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
++aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
++aufs-$(CONFIG_AUFS_EXPORT) += export.o
++aufs-$(CONFIG_AUFS_DEBUG) += debug.o
++aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
+diff -Naur a/fs/aufs/module.c b/fs/aufs/module.c
+--- a/fs/aufs/module.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * module global variables and operations
++ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include "aufs.h"
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
++{
++ if (new_sz <= nused)
++ return p;
++
++ p = krealloc(p, new_sz, gfp);
++ if (p)
++ memset(p + nused, 0, new_sz - nused);
++ return p;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * aufs caches
++ */
++struct kmem_cache *au_cachep[AuCache_Last];
++static int __init au_cache_init(void)
++{
++ au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
++ if (au_cachep[AuCache_DINFO])
++ au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
++ if (au_cachep[AuCache_ICNTNR])
++ au_cachep[AuCache_FINFO] = AuCache(au_finfo);
++ if (au_cachep[AuCache_FINFO])
++ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
++ if (au_cachep[AuCache_VDIR])
++ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
++ if (au_cachep[AuCache_DEHSTR])
++ return 0;
++
++ return -ENOMEM;
++}
++
++static void au_cache_fin(void)
++{
++ int i;
++ for (i = 0; i < AuCache_Last; i++)
++ if (au_cachep[i]) {
++ kmem_cache_destroy(au_cachep[i]);
++ au_cachep[i] = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_dir_roflags;
++
++/*
++ * functions for module interface.
++ */
++MODULE_LICENSE("GPL");
++/* MODULE_LICENSE("GPL v2"); */
++MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
++MODULE_DESCRIPTION(AUFS_NAME
++ " -- Advanced multi layered unification filesystem");
++MODULE_VERSION(AUFS_VERSION);
++
++/* it should be 'byte', but param_set_byte() prints it by "%c" */
++short aufs_nwkq = AUFS_NWKQ_DEF;
++MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
++module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
++
++/* this module parameter has no meaning when SYSFS is disabled */
++int sysaufs_brs = 1;
++MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
++module_param_named(brs, sysaufs_brs, int, S_IRUGO);
++
++/* ---------------------------------------------------------------------- */
++
++static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
++
++int au_seq_path(struct seq_file *seq, struct path *path)
++{
++ return seq_path(seq, path, au_esc_chars);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int __init aufs_init(void)
++{
++ int err, i;
++ char *p;
++
++ p = au_esc_chars;
++ for (i = 1; i <= ' '; i++)
++ *p++ = i;
++ *p++ = '\\';
++ *p++ = '\x7f';
++ *p = 0;
++
++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
++
++ sysaufs_brs_init();
++ au_debug_init();
++
++ err = -EINVAL;
++ if (unlikely(aufs_nwkq <= 0))
++ goto out;
++
++ err = sysaufs_init();
++ if (unlikely(err))
++ goto out;
++ err = au_wkq_init();
++ if (unlikely(err))
++ goto out_sysaufs;
++ err = au_hinotify_init();
++ if (unlikely(err))
++ goto out_wkq;
++ err = au_sysrq_init();
++ if (unlikely(err))
++ goto out_hin;
++ err = au_cache_init();
++ if (unlikely(err))
++ goto out_sysrq;
++ err = register_filesystem(&aufs_fs_type);
++ if (unlikely(err))
++ goto out_cache;
++ pr_info(AUFS_NAME " " AUFS_VERSION "\n");
++ goto out; /* success */
++
++ out_cache:
++ au_cache_fin();
++ out_sysrq:
++ au_sysrq_fin();
++ out_hin:
++ au_hinotify_fin();
++ out_wkq:
++ au_wkq_fin();
++ out_sysaufs:
++ sysaufs_fin();
++ out:
++ return err;
++}
++
++static void __exit aufs_exit(void)
++{
++ unregister_filesystem(&aufs_fs_type);
++ au_cache_fin();
++ au_sysrq_fin();
++ au_hinotify_fin();
++ au_wkq_fin();
++ sysaufs_fin();
++}
++
++module_init(aufs_init);
++module_exit(aufs_exit);
+diff -Naur a/fs/aufs/module.h b/fs/aufs/module.h
+--- a/fs/aufs/module.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * module initialization and module-global
++ */
++
++#ifndef __AUFS_MODULE_H__
++#define __AUFS_MODULE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/slab.h>
++
++struct path;
++struct seq_file;
++
++/* module parameters */
++extern short aufs_nwkq;
++extern int sysaufs_brs;
++
++/* ---------------------------------------------------------------------- */
++
++extern int au_dir_roflags;
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
++int au_seq_path(struct seq_file *seq, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++/* kmem cache */
++enum {
++ AuCache_DINFO,
++ AuCache_ICNTNR,
++ AuCache_FINFO,
++ AuCache_VDIR,
++ AuCache_DEHSTR,
++#ifdef CONFIG_AUFS_HINOTIFY
++ AuCache_HINOTIFY,
++#endif
++ AuCache_Last
++};
++
++#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
++
++extern struct kmem_cache *au_cachep[];
++
++#define AuCacheFuncs(name, index) \
++static inline void *au_cache_alloc_##name(void) \
++{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
++static inline void au_cache_free_##name(void *p) \
++{ kmem_cache_free(au_cachep[AuCache_##index], p); }
++
++AuCacheFuncs(dinfo, DINFO);
++AuCacheFuncs(icntnr, ICNTNR);
++AuCacheFuncs(finfo, FINFO);
++AuCacheFuncs(vdir, VDIR);
++AuCacheFuncs(dehstr, DEHSTR);
++
++/* ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MODULE_H__ */
+diff -Naur a/fs/aufs/opts.c b/fs/aufs/opts.c
+--- a/fs/aufs/opts.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1533 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount options/flags
++ */
++
++#include <linux/file.h>
++#include <linux/namei.h>
++#include <linux/types.h> /* a distribution requires */
++#include <linux/parser.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++enum {
++ Opt_br,
++ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
++ Opt_idel, Opt_imod, Opt_ireorder,
++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
++ Opt_rdblk_def, Opt_rdhash_def,
++ Opt_xino, Opt_zxino, Opt_noxino,
++ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
++ Opt_trunc_xino_path, Opt_itrunc_xino,
++ Opt_trunc_xib, Opt_notrunc_xib,
++ Opt_shwh, Opt_noshwh,
++ Opt_plink, Opt_noplink, Opt_list_plink,
++ Opt_udba,
++ /* Opt_lock, Opt_unlock, */
++ Opt_cmd, Opt_cmd_args,
++ Opt_diropq_a, Opt_diropq_w,
++ Opt_warn_perm, Opt_nowarn_perm,
++ Opt_wbr_copyup, Opt_wbr_create,
++ Opt_refrof, Opt_norefrof,
++ Opt_verbose, Opt_noverbose,
++ Opt_sum, Opt_nosum, Opt_wsum,
++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
++};
++
++static match_table_t options = {
++ {Opt_br, "br=%s"},
++ {Opt_br, "br:%s"},
++
++ {Opt_add, "add=%d:%s"},
++ {Opt_add, "add:%d:%s"},
++ {Opt_add, "ins=%d:%s"},
++ {Opt_add, "ins:%d:%s"},
++ {Opt_append, "append=%s"},
++ {Opt_append, "append:%s"},
++ {Opt_prepend, "prepend=%s"},
++ {Opt_prepend, "prepend:%s"},
++
++ {Opt_del, "del=%s"},
++ {Opt_del, "del:%s"},
++ /* {Opt_idel, "idel:%d"}, */
++ {Opt_mod, "mod=%s"},
++ {Opt_mod, "mod:%s"},
++ /* {Opt_imod, "imod:%d:%s"}, */
++
++ {Opt_dirwh, "dirwh=%d"},
++
++ {Opt_xino, "xino=%s"},
++ {Opt_noxino, "noxino"},
++ {Opt_trunc_xino, "trunc_xino"},
++ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
++ {Opt_notrunc_xino, "notrunc_xino"},
++ {Opt_trunc_xino_path, "trunc_xino=%s"},
++ {Opt_itrunc_xino, "itrunc_xino=%d"},
++ /* {Opt_zxino, "zxino=%s"}, */
++ {Opt_trunc_xib, "trunc_xib"},
++ {Opt_notrunc_xib, "notrunc_xib"},
++
++ {Opt_plink, "plink"},
++ {Opt_noplink, "noplink"},
++#ifdef CONFIG_AUFS_DEBUG
++ {Opt_list_plink, "list_plink"},
++#endif
++
++ {Opt_udba, "udba=%s"},
++
++ {Opt_diropq_a, "diropq=always"},
++ {Opt_diropq_a, "diropq=a"},
++ {Opt_diropq_w, "diropq=whiteouted"},
++ {Opt_diropq_w, "diropq=w"},
++
++ {Opt_warn_perm, "warn_perm"},
++ {Opt_nowarn_perm, "nowarn_perm"},
++
++ /* keep them temporary */
++ {Opt_ignore_silent, "coo=%s"},
++ {Opt_ignore_silent, "nodlgt"},
++ {Opt_ignore_silent, "nodirperm1"},
++ {Opt_ignore_silent, "clean_plink"},
++
++#ifdef CONFIG_AUFS_SHWH
++ {Opt_shwh, "shwh"},
++#endif
++ {Opt_noshwh, "noshwh"},
++
++ {Opt_rendir, "rendir=%d"},
++
++ {Opt_refrof, "refrof"},
++ {Opt_norefrof, "norefrof"},
++
++ {Opt_verbose, "verbose"},
++ {Opt_verbose, "v"},
++ {Opt_noverbose, "noverbose"},
++ {Opt_noverbose, "quiet"},
++ {Opt_noverbose, "q"},
++ {Opt_noverbose, "silent"},
++
++ {Opt_sum, "sum"},
++ {Opt_nosum, "nosum"},
++ {Opt_wsum, "wsum"},
++
++ {Opt_rdcache, "rdcache=%d"},
++ {Opt_rdblk, "rdblk=%d"},
++ {Opt_rdblk_def, "rdblk=def"},
++ {Opt_rdhash, "rdhash=%d"},
++ {Opt_rdhash_def, "rdhash=def"},
++
++ {Opt_wbr_create, "create=%s"},
++ {Opt_wbr_create, "create_policy=%s"},
++ {Opt_wbr_copyup, "cpup=%s"},
++ {Opt_wbr_copyup, "copyup=%s"},
++ {Opt_wbr_copyup, "copyup_policy=%s"},
++
++ /* internal use for the scripts */
++ {Opt_ignore_silent, "si=%s"},
++
++ {Opt_br, "dirs=%s"},
++ {Opt_ignore, "debug=%d"},
++ {Opt_ignore, "delete=whiteout"},
++ {Opt_ignore, "delete=all"},
++ {Opt_ignore, "imap=%s"},
++
++ {Opt_err, NULL}
++};
++
++/* ---------------------------------------------------------------------- */
++
++static const char *au_parser_pattern(int val, struct match_token *token)
++{
++ while (token->pattern) {
++ if (token->token == val)
++ return token->pattern;
++ token++;
++ }
++ BUG();
++ return "??";
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t brperms = {
++ {AuBrPerm_RO, AUFS_BRPERM_RO},
++ {AuBrPerm_RR, AUFS_BRPERM_RR},
++ {AuBrPerm_RW, AUFS_BRPERM_RW},
++
++ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
++ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
++ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
++
++ {AuBrPerm_ROWH, "nfsro"},
++ {AuBrPerm_RO, NULL}
++};
++
++static int br_perm_val(char *perm)
++{
++ int val;
++ substring_t args[MAX_OPT_ARGS];
++
++ val = match_token(perm, brperms, args);
++ return val;
++}
++
++const char *au_optstr_br_perm(int brperm)
++{
++ return au_parser_pattern(brperm, (void *)brperms);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t udbalevel = {
++ {AuOpt_UDBA_REVAL, "reval"},
++ {AuOpt_UDBA_NONE, "none"},
++#ifdef CONFIG_AUFS_HINOTIFY
++ {AuOpt_UDBA_HINOTIFY, "inotify"},
++#endif
++ {-1, NULL}
++};
++
++static int udba_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++
++ return match_token(str, udbalevel, args);
++}
++
++const char *au_optstr_udba(int udba)
++{
++ return au_parser_pattern(udba, (void *)udbalevel);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t au_wbr_create_policy = {
++ {AuWbrCreate_TDP, "tdp"},
++ {AuWbrCreate_TDP, "top-down-parent"},
++ {AuWbrCreate_RR, "rr"},
++ {AuWbrCreate_RR, "round-robin"},
++ {AuWbrCreate_MFS, "mfs"},
++ {AuWbrCreate_MFS, "most-free-space"},
++ {AuWbrCreate_MFSV, "mfs:%d"},
++ {AuWbrCreate_MFSV, "most-free-space:%d"},
++
++ {AuWbrCreate_MFSRR, "mfsrr:%d"},
++ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
++ {AuWbrCreate_PMFS, "pmfs"},
++ {AuWbrCreate_PMFSV, "pmfs:%d"},
++
++ {-1, NULL}
++};
++
++/*
++ * cf. linux/lib/parser.c and cmdline.c
++ * gave up calling memparse() since it uses simple_strtoull() instead of
++ * strict_...().
++ */
++static int au_match_ull(substring_t *s, unsigned long long *result)
++{
++ int err;
++ unsigned int len;
++ char a[32];
++
++ err = -ERANGE;
++ len = s->to - s->from;
++ if (len + 1 <= sizeof(a)) {
++ memcpy(a, s->from, len);
++ a[len] = '\0';
++ err = strict_strtoull(a, 0, result);
++ }
++ return err;
++}
++
++static int au_wbr_mfs_wmark(substring_t *arg, char *str,
++ struct au_opt_wbr_create *create)
++{
++ int err;
++ unsigned long long ull;
++
++ err = 0;
++ if (!au_match_ull(arg, &ull))
++ create->mfsrr_watermark = ull;
++ else {
++ AuErr("bad integer in %s\n", str);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static int au_wbr_mfs_sec(substring_t *arg, char *str,
++ struct au_opt_wbr_create *create)
++{
++ int n, err;
++
++ err = 0;
++ if (!match_int(arg, &n) && 0 <= n)
++ create->mfs_second = n;
++ else {
++ AuErr("bad integer in %s\n", str);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
++{
++ int err, e;
++ substring_t args[MAX_OPT_ARGS];
++
++ err = match_token(str, au_wbr_create_policy, args);
++ create->wbr_create = err;
++ switch (err) {
++ case AuWbrCreate_MFSRRV:
++ e = au_wbr_mfs_wmark(&args[0], str, create);
++ if (!e)
++ e = au_wbr_mfs_sec(&args[1], str, create);
++ if (unlikely(e))
++ err = e;
++ break;
++ case AuWbrCreate_MFSRR:
++ e = au_wbr_mfs_wmark(&args[0], str, create);
++ if (unlikely(e)) {
++ err = e;
++ break;
++ }
++ /*FALLTHROUGH*/
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_PMFS:
++ create->mfs_second = AUFS_MFS_SECOND_DEF;
++ break;
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFSV:
++ e = au_wbr_mfs_sec(&args[0], str, create);
++ if (unlikely(e))
++ err = e;
++ break;
++ }
++
++ return err;
++}
++
++const char *au_optstr_wbr_create(int wbr_create)
++{
++ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
++}
++
++static match_table_t au_wbr_copyup_policy = {
++ {AuWbrCopyup_TDP, "tdp"},
++ {AuWbrCopyup_TDP, "top-down-parent"},
++ {AuWbrCopyup_BUP, "bup"},
++ {AuWbrCopyup_BUP, "bottom-up-parent"},
++ {AuWbrCopyup_BU, "bu"},
++ {AuWbrCopyup_BU, "bottom-up"},
++ {-1, NULL}
++};
++
++static int au_wbr_copyup_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++
++ return match_token(str, au_wbr_copyup_policy, args);
++}
++
++const char *au_optstr_wbr_copyup(int wbr_copyup)
++{
++ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
++
++static void dump_opts(struct au_opts *opts)
++{
++#ifdef CONFIG_AUFS_DEBUG
++ /* reduce stack space */
++ union {
++ struct au_opt_add *add;
++ struct au_opt_del *del;
++ struct au_opt_mod *mod;
++ struct au_opt_xino *xino;
++ struct au_opt_xino_itrunc *xino_itrunc;
++ struct au_opt_wbr_create *create;
++ } u;
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ u.add = &opt->add;
++ AuDbg("add {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ u.del = &opt->del;
++ AuDbg("del {%s, %p}\n",
++ u.del->pathname, u.del->h_path.dentry);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ u.mod = &opt->mod;
++ AuDbg("mod {%s, 0x%x, %p}\n",
++ u.mod->path, u.mod->perm, u.mod->h_root);
++ break;
++ case Opt_append:
++ u.add = &opt->add;
++ AuDbg("append {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_prepend:
++ u.add = &opt->add;
++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_dirwh:
++ AuDbg("dirwh %d\n", opt->dirwh);
++ break;
++ case Opt_rdcache:
++ AuDbg("rdcache %d\n", opt->rdcache);
++ break;
++ case Opt_rdblk:
++ AuDbg("rdblk %u\n", opt->rdblk);
++ break;
++ case Opt_rdblk_def:
++ AuDbg("rdblk_def\n");
++ break;
++ case Opt_rdhash:
++ AuDbg("rdhash %u\n", opt->rdhash);
++ break;
++ case Opt_rdhash_def:
++ AuDbg("rdhash_def\n");
++ break;
++ case Opt_xino:
++ u.xino = &opt->xino;
++ AuDbg("xino {%s %.*s}\n",
++ u.xino->path,
++ AuDLNPair(u.xino->file->f_dentry));
++ break;
++ case Opt_trunc_xino:
++ AuLabel(trunc_xino);
++ break;
++ case Opt_notrunc_xino:
++ AuLabel(notrunc_xino);
++ break;
++ case Opt_trunc_xino_path:
++ case Opt_itrunc_xino:
++ u.xino_itrunc = &opt->xino_itrunc;
++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
++ break;
++
++ case Opt_noxino:
++ AuLabel(noxino);
++ break;
++ case Opt_trunc_xib:
++ AuLabel(trunc_xib);
++ break;
++ case Opt_notrunc_xib:
++ AuLabel(notrunc_xib);
++ break;
++ case Opt_shwh:
++ AuLabel(shwh);
++ break;
++ case Opt_noshwh:
++ AuLabel(noshwh);
++ break;
++ case Opt_plink:
++ AuLabel(plink);
++ break;
++ case Opt_noplink:
++ AuLabel(noplink);
++ break;
++ case Opt_list_plink:
++ AuLabel(list_plink);
++ break;
++ case Opt_udba:
++ AuDbg("udba %d, %s\n",
++ opt->udba, au_optstr_udba(opt->udba));
++ break;
++ case Opt_diropq_a:
++ AuLabel(diropq_a);
++ break;
++ case Opt_diropq_w:
++ AuLabel(diropq_w);
++ break;
++ case Opt_warn_perm:
++ AuLabel(warn_perm);
++ break;
++ case Opt_nowarn_perm:
++ AuLabel(nowarn_perm);
++ break;
++ case Opt_refrof:
++ AuLabel(refrof);
++ break;
++ case Opt_norefrof:
++ AuLabel(norefrof);
++ break;
++ case Opt_verbose:
++ AuLabel(verbose);
++ break;
++ case Opt_noverbose:
++ AuLabel(noverbose);
++ break;
++ case Opt_sum:
++ AuLabel(sum);
++ break;
++ case Opt_nosum:
++ AuLabel(nosum);
++ break;
++ case Opt_wsum:
++ AuLabel(wsum);
++ break;
++ case Opt_wbr_create:
++ u.create = &opt->wbr_create;
++ AuDbg("create %d, %s\n", u.create->wbr_create,
++ au_optstr_wbr_create(u.create->wbr_create));
++ switch (u.create->wbr_create) {
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFSV:
++ AuDbg("%d sec\n", u.create->mfs_second);
++ break;
++ case AuWbrCreate_MFSRR:
++ AuDbg("%llu watermark\n",
++ u.create->mfsrr_watermark);
++ break;
++ case AuWbrCreate_MFSRRV:
++ AuDbg("%llu watermark, %d sec\n",
++ u.create->mfsrr_watermark,
++ u.create->mfs_second);
++ break;
++ }
++ break;
++ case Opt_wbr_copyup:
++ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
++ au_optstr_wbr_copyup(opt->wbr_copyup));
++ break;
++ default:
++ BUG();
++ }
++ opt++;
++ }
++#endif
++}
++
++void au_opts_free(struct au_opts *opts)
++{
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ case Opt_append:
++ case Opt_prepend:
++ path_put(&opt->add.path);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ path_put(&opt->del.h_path);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ dput(opt->mod.h_root);
++ break;
++ case Opt_xino:
++ fput(opt->xino.file);
++ break;
++ }
++ opt++;
++ }
++}
++
++static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct au_opt_add *add = &opt->add;
++ char *p;
++
++ add->bindex = bindex;
++ add->perm = AuBrPerm_Last;
++ add->pathname = opt_str;
++ p = strchr(opt_str, '=');
++ if (p) {
++ *p++ = 0;
++ if (*p)
++ add->perm = br_perm_val(p);
++ }
++
++ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
++ if (!err) {
++ if (!p) {
++ add->perm = AuBrPerm_RO;
++ if (au_test_fs_rr(add->path.dentry->d_sb))
++ add->perm = AuBrPerm_RR;
++ else if (!bindex && !(sb_flags & MS_RDONLY))
++ add->perm = AuBrPerm_RW;
++ }
++ opt->type = Opt_add;
++ goto out;
++ }
++ AuErr("lookup failed %s (%d)\n", add->pathname, err);
++ err = -EINVAL;
++
++ out:
++ return err;
++}
++
++static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
++{
++ int err;
++
++ del->pathname = args[0].from;
++ AuDbg("del path %s\n", del->pathname);
++
++ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
++ if (unlikely(err))
++ AuErr("lookup failed %s (%d)\n", del->pathname, err);
++
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_opt_del *del, substring_t args[])
++{
++ int err;
++ struct dentry *root;
++
++ err = -EINVAL;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (bindex < 0 || au_sbend(sb) < bindex) {
++ AuErr("out of bounds, %d\n", bindex);
++ goto out;
++ }
++
++ err = 0;
++ del->h_path.dentry = dget(au_h_dptr(root, bindex));
++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
++
++ out:
++ aufs_read_unlock(root, !AuLock_IR);
++ return err;
++}
++#endif
++
++static int au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
++{
++ int err;
++ struct path path;
++ char *p;
++
++ err = -EINVAL;
++ mod->path = args[0].from;
++ p = strchr(mod->path, '=');
++ if (unlikely(!p)) {
++ AuErr("no permssion %s\n", args[0].from);
++ goto out;
++ }
++
++ *p++ = 0;
++ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
++ if (unlikely(err)) {
++ AuErr("lookup failed %s (%d)\n", mod->path, err);
++ goto out;
++ }
++
++ mod->perm = br_perm_val(p);
++ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
++ mod->h_root = dget(path.dentry);
++ path_put(&path);
++
++ out:
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_opt_mod *mod, substring_t args[])
++{
++ int err;
++ struct dentry *root;
++
++ err = -EINVAL;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (bindex < 0 || au_sbend(sb) < bindex) {
++ AuErr("out of bounds, %d\n", bindex);
++ goto out;
++ }
++
++ err = 0;
++ mod->perm = br_perm_val(args[1].from);
++ AuDbg("mod path %s, perm 0x%x, %s\n",
++ mod->path, mod->perm, args[1].from);
++ mod->h_root = dget(au_h_dptr(root, bindex));
++
++ out:
++ aufs_read_unlock(root, !AuLock_IR);
++ return err;
++}
++#endif
++
++static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
++ substring_t args[])
++{
++ int err;
++ struct file *file;
++
++ file = au_xino_create(sb, args[0].from, /*silent*/0);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++
++ err = -EINVAL;
++ if (unlikely(file->f_dentry->d_sb == sb)) {
++ fput(file);
++ AuErr("%s must be outside\n", args[0].from);
++ goto out;
++ }
++
++ err = 0;
++ xino->file = file;
++ xino->path = args[0].from;
++
++ out:
++ return err;
++}
++
++static
++int au_opts_parse_xino_itrunc_path(struct super_block *sb,
++ struct au_opt_xino_itrunc *xino_itrunc,
++ substring_t args[])
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct path path;
++ struct dentry *root;
++
++ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
++ if (unlikely(err)) {
++ AuErr("lookup failed %s (%d)\n", args[0].from, err);
++ goto out;
++ }
++
++ xino_itrunc->bindex = -1;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ if (au_h_dptr(root, bindex) == path.dentry) {
++ xino_itrunc->bindex = bindex;
++ break;
++ }
++ }
++ aufs_read_unlock(root, !AuLock_IR);
++ path_put(&path);
++
++ if (unlikely(xino_itrunc->bindex < 0)) {
++ AuErr("no such branch %s\n", args[0].from);
++ err = -EINVAL;
++ }
++
++ out:
++ return err;
++}
++
++/* called without aufs lock */
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
++{
++ int err, n, token;
++ aufs_bindex_t bindex;
++ unsigned char skipped;
++ struct dentry *root;
++ struct au_opt *opt, *opt_tail;
++ char *opt_str;
++ /* reduce the stack space */
++ union {
++ struct au_opt_xino_itrunc *xino_itrunc;
++ struct au_opt_wbr_create *create;
++ } u;
++ struct {
++ substring_t args[MAX_OPT_ARGS];
++ } *a;
++
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ root = sb->s_root;
++ err = 0;
++ bindex = 0;
++ opt = opts->opt;
++ opt_tail = opt + opts->max_opt - 1;
++ opt->type = Opt_tail;
++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
++ err = -EINVAL;
++ skipped = 0;
++ token = match_token(opt_str, options, a->args);
++ switch (token) {
++ case Opt_br:
++ err = 0;
++ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
++ && *opt_str) {
++ err = opt_add(opt, opt_str, opts->sb_flags,
++ bindex++);
++ if (unlikely(!err && ++opt > opt_tail)) {
++ err = -E2BIG;
++ break;
++ }
++ opt->type = Opt_tail;
++ skipped = 1;
++ }
++ break;
++ case Opt_add:
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ err = opt_add(opt, a->args[1].from, opts->sb_flags,
++ bindex);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_append:
++ err = opt_add(opt, a->args[0].from, opts->sb_flags,
++ /*dummy bindex*/1);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_prepend:
++ err = opt_add(opt, a->args[0].from, opts->sb_flags,
++ /*bindex*/0);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_del:
++ err = au_opts_parse_del(&opt->del, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#if 0 /* reserved for future use */
++ case Opt_idel:
++ del->pathname = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#endif
++ case Opt_mod:
++ err = au_opts_parse_mod(&opt->mod, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#ifdef IMOD /* reserved for future use */
++ case Opt_imod:
++ u.mod->path = "(indexed)";
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#endif
++ case Opt_xino:
++ err = au_opts_parse_xino(sb, &opt->xino, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++
++ case Opt_trunc_xino_path:
++ err = au_opts_parse_xino_itrunc_path
++ (sb, &opt->xino_itrunc, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++
++ case Opt_itrunc_xino:
++ u.xino_itrunc = &opt->xino_itrunc;
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ u.xino_itrunc->bindex = n;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (n < 0 || au_sbend(sb) < n) {
++ AuErr("out of bounds, %d\n", n);
++ aufs_read_unlock(root, !AuLock_IR);
++ break;
++ }
++ aufs_read_unlock(root, !AuLock_IR);
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_dirwh:
++ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_rdcache:
++ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++ case Opt_rdblk:
++ if (unlikely(match_int(&a->args[0], &n)
++ || n <= 0
++ || n > KMALLOC_MAX_SIZE)) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ if (unlikely(n < NAME_MAX)) {
++ AuErr("rdblk must be larger than %d\n",
++ NAME_MAX);
++ break;
++ }
++ opt->rdblk = n;
++ err = 0;
++ opt->type = token;
++ break;
++ case Opt_rdhash:
++ if (unlikely(match_int(&a->args[0], &n)
++ || n <= 0
++ || n * sizeof(struct hlist_head)
++ > KMALLOC_MAX_SIZE)) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ opt->rdhash = n;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_trunc_xino:
++ case Opt_notrunc_xino:
++ case Opt_noxino:
++ case Opt_trunc_xib:
++ case Opt_notrunc_xib:
++ case Opt_shwh:
++ case Opt_noshwh:
++ case Opt_plink:
++ case Opt_noplink:
++ case Opt_list_plink:
++ case Opt_diropq_a:
++ case Opt_diropq_w:
++ case Opt_warn_perm:
++ case Opt_nowarn_perm:
++ case Opt_refrof:
++ case Opt_norefrof:
++ case Opt_verbose:
++ case Opt_noverbose:
++ case Opt_sum:
++ case Opt_nosum:
++ case Opt_wsum:
++ case Opt_rdblk_def:
++ case Opt_rdhash_def:
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_udba:
++ opt->udba = udba_val(a->args[0].from);
++ if (opt->udba >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++
++ case Opt_wbr_create:
++ u.create = &opt->wbr_create;
++ u.create->wbr_create
++ = au_wbr_create_val(a->args[0].from, u.create);
++ if (u.create->wbr_create >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++ case Opt_wbr_copyup:
++ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
++ if (opt->wbr_copyup >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++
++ case Opt_ignore:
++ AuWarn("ignored %s\n", opt_str);
++ /*FALLTHROUGH*/
++ case Opt_ignore_silent:
++ skipped = 1;
++ err = 0;
++ break;
++ case Opt_err:
++ AuErr("unknown option %s\n", opt_str);
++ break;
++ }
++
++ if (!err && !skipped) {
++ if (unlikely(++opt > opt_tail)) {
++ err = -E2BIG;
++ opt--;
++ opt->type = Opt_tail;
++ break;
++ }
++ opt->type = Opt_tail;
++ }
++ }
++
++ kfree(a);
++ dump_opts(opts);
++ if (unlikely(err))
++ au_opts_free(opts);
++
++ out:
++ return err;
++}
++
++static int au_opt_wbr_create(struct super_block *sb,
++ struct au_opt_wbr_create *create)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = 1; /* handled */
++ sbinfo = au_sbi(sb);
++ if (sbinfo->si_wbr_create_ops->fin) {
++ err = sbinfo->si_wbr_create_ops->fin(sb);
++ if (!err)
++ err = 1;
++ }
++
++ sbinfo->si_wbr_create = create->wbr_create;
++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
++ switch (create->wbr_create) {
++ case AuWbrCreate_MFSRRV:
++ case AuWbrCreate_MFSRR:
++ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
++ /*FALLTHROUGH*/
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFS:
++ case AuWbrCreate_PMFSV:
++ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
++ break;
++ }
++
++ if (sbinfo->si_wbr_create_ops->init)
++ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
++
++ return err;
++}
++
++/*
++ * returns,
++ * plus: processed without an error
++ * zero: unprocessed
++ */
++static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
++ struct au_opts *opts)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = 1; /* handled */
++ sbinfo = au_sbi(sb);
++ switch (opt->type) {
++ case Opt_udba:
++ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++ sbinfo->si_mntflags |= opt->udba;
++ opts->given_udba |= opt->udba;
++ break;
++
++ case Opt_plink:
++ au_opt_set(sbinfo->si_mntflags, PLINK);
++ break;
++ case Opt_noplink:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_put(sb);
++ au_opt_clr(sbinfo->si_mntflags, PLINK);
++ break;
++ case Opt_list_plink:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_list(sb);
++ break;
++
++ case Opt_diropq_a:
++ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++ break;
++ case Opt_diropq_w:
++ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++ break;
++
++ case Opt_warn_perm:
++ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
++ break;
++ case Opt_nowarn_perm:
++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
++ break;
++
++ case Opt_refrof:
++ au_opt_set(sbinfo->si_mntflags, REFROF);
++ break;
++ case Opt_norefrof:
++ au_opt_clr(sbinfo->si_mntflags, REFROF);
++ break;
++
++ case Opt_verbose:
++ au_opt_set(sbinfo->si_mntflags, VERBOSE);
++ break;
++ case Opt_noverbose:
++ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
++ break;
++
++ case Opt_sum:
++ au_opt_set(sbinfo->si_mntflags, SUM);
++ break;
++ case Opt_wsum:
++ au_opt_clr(sbinfo->si_mntflags, SUM);
++ au_opt_set(sbinfo->si_mntflags, SUM_W);
++ case Opt_nosum:
++ au_opt_clr(sbinfo->si_mntflags, SUM);
++ au_opt_clr(sbinfo->si_mntflags, SUM_W);
++ break;
++
++ case Opt_wbr_create:
++ err = au_opt_wbr_create(sb, &opt->wbr_create);
++ break;
++ case Opt_wbr_copyup:
++ sbinfo->si_wbr_copyup = opt->wbr_copyup;
++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
++ break;
++
++ case Opt_dirwh:
++ sbinfo->si_dirwh = opt->dirwh;
++ break;
++
++ case Opt_rdcache:
++ sbinfo->si_rdcache = opt->rdcache * HZ;
++ break;
++ case Opt_rdblk:
++ sbinfo->si_rdblk = opt->rdblk;
++ break;
++ case Opt_rdblk_def:
++ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++ break;
++ case Opt_rdhash:
++ sbinfo->si_rdhash = opt->rdhash;
++ break;
++ case Opt_rdhash_def:
++ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++ break;
++
++ case Opt_shwh:
++ au_opt_set(sbinfo->si_mntflags, SHWH);
++ break;
++ case Opt_noshwh:
++ au_opt_clr(sbinfo->si_mntflags, SHWH);
++ break;
++
++ case Opt_trunc_xino:
++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
++ break;
++ case Opt_notrunc_xino:
++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
++ break;
++
++ case Opt_trunc_xino_path:
++ case Opt_itrunc_xino:
++ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
++ if (!err)
++ err = 1;
++ break;
++
++ case Opt_trunc_xib:
++ au_fset_opts(opts->flags, TRUNC_XIB);
++ break;
++ case Opt_notrunc_xib:
++ au_fclr_opts(opts->flags, TRUNC_XIB);
++ break;
++
++ default:
++ err = 0;
++ break;
++ }
++
++ return err;
++}
++
++/*
++ * returns tri-state.
++ * plus: processed without an error
++ * zero: unprocessed
++ * minus: error
++ */
++static int au_opt_br(struct super_block *sb, struct au_opt *opt,
++ struct au_opts *opts)
++{
++ int err, do_refresh;
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_append:
++ opt->add.bindex = au_sbend(sb) + 1;
++ if (opt->add.bindex < 0)
++ opt->add.bindex = 0;
++ goto add;
++ case Opt_prepend:
++ opt->add.bindex = 0;
++ add:
++ case Opt_add:
++ err = au_br_add(sb, &opt->add,
++ au_ftest_opts(opts->flags, REMOUNT));
++ if (!err) {
++ err = 1;
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ if (au_br_whable(opt->add.perm))
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ break;
++
++ case Opt_del:
++ case Opt_idel:
++ err = au_br_del(sb, &opt->del,
++ au_ftest_opts(opts->flags, REMOUNT));
++ if (!err) {
++ err = 1;
++ au_fset_opts(opts->flags, TRUNC_XIB);
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ break;
++
++ case Opt_mod:
++ case Opt_imod:
++ err = au_br_mod(sb, &opt->mod,
++ au_ftest_opts(opts->flags, REMOUNT),
++ &do_refresh);
++ if (!err) {
++ err = 1;
++ if (do_refresh) {
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ }
++ break;
++ }
++
++ return err;
++}
++
++static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
++ struct au_opt_xino **opt_xino,
++ struct au_opts *opts)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct dentry *root, *parent, *h_root;
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_xino:
++ err = au_xino_set(sb, &opt->xino,
++ !!au_ftest_opts(opts->flags, REMOUNT));
++ if (unlikely(err))
++ break;
++
++ *opt_xino = &opt->xino;
++ au_xino_brid_set(sb, -1);
++
++ /* safe d_parent access */
++ parent = opt->xino.file->f_dentry->d_parent;
++ root = sb->s_root;
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ h_root = au_h_dptr(root, bindex);
++ if (h_root == parent) {
++ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
++ break;
++ }
++ }
++ break;
++
++ case Opt_noxino:
++ au_xino_clr(sb);
++ au_xino_brid_set(sb, -1);
++ *opt_xino = (void *)-1;
++ break;
++ }
++
++ return err;
++}
++
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++ unsigned int pending)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ unsigned char do_plink, skip, do_free;
++ struct au_branch *br;
++ struct au_wbr *wbr;
++ struct dentry *root;
++ struct inode *dir, *h_dir;
++ struct au_sbinfo *sbinfo;
++ struct au_hinode *hdir;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
++
++ if (!(sb_flags & MS_RDONLY)) {
++ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
++ AuWarn("first branch should be rw\n");
++ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
++ AuWarn("shwh should be used with ro\n");
++ }
++
++ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
++ && !au_opt_test(sbinfo->si_mntflags, XINO))
++ AuWarn("udba=inotify requires xino\n");
++
++ err = 0;
++ root = sb->s_root;
++ dir = sb->s_root->d_inode;
++ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
++ bend = au_sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ skip = 0;
++ h_dir = au_h_iptr(dir, bindex);
++ br = au_sbr(sb, bindex);
++ do_free = 0;
++
++ wbr = br->br_wbr;
++ if (wbr)
++ wbr_wh_read_lock(wbr);
++
++ switch (br->br_perm) {
++ case AuBrPerm_RO:
++ case AuBrPerm_ROWH:
++ case AuBrPerm_RR:
++ case AuBrPerm_RRWH:
++ do_free = !!wbr;
++ skip = (!wbr
++ || (!wbr->wbr_whbase
++ && !wbr->wbr_plink
++ && !wbr->wbr_orph));
++ break;
++
++ case AuBrPerm_RWNoLinkWH:
++ /* skip = (!br->br_whbase && !br->br_orph); */
++ skip = (!wbr || !wbr->wbr_whbase);
++ if (skip && wbr) {
++ if (do_plink)
++ skip = !!wbr->wbr_plink;
++ else
++ skip = !wbr->wbr_plink;
++ }
++ break;
++
++ case AuBrPerm_RW:
++ /* skip = (br->br_whbase && br->br_ohph); */
++ skip = (wbr && wbr->wbr_whbase);
++ if (skip) {
++ if (do_plink)
++ skip = !!wbr->wbr_plink;
++ else
++ skip = !wbr->wbr_plink;
++ }
++ break;
++
++ default:
++ BUG();
++ }
++ if (wbr)
++ wbr_wh_read_unlock(wbr);
++
++ if (skip)
++ continue;
++
++ hdir = au_hi(dir, bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ if (wbr)
++ wbr_wh_write_lock(wbr);
++ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
++ if (wbr)
++ wbr_wh_write_unlock(wbr);
++ au_hin_imtx_unlock(hdir);
++
++ if (!err && do_free) {
++ kfree(wbr);
++ br->br_wbr = NULL;
++ }
++ }
++
++ return err;
++}
++
++int au_opts_mount(struct super_block *sb, struct au_opts *opts)
++{
++ int err;
++ unsigned int tmp;
++ aufs_bindex_t bend;
++ struct au_opt *opt;
++ struct au_opt_xino *opt_xino, xino;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_opt_simple(sb, opt++, opts);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ /* disable xino and udba temporary */
++ sbinfo = au_sbi(sb);
++ tmp = sbinfo->si_mntflags;
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
++
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_opt_br(sb, opt++, opts);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ bend = au_sbend(sb);
++ if (unlikely(bend < 0)) {
++ err = -EINVAL;
++ AuErr("no branches\n");
++ goto out;
++ }
++
++ if (au_opt_test(tmp, XINO))
++ au_opt_set(sbinfo->si_mntflags, XINO);
++ opt = opts->opt;
++ while (!err && opt->type != Opt_tail)
++ err = au_opt_xino(sb, opt++, &opt_xino, opts);
++ if (unlikely(err))
++ goto out;
++
++ err = au_opts_verify(sb, sb->s_flags, tmp);
++ if (unlikely(err))
++ goto out;
++
++ /* restore xino */
++ if (au_opt_test(tmp, XINO) && !opt_xino) {
++ xino.file = au_xino_def(sb);
++ err = PTR_ERR(xino.file);
++ if (IS_ERR(xino.file))
++ goto out;
++
++ err = au_xino_set(sb, &xino, /*remount*/0);
++ fput(xino.file);
++ if (unlikely(err))
++ goto out;
++ }
++
++ /* restore udba */
++ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
++ if (au_opt_test(tmp, UDBA_HINOTIFY)) {
++ struct inode *dir = sb->s_root->d_inode;
++ au_reset_hinotify(dir,
++ au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
++ }
++
++ out:
++ return err;
++}
++
++int au_opts_remount(struct super_block *sb, struct au_opts *opts)
++{
++ int err, rerr;
++ struct inode *dir;
++ struct au_opt_xino *opt_xino;
++ struct au_opt *opt;
++ struct au_sbinfo *sbinfo;
++
++ dir = sb->s_root->d_inode;
++ sbinfo = au_sbi(sb);
++ err = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail) {
++ err = au_opt_simple(sb, opt, opts);
++ if (!err)
++ err = au_opt_br(sb, opt, opts);
++ if (!err)
++ err = au_opt_xino(sb, opt, &opt_xino, opts);
++ opt++;
++ }
++ if (err > 0)
++ err = 0;
++ AuTraceErr(err);
++ /* go on even err */
++
++ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
++ if (unlikely(rerr && !err))
++ err = rerr;
++
++ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
++ rerr = au_xib_trunc(sb);
++ if (unlikely(rerr && !err))
++ err = rerr;
++ }
++
++ /* will be handled by the caller */
++ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
++ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
++ au_fset_opts(opts->flags, REFRESH_DIR);
++
++ AuDbg("status 0x%x\n", opts->flags);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_opt_udba(struct super_block *sb)
++{
++ return au_mntflags(sb) & AuOptMask_UDBA;
++}
+diff -Naur a/fs/aufs/opts.h b/fs/aufs/opts.h
+--- a/fs/aufs/opts.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,196 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount options/flags
++ */
++
++#ifndef __AUFS_OPTS_H__
++#define __AUFS_OPTS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/aufs_type.h>
++
++struct file;
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/* mount flags */
++#define AuOpt_XINO 1 /* external inode number bitmap
++ and translation table */
++#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
++#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
++#define AuOpt_UDBA_REVAL (1 << 3)
++#define AuOpt_UDBA_HINOTIFY (1 << 4)
++#define AuOpt_SHWH (1 << 5) /* show whiteout */
++#define AuOpt_PLINK (1 << 6) /* pseudo-link */
++#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
++#define AuOpt_REFROF (1 << 8) /* unimplemented */
++#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
++#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
++#define AuOpt_SUM_W (1 << 11) /* unimplemented */
++#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
++#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuOpt_UDBA_HINOTIFY
++#define AuOpt_UDBA_HINOTIFY 0
++#endif
++#ifndef CONFIG_AUFS_SHWH
++#undef AuOpt_SHWH
++#define AuOpt_SHWH 0
++#endif
++
++#define AuOpt_Def (AuOpt_XINO \
++ | AuOpt_UDBA_REVAL \
++ | AuOpt_PLINK \
++ /* | AuOpt_DIRPERM1 */ \
++ | AuOpt_WARN_PERM)
++#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
++ | AuOpt_UDBA_REVAL \
++ | AuOpt_UDBA_HINOTIFY)
++
++#define au_opt_test(flags, name) (flags & AuOpt_##name)
++#define au_opt_set(flags, name) do { \
++ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
++ ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_set_udba(flags, name) do { \
++ (flags) &= ~AuOptMask_UDBA; \
++ ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
++
++/* ---------------------------------------------------------------------- */
++
++/* policies to select one among multiple writable branches */
++enum {
++ AuWbrCreate_TDP, /* top down parent */
++ AuWbrCreate_RR, /* round robin */
++ AuWbrCreate_MFS, /* most free space */
++ AuWbrCreate_MFSV, /* mfs with seconds */
++ AuWbrCreate_MFSRR, /* mfs then rr */
++ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
++ AuWbrCreate_PMFS, /* parent and mfs */
++ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
++
++ AuWbrCreate_Def = AuWbrCreate_TDP
++};
++
++enum {
++ AuWbrCopyup_TDP, /* top down parent */
++ AuWbrCopyup_BUP, /* bottom up parent */
++ AuWbrCopyup_BU, /* bottom up */
++
++ AuWbrCopyup_Def = AuWbrCopyup_TDP
++};
++
++/* ---------------------------------------------------------------------- */
++
++struct au_opt_add {
++ aufs_bindex_t bindex;
++ char *pathname;
++ int perm;
++ struct path path;
++};
++
++struct au_opt_del {
++ char *pathname;
++ struct path h_path;
++};
++
++struct au_opt_mod {
++ char *path;
++ int perm;
++ struct dentry *h_root;
++};
++
++struct au_opt_xino {
++ char *path;
++ struct file *file;
++};
++
++struct au_opt_xino_itrunc {
++ aufs_bindex_t bindex;
++};
++
++struct au_opt_wbr_create {
++ int wbr_create;
++ int mfs_second;
++ unsigned long long mfsrr_watermark;
++};
++
++struct au_opt {
++ int type;
++ union {
++ struct au_opt_xino xino;
++ struct au_opt_xino_itrunc xino_itrunc;
++ struct au_opt_add add;
++ struct au_opt_del del;
++ struct au_opt_mod mod;
++ int dirwh;
++ int rdcache;
++ unsigned int rdblk;
++ unsigned int rdhash;
++ int udba;
++ struct au_opt_wbr_create wbr_create;
++ int wbr_copyup;
++ };
++};
++
++/* opts flags */
++#define AuOpts_REMOUNT 1
++#define AuOpts_REFRESH_DIR (1 << 1)
++#define AuOpts_REFRESH_NONDIR (1 << 2)
++#define AuOpts_TRUNC_XIB (1 << 3)
++#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
++#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
++#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
++
++struct au_opts {
++ struct au_opt *opt;
++ int max_opt;
++
++ unsigned int given_udba;
++ unsigned int flags;
++ unsigned long sb_flags;
++};
++
++/* ---------------------------------------------------------------------- */
++
++const char *au_optstr_br_perm(int brperm);
++const char *au_optstr_udba(int udba);
++const char *au_optstr_wbr_copyup(int wbr_copyup);
++const char *au_optstr_wbr_create(int wbr_create);
++
++void au_opts_free(struct au_opts *opts);
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++ unsigned int pending);
++int au_opts_mount(struct super_block *sb, struct au_opts *opts);
++int au_opts_remount(struct super_block *sb, struct au_opts *opts);
++
++unsigned int au_opt_udba(struct super_block *sb);
++
++/* ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_OPTS_H__ */
+diff -Naur a/fs/aufs/plink.c b/fs/aufs/plink.c
+--- a/fs/aufs/plink.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/plink.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,344 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * pseudo-link
++ */
++
++#include "aufs.h"
++
++/*
++ * during a user process maintains the pseudo-links,
++ * prohibit adding a new plink and branch manipulation.
++ */
++void au_plink_block_maintain(struct super_block *sb)
++{
++ struct au_sbinfo *sbi = au_sbi(sb);
++ /* gave up wake_up_bit() */
++ wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct pseudo_link {
++ struct list_head list;
++ struct inode *inode;
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list)
++ AuDbg("%lu\n", plink->inode->i_ino);
++ spin_unlock(&sbinfo->si_plink.spin);
++}
++#endif
++
++/* is the inode pseudo-linked? */
++int au_plink_test(struct inode *inode)
++{
++ int found;
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ sbinfo = au_sbi(inode->i_sb);
++ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
++
++ found = 0;
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list)
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ spin_unlock(&sbinfo->si_plink.spin);
++ return found;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generate a name for plink.
++ * the file will be stored under AUFS_WH_PLINKDIR.
++ */
++/* 20 is max digits length of ulong 64 */
++#define PLINK_NAME_LEN ((20 + 1) * 2)
++
++static int plink_name(char *name, int len, struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ int rlen;
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, bindex);
++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
++ return rlen;
++}
++
++/* lookup the plink-ed @inode under the branch at @bindex */
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct dentry *h_dentry, *h_parent;
++ struct au_branch *br;
++ struct inode *h_dir;
++ char a[PLINK_NAME_LEN];
++ struct qstr tgtname = {
++ .name = a
++ };
++
++ br = au_sbr(inode->i_sb, bindex);
++ h_parent = br->br_wbr->wbr_plink;
++ h_dir = h_parent->d_inode;
++ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++ /* always superio. */
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
++ mutex_unlock(&h_dir->i_mutex);
++ return h_dentry;
++}
++
++/* create a pseudo-link */
++static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
++ struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++
++ h_dir = h_parent->d_inode;
++ again:
++ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ err = 0;
++ /* wh.plink dir is not monitored */
++ if (h_path.dentry->d_inode
++ && h_path.dentry->d_inode != h_dentry->d_inode) {
++ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ dput(h_path.dentry);
++ h_path.dentry = NULL;
++ if (!err)
++ goto again;
++ }
++ if (!err && !h_path.dentry->d_inode)
++ err = vfsub_link(h_dentry, h_dir, &h_path);
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++struct do_whplink_args {
++ int *errp;
++ struct qstr *tgt;
++ struct dentry *h_parent;
++ struct dentry *h_dentry;
++ struct au_branch *br;
++};
++
++static void call_do_whplink(void *args)
++{
++ struct do_whplink_args *a = args;
++ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
++}
++
++static int whplink(struct dentry *h_dentry, struct inode *inode,
++ aufs_bindex_t bindex, struct au_branch *br)
++{
++ int err, wkq_err;
++ struct au_wbr *wbr;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ char a[PLINK_NAME_LEN];
++ struct qstr tgtname = {
++ .name = a
++ };
++
++ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
++ h_parent = wbr->wbr_plink;
++ h_dir = h_parent->d_inode;
++ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++ /* always superio. */
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++ if (!au_test_wkq(current)) {
++ struct do_whplink_args args = {
++ .errp = &err,
++ .tgt = &tgtname,
++ .h_parent = h_parent,
++ .h_dentry = h_dentry,
++ .br = br
++ };
++ wkq_err = au_wkq_wait(call_do_whplink, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ } else
++ err = do_whplink(&tgtname, h_parent, h_dentry, br);
++ mutex_unlock(&h_dir->i_mutex);
++
++ return err;
++}
++
++/* free a single plink */
++static void do_put_plink(struct pseudo_link *plink, int do_del)
++{
++ iput(plink->inode);
++ if (do_del)
++ list_del(&plink->list);
++ kfree(plink);
++}
++
++/*
++ * create a new pseudo-link for @h_dentry on @bindex.
++ * the linked inode is held in aufs @inode.
++ */
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++ int found, err, cnt;
++
++ sb = inode->i_sb;
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ err = 0;
++ cnt = 0;
++ found = 0;
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list) {
++ cnt++;
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ spin_unlock(&sbinfo->si_plink.spin);
++ return;
++ }
++
++ plink = NULL;
++ if (!found) {
++ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
++ if (plink) {
++ plink->inode = au_igrab(inode);
++ list_add(&plink->list, plink_list);
++ cnt++;
++ } else
++ err = -ENOMEM;
++ }
++ spin_unlock(&sbinfo->si_plink.spin);
++
++ if (!err) {
++ au_plink_block_maintain(sb);
++ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
++ }
++
++ if (unlikely(cnt > AUFS_PLINK_WARN))
++ AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
++ if (unlikely(err)) {
++ AuWarn("err %d, damaged pseudo link.\n", err);
++ if (!found && plink)
++ do_put_plink(plink, /*do_del*/1);
++ }
++}
++
++/* free all plinks */
++void au_plink_put(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ /* no spin_lock since sbinfo is write-locked */
++ list_for_each_entry_safe(plink, tmp, plink_list, list)
++ do_put_plink(plink, 0);
++ INIT_LIST_HEAD(plink_list);
++}
++
++/* free the plinks on a branch specified by @br_id */
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++ struct inode *inode;
++ aufs_bindex_t bstart, bend, bindex;
++ unsigned char do_put;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ /* no spin_lock since sbinfo is write-locked */
++ list_for_each_entry_safe(plink, tmp, plink_list, list) {
++ do_put = 0;
++ inode = au_igrab(plink->inode);
++ ii_write_lock_child(inode);
++ bstart = au_ibstart(inode);
++ bend = au_ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (!au_h_iptr(inode, bindex)
++ || au_ii_br_id(inode, bindex) != br_id)
++ continue;
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ do_put = 1;
++ break;
++ }
++ } else
++ do_put_plink(plink, 1);
++
++ if (do_put) {
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (au_h_iptr(inode, bindex)) {
++ do_put = 0;
++ break;
++ }
++ if (do_put)
++ do_put_plink(plink, 1);
++ }
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++}
+diff -Naur a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h
+--- a/fs/aufs/rwsem.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/rwsem.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,61 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * simple read-write semaphore wrappers
++ */
++
++#ifndef __AUFS_RWSEM_H__
++#define __AUFS_RWSEM_H__
++
++#ifdef __KERNEL__
++
++#include <linux/rwsem.h>
++
++#define au_rwsem_destroy(rw) AuDebugOn(rwsem_is_locked(rw))
++#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->wait_list))
++
++#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_lock(param) \
++{ down_read(rwsem); } \
++static inline void prefix##_write_lock(param) \
++{ down_write(rwsem); } \
++static inline int prefix##_read_trylock(param) \
++{ return down_read_trylock(rwsem); } \
++static inline int prefix##_write_trylock(param) \
++{ return down_write_trylock(rwsem); }
++/* why is not _nested version defined */
++/* static inline void prefix##_read_trylock_nested(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc)); }
++static inline void prefix##_write_trylock_nestd(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc); } */
++
++#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_unlock(param) \
++{ up_read(rwsem); } \
++static inline void prefix##_write_unlock(param) \
++{ up_write(rwsem); } \
++static inline void prefix##_downgrade_lock(param) \
++{ downgrade_write(rwsem); }
++
++#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
++ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_RWSEM_H__ */
+diff -Naur a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
+--- a/fs/aufs/sbinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sbinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * superblock private data
++ */
++
++#include "aufs.h"
++
++/*
++ * they are necessary regardless sysfs is disabled.
++ */
++void au_si_free(struct kobject *kobj)
++{
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
++
++ sb = sbinfo->si_sb;
++ si_write_lock(sb);
++ au_xino_clr(sb);
++ au_br_free(sbinfo);
++ kfree(sbinfo->si_branch);
++ mutex_destroy(&sbinfo->si_xib_mtx);
++ si_write_unlock(sb);
++ au_rwsem_destroy(&sbinfo->si_rwsem);
++
++ kfree(sbinfo);
++}
++
++int au_si_alloc(struct super_block *sb)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = -ENOMEM;
++ sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
++ if (unlikely(!sbinfo))
++ goto out;
++
++ /* will be reallocated separately */
++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
++ if (unlikely(!sbinfo->si_branch))
++ goto out_sbinfo;
++
++ memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
++ err = sysaufs_si_init(sbinfo);
++ if (unlikely(err))
++ goto out_br;
++
++ au_nwt_init(&sbinfo->si_nowait);
++ init_rwsem(&sbinfo->si_rwsem);
++ down_write(&sbinfo->si_rwsem);
++ sbinfo->si_generation = 0;
++ sbinfo->au_si_status = 0;
++ sbinfo->si_bend = -1;
++ sbinfo->si_last_br_id = 0;
++
++ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
++ sbinfo->si_wbr_create = AuWbrCreate_Def;
++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
++
++ sbinfo->si_mntflags = AuOpt_Def;
++
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ sbinfo->si_xib = NULL;
++ mutex_init(&sbinfo->si_xib_mtx);
++ sbinfo->si_xib_buf = NULL;
++ sbinfo->si_xino_brid = -1;
++ /* leave si_xib_last_pindex and si_xib_next_bit */
++
++ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
++
++ au_spl_init(&sbinfo->si_plink);
++ init_waitqueue_head(&sbinfo->si_plink_wq);
++
++ /* leave other members for sysaufs and si_mnt. */
++ sbinfo->si_sb = sb;
++ sb->s_fs_info = sbinfo;
++ au_debug_sbinfo_init(sbinfo);
++ return 0; /* success */
++
++ out_br:
++ kfree(sbinfo->si_branch);
++ out_sbinfo:
++ kfree(sbinfo);
++ out:
++ return err;
++}
++
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
++{
++ int err, sz;
++ struct au_branch **brp;
++
++ err = -ENOMEM;
++ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
++ if (unlikely(!sz))
++ sz = sizeof(*brp);
++ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
++ if (brp) {
++ sbinfo->si_branch = brp;
++ err = 0;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_sigen_inc(struct super_block *sb)
++{
++ unsigned int gen;
++
++ gen = ++au_sbi(sb)->si_generation;
++ au_update_digen(sb->s_root);
++ au_update_iigen(sb->s_root->d_inode);
++ sb->s_root->d_inode->i_version++;
++ return gen;
++}
++
++aufs_bindex_t au_new_br_id(struct super_block *sb)
++{
++ aufs_bindex_t br_id;
++ int i;
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
++ br_id = ++sbinfo->si_last_br_id;
++ if (br_id && au_br_index(sb, br_id) < 0)
++ return br_id;
++ }
++
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry and super_block lock. call at entry point */
++void aufs_read_lock(struct dentry *dentry, int flags)
++{
++ si_read_lock(dentry->d_sb, flags);
++ if (au_ftest_lock(flags, DW))
++ di_write_lock_child(dentry);
++ else
++ di_read_lock_child(dentry, flags);
++}
++
++void aufs_read_unlock(struct dentry *dentry, int flags)
++{
++ if (au_ftest_lock(flags, DW))
++ di_write_unlock(dentry);
++ else
++ di_read_unlock(dentry, flags);
++ si_read_unlock(dentry->d_sb);
++}
++
++void aufs_write_lock(struct dentry *dentry)
++{
++ si_write_lock(dentry->d_sb);
++ di_write_lock_child(dentry);
++}
++
++void aufs_write_unlock(struct dentry *dentry)
++{
++ di_write_unlock(dentry);
++ si_write_unlock(dentry->d_sb);
++}
++
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
++{
++ si_read_lock(d1->d_sb, flags);
++ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
++}
++
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock2(d1, d2);
++ si_read_unlock(d1->d_sb);
++}
+diff -Naur a/fs/aufs/spl.h b/fs/aufs/spl.h
+--- a/fs/aufs/spl.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/spl.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * simple list protected by a spinlock
++ */
++
++#ifndef __AUFS_SPL_H__
++#define __AUFS_SPL_H__
++
++#ifdef __KERNEL__
++
++#include <linux/spinlock.h>
++#include <linux/list.h>
++
++struct au_splhead {
++ spinlock_t spin;
++ struct list_head head;
++};
++
++static inline void au_spl_init(struct au_splhead *spl)
++{
++ spin_lock_init(&spl->spin);
++ INIT_LIST_HEAD(&spl->head);
++}
++
++static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
++{
++ spin_lock(&spl->spin);
++ list_add(list, &spl->head);
++ spin_unlock(&spl->spin);
++}
++
++static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
++{
++ spin_lock(&spl->spin);
++ list_del(list);
++ spin_unlock(&spl->spin);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SPL_H__ */
+diff -Naur a/fs/aufs/super.c b/fs/aufs/super.c
+--- a/fs/aufs/super.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,870 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount and super_block operations
++ */
++
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/*
++ * super_operations
++ */
++static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
++{
++ struct au_icntnr *c;
++
++ c = au_cache_alloc_icntnr();
++ if (c) {
++ inode_init_once(&c->vfs_inode);
++ c->vfs_inode.i_version = 1; /* sigen(sb); */
++ c->iinfo.ii_hinode = NULL;
++ return &c->vfs_inode;
++ }
++ return NULL;
++}
++
++static void aufs_destroy_inode(struct inode *inode)
++{
++ au_iinfo_fin(inode);
++ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
++}
++
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
++{
++ struct inode *inode;
++ int err;
++
++ inode = iget_locked(sb, ino);
++ if (unlikely(!inode)) {
++ inode = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++ if (!(inode->i_state & I_NEW))
++ goto out;
++
++ err = au_xigen_new(inode);
++ if (!err)
++ err = au_iinfo_init(inode);
++ if (!err)
++ inode->i_version++;
++ else {
++ iget_failed(inode);
++ inode = ERR_PTR(err);
++ }
++
++ out:
++ /* never return NULL */
++ AuDebugOn(!inode);
++ AuTraceErrPtr(inode);
++ return inode;
++}
++
++/* lock free root dinfo */
++static int au_show_brs(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct path path;
++ struct au_hdentry *hd;
++ struct au_branch *br;
++
++ err = 0;
++ bend = au_sbend(sb);
++ hd = au_di(sb->s_root)->di_hdentry;
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ path.mnt = br->br_mnt;
++ path.dentry = hd[bindex].hd_dentry;
++ err = au_seq_path(seq, &path);
++ if (err > 0)
++ err = seq_printf(seq, "=%s",
++ au_optstr_br_perm(br->br_perm));
++ if (!err && bindex != bend)
++ err = seq_putc(seq, ':');
++ }
++
++ return err;
++}
++
++static void au_show_wbr_create(struct seq_file *m, int v,
++ struct au_sbinfo *sbinfo)
++{
++ const char *pat;
++
++ seq_printf(m, ",create=");
++ pat = au_optstr_wbr_create(v);
++ switch (v) {
++ case AuWbrCreate_TDP:
++ case AuWbrCreate_RR:
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_PMFS:
++ seq_printf(m, pat);
++ break;
++ case AuWbrCreate_MFSV:
++ seq_printf(m, /*pat*/"mfs:%lu",
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ case AuWbrCreate_PMFSV:
++ seq_printf(m, /*pat*/"pmfs:%lu",
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ case AuWbrCreate_MFSRR:
++ seq_printf(m, /*pat*/"mfsrr:%llu",
++ sbinfo->si_wbr_mfs.mfsrr_watermark);
++ break;
++ case AuWbrCreate_MFSRRV:
++ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
++ sbinfo->si_wbr_mfs.mfsrr_watermark,
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ }
++}
++
++static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
++{
++#ifdef CONFIG_SYSFS
++ return 0;
++#else
++ int err;
++ const int len = sizeof(AUFS_XINO_FNAME) - 1;
++ aufs_bindex_t bindex, brid;
++ struct super_block *sb;
++ struct qstr *name;
++ struct file *f;
++ struct dentry *d, *h_root;
++
++ err = 0;
++ sb = mnt->mnt_sb;
++ f = au_sbi(sb)->si_xib;
++ if (!f)
++ goto out;
++
++ /* stop printing the default xino path on the first writable branch */
++ h_root = NULL;
++ brid = au_xino_brid(sb);
++ if (brid >= 0) {
++ bindex = au_br_index(sb, brid);
++ h_root = au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
++ }
++ d = f->f_dentry;
++ name = &d->d_name;
++ /* safe ->d_parent because the file is unlinked */
++ if (d->d_parent == h_root
++ && name->len == len
++ && !memcmp(name->name, AUFS_XINO_FNAME, len))
++ goto out;
++
++ seq_puts(seq, ",xino=");
++ err = au_xino_path(seq, f);
++
++ out:
++ return err;
++#endif
++}
++
++/* seq_file will re-call me in case of too long string */
++static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ int err, n;
++ unsigned int mnt_flags, v;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++#define AuBool(name, str) do { \
++ v = au_opt_test(mnt_flags, name); \
++ if (v != au_opt_test(AuOpt_Def, name)) \
++ seq_printf(m, ",%s" #str, v ? "" : "no"); \
++} while (0)
++
++#define AuStr(name, str) do { \
++ v = mnt_flags & AuOptMask_##name; \
++ if (v != (AuOpt_Def & AuOptMask_##name)) \
++ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
++} while (0)
++
++#define AuUInt(name, str, val) do { \
++ if (val != AUFS_##name##_DEF) \
++ seq_printf(m, "," #str "=%u", val); \
++} while (0)
++
++ /* lock free root dinfo */
++ sb = mnt->mnt_sb;
++ si_noflush_read_lock(sb);
++ sbinfo = au_sbi(sb);
++ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
++
++ mnt_flags = au_mntflags(sb);
++ if (au_opt_test(mnt_flags, XINO)) {
++ err = au_show_xino(m, mnt);
++ if (unlikely(err))
++ goto out;
++ } else
++ seq_puts(m, ",noxino");
++
++ AuBool(TRUNC_XINO, trunc_xino);
++ AuStr(UDBA, udba);
++ AuBool(SHWH, shwh);
++ AuBool(PLINK, plink);
++ /* AuBool(DIRPERM1, dirperm1); */
++ /* AuBool(REFROF, refrof); */
++
++ v = sbinfo->si_wbr_create;
++ if (v != AuWbrCreate_Def)
++ au_show_wbr_create(m, v, sbinfo);
++
++ v = sbinfo->si_wbr_copyup;
++ if (v != AuWbrCopyup_Def)
++ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
++
++ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
++ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
++ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
++
++ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
++
++ n = sbinfo->si_rdcache / HZ;
++ AuUInt(RDCACHE, rdcache, n);
++
++ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
++ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
++
++ AuBool(SUM, sum);
++ /* AuBool(SUM_W, wsum); */
++ AuBool(WARN_PERM, warn_perm);
++ AuBool(VERBOSE, verbose);
++
++ out:
++ /* be sure to print "br:" last */
++ if (!sysaufs_brs) {
++ seq_puts(m, ",br:");
++ au_show_brs(m, sb);
++ }
++ si_read_unlock(sb);
++ return 0;
++
++#undef Deleted
++#undef AuBool
++#undef AuStr
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* sum mode which returns the summation for statfs(2) */
++
++static u64 au_add_till_max(u64 a, u64 b)
++{
++ u64 old;
++
++ old = a;
++ a += b;
++ if (old < a)
++ return a;
++ return ULLONG_MAX;
++}
++
++static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
++{
++ int err;
++ u64 blocks, bfree, bavail, files, ffree;
++ aufs_bindex_t bend, bindex, i;
++ unsigned char shared;
++ struct vfsmount *h_mnt;
++ struct super_block *h_sb;
++
++ blocks = 0;
++ bfree = 0;
++ bavail = 0;
++ files = 0;
++ ffree = 0;
++
++ err = 0;
++ bend = au_sbend(sb);
++ for (bindex = bend; bindex >= 0; bindex--) {
++ h_mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_mnt->mnt_sb;
++ shared = 0;
++ for (i = bindex + 1; !shared && i <= bend; i++)
++ shared = (au_sbr_sb(sb, i) == h_sb);
++ if (shared)
++ continue;
++
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(h_mnt->mnt_root, buf);
++ if (unlikely(err))
++ goto out;
++
++ blocks = au_add_till_max(blocks, buf->f_blocks);
++ bfree = au_add_till_max(bfree, buf->f_bfree);
++ bavail = au_add_till_max(bavail, buf->f_bavail);
++ files = au_add_till_max(files, buf->f_files);
++ ffree = au_add_till_max(ffree, buf->f_ffree);
++ }
++
++ buf->f_blocks = blocks;
++ buf->f_bfree = bfree;
++ buf->f_bavail = bavail;
++ buf->f_files = files;
++ buf->f_ffree = ffree;
++
++ out:
++ return err;
++}
++
++static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ int err;
++ struct super_block *sb;
++
++ /* lock free root dinfo */
++ sb = dentry->d_sb;
++ si_noflush_read_lock(sb);
++ if (!au_opt_test(au_mntflags(sb), SUM))
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
++ else
++ err = au_statfs_sum(sb, buf);
++ si_read_unlock(sb);
++
++ if (!err) {
++ buf->f_type = AUFS_SUPER_MAGIC;
++ buf->f_namelen -= AUFS_WH_PFX_LEN;
++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
++ }
++ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* try flushing the lower fs at aufs remount/unmount time */
++
++static void au_fsync_br(struct super_block *sb)
++{
++ aufs_bindex_t bend, bindex;
++ int brperm;
++ struct au_branch *br;
++ struct super_block *h_sb;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex < bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ brperm = br->br_perm;
++ if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
++ continue;
++ h_sb = br->br_mnt->mnt_sb;
++ if (bdev_read_only(h_sb->s_bdev))
++ continue;
++
++ lockdep_off();
++ down_write(&h_sb->s_umount);
++ shrink_dcache_sb(h_sb);
++ fsync_super(h_sb);
++ up_write(&h_sb->s_umount);
++ lockdep_on();
++ }
++}
++
++/*
++ * this IS NOT for super_operations.
++ * I guess it will be reverted someday.
++ */
++static void aufs_umount_begin(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++
++ si_write_lock(sb);
++ au_fsync_br(sb);
++ if (au_opt_test(au_mntflags(sb), PLINK))
++ au_plink_put(sb);
++ if (sbinfo->si_wbr_create_ops->fin)
++ sbinfo->si_wbr_create_ops->fin(sb);
++ si_write_unlock(sb);
++}
++
++/* final actions when unmounting a file system */
++static void aufs_put_super(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++
++ aufs_umount_begin(sb);
++ dbgaufs_si_fin(sbinfo);
++ kobject_put(&sbinfo->si_kobj);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * refresh dentry and inode at remount time.
++ */
++static int do_refresh(struct dentry *dentry, mode_t type,
++ unsigned int dir_flags)
++{
++ int err;
++ struct dentry *parent;
++
++ di_write_lock_child(dentry);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++
++ /* returns the number of positive dentries */
++ err = au_refresh_hdentry(dentry, type);
++ if (err >= 0) {
++ struct inode *inode = dentry->d_inode;
++ err = au_refresh_hinode(inode, dentry);
++ if (!err && type == S_IFDIR)
++ au_reset_hinotify(inode, dir_flags);
++ }
++ if (unlikely(err))
++ AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
++
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ di_write_unlock(dentry);
++
++ return err;
++}
++
++static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
++{
++ return S_ISDIR(dentry->d_inode->i_mode);
++}
++
++/* gave up consolidating with refresh_nondir() */
++static int refresh_dir(struct dentry *root, unsigned int sigen)
++{
++ int err, i, j, ndentry, e;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++ struct inode *inode;
++ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
++
++ err = 0;
++ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++ ii_write_lock_child(inode);
++ e = au_refresh_hinode_self(inode, /*do_attr*/1);
++ ii_write_unlock(inode);
++ if (unlikely(e)) {
++ AuDbg("e %d, i%lu\n", e, inode->i_ino);
++ if (!err)
++ err = e;
++ /* go on even if err */
++ }
++ }
++
++ e = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out;
++ }
++ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out_dpages;
++ }
++
++ for (i = 0; !e && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; !e && j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ au_dbg_verify_dir_parent(d, sigen);
++ if (au_digen(d) != sigen) {
++ e = do_refresh(d, S_IFDIR, flags);
++ if (unlikely(e && !err))
++ err = e;
++ /* break on err */
++ }
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
++{
++ return !S_ISDIR(dentry->d_inode->i_mode);
++}
++
++static int refresh_nondir(struct dentry *root, unsigned int sigen,
++ int do_dentry)
++{
++ int err, i, j, ndentry, e;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++ struct inode *inode;
++
++ err = 0;
++ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++ ii_write_lock_child(inode);
++ e = au_refresh_hinode_self(inode, /*do_attr*/1);
++ ii_write_unlock(inode);
++ if (unlikely(e)) {
++ AuDbg("e %d, i%lu\n", e, inode->i_ino);
++ if (!err)
++ err = e;
++ /* go on even if err */
++ }
++ }
++
++ if (!do_dentry)
++ goto out;
++
++ e = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out;
++ }
++ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out_dpages;
++ }
++
++ for (i = 0; i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ au_dbg_verify_nondir_parent(d, sigen);
++ inode = d->d_inode;
++ if (inode && au_digen(d) != sigen) {
++ e = do_refresh(d, inode->i_mode & S_IFMT,
++ /*dir_flags*/0);
++ if (unlikely(e && !err))
++ err = e;
++ /* go on even err */
++ }
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static void au_remount_refresh(struct super_block *sb, unsigned int flags)
++{
++ int err;
++ unsigned int sigen;
++ struct au_sbinfo *sbinfo;
++ struct dentry *root;
++ struct inode *inode;
++
++ au_sigen_inc(sb);
++ sigen = au_sigen(sb);
++ sbinfo = au_sbi(sb);
++ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
++
++ root = sb->s_root;
++ DiMustNoWaiters(root);
++ inode = root->d_inode;
++ IiMustNoWaiters(inode);
++ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++ di_write_unlock(root);
++
++ err = refresh_dir(root, sigen);
++ if (unlikely(err)) {
++ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
++ AuWarn("Refreshing directories failed, ignored (%d)\n", err);
++ }
++
++ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
++ err = refresh_nondir(root, sigen, !err);
++ if (unlikely(err))
++ AuWarn("Refreshing non-directories failed, ignored"
++ "(%d)\n", err);
++ }
++
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++ au_cpup_attr_all(root->d_inode, /*force*/1);
++}
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++ AuTraceErr(err);
++
++ switch (err) {
++ case -ENOENT:
++ case -ENOTDIR:
++ case -EEXIST:
++ case -EIO:
++ err = -EINVAL;
++ }
++ return err;
++}
++
++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++ int err;
++ struct au_opts opts;
++ struct dentry *root;
++ struct inode *inode;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ root = sb->s_root;
++ if (!data || !*data) {
++ aufs_write_lock(root);
++ err = au_opts_verify(sb, *flags, /*pending*/0);
++ if (!err)
++ au_fsync_br(sb);
++ aufs_write_unlock(root);
++ goto out;
++ }
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++ opts.flags = AuOpts_REMOUNT;
++ opts.sb_flags = *flags;
++
++ /* parse it before aufs lock */
++ err = au_opts_parse(sb, data, &opts);
++ if (unlikely(err))
++ goto out_opts;
++
++ sbinfo = au_sbi(sb);
++ inode = root->d_inode;
++ mutex_lock(&inode->i_mutex);
++ aufs_write_lock(root);
++ au_fsync_br(sb);
++
++ /* au_opts_remount() may return an error */
++ err = au_opts_remount(sb, &opts);
++ au_opts_free(&opts);
++
++ if (au_ftest_opts(opts.flags, REFRESH_DIR)
++ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
++ au_remount_refresh(sb, opts.flags);
++
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ err = cvt_err(err);
++ AuTraceErr(err);
++ return err;
++}
++
++static struct super_operations aufs_sop = {
++ .alloc_inode = aufs_alloc_inode,
++ .destroy_inode = aufs_destroy_inode,
++ .drop_inode = generic_delete_inode,
++ .show_options = aufs_show_options,
++ .statfs = aufs_statfs,
++ .put_super = aufs_put_super,
++ .remount_fs = aufs_remount_fs
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int alloc_root(struct super_block *sb)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *root;
++
++ err = -ENOMEM;
++ inode = au_iget_locked(sb, AUFS_ROOT_INO);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ inode->i_mode = S_IFDIR;
++ inode->i_nlink = 2;
++ unlock_new_inode(inode);
++
++ root = d_alloc_root(inode);
++ if (unlikely(!root))
++ goto out_iput;
++ err = PTR_ERR(root);
++ if (IS_ERR(root))
++ goto out_iput;
++
++ err = au_alloc_dinfo(root);
++ if (!err) {
++ sb->s_root = root;
++ return 0; /* success */
++ }
++ dput(root);
++ goto out; /* do not iput */
++
++ out_iput:
++ iget_failed(inode);
++ iput(inode);
++ out:
++ return err;
++
++}
++
++static int aufs_fill_super(struct super_block *sb, void *raw_data,
++ int silent __maybe_unused)
++{
++ int err;
++ struct au_opts opts;
++ struct dentry *root;
++ struct inode *inode;
++ char *arg = raw_data;
++
++ if (unlikely(!arg || !*arg)) {
++ err = -EINVAL;
++ AuErr("no arg\n");
++ goto out;
++ }
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++ opts.sb_flags = sb->s_flags;
++
++ err = au_si_alloc(sb);
++ if (unlikely(err))
++ goto out_opts;
++
++ /* all timestamps always follow the ones on the branch */
++ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
++ sb->s_op = &aufs_sop;
++ sb->s_magic = AUFS_SUPER_MAGIC;
++ sb->s_maxbytes = 0;
++ au_export_init(sb);
++
++ err = alloc_root(sb);
++ if (unlikely(err)) {
++ si_write_unlock(sb);
++ goto out_info;
++ }
++ root = sb->s_root;
++ inode = root->d_inode;
++
++ /*
++ * actually we can parse options regardless aufs lock here.
++ * but at remount time, parsing must be done before aufs lock.
++ * so we follow the same rule.
++ */
++ ii_write_lock_parent(inode);
++ aufs_write_unlock(root);
++ err = au_opts_parse(sb, arg, &opts);
++ if (unlikely(err))
++ goto out_root;
++
++ /* lock vfs_inode first, then aufs. */
++ mutex_lock(&inode->i_mutex);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ aufs_write_lock(root);
++ err = au_opts_mount(sb, &opts);
++ au_opts_free(&opts);
++ if (unlikely(err))
++ goto out_unlock;
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++ goto out_opts; /* success */
++
++ out_unlock:
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++ out_root:
++ dput(root);
++ sb->s_root = NULL;
++ out_info:
++ kobject_put(&au_sbi(sb)->si_kobj);
++ sb->s_fs_info = NULL;
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ AuTraceErr(err);
++ err = cvt_err(err);
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name __maybe_unused, void *raw_data,
++ struct vfsmount *mnt)
++{
++ int err;
++ struct super_block *sb;
++
++ /* all timestamps always follow the ones on the branch */
++ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
++ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
++ if (!err) {
++ sb = mnt->mnt_sb;
++ si_write_lock(sb);
++ sysaufs_brs_add(sb, 0);
++ si_write_unlock(sb);
++ }
++ return err;
++}
++
++struct file_system_type aufs_fs_type = {
++ .name = AUFS_FSTYPE,
++ .fs_flags =
++ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
++ | FS_REVAL_DOT, /* for NFS branch and udba */
++ .get_sb = aufs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ /* no need to __module_get() and module_put(). */
++ .owner = THIS_MODULE,
++};
+diff -Naur a/fs/aufs/super.h b/fs/aufs/super.h
+--- a/fs/aufs/super.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,359 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * super_block operations
++ */
++
++#ifndef __AUFS_SUPER_H__
++#define __AUFS_SUPER_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "spl.h"
++#include "wkq.h"
++
++typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
++typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
++ loff_t *);
++
++/* policies to select one among multiple writable branches */
++struct au_wbr_copyup_operations {
++ int (*copyup)(struct dentry *dentry);
++};
++
++struct au_wbr_create_operations {
++ int (*create)(struct dentry *dentry, int isdir);
++ int (*init)(struct super_block *sb);
++ int (*fin)(struct super_block *sb);
++};
++
++struct au_wbr_mfs {
++ struct mutex mfs_lock; /* protect this structure */
++ unsigned long mfs_jiffy;
++ unsigned long mfs_expire;
++ aufs_bindex_t mfs_bindex;
++
++ unsigned long long mfsrr_bytes;
++ unsigned long long mfsrr_watermark;
++};
++
++/* sbinfo status flags */
++/*
++ * set true when refresh_dirs() failed at remount time.
++ * then try refreshing dirs at access time again.
++ * if it is false, refreshing dirs at access time is unnecesary
++ */
++#define AuSi_FAILED_REFRESH_DIRS 1
++#define AuSi_MAINTAIN_PLINK (1 << 1) /* ioctl */
++#define au_ftest_si(sbinfo, name) ((sbinfo)->au_si_status & AuSi_##name)
++#define au_fset_si(sbinfo, name) \
++ { (sbinfo)->au_si_status |= AuSi_##name; }
++#define au_fclr_si(sbinfo, name) \
++ { (sbinfo)->au_si_status &= ~AuSi_##name; }
++
++struct au_branch;
++struct au_sbinfo {
++ /* nowait tasks in the system-wide workqueue */
++ struct au_nowait_tasks si_nowait;
++
++ struct rw_semaphore si_rwsem;
++
++ /* branch management */
++ unsigned int si_generation;
++
++ /* see above flags */
++ unsigned char au_si_status;
++
++ aufs_bindex_t si_bend;
++ aufs_bindex_t si_last_br_id;
++ struct au_branch **si_branch;
++
++ /* policy to select a writable branch */
++ unsigned char si_wbr_copyup;
++ unsigned char si_wbr_create;
++ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
++ struct au_wbr_create_operations *si_wbr_create_ops;
++
++ /* round robin */
++ atomic_t si_wbr_rr_next;
++
++ /* most free space */
++ struct au_wbr_mfs si_wbr_mfs;
++
++ /* mount flags */
++ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
++ unsigned int si_mntflags;
++
++ /* external inode number (bitmap and translation table) */
++ au_readf_t si_xread;
++ au_writef_t si_xwrite;
++ struct file *si_xib;
++ struct mutex si_xib_mtx; /* protect xib members */
++ unsigned long *si_xib_buf;
++ unsigned long si_xib_last_pindex;
++ int si_xib_next_bit;
++ aufs_bindex_t si_xino_brid;
++ /* reserved for future use */
++ /* unsigned long long si_xib_limit; */ /* Max xib file size */
++
++#ifdef CONFIG_AUFS_EXPORT
++ /* i_generation */
++ struct file *si_xigen;
++ atomic_t si_xigen_next;
++#endif
++
++ /* vdir parameters */
++ unsigned long si_rdcache; /* max cache time in HZ */
++ unsigned int si_rdblk; /* deblk size */
++ unsigned int si_rdhash; /* hash size */
++
++ /*
++ * If the number of whiteouts are larger than si_dirwh, leave all of
++ * them after au_whtmp_ren to reduce the cost of rmdir(2).
++ * future fsck.aufs or kernel thread will remove them later.
++ * Otherwise, remove all whiteouts and the dir in rmdir(2).
++ */
++ unsigned int si_dirwh;
++
++ /*
++ * rename(2) a directory with all children.
++ */
++ /* reserved for future use */
++ /* int si_rendir; */
++
++ /* pseudo_link list */
++ struct au_splhead si_plink;
++ wait_queue_head_t si_plink_wq;
++
++ /*
++ * sysfs and lifetime management.
++ * this is not a small structure and it may be a waste of memory in case
++ * of sysfs is disabled, particulary when many aufs-es are mounted.
++ * but using sysfs is majority.
++ */
++ struct kobject si_kobj;
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
++#ifdef CONFIG_AUFS_EXPORT
++ struct dentry *si_dbgaufs_xigen;
++#endif
++#endif
++
++ /* dirty, necessary for unmounting, sysfs and sysrq */
++ struct super_block *si_sb;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* policy to select one among writable branches */
++#define AuWbrCopyup(sbinfo, args...) \
++ ((sbinfo)->si_wbr_copyup_ops->copyup(args))
++#define AuWbrCreate(sbinfo, args...) \
++ ((sbinfo)->si_wbr_create_ops->create(args))
++
++/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
++#define AuLock_DW 1 /* write-lock dentry */
++#define AuLock_IR (1 << 1) /* read-lock inode */
++#define AuLock_IW (1 << 2) /* write-lock inode */
++#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
++#define AuLock_DIR (1 << 4) /* target is a dir */
++#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
++#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
++#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
++
++/* ---------------------------------------------------------------------- */
++
++/* super.c */
++extern struct file_system_type aufs_fs_type;
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
++
++/* sbinfo.c */
++void au_si_free(struct kobject *kobj);
++int au_si_alloc(struct super_block *sb);
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
++
++unsigned int au_sigen_inc(struct super_block *sb);
++aufs_bindex_t au_new_br_id(struct super_block *sb);
++
++void aufs_read_lock(struct dentry *dentry, int flags);
++void aufs_read_unlock(struct dentry *dentry, int flags);
++void aufs_write_lock(struct dentry *dentry);
++void aufs_write_unlock(struct dentry *dentry);
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++/* wbr_policy.c */
++extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
++extern struct au_wbr_create_operations au_wbr_create_ops[];
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_sbinfo *au_sbi(struct super_block *sb)
++{
++ return sb->s_fs_info;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++void au_export_init(struct super_block *sb);
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
++}
++
++int au_xigen_inc(struct inode *inode);
++int au_xigen_new(struct inode *inode);
++int au_xigen_set(struct super_block *sb, struct file *base);
++void au_xigen_clr(struct super_block *sb);
++
++static inline int au_busy_or_stale(void)
++{
++ if (!au_test_nfsd(current))
++ return -EBUSY;
++ return -ESTALE;
++}
++#else
++static inline void au_export_init(struct super_block *sb)
++{
++ /* nothing */
++}
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++ return 0;
++}
++
++static inline int au_xigen_inc(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int au_xigen_new(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int au_xigen_set(struct super_block *sb, struct file *base)
++{
++ return 0;
++}
++
++static inline void au_xigen_clr(struct super_block *sb)
++{
++ /* empty */
++}
++
++static inline int au_busy_or_stale(void)
++{
++ return -EBUSY;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
++{
++#ifdef CONFIG_DEBUG_FS
++ sbinfo->si_dbgaufs = NULL;
++ sbinfo->si_dbgaufs_xib = NULL;
++#ifdef CONFIG_AUFS_EXPORT
++ sbinfo->si_dbgaufs_xigen = NULL;
++#endif
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock superblock. mainly for entry point functions */
++/*
++ * si_noflush_read_lock, si_noflush_write_lock,
++ * si_read_unlock, si_write_unlock, si_downgrade_lock
++ */
++AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
++ &au_sbi(sb)->si_rwsem);
++AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
++
++static inline void si_read_lock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ si_noflush_read_lock(sb);
++}
++
++static inline void si_write_lock(struct super_block *sb)
++{
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ si_noflush_write_lock(sb);
++}
++
++static inline int si_read_trylock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ return si_noflush_read_trylock(sb);
++}
++
++static inline int si_write_trylock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ return si_noflush_write_trylock(sb);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_sbend(struct super_block *sb)
++{
++ return au_sbi(sb)->si_bend;
++}
++
++static inline unsigned int au_mntflags(struct super_block *sb)
++{
++ return au_sbi(sb)->si_mntflags;
++}
++
++static inline unsigned int au_sigen(struct super_block *sb)
++{
++ return au_sbi(sb)->si_generation;
++}
++
++static inline struct au_branch *au_sbr(struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ return au_sbi(sb)->si_branch[0 + bindex];
++}
++
++static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
++{
++ au_sbi(sb)->si_xino_brid = brid;
++}
++
++static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
++{
++ return au_sbi(sb)->si_xino_brid;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SUPER_H__ */
+diff -Naur a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
+--- a/fs/aufs/sysaufs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface and lifetime management
++ * they are necessary regardless sysfs is disabled.
++ */
++
++#include <linux/fs.h>
++#include <linux/random.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++unsigned long sysaufs_si_mask;
++struct kset *sysaufs_ket;
++
++#define AuSiAttr(_name) { \
++ .attr = { .name = __stringify(_name), .mode = 0444 }, \
++ .show = sysaufs_si_##_name, \
++}
++
++static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
++struct attribute *sysaufs_si_attrs[] = {
++ &sysaufs_si_attr_xi_path.attr,
++ NULL,
++};
++
++static struct sysfs_ops au_sbi_ops = {
++ .show = sysaufs_si_show
++};
++
++static struct kobj_type au_sbi_ktype = {
++ .release = au_si_free,
++ .sysfs_ops = &au_sbi_ops,
++ .default_attrs = sysaufs_si_attrs
++};
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++
++ sbinfo->si_kobj.kset = sysaufs_ket;
++ /* cf. sysaufs_name() */
++ err = kobject_init_and_add
++ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
++ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
++
++ dbgaufs_si_null(sbinfo);
++ if (!err) {
++ err = dbgaufs_si_init(sbinfo);
++ if (unlikely(err))
++ kobject_put(&sbinfo->si_kobj);
++ }
++ return err;
++}
++
++void sysaufs_fin(void)
++{
++ dbgaufs_fin();
++ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++ kset_unregister(sysaufs_ket);
++}
++
++int __init sysaufs_init(void)
++{
++ int err;
++
++ do {
++ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
++ } while (!sysaufs_si_mask);
++
++ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
++ err = PTR_ERR(sysaufs_ket);
++ if (IS_ERR(sysaufs_ket))
++ goto out;
++ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++ if (unlikely(err)) {
++ kset_unregister(sysaufs_ket);
++ goto out;
++ }
++
++ err = dbgaufs_init();
++ if (unlikely(err))
++ sysaufs_fin();
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
+--- a/fs/aufs/sysaufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface and mount lifetime management
++ */
++
++#ifndef __SYSAUFS_H__
++#define __SYSAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sysfs.h>
++#include <linux/aufs_type.h>
++#include "module.h"
++
++struct super_block;
++struct au_sbinfo;
++
++struct sysaufs_si_attr {
++ struct attribute attr;
++ int (*show)(struct seq_file *seq, struct super_block *sb);
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* sysaufs.c */
++extern unsigned long sysaufs_si_mask;
++extern struct kset *sysaufs_ket;
++extern struct attribute *sysaufs_si_attrs[];
++int sysaufs_si_init(struct au_sbinfo *sbinfo);
++int __init sysaufs_init(void);
++void sysaufs_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++/* some people doesn't like to show a pointer in kernel */
++static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
++{
++ return sysaufs_si_mask ^ (unsigned long)sbinfo;
++}
++
++#define SysaufsSiNamePrefix "si_"
++#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
++static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
++{
++ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
++ sysaufs_si_id(sbinfo));
++}
++
++struct au_branch;
++#ifdef CONFIG_SYSFS
++/* sysfs.c */
++extern struct attribute_group *sysaufs_attr_group;
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf);
++
++void sysaufs_br_init(struct au_branch *br);
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++
++#define sysaufs_brs_init() do {} while (0)
++
++#else
++#define sysaufs_attr_group NULL
++
++static inline
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++ return 0;
++}
++
++static inline
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ return 0;
++}
++
++static inline void sysaufs_br_init(struct au_branch *br)
++{
++ /* empty */
++}
++
++static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_brs_init(void)
++{
++ sysaufs_brs = 0;
++}
++
++#endif /* CONFIG_SYSFS */
++
++#endif /* __KERNEL__ */
++#endif /* __SYSAUFS_H__ */
+diff -Naur a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
+--- a/fs/aufs/sysfs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysfs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,208 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++static struct attribute *au_attr[] = {
++ NULL, /* need to NULL terminate the list of attributes */
++};
++
++static struct attribute_group sysaufs_attr_group_body = {
++ .attrs = au_attr
++};
++
++struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++
++ err = 0;
++ if (au_opt_test(au_mntflags(sb), XINO)) {
++ err = au_xino_path(seq, au_sbi(sb)->si_xib);
++ seq_putc(seq, '\n');
++ }
++ return err;
++}
++
++/*
++ * the lifetime of branch is independent from the entry under sysfs.
++ * sysfs handles the lifetime of the entry, and never call ->show() after it is
++ * unlinked.
++ */
++static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ struct path path;
++ struct dentry *root;
++ struct au_branch *br;
++
++ AuDbg("b%d\n", bindex);
++
++ root = sb->s_root;
++ di_read_lock_parent(root, !AuLock_IR);
++ br = au_sbr(sb, bindex);
++ path.mnt = br->br_mnt;
++ path.dentry = au_h_dptr(root, bindex);
++ au_seq_path(seq, &path);
++ di_read_unlock(root, !AuLock_IR);
++ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct seq_file *au_seq(char *p, ssize_t len)
++{
++ struct seq_file *seq;
++
++ seq = kzalloc(sizeof(*seq), GFP_NOFS);
++ if (seq) {
++ /* mutex_init(&seq.lock); */
++ seq->buf = p;
++ seq->size = len;
++ return seq; /* success */
++ }
++
++ seq = ERR_PTR(-ENOMEM);
++ return seq;
++}
++
++#define SysaufsBr_PREFIX "br"
++
++/* todo: file size may exceed PAGE_SIZE */
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ ssize_t err;
++ long l;
++ aufs_bindex_t bend;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++ struct seq_file *seq;
++ char *name;
++ struct attribute **cattr;
++
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++
++ seq = au_seq(buf, PAGE_SIZE);
++ err = PTR_ERR(seq);
++ if (IS_ERR(seq))
++ goto out;
++
++ name = (void *)attr->name;
++ cattr = sysaufs_si_attrs;
++ while (*cattr) {
++ if (!strcmp(name, (*cattr)->name)) {
++ err = container_of(*cattr, struct sysaufs_si_attr, attr)
++ ->show(seq, sb);
++ goto out_seq;
++ }
++ cattr++;
++ }
++
++ bend = au_sbend(sb);
++ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
++ name += sizeof(SysaufsBr_PREFIX) - 1;
++ err = strict_strtol(name, 10, &l);
++ if (!err) {
++ if (l <= bend)
++ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
++ else
++ err = -ENOENT;
++ }
++ goto out_seq;
++ }
++ BUG();
++
++ out_seq:
++ if (!err) {
++ err = seq->count;
++ /* sysfs limit */
++ if (unlikely(err == PAGE_SIZE))
++ err = -EFBIG;
++ }
++ kfree(seq);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void sysaufs_br_init(struct au_branch *br)
++{
++ br->br_attr.name = br->br_name;
++ br->br_attr.mode = S_IRUGO;
++ br->br_attr.owner = THIS_MODULE;
++}
++
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ struct au_branch *br;
++ struct kobject *kobj;
++ aufs_bindex_t bend;
++
++ dbgaufs_brs_del(sb, bindex);
++
++ if (!sysaufs_brs)
++ return;
++
++ kobj = &au_sbi(sb)->si_kobj;
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ sysfs_remove_file(kobj, &br->br_attr);
++ }
++}
++
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ aufs_bindex_t bend;
++ struct kobject *kobj;
++ struct au_branch *br;
++
++ dbgaufs_brs_add(sb, bindex);
++
++ if (!sysaufs_brs)
++ return;
++
++ kobj = &au_sbi(sb)->si_kobj;
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
++ "%d", bindex);
++ err = sysfs_create_file(kobj, &br->br_attr);
++ if (unlikely(err))
++ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
++ }
++}
+diff -Naur a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c
+--- a/fs/aufs/sysrq.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysrq.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,115 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * magic sysrq hanlder
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++/* #include <linux/sysrq.h> */
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++static void sysrq_sb(struct super_block *sb)
++{
++ char *plevel;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ plevel = au_plevel;
++ au_plevel = KERN_WARNING;
++ au_debug(1);
++
++ sbinfo = au_sbi(sb);
++ pr_warning("si=%lx\n", sysaufs_si_id(sbinfo));
++ pr_warning(AUFS_NAME ": superblock\n");
++ au_dpri_sb(sb);
++ pr_warning(AUFS_NAME ": root dentry\n");
++ au_dpri_dentry(sb->s_root);
++ pr_warning(AUFS_NAME ": root inode\n");
++ au_dpri_inode(sb->s_root->d_inode);
++#if 0
++ struct inode *i;
++ pr_warning(AUFS_NAME ": isolated inode\n");
++ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
++ if (list_empty(&i->i_dentry))
++ au_dpri_inode(i);
++#endif
++ pr_warning(AUFS_NAME ": files\n");
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list)
++ if (!special_file(file->f_dentry->d_inode->i_mode))
++ au_dpri_file(file);
++
++ au_plevel = plevel;
++ au_debug(0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* module parameter */
++static char *aufs_sysrq_key = "a";
++module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
++MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
++
++static void au_sysrq(int key __maybe_unused,
++ struct tty_struct *tty __maybe_unused)
++{
++ struct kobject *kobj;
++ struct au_sbinfo *sbinfo;
++
++ /* spin_lock(&sysaufs_ket->list_lock); */
++ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ sysrq_sb(sbinfo->si_sb);
++ }
++ /* spin_unlock(&sysaufs_ket->list_lock); */
++}
++
++static struct sysrq_key_op au_sysrq_op = {
++ .handler = au_sysrq,
++ .help_msg = "Aufs",
++ .action_msg = "Aufs",
++ .enable_mask = SYSRQ_ENABLE_DUMP
++};
++
++/* ---------------------------------------------------------------------- */
++
++int __init au_sysrq_init(void)
++{
++ int err;
++ char key;
++
++ err = -1;
++ key = *aufs_sysrq_key;
++ if ('a' <= key && key <= 'z')
++ err = register_sysrq_key(key, &au_sysrq_op);
++ if (unlikely(err))
++ AuErr("err %d, sysrq=%c\n", err, key);
++ return err;
++}
++
++void au_sysrq_fin(void)
++{
++ int err;
++ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
++ if (unlikely(err))
++ AuErr("err %d (ignored)\n", err);
++}
+diff -Naur a/fs/aufs/vdir.c b/fs/aufs/vdir.c
+--- a/fs/aufs/vdir.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vdir.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * virtual or vertical directory
++ */
++
++#include <linux/hash.h>
++#include "aufs.h"
++
++static unsigned int calc_size(int nlen)
++{
++ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
++ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
++}
++
++static int set_deblk_end(union au_vdir_deblk_p *p,
++ union au_vdir_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
++ p->de->de_str.len = 0;
++ /* smp_mb(); */
++ return 0;
++ }
++ return -1; /* error */
++}
++
++/* returns true or false */
++static int is_deblk_end(union au_vdir_deblk_p *p,
++ union au_vdir_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->deblk - p->deblk)
++ return !p->de->de_str.len;
++ return 1;
++}
++
++static unsigned char *last_deblk(struct au_vdir *vdir)
++{
++ return vdir->vd_deblk[vdir->vd_nblk - 1];
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the allocated memory has to be freed by
++ * au_nhash_wh_free() or au_nhash_de_free().
++ */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
++{
++ struct hlist_head *head;
++ unsigned int u;
++
++ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
++ if (head) {
++ nhash->nh_num = num_hash;
++ nhash->nh_head = head;
++ for (u = 0; u < num_hash; u++)
++ INIT_HLIST_HEAD(head++);
++ return 0; /* success */
++ }
++
++ return -ENOMEM;
++}
++
++static void nhash_count(struct hlist_head *head)
++{
++#if 0
++ unsigned long n;
++ struct hlist_node *pos;
++
++ n = 0;
++ hlist_for_each(pos, head)
++ n++;
++ AuInfo("%lu\n", n);
++#endif
++}
++
++static void au_nhash_wh_do_free(struct hlist_head *head)
++{
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos, *node;
++
++ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
++ /* hlist_del(pos); */
++ kfree(tpos);
++ }
++}
++
++static void au_nhash_de_do_free(struct hlist_head *head)
++{
++ struct au_vdir_dehstr *tpos;
++ struct hlist_node *pos, *node;
++
++ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
++ /* hlist_del(pos); */
++ au_cache_free_dehstr(tpos);
++ }
++}
++
++static void au_nhash_do_free(struct au_nhash *nhash,
++ void (*free)(struct hlist_head *head))
++{
++ unsigned int u, n;
++ struct hlist_head *head;
++
++ n = nhash->nh_num;
++ head = nhash->nh_head;
++ for (u = 0; u < n; u++) {
++ nhash_count(head);
++ free(head++);
++ }
++ kfree(nhash->nh_head);
++}
++
++void au_nhash_wh_free(struct au_nhash *whlist)
++{
++ au_nhash_do_free(whlist, au_nhash_wh_do_free);
++}
++
++static void au_nhash_de_free(struct au_nhash *delist)
++{
++ au_nhash_do_free(delist, au_nhash_de_do_free);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++ int limit)
++{
++ int num;
++ unsigned int u, n;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++
++ num = 0;
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (u = 0; u < n; u++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ if (tpos->wh_bindex == btgt && ++num > limit)
++ return 1;
++ head++;
++ }
++ return 0;
++}
++
++static struct hlist_head *au_name_hash(struct au_nhash *nhash,
++ unsigned char *name,
++ unsigned int len)
++{
++ unsigned int v;
++ /* const unsigned int magic_bit = 12; */
++
++ v = 0;
++ while (len--)
++ v += *name++;
++ /* v = hash_long(v, magic_bit); */
++ v %= nhash->nh_num;
++ return nhash->nh_head + v;
++}
++
++static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
++ int nlen)
++{
++ return str->len == nlen && !memcmp(str->name, name, nlen);
++}
++
++/* returns found or not */
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
++{
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ head = au_name_hash(whlist, name, nlen);
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ str = &tpos->wh_str;
++ AuDbg("%.*s\n", str->len, str->name);
++ if (au_nhash_test_name(str, name, nlen))
++ return 1;
++ }
++ return 0;
++}
++
++/* returns found(true) or not */
++static int test_known(struct au_nhash *delist, char *name, int nlen)
++{
++ struct hlist_head *head;
++ struct au_vdir_dehstr *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ head = au_name_hash(delist, name, nlen);
++ hlist_for_each_entry(tpos, pos, head, hash) {
++ str = tpos->str;
++ AuDbg("%.*s\n", str->len, str->name);
++ if (au_nhash_test_name(str, name, nlen))
++ return 1;
++ }
++ return 0;
++}
++
++static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
++ unsigned char d_type)
++{
++#ifdef CONFIG_AUFS_SHWH
++ wh->wh_ino = ino;
++ wh->wh_type = d_type;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++ unsigned int d_type, aufs_bindex_t bindex,
++ unsigned char shwh)
++{
++ int err;
++ struct au_vdir_destr *str;
++ struct au_vdir_wh *wh;
++
++ AuDbg("%.*s\n", nlen, name);
++ err = -ENOMEM;
++ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
++ if (unlikely(!wh))
++ goto out;
++
++ err = 0;
++ wh->wh_bindex = bindex;
++ if (shwh)
++ au_shwh_init_wh(wh, ino, d_type);
++ str = &wh->wh_str;
++ str->len = nlen;
++ memcpy(str->name, name, nlen);
++ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
++ /* smp_mb(); */
++
++ out:
++ return err;
++}
++
++static int append_deblk(struct au_vdir *vdir)
++{
++ int err;
++ unsigned long ul;
++ const unsigned int deblk_sz = vdir->vd_deblk_sz;
++ union au_vdir_deblk_p p, deblk_end;
++ unsigned char **o;
++
++ err = -ENOMEM;
++ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
++ GFP_NOFS);
++ if (unlikely(!o))
++ goto out;
++
++ vdir->vd_deblk = o;
++ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
++ if (p.deblk) {
++ ul = vdir->vd_nblk++;
++ vdir->vd_deblk[ul] = p.deblk;
++ vdir->vd_last.ul = ul;
++ vdir->vd_last.p.deblk = p.deblk;
++ deblk_end.deblk = p.deblk + deblk_sz;
++ err = set_deblk_end(&p, &deblk_end);
++ }
++
++ out:
++ return err;
++}
++
++static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
++ unsigned int d_type, struct au_nhash *delist)
++{
++ int err;
++ unsigned int sz;
++ const unsigned int deblk_sz = vdir->vd_deblk_sz;
++ union au_vdir_deblk_p p, *room, deblk_end;
++ struct au_vdir_dehstr *dehstr;
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + deblk_sz;
++ room = &vdir->vd_last.p;
++ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
++ || !is_deblk_end(room, &deblk_end));
++
++ sz = calc_size(nlen);
++ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
++ err = append_deblk(vdir);
++ if (unlikely(err))
++ goto out;
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + deblk_sz;
++ /* smp_mb(); */
++ AuDebugOn(room->deblk != p.deblk);
++ }
++
++ err = -ENOMEM;
++ dehstr = au_cache_alloc_dehstr();
++ if (unlikely(!dehstr))
++ goto out;
++
++ dehstr->str = &room->de->de_str;
++ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
++ room->de->de_ino = ino;
++ room->de->de_type = d_type;
++ room->de->de_str.len = nlen;
++ memcpy(room->de->de_str.name, name, nlen);
++
++ err = 0;
++ room->deblk += sz;
++ if (unlikely(set_deblk_end(room, &deblk_end)))
++ err = append_deblk(vdir);
++ /* smp_mb(); */
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_vdir_free(struct au_vdir *vdir)
++{
++ unsigned char **deblk;
++
++ deblk = vdir->vd_deblk;
++ while (vdir->vd_nblk--)
++ kfree(*deblk++);
++ kfree(vdir->vd_deblk);
++ au_cache_free_vdir(vdir);
++}
++
++static struct au_vdir *alloc_vdir(struct super_block *sb)
++{
++ struct au_vdir *vdir;
++ int err;
++
++ err = -ENOMEM;
++ vdir = au_cache_alloc_vdir();
++ if (unlikely(!vdir))
++ goto out;
++
++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
++ if (unlikely(!vdir->vd_deblk))
++ goto out_free;
++
++ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
++ vdir->vd_nblk = 0;
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ err = append_deblk(vdir);
++ if (!err)
++ return vdir; /* success */
++
++ kfree(vdir->vd_deblk);
++
++ out_free:
++ au_cache_free_vdir(vdir);
++ out:
++ vdir = ERR_PTR(err);
++ return vdir;
++}
++
++static int reinit_vdir(struct au_vdir *vdir)
++{
++ int err;
++ union au_vdir_deblk_p p, deblk_end;
++
++ while (vdir->vd_nblk > 1) {
++ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
++ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
++ vdir->vd_nblk--;
++ }
++ p.deblk = vdir->vd_deblk[0];
++ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
++ err = set_deblk_end(&p, &deblk_end);
++ /* keep vd_dblk_sz */
++ vdir->vd_last.ul = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ /* smp_mb(); */
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ unsigned int d_type, ino_t *ino)
++{
++ int err;
++ struct mutex *mtx;
++ const int isdir = (d_type == DT_DIR);
++
++ /* prevent hardlinks from race condition */
++ mtx = NULL;
++ if (!isdir) {
++ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
++ mutex_lock(mtx);
++ }
++ err = au_xino_read(sb, bindex, h_ino, ino);
++ if (unlikely(err))
++ goto out;
++
++ if (!*ino) {
++ err = -EIO;
++ *ino = au_xino_new_ino(sb);
++ if (unlikely(!*ino))
++ goto out;
++ err = au_xino_write(sb, bindex, h_ino, *ino);
++ if (unlikely(err))
++ goto out;
++ }
++
++ out:
++ if (!isdir)
++ mutex_unlock(mtx);
++ return err;
++}
++
++static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ unsigned int d_type, ino_t *ino)
++{
++#ifdef CONFIG_AUFS_SHWH
++ return au_ino(sb, bindex, h_ino, d_type, ino);
++#else
++ return 0;
++#endif
++}
++
++#define AuFillVdir_CALLED 1
++#define AuFillVdir_WHABLE (1 << 1)
++#define AuFillVdir_SHWH (1 << 2)
++#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
++#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
++#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuFillVdir_SHWH
++#define AuFillVdir_SHWH 0
++#endif
++
++struct fillvdir_arg {
++ struct file *file;
++ struct au_vdir *vdir;
++ struct au_nhash delist;
++ struct au_nhash whlist;
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ int err;
++};
++
++static int fillvdir(void *__arg, const char *__name, int nlen,
++ loff_t offset __maybe_unused, u64 h_ino,
++ unsigned int d_type)
++{
++ struct fillvdir_arg *arg = __arg;
++ char *name = (void *)__name;
++ struct super_block *sb;
++ ino_t ino;
++ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
++
++ arg->err = 0;
++ sb = arg->file->f_dentry->d_sb;
++ au_fset_fillvdir(arg->flags, CALLED);
++ /* smp_mb(); */
++ if (nlen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (test_known(&arg->delist, name, nlen)
++ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
++ goto out; /* already exists or whiteouted */
++
++ sb = arg->file->f_dentry->d_sb;
++ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
++ if (!arg->err)
++ arg->err = append_de(arg->vdir, name, nlen, ino,
++ d_type, &arg->delist);
++ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
++ name += AUFS_WH_PFX_LEN;
++ nlen -= AUFS_WH_PFX_LEN;
++ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
++ goto out; /* already whiteouted */
++
++ if (shwh)
++ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
++ &ino);
++ if (!arg->err)
++ arg->err = au_nhash_append_wh
++ (&arg->whlist, name, nlen, ino, d_type,
++ arg->bindex, shwh);
++ }
++
++ out:
++ if (!arg->err)
++ arg->vdir->vd_jiffy = jiffies;
++ /* smp_mb(); */
++ AuTraceErr(arg->err);
++ return arg->err;
++}
++
++static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
++ struct au_nhash *whlist, struct au_nhash *delist)
++{
++#ifdef CONFIG_AUFS_SHWH
++ int err;
++ unsigned int nh, u;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos, *n;
++ char *p, *o;
++ struct au_vdir_destr *destr;
++
++ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
++
++ err = -ENOMEM;
++ o = p = __getname();
++ if (unlikely(!p))
++ goto out;
++
++ err = 0;
++ nh = whlist->nh_num;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++ for (u = 0; u < nh; u++) {
++ head = whlist->nh_head + u;
++ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
++ destr = &tpos->wh_str;
++ memcpy(p, destr->name, destr->len);
++ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
++ tpos->wh_ino, tpos->wh_type, delist);
++ if (unlikely(err))
++ break;
++ }
++ }
++
++ __putname(o);
++
++ out:
++ AuTraceErr(err);
++ return err;
++#else
++ return 0;
++#endif
++}
++
++static int au_do_read_vdir(struct fillvdir_arg *arg)
++{
++ int err;
++ unsigned int rdhash;
++ loff_t offset;
++ aufs_bindex_t bend, bindex, bstart;
++ unsigned char shwh;
++ struct file *hf, *file;
++ struct super_block *sb;
++
++ file = arg->file;
++ sb = file->f_dentry->d_sb;
++ rdhash = au_sbi(sb)->si_rdhash;
++ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out_delist;
++
++ err = 0;
++ arg->flags = 0;
++ shwh = 0;
++ if (au_opt_test(au_mntflags(sb), SHWH)) {
++ shwh = 1;
++ au_fset_fillvdir(arg->flags, SHWH);
++ }
++ bstart = au_fbstart(file);
++ bend = au_fbend(file);
++ for (bindex = bstart; !err && bindex <= bend; bindex++) {
++ hf = au_h_fptr(file, bindex);
++ if (!hf)
++ continue;
++
++ offset = vfsub_llseek(hf, 0, SEEK_SET);
++ err = offset;
++ if (unlikely(offset))
++ break;
++
++ arg->bindex = bindex;
++ au_fclr_fillvdir(arg->flags, WHABLE);
++ if (shwh
++ || (bindex != bend
++ && au_br_whable(au_sbr_perm(sb, bindex))))
++ au_fset_fillvdir(arg->flags, WHABLE);
++ do {
++ arg->err = 0;
++ au_fclr_fillvdir(arg->flags, CALLED);
++ /* smp_mb(); */
++ err = vfsub_readdir(hf, fillvdir, arg);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
++ }
++
++ if (!err && shwh)
++ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
++
++ au_nhash_wh_free(&arg->whlist);
++
++ out_delist:
++ au_nhash_de_free(&arg->delist);
++ out:
++ return err;
++}
++
++static int read_vdir(struct file *file, int may_read)
++{
++ int err;
++ unsigned long expire;
++ unsigned char do_read;
++ struct fillvdir_arg arg;
++ struct inode *inode;
++ struct au_vdir *vdir, *allocated;
++
++ err = 0;
++ inode = file->f_dentry->d_inode;
++ IMustLock(inode);
++ allocated = NULL;
++ do_read = 0;
++ expire = au_sbi(inode->i_sb)->si_rdcache;
++ vdir = au_ivdir(inode);
++ if (!vdir) {
++ do_read = 1;
++ vdir = alloc_vdir(inode->i_sb);
++ err = PTR_ERR(vdir);
++ if (IS_ERR(vdir))
++ goto out;
++ err = 0;
++ allocated = vdir;
++ } else if (may_read
++ && (inode->i_version != vdir->vd_version
++ || time_after(jiffies, vdir->vd_jiffy + expire))) {
++ do_read = 1;
++ err = reinit_vdir(vdir);
++ if (unlikely(err))
++ goto out;
++ }
++
++ if (!do_read)
++ return 0; /* success */
++
++ arg.file = file;
++ arg.vdir = vdir;
++ err = au_do_read_vdir(&arg);
++ if (!err) {
++ /* file->f_pos = 0; */
++ vdir->vd_version = inode->i_version;
++ vdir->vd_last.ul = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ if (allocated)
++ au_set_ivdir(inode, allocated);
++ } else if (allocated)
++ au_vdir_free(allocated);
++
++ out:
++ return err;
++}
++
++static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
++{
++ int err, rerr;
++ unsigned long ul, n;
++ const unsigned int deblk_sz = src->vd_deblk_sz;
++
++ AuDebugOn(tgt->vd_nblk != 1);
++
++ err = -ENOMEM;
++ if (tgt->vd_nblk < src->vd_nblk) {
++ unsigned char **p;
++
++ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
++ GFP_NOFS);
++ if (unlikely(!p))
++ goto out;
++ tgt->vd_deblk = p;
++ }
++
++ tgt->vd_nblk = src->vd_nblk;
++ tgt->vd_deblk_sz = deblk_sz;
++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
++ /* tgt->vd_last.i = 0; */
++ /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */
++ tgt->vd_version = src->vd_version;
++ tgt->vd_jiffy = src->vd_jiffy;
++
++ n = src->vd_nblk;
++ for (ul = 1; ul < n; ul++) {
++ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
++ GFP_NOFS);
++ if (unlikely(!tgt->vd_deblk[ul]))
++ goto out;
++ }
++ /* smp_mb(); */
++ return 0; /* success */
++
++ out:
++ rerr = reinit_vdir(tgt);
++ BUG_ON(rerr);
++ return err;
++}
++
++int au_vdir_init(struct file *file)
++{
++ int err;
++ struct inode *inode;
++ struct au_vdir *vdir_cache, *allocated;
++
++ err = read_vdir(file, !file->f_pos);
++ if (unlikely(err))
++ goto out;
++
++ allocated = NULL;
++ vdir_cache = au_fvdir_cache(file);
++ if (!vdir_cache) {
++ vdir_cache = alloc_vdir(file->f_dentry->d_sb);
++ err = PTR_ERR(vdir_cache);
++ if (IS_ERR(vdir_cache))
++ goto out;
++ allocated = vdir_cache;
++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
++ err = reinit_vdir(vdir_cache);
++ if (unlikely(err))
++ goto out;
++ } else
++ return 0; /* success */
++
++ inode = file->f_dentry->d_inode;
++ err = copy_vdir(vdir_cache, au_ivdir(inode));
++ if (!err) {
++ file->f_version = inode->i_version;
++ if (allocated)
++ au_set_fvdir_cache(file, allocated);
++ } else if (allocated)
++ au_vdir_free(allocated);
++
++ out:
++ return err;
++}
++
++static loff_t calc_offset(struct au_vdir *vdir)
++{
++ loff_t offset;
++ union au_vdir_deblk_p p;
++
++ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
++ offset = vdir->vd_last.p.deblk - p.deblk;
++ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
++ return offset;
++}
++
++/* returns true or false */
++static int seek_vdir(struct file *file)
++{
++ int valid;
++ unsigned int deblk_sz;
++ unsigned long ul, n;
++ loff_t offset;
++ union au_vdir_deblk_p p, deblk_end;
++ struct au_vdir *vdir_cache;
++
++ valid = 1;
++ vdir_cache = au_fvdir_cache(file);
++ offset = calc_offset(vdir_cache);
++ AuDbg("offset %lld\n", offset);
++ if (file->f_pos == offset)
++ goto out;
++
++ vdir_cache->vd_last.ul = 0;
++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
++ if (!file->f_pos)
++ goto out;
++
++ valid = 0;
++ deblk_sz = vdir_cache->vd_deblk_sz;
++ ul = div64_u64(file->f_pos, deblk_sz);
++ AuDbg("ul %lu\n", ul);
++ if (ul >= vdir_cache->vd_nblk)
++ goto out;
++
++ n = vdir_cache->vd_nblk;
++ for (; ul < n; ul++) {
++ p.deblk = vdir_cache->vd_deblk[ul];
++ deblk_end.deblk = p.deblk + deblk_sz;
++ offset = ul;
++ offset *= deblk_sz;
++ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
++ unsigned int l;
++
++ l = calc_size(p.de->de_str.len);
++ offset += l;
++ p.deblk += l;
++ }
++ if (!is_deblk_end(&p, &deblk_end)) {
++ valid = 1;
++ vdir_cache->vd_last.ul = ul;
++ vdir_cache->vd_last.p = p;
++ break;
++ }
++ }
++
++ out:
++ /* smp_mb(); */
++ AuTraceErr(!valid);
++ return valid;
++}
++
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ unsigned int l, deblk_sz;
++ union au_vdir_deblk_p deblk_end;
++ struct au_vdir *vdir_cache;
++ struct au_vdir_de *de;
++
++ vdir_cache = au_fvdir_cache(file);
++ if (!seek_vdir(file))
++ return 0;
++
++ deblk_sz = vdir_cache->vd_deblk_sz;
++ while (1) {
++ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++ deblk_end.deblk += deblk_sz;
++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
++ de = vdir_cache->vd_last.p.de;
++ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
++ de->de_str.len, de->de_str.name, file->f_pos,
++ (unsigned long)de->de_ino, de->de_type);
++ err = filldir(dirent, de->de_str.name, de->de_str.len,
++ file->f_pos, de->de_ino, de->de_type);
++ if (unlikely(err)) {
++ AuTraceErr(err);
++ /* todo: ignore the error caused by udba? */
++ /* return err; */
++ return 0;
++ }
++
++ l = calc_size(de->de_str.len);
++ vdir_cache->vd_last.p.deblk += l;
++ file->f_pos += l;
++ }
++ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
++ vdir_cache->vd_last.ul++;
++ vdir_cache->vd_last.p.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
++ continue;
++ }
++ break;
++ }
++
++ /* smp_mb(); */
++ return 0;
++}
+diff -Naur a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
+--- a/fs/aufs/vfsub.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/splice.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++int vfsub_update_h_iattr(struct path *h_path, int *did)
++{
++ int err;
++ struct kstat st;
++ struct super_block *h_sb;
++
++ /* for remote fs, leave work for its getattr or d_revalidate */
++ /* for bad i_attr fs, handle them in aufs_getattr() */
++ /* still some fs may acquire i_mutex. we need to skip them */
++ err = 0;
++ if (!did)
++ did = &err;
++ h_sb = h_path->dentry->d_sb;
++ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
++ if (*did)
++ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct file *vfsub_filp_open(const char *path, int oflags, int mode)
++{
++ struct file *file;
++
++ lockdep_off();
++ file = filp_open(path, oflags, mode);
++ lockdep_on();
++ if (IS_ERR(file))
++ goto out;
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++
++ out:
++ return file;
++}
++
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
++{
++ int err;
++
++ /* lockdep_off(); */
++ err = kern_path(name, flags, path);
++ /* lockdep_on(); */
++ if (!err && path->dentry->d_inode)
++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++ int len)
++{
++ struct path path = {
++ .mnt = NULL
++ };
++
++ IMustLock(parent->d_inode);
++
++ path.dentry = lookup_one_len(name, parent, len);
++ if (IS_ERR(path.dentry))
++ goto out;
++ if (path.dentry->d_inode)
++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++ out:
++ return path.dentry;
++}
++
++struct dentry *vfsub_lookup_hash(struct nameidata *nd)
++{
++ struct path path = {
++ .mnt = nd->path.mnt
++ };
++
++ IMustLock(nd->path.dentry->d_inode);
++
++ path.dentry = lookup_hash(nd);
++ if (!IS_ERR(path.dentry) && path.dentry->d_inode)
++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++ return path.dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2)
++{
++ struct dentry *d;
++
++ lockdep_off();
++ d = lock_rename(d1, d2);
++ lockdep_on();
++ au_hin_suspend(hdir1);
++ if (hdir1 != hdir2)
++ au_hin_suspend(hdir2);
++
++ return d;
++}
++
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2)
++{
++ au_hin_resume(hdir1);
++ if (hdir1 != hdir2)
++ au_hin_resume(hdir2);
++ lockdep_off();
++ unlock_rename(d1, d2);
++ lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_create(struct inode *dir, struct path *path, int mode)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mknod(path, path->dentry, mode, 0);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ if (au_test_fs_null_nd(dir->i_sb))
++ err = vfs_create(dir, path->dentry, mode, NULL);
++ else {
++ struct nameidata h_nd;
++
++ memset(&h_nd, 0, sizeof(h_nd));
++ h_nd.flags = LOOKUP_CREATE;
++ h_nd.intent.open.flags = O_CREAT
++ | vfsub_fmode_to_uint(FMODE_READ);
++ h_nd.intent.open.create_mode = mode;
++ h_nd.path.dentry = path->dentry->d_parent;
++ h_nd.path.mnt = path->mnt;
++ path_get(&h_nd.path);
++ err = vfs_create(dir, path->dentry, mode, &h_nd);
++ path_put(&h_nd.path);
++ }
++
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_symlink(path, path->dentry, symname);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_symlink(dir, path->dentry, symname);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mknod(path, path->dentry, mode, dev);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_mknod(dir, path->dentry, mode, dev);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++static int au_test_nlink(struct inode *inode)
++{
++ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
++
++ if (!au_test_fs_no_limit_nlink(inode->i_sb)
++ || inode->i_nlink < link_max)
++ return 0;
++ return -EMLINK;
++}
++
++int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ err = au_test_nlink(src_dentry->d_inode);
++ if (unlikely(err))
++ return err;
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_link(src_dentry, path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_link(src_dentry, dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ /* fuse has different memory inode for the same inumber */
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ tmp.dentry = src_dentry;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct path *path)
++{
++ int err;
++ struct path tmp = {
++ .mnt = path->mnt
++ };
++ struct dentry *d;
++
++ IMustLock(dir);
++ IMustLock(src_dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ tmp.dentry = src_dentry->d_parent;
++ err = security_path_rename(&tmp, src_dentry, path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ int did;
++
++ tmp.dentry = d->d_parent;
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = src_dentry;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ tmp.dentry = src_dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mkdir(path, path->dentry, mode);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_mkdir(dir, path->dentry, mode);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_rmdir(struct inode *dir, struct path *path)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_rmdir(path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_rmdir(dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ struct path tmp = {
++ .dentry = path->dentry->d_parent,
++ .mnt = path->mnt
++ };
++
++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ err = vfs_read(file, ubuf, count, ppos);
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++/* todo: kernel_read()? */
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ lockdep_off();
++ err = vfs_write(file, ubuf, count, ppos);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_readdir(file, filldir, arg);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ long err;
++
++ lockdep_off();
++ err = do_splice_to(in, ppos, pipe, len, flags);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
++{
++ long err;
++
++ lockdep_off();
++ err = do_splice_from(pipe, out, ppos, len, flags);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++ struct file *h_file)
++{
++ int err;
++ struct inode *h_inode;
++
++ h_inode = h_path->dentry->d_inode;
++ if (!h_file) {
++ err = mnt_want_write(h_path->mnt);
++ if (err)
++ goto out;
++ err = inode_permission(h_inode, MAY_WRITE);
++ if (err)
++ goto out_mnt;
++ err = get_write_access(h_inode);
++ if (err)
++ goto out_mnt;
++ err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
++ if (err)
++ goto out_inode;
++ }
++
++ err = locks_verify_truncate(h_inode, h_file, length);
++ if (!err)
++ err = security_path_truncate(h_path, length, attr);
++ if (!err) {
++ lockdep_off();
++ err = do_truncate(h_path->dentry, length, attr, h_file);
++ lockdep_on();
++ }
++
++ out_inode:
++ if (!h_file)
++ put_write_access(h_inode);
++ out_mnt:
++ if (!h_file)
++ mnt_drop_write(h_path->mnt);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_vfsub_mkdir_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++ int mode;
++};
++
++static void au_call_vfsub_mkdir(void *args)
++{
++ struct au_vfsub_mkdir_args *a = args;
++ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
++}
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
++{
++ int err, do_sio, wkq_err;
++
++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio)
++ err = vfsub_mkdir(dir, path, mode);
++ else {
++ struct au_vfsub_mkdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path,
++ .mode = mode
++ };
++ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++struct au_vfsub_rmdir_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++};
++
++static void au_call_vfsub_rmdir(void *args)
++{
++ struct au_vfsub_rmdir_args *a = args;
++ *a->errp = vfsub_rmdir(a->dir, a->path);
++}
++
++int vfsub_sio_rmdir(struct inode *dir, struct path *path)
++{
++ int err, do_sio, wkq_err;
++
++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio)
++ err = vfsub_rmdir(dir, path);
++ else {
++ struct au_vfsub_rmdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path
++ };
++ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct notify_change_args {
++ int *errp;
++ struct path *path;
++ struct iattr *ia;
++};
++
++static void call_notify_change(void *args)
++{
++ struct notify_change_args *a = args;
++ struct inode *h_inode;
++
++ h_inode = a->path->dentry->d_inode;
++ IMustLock(h_inode);
++
++ *a->errp = -EPERM;
++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ lockdep_off();
++ *a->errp = notify_change(a->path->dentry, a->ia);
++ lockdep_on();
++ if (!*a->errp)
++ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
++ }
++ AuTraceErr(*a->errp);
++}
++
++int vfsub_notify_change(struct path *path, struct iattr *ia)
++{
++ int err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .path = path,
++ .ia = ia
++ };
++
++ call_notify_change(&args);
++
++ return err;
++}
++
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
++{
++ int err, wkq_err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .path = path,
++ .ia = ia
++ };
++
++ wkq_err = au_wkq_wait(call_notify_change, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct unlink_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++};
++
++static void call_unlink(void *args)
++{
++ struct unlink_args *a = args;
++ struct dentry *d = a->path->dentry;
++ struct inode *h_inode;
++ const int stop_sillyrename = (au_test_nfs(d->d_sb)
++ && atomic_read(&d->d_count) == 1);
++
++ IMustLock(a->dir);
++
++ a->path->dentry = d->d_parent;
++ *a->errp = security_path_unlink(a->path, d);
++ a->path->dentry = d;
++ if (unlikely(*a->errp))
++ return;
++
++ if (!stop_sillyrename)
++ dget(d);
++ h_inode = d->d_inode;
++ if (h_inode)
++ atomic_inc(&h_inode->i_count);
++
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, d);
++ lockdep_on();
++ if (!*a->errp) {
++ struct path tmp = {
++ .dentry = d->d_parent,
++ .mnt = a->path->mnt
++ };
++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++ }
++
++ if (!stop_sillyrename)
++ dput(d);
++ if (h_inode)
++ iput(h_inode);
++
++ AuTraceErr(*a->errp);
++}
++
++/*
++ * @dir: must be locked.
++ * @dentry: target dentry.
++ */
++int vfsub_unlink(struct inode *dir, struct path *path, int force)
++{
++ int err;
++ struct unlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path
++ };
++
++ if (!force)
++ call_unlink(&args);
++ else {
++ int wkq_err;
++
++ wkq_err = au_wkq_wait(call_unlink, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
+diff -Naur a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+--- a/fs/aufs/vfsub.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,171 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#ifndef __AUFS_VFSUB_H__
++#define __AUFS_VFSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/fs_stack.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for lower inode */
++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
++/* reduce? gave up. */
++enum {
++ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
++ AuLsc_I_PARENT, /* lower inode, parent first */
++ AuLsc_I_PARENT2, /* copyup dirs */
++ AuLsc_I_CHILD,
++ AuLsc_I_CHILD2,
++ AuLsc_I_End
++};
++
++/* to debug easier, do not make them inlined functions */
++#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
++#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
++
++/* ---------------------------------------------------------------------- */
++
++static inline void vfsub_copy_inode_size(struct inode *inode,
++ struct inode *h_inode)
++{
++ spin_lock(&inode->i_lock);
++ fsstack_copy_inode_size(inode, h_inode);
++ spin_unlock(&inode->i_lock);
++}
++
++int vfsub_update_h_iattr(struct path *h_path, int *did);
++struct file *vfsub_filp_open(const char *path, int oflags, int mode);
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++ int len);
++struct dentry *vfsub_lookup_hash(struct nameidata *nd);
++
++/* ---------------------------------------------------------------------- */
++
++struct au_hinode;
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2);
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2);
++
++int vfsub_create(struct inode *dir, struct path *path, int mode);
++int vfsub_symlink(struct inode *dir, struct path *path,
++ const char *symname);
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct path *path);
++int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
++ struct inode *hdir, struct path *path);
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_rmdir(struct inode *dir, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos);
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
++
++static inline void vfsub_file_accessed(struct file *h_file)
++{
++ file_accessed(h_file);
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
++}
++
++static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
++ struct dentry *h_dentry)
++{
++ struct path h_path = {
++ .dentry = h_dentry,
++ .mnt = h_mnt
++ };
++ touch_atime(h_mnt, h_dentry);
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++ struct file *h_file);
++
++/* ---------------------------------------------------------------------- */
++
++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
++{
++ loff_t err;
++
++ lockdep_off();
++ err = vfs_llseek(file, offset, origin);
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dirty workaround for strict type of fmode_t */
++union vfsub_fmu {
++ fmode_t fm;
++ unsigned int ui;
++};
++
++static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
++{
++ union vfsub_fmu u = {
++ .fm = fm
++ };
++
++ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
++
++ return u.ui;
++}
++
++static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
++{
++ union vfsub_fmu u = {
++ .ui = ui
++ };
++
++ return u.fm;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_sio_rmdir(struct inode *dir, struct path *path);
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
++int vfsub_notify_change(struct path *path, struct iattr *ia);
++int vfsub_unlink(struct inode *dir, struct path *path, int force);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_VFSUB_H__ */
+diff -Naur a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c
+--- a/fs/aufs/wbr_policy.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wbr_policy.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,637 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * policies for selecting one among multiple writable branches
++ */
++
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/* subset of cpup_attr() */
++static noinline_for_stack
++int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
++{
++ int err, sbits;
++ struct iattr ia;
++ struct inode *h_isrc;
++
++ h_isrc = h_src->d_inode;
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
++ ia.ia_mode = h_isrc->i_mode;
++ ia.ia_uid = h_isrc->i_uid;
++ ia.ia_gid = h_isrc->i_gid;
++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
++ err = vfsub_sio_notify_change(h_path, &ia);
++
++ /* is this nfs only? */
++ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++ ia.ia_mode = h_isrc->i_mode;
++ err = vfsub_sio_notify_change(h_path, &ia);
++ }
++
++ return err;
++}
++
++#define AuCpdown_PARENT_OPQ 1
++#define AuCpdown_WHED (1 << 1)
++#define AuCpdown_MADE_DIR (1 << 2)
++#define AuCpdown_DIROPQ (1 << 3)
++#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
++#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
++#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
++
++struct au_cpdown_dir_args {
++ struct dentry *parent;
++ unsigned int flags;
++};
++
++static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
++ struct au_cpdown_dir_args *a)
++{
++ int err;
++ struct dentry *opq_dentry;
++
++ opq_dentry = au_diropq_create(dentry, bdst);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out;
++ dput(opq_dentry);
++ au_fset_cpdown(a->flags, DIROPQ);
++
++ out:
++ return err;
++}
++
++static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
++ struct inode *dir, aufs_bindex_t bdst)
++{
++ int err;
++ struct path h_path;
++ struct au_branch *br;
++
++ br = au_sbr(dentry->d_sb, bdst);
++ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ err = 0;
++ if (h_path.dentry->d_inode) {
++ h_path.mnt = br->br_mnt;
++ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
++ dentry);
++ }
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg)
++{
++ int err, rerr;
++ aufs_bindex_t bend, bopq, bstart;
++ unsigned char parent_opq;
++ struct path h_path;
++ struct dentry *parent;
++ struct inode *h_dir, *h_inode, *inode, *dir;
++ struct au_cpdown_dir_args *args = arg;
++
++ bstart = au_dbstart(dentry);
++ /* dentry is di-locked */
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ h_dir = h_parent->d_inode;
++ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
++ IMustLock(h_dir);
++
++ err = au_lkup_neg(dentry, bdst);
++ if (unlikely(err < 0))
++ goto out;
++ h_path.dentry = au_h_dptr(dentry, bdst);
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
++ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
++ S_IRWXU | S_IRUGO | S_IXUGO);
++ if (unlikely(err))
++ goto out_put;
++ au_fset_cpdown(args->flags, MADE_DIR);
++
++ bend = au_dbend(dentry);
++ bopq = au_dbdiropq(dentry);
++ au_fclr_cpdown(args->flags, WHED);
++ au_fclr_cpdown(args->flags, DIROPQ);
++ if (au_dbwh(dentry) == bdst)
++ au_fset_cpdown(args->flags, WHED);
++ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
++ au_fset_cpdown(args->flags, PARENT_OPQ);
++ parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
++ && args->parent == dentry);
++ h_inode = h_path.dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ if (au_ftest_cpdown(args->flags, WHED)) {
++ err = au_cpdown_dir_opq(dentry, bdst, args);
++ if (unlikely(err)) {
++ mutex_unlock(&h_inode->i_mutex);
++ goto out_dir;
++ }
++ }
++
++ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
++ mutex_unlock(&h_inode->i_mutex);
++ if (unlikely(err))
++ goto out_opq;
++
++ if (au_ftest_cpdown(args->flags, WHED)) {
++ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
++ if (unlikely(err))
++ goto out_opq;
++ }
++
++ inode = dentry->d_inode;
++ if (au_ibend(inode) < bdst)
++ au_set_ibend(inode, bdst);
++ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
++ au_hi_flags(inode, /*isdir*/1));
++ goto out; /* success */
++
++ /* revert */
++ out_opq:
++ if (au_ftest_cpdown(args->flags, DIROPQ)) {
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(dentry, bdst);
++ mutex_unlock(&h_inode->i_mutex);
++ if (unlikely(rerr)) {
++ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
++ AuDLNPair(dentry), bdst, rerr);
++ err = -EIO;
++ goto out;
++ }
++ }
++ out_dir:
++ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
++ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
++ if (unlikely(rerr)) {
++ AuIOErr("failed removing %.*s b%d (%d)\n",
++ AuDLNPair(dentry), bdst, rerr);
++ err = -EIO;
++ }
++ }
++ out_put:
++ au_set_h_dptr(dentry, bdst, NULL);
++ if (au_dbend(dentry) == bdst)
++ au_update_dbend(dentry);
++ out:
++ dput(parent);
++ return err;
++}
++
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ int err;
++ struct au_cpdown_dir_args args = {
++ .parent = dget_parent(dentry),
++ .flags = 0
++ };
++
++ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
++ dput(args.parent);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for create */
++
++static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
++{
++ for (; bindex >= 0; bindex--)
++ if (!au_br_rdonly(au_sbr(sb, bindex)))
++ return bindex;
++ return -EROFS;
++}
++
++/* top down parent */
++static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
++{
++ int err;
++ aufs_bindex_t bstart, bindex;
++ struct super_block *sb;
++ struct dentry *parent, *h_parent;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ err = bstart;
++ if (!au_br_rdonly(au_sbr(sb, bstart)))
++ goto out;
++
++ err = -EROFS;
++ parent = dget_parent(dentry);
++ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = bindex;
++ break;
++ }
++ }
++ dput(parent);
++
++ /* bottom up here */
++ if (unlikely(err < 0))
++ err = au_wbr_bu(sb, bstart - 1);
++
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* an exception for the policy other than tdp */
++static int au_wbr_create_exp(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bwh, bdiropq;
++ struct dentry *parent;
++
++ err = -1;
++ bwh = au_dbwh(dentry);
++ parent = dget_parent(dentry);
++ bdiropq = au_dbdiropq(parent);
++ if (bwh >= 0) {
++ if (bdiropq >= 0)
++ err = min(bdiropq, bwh);
++ else
++ err = bwh;
++ AuDbg("%d\n", err);
++ } else if (bdiropq >= 0) {
++ err = bdiropq;
++ AuDbg("%d\n", err);
++ }
++ dput(parent);
++
++ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
++ err = -1;
++
++ AuDbg("%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* round robin */
++static int au_wbr_create_init_rr(struct super_block *sb)
++{
++ int err;
++
++ err = au_wbr_bu(sb, au_sbend(sb));
++ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_rr(struct dentry *dentry, int isdir)
++{
++ int err, nbr;
++ unsigned int u;
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++ atomic_t *next;
++
++ err = au_wbr_create_exp(dentry);
++ if (err >= 0)
++ goto out;
++
++ sb = dentry->d_sb;
++ next = &au_sbi(sb)->si_wbr_rr_next;
++ bend = au_sbend(sb);
++ nbr = bend + 1;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ if (!isdir) {
++ err = atomic_dec_return(next) + 1;
++ /* modulo for 0 is meaningless */
++ if (unlikely(!err))
++ err = atomic_dec_return(next) + 1;
++ } else
++ err = atomic_read(next);
++ AuDbg("%d\n", err);
++ u = err;
++ err = u % nbr;
++ AuDbg("%d\n", err);
++ if (!au_br_rdonly(au_sbr(sb, err)))
++ break;
++ err = -EROFS;
++ }
++
++ out:
++ AuDbg("%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space */
++static void au_mfs(struct dentry *dentry)
++{
++ struct super_block *sb;
++ struct au_branch *br;
++ struct au_wbr_mfs *mfs;
++ aufs_bindex_t bindex, bend;
++ int err;
++ unsigned long long b, bavail;
++ /* reduce the stack usage */
++ struct kstatfs *st;
++
++ st = kmalloc(sizeof(*st), GFP_NOFS);
++ if (unlikely(!st)) {
++ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
++ return;
++ }
++
++ bavail = 0;
++ sb = dentry->d_sb;
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mfs->mfs_bindex = -EROFS;
++ mfs->mfsrr_bytes = 0;
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (au_br_rdonly(br))
++ continue;
++
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(br->br_mnt->mnt_root, st);
++ if (unlikely(err)) {
++ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
++ continue;
++ }
++
++ /* when the available size is equal, select the lower one */
++ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
++ || sizeof(b) < sizeof(st->f_bsize));
++ b = st->f_bavail * st->f_bsize;
++ br->br_wbr->wbr_bytes = b;
++ if (b >= bavail) {
++ bavail = b;
++ mfs->mfs_bindex = bindex;
++ mfs->mfs_jiffy = jiffies;
++ }
++ }
++
++ mfs->mfsrr_bytes = bavail;
++ AuDbg("b%d\n", mfs->mfs_bindex);
++ kfree(st);
++}
++
++static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
++{
++ int err;
++ struct super_block *sb;
++ struct au_wbr_mfs *mfs;
++
++ err = au_wbr_create_exp(dentry);
++ if (err >= 0)
++ goto out;
++
++ sb = dentry->d_sb;
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mutex_lock(&mfs->mfs_lock);
++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
++ || mfs->mfs_bindex < 0
++ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
++ au_mfs(dentry);
++ mutex_unlock(&mfs->mfs_lock);
++ err = mfs->mfs_bindex;
++
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_init_mfs(struct super_block *sb)
++{
++ struct au_wbr_mfs *mfs;
++
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mutex_init(&mfs->mfs_lock);
++ mfs->mfs_jiffy = 0;
++ mfs->mfs_bindex = -EROFS;
++
++ return 0;
++}
++
++static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
++{
++ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space and then round robin */
++static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
++{
++ int err;
++ struct au_wbr_mfs *mfs;
++
++ err = au_wbr_create_mfs(dentry, isdir);
++ if (err >= 0) {
++ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
++ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
++ err = au_wbr_create_rr(dentry, isdir);
++ }
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_init_mfsrr(struct super_block *sb)
++{
++ int err;
++
++ au_wbr_create_init_mfs(sb); /* ignore */
++ err = au_wbr_create_init_rr(sb);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* top down parent and most free space */
++static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
++{
++ int err, e2;
++ unsigned long long b;
++ aufs_bindex_t bindex, bstart, bend;
++ struct super_block *sb;
++ struct dentry *parent, *h_parent;
++ struct au_branch *br;
++
++ err = au_wbr_create_tdp(dentry, isdir);
++ if (unlikely(err < 0))
++ goto out;
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(parent);
++ bend = au_dbtaildir(parent);
++ if (bstart == bend)
++ goto out_parent; /* success */
++
++ e2 = au_wbr_create_mfs(dentry, isdir);
++ if (e2 < 0)
++ goto out_parent; /* success */
++
++ /* when the available size is equal, select upper one */
++ sb = dentry->d_sb;
++ br = au_sbr(sb, err);
++ b = br->br_wbr->wbr_bytes;
++ AuDbg("b%d, %llu\n", err, b);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ br = au_sbr(sb, bindex);
++ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
++ b = br->br_wbr->wbr_bytes;
++ err = bindex;
++ AuDbg("b%d, %llu\n", err, b);
++ }
++ }
++
++ out_parent:
++ dput(parent);
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for copyup */
++
++/* top down parent */
++static int au_wbr_copyup_tdp(struct dentry *dentry)
++{
++ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
++}
++
++/* bottom up parent */
++static int au_wbr_copyup_bup(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bindex, bstart;
++ struct dentry *parent, *h_parent;
++ struct super_block *sb;
++
++ err = -EROFS;
++ sb = dentry->d_sb;
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(parent);
++ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = bindex;
++ break;
++ }
++ }
++ dput(parent);
++
++ /* bottom up here */
++ if (unlikely(err < 0))
++ err = au_wbr_bu(sb, bstart - 1);
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* bottom up */
++static int au_wbr_copyup_bu(struct dentry *dentry)
++{
++ int err;
++
++ err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
++ [AuWbrCopyup_TDP] = {
++ .copyup = au_wbr_copyup_tdp
++ },
++ [AuWbrCopyup_BUP] = {
++ .copyup = au_wbr_copyup_bup
++ },
++ [AuWbrCopyup_BU] = {
++ .copyup = au_wbr_copyup_bu
++ }
++};
++
++struct au_wbr_create_operations au_wbr_create_ops[] = {
++ [AuWbrCreate_TDP] = {
++ .create = au_wbr_create_tdp
++ },
++ [AuWbrCreate_RR] = {
++ .create = au_wbr_create_rr,
++ .init = au_wbr_create_init_rr
++ },
++ [AuWbrCreate_MFS] = {
++ .create = au_wbr_create_mfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSV] = {
++ .create = au_wbr_create_mfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSRR] = {
++ .create = au_wbr_create_mfsrr,
++ .init = au_wbr_create_init_mfsrr,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSRRV] = {
++ .create = au_wbr_create_mfsrr,
++ .init = au_wbr_create_init_mfsrr,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_PMFS] = {
++ .create = au_wbr_create_pmfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_PMFSV] = {
++ .create = au_wbr_create_pmfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ }
++};
+diff -Naur a/fs/aufs/whout.c b/fs/aufs/whout.c
+--- a/fs/aufs/whout.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1042 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#include <linux/fs.h>
++#include "aufs.h"
++
++#define WH_MASK S_IRUGO
++
++/*
++ * If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++static struct qstr diropq_name = {
++ .name = AUFS_WH_DIROPQ,
++ .len = sizeof(AUFS_WH_DIROPQ) - 1
++};
++
++/*
++ * generate whiteout name, which is NOT terminated by NULL.
++ * @name: original d_name.name
++ * @len: original d_name.len
++ * @wh: whiteout qstr
++ * returns zero when succeeds, otherwise error.
++ * succeeded value as wh->name should be freed by kfree().
++ */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
++{
++ char *p;
++
++ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
++ return -ENAMETOOLONG;
++
++ wh->len = name->len + AUFS_WH_PFX_LEN;
++ p = kmalloc(wh->len, GFP_NOFS);
++ wh->name = p;
++ if (p) {
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
++ /* smp_mb(); */
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the @wh_name exists under @h_parent.
++ * @try_sio specifies the necessary of super-io.
++ */
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++ struct au_branch *br, int try_sio)
++{
++ int err;
++ struct dentry *wh_dentry;
++ struct inode *h_dir;
++
++ h_dir = h_parent->d_inode;
++ if (!try_sio)
++ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
++ else
++ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ err = 0;
++ if (!wh_dentry->d_inode)
++ goto out_wh; /* success */
++
++ err = 1;
++ if (S_ISREG(wh_dentry->d_inode->i_mode))
++ goto out_wh; /* success */
++
++ err = -EIO;
++ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
++ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ return err;
++}
++
++/*
++ * test if the @h_dentry sets opaque or not.
++ */
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct inode *h_dir;
++
++ h_dir = h_dentry->d_inode;
++ err = au_wh_test(h_dentry, &diropq_name, br,
++ au_test_h_perm_sio(h_dir, MAY_EXEC));
++ return err;
++}
++
++/*
++ * returns a negative dentry whose name is unique and temporary.
++ */
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++ struct qstr *prefix)
++{
++#define HEX_LEN 4
++ struct dentry *dentry;
++ int i;
++ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
++ + HEX_LEN + 1], *name, *p;
++ static unsigned short cnt;
++ struct qstr qs;
++
++ name = defname;
++ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
++ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
++ dentry = ERR_PTR(-ENAMETOOLONG);
++ if (unlikely(qs.len >= PATH_MAX))
++ goto out;
++ dentry = ERR_PTR(-ENOMEM);
++ name = kmalloc(qs.len + 1, GFP_NOFS);
++ if (unlikely(!name))
++ goto out;
++ }
++
++ /* doubly whiteout-ed */
++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
++ p = name + AUFS_WH_PFX_LEN * 2;
++ memcpy(p, prefix->name, prefix->len);
++ p += prefix->len;
++ *p++ = '.';
++ AuDebugOn(name + qs.len + 1 - p <= HEX_LEN);
++
++ qs.name = name;
++ for (i = 0; i < 3; i++) {
++ sprintf(p, "%.*d", HEX_LEN, cnt++);
++ dentry = au_sio_lkup_one(&qs, h_parent, br);
++ if (IS_ERR(dentry) || !dentry->d_inode)
++ goto out_name;
++ dput(dentry);
++ }
++ /* AuWarn("could not get random name\n"); */
++ dentry = ERR_PTR(-EEXIST);
++ AuDbg("%.*s\n", AuLNPair(&qs));
++ BUG();
++
++ out_name:
++ if (name != defname)
++ kfree(name);
++ out:
++ return dentry;
++#undef HEX_LEN
++}
++
++/*
++ * rename the @h_dentry on @br to the whiteouted temporary name.
++ */
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++ struct dentry *h_parent;
++
++ h_parent = h_dentry->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ /* under the same dir, no need to lock_rename() */
++ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
++ AuTraceErr(err);
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * functions for removing a whiteout
++ */
++
++static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
++{
++ int force;
++
++ /*
++ * forces superio when the dir has a sticky bit.
++ * this may be a violation of unix fs semantics.
++ */
++ force = (h_dir->i_mode & S_ISVTX)
++ && h_path->dentry->d_inode->i_uid != current_fsuid();
++ return vfsub_unlink(h_dir, h_path, force);
++}
++
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++ struct dentry *dentry)
++{
++ int err;
++
++ err = do_unlink_wh(h_dir, h_path);
++ if (!err && dentry)
++ au_set_dbwh(dentry, -1);
++
++ return err;
++}
++
++static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
++ struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++
++ err = 0;
++ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
++ if (IS_ERR(h_path.dentry))
++ err = PTR_ERR(h_path.dentry);
++ else {
++ if (h_path.dentry->d_inode
++ && S_ISREG(h_path.dentry->d_inode->i_mode))
++ err = do_unlink_wh(h_parent->d_inode, &h_path);
++ dput(h_path.dentry);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * initialize/clean whiteout for a branch
++ */
++
++static void au_wh_clean(struct inode *h_dir, struct path *whpath,
++ const int isdir)
++{
++ int err;
++
++ if (!whpath->dentry->d_inode)
++ return;
++
++ err = mnt_want_write(whpath->mnt);
++ if (!err) {
++ if (isdir)
++ err = vfsub_rmdir(h_dir, whpath);
++ else
++ err = vfsub_unlink(h_dir, whpath, /*force*/0);
++ mnt_drop_write(whpath->mnt);
++ }
++ if (unlikely(err))
++ AuWarn("failed removing %.*s (%d), ignored.\n",
++ AuDLNPair(whpath->dentry), err);
++}
++
++static int test_linkable(struct dentry *h_root)
++{
++ struct inode *h_dir = h_root->d_inode;
++
++ if (h_dir->i_op->link)
++ return 0;
++
++ AuErr("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
++ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++ return -ENOSYS;
++}
++
++/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
++static int au_whdir(struct inode *h_dir, struct path *path)
++{
++ int err;
++
++ err = -EEXIST;
++ if (!path->dentry->d_inode) {
++ int mode = S_IRWXU;
++
++ if (au_test_nfs(path->dentry->d_sb))
++ mode |= S_IXUGO;
++ err = mnt_want_write(path->mnt);
++ if (!err) {
++ err = vfsub_mkdir(h_dir, path, mode);
++ mnt_drop_write(path->mnt);
++ }
++ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
++ err = 0;
++ else
++ AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
++
++ return err;
++}
++
++struct au_wh_base {
++ const struct qstr *name;
++ struct dentry *dentry;
++};
++
++static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
++ struct path *h_path)
++{
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/0);
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++}
++
++/*
++ * returns tri-state,
++ * minus: error, caller should print the mesage
++ * zero: succuess
++ * plus: error, caller should NOT print the mesage
++ */
++static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
++ int do_plink, struct au_wh_base base[],
++ struct path *h_path)
++{
++ int err;
++ struct inode *h_dir;
++
++ h_dir = h_root->d_inode;
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/0);
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ if (do_plink) {
++ err = test_linkable(h_root);
++ if (unlikely(err)) {
++ err = 1;
++ goto out;
++ }
++
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++ } else
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++ return err;
++}
++
++/*
++ * for the moment, aufs supports the branch filesystem which does not support
++ * link(2). testing on FAT which does not support i_op->setattr() fully either,
++ * copyup failed. finally, such filesystem will not be used as the writable
++ * branch.
++ *
++ * returns tri-state, see above.
++ */
++static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
++ int do_plink, struct au_wh_base base[],
++ struct path *h_path)
++{
++ int err;
++ struct inode *h_dir;
++
++ err = test_linkable(h_root);
++ if (unlikely(err)) {
++ err = 1;
++ goto out;
++ }
++
++ /*
++ * todo: should this create be done in /sbin/mount.aufs helper?
++ */
++ err = -EEXIST;
++ h_dir = h_root->d_inode;
++ if (!base[AuBrWh_BASE].dentry->d_inode) {
++ err = mnt_want_write(h_path->mnt);
++ if (!err) {
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ err = vfsub_create(h_dir, h_path, WH_MASK);
++ mnt_drop_write(h_path->mnt);
++ }
++ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
++ err = 0;
++ else
++ AuErr("unknown %.*s/%.*s exists\n",
++ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
++ if (unlikely(err))
++ goto out;
++
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ if (do_plink) {
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++ } else
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
++
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++ return err;
++}
++
++/*
++ * initialize the whiteout base file/dir for @br.
++ */
++int au_wh_init(struct dentry *h_root, struct au_branch *br,
++ struct super_block *sb)
++{
++ int err, i;
++ const unsigned char do_plink
++ = !!au_opt_test(au_mntflags(sb), PLINK);
++ struct path path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++ struct au_wbr *wbr = br->br_wbr;
++ static const struct qstr base_name[] = {
++ [AuBrWh_BASE] = {
++ .name = AUFS_BASE_NAME,
++ .len = sizeof(AUFS_BASE_NAME) - 1
++ },
++ [AuBrWh_PLINK] = {
++ .name = AUFS_PLINKDIR_NAME,
++ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
++ },
++ [AuBrWh_ORPH] = {
++ .name = AUFS_ORPHDIR_NAME,
++ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
++ }
++ };
++ struct au_wh_base base[] = {
++ [AuBrWh_BASE] = {
++ .name = base_name + AuBrWh_BASE,
++ .dentry = NULL
++ },
++ [AuBrWh_PLINK] = {
++ .name = base_name + AuBrWh_PLINK,
++ .dentry = NULL
++ },
++ [AuBrWh_ORPH] = {
++ .name = base_name + AuBrWh_ORPH,
++ .dentry = NULL
++ }
++ };
++
++
++ h_dir = h_root->d_inode;
++ for (i = 0; i < AuBrWh_Last; i++) {
++ /* doubly whiteouted */
++ struct dentry *d;
++
++ d = au_wh_lkup(h_root, (void *)base[i].name, br);
++ err = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out;
++
++ base[i].dentry = d;
++ AuDebugOn(wbr
++ && wbr->wbr_wh[i]
++ && wbr->wbr_wh[i] != base[i].dentry);
++ }
++
++ if (wbr)
++ for (i = 0; i < AuBrWh_Last; i++) {
++ dput(wbr->wbr_wh[i]);
++ wbr->wbr_wh[i] = NULL;
++ }
++
++ err = 0;
++
++ switch (br->br_perm) {
++ case AuBrPerm_RO:
++ case AuBrPerm_ROWH:
++ case AuBrPerm_RR:
++ case AuBrPerm_RRWH:
++ au_wh_init_ro(h_dir, base, &path);
++ break;
++
++ case AuBrPerm_RWNoLinkWH:
++ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
++ if (err > 0)
++ goto out;
++ else if (err)
++ goto out_err;
++ break;
++
++ case AuBrPerm_RW:
++ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
++ if (err > 0)
++ goto out;
++ else if (err)
++ goto out_err;
++ break;
++
++ default:
++ BUG();
++ }
++ goto out; /* success */
++
++ out_err:
++ AuErr("an error(%d) on the writable branch %.*s(%s)\n",
++ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++ out:
++ for (i = 0; i < AuBrWh_Last; i++)
++ dput(base[i].dentry);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * whiteouts are all hard-linked usually.
++ * when its link count reaches a ceiling, we create a new whiteout base
++ * asynchronously.
++ */
++
++struct reinit_br_wh {
++ struct super_block *sb;
++ struct au_branch *br;
++};
++
++static void reinit_br_wh(void *arg)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct path h_path;
++ struct reinit_br_wh *a = arg;
++ struct au_wbr *wbr;
++ struct inode *dir;
++ struct dentry *h_root;
++ struct au_hinode *hdir;
++
++ err = 0;
++ wbr = a->br->br_wbr;
++ /* big aufs lock */
++ si_noflush_write_lock(a->sb);
++ if (!au_br_writable(a->br->br_perm))
++ goto out;
++ bindex = au_br_index(a->sb, a->br->br_id);
++ if (unlikely(bindex < 0))
++ goto out;
++
++ dir = a->sb->s_root->d_inode;
++ /* ii_read_lock_parent(dir); */
++ hdir = au_hi(dir, bindex);
++ h_root = au_h_dptr(a->sb->s_root, bindex);
++
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ wbr_wh_write_lock(wbr);
++ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
++ h_root, a->br);
++ if (!err) {
++ err = mnt_want_write(a->br->br_mnt);
++ if (!err) {
++ h_path.dentry = wbr->wbr_whbase;
++ h_path.mnt = a->br->br_mnt;
++ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
++ mnt_drop_write(a->br->br_mnt);
++ }
++ } else {
++ AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
++ err = 0;
++ }
++ dput(wbr->wbr_whbase);
++ wbr->wbr_whbase = NULL;
++ if (!err)
++ err = au_wh_init(h_root, a->br, a->sb);
++ wbr_wh_write_unlock(wbr);
++ au_hin_imtx_unlock(hdir);
++ /* ii_read_unlock(dir); */
++
++ out:
++ if (wbr)
++ atomic_dec(&wbr->wbr_wh_running);
++ atomic_dec(&a->br->br_count);
++ au_nwt_done(&au_sbi(a->sb)->si_nowait);
++ si_write_unlock(a->sb);
++ kfree(arg);
++ if (unlikely(err))
++ AuIOErr("err %d\n", err);
++}
++
++static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
++{
++ int do_dec, wkq_err;
++ struct reinit_br_wh *arg;
++
++ do_dec = 1;
++ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
++ goto out;
++
++ /* ignore ENOMEM */
++ arg = kmalloc(sizeof(*arg), GFP_NOFS);
++ if (arg) {
++ /*
++ * dec(wh_running), kfree(arg) and dec(br_count)
++ * in reinit function
++ */
++ arg->sb = sb;
++ arg->br = br;
++ atomic_inc(&br->br_count);
++ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
++ if (unlikely(wkq_err)) {
++ atomic_dec(&br->br_wbr->wbr_wh_running);
++ atomic_dec(&br->br_count);
++ kfree(arg);
++ }
++ do_dec = 0;
++ }
++
++ out:
++ if (do_dec)
++ atomic_dec(&br->br_wbr->wbr_wh_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create the whiteout @wh.
++ */
++static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
++ struct dentry *wh)
++{
++ int err;
++ struct path h_path = {
++ .dentry = wh
++ };
++ struct au_branch *br;
++ struct au_wbr *wbr;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++
++ h_parent = wh->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ br = au_sbr(sb, bindex);
++ h_path.mnt = br->br_mnt;
++ wbr = br->br_wbr;
++ wbr_wh_read_lock(wbr);
++ if (wbr->wbr_whbase) {
++ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
++ if (!err || err != -EMLINK)
++ goto out;
++
++ /* link count full. re-initialize br_whbase. */
++ kick_reinit_br_wh(sb, br);
++ }
++
++ /* return this error in this context */
++ err = vfsub_create(h_dir, &h_path, WH_MASK);
++
++ out:
++ wbr_wh_read_unlock(wbr);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create or remove the diropq.
++ */
++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags)
++{
++ struct dentry *opq_dentry, *h_dentry;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++
++ sb = dentry->d_sb;
++ br = au_sbr(sb, bindex);
++ h_dentry = au_h_dptr(dentry, bindex);
++ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
++ if (IS_ERR(opq_dentry))
++ goto out;
++
++ if (au_ftest_diropq(flags, CREATE)) {
++ err = link_or_create_wh(sb, bindex, opq_dentry);
++ if (!err) {
++ au_set_dbdiropq(dentry, bindex);
++ goto out; /* success */
++ }
++ } else {
++ struct path tmp = {
++ .dentry = opq_dentry,
++ .mnt = br->br_mnt
++ };
++ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
++ if (!err)
++ au_set_dbdiropq(dentry, -1);
++ }
++ dput(opq_dentry);
++ opq_dentry = ERR_PTR(err);
++
++ out:
++ return opq_dentry;
++}
++
++struct do_diropq_args {
++ struct dentry **errp;
++ struct dentry *dentry;
++ aufs_bindex_t bindex;
++ unsigned int flags;
++};
++
++static void call_do_diropq(void *args)
++{
++ struct do_diropq_args *a = args;
++ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
++}
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags)
++{
++ struct dentry *diropq, *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
++ diropq = do_diropq(dentry, bindex, flags);
++ else {
++ int wkq_err;
++ struct do_diropq_args args = {
++ .errp = &diropq,
++ .dentry = dentry,
++ .bindex = bindex,
++ .flags = flags
++ };
++
++ wkq_err = au_wkq_wait(call_do_diropq, &args);
++ if (unlikely(wkq_err))
++ diropq = ERR_PTR(wkq_err);
++ }
++
++ return diropq;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * lookup whiteout dentry.
++ * @h_parent: lower parent dentry which must exist and be locked
++ * @base_name: name of dentry which will be whiteouted
++ * returns dentry for whiteout.
++ */
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++ struct au_branch *br)
++{
++ int err;
++ struct qstr wh_name;
++ struct dentry *wh_dentry;
++
++ err = au_wh_name_alloc(&wh_name, base_name);
++ wh_dentry = ERR_PTR(err);
++ if (!err) {
++ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
++ kfree(wh_name.name);
++ }
++ return wh_dentry;
++}
++
++/*
++ * link/create a whiteout for @dentry on @bindex.
++ */
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent)
++{
++ struct dentry *wh_dentry;
++ struct super_block *sb;
++ int err;
++
++ sb = dentry->d_sb;
++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
++ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
++ err = link_or_create_wh(sb, bindex, wh_dentry);
++ if (!err)
++ au_set_dbwh(dentry, bindex);
++ else {
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(err);
++ }
++ }
++
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Delete all whiteouts in this directory on branch bindex. */
++static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
++ aufs_bindex_t bindex, struct au_branch *br)
++{
++ int err;
++ unsigned long ul, n;
++ struct qstr wh_name;
++ char *p;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ err = -ENOMEM;
++ p = __getname();
++ wh_name.name = p;
++ if (unlikely(!wh_name.name))
++ goto out;
++
++ err = 0;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (ul = 0; !err && ul < n; ul++, head++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ if (tpos->wh_bindex != bindex)
++ continue;
++
++ str = &tpos->wh_str;
++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
++ memcpy(p, str->name, str->len);
++ wh_name.len = AUFS_WH_PFX_LEN + str->len;
++ err = unlink_wh_name(h_dentry, &wh_name, br);
++ if (!err)
++ continue;
++ break;
++ }
++ AuIOErr("whiteout name too long %.*s\n",
++ str->len, str->name);
++ err = -EIO;
++ break;
++ }
++ }
++ __putname(wh_name.name);
++
++ out:
++ return err;
++}
++
++struct del_wh_children_args {
++ int *errp;
++ struct dentry *h_dentry;
++ struct au_nhash whlist;
++ aufs_bindex_t bindex;
++ struct au_branch *br;
++};
++
++static void call_del_wh_children(void *args)
++{
++ struct del_wh_children_args *a = args;
++ *a->errp = del_wh_children(a->h_dentry, &a->whlist, a->bindex, a->br);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
++{
++ struct au_whtmp_rmdir *whtmp;
++ int err;
++
++ whtmp = kmalloc(sizeof(*whtmp), gfp);
++ if (unlikely(!whtmp)) {
++ whtmp = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++
++ whtmp->dir = NULL;
++ whtmp->wh_dentry = NULL;
++ err = au_nhash_alloc(&whtmp->whlist, au_sbi(sb)->si_rdhash, gfp);
++ if (!err)
++ return whtmp; /* success */
++
++ kfree(whtmp);
++ whtmp = ERR_PTR(err);
++
++ out:
++ return whtmp;
++}
++
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
++{
++ dput(whtmp->wh_dentry);
++ iput(whtmp->dir);
++ au_nhash_wh_free(&whtmp->whlist);
++ kfree(whtmp);
++}
++
++/*
++ * rmdir the whiteouted temporary named dir @h_dentry.
++ * @whlist: whiteouted children.
++ */
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_nhash *whlist)
++{
++ int err;
++ struct path h_tmp;
++ struct inode *wh_inode, *h_dir;
++ struct au_branch *br;
++
++ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(h_dir);
++
++ br = au_sbr(dir->i_sb, bindex);
++ wh_inode = wh_dentry->d_inode;
++ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
++
++ /*
++ * someone else might change some whiteouts while we were sleeping.
++ * it means this whlist may have an obsoleted entry.
++ */
++ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
++ err = del_wh_children(wh_dentry, whlist, bindex, br);
++ else {
++ int wkq_err;
++ struct del_wh_children_args args = {
++ .errp = &err,
++ .h_dentry = wh_dentry,
++ .whlist = *whlist,
++ .bindex = bindex,
++ .br = br
++ };
++
++ wkq_err = au_wkq_wait(call_del_wh_children, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++ mutex_unlock(&wh_inode->i_mutex);
++
++ if (!err) {
++ h_tmp.dentry = wh_dentry;
++ h_tmp.mnt = br->br_mnt;
++ err = vfsub_rmdir(h_dir, &h_tmp);
++ /* d_drop(h_dentry); */
++ }
++
++ if (!err) {
++ if (au_ibstart(dir) == bindex) {
++ au_cpup_attr_timesizes(dir);
++ drop_nlink(dir);
++ }
++ return 0; /* success */
++ }
++
++ AuWarn("failed removing %.*s(%d), ignored\n",
++ AuDLNPair(wh_dentry), err);
++ return err;
++}
++
++static void call_rmdir_whtmp(void *args)
++{
++ int err;
++ struct au_whtmp_rmdir *a = args;
++ struct super_block *sb;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ struct au_branch *br;
++ struct au_hinode *hdir;
++
++ /* rmdir by nfsd may cause deadlock with this i_mutex */
++ /* mutex_lock(&a->dir->i_mutex); */
++ sb = a->dir->i_sb;
++ si_noflush_read_lock(sb);
++ err = au_test_ro(sb, a->bindex, NULL);
++ if (unlikely(err))
++ goto out;
++
++ err = -EIO;
++ br = au_sbr(sb, a->bindex);
++ ii_write_lock_parent(a->dir);
++ h_parent = dget_parent(a->wh_dentry);
++ h_dir = h_parent->d_inode;
++ hdir = au_hi(a->dir, a->bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
++ if (!err) {
++ err = mnt_want_write(br->br_mnt);
++ if (!err) {
++ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
++ &a->whlist);
++ mnt_drop_write(br->br_mnt);
++ }
++ }
++ au_hin_imtx_unlock(hdir);
++ dput(h_parent);
++ ii_write_unlock(a->dir);
++
++ out:
++ /* mutex_unlock(&a->dir->i_mutex); */
++ au_nwt_done(&au_sbi(sb)->si_nowait);
++ si_read_unlock(sb);
++ au_whtmp_rmdir_free(a);
++ if (unlikely(err))
++ AuIOErr("err %d\n", err);
++}
++
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
++{
++ int wkq_err;
++
++ IMustLock(dir);
++
++ /* all post-process will be done in do_rmdir_whtmp(). */
++ args->dir = au_igrab(dir);
++ args->bindex = bindex;
++ args->wh_dentry = dget(wh_dentry);
++ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
++ if (unlikely(wkq_err)) {
++ AuWarn("rmdir error %.*s (%d), ignored\n",
++ AuDLNPair(wh_dentry), wkq_err);
++ au_whtmp_rmdir_free(args);
++ }
++}
+diff -Naur a/fs/aufs/whout.h b/fs/aufs/whout.h
+--- a/fs/aufs/whout.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#ifndef __AUFS_WHOUT_H__
++#define __AUFS_WHOUT_H__
++
++#ifdef __KERNEL__
++
++#include <linux/aufs_type.h>
++#include "dir.h"
++
++/* whout.c */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
++struct au_branch;
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++ struct au_branch *br, int try_sio);
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++ struct qstr *prefix);
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++ struct dentry *dentry);
++int au_wh_init(struct dentry *h_parent, struct au_branch *br,
++ struct super_block *sb);
++
++/* diropq flags */
++#define AuDiropq_CREATE 1
++#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
++#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
++#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags);
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++ struct au_branch *br);
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent);
++
++/* real rmdir for the whiteout-ed dir */
++struct au_whtmp_rmdir {
++ struct inode *dir;
++ aufs_bindex_t bindex;
++ struct dentry *wh_dentry;
++ struct au_nhash whlist;
++};
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_nhash *whlist);
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_diropq_create(struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
++}
++
++static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WHOUT_H__ */
+diff -Naur a/fs/aufs/wkq.c b/fs/aufs/wkq.c
+--- a/fs/aufs/wkq.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,259 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new dredential scheme
++ */
++
++#include <linux/module.h>
++#include "aufs.h"
++
++/* internal workqueue named AUFS_WKQ_NAME */
++static struct au_wkq {
++ struct workqueue_struct *q;
++
++ /* balancing */
++ atomic_t busy;
++} *au_wkq;
++
++struct au_wkinfo {
++ struct work_struct wk;
++ struct super_block *sb;
++
++ unsigned int flags; /* see wkq.h */
++
++ au_wkq_func_t func;
++ void *args;
++
++ atomic_t *busyp;
++ struct completion *comp;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++ wkinfo->busyp = &wkq->busy;
++ if (au_ftest_wkq(wkinfo->flags, WAIT))
++ return !queue_work(wkq->q, &wkinfo->wk);
++ else
++ return !schedule_work(&wkinfo->wk);
++}
++
++static void do_wkq(struct au_wkinfo *wkinfo)
++{
++ unsigned int idle, n;
++ int i, idle_idx;
++
++ while (1) {
++ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
++ idle_idx = 0;
++ idle = UINT_MAX;
++ for (i = 0; i < aufs_nwkq; i++) {
++ n = atomic_inc_return(&au_wkq[i].busy);
++ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
++ return; /* success */
++
++ if (n < idle) {
++ idle_idx = i;
++ idle = n;
++ }
++ atomic_dec(&au_wkq[i].busy);
++ }
++ } else
++ idle_idx = aufs_nwkq;
++
++ atomic_inc(&au_wkq[idle_idx].busy);
++ if (!enqueue(au_wkq + idle_idx, wkinfo))
++ return; /* success */
++
++ /* impossible? */
++ AuWarn1("failed to queue_work()\n");
++ yield();
++ }
++}
++
++static void wkq_func(struct work_struct *wk)
++{
++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
++
++ wkinfo->func(wkinfo->args);
++ atomic_dec(wkinfo->busyp);
++ if (au_ftest_wkq(wkinfo->flags, WAIT))
++ complete(wkinfo->comp);
++ else {
++ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
++ module_put(THIS_MODULE);
++ kfree(wkinfo);
++ }
++}
++
++/*
++ * Since struct completion is large, try allocating it dynamically.
++ */
++#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
++#define AuWkqCompDeclare(name) struct completion *comp = NULL
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
++ if (*comp) {
++ init_completion(*comp);
++ wkinfo->comp = *comp;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++static void au_wkq_comp_free(struct completion *comp)
++{
++ kfree(comp);
++}
++
++#else
++
++/* no braces */
++#define AuWkqCompDeclare(name) \
++ DECLARE_COMPLETION_ONSTACK(_ ## name); \
++ struct completion *comp = &_ ## name
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++ wkinfo->comp = *comp;
++ return 0;
++}
++
++static void au_wkq_comp_free(struct completion *comp __maybe_unused)
++{
++ /* empty */
++}
++#endif /* 4KSTACKS */
++
++static void au_wkq_run(struct au_wkinfo *wkinfo)
++{
++ au_dbg_verify_kthread();
++ INIT_WORK(&wkinfo->wk, wkq_func);
++ do_wkq(wkinfo);
++}
++
++int au_wkq_wait(au_wkq_func_t func, void *args)
++{
++ int err;
++ AuWkqCompDeclare(comp);
++ struct au_wkinfo wkinfo = {
++ .flags = AuWkq_WAIT,
++ .func = func,
++ .args = args
++ };
++
++ err = au_wkq_comp_alloc(&wkinfo, &comp);
++ if (!err) {
++ au_wkq_run(&wkinfo);
++ /* no timeout, no interrupt */
++ wait_for_completion(wkinfo.comp);
++ au_wkq_comp_free(comp);
++ }
++
++ return err;
++
++}
++
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
++{
++ int err;
++ struct au_wkinfo *wkinfo;
++
++ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
++
++ /*
++ * wkq_func() must free this wkinfo.
++ * it highly depends upon the implementation of workqueue.
++ */
++ err = 0;
++ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
++ if (wkinfo) {
++ wkinfo->sb = sb;
++ wkinfo->flags = !AuWkq_WAIT;
++ wkinfo->func = func;
++ wkinfo->args = args;
++ wkinfo->comp = NULL;
++ kobject_get(&au_sbi(sb)->si_kobj);
++ __module_get(THIS_MODULE);
++
++ au_wkq_run(wkinfo);
++ } else {
++ err = -ENOMEM;
++ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_nwt_init(struct au_nowait_tasks *nwt)
++{
++ atomic_set(&nwt->nw_len, 0);
++ /* smp_mb();*/ /* atomic_set */
++ init_waitqueue_head(&nwt->nw_wq);
++}
++
++void au_wkq_fin(void)
++{
++ int i;
++
++ for (i = 0; i < aufs_nwkq; i++)
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
++ destroy_workqueue(au_wkq[i].q);
++ kfree(au_wkq);
++}
++
++int __init au_wkq_init(void)
++{
++ int err, i;
++ struct au_wkq *nowaitq;
++
++ /* '+1' is for accounting of nowait queue */
++ err = -ENOMEM;
++ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
++ if (unlikely(!au_wkq))
++ goto out;
++
++ err = 0;
++ for (i = 0; i < aufs_nwkq; i++) {
++ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
++ atomic_set(&au_wkq[i].busy, 0);
++ continue;
++ }
++
++ err = PTR_ERR(au_wkq[i].q);
++ au_wkq_fin();
++ goto out;
++ }
++
++ /* nowait accounting */
++ nowaitq = au_wkq + aufs_nwkq;
++ atomic_set(&nowaitq->busy, 0);
++ nowaitq->q = NULL;
++ /* smp_mb(); */ /* atomic_set */
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/wkq.h b/fs/aufs/wkq.h
+--- a/fs/aufs/wkq.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new credentials management scheme
++ */
++
++#ifndef __AUFS_WKQ_H__
++#define __AUFS_WKQ_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
++ */
++struct au_nowait_tasks {
++ atomic_t nw_len;
++ wait_queue_head_t nw_wq;
++};
++
++/* ---------------------------------------------------------------------- */
++
++typedef void (*au_wkq_func_t)(void *args);
++
++/* wkq flags */
++#define AuWkq_WAIT 1
++#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
++#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
++#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
++
++/* wkq.c */
++int au_wkq_wait(au_wkq_func_t func, void *args);
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
++void au_nwt_init(struct au_nowait_tasks *nwt);
++int __init au_wkq_init(void);
++void au_wkq_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_test_wkq(struct task_struct *tsk)
++{
++ return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
++}
++
++static inline void au_nwt_done(struct au_nowait_tasks *nwt)
++{
++ if (!atomic_dec_return(&nwt->nw_len))
++ wake_up_all(&nwt->nw_wq);
++}
++
++static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
++{
++ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
++ return 0;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WKQ_H__ */
+diff -Naur a/fs/aufs/xino.c b/fs/aufs/xino.c
+--- a/fs/aufs/xino.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/xino.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1191 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * external inode number translation table and bitmap
++ */
++
++#include <linux/file.h>
++#include <linux/seq_file.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ /* todo: signal_pending? */
++ err = func(file, (char __user *)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++ if (err > 0)
++ fsnotify_access(file->f_dentry);
++#endif
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ lockdep_off();
++ do {
++ /* todo: signal_pending? */
++ err = func(file, (const char __user *)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ lockdep_on();
++ set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++ if (err > 0)
++ fsnotify_modify(file->f_dentry);
++#endif
++
++ return err;
++}
++
++struct do_xino_fwrite_args {
++ ssize_t *errp;
++ au_writef_t func;
++ struct file *file;
++ void *buf;
++ size_t size;
++ loff_t *pos;
++};
++
++static void call_do_xino_fwrite(void *args)
++{
++ struct do_xino_fwrite_args *a = args;
++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
++}
++
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos)
++{
++ ssize_t err;
++
++ /* todo: signal block and no wkq? */
++ /* todo: new credential scheme */
++ /*
++ * it breaks RLIMIT_FSIZE and normal user's limit,
++ * users should care about quota and real 'filesystem full.'
++ */
++ if (!au_test_wkq(current)) {
++ int wkq_err;
++ struct do_xino_fwrite_args args = {
++ .errp = &err,
++ .func = func,
++ .file = file,
++ .buf = buf,
++ .size = size,
++ .pos = pos
++ };
++
++ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ } else
++ err = do_xino_fwrite(func, file, buf, size, pos);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a new xinofile at the same place/path as @base_file.
++ */
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
++{
++ struct file *file;
++ struct dentry *base, *dentry, *parent;
++ struct inode *dir;
++ struct qstr *name;
++ int err;
++
++ base = base_file->f_dentry;
++ parent = base->d_parent; /* dir inode is locked */
++ dir = parent->d_inode;
++ IMustLock(dir);
++
++ file = ERR_PTR(-EINVAL);
++ name = &base->d_name;
++ dentry = vfsub_lookup_one_len(name->name, parent, name->len);
++ if (IS_ERR(dentry)) {
++ file = (void *)dentry;
++ AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
++ goto out;
++ }
++
++ /* no need to mnt_want_write() since we call dentry_open() later */
++ err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
++ if (unlikely(err)) {
++ file = ERR_PTR(err);
++ AuErr("%.*s create err %d\n", AuLNPair(name), err);
++ goto out_dput;
++ }
++
++ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ current_cred());
++ if (IS_ERR(file)) {
++ AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
++ goto out_dput;
++ }
++
++ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
++ if (unlikely(err)) {
++ AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
++ goto out_fput;
++ }
++
++ if (copy_src) {
++ /* no one can touch copy_src xino */
++ err = au_copy_file(file, copy_src,
++ i_size_read(copy_src->f_dentry->d_inode));
++ if (unlikely(err)) {
++ AuErr("%.*s copy err %d\n", AuLNPair(name), err);
++ goto out_fput;
++ }
++ }
++ goto out_dput; /* success */
++
++ out_fput:
++ fput(file);
++ file = ERR_PTR(err);
++ out_dput:
++ dput(dentry);
++ out:
++ return file;
++}
++
++struct au_xino_lock_dir {
++ struct au_hinode *hdir;
++ struct dentry *parent;
++ struct mutex *mtx;
++};
++
++static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
++ struct au_xino_lock_dir *ldir)
++{
++ aufs_bindex_t brid, bindex;
++
++ ldir->hdir = NULL;
++ bindex = -1;
++ brid = au_xino_brid(sb);
++ if (brid >= 0)
++ bindex = au_br_index(sb, brid);
++ if (bindex >= 0) {
++ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
++ au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
++ } else {
++ ldir->parent = dget_parent(xino->f_dentry);
++ ldir->mtx = &ldir->parent->d_inode->i_mutex;
++ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
++ }
++}
++
++static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
++{
++ if (ldir->hdir)
++ au_hin_imtx_unlock(ldir->hdir);
++ else {
++ mutex_unlock(ldir->mtx);
++ dput(ldir->parent);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate xino files asynchronously */
++
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ aufs_bindex_t bi, bend;
++ struct au_branch *br;
++ struct file *new_xino, *file;
++ struct super_block *h_sb;
++ struct au_xino_lock_dir ldir;
++
++ err = -EINVAL;
++ bend = au_sbend(sb);
++ if (unlikely(bindex < 0 || bend < bindex))
++ goto out;
++ br = au_sbr(sb, bindex);
++ file = br->br_xino.xi_file;
++ if (!file)
++ goto out;
++
++ au_xino_lock_dir(sb, file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ new_xino = au_xino_create2(file, file);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(new_xino);
++ if (IS_ERR(new_xino))
++ goto out;
++ err = 0;
++ fput(file);
++ br->br_xino.xi_file = new_xino;
++
++ h_sb = br->br_mnt->mnt_sb;
++ for (bi = 0; bi <= bend; bi++) {
++ if (unlikely(bi == bindex))
++ continue;
++ br = au_sbr(sb, bi);
++ if (br->br_mnt->mnt_sb != h_sb)
++ continue;
++
++ fput(br->br_xino.xi_file);
++ br->br_xino.xi_file = new_xino;
++ get_file(new_xino);
++ }
++
++ out:
++ return err;
++}
++
++struct xino_do_trunc_args {
++ struct super_block *sb;
++ struct au_branch *br;
++};
++
++static void xino_do_trunc(void *_args)
++{
++ struct xino_do_trunc_args *args = _args;
++ struct super_block *sb;
++ struct au_branch *br;
++ struct inode *dir;
++ int err;
++ aufs_bindex_t bindex;
++
++ err = 0;
++ sb = args->sb;
++ dir = sb->s_root->d_inode;
++ br = args->br;
++
++ si_noflush_write_lock(sb);
++ ii_read_lock_parent(dir);
++ bindex = au_br_index(sb, br->br_id);
++ err = au_xino_trunc(sb, bindex);
++ if (unlikely(err))
++ goto out;
++
++ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++ >= br->br_xino_upper)
++ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
++
++ out:
++ ii_read_unlock(dir);
++ if (unlikely(err))
++ AuWarn("err b%d, (%d)\n", bindex, err);
++ atomic_dec(&br->br_xino_running);
++ atomic_dec(&br->br_count);
++ au_nwt_done(&au_sbi(sb)->si_nowait);
++ si_write_unlock(sb);
++ kfree(args);
++}
++
++static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
++{
++ struct xino_do_trunc_args *args;
++ int wkq_err;
++
++ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++ < br->br_xino_upper)
++ return;
++
++ if (atomic_inc_return(&br->br_xino_running) > 1)
++ goto out;
++
++ /* lock and kfree() will be called in trunc_xino() */
++ args = kmalloc(sizeof(*args), GFP_NOFS);
++ if (unlikely(!args)) {
++ AuErr1("no memory\n");
++ goto out_args;
++ }
++
++ atomic_inc(&br->br_count);
++ args->sb = sb;
++ args->br = br;
++ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
++ if (!wkq_err)
++ return; /* success */
++
++ AuErr("wkq %d\n", wkq_err);
++ atomic_dec(&br->br_count);
++
++ out_args:
++ kfree(args);
++ out:
++ atomic_dec(&br->br_xino_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_xino_do_write(au_writef_t write, struct file *file,
++ ino_t h_ino, ino_t ino)
++{
++ loff_t pos;
++ ssize_t sz;
++
++ pos = h_ino;
++ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
++ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++ return -EFBIG;
++ }
++ pos *= sizeof(ino);
++ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
++ if (sz == sizeof(ino))
++ return 0; /* success */
++
++ AuIOErr("write failed (%zd)\n", sz);
++ return -EIO;
++}
++
++/*
++ * write @ino to the xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * even if @ino is zero, it is written to the xinofile and means no entry.
++ * if the size of the xino file on a specific filesystem exceeds the watermark,
++ * try truncating it.
++ */
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino)
++{
++ int err;
++ unsigned int mnt_flags;
++ struct au_branch *br;
++
++ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
++ || ((loff_t)-1) > 0);
++
++ mnt_flags = au_mntflags(sb);
++ if (!au_opt_test(mnt_flags, XINO))
++ return 0;
++
++ br = au_sbr(sb, bindex);
++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++ h_ino, ino);
++ if (!err) {
++ if (au_opt_test(mnt_flags, TRUNC_XINO)
++ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
++ xino_try_trunc(sb, br);
++ return 0; /* success */
++ }
++
++ AuIOErr("write failed (%d)\n", err);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* aufs inode number bitmap */
++
++static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
++static ino_t xib_calc_ino(unsigned long pindex, int bit)
++{
++ ino_t ino;
++
++ AuDebugOn(bit < 0 || page_bits <= bit);
++ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
++ return ino;
++}
++
++static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
++{
++ AuDebugOn(ino < AUFS_FIRST_INO);
++ ino -= AUFS_FIRST_INO;
++ *pindex = ino / page_bits;
++ *bit = ino % page_bits;
++}
++
++static int xib_pindex(struct super_block *sb, unsigned long pindex)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ struct au_sbinfo *sbinfo;
++ struct file *xib;
++ unsigned long *p;
++
++ sbinfo = au_sbi(sb);
++ MtxMustLock(&sbinfo->si_xib_mtx);
++ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
++ || !au_opt_test(sbinfo->si_mntflags, XINO));
++
++ if (pindex == sbinfo->si_xib_last_pindex)
++ return 0;
++
++ xib = sbinfo->si_xib;
++ p = sbinfo->si_xib_buf;
++ pos = sbinfo->si_xib_last_pindex;
++ pos *= PAGE_SIZE;
++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ if (unlikely(sz != PAGE_SIZE))
++ goto out;
++
++ pos = pindex;
++ pos *= PAGE_SIZE;
++ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
++ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
++ else {
++ memset(p, 0, PAGE_SIZE);
++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ }
++ if (sz == PAGE_SIZE) {
++ sbinfo->si_xib_last_pindex = pindex;
++ return 0; /* success */
++ }
++
++ out:
++ AuIOErr1("write failed (%zd)\n", sz);
++ err = sz;
++ if (sz >= 0)
++ err = -EIO;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino)
++{
++ int err, bit;
++ unsigned long pindex;
++ struct au_sbinfo *sbinfo;
++
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return 0;
++
++ err = 0;
++ if (ino) {
++ sbinfo = au_sbi(sb);
++ xib_calc_bit(ino, &pindex, &bit);
++ AuDebugOn(page_bits <= bit);
++ mutex_lock(&sbinfo->si_xib_mtx);
++ err = xib_pindex(sb, pindex);
++ if (!err) {
++ clear_bit(bit, sbinfo->si_xib_buf);
++ sbinfo->si_xib_next_bit = bit;
++ }
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ }
++
++ if (!err)
++ err = au_xino_write(sb, bindex, h_ino, 0);
++ return err;
++}
++
++/* get an unused inode number from bitmap */
++ino_t au_xino_new_ino(struct super_block *sb)
++{
++ ino_t ino;
++ unsigned long *p, pindex, ul, pend;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++ int free_bit, err;
++
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return iunique(sb, AUFS_FIRST_INO);
++
++ sbinfo = au_sbi(sb);
++ mutex_lock(&sbinfo->si_xib_mtx);
++ p = sbinfo->si_xib_buf;
++ free_bit = sbinfo->si_xib_next_bit;
++ if (free_bit < page_bits && !test_bit(free_bit, p))
++ goto out; /* success */
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++
++ pindex = sbinfo->si_xib_last_pindex;
++ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
++ err = xib_pindex(sb, ul);
++ if (unlikely(err))
++ goto out_err;
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++ }
++
++ file = sbinfo->si_xib;
++ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
++ for (ul = pindex + 1; ul <= pend; ul++) {
++ err = xib_pindex(sb, ul);
++ if (unlikely(err))
++ goto out_err;
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++ }
++ BUG();
++
++ out:
++ set_bit(free_bit, p);
++ sbinfo->si_xib_next_bit++;
++ pindex = sbinfo->si_xib_last_pindex;
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ ino = xib_calc_ino(pindex, free_bit);
++ AuDbg("i%lu\n", (unsigned long)ino);
++ return ino;
++ out_err:
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ AuDbg("i0\n");
++ return 0;
++}
++
++/*
++ * read @ino from xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * if @ino does not exist and @do_new is true, get new one.
++ */
++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t *ino)
++{
++ int err;
++ ssize_t sz;
++ loff_t pos;
++ struct file *file;
++ struct au_sbinfo *sbinfo;
++
++ *ino = 0;
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return 0; /* no xino */
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ pos = h_ino;
++ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
++ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++ return -EFBIG;
++ }
++ pos *= sizeof(*ino);
++
++ file = au_sbr(sb, bindex)->br_xino.xi_file;
++ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
++ return 0; /* no ino */
++
++ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
++ if (sz == sizeof(*ino))
++ return 0; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xino read error (%zd)\n", sz);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* create and set a new xino file */
++
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
++{
++ struct file *file;
++ struct dentry *h_parent, *d;
++ struct inode *h_dir;
++ int err;
++
++ /*
++ * at mount-time, and the xino file is the default path,
++ * hinotify is disabled so we have no inotify events to ignore.
++ * when a user specified the xino, we cannot get au_hdir to be ignored.
++ */
++ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ S_IRUGO | S_IWUGO);
++ if (IS_ERR(file)) {
++ if (!silent)
++ AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
++ return file;
++ }
++
++ /* keep file count */
++ h_parent = dget_parent(file->f_dentry);
++ h_dir = h_parent->d_inode;
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ /* mnt_want_write() is unnecessary here */
++ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
++ mutex_unlock(&h_dir->i_mutex);
++ dput(h_parent);
++ if (unlikely(err)) {
++ if (!silent)
++ AuErr("unlink %s(%d)\n", fname, err);
++ goto out;
++ }
++
++ err = -EINVAL;
++ d = file->f_dentry;
++ if (unlikely(sb == d->d_sb)) {
++ if (!silent)
++ AuErr("%s must be outside\n", fname);
++ goto out;
++ }
++ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
++ if (!silent)
++ AuErr("xino doesn't support %s(%s)\n",
++ fname, au_sbtype(d->d_sb));
++ goto out;
++ }
++ return file; /* success */
++
++ out:
++ fput(file);
++ file = ERR_PTR(err);
++ return file;
++}
++
++/*
++ * find another branch who is on the same filesystem of the specified
++ * branch{@btgt}. search until @bend.
++ */
++static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
++ aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
++
++ for (bindex = 0; bindex < btgt; bindex++)
++ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++ return bindex;
++ for (bindex++; bindex <= bend; bindex++)
++ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * initialize the xinofile for the specified branch @br
++ * at the place/path where @base_file indicates.
++ * test whether another branch is on the same filesystem or not,
++ * if @do_test is true.
++ */
++int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
++ struct file *base_file, int do_test)
++{
++ int err;
++ ino_t ino;
++ aufs_bindex_t bend, bindex;
++ struct au_branch *shared_br, *b;
++ struct file *file;
++ struct super_block *tgt_sb;
++
++ shared_br = NULL;
++ bend = au_sbend(sb);
++ if (do_test) {
++ tgt_sb = br->br_mnt->mnt_sb;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ b = au_sbr(sb, bindex);
++ if (tgt_sb == b->br_mnt->mnt_sb) {
++ shared_br = b;
++ break;
++ }
++ }
++ }
++
++ if (!shared_br || !shared_br->br_xino.xi_file) {
++ struct au_xino_lock_dir ldir;
++
++ au_xino_lock_dir(sb, base_file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ file = au_xino_create2(base_file, NULL);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ br->br_xino.xi_file = file;
++ } else {
++ br->br_xino.xi_file = shared_br->br_xino.xi_file;
++ get_file(br->br_xino.xi_file);
++ }
++
++ ino = AUFS_ROOT_INO;
++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++ h_ino, ino);
++ if (!err)
++ return 0; /* success */
++
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate a xino bitmap file */
++
++/* todo: slow */
++static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
++{
++ int err, bit;
++ ssize_t sz;
++ unsigned long pindex;
++ loff_t pos, pend;
++ struct au_sbinfo *sbinfo;
++ au_readf_t func;
++ ino_t *ino;
++ unsigned long *p;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ p = sbinfo->si_xib_buf;
++ func = sbinfo->si_xread;
++ pend = i_size_read(file->f_dentry->d_inode);
++ pos = 0;
++ while (pos < pend) {
++ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
++ err = sz;
++ if (unlikely(sz <= 0))
++ goto out;
++
++ err = 0;
++ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
++ if (unlikely(*ino < AUFS_FIRST_INO))
++ continue;
++
++ xib_calc_bit(*ino, &pindex, &bit);
++ AuDebugOn(page_bits <= bit);
++ err = xib_pindex(sb, pindex);
++ if (!err)
++ set_bit(bit, p);
++ else
++ goto out;
++ }
++ }
++
++ out:
++ return err;
++}
++
++static int xib_restore(struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ void *page;
++
++ err = -ENOMEM;
++ page = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!page))
++ goto out;
++
++ err = 0;
++ bend = au_sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++)
++ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
++ err = do_xib_restore
++ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
++ else
++ AuDbg("b%d\n", bindex);
++ free_page((unsigned long)page);
++
++ out:
++ return err;
++}
++
++int au_xib_trunc(struct super_block *sb)
++{
++ int err;
++ ssize_t sz;
++ loff_t pos;
++ struct au_xino_lock_dir ldir;
++ struct au_sbinfo *sbinfo;
++ unsigned long *p;
++ struct file *file;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ if (!au_opt_test(sbinfo->si_mntflags, XINO))
++ goto out;
++
++ file = sbinfo->si_xib;
++ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
++ goto out;
++
++ au_xino_lock_dir(sb, file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ file = au_xino_create2(sbinfo->si_xib, NULL);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = file;
++
++ p = sbinfo->si_xib_buf;
++ memset(p, 0, PAGE_SIZE);
++ pos = 0;
++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
++ if (unlikely(sz != PAGE_SIZE)) {
++ err = sz;
++ AuIOErr("err %d\n", err);
++ if (sz >= 0)
++ err = -EIO;
++ goto out;
++ }
++
++ mutex_lock(&sbinfo->si_xib_mtx);
++ /* mnt_want_write() is unnecessary here */
++ err = xib_restore(sb);
++ mutex_unlock(&sbinfo->si_xib_mtx);
++
++out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * xino mount option handlers
++ */
++static au_readf_t find_readf(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->read)
++ return fop->read;
++ if (fop->aio_read)
++ return do_sync_read;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++static au_writef_t find_writef(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->write)
++ return fop->write;
++ if (fop->aio_write)
++ return do_sync_write;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++/* xino bitmap */
++static void xino_clear_xib(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ if (sbinfo->si_xib)
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = NULL;
++ free_page((unsigned long)sbinfo->si_xib_buf);
++ sbinfo->si_xib_buf = NULL;
++}
++
++static int au_xino_set_xib(struct super_block *sb, struct file *base)
++{
++ int err;
++ loff_t pos;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ sbinfo = au_sbi(sb);
++ file = au_xino_create2(base, sbinfo->si_xib);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ if (sbinfo->si_xib)
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = file;
++ sbinfo->si_xread = find_readf(file);
++ sbinfo->si_xwrite = find_writef(file);
++
++ err = -ENOMEM;
++ if (!sbinfo->si_xib_buf)
++ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
++ if (unlikely(!sbinfo->si_xib_buf))
++ goto out_unset;
++
++ sbinfo->si_xib_last_pindex = 0;
++ sbinfo->si_xib_next_bit = 0;
++ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
++ pos = 0;
++ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
++ PAGE_SIZE, &pos);
++ if (unlikely(err != PAGE_SIZE))
++ goto out_free;
++ }
++ err = 0;
++ goto out; /* success */
++
++ out_free:
++ free_page((unsigned long)sbinfo->si_xib_buf);
++ sbinfo->si_xib_buf = NULL;
++ if (err >= 0)
++ err = -EIO;
++ out_unset:
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = NULL;
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ out:
++ return err;
++}
++
++/* xino for each branch */
++static void xino_clear_br(struct super_block *sb)
++{
++ aufs_bindex_t bindex, bend;
++ struct au_branch *br;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (!br || !br->br_xino.xi_file)
++ continue;
++
++ fput(br->br_xino.xi_file);
++ br->br_xino.xi_file = NULL;
++ }
++}
++
++static int au_xino_set_br(struct super_block *sb, struct file *base)
++{
++ int err;
++ ino_t ino;
++ aufs_bindex_t bindex, bend, bshared;
++ struct {
++ struct file *old, *new;
++ } *fpair, *p;
++ struct au_branch *br;
++ struct inode *inode;
++ au_writef_t writef;
++
++ err = -ENOMEM;
++ bend = au_sbend(sb);
++ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
++ if (unlikely(!fpair))
++ goto out;
++
++ inode = sb->s_root->d_inode;
++ ino = AUFS_ROOT_INO;
++ writef = au_sbi(sb)->si_xwrite;
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++ br = au_sbr(sb, bindex);
++ bshared = is_sb_shared(sb, bindex, bindex - 1);
++ if (bshared >= 0) {
++ /* shared xino */
++ *p = fpair[bshared];
++ get_file(p->new);
++ }
++
++ if (!p->new) {
++ /* new xino */
++ p->old = br->br_xino.xi_file;
++ p->new = au_xino_create2(base, br->br_xino.xi_file);
++ err = PTR_ERR(p->new);
++ if (IS_ERR(p->new)) {
++ p->new = NULL;
++ goto out_pair;
++ }
++ }
++
++ err = au_xino_do_write(writef, p->new,
++ au_h_iptr(inode, bindex)->i_ino, ino);
++ if (unlikely(err))
++ goto out_pair;
++ }
++
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++ br = au_sbr(sb, bindex);
++ if (br->br_xino.xi_file)
++ fput(br->br_xino.xi_file);
++ get_file(p->new);
++ br->br_xino.xi_file = p->new;
++ }
++
++ out_pair:
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
++ if (p->new)
++ fput(p->new);
++ else
++ break;
++ kfree(fpair);
++ out:
++ return err;
++}
++
++void au_xino_clr(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ au_xigen_clr(sb);
++ xino_clear_xib(sb);
++ xino_clear_br(sb);
++ sbinfo = au_sbi(sb);
++ /* lvalue, do not call au_mntflags() */
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++}
++
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
++{
++ int err, skip;
++ struct dentry *parent, *cur_parent;
++ struct qstr *dname, *cur_name;
++ struct file *cur_xino;
++ struct inode *dir;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ parent = dget_parent(xino->file->f_dentry);
++ if (remount) {
++ skip = 0;
++ dname = &xino->file->f_dentry->d_name;
++ cur_xino = sbinfo->si_xib;
++ if (cur_xino) {
++ cur_parent = dget_parent(cur_xino->f_dentry);
++ cur_name = &cur_xino->f_dentry->d_name;
++ skip = (cur_parent == parent
++ && dname->len == cur_name->len
++ && !memcmp(dname->name, cur_name->name,
++ dname->len));
++ dput(cur_parent);
++ }
++ if (skip)
++ goto out;
++ }
++
++ au_opt_set(sbinfo->si_mntflags, XINO);
++ dir = parent->d_inode;
++ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
++ /* mnt_want_write() is unnecessary here */
++ err = au_xino_set_xib(sb, xino->file);
++ if (!err)
++ err = au_xigen_set(sb, xino->file);
++ if (!err)
++ err = au_xino_set_br(sb, xino->file);
++ mutex_unlock(&dir->i_mutex);
++ if (!err)
++ goto out; /* success */
++
++ /* reset all */
++ AuIOErr("failed creating xino(%d).\n", err);
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a xinofile at the default place/path.
++ */
++struct file *au_xino_def(struct super_block *sb)
++{
++ struct file *file;
++ char *page, *p;
++ struct au_branch *br;
++ struct super_block *h_sb;
++ struct path path;
++ aufs_bindex_t bend, bindex, bwr;
++
++ br = NULL;
++ bend = au_sbend(sb);
++ bwr = -1;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (au_br_writable(br->br_perm)
++ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
++ bwr = bindex;
++ break;
++ }
++ }
++
++ if (bwr >= 0) {
++ file = ERR_PTR(-ENOMEM);
++ page = __getname();
++ if (unlikely(!page))
++ goto out;
++ path.mnt = br->br_mnt;
++ path.dentry = au_h_dptr(sb->s_root, bwr);
++ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
++ file = (void *)p;
++ if (!IS_ERR(p)) {
++ strcat(p, "/" AUFS_XINO_FNAME);
++ AuDbg("%s\n", p);
++ file = au_xino_create(sb, p, /*silent*/0);
++ if (!IS_ERR(file))
++ au_xino_brid_set(sb, br->br_id);
++ }
++ __putname(page);
++ } else {
++ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
++ if (IS_ERR(file))
++ goto out;
++ h_sb = file->f_dentry->d_sb;
++ if (unlikely(au_test_fs_bad_xino(h_sb))) {
++ AuErr("xino doesn't support %s(%s)\n",
++ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
++ fput(file);
++ file = ERR_PTR(-EINVAL);
++ }
++ if (!IS_ERR(file))
++ au_xino_brid_set(sb, -1);
++ }
++
++ out:
++ return file;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_path(struct seq_file *seq, struct file *file)
++{
++ int err;
++
++ err = au_seq_path(seq, &file->f_path);
++ if (unlikely(err < 0))
++ goto out;
++
++ err = 0;
++#define Deleted "\\040(deleted)"
++ seq->count -= sizeof(Deleted) - 1;
++ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
++ sizeof(Deleted) - 1));
++#undef Deleted
++
++ out:
++ return err;
++}
+diff -Naur a/include/linux/aufs_type.h b/include/linux/aufs_type.h
+--- a/include/linux/aufs_type.h 1969-12-31 16:00:00.000000000 -0800
++++ b/include/linux/aufs_type.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#include <linux/ioctl.h>
++
++#define AUFS_VERSION "2-standalone.tree-29-20090622"
++
++/* todo? move this to linux-2.6.19/include/magic.h */
++#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++/* some environments treat 'char' as 'unsigned char' by default */
++typedef signed char aufs_bindex_t;
++#define AUFS_BRANCH_MAX 127
++#else
++typedef short aufs_bindex_t;
++#ifdef CONFIG_AUFS_BRANCH_MAX_511
++#define AUFS_BRANCH_MAX 511
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++#define AUFS_BRANCH_MAX 1023
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++#define AUFS_BRANCH_MAX 32767
++#endif
++#endif
++
++#ifdef __KERNEL__
++#ifndef AUFS_BRANCH_MAX
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif /* __KERNEL__ */
++
++/* ---------------------------------------------------------------------- */
++
++#define AUFS_NAME "aufs"
++#define AUFS_FSTYPE AUFS_NAME
++
++#define AUFS_ROOT_INO 2
++#define AUFS_FIRST_INO 11
++
++#define AUFS_WH_PFX ".wh."
++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
++#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
++#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
++#define AUFS_DIRWH_DEF 3
++#define AUFS_RDCACHE_DEF 10 /* seconds */
++#define AUFS_RDBLK_DEF 512 /* bytes */
++#define AUFS_RDHASH_DEF 32
++#define AUFS_WKQ_NAME AUFS_NAME "d"
++#define AUFS_NWKQ_DEF 4
++#define AUFS_MFS_SECOND_DEF 30 /* seconds */
++#define AUFS_PLINK_WARN 100 /* number of plinks */
++
++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
++#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
++#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
++
++/* doubly whiteouted */
++#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
++#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
++#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
++
++/* branch permission */
++#define AUFS_BRPERM_RW "rw"
++#define AUFS_BRPERM_RO "ro"
++#define AUFS_BRPERM_RR "rr"
++#define AUFS_BRPERM_WH "wh"
++#define AUFS_BRPERM_NLWH "nolwh"
++#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {
++ AuCtl_PLINK_MAINT,
++ AuCtl_PLINK_CLEAN
++};
++
++#define AuCtlType 'A'
++#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
++#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
++
++#endif /* __AUFS_TYPE_H__ */
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch
new file mode 100644
index 0000000000..9a9b982fef
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch
@@ -0,0 +1,40 @@
+--- linux-omap-2.6/init/do_mounts.c 2008-11-23 01:22:52.000000000 -0800
++++ linux-omap-2.6/init/do_mounts.c 2008-11-23 02:17:58.000000000 -0800
+@@ -325,6 +325,37 @@
+
+ void __init mount_root(void)
+ {
++ int do_special = 0;
++ if (strcmp(root_device_name, "special") == 0)
++ do_special = 1;
++ //do_special = 1;
++
++ if (do_special) {
++ dev_t ROOT_DEV_RO;
++ dev_t ROOT_DEV_RW;
++
++ sys_mkdir("/root-ro", 0700);
++ ROOT_DEV_RO = name_to_dev_t("/dev/mtd4");
++ create_dev("/dev/root-ro", ROOT_DEV_RO);
++ if (sys_mount("/dev/root-ro", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0) {
++ ROOT_DEV_RO = name_to_dev_t("/dev/mmcblk0p2");
++ create_dev("/dev/root-ro2", ROOT_DEV_RO);
++ if (sys_mount("/dev/root-ro2", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0)
++ goto no_special;
++ }
++
++ sys_mkdir("/root-rw", 0700);
++ ROOT_DEV_RW = name_to_dev_t("/dev/mmcblk0p3");
++ create_dev("/dev/root-rw", ROOT_DEV_RW);
++ if (sys_mount("/dev/root-rw", "/root-rw", "ext3", MS_SILENT, NULL) != 0)
++ goto no_special;
++ sys_mount("none", "/root", "aufs", 0, "br:/root-rw:/root-ro=ro");
++ sys_chdir("/root");
++ return;
++ }
++
++no_special:
++
+ #ifdef CONFIG_ROOT_NFS
+ if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (mount_nfs_root())
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch
new file mode 100644
index 0000000000..035627ac79
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch
@@ -0,0 +1,221 @@
+From 1b3e7e2e095648f244a08b1459ff035bbdc99942 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Tue, 5 May 2009 23:33:00 -0700
+Subject: [PATCH] TWL BCI: Make charge current controllable and backup battery optional.
+
+This patch makes the charging current controllable via sysfs and also
+makes the backup battery optional. Also, if you don't care about the
+temperature readings, you can opt-out from having to supply a
+temperature lookup table.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/power/twl4030_bci_battery.c | 91 +++++++++++++++++++++++++++++------
+ include/linux/i2c/twl4030.h | 2 +
+ 2 files changed, 78 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index ddba62b..eab0933 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -125,6 +125,14 @@
+ /* BCIEDR3 */
+ #define VBATLVL_EDRRISIN 0x02
+
++/* BCIIREF1 */
++#define REG_BCIIREF1 0x027
++#define REG_BCIIREF2 0x028
++
++/* Key */
++#define KEY_IIREF 0xE7
++#define REG_BCIMFKEY 0x011
++
+ /* Step size and prescaler ratio */
+ #define TEMP_STEP_SIZE 147
+ #define TEMP_PSR_R 100
+@@ -142,9 +150,6 @@
+ #define ENABLE 1
+ #define DISABLE 1
+
+-/* Ptr to thermistor table */
+-int *therm_tbl;
+-
+ struct twl4030_bci_device_info {
+ struct device *dev;
+
+@@ -160,6 +165,8 @@ struct twl4030_bci_device_info {
+ struct power_supply bk_bat;
+ struct delayed_work twl4030_bci_monitor_work;
+ struct delayed_work twl4030_bk_bci_monitor_work;
++
++ struct twl4030_bci_platform_data *pdata;
+ };
+
+ static int usb_charger_flag;
+@@ -518,11 +525,15 @@ int twl4030charger_usb_en(int enable)
+ * Return battery temperature
+ * Or < 0 on failure.
+ */
+-static int twl4030battery_temperature(void)
++static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
+ {
+ u8 val;
+ int temp, curr, volt, res, ret;
+
++ /* Is a temperature table specified? */
++ if (!di->pdata->tblsize)
++ return 0;
++
+ /* Getting and calculating the thermistor voltage */
+ ret = read_bci_val(T2_BATTERY_TEMP);
+ if (ret < 0)
+@@ -543,7 +554,7 @@ static int twl4030battery_temperature(void)
+
+ /*calculating temperature*/
+ for (temp = 58; temp >= 0; temp--) {
+- int actual = therm_tbl[temp];
++ int actual = di->pdata->battery_tmp_tbl[temp];
+ if ((actual - res) >= 0)
+ break;
+ }
+@@ -772,13 +783,14 @@ static void twl4030_bk_bci_battery_work(struct work_struct *work)
+ struct twl4030_bci_device_info,
+ twl4030_bk_bci_monitor_work.work);
+
+- twl4030_bk_bci_battery_read_status(di);
++ if(!di->pdata->no_backup_battery)
++ twl4030_bk_bci_battery_read_status(di);
+ schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
+ }
+
+ static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
+ {
+- di->temp_C = twl4030battery_temperature();
++ di->temp_C = twl4030battery_temperature(di);
+ di->voltage_uV = twl4030battery_voltage();
+ di->current_uA = twl4030battery_current();
+ }
+@@ -819,6 +831,43 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ #define to_twl4030_bk_bci_device_info(x) container_of((x), \
+ struct twl4030_bci_device_info, bk_bat);
+
++static ssize_t
++show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++}
++
++static ssize_t
++set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long newCurrent;
++ int ret;
++
++ ret = strict_strtoul(buf, 10, &newCurrent);
++ if (ret)
++ return -EINVAL;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
++
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+@@ -912,8 +961,6 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ int irq;
+ int ret;
+
+- therm_tbl = pdata->battery_tmp_tbl;
+-
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+@@ -937,6 +984,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
+ di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
+ di->bk_bat.external_power_changed = NULL;
++ di->pdata = pdata;
+
+ twl4030charger_ac_en(ENABLE);
+ twl4030charger_usb_en(ENABLE);
+@@ -951,9 +999,12 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ goto temp_setup_fail;
+
+ /* enabling GPCH09 for read back battery voltage */
+- ret = twl4030backupbatt_voltage_setup();
+- if (ret)
+- goto voltage_setup_fail;
++ if(!di->pdata->no_backup_battery)
++ {
++ ret = twl4030backupbatt_voltage_setup();
++ if (ret)
++ goto voltage_setup_fail;
++ }
+
+ /* REVISIT do we need to request both IRQs ?? */
+
+@@ -988,9 +1039,18 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ twl4030_bci_battery_work);
+ schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
+
+- ret = power_supply_register(&pdev->dev, &di->bk_bat);
++ if(!pdata->no_backup_battery)
++ {
++ ret = power_supply_register(&pdev->dev, &di->bk_bat);
++ if (ret) {
++ dev_dbg(&pdev->dev, "failed to register backup battery\n");
++ goto bk_batt_failed;
++ }
++ }
++
++ ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
+ if (ret) {
+- dev_dbg(&pdev->dev, "failed to register backup battery\n");
++ dev_err(&pdev->dev, "failed to create sysfs entries\n");
+ goto bk_batt_failed;
+ }
+
+@@ -1001,7 +1061,8 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ return 0;
+
+ bk_batt_failed:
+- power_supply_unregister(&di->bat);
++ if(!pdata->no_backup_battery)
++ power_supply_unregister(&di->bat);
+ batt_failed:
+ free_irq(irq, di);
+ chg_irq_fail:
+diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
+index 87accda..a188b6c 100644
+--- a/include/linux/i2c/twl4030.h
++++ b/include/linux/i2c/twl4030.h
+@@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+ struct twl4030_bci_platform_data {
+ int *battery_tmp_tbl;
+ unsigned int tblsize;
++
++ bool no_backup_battery;
+ };
+
+ /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch
new file mode 100644
index 0000000000..ce5a98f69d
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch
@@ -0,0 +1,246 @@
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index eab0933..d1220d7 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -15,6 +15,9 @@
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
++/* Boot with automatic charge */
++#define CHARGE_MODE 1
++
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -50,6 +53,7 @@
+ /* Boot BCI flag bits */
+ #define BCIAUTOWEN 0x020
+ #define CONFIG_DONE 0x010
++#define CVENAC 0x004
+ #define BCIAUTOUSB 0x002
+ #define BCIAUTOAC 0x001
+ #define BCIMSTAT_MASK 0x03F
+@@ -81,6 +85,11 @@
+ #define REG_BB_CFG 0x012
+ #define BBCHEN 0x010
+
++/* GPBR */
++#define REG_GPBR1 0x0c
++#define MADC_HFCLK_EN 0x80
++#define DEFAULT_MADC_CLK_EN 0x10
++
+ /* Power supply charge interrupt */
+ #define REG_PWR_ISR1 0x00
+ #define REG_PWR_IMR1 0x01
+@@ -129,8 +138,12 @@
+ #define REG_BCIIREF1 0x027
+ #define REG_BCIIREF2 0x028
+
++/* BCIMFTH1 */
++#define REG_BCIMFTH1 0x016
++
+ /* Key */
+ #define KEY_IIREF 0xE7
++#define KEY_FTH1 0xD2
+ #define REG_BCIMFKEY 0x011
+
+ /* Step size and prescaler ratio */
+@@ -432,15 +445,21 @@ static int twl4030battery_hw_presence_en(int enable)
+ /*
+ * Enable/Disable AC Charge funtionality.
+ */
+-static int twl4030charger_ac_en(int enable)
++static int twl4030charger_ac_en(int enable, int automatic)
+ {
+ int ret;
+
+ if (enable) {
+ /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
+- ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+- (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
+- REG_BOOT_BCI);
++ if(!automatic) {
++ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
++ (CONFIG_DONE | BCIAUTOWEN),
++ REG_BOOT_BCI);
++ } else {
++ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
++ (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
++ REG_BOOT_BCI);
++ }
+ if (ret)
+ return ret;
+ } else {
+@@ -672,6 +691,9 @@ static int twl4030bci_status(void)
+ return ret;
+ }
+
++#ifdef DEBUG
++ printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
++#endif
+ return (int) (status & BCIMSTAT_MASK);
+ }
+
+@@ -720,14 +742,43 @@ static int twl4030backupbatt_voltage_setup(void)
+ */
+ static int twl4030battery_temp_setup(void)
+ {
+- int ret;
++#ifdef DEBUG
++ u8 i;
++#endif
++ u8 ret;
+
+ /* Enabling thermistor current */
+- ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
++ ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
+ REG_BCICTL1);
+ if (ret)
+ return ret;
+
++#ifdef DEBUG
++ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
++ printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
++ printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
++ printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
++ printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
++ printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
++ printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
++
++ for(i = 0x0; i <= 0x32; i++)
++ {
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
++ printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
++ }
++#endif
++
+ return 0;
+ }
+
+@@ -743,7 +794,6 @@ static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
+ ret = twl4030_i2c_read_u8(mod_no, &val, reg);
+ if (ret)
+ return ret;
+-
+ /* Clearing all those bits to clear */
+ val &= ~(clear);
+
+@@ -834,7 +884,19 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ static ssize_t
+ show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++ u8 ctl;
++ int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
++
++ if (ctl & CGAIN)
++ ret |= 0x200;
++
++#ifdef DEBUG
++ /* Dump debug */
++ twl4030battery_temp_setup();
++#endif
++
++ return sprintf(buf, "%d\n", ret);
+ }
+
+ static ssize_t
+@@ -859,13 +921,45 @@ set_charge_current(struct device *dev, struct device_attribute *attr, const char
+ if (ret)
+ return ret;
+
+- ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+ if (ret)
+ return ret;
+
++ /* Set software-controlled charge */
++ twl4030charger_ac_en(ENABLE, 0);
++
++ /* Set CGAIN = 0 or 1 */
++ if(newCurrent > 511) {
++ u8 tmp;
++
++ /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
++ while(!ret) {
++ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++ ret = tmp & CGAIN;
++ if(!ret)
++ mdelay(50);
++ }
++ } else {
++ u8 tmp;
++
++ /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
++ while(!ret) {
++ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++ ret = !(tmp & CGAIN);
++ if(!ret)
++ mdelay(50);
++ }
++ }
++
++ /* Set automatic charge (CGAIN = 0/1 persists) */
++ twl4030charger_ac_en(ENABLE, 1);
++
+ return count;
+ }
+-
+ static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
+
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+@@ -986,7 +1080,10 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ di->bk_bat.external_power_changed = NULL;
+ di->pdata = pdata;
+
+- twl4030charger_ac_en(ENABLE);
++ /* Set up clocks */
++ twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
++
++ twl4030charger_ac_en(ENABLE, CHARGE_MODE);
+ twl4030charger_usb_en(ENABLE);
+ twl4030battery_hw_level_en(ENABLE);
+ twl4030battery_hw_presence_en(ENABLE);
+@@ -1058,6 +1155,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ twl4030_bk_bci_battery_work);
+ schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
+
++ set_charge_current (NULL, NULL, "1023", 4);
+ return 0;
+
+ bk_batt_failed:
+@@ -1071,7 +1169,7 @@ chg_irq_fail:
+ batt_irq_fail:
+ voltage_setup_fail:
+ temp_setup_fail:
+- twl4030charger_ac_en(DISABLE);
++ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+ twl4030charger_usb_en(DISABLE);
+ twl4030battery_hw_level_en(DISABLE);
+ twl4030battery_hw_presence_en(DISABLE);
+@@ -1085,7 +1183,7 @@ static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+ int irq;
+
+- twl4030charger_ac_en(DISABLE);
++ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+ twl4030charger_usb_en(DISABLE);
+ twl4030battery_hw_level_en(DISABLE);
+ twl4030battery_hw_presence_en(DISABLE);
+
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch
new file mode 100644
index 0000000000..fd629078ca
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch
@@ -0,0 +1,53 @@
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index bc6ef06..df7aa70 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -28,6 +28,7 @@
+
+ #define DRIVER_VERSION "1.0.0"
+
++#define BQ27x00_REG_MODE 0x00
+ #define BQ27x00_REG_TEMP 0x06
+ #define BQ27x00_REG_VOLT 0x08
+ #define BQ27x00_REG_RSOC 0x0B /* Relative State-of-Charge */
+@@ -65,6 +66,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
++ POWER_SUPPLY_PROP_ONLINE,
+ };
+
+ /*
+@@ -83,6 +85,22 @@ static int bq27x00_read(u8 reg, int *rt_value, int b_single,
+ }
+
+ /*
++ * Return the GPIO status (0 or 1)
++ * Or < 0 if something fails.
++ */
++static int bq27x00_gpio(struct bq27x00_device_info *di)
++{
++ int ret;
++ int gpio = 0;
++
++ ret = bq27x00_read(BQ27x00_REG_MODE, &gpio, 0, di);
++ if (ret)
++ return ret;
++
++ return (gpio & 0x40) >> 6;
++}
++
++/*
+ * Return the battery temperature in Celcius degrees
+ * Or < 0 if something fails.
+ */
+@@ -184,6 +202,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = bq27x00_battery_temperature(di);
+ break;
++ case POWER_SUPPLY_PROP_ONLINE:
++ val->intval = bq27x00_gpio(di);
++ break;
+ default:
+ return -EINVAL;
+ }
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch
new file mode 100644
index 0000000000..eb7c8c9699
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch
@@ -0,0 +1,39 @@
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -93,7 +93,6 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading temperature\n");
+ return ret;
+ }
+
+@@ -111,7 +110,6 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading voltage\n");
+ return ret;
+ }
+
+@@ -131,12 +129,10 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading current\n");
+ return 0;
+ }
+ ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+ if (ret < 0) {
+- dev_err(di->dev, "error reading flags\n");
+ return 0;
+ }
+ if ((flags & (1 << 7)) != 0) {
+@@ -157,7 +153,6 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di);
+ if (ret) {
+- dev_err(di->dev, "error reading relative State-of-Charge\n");
+ return ret;
+ }
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/beagle-asoc.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/beagle-asoc.patch
new file mode 100644
index 0000000000..b2b920037e
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/beagle-asoc.patch
@@ -0,0 +1,35 @@
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 4f7f040..ccd8973 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
++
++config SND_OMAP_SOC_OMAP3_BEAGLE
++ tristate "SoC Audio support for OMAP3 Beagle"
++ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE
++ select SND_OMAP_SOC_MCBSP
++ select SND_SOC_TWL4030
++ help
++ Say Y if you want to add support for SoC audio on the Beagleboard.
++
++
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index 76fedd9..0c9e4ac 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o
+ snd-soc-omap2evm-objs := omap2evm.o
+ snd-soc-sdp3430-objs := sdp3430.o
+ snd-soc-omap3pandora-objs := omap3pandora.o
++snd-soc-omap3beagle-objs := omap3beagle.o
+
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+@@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+ obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
+ obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
++obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/board-omap3beagle.c b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/board-omap3beagle.c
new file mode 100644
index 0000000000..26efafff21
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/board-omap3beagle.c
@@ -0,0 +1,739 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3beagle.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/mcspi.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/mma7455l.h>
+
+#include <mach/dmtimer.h>
+#include <linux/backlight.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/omapfb.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/board.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/gpmc.h>
+#include <mach/nand.h>
+#include <mach/mux.h>
+#include <mach/display.h>
+
+#include "twl4030-generic-scripts.h"
+#include "mmc-twl4030.h"
+
+
+#define GPMC_CS0_BASE 0x60
+#define GPMC_CS_SIZE 0x30
+
+#define NAND_BLOCK_SIZE SZ_128K
+
+#define OMAP3_AC_GPIO 136 //Int1 DRDY
+#define OMAP3_TS_GPIO 162
+#define TB_BL_PWM_TIMER 9
+#define TB_KILL_POWER_GPIO 168
+
+static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader",
+ .offset = 0,
+ .size = 4 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 15 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot Env",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
+ .size = 1 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "Kernel",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 32 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "File System",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct omap_nand_platform_data omap3beagle_nand_data = {
+ .options = NAND_BUSWIDTH_16,
+ .parts = omap3beagle_nand_partitions,
+ .nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions),
+ .dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .nand_setup = NULL,
+ .dev_ready = NULL,
+};
+
+static struct resource omap3beagle_nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device omap3beagle_nand_device = {
+ .name = "omap2-nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &omap3beagle_nand_data,
+ },
+ .num_resources = 1,
+ .resource = &omap3beagle_nand_resource,
+};
+
+#include "sdram-micron-mt46h32m32lf-6.h"
+
+static struct omap_uart_config omap3_beagle_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct twl4030_usb_data beagle_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+ {
+ .mmc = 1,
+ .wires = 8,
+ .gpio_wp = 29,
+ },
+ {} /* Terminator */
+};
+
+static struct regulator_consumer_supply beagle_vmmc1_supply = {
+ .supply = "vmmc",
+};
+
+static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+};
+
+static struct gpio_led gpio_leds[];
+
+static int beagle_twl_gpio_setup(struct device *dev,
+ unsigned gpio, unsigned ngpio)
+{
+ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+ omap_cfg_reg(AH8_34XX_GPIO29);
+ mmc[0].gpio_cd = gpio + 0;
+ twl4030_mmc_init(mmc);
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+ * power switch and overcurrent detect
+ */
+
+#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+ gpio_request(gpio + 1, "EHCI_nOC");
+ gpio_direction_input(gpio + 1);
+
+ /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+ gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+ return 0;
+}
+
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+ .use_leds = true,
+ .pullups = BIT(1),
+ .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+ | BIT(15) | BIT(16) | BIT(17),
+ .setup = beagle_twl_gpio_setup,
+};
+
+static struct platform_device omap3_beagle_lcd_device = {
+ .name = "omap3beagle_lcd",
+ .id = -1,
+};
+
+static struct regulator_consumer_supply beagle_vdac_supply = {
+ .supply = "vdac",
+ .dev = &omap3_beagle_lcd_device.dev,
+};
+
+static struct regulator_consumer_supply beagle_vdvi_supply = {
+ .supply = "vdvi",
+ .dev = &omap3_beagle_lcd_device.dev,
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data beagle_vmmc1 = {
+ .constraints = {
+ .min_uV = 1850000,
+ .max_uV = 3150000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vmmc1_supply,
+};
+
+/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 3000000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data beagle_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data beagle_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vdvi_supply,
+};
+
+static const struct twl4030_resconfig beagle_resconfig[] = {
+ /* disable regulators that u-boot left enabled; the
+ * devices' drivers should be managing these.
+ */
+ { .resource = RES_VAUX3, }, /* not even connected! */
+ { .resource = RES_VMMC1, },
+ { .resource = RES_VSIM, },
+ { .resource = RES_VPLL2, },
+ { .resource = RES_VDAC, },
+ { .resource = RES_VUSB_1V5, },
+ { .resource = RES_VUSB_1V8, },
+ { .resource = RES_VUSB_3V1, },
+ { 0, },
+};
+
+static struct twl4030_power_data beagle_power_data = {
+ .resource_config = beagle_resconfig,
+ /* REVISIT can't use GENERIC3430_T2SCRIPTS_DATA;
+ * among other things, it makes reboot fail.
+ */
+};
+
+static struct twl4030_bci_platform_data touchbook_bci_data = {
+ .tblsize = 0,
+ .no_backup_battery = 1,
+};
+
+static struct twl4030_platform_data beagle_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .usb = &beagle_usb_data,
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
+
+ /* TouchBook BCI */
+ .bci = &touchbook_bci_data,
+};
+
+static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .irq = INT_34XX_SYS_NIRQ,
+ .platform_data = &beagle_twldata,
+ },
+};
+
+static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("bq27200", 0x55),
+ },
+};
+
+static int __init omap3_beagle_i2c_init(void)
+{
+ /* Standard BeagleBoard bus */
+ omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+ ARRAY_SIZE(beagle_i2c_boardinfo));
+
+ /* TouchBook keyboard bus */
+ omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
+ ARRAY_SIZE(touchBook_i2c_boardinfo));
+
+ return 0;
+}
+
+static void __init omap3_ads7846_init(void)
+{
+ if (gpio_request(OMAP3_TS_GPIO, "ads7846_pen_down")) {
+ printk(KERN_ERR "Failed to request GPIO %d for "
+ "ads7846 pen down IRQ\n", OMAP3_TS_GPIO);
+ return;
+ }
+
+ gpio_direction_input(OMAP3_TS_GPIO);
+ omap_set_gpio_debounce(OMAP3_TS_GPIO, 1);
+ omap_set_gpio_debounce_time(OMAP3_TS_GPIO, 0xa);
+}
+
+static struct ads7846_platform_data ads7846_config = {
+ .x_min = 100,
+ .y_min = 265,
+ .x_max = 3950,
+ .y_max = 3750,
+ .x_plate_ohms = 40,
+ .pressure_max = 255,
+ .debounce_max = 10,
+ .debounce_tol = 5,
+ .debounce_rep = 1,
+ .gpio_pendown = OMAP3_TS_GPIO,
+ .keep_vref_on = 1,
+};
+
+static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_ads7846_spi_board_info[] __initdata = {
+ {
+ .modalias = "ads7846",
+ .bus_num = 4,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ .controller_data = &ads7846_mcspi_config, //(void *) 161,
+ .irq = OMAP_GPIO_IRQ(OMAP3_TS_GPIO),
+ .platform_data = &ads7846_config,
+ }
+};
+
+static void __init omap3_beagle_init_irq(void)
+{
+ omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "beagleboard::usr0",
+ .default_trigger = "heartbeat",
+ .gpio = 150,
+ },
+ {
+ .name = "beagleboard::usr1",
+ .default_trigger = "mmc0",
+ .gpio = 149,
+ },
+ {
+ .name = "beagleboard::pmu_stat",
+ .gpio = -EINVAL, /* gets replaced */
+ .active_low = true,
+ },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_led_info,
+ },
+};
+
+static struct gpio_keys_button gpio_buttons[] = {
+ {
+ .code = BTN_EXTRA,
+ .gpio = 7,
+ .desc = "user",
+ .wakeup = 1,
+ },
+ {
+ .code = KEY_POWER,
+ .gpio = 183,
+ .desc = "power",
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device keys_gpio = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* DSS */
+
+static int beagle_enable_dvi(struct omap_display *display)
+{
+ if (display->hw_config.panel_reset_gpio != -1)
+ gpio_set_value(display->hw_config.panel_reset_gpio, 1);
+
+ return 0;
+}
+
+static void beagle_disable_dvi(struct omap_display *display)
+{
+ if (display->hw_config.panel_reset_gpio != -1)
+ gpio_set_value(display->hw_config.panel_reset_gpio, 0);
+}
+
+static struct omap_dss_display_config beagle_display_data_dvi = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "dvi",
+ .panel_name = "panel-generic",
+ .u.dpi.data_lines = 24,
+ .panel_reset_gpio = 176,
+ .panel_enable = beagle_enable_dvi,
+ .panel_disable = beagle_disable_dvi,
+};
+
+
+static int beagle_panel_enable_tv(struct omap_display *display)
+{
+#define ENABLE_VDAC_DEDICATED 0x03
+#define ENABLE_VDAC_DEV_GRP 0x20
+
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ ENABLE_VDAC_DEDICATED,
+ TWL4030_VDAC_DEDICATED);
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+
+ return 0;
+}
+
+static void beagle_panel_disable_tv(struct omap_display *display)
+{
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+ TWL4030_VDAC_DEDICATED);
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+ TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_dss_display_config beagle_display_data_tv = {
+ .type = OMAP_DISPLAY_TYPE_VENC,
+ .name = "tv",
+ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+ .panel_enable = beagle_panel_enable_tv,
+ .panel_disable = beagle_panel_disable_tv,
+};
+
+static struct omap_dss_board_info beagle_dss_data = {
+ .num_displays = 2,
+ .displays = {
+ &beagle_display_data_dvi,
+ &beagle_display_data_tv,
+ }
+};
+
+static struct platform_device beagle_dss_device = {
+ .name = "omapdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &beagle_dss_data,
+ },
+};
+
+static void __init beagle_display_init(void)
+{
+ int r;
+
+ r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+ if (r < 0) {
+ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+ return;
+ }
+
+ gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+}
+
+static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_beagle_uart_config },
+};
+
+static struct platform_device *omap3_beagle_devices[] __initdata = {
+ &beagle_dss_device,
+ &leds_gpio,
+ &keys_gpio,
+};
+
+static void __init omap3beagle_flash_init(void)
+{
+ u8 cs = 0;
+ u8 nandcs = GPMC_CS_NUM + 1;
+
+ u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+ /* find out the chip-select on which NAND exists */
+ while (cs < GPMC_CS_NUM) {
+ u32 ret = 0;
+ ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+ if ((ret & 0xC00) == 0x800) {
+ printk(KERN_INFO "Found NAND on CS%d\n", cs);
+ if (nandcs > GPMC_CS_NUM)
+ nandcs = cs;
+ }
+ cs++;
+ }
+
+ if (nandcs > GPMC_CS_NUM) {
+ printk(KERN_INFO "NAND: Unable to find configuration "
+ "in GPMC\n ");
+ return;
+ }
+
+ if (nandcs < GPMC_CS_NUM) {
+ omap3beagle_nand_data.cs = nandcs;
+ omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
+ (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
+ omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
+
+ printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+ if (platform_device_register(&omap3beagle_nand_device) < 0)
+ printk(KERN_ERR "Unable to register NAND device\n");
+ }
+}
+
+static void __init omap3_mma7455l_init(void)
+{
+ int ret;
+
+ ret = gpio_request(OMAP3_AC_GPIO, "mma7455l");
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to request GPIO %d for mma7455l IRQ\n", OMAP3_AC_GPIO);
+ return;
+ }
+
+ gpio_direction_input(OMAP3_AC_GPIO);
+}
+
+static struct mma7455l_platform_data mma7455l_config = {
+ .calibration_x = -4, //26 for Beagleboard
+ .calibration_y = 28, //44 for Beagleboard
+ .calibration_z = -28, //26 for Beagleboard
+};
+
+static struct omap2_mcspi_device_config mma7455l_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_mma7455l_spi_board_info[] __initdata = {
+ {
+ .modalias = "mma7455l",
+ .bus_num = 3,
+ .chip_select = 0,
+ .max_speed_hz = 200000,
+ .irq = OMAP_GPIO_IRQ(OMAP3_AC_GPIO),
+ .controller_data = &mma7455l_mcspi_config, //(void *) 135,
+ .platform_data = &mma7455l_config,
+ }
+};
+
+static int touchbook_backlight_brightness = 50;
+static struct omap_dm_timer *touchbook_backlight_pwm;
+
+static int touchbook_backlight_read(struct backlight_device *bd)
+{
+ return touchbook_backlight_brightness;
+}
+
+static int touchbook_backlight_update(struct backlight_device *bd)
+{
+ int value = bd->props.brightness;
+ touchbook_backlight_brightness = value;
+
+ /* Frequency calculation:
+ - For 200Hz PWM, you want to load -164 (=> -32768Hz / 200Hz).
+ - Minimum duty cycle for the backlight is 15%.
+ - You have (164*0.85) => ~140 levels of brightness.
+ */
+
+ /* Convert from 0-100 range to 0-140 range */
+ value = (value * 14) / 10 / 2;
+
+ /* For maximum brightness, just stop the timer... */
+ if(value != bd->props.max_brightness)
+ {
+ omap_dm_timer_set_load(touchbook_backlight_pwm, 1, -164);
+ omap_dm_timer_set_match(touchbook_backlight_pwm, 1, -24 - value);
+ omap_dm_timer_write_counter(touchbook_backlight_pwm, -1);
+ //omap_dm_timer_stop(touchbook_backlight_pwm);
+ omap_dm_timer_start(touchbook_backlight_pwm);
+ }
+ else
+ omap_dm_timer_stop(touchbook_backlight_pwm);
+
+
+ return 0;
+}
+
+static struct backlight_ops touchbook_backlight_properties = {
+ .get_brightness = touchbook_backlight_read,
+ .update_status = touchbook_backlight_update,
+};
+
+static void __init omap3_touchbook_backlight_init(void)
+{
+ static struct backlight_device *bd;
+ bd = backlight_device_register("touchbook", NULL, NULL, &touchbook_backlight_properties);
+
+ if(bd)
+ {
+ touchbook_backlight_pwm = omap_dm_timer_request_specific(TB_BL_PWM_TIMER);
+ omap_dm_timer_enable(touchbook_backlight_pwm);
+ omap_dm_timer_set_source(touchbook_backlight_pwm, OMAP_TIMER_SRC_32_KHZ);
+ omap_dm_timer_set_pwm(touchbook_backlight_pwm, 1, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+
+ bd->props.max_brightness = 100;
+ bd->props.brightness = touchbook_backlight_brightness;
+ }
+
+ touchbook_backlight_update(bd);
+}
+
+static void omap3_touchbook_poweroff(void)
+{
+ int r;
+
+ r = gpio_request(TB_KILL_POWER_GPIO, "DVI reset");
+ if (r < 0) {
+ printk(KERN_ERR "Unable to get kill power GPIO\n");
+ return;
+ }
+
+ gpio_direction_output(TB_KILL_POWER_GPIO, 0);
+}
+
+static void __init omap3_beagle_init(void)
+{
+ pm_power_off = omap3_touchbook_poweroff;
+
+ omap3_beagle_i2c_init();
+ platform_add_devices(omap3_beagle_devices,
+ ARRAY_SIZE(omap3_beagle_devices));
+ omap_board_config = omap3_beagle_config;
+ omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+ omap_serial_init();
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
+ omap3beagle_flash_init();
+ beagle_display_init();
+ omap3_touchbook_backlight_init();
+
+ /* Touch Book */
+ spi_register_board_info(omap3_ads7846_spi_board_info, ARRAY_SIZE(omap3_ads7846_spi_board_info));
+ spi_register_board_info(omap3_mma7455l_spi_board_info, ARRAY_SIZE(omap3_mma7455l_spi_board_info));
+
+ omap3_ads7846_init();
+ omap3_mma7455l_init();
+
+ usb_musb_init();
+ usb_ehci_init();
+}
+
+static void __init omap3_beagle_map_io(void)
+{
+ omap2_set_globals_343x();
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP3_BEAGLE, "OMAP3 Touch Book")
+ /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap3_beagle_map_io,
+ .init_irq = omap3_beagle_init_irq,
+ .init_machine = omap3_beagle_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/boot-no-power-message.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/boot-no-power-message.patch
new file mode 100644
index 0000000000..4be59a4212
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/boot-no-power-message.patch
@@ -0,0 +1,11 @@
+--- a/arch/arm/mach-omap2/pm34xx.c 2009-07-18 10:13:43.000000000 -0700
++++ b/arch/arm/mach-omap2/pm34xx.c 2009-07-18 10:13:54.000000000 -0700
+@@ -625,7 +625,7 @@
+ struct power_state *pwrst, *tmp;
+ int ret;
+
+- printk(KERN_ERR "Power Management for TI OMAP3.\n");
++// printk(KERN_ERR "Power Management for TI OMAP3.\n");
+
+ /* XXX prcm_setup_regs needs to be before enabling hw
+ * supervised mode for powerdomains */
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig
new file mode 100644
index 0000000000..2ff46a4832
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig
@@ -0,0 +1,2720 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri May 29 14:47:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_MMA7455L=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=y
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_TWL4030_BCI_BATTERY=y
+CONFIG_BATTERY_BQ27x00=y
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+CONFIG_MPU_BRIDGE=m
+CONFIG_BRIDGE_MEMPOOL_SIZE=0x600000
+# CONFIG_BRIDGE_DEBUG is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+# CONFIG_AUFS_HINOTIFY is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+CONFIG_AUFS_DEBUG=y
+CONFIG_AUFS_MAGIC_SYSRQ=y
+CONFIG_AUFS_BDEV_LOOP=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig.orig b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig.orig
new file mode 100644
index 0000000000..1aa7cf57ac
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/defconfig.orig
@@ -0,0 +1,2701 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri May 29 14:47:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OMAP24XX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
new file mode 100644
index 0000000000..621ae93d3b
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
@@ -0,0 +1,66715 @@
+From ea83ad971e877ef8e9b1304f2678469c2fc74c67 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sun, 26 Apr 2009 18:58:30 -0700
+Subject: [PATCH] Merge in tidspbridge from git://gitorious.org/tidspbridge/mainline.git
+ revisions fe30e75..20f5ca.
+
+Made a few changes so this compiles clean against a 2.6.29 non-PM
+tree.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ Documentation/tidspbridge/README | 70 +
+ arch/arm/Kconfig | 2 +
+ arch/arm/mach-omap2/Makefile | 2 +
+ arch/arm/mach-omap2/dspbridge.c | 74 +
+ arch/arm/mach-omap2/io.c | 3 +
+ arch/arm/plat-omap/devices.c | 28 +
+ arch/arm/plat-omap/include/dspbridge/_chnl_sm.h | 212 ++
+ arch/arm/plat-omap/include/dspbridge/_dcd.h | 187 +
+ arch/arm/plat-omap/include/dspbridge/brddefs.h | 54 +
+ arch/arm/plat-omap/include/dspbridge/cfg.h | 339 ++
+ arch/arm/plat-omap/include/dspbridge/cfgdefs.h | 126 +
+ arch/arm/plat-omap/include/dspbridge/chnl.h | 170 +
+ arch/arm/plat-omap/include/dspbridge/chnl_sm.h | 168 +
+ arch/arm/plat-omap/include/dspbridge/chnldefs.h | 92 +
+ arch/arm/plat-omap/include/dspbridge/chnlpriv.h | 136 +
+ arch/arm/plat-omap/include/dspbridge/clk.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/cmm.h | 420 +++
+ arch/arm/plat-omap/include/dspbridge/cmmdefs.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/cod.h | 433 +++
+ arch/arm/plat-omap/include/dspbridge/csl.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/dbc.h | 66 +
+ arch/arm/plat-omap/include/dspbridge/dbdcd.h | 388 +++
+ arch/arm/plat-omap/include/dspbridge/dbdcddef.h | 94 +
+ arch/arm/plat-omap/include/dspbridge/dbdefs.h | 580 ++++
+ arch/arm/plat-omap/include/dspbridge/dbg.h | 110 +
+ arch/arm/plat-omap/include/dspbridge/dbl.h | 354 ++
+ arch/arm/plat-omap/include/dspbridge/dbldefs.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/dbll.h | 70 +
+ arch/arm/plat-omap/include/dspbridge/dblldefs.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/dbof.h | 117 +
+ arch/arm/plat-omap/include/dspbridge/dbreg.h | 113 +
+ arch/arm/plat-omap/include/dspbridge/dbtype.h | 103 +
+ arch/arm/plat-omap/include/dspbridge/dehdefs.h | 42 +
+ arch/arm/plat-omap/include/dspbridge/dev.h | 785 +++++
+ arch/arm/plat-omap/include/dspbridge/devdefs.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/disp.h | 236 ++
+ arch/arm/plat-omap/include/dspbridge/dispdefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/dmm.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/dpc.h | 167 +
+ arch/arm/plat-omap/include/dspbridge/drv.h | 449 +++
+ arch/arm/plat-omap/include/dspbridge/drvdefs.h | 34 +
+ arch/arm/plat-omap/include/dspbridge/dspdrv.h | 106 +
+ .../plat-omap/include/dspbridge/dynamic_loader.h | 505 +++
+ arch/arm/plat-omap/include/dspbridge/errbase.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/gb.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/getsection.h | 118 +
+ arch/arm/plat-omap/include/dspbridge/gh.h | 37 +
+ arch/arm/plat-omap/include/dspbridge/gs.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/gt.h | 315 ++
+ arch/arm/plat-omap/include/dspbridge/host_os.h | 96 +
+ arch/arm/plat-omap/include/dspbridge/io.h | 132 +
+ arch/arm/plat-omap/include/dspbridge/io_sm.h | 335 ++
+ arch/arm/plat-omap/include/dspbridge/iodefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/kfile.h | 216 ++
+ arch/arm/plat-omap/include/dspbridge/ldr.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/list.h | 296 ++
+ arch/arm/plat-omap/include/dspbridge/mbx_sh.h | 213 ++
+ arch/arm/plat-omap/include/dspbridge/mem.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/memdefs.h | 52 +
+ arch/arm/plat-omap/include/dspbridge/mgr.h | 234 ++
+ arch/arm/plat-omap/include/dspbridge/mgrpriv.h | 55 +
+ arch/arm/plat-omap/include/dspbridge/msg.h | 106 +
+ arch/arm/plat-omap/include/dspbridge/msgdefs.h | 43 +
+ arch/arm/plat-omap/include/dspbridge/nldr.h | 81 +
+ arch/arm/plat-omap/include/dspbridge/nldrdefs.h | 307 ++
+ arch/arm/plat-omap/include/dspbridge/node.h | 619 ++++
+ arch/arm/plat-omap/include/dspbridge/nodedefs.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/nodepriv.h | 202 ++
+ arch/arm/plat-omap/include/dspbridge/ntfy.h | 146 +
+ arch/arm/plat-omap/include/dspbridge/proc.h | 648 ++++
+ arch/arm/plat-omap/include/dspbridge/procpriv.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/pwr.h | 129 +
+ arch/arm/plat-omap/include/dspbridge/pwr_sh.h | 41 +
+ arch/arm/plat-omap/include/dspbridge/reg.h | 257 ++
+ .../plat-omap/include/dspbridge/resourcecleanup.h | 88 +
+ arch/arm/plat-omap/include/dspbridge/rmm.h | 199 ++
+ arch/arm/plat-omap/include/dspbridge/rms_sh.h | 125 +
+ arch/arm/plat-omap/include/dspbridge/rmstypes.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/services.h | 63 +
+ arch/arm/plat-omap/include/dspbridge/std.h | 143 +
+ arch/arm/plat-omap/include/dspbridge/strm.h | 441 +++
+ arch/arm/plat-omap/include/dspbridge/strmdefs.h | 57 +
+ arch/arm/plat-omap/include/dspbridge/sync.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/util.h | 122 +
+ arch/arm/plat-omap/include/dspbridge/utildefs.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/uuidutil.h | 74 +
+ arch/arm/plat-omap/include/dspbridge/wcd.h | 61 +
+ arch/arm/plat-omap/include/dspbridge/wcdioctl.h | 519 +++
+ arch/arm/plat-omap/include/dspbridge/wmd.h | 1193 +++++++
+ arch/arm/plat-omap/include/dspbridge/wmdchnl.h | 90 +
+ arch/arm/plat-omap/include/dspbridge/wmddeh.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/wmdio.h | 53 +
+ arch/arm/plat-omap/include/dspbridge/wmdioctl.h | 91 +
+ arch/arm/plat-omap/include/dspbridge/wmdmsg.h | 70 +
+ drivers/Makefile | 1 +
+ drivers/dsp/bridge/Kbuild | 39 +
+ drivers/dsp/bridge/Kconfig | 36 +
+ drivers/dsp/bridge/dynload/cload.c | 1854 ++++++++++
+ drivers/dsp/bridge/dynload/dlclasses_hdr.h | 41 +
+ drivers/dsp/bridge/dynload/dload_internal.h | 237 ++
+ drivers/dsp/bridge/dynload/doff.h | 347 ++
+ drivers/dsp/bridge/dynload/getsection.c | 412 +++
+ drivers/dsp/bridge/dynload/header.h | 59 +
+ drivers/dsp/bridge/dynload/module_list.h | 161 +
+ drivers/dsp/bridge/dynload/params.h | 231 ++
+ drivers/dsp/bridge/dynload/reloc.c | 425 +++
+ drivers/dsp/bridge/dynload/reloc_table.h | 102 +
+ drivers/dsp/bridge/dynload/reloc_table_c6000.c | 258 ++
+ drivers/dsp/bridge/gen/_gt_para.c | 107 +
+ drivers/dsp/bridge/gen/gb.c | 182 +
+ drivers/dsp/bridge/gen/gh.c | 191 ++
+ drivers/dsp/bridge/gen/gs.c | 108 +
+ drivers/dsp/bridge/gen/gt.c | 348 ++
+ drivers/dsp/bridge/gen/uuidutil.c | 238 ++
+ drivers/dsp/bridge/hw/EasiGlobal.h | 42 +
+ drivers/dsp/bridge/hw/GlobalTypes.h | 325 ++
+ drivers/dsp/bridge/hw/IPIAccInt.h | 41 +
+ drivers/dsp/bridge/hw/IVA2RegAcM.h | 28 +
+ drivers/dsp/bridge/hw/MLBAccInt.h | 132 +
+ drivers/dsp/bridge/hw/MLBRegAcM.h | 200 ++
+ drivers/dsp/bridge/hw/MMUAccInt.h | 76 +
+ drivers/dsp/bridge/hw/MMURegAcM.h | 253 ++
+ drivers/dsp/bridge/hw/PRCMAccInt.h | 300 ++
+ drivers/dsp/bridge/hw/PRCMRegAcM.h | 669 ++++
+ drivers/dsp/bridge/hw/hw_defs.h | 73 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.c | 55 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.h | 48 +
+ drivers/dsp/bridge/hw/hw_mbox.c | 244 ++
+ drivers/dsp/bridge/hw/hw_mbox.h | 323 ++
+ drivers/dsp/bridge/hw/hw_mmu.c | 598 ++++
+ drivers/dsp/bridge/hw/hw_mmu.h | 177 +
+ drivers/dsp/bridge/hw/hw_prcm.c | 167 +
+ drivers/dsp/bridge/hw/hw_prcm.h | 168 +
+ drivers/dsp/bridge/pmgr/chnl.c | 260 ++
+ drivers/dsp/bridge/pmgr/chnlobj.h | 71 +
+ drivers/dsp/bridge/pmgr/cmm.c | 1291 +++++++
+ drivers/dsp/bridge/pmgr/cod.c | 683 ++++
+ drivers/dsp/bridge/pmgr/dbl.c | 1385 ++++++++
+ drivers/dsp/bridge/pmgr/dbll.c | 1564 +++++++++
+ drivers/dsp/bridge/pmgr/dev.c | 1476 ++++++++
+ drivers/dsp/bridge/pmgr/dmm.c | 692 ++++
+ drivers/dsp/bridge/pmgr/io.c | 205 ++
+ drivers/dsp/bridge/pmgr/ioobj.h | 52 +
+ drivers/dsp/bridge/pmgr/msg.c | 173 +
+ drivers/dsp/bridge/pmgr/msgobj.h | 52 +
+ drivers/dsp/bridge/pmgr/wcd.c | 1647 +++++++++
+ drivers/dsp/bridge/rmgr/dbdcd.c | 1573 +++++++++
+ drivers/dsp/bridge/rmgr/disp.c | 916 +++++
+ drivers/dsp/bridge/rmgr/drv.c | 1893 +++++++++++
+ drivers/dsp/bridge/rmgr/drv_interface.c | 777 +++++
+ drivers/dsp/bridge/rmgr/drv_interface.h | 40 +
+ drivers/dsp/bridge/rmgr/dspdrv.c | 276 ++
+ drivers/dsp/bridge/rmgr/mgr.c | 491 +++
+ drivers/dsp/bridge/rmgr/nldr.c | 1967 +++++++++++
+ drivers/dsp/bridge/rmgr/node.c | 3544 ++++++++++++++++++++
+ drivers/dsp/bridge/rmgr/proc.c | 1985 +++++++++++
+ drivers/dsp/bridge/rmgr/pwr.c | 184 +
+ drivers/dsp/bridge/rmgr/rmm.c | 604 ++++
+ drivers/dsp/bridge/rmgr/strm.c | 1066 ++++++
+ drivers/dsp/bridge/services/cfg.c | 483 +++
+ drivers/dsp/bridge/services/clk.c | 375 +++
+ drivers/dsp/bridge/services/csl.c | 173 +
+ drivers/dsp/bridge/services/dbg.c | 119 +
+ drivers/dsp/bridge/services/dpc.c | 274 ++
+ drivers/dsp/bridge/services/kfile.c | 338 ++
+ drivers/dsp/bridge/services/list.c | 285 ++
+ drivers/dsp/bridge/services/mem.c | 599 ++++
+ drivers/dsp/bridge/services/ntfy.c | 329 ++
+ drivers/dsp/bridge/services/reg.c | 196 ++
+ drivers/dsp/bridge/services/regsup.c | 368 ++
+ drivers/dsp/bridge/services/regsup.h | 58 +
+ drivers/dsp/bridge/services/services.c | 193 ++
+ drivers/dsp/bridge/services/sync.c | 602 ++++
+ drivers/dsp/bridge/wmd/_cmm.h | 59 +
+ drivers/dsp/bridge/wmd/_deh.h | 46 +
+ drivers/dsp/bridge/wmd/_msg_sm.h | 158 +
+ drivers/dsp/bridge/wmd/_tiomap.h | 384 +++
+ drivers/dsp/bridge/wmd/_tiomap_mmu.h | 53 +
+ drivers/dsp/bridge/wmd/_tiomap_pwr.h | 102 +
+ drivers/dsp/bridge/wmd/_tiomap_util.h | 46 +
+ drivers/dsp/bridge/wmd/chnl_sm.c | 1100 ++++++
+ drivers/dsp/bridge/wmd/io_sm.c | 2011 +++++++++++
+ drivers/dsp/bridge/wmd/mmu_fault.c | 172 +
+ drivers/dsp/bridge/wmd/mmu_fault.h | 45 +
+ drivers/dsp/bridge/wmd/msg_sm.c | 643 ++++
+ drivers/dsp/bridge/wmd/tiomap3430.c | 2149 ++++++++++++
+ drivers/dsp/bridge/wmd/tiomap3430_pwr.c | 731 ++++
+ drivers/dsp/bridge/wmd/tiomap_io.c | 427 +++
+ drivers/dsp/bridge/wmd/tiomap_io.h | 112 +
+ drivers/dsp/bridge/wmd/tiomap_sm.c | 195 ++
+ drivers/dsp/bridge/wmd/ue_deh.c | 329 ++
+ 191 files changed, 65137 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/tidspbridge/README
+ create mode 100644 arch/arm/mach-omap2/dspbridge.c
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_dcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/brddefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/clk.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cod.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/csl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbll.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dblldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbof.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbreg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbtype.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dehdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dev.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/devdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/disp.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dispdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dpc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drvdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dspdrv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/errbase.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gb.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/getsection.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gt.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/host_os.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/iodefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/kfile.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/list.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mem.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/memdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/node.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodedefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodepriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ntfy.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/proc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/procpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/reg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rms_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmstypes.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/services.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/std.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/sync.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/util.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/utildefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/uuidutil.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmddeh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdio.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+ create mode 100644 drivers/dsp/bridge/Kbuild
+ create mode 100644 drivers/dsp/bridge/Kconfig
+ create mode 100644 drivers/dsp/bridge/dynload/cload.c
+ create mode 100644 drivers/dsp/bridge/dynload/dlclasses_hdr.h
+ create mode 100644 drivers/dsp/bridge/dynload/dload_internal.h
+ create mode 100644 drivers/dsp/bridge/dynload/doff.h
+ create mode 100644 drivers/dsp/bridge/dynload/getsection.c
+ create mode 100644 drivers/dsp/bridge/dynload/header.h
+ create mode 100644 drivers/dsp/bridge/dynload/module_list.h
+ create mode 100644 drivers/dsp/bridge/dynload/params.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc.c
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table_c6000.c
+ create mode 100644 drivers/dsp/bridge/gen/_gt_para.c
+ create mode 100644 drivers/dsp/bridge/gen/gb.c
+ create mode 100644 drivers/dsp/bridge/gen/gh.c
+ create mode 100644 drivers/dsp/bridge/gen/gs.c
+ create mode 100644 drivers/dsp/bridge/gen/gt.c
+ create mode 100644 drivers/dsp/bridge/gen/uuidutil.c
+ create mode 100644 drivers/dsp/bridge/hw/EasiGlobal.h
+ create mode 100644 drivers/dsp/bridge/hw/GlobalTypes.h
+ create mode 100644 drivers/dsp/bridge/hw/IPIAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/IVA2RegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MMUAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MMURegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_defs.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.h
+ create mode 100644 drivers/dsp/bridge/pmgr/chnl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/chnlobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/cmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/cod.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbll.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dev.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/io.c
+ create mode 100644 drivers/dsp/bridge/pmgr/ioobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/msg.c
+ create mode 100644 drivers/dsp/bridge/pmgr/msgobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/wcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/disp.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
+ create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/node.c
+ create mode 100644 drivers/dsp/bridge/rmgr/proc.c
+ create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
+ create mode 100644 drivers/dsp/bridge/rmgr/strm.c
+ create mode 100644 drivers/dsp/bridge/services/cfg.c
+ create mode 100644 drivers/dsp/bridge/services/clk.c
+ create mode 100644 drivers/dsp/bridge/services/csl.c
+ create mode 100644 drivers/dsp/bridge/services/dbg.c
+ create mode 100644 drivers/dsp/bridge/services/dpc.c
+ create mode 100644 drivers/dsp/bridge/services/kfile.c
+ create mode 100644 drivers/dsp/bridge/services/list.c
+ create mode 100644 drivers/dsp/bridge/services/mem.c
+ create mode 100644 drivers/dsp/bridge/services/ntfy.c
+ create mode 100644 drivers/dsp/bridge/services/reg.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.h
+ create mode 100644 drivers/dsp/bridge/services/services.c
+ create mode 100644 drivers/dsp/bridge/services/sync.c
+ create mode 100644 drivers/dsp/bridge/wmd/_cmm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_deh.h
+ create mode 100644 drivers/dsp/bridge/wmd/_msg_sm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_mmu.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_pwr.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_util.h
+ create mode 100644 drivers/dsp/bridge/wmd/chnl_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/io_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.h
+ create mode 100644 drivers/dsp/bridge/wmd/msg_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.h
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/ue_deh.c
+
+diff --git a/Documentation/tidspbridge/README b/Documentation/tidspbridge/README
+new file mode 100644
+index 0000000..df6d371
+--- /dev/null
++++ b/Documentation/tidspbridge/README
+@@ -0,0 +1,70 @@
++ Linux DSP/BIOS Bridge release
++
++DSP/BIOS Bridge overview
++========================
++
++DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more
++attached DSPs. The GPP is considered the master or "host" processor, and the
++attached DSPs are processing resources that can be utilized by applications
++and drivers running on the GPP.
++
++The abstraction that DSP/BIOS Bridge supplies, is a direct link between a GPP
++program and a DSP task. This communication link is partitioned into two
++types of sub-links: messaging (short, fixed-length packets) and data
++streaming (multiple, large buffers). Each sub-link operates independently,
++and features in-order delivery of data, meaning that messages are delivered
++in the order they were submitted to the message link, and stream buffers are
++delivered in the order they were submitted to the stream link.
++
++In addition, a GPP client can specify what inputs and outputs a DSP task
++uses. DSP tasks typically use message objects for passing control and status
++information and stream objects for efficient streaming of real-time data.
++
++GPP Software Architecture
++=========================
++
++A GPP application communicates with its associated DSP task running on the
++DSP subsystem using the DSP/BIOS Bridge API. For example, a GPP audio
++application can use the API to pass messages to a DSP task that is managing
++data flowing from analog-to-digital converters (ADCs) to digital-to-analog
++converters (DACs).
++
++From the perspective of the GPP OS, the DSP is treated as just another
++peripheral device. Most high level GPP OS typically support a device driver
++model, whereby applications can safely access and share a hardware peripheral
++through standard driver interfaces. Therefore, to allow multiple GPP
++applications to share access to the DSP, the GPP side of DSP/BIOS Bridge
++implements a device driver for the DSP.
++
++Since driver interfaces are not always standard across GPP OS, and to provide
++some level of interoperability of application code using DSP/BIOS Bridge
++between GPP OS, DSP/BIOS Bridge provides a standard library of APIs which
++wrap calls into the device driver. So, rather than calling GPP OS specific
++driver interfaces, applications (and even other device drivers) can use the
++standard API library directly.
++
++DSP Software Architecture
++=========================
++
++For DSP/BIOS, DSP/BIOS Bridge adds a device-independent streaming I/O (STRM)
++interface, a messaging interface (NODE), and a Resource Manager (RM) Server.
++The RM Server runs as a task of DSP/BIOS and is subservient to commands
++and queries from the GPP. It executes commands to start and stop DSP signal
++processing nodes in response to GPP programs making requests through the
++(GPP-side) API.
++
++DSP tasks started by the RM Server are similar to any other DSP task with two
++important differences: they must follow a specific task model consisting of
++three C-callable functions (node create, execute, and delete), with specific
++sets of arguments, and they have a pre-defined task environment established
++by the RM Server.
++
++Tasks started by the RM Server communicate using the STRM and NODE interfaces
++and act as servers for their corresponding GPP clients, performing signal
++processing functions as requested by messages sent by their GPP client.
++Typically, a DSP task moves data from source devices to sink devices using
++device independent I/O streams, performing application-specific processing
++and transformations on the data while it is moved. For example, an audio
++task might perform audio decompression (ADPCM, MPEG, CELP) on data received
++from a GPP audio driver and then send the decompressed linear samples to a
++digital-to-analog converter.
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index e7fb201..2060772 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1331,6 +1331,8 @@ if ARCH_OMAP
+ source "drivers/cbus/Kconfig"
+ endif
+
++source "drivers/dsp/bridge/Kconfig"
++
+ endmenu
+
+ source "fs/Kconfig"
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 9b270d8..e52e01e 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -34,6 +34,8 @@ obj-$(CONFIG_OMAP_SMARTREFLEX) += smartreflex.o
+ obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
+ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+
++obj-$(CONFIG_MPU_BRIDGE) += dspbridge.o
++
+ # DSP
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+ mailbox_mach-objs := mailbox.o
+diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
+new file mode 100644
+index 0000000..221e8ff
+--- /dev/null
++++ b/arch/arm/mach-omap2/dspbridge.c
+@@ -0,0 +1,74 @@
++/*
++ * TI's dspbridge platform device registration
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ * Copyright (C) 2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <dspbridge/host_os.h>
++
++static struct platform_device *dspbridge_pdev;
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++static struct dspbridge_platform_data dspbridge_pdata __initdata = {
++ .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
++ .dsp_get_opp = omap_pm_dsp_get_opp,
++ .cpu_set_freq = omap_pm_cpu_set_freq,
++ .cpu_get_freq = omap_pm_cpu_get_freq,
++};
++#else
++static struct dspbridge_platform_data dspbridge_pdata;
++#endif
++
++static int __init dspbridge_init(void)
++{
++ struct platform_device *pdev;
++ int err = -ENOMEM;
++ struct dspbridge_platform_data *pdata = &dspbridge_pdata;
++
++ pdata->phys_mempool_base = dspbridge_get_mempool_base();
++
++ if (pdata->phys_mempool_base) {
++ pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++ pr_info("%s: %x bytes @ %x\n", __func__,
++ pdata->phys_mempool_size, pdata->phys_mempool_base);
++ }
++
++ pdev = platform_device_alloc("C6410", -1);
++ if (!pdev)
++ goto err_out;
++
++ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
++ if (err)
++ goto err_out;
++
++ err = platform_device_add(pdev);
++ if (err)
++ goto err_out;
++
++ dspbridge_pdev = pdev;
++ return 0;
++
++err_out:
++ platform_device_put(pdev);
++ return err;
++}
++module_init(dspbridge_init);
++
++static void __exit dspbridge_exit(void)
++{
++ platform_device_unregister(dspbridge_pdev);
++}
++module_exit(dspbridge_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU");
++MODULE_DESCRIPTION("TI's dspbridge platform device registration");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index a04e3ee..40488ae 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -38,6 +38,8 @@
+ #include <mach/clockdomain.h>
+ #include "clockdomains.h"
+
++#include <dspbridge/host_os.h>
++
+ /*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+@@ -192,6 +194,7 @@ void __init omap2_map_common_io(void)
+ omap2_check_revision();
+ omap_sram_init();
+ omapfb_reserve_sdram();
++ dspbridge_reserve_sdram();
+ }
+
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
+index 6b742a8..e66dd8a 100644
+--- a/arch/arm/plat-omap/devices.c
++++ b/arch/arm/plat-omap/devices.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/i2c/menelaus.h>
++#include <linux/bootmem.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -89,6 +90,33 @@ EXPORT_SYMBOL(dsp_kfunc_device_register);
+ static inline void omap_init_dsp(void) { }
+ #endif /* CONFIG_OMAP_DSP */
+
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++
++static unsigned long dspbridge_phys_mempool_base;
++
++void dspbridge_reserve_sdram(void)
++{
++ void *va;
++ unsigned long size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++
++ if (!size)
++ return;
++
++ va = __alloc_bootmem_nopanic(size, SZ_1M, 0);
++ if (!va) {
++ pr_err("%s: Failed to bootmem allocation(%lu bytes)\n",
++ __func__, size);
++ return;
++ }
++ dspbridge_phys_mempool_base = virt_to_phys(va);
++}
++
++unsigned long dspbridge_get_mempool_base(void)
++{
++ return dspbridge_phys_mempool_base;
++}
++EXPORT_SYMBOL(dspbridge_get_mempool_base);
++#endif
+ /*-------------------------------------------------------------------------*/
+ #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+new file mode 100644
+index 0000000..28af799
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+@@ -0,0 +1,212 @@
++/*
++ * _chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _chnl_sm.h ========
++ * Description:
++ * Private header file defining channel manager and channel objects for
++ * a shared memory channel driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ * Shared between the modules implementing the shared memory channel class
++ * library.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc Removed legacy PERF code.
++ *! 12-Jan-2002 ag Removed unused gppReqIO & ddmaChnlId DDMA fields.
++ *! Added zero-copy chnl descriptor array: zchnldesc.
++ *! 21-Dec-2001 ag Moved descPaGpp to private chnl obj from chnl descriptor.
++ *! 20-May-2001 ag/jeh Removed fShmSyms field from CHNL_MGR.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 26-Oct-2000 jeh Added arg and resvd to SHM control structure. Added dwArg
++ *! to CHNL_IRP.
++ *! 16-Oct-2000 jeh Removed #ifdef DEBUG from around channel object's cIOCs
++ *! field, added cIOReqs.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 03-Nov-1999 ag: Added szEventName[] to CHNL object for name event support.
++ *! 02-Nov-1999 ag: _SHM_BEG & _END Syms from COFF now used for IO and SM CLASS.
++ *! 27-Oct-1999 jeh Define SHM structure to work for 16-bit targets.
++ *! 25-May-1999 jg: Added target side symbol names for share memory buffer
++ *! 03-Jan-1997 gp: Added fSharedIRQ field.
++ *! 22-Oct-1996 gp: Made dwProcessID a handle.
++ *! 09-Sep-1996 gp: Added dwProcessID field to CHNL_OBJECT.
++ *! 13-Aug-1996 gp: Created.
++ */
++
++#ifndef _CHNL_SM_
++#define _CHNL_SM_
++
++#include <dspbridge/wcd.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dpc.h>
++
++#include <dspbridge/list.h>
++#include <dspbridge/ntfy.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of shared memory buffer. They are defined in the *cfg.cmd file by
++ * cdb code.
++ */
++#define CHNL_SHARED_BUFFER_BASE_SYM "_SHM_BEG"
++#define CHNL_SHARED_BUFFER_LIMIT_SYM "_SHM_END"
++#define BRIDGEINIT_BIOSGPTIMER "_BRIDGEINIT_BIOSGPTIMER"
++#define BRIDGEINIT_LOADMON_GPTIMER "_BRIDGEINIT_LOADMON_GPTIMER"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++#define MAXOPPS 16
++
++struct oppTableEntry {
++ u32 voltage;
++ u32 frequency;
++ u32 minFreq;
++ u32 maxFreq;
++} ;
++
++struct oppStruct {
++ u32 currOppPt;
++ u32 numOppPts;
++ struct oppTableEntry oppPoint[MAXOPPS];
++} ;
++
++/* Request to MPU */
++struct oppRqstStruct {
++ u32 rqstDspFreq;
++ u32 rqstOppPt;
++};
++
++/* Info to MPU */
++struct loadMonStruct {
++ u32 currDspLoad;
++ u32 currDspFreq;
++ u32 predDspLoad;
++ u32 predDspFreq;
++};
++
++ enum SHM_DESCTYPE {
++ SHM_CURROPP = 0,
++ SHM_OPPINFO = 1,
++ SHM_GETOPP = 2, /* Get DSP requested OPP info */
++ } ;
++
++/* Structure in shared between DSP and PC for communication.*/
++ struct SHM {
++ u32 dspFreeMask; /* Written by DSP, read by PC. */
++ u32 hostFreeMask; /* Written by PC, read by DSP */
++
++ u32 inputFull; /* Input channel has unread data. */
++ u32 inputId; /* Channel for which input is available. */
++ u32 inputSize; /* Size of data block (in DSP words). */
++
++ u32 outputFull; /* Output channel has unread data. */
++ u32 outputId; /* Channel for which output is available. */
++ u32 outputSize; /* Size of data block (in DSP words). */
++
++ u32 arg; /* Arg for Issue/Reclaim (23 bits for 55x). */
++ u32 resvd; /* Keep structure size even for 32-bit DSPs */
++
++ /* Operating Point structure */
++ struct oppStruct oppTableStruct;
++ /* Operating Point Request structure */
++ struct oppRqstStruct oppRequest;
++ /* load monitor information structure*/
++ struct loadMonStruct loadMonInfo;
++ char dummy[184]; /* padding to 256 byte boundary */
++ u32 shm_dbg_var[64]; /* shared memory debug variables */
++ } ;
++
++ /* Channel Manager: only one created per board: */
++ struct CHNL_MGR {
++ u32 dwSignature; /* Used for object validation */
++ /* Function interface to WMD */
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr; /* IO manager */
++ /* Device this board represents */
++ struct DEV_OBJECT *hDevObject;
++
++ /* These fields initialized in WMD_CHNL_Create(): */
++ u32 dwOutputMask; /* Host output channels w/ full buffers */
++ u32 dwLastOutput; /* Last output channel fired from DPC */
++ /* Critical section object handle */
++ struct SYNC_CSOBJECT *hCSObj;
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u32 cChannels; /* Total number of channels */
++ u32 cOpenChannels; /* Total number of open channels */
++ struct CHNL_OBJECT **apChannel; /* Array of channels */
++ u32 dwType; /* Type of channel class library */
++ /* If no SHM syms, return for CHNL_Open */
++ DSP_STATUS chnlOpenStatus;
++ } ;
++
++/*
++ * Channel: up to CHNL_MAXCHANNELS per board or if DSP-DMA supported then
++ * up to CHNL_MAXCHANNELS + CHNL_MAXDDMACHNLS per board.
++ */
++ struct CHNL_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Pointer back to channel manager */
++ struct CHNL_MGR *pChnlMgr;
++ u32 uId; /* Channel id */
++ u32 dwState; /* Current channel state */
++ u32 uMode; /* Chnl mode and attributes */
++ /* Chnl I/O completion event (user mode) */
++ HANDLE hUserEvent;
++ /* Abstract syncronization object */
++ struct SYNC_OBJECT *hSyncEvent;
++ /* Name of Sync event */
++ char szEventName[SYNC_MAXNAMELENGTH + 1];
++ u32 hProcess; /* Process which created this channel */
++ u32 pCBArg; /* Argument to use with callback */
++ struct LST_LIST *pIORequests; /* List of IOR's to driver */
++ s32 cIOCs; /* Number of IOC's in queue */
++ s32 cIOReqs; /* Number of IORequests in queue */
++ s32 cChirps; /* Initial number of free Irps */
++ /* List of IOC's from driver */
++ struct LST_LIST *pIOCompletions;
++ struct LST_LIST *pFreeList; /* List of free Irps */
++ struct NTFY_OBJECT *hNtfy;
++ u32 cBytesMoved; /* Total number of bytes transfered */
++
++ /* For DSP-DMA */
++
++ /* Type of chnl transport:CHNL_[PCPY][DDMA] */
++ u32 uChnlType;
++ } ;
++
++/* I/O Request/completion packet: */
++ struct CHNL_IRP {
++ struct LST_ELEM link; /* Link to next CHIRP in queue. */
++ /* Buffer to be filled/emptied. (User) */
++ u8 *pHostUserBuf;
++ /* Buffer to be filled/emptied. (System) */
++ u8 *pHostSysBuf;
++ u32 dwArg; /* Issue/Reclaim argument. */
++ u32 uDspAddr; /* Transfer address on DSP side. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size when allocated. */
++ u32 status; /* Status of IO completion. */
++ } ;
++
++#endif /* _CHNL_SM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/_dcd.h b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+new file mode 100644
+index 0000000..b6a8d9e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+@@ -0,0 +1,187 @@
++/*
++ * _dcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _dcd.h ========
++ * Description:
++ * Includes the wrapper functions called directly by the
++ * DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ * Notes:
++ * Compiled with CDECL calling convention.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 30-Jan-2002 ag Renamed CMMWRAP_AllocBuf to CMMWRAP_CallocBuf.
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data to acquire PERF stats.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 10-Oct-2000 ag: Added user CMM wrappers.
++ *! 04-Aug-2000 rr: MEMWRAP and UTIL_Wrap added.
++ *! 27-Jul-2000 rr: NODEWRAP, STRMWRAP added.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 03-Dec-1999 rr: WCD_InitComplete2 enabled for BRD_AutoStart.
++ *! 09-Nov-1999 kc: Added MEMRY.
++ *! 02-Nov-1999 ag: Added CHNL.
++ *! 08-Oct-1999 rr: Utilwrap_Testdll fxn added
++ *! 24-Sep-1999 rr: header changed from _wcd.h to _dcd.h
++ *! 09-Sep-1997 gp: Created.
++ */
++
++#ifndef _WCD_
++#define _WCD_
++
++#include <dspbridge/wcdioctl.h>
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ * Parameters:
++ * cmd: IOCTL id, base 0.
++ * args: Argument structure.
++ * pResult:
++ * Returns:
++ * DSP_SOK if command called; DSP_EINVALIDARG if command not in IOCTL
++ * table.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_CallDevIOCtl(unsigned int cmd,
++ union Trapped_Args *args,
++ u32 *pResult);
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Initialize WCD modules, and export WCD services to WMD's.
++ * This procedure is called when the class driver is loaded.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool WCD_Init(void);
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init(void) or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_InitComplete2(void);
++
++/*
++ * ======== WCD_Exit ========
++ * Purpose:
++ * Exit all modules initialized in WCD_Init(void).
++ * This procedure is called when the class driver is unloaded.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * WCD_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in WCD_Init(void) are freed.
++ */
++ extern void WCD_Exit(void);
++
++/* MGR wrapper functions */
++ extern u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_RegisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_UnregisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args);
++
++#ifndef RES_CLEANUP_DISABLE
++ extern u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args);
++#endif
++
++
++/* CPRC (Processor) wrapper Functions */
++ extern u32 PROCWRAP_Attach(union Trapped_Args *args);
++ extern u32 PROCWRAP_Ctrl(union Trapped_Args *args);
++ extern u32 PROCWRAP_Detach(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumResources(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetState(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetTrace(union Trapped_Args *args);
++ extern u32 PROCWRAP_Load(union Trapped_Args *args);
++ extern u32 PROCWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 PROCWRAP_Start(union Trapped_Args *args);
++ extern u32 PROCWRAP_ReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Map(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnMap(union Trapped_Args *args);
++ extern u32 PROCWRAP_FlushMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Stop(union Trapped_Args *args);
++ extern u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args);
++
++/* NODE wrapper functions */
++ extern u32 NODEWRAP_Allocate(union Trapped_Args *args);
++ extern u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_ChangePriority(union Trapped_Args *args);
++ extern u32 NODEWRAP_Connect(union Trapped_Args *args);
++ extern u32 NODEWRAP_Create(union Trapped_Args *args);
++ extern u32 NODEWRAP_Delete(union Trapped_Args *args);
++ extern u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetAttr(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_Pause(union Trapped_Args *args);
++ extern u32 NODEWRAP_PutMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 NODEWRAP_Run(union Trapped_Args *args);
++ extern u32 NODEWRAP_Terminate(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args);
++
++/* STRM wrapper functions */
++ extern u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_Close(union Trapped_Args *args);
++ extern u32 STRMWRAP_FreeBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetEventHandle(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetInfo(union Trapped_Args *args);
++ extern u32 STRMWRAP_Idle(union Trapped_Args *args);
++ extern u32 STRMWRAP_Issue(union Trapped_Args *args);
++ extern u32 STRMWRAP_Open(union Trapped_Args *args);
++ extern u32 STRMWRAP_Reclaim(union Trapped_Args *args);
++ extern u32 STRMWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 STRMWRAP_Select(union Trapped_Args *args);
++
++ extern u32 CMMWRAP_CallocBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_FreeBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetHandle(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetInfo(union Trapped_Args *args);
++
++#endif /* _WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/brddefs.h b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+new file mode 100644
+index 0000000..c62388c
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+@@ -0,0 +1,54 @@
++/*
++ * brddefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== brddefs.h ========
++ * Description:
++ * Global BRD constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: Comment Exec changed to Monitor
++ *! 22-Jul-1999 jeh Added BRD_LOADED state.
++ *! 26-Mar-1997 gp: Added BRD_SYNCINIT state.
++ *! 11-Dec-1996 cr: Added BRD_LASTSTATE definition.
++ *! 11-Jul-1996 gp: Added missing u32 callback argument to BRD_CALLBACK.
++ *! 10-Jun-1996 gp: Created from board.h and brd.h.
++ */
++
++#ifndef BRDDEFS_
++#define BRDDEFS_
++
++/* platform status values */
++#define BRD_STOPPED 0x0 /* No Monitor Loaded, Not running. */
++#define BRD_IDLE 0x1 /* Monitor Loaded, but suspended. */
++#define BRD_RUNNING 0x2 /* Monitor loaded, and executing. */
++#define BRD_UNKNOWN 0x3 /* Board state is indeterminate. */
++#define BRD_SYNCINIT 0x4
++#define BRD_LOADED 0x5
++#define BRD_LASTSTATE BRD_LOADED /* Set to highest legal board state. */
++#define BRD_SLEEP_TRANSITION 0x6 /* Sleep transition in progress */
++#define BRD_HIBERNATION 0x7 /* MPU initiated hibernation */
++#define BRD_RETENTION 0x8 /* Retention mode */
++#define BRD_DSP_HIBERNATION 0x9 /* DSP initiated hibernation */
++#define BRD_ERROR 0xA /* Board state is Error */
++ typedef u32 BRD_STATUS;
++
++/* BRD Object */
++ struct BRD_OBJECT;
++
++#endif /* BRDDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfg.h b/arch/arm/plat-omap/include/dspbridge/cfg.h
+new file mode 100644
+index 0000000..68db842
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfg.h
+@@ -0,0 +1,339 @@
++/*
++ * cfg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfg.h ========
++ * Purpose:
++ * PM Configuration module.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetCDVersion
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_GetPerfValue
++ * CFG_GetWMDFileName
++ * CFG_GetZLFile
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *! Revision History:
++ *! =================
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 28-Aug-2001 jeh Added CFG_GetLoaderName.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName to retrieve the DCD Dll name.
++ *! 13-Jul-2000 rr: Added CFG_GetObject & CFG_SetObject.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! CFG_GetWinBRIDGEDir/Directory,CFG_GetSearchPath removed.
++ *! 15-Jan-1998 cr: Code review cleanup.
++ *! 16-Aug-1997 cr: Added explicit cdecl identifiers.
++ *! 12-Dec-1996 gp: Moved CFG_FindInSearchPath to CSP module.
++ *! 13-Sep-1996 gp: Added CFG_GetBoardName().
++ *! 22-Jul-1996 gp: Added CFG_GetTraceStr, to retrieve an initial GT trace.
++ *! 26-Jun-1996 cr: Added CFG_FindInSearchPath.
++ *! 25-Jun-1996 cr: Added CFG_GetWinSPOXDir.
++ *! 17-Jun-1996 cr: Added CFG_GetDevNode.
++ *! 11-Jun-1996 cr: Cleaned up for code review.
++ *! 07-Jun-1996 cr: Added CFG_GetExecFile and CFG_GetZLFileName functions.
++ *! 04-Jun-1996 gp: Added AutoStart regkey and accessor function. Placed
++ *! OUT parameters in accessor function param. lists at end.
++ *! 29-May-1996 gp: Moved DEV_HDEVNODE to here and renamed CFG_HDEVNODE.
++ *! 22-May-1996 cr: Added GetHostResources, GetDSPResources, and
++ *! GetWMDFileName services.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef CFG_
++#define CFG_
++#include <dspbridge/host_os.h>
++#include <dspbridge/cfgdefs.h>
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CFG_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in CFG_Init(void) are freed.
++ */
++ extern void CFG_Exit(void);
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * pdwAutoStart: Ptr to location for 32 bit autostart mask.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: Unable to retreive resource.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwAutoStart contains autostart mask for this devnode.
++ */
++ extern DSP_STATUS CFG_GetAutoStart(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart);
++
++/*
++ * ======== CFG_GetCDVersion ========
++ * Purpose:
++ * Retrieves the version of the PM Class Driver.
++ * Parameters:
++ * pdwVersion: Ptr to u32 to contain version number upon return.
++ * Returns:
++ * DSP_SOK: Success. pdwVersion contains Class Driver version in
++ * the form: 0xAABBCCDD where AABB is Major version and
++ * CCDD is Minor.
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Success.
++ * else: *pdwVersion is NULL.
++ */
++ extern DSP_STATUS CFG_GetCDVersion(OUT u32 *pdwVersion);
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle from which to retrieve value.
++ * pdwValue: Ptr to location to store the value.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: phDevObject is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32.
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwValue);
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pDSPResTable: Ptr to a location to store the DSP resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The DSP Resource information is not
++ * available
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pDSPResTable points to a filled table of resources allocated
++ * for the specified WMD.
++ */
++ extern DSP_STATUS CFG_GetDSPResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable);
++
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrExecFile: Ptr to character buf to hold ExecFile.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: pstrExecFile is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into pstrExecFile,
++ * and *pstrExecFile contains default executable for this
++ * devnode.
++ */
++ extern DSP_STATUS CFG_GetExecFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrExecFile);
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host PC allocated resources assigned to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pHostResTable: Ptr to a location to store the host resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDPOINTER: pHostResTable is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pHostResTable points to a filled table of resources
++ * allocated for the specified WMD.
++ *
++ */
++ extern DSP_STATUS CFG_GetHostResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable);
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Driver Object handle From the Registry
++ * Parameters:
++ * pdwValue: Ptr to location to store the value.
++ * dwType Type of Object to Get
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32(non-Zero).
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType);
++
++/*
++ * ======== CFG_GetPerfValue ========
++ * Purpose:
++ * Retrieve a flag indicating whether PERF should log statistics for the
++ * PM class driver.
++ * Parameters:
++ * pfEnablePerf: Location to store flag. 0 indicates the key was
++ * not found, or had a zero value. A nonzero value
++ * means the key was found and had a nonzero value.
++ * Returns:
++ * Requires:
++ * pfEnablePerf != NULL;
++ * Ensures:
++ */
++ extern void CFG_GetPerfValue(OUT bool *pfEnablePerf);
++
++/*
++ * ======== CFG_GetWMDFileName ========
++ * Purpose:
++ * Get the mini-driver file name for a given device.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pWMDFileName: Ptr to a character buffer to hold the WMD filename.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The filename is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied
++ * into pWMDFileName.
++ *
++ */
++ extern DSP_STATUS CFG_GetWMDFileName(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pWMDFileName);
++
++/*
++ * ======== CFG_GetZLFile ========
++ * Purpose:
++ * Retreive the ZLFile, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrZLFileName: Ptr to character buf to hold ZLFileName.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDPOINTER: pstrZLFileName is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: couldn't find the ZLFileName.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into
++ * pstrZLFileName, and *pstrZLFileName contains ZLFileName
++ * for this devnode.
++ */
++ extern DSP_STATUS CFG_GetZLFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrZLFileName);
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CFG functions.
++ */
++ extern bool CFG_Init(void);
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle we are storing value with.
++ * dwValue: Arbitrary value to store.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 dwValue);
++
++/*
++ * ======== CFG_SetDrvObject ========
++ * Purpose:
++ * Store the Driver Object handle.
++ * Parameters:
++ * dwValue: Arbitrary value to store.
++ * dwType Type of Object to Store
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetObject(IN u32 dwValue, IN u32 dwType);
++
++#endif /* CFG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+new file mode 100644
+index 0000000..4f78d82
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+@@ -0,0 +1,126 @@
++/*
++ * cfgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cfgdefs.h ========
++ * Purpose:
++ * Global CFG constants and types, shared between class and mini driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* in CFG_HOSTRES.
++ *! 06-Sep-2000 jeh Added channel info to CFG_HOSTRES.
++ *! 09-May-2000 rr: CFG_HOSTRES now support multiple windows for PCI support.
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 06-Jan-2000 rr: Bus Type included in CFG_HOSTRES.
++ *! 12-Nov-1999 rr: CFG_HOSTRES member names changed.
++ *! 25-Oct-1999 rr: Modified the CFG_HOSTRES Structure
++ *! PCMCIA ISR Register/Unregister fxn removed..
++ *! New flag PCCARD introduced during compile time.
++ *! 10-Sep-1999 ww: Added PCMCIA ISR Register/Unregister fxn.
++ *! 01-Sep-1999 ag: Removed NT/95 specific fields in CFG_HOSTRES
++ *! 27-Oct-1997 cr: Updated CFG_HOSTRES struct to support 1+ IRQs per board.
++ *! 17-Sep-1997 gp: Tacked some NT config info to end of CFG_HOSTRES structure.
++ *! 12-Dec-1996 cr: Cleaned up after code review.
++ *! 14-Nov-1996 gp: Renamed from wsxcfg.h
++ *! 19-Jun-1996 cr: Created.
++ */
++
++#ifndef CFGDEFS_
++#define CFGDEFS_
++
++/* Maximum length of module search path. */
++#define CFG_MAXSEARCHPATHLEN 255
++
++/* Maximum length of general paths. */
++#define CFG_MAXPATH 255
++
++/* Host Resources: */
++#define CFG_MAXMEMREGISTERS 9
++#define CFG_MAXIOPORTS 20
++#define CFG_MAXIRQS 7
++#define CFG_MAXDMACHANNELS 7
++
++/* IRQ flag */
++#define CFG_IRQSHARED 0x01 /* IRQ can be shared */
++
++/* DSP Resources: */
++#define CFG_DSPMAXMEMTYPES 10
++#define CFG_DEFAULT_NUM_WINDOWS 1 /* We support only one window. */
++
++/* A platform-related device handle: */
++ struct CFG_DEVNODE;
++
++/*
++ * Host resource structure.
++ */
++ struct CFG_HOSTRES {
++ u32 wNumMemWindows; /* Set to default */
++ /* This is the base.memory */
++ u32 dwMemBase[CFG_MAXMEMREGISTERS]; /* SHM virtual address */
++ u32 dwMemLength[CFG_MAXMEMREGISTERS]; /* Length of the Base */
++ u32 dwMemPhys[CFG_MAXMEMREGISTERS]; /* SHM Physical address */
++ u8 bIRQRegisters; /* IRQ Number */
++ u8 bIRQAttrib; /* IRQ Attribute */
++ u32 dwOffsetForMonitor; /* The Shared memory starts from
++ * dwMemBase + this offset */
++ u32 dwBusType; /* Bus type for this device */
++ u32 dwProgBase; /* DSP ProgBase */
++ u32 dwProgLength; /* DSP ProgBase Length */
++ u32 dwRegBase; /* DSP memory mapped register base */
++ u32 dwRegLength; /* DSP Register Base Length */
++ u32 ClientHandle; /* Client Handle */
++ u32 SocketHandle; /* Socket and Function Pair */
++ u32 CardInfo; /* This will be used as a context data in
++ * in the CardRequestIRQ */
++ /*
++ * Info needed by NODE for allocating channels to communicate with RMS:
++ * dwChnlOffset: Offset of RMS channels. Lower channels are
++ * reserved.
++ * dwChnlBufSize: Size of channel buffer to send to RMS
++ * dwNumChnls: Total number of channels (including reserved).
++ */
++ u32 dwChnlOffset;
++ u32 dwChnlBufSize;
++ u32 dwNumChnls;
++ u32 dwPrmBase;
++ u32 dwCmBase;
++ u32 dwPerBase;
++ u32 dwPerPmBase;
++ u32 dwCorePmBase;
++ u32 dwWdTimerDspBase;
++ u32 dwMboxBase;
++ u32 dwDmmuBase;
++ u32 dwDipiBase;
++ u32 dwSysCtrlBase;
++ } ;
++
++ struct CFG_DSPMEMDESC {
++ u32 uMemType; /* Type of memory. */
++ u32 ulMin; /* Minimum amount of memory of this type. */
++ u32 ulMax; /* Maximum amount of memory of this type. */
++ } ;
++
++ struct CFG_DSPRES {
++ u32 uChipType; /* DSP chip type. */
++ u32 uWordSize; /* Number of bytes in a word */
++ u32 cChips; /* Number of chips. */
++ u32 cMemTypes; /* Types of memory. */
++ struct CFG_DSPMEMDESC aMemDesc[CFG_DSPMAXMEMTYPES];
++ /* DSP Memory types */
++ } ;
++
++#endif /* CFGDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl.h b/arch/arm/plat-omap/include/dspbridge/chnl.h
+new file mode 100644
+index 0000000..f39e3f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl.h
+@@ -0,0 +1,170 @@
++/*
++ * chnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.h ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a mini-driver.
++ *
++ * Public Functions:
++ * CHNL_AddIOReq
++ * CHNL_AllocBuffer
++ * CHNL_CancelIO
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_FlushIO
++ * CHNL_FreeBuffer
++ * CHNL_GetEventHandle
++ * CHNL_GetHandle
++ * CHNL_GetIOCompletion
++ * CHNL_GetId
++ * CHNL_GetMgr
++ * CHNL_GetMode
++ * CHNL_GetPosition
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * See DSP API chnl.h for more details.
++ *
++ *! Revision History:
++ *! ================
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 24-Oct-1996 gp: Move CloseOrphans into here from dspsys.
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessID() and CHNL_GetHandle().
++ *! 10-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNL_
++#define CHNL_
++
++#include <dspbridge/chnlpriv.h>
++
++/*
++ * ======== CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * CHNL_Init(void) called.
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: The I/O completion event for this channel is freed.
++ * hChnl is no longer valid.
++ */
++ extern DSP_STATUS CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: hDevObject is invalid.
++ * DSP_EINVALIDARG: cChannels is 0.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_MAXCHANNELS: This manager cannot handle this many channels.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * CHNL_E_MGREXISTS: Channel manager already exists for this device.
++ * Requires:
++ * CHNL_Init(void) called.
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Subsequent calls to CHNL_Create() for the same
++ * board without an intervening call to
++ * CHNL_Destroy() will fail.
++ */
++ extern DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * CHNL_Init(void) called.
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel.
++ * Closes each open channel.
++ * CHNL_Create may subsequently be called for the
++ * same board.
++ */
++ extern DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CHNL_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in CHNL_Init(void), are freed when the last
++ * client of CHNL calls CHNL_Exit(void).
++ */
++ extern void CHNL_Exit(void);
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool CHNL_Init(void);
++
++
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+new file mode 100644
+index 0000000..789b9bd
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+@@ -0,0 +1,168 @@
++/*
++ * chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.h ========
++ * Description:
++ * Prototypes for channel lower edge functions for a WinBRIDGE mini driver
++ * implementing data transfer via shared memory.
++ *
++ * Public Functions:
++ * CHNLSM_DisableInterrupt;
++ * CHNLSM_EnableInterrupt;
++ * CHNLSM_ISR;
++ * CHNLSM_Read;
++ * CHNLSM_UpdateSHMLength;
++ * CHNLSM_Write;
++ *
++ * Notes:
++ * These lower edge functions must be implemented by the WMD writer.
++ * Currently, CHNLSM_Read() and CHNLSM_Write() are not called, but must
++ * be defined to link.
++ *
++ */
++
++#ifndef CHNLSM_
++#define CHNLSM_
++
++#include <dspbridge/wmd.h>
++
++/*
++ * ======== CHNLSM_DisableInterrupt ========
++ * Purpose:
++ * Disable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_EnableInterrupt ========
++ * Purpose:
++ * Enable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_InterruptDSP2 ========
++ * Purpose:
++ * Set interrupt value & send an interrupt to the DSP processor(s).
++ * This is typicaly used when mailbox interrupt mechanisms allow data
++ * to be associated with interrupt such as for OMAP's CMD/DATA regs.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * wMbVal: Value associated with interrupt(e.g. mailbox value).
++ * Returns:
++ * DSP_SOK: Interrupt sent;
++ * else: Unable to send interrupt.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT*
++ hDevContext, u16 wMbVal);
++
++/*
++ * ======== CHNLSM_ISR ========
++ * Purpose:
++ * Mini-driver's ISR, called by WCD when the board interrupts the host.
++ * Parameters:
++ * hDevContext: Handle to the mini-driver defined device info.
++ * pfSchedDPC: Set to TRUE to schedule a deferred procedure call
++ * to advance the channel protocol. The channel class
++ * library will call the WMD's CHNLSM_DPC routine during
++ * its own DPC, before dispatching I/O.
++ * The channel class library should ignore *pfSchedDPC when
++ * CHNLSM_ISR returns FALSE.
++ * pwMBRegVal: Value of mailbox register.
++ * Returns:
++ * TRUE if this interrupt is was generated by the DSP board.
++ * FALSE otherwise.
++ * Requires:
++ * Interrupts to the host processor are disabled on entry.
++ * Must only call functions which are in page locked memory.
++ * Must only call asynchronous OS services.
++ * The EOI for this interrupt has already been sent to the PIC.
++ * Ensures:
++ * If the interrupt is *not* shared, this routine must return TRUE.
++ */
++ extern bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT bool *pfSchedDPC,
++ OUT u16 *pwIntrVal);
++
++/*
++ * ======== CHNLSM_Read ========
++ * Purpose:
++ * Read data from DSP board memory into a Host buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++/*
++ * ======== CHNLSM_UpdateSHMLength ========
++ * Purpose:
++ * Allow the minidriver a chance to override the SHM length as reported
++ * to the mini driver (chnl_sm.lib) by Windows Plug and Play.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pSHMLength: Pointer to size of SHM window (in DSP words).
++ * Returns:
++ * TRUE if pSHMLength updated; FALSE otherwise.
++ * Requires:
++ * pSHMLength != NULL.
++ * Ensures:
++ * No more than sizeof(u32) bytes written to *pSHMLength
++ */
++ extern bool CHNLSM_UpdateSHMLength(struct WMD_DEV_CONTEXT *hDevContext,
++ IN OUT u32 *pSHMLength);
++
++/*
++ * ======== CHNLSM_Write ========
++ * Purpose:
++ * Write data from a Host buffer to DSP board memory.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Source).
++ * dwDSPAddr: Address on DSP board (Destination).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++#endif /* CHNLSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnldefs.h b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+new file mode 100644
+index 0000000..9f59229
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+@@ -0,0 +1,92 @@
++/*
++ * chnldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnldefs.h ========
++ * Purpose:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Jan-2002 ag Added cBufSize to IOC.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 02-Dec-1999 ag: Added new chnl attribute pstrEventName.
++ *! 12-Nov-1999 kc: Enabled hEvent attribute for tests.
++ *! 01-Nov-1999 ag: hEvent attribute not supported(yet).
++ *! 16-Jan-1997 gp: Moved private stuff into chnlpriv.h
++ *! 14-Jan-1997 gp: Updated based on code review feedback:
++ *! Removed CHNL_MODENOWAIT, CHNL_MODEDIRECT,
++ *! 03-Jan-1997 gp: Added channel class library types.
++ *! 14-Dec-1996 gp: Moved uChnlId field from CHNL_ATTRS to CHNL_Open().
++ *! 10-Dec-1996 gp: Added CHNL_IsTimedOut() macro.
++ *! 14-Nov-1996 gp: Renamed from wsxchnl.h.
++ *! 09-Sep-1996 gp: Added hReserved2 field to CHNL_ATTRS. Updated CHNL_INFO.
++ *! 10-Jul-1996 gp: Created from channel.h.
++ */
++
++#ifndef CHNLDEFS_
++#define CHNLDEFS_
++
++/* Channel id option. */
++#define CHNL_PICKFREE (~0UL) /* Let manager pick a free channel. */
++
++/* Channel manager limits: */
++#define CHNL_INITIOREQS 4 /* Default # of I/O requests. */
++
++/* Channel modes */
++#define CHNL_MODETODSP 0x0000 /* Data streaming to the DSP. */
++#define CHNL_MODEFROMDSP 0x0001 /* Data streaming from the DSP. */
++
++/* GetIOCompletion flags */
++#define CHNL_IOCINFINITE 0xffffffff /* Wait forever for IO completion. */
++#define CHNL_IOCNOWAIT 0x0 /* Dequeue an IOC, if available. */
++
++/* IO Completion Record status: */
++#define CHNL_IOCSTATCOMPLETE 0x0000 /* IO Completed. */
++#define CHNL_IOCSTATCANCEL 0x0002 /* IO was cancelled */
++#define CHNL_IOCSTATTIMEOUT 0x0008 /* Wait for IOC timed out. */
++#define CHNL_IOCSTATEOS 0x8000 /* End Of Stream reached. */
++
++/* Macros for checking I/O Completion status: */
++#define CHNL_IsEOS(ioc) (ioc.status & CHNL_IOCSTATEOS)
++#define CHNL_IsIOComplete(ioc) (!(ioc.status & ~CHNL_IOCSTATEOS))
++#define CHNL_IsIOCancelled(ioc) (ioc.status & CHNL_IOCSTATCANCEL)
++#define CHNL_IsTimedOut(ioc) (ioc.status & CHNL_IOCSTATTIMEOUT)
++
++/* CHNL types: */
++ typedef u32 CHNL_MODE; /* Channel transfer mode. */
++
++/* Channel attributes: */
++ struct CHNL_ATTRS {
++ u32 uIOReqs; /* Max # of preallocated I/O requests. */
++ HANDLE hEvent; /* User supplied auto-reset event object. */
++ char *pstrEventName; /* Ptr to name of user event object. */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++
++ };
++
++/* I/O completion record: */
++ struct CHNL_IOC {
++ void *pBuf; /* Buffer to be filled/emptied. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size in bytes */
++ u32 status; /* Status of IO completion. */
++ u32 dwArg; /* User argument associated with pBuf. */
++ } ;
++
++#endif /* CHNLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnlpriv.h b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+new file mode 100644
+index 0000000..fdcda24
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+@@ -0,0 +1,136 @@
++/*
++ * chnlpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlpriv.h ========
++ * Description:
++ * Private channel header shared between DSPSYS, WCD and WMD modules.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Jan-2002 ag Added cChannels(total # of chnls) to CHNL_MGRINFO struct.
++ *! Added private CHNL_[PCPY][ZCPY][DDMA].
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory from CHNL_MGRATTRS, since these
++ *! now belong to IO_ATTRS.
++ *! 21-Jan-2000 ag: Code review comments added.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 11-Dec-1999 ag: Added CHNL_MAXLOCKPAGES for CHNL_PrepareBuffer().
++ *! 04-Dec-1999 ag: Added CHNL_MAXEVTNAMELEN for i/o compl named event support.
++ *! 01-Nov-1999 ag: CHNL_MAXCHANNELS set to 16 for 16-bit DSPs.
++ *! 27-Oct-1997 cr: Expanded CHNL_MAXIRQ from 0x0f to 0xff.
++ *! 16-Jan-1997 gp: Moved symbols into here from chnldefs.h.
++ *! 03-Jan-1997 gp: Added CHNL_MAXIRQ define.
++ *! 09-Dec-1996 gp: Removed CHNL_STATEIDLE.
++ *! 15-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNLPRIV_
++#define CHNLPRIV_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/sync.h>
++
++/* CHNL Object validation signatures: */
++#define CHNL_MGRSIGNATURE 0x52474D43 /* "CMGR" (in reverse). */
++#define CHNL_SIGNATURE 0x4C4E4843 /* "CHNL" (in reverse). */
++
++/* Channel manager limits: */
++#define CHNL_MAXCHANNELS 32 /* Max channels available per transport */
++
++
++/*
++ * Trans port channel Id definitions:(must match dsp-side).
++ *
++ * For CHNL_MAXCHANNELS = 16:
++ *
++ * ChnlIds:
++ * 0-15 (PCPY) - transport 0)
++ * 16-31 (DDMA) - transport 1)
++ * 32-47 (ZCPY) - transport 2)
++ */
++#define CHNL_PCPY 0 /* Proc-copy transport 0 */
++
++#define CHNL_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* The following modes are private: */
++#define CHNL_MODEUSEREVENT 0x1000 /* User provided the channel event. */
++#define CHNL_MODEMASK 0x1001
++
++/* Higher level channel states: */
++#define CHNL_STATEREADY 0x0000 /* Channel ready for I/O. */
++#define CHNL_STATECANCEL 0x0001 /* I/O was cancelled. */
++#define CHNL_STATEEOS 0x0002 /* End Of Stream reached. */
++
++/* Determine if user supplied an event for this channel: */
++#define CHNL_IsUserEvent(mode) (mode & CHNL_MODEUSEREVENT)
++
++/* Macros for checking mode: */
++#define CHNL_IsInput(mode) (mode & CHNL_MODEFROMDSP)
++#define CHNL_IsOutput(mode) (!CHNL_IsInput(mode))
++
++/* Types of channel class libraries: */
++#define CHNL_TYPESM 1 /* Shared memory driver. */
++#define CHNL_TYPEBM 2 /* Bus Mastering driver. */
++
++/* Max string length of channel I/O completion event name - change if needed */
++#define CHNL_MAXEVTNAMELEN 32
++
++/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
++#define CHNL_MAXLOCKPAGES 64
++
++/* Channel info. */
++ struct CHNL_INFO {
++ struct CHNL_MGR *hChnlMgr; /* Owning channel manager. */
++ u32 dwID; /* Channel ID. */
++ HANDLE hEvent; /* Channel I/O completion event. */
++ /*Abstraction of I/O completion event.*/
++ struct SYNC_OBJECT *hSyncEvent;
++ u32 dwMode; /* Channel mode. */
++ u32 dwState; /* Current channel state. */
++ u32 cPosition; /* Total bytes transferred. */
++ u32 cIOCs; /* Number of IOCs in queue. */
++ u32 cIOReqs; /* Number of IO Requests in queue. */
++ u32 hProcess; /* Process owning this channel. */
++ /*
++ * Name of channel I/O completion event. Not required in Linux
++ */
++ char szEventName[CHNL_MAXEVTNAMELEN + 1];
++ } ;
++
++/* Channel manager info: */
++ struct CHNL_MGRINFO {
++ u32 dwType; /* Type of channel class library. */
++ /* Channel handle, given the channel id. */
++ struct CHNL_OBJECT *hChnl;
++ u32 cOpenChannels; /* Number of open channels. */
++ u32 cChannels; /* total # of chnls supported */
++ } ;
++
++/* Channel Manager Attrs: */
++ struct CHNL_MGRATTRS {
++ /* Max number of channels this manager can use. */
++ u32 cChannels;
++ u32 uWordSize; /* DSP Word size. */
++ } ;
++
++#endif /* CHNLPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/clk.h b/arch/arm/plat-omap/include/dspbridge/clk.h
+new file mode 100644
+index 0000000..4a23dab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/clk.h
+@@ -0,0 +1,155 @@
++/*
++ * clk.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.h ========
++ * Purpose: Provides Clock functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: Moved all clock functions from sync module.
++ */
++
++#ifndef _CLK_H
++#define _CLK_H
++
++ /* Generic TIMER object: */
++ struct TIMER_OBJECT;
++ enum SERVICES_ClkId {
++ SERVICESCLK_iva2_ck = 0,
++ SERVICESCLK_mailbox_ick,
++ SERVICESCLK_gpt5_fck,
++ SERVICESCLK_gpt5_ick,
++ SERVICESCLK_gpt6_fck,
++ SERVICESCLK_gpt6_ick,
++ SERVICESCLK_gpt7_fck,
++ SERVICESCLK_gpt7_ick,
++ SERVICESCLK_gpt8_fck,
++ SERVICESCLK_gpt8_ick,
++ SERVICESCLK_wdt3_fck,
++ SERVICESCLK_wdt3_ick,
++ SERVICESCLK_mcbsp1_fck,
++ SERVICESCLK_mcbsp1_ick,
++ SERVICESCLK_mcbsp2_fck,
++ SERVICESCLK_mcbsp2_ick,
++ SERVICESCLK_mcbsp3_fck,
++ SERVICESCLK_mcbsp3_ick,
++ SERVICESCLK_mcbsp4_fck,
++ SERVICESCLK_mcbsp4_ick,
++ SERVICESCLK_mcbsp5_fck,
++ SERVICESCLK_mcbsp5_ick,
++ SERVICESCLK_ssi_fck,
++ SERVICESCLK_ssi_ick,
++ SERVICESCLK_sys_32k_ck,
++ SERVICESCLK_sys_ck,
++ SERVICESCLK_NOT_DEFINED
++ } ;
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CLK initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void CLK_Exit(void);
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initializes private state of CLK module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CLK initialized.
++ */
++ extern bool CLK_Init(void);
++
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while enabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while disabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * Get the clock rate of requested clock.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while Getting the clock rate.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id,
++ u32 *speedMhz);
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * Set the requested clock to 32KHz.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while setting the clock parent to 32KHz.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id);
++ extern void SSI_Clk_Prepare(bool FLAG);
++
++/*
++ * ======== CLK_Get_RefCnt ========
++ * Purpose:
++ * get the reference count for the clock.
++ * Parameters:
++ * Returns:
++ * s32: Reference Count for the clock.
++ * DSP_EFAIL: Error occured while getting the reference count of a clock.
++ * Requires:
++ * Ensures:
++ */
++ extern s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmm.h b/arch/arm/plat-omap/include/dspbridge/cmm.h
+new file mode 100644
+index 0000000..0df8b83
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmm.h
+@@ -0,0 +1,420 @@
++/*
++ * cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cmm.h ========
++ * Purpose:
++ * The Communication Memory Management(CMM) module provides shared memory
++ * management services for DSP/BIOS Bridge data streaming and messaging.
++ * Multiple shared memory segments can be registered with CMM. Memory is
++ * coelesced back to the appropriate pool when a buffer is freed.
++ *
++ * The CMM_Xlator[xxx] functions are used for node messaging and data
++ * streaming address translation to perform zero-copy inter-processor
++ * data transfer(GPP<->DSP). A "translator" object is created for a node or
++ * stream object that contains per thread virtual address information. This
++ * translator info is used at runtime to perform SM address translation
++ * to/from the DSP address space.
++ *
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ * CMM_XlatorAllocBuf (Note #1 below)
++ * CMM_XlatorCreate "
++ * CMM_XlatorDelete "
++ * CMM_XlatorFreeBuf "
++ * CMM_XlatorTranslate "
++ *
++ *
++ * Notes:
++ * #1: Used by Node and Stream modules for SM address translation.
++ *
++ *! Revision History:
++ *! ================
++ *! 30-Jan-2002 ag Removed unused CMM_Alloc[Free]Desc & CMM_XlatorRegisterPa.
++ *! Renamed CMM_AllocBuf() to CMM_CallocBuf().
++ *! 29-Aug-2001 ag: Added dsp virt base and size to CMM_RegisterGPPSMSeg().
++ *! 12-Aug-2001 ag: Added CMM_UnRegisterGPP[DSP}SMSeg[s]().
++ *! 05-Dec-2000 ag: Added param to CMM_XlatorDelete() to force buf cleanup.
++ *! 30-Oct-2000 ag: Added conversion factor to CMM_RegisterDSP[GPP]SMSeg().
++ *! 12-Oct-2000 ag: Added CMM_Xlator[xxx] functions.
++ *! 10-Aug-2000 ag: Created.
++ *!
++ */
++
++#ifndef CMM_
++#define CMM_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/cmmdefs.h>
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate memory buffers that can be used for data streaming or
++ * messaging.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * uSize: Number of bytes to allocate.
++ * pAttr: Attributes of memory to allocate.
++ * ppBufVA: Address of where to place VA.
++ * Returns:
++ * Pointer to a zero'd block of SM memory;
++ * NULL if memory couldn't be allocated,
++ * or if cBytes == 0,
++ * Requires:
++ * Valid hCmmMgr.
++ * CMM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ *
++ */
++ extern void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr,
++ u32 uSize, struct CMM_ATTRS *pAttrs,
++ OUT void **ppBufVA);
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ * Parameters:
++ * phCmmMgr: Location to store a communication manager handle on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Comm mem manager attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Failed to initialize critical sect sync object.
++ *
++ * Requires:
++ * CMM_Init(void) called.
++ * phCmmMgr != NULL.
++ * pMgrAttrs->ulMinBlockSize >= 4 bytes.
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Destroy the communication memory manager object.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * bForce: Force deallocation of all cmm memory immediately if set TRUE.
++ * If FALSE, and outstanding allocations will return DSP_EFAIL
++ * status.
++ * Returns:
++ * DSP_SOK: CMM object & resources deleted.
++ * DSP_EFAIL: Unable to free CMM object due to outstanding allocation.
++ * DSP_EHANDLE: Unable to free CMM due to bad handle.
++ * Requires:
++ * CMM is initialized.
++ * hCmmMgr != NULL.
++ * Ensures:
++ * Memory resources used by Cmm Mgr are freed.
++ */
++ extern DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce);
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module. Cleanup CMM module if CMM cRef reaches zero.
++ * Parameters:
++ * n/a
++ * Returns:
++ * n/a
++ * Requires:
++ * CMM is initialized.
++ * Ensures:
++ */
++ extern void CMM_Exit(void);
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * pBuf: Pointer to memory allocated by CMM_CallocBuf().
++ * ulSegId: SM segment Id used in CMM_Calloc() attrs.
++ * Set to 0 to use default segment.
++ * Returns:
++ * DSP_SOK
++ * DSP_EFAIL
++ * Requires:
++ * CMM initialized.
++ * pBufPA != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr,
++ void *pBufPA, u32 ulSegId);
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the handle to the cmm mgr for the given device obj.
++ * Parameters:
++ * hProcessor: Handle to a Processor.
++ * phCmmMgr: Location to store the shared memory mgr handle on output.
++ *
++ * Returns:
++ * DSP_SOK: Cmm Mgr opaque handle returned.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * phCmmMgr != NULL
++ * hDevObject != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr);
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current SM and VM utilization information.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * pCmmInfo: Location to store the Cmm information on output.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG Invalid input argument.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo);
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CMM initialized.
++ */
++ extern bool CMM_Init(void);
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * lpGPPBasePA: GPP Base Physical address.
++ * ulSize: Size in GPP bytes.
++ * dwDSPAddrOffset GPP PA to DSP PA Offset.
++ * cFactor: Add offset if CMM_ADDTODSPPA, sub if CMM_SUBFROMDSPPA.
++ * dwDSPBase: DSP virtual base byte address.
++ * ulDSPSize: Size of DSP segment in bytes.
++ * pulSegId: Address to store segment Id.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hCmmMgr handle.
++ * DSP_EINVALIDARG: Invalid input argument.
++ * DSP_EFAIL: Unable to register.
++ * - On success *pulSegId is a valid SM segment ID.
++ * Requires:
++ * ulSize > 0
++ * pulSegId != NULL
++ * dwGPPBasePA != 0
++ * cFactor = CMM_ADDTODSPPA || cFactor = CMM_SUBFROMDSPPA
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ unsigned int dwGPPBasePA,
++ u32 ulSize,
++ u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor,
++ unsigned int dwDSPBase,
++ u32 ulDSPSize,
++ u32 *pulSegId,
++ u32 dwGPPBaseBA);
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * Unregister the given memory segment that was previously registered
++ * by CMM_RegisterGPPSMSeg.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * ulSegId Segment identifier returned by CMM_RegisterGPPSMSeg.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG: Invalid ulSegId.
++ * DSP_EFAIL: Unable to unregister for unknown reason.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ u32 ulSegId);
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ * Purpose:
++ * Allocate the specified SM buffer and create a local memory descriptor.
++ * Place on the descriptor on the translator's HaQ (Host Alloc'd Queue).
++ * Parameters:
++ * hXlator: Handle to a Xlator object.
++ * pVaBuf: Virtual address ptr(client context)
++ * uPaSize: Size of SM memory to allocate.
++ * Returns:
++ * Ptr to valid physical address(Pa) of uPaSize bytes, NULL if failed.
++ * Requires:
++ * pVaBuf != 0.
++ * uPaSize != 0.
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pVaBuf, u32 uPaSize);
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create a translator(xlator) object used for process specific Va<->Pa
++ * address translation. Node messaging and streams use this to perform
++ * inter-processor(GPP<->DSP) zero-copy data transfer.
++ * Parameters:
++ * phXlator: Address to place handle to a new Xlator handle.
++ * hCmmMgr: Handle to Cmm Mgr associated with this translator.
++ * pXlatorAttrs: Translator attributes used for the client NODE or STREAM.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Bad input Attrs.
++ * DSP_EMEMORY: Insufficient memory(local) for requested resources.
++ * Requires:
++ * phXlator != NULL
++ * hCmmMgr != NULL
++ * pXlatorAttrs != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs);
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Delete translator resources
++ * Parameters:
++ * hXlator: handle to translator.
++ * bForce: bForce = TRUE will free XLators SM buffers/dscriptrs.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * DSP_EFAIL: Unable to free translator resources.
++ * Requires:
++ * cRefs > 0
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator,
++ bool bForce);
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free SM buffer and descriptor.
++ * Does not free client process VM.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pBufVa Virtual address of PA to free.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pBufVa);
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get process specific "translator" address info.
++ * This is used to perform fast virtaul address translation
++ * for shared memory buffers between the GPP and DSP.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr: Virtual base address of segment.
++ * ulSize: Size in bytes.
++ * uSegId: Segment identifier of SM segment(s)
++ * bSetInfo Set xlator fields if TRUE, else return base addr
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * (cRefs > 0)
++ * (pAddr != NULL)
++ * (ulSize > 0)
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator,
++ IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId,
++ bool bSetInfo);
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ * Purpose:
++ * Perform address translation VA<->PA for the specified stream or
++ * message shared memory buffer.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr address of buffer to translate.
++ * xType Type of address xlation. CMM_PA2VA or CMM_VA2PA.
++ * Returns:
++ * Valid address on success, else NULL.
++ * Requires:
++ * cRefs > 0
++ * pAddr != NULL
++ * xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA)
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator,
++ void *pAddr, enum CMM_XLATETYPE xType);
++
++#endif /* CMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmmdefs.h b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+new file mode 100644
+index 0000000..a779377
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+@@ -0,0 +1,135 @@
++/*
++ * cmmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmmdefs.h ========
++ * Purpose:
++ * Global MEM constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-2001 ag CMM_KERNMAPTYPE added for dsp<->device process addr map'n.
++ *! This allows addr conversion from drvr process <-> DSP addr.
++ *! 29-Aug-2001 ag Added CMM_ALLSEGMENTS.
++ *! 08-Dec-2000 ag Added bus address conversion type CMM_POMAPEMIF2DSPBUS.
++ *! 05-Dec-2000 ag Added default CMM_DEFLTCONVFACTOR & CMM_DEFLTDSPADDROFFSET.
++ *! 29-Oct-2000 ag Added converstion factor for GPP DSP Pa translation.
++ *! 15-Oct-2000 ag Added address translator attributes and defaults.
++ *! 12-Jul-2000 ag Created.
++ */
++
++#ifndef CMMDEFS_
++#define CMMDEFS_
++
++#include <dspbridge/list.h>
++
++/* Cmm attributes used in CMM_Create() */
++ struct CMM_MGRATTRS {
++ /* Minimum SM allocation; default 32 bytes. */
++ u32 ulMinBlockSize;
++ } ;
++
++/* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
++ struct CMM_ATTRS {
++ u32 ulSegId; /* 1,2... are SM segments. 0 is not. */
++ u32 ulAlignment; /* 0,1,2,4....ulMinBlockSize */
++ } ;
++
++/*
++ * DSPPa to GPPPa Conversion Factor.
++ *
++ * For typical platforms:
++ * converted Address = PaDSP + ( cFactor * addressToConvert).
++ */
++ enum CMM_CNVTTYPE {
++ CMM_SUBFROMDSPPA = -1,
++ /* PreOMAP is special case: not simple offset */
++ CMM_POMAPEMIF2DSPBUS = 0,
++ CMM_ADDTODSPPA = 1
++ } ;
++
++#define CMM_DEFLTDSPADDROFFSET 0
++#define CMM_DEFLTCONVFACTOR CMM_POMAPEMIF2DSPBUS /* PreOMAP DSPBUS<->EMIF */
++#define CMM_ALLSEGMENTS 0xFFFFFF /* All SegIds */
++#define CMM_MAXGPPSEGS 1 /* Maximum # of SM segs */
++
++/*
++ * SMSEGs are SM segments the DSP allocates from.
++ *
++ * This info is used by the GPP to xlate DSP allocated PAs.
++ */
++
++ struct CMM_SEGINFO {
++ u32 dwSegBasePa; /* Start Phys address of SM segment */
++ /* Total size in bytes of segment: DSP+GPP */
++ u32 ulTotalSegSize;
++ u32 dwGPPBasePA; /* Start Phys addr of Gpp SM seg */
++ u32 ulGPPSize; /* Size of Gpp SM seg in bytes */
++ u32 dwDSPBaseVA; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ /* # of current GPP allocations from this segment */
++ u32 ulInUseCnt;
++ u32 dwSegBaseVa; /* Start Virt address of SM seg */
++
++ } ;
++
++/* CMM useful information */
++ struct CMM_INFO {
++ /* # of SM segments registered with this Cmm. */
++ u32 ulNumGPPSMSegs;
++ /* Total # of allocations outstanding for CMM */
++ u32 ulTotalInUseCnt;
++ /* Min SM block size allocation from CMM_Create() */
++ u32 ulMinBlockSize;
++ /* Info per registered SM segment. */
++ struct CMM_SEGINFO segInfo[CMM_MAXGPPSEGS];
++ } ;
++
++/* XlatorCreate attributes */
++ struct CMM_XLATORATTRS {
++ u32 ulSegId; /* segment Id used for SM allocations */
++ u32 dwDSPBufs; /* # of DSP-side bufs */
++ u32 dwDSPBufSize; /* size of DSP-side bufs in GPP bytes */
++ /* Vm base address alloc'd in client process context */
++ void *pVmBase;
++ /* dwVmSize must be >= (dwMaxNumBufs * dwMaxSize) */
++ u32 dwVmSize;
++ } ;
++
++/*
++ * Cmm translation types. Use to map SM addresses to process context.
++ */
++ enum CMM_XLATETYPE {
++ CMM_VA2PA = 0, /* Virtual to GPP physical address xlation */
++ CMM_PA2VA = 1, /* GPP Physical to virtual */
++ CMM_VA2DSPPA = 2, /* Va to DSP Pa */
++ CMM_PA2DSPPA = 3, /* GPP Pa to DSP Pa */
++ CMM_DSPPA2PA = 4, /* DSP Pa to GPP Pa */
++ } ;
++
++/*
++ * Used to "map" between device process virt addr and dsp addr.
++ */
++ enum CMM_KERNMAPTYPE {
++ CMM_KERNVA2DSP = 0, /* Device process context to dsp address. */
++ CMM_DSP2KERNVA = 1, /* Dsp address to device process context. */
++ } ;
++
++ struct CMM_OBJECT;
++ struct CMM_XLATOROBJECT;
++
++#endif /* CMMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cod.h b/arch/arm/plat-omap/include/dspbridge/cod.h
+new file mode 100644
+index 0000000..a8a12c6
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cod.h
+@@ -0,0 +1,433 @@
++/*
++ * cod.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.h ========
++ * Description:
++ * Code management module for DSPs. This module provides an interface
++ * interface for loading both static and dynamic code objects onto DSP
++ * systems.
++ *
++ * Public Functions:
++ * COD_Close
++ * COD_Create
++ * COD_Delete
++ * COD_Exit
++ * COD_GetBaseLib
++ * COD_GetBaseName
++ * COD_GetLoader
++ * COD_GetSection
++ * COD_GetSymValue
++ * COD_Init
++ * COD_LoadBase
++ * COD_Open
++ * COD_OpenBase
++ * COD_ReadSection
++ * COD_UnloadSection
++ *
++ * Note:
++ * Currently, only static loading is supported.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Changed DBL to DBLL
++ *! 07-Aug-2002 jeh: Added COD_GetBaseName().
++ *! 17-Jul-2002 jeh: Added COD_Open(), COD_Close().
++ *! 15-Mar-2002 jeh: Added DBL_Flags param to COD_OpenBase().
++ *! 19-Oct-2001 jeh: Added COD_GetBaseLib, COD_GetLoader, (left in
++ *! COD_LoadSection(), COD_UnloadSection(), since they
++ *! may be needed for BridgeLite).
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 11-Jan-2001 jeh: Added COD_OpenBase.
++ *! 29-Sep-2000 kc: Added size param to COD_ReadSection for input buffer
++ *! validation.
++ *! 02-Aug-2000 kc: Added COD_ReadSection.
++ *! 04-Sep-1997 gp: Added CDECL identifier to COD_WRITEFXN (for NT)..
++ *! 18-Aug-1997 cr: Added explicit CDECL identifier.
++ *! 28-Oct-1996 gp: Added COD_GetSection.
++ *! 30-Jul-1996 gp: Added envp[] argument to COD_LoadBase().
++ *! 12-Jun-1996 gp: Moved OUT param first in _Create(). Updated _Create()
++ *! call to take a ZLFileName. Moved COD_ processor types
++ *! to CFG.
++ *! 29-May-1996 gp: Changed WCD_STATUS to DSP_STATUS. Removed include's.
++ *! 07-May-1996 mg: Created.
++ *
++ */
++
++#ifndef COD_
++#define COD_
++
++#include <dspbridge/dblldefs.h>
++
++#define COD_MAXPATHLENGTH 255
++#define COD_TRACEBEG "SYS_PUTCBEG"
++#define COD_TRACEEND "SYS_PUTCEND"
++#define COD_TRACESECT "trace"
++#define COD_TRACEBEGOLD "PUTCBEG"
++#define COD_TRACEENDOLD "PUTCEND"
++
++#define COD_NOLOAD DBLL_NOLOAD
++#define COD_SYMB DBLL_SYMB
++
++/* Flags passed to COD_Open */
++ typedef DBLL_Flags COD_FLAGS;
++
++/* COD code manager handle */
++ struct COD_MANAGER;
++
++/* COD library handle */
++ struct COD_LIBRARYOBJ;
++
++/* COD attributes */
++ struct COD_ATTRS {
++ u32 ulReserved;
++ } ;
++
++/*
++ * Function prototypes for writing memory to a DSP system, allocating
++ * and freeing DSP memory.
++ */
++ typedef u32(*COD_WRITEFXN) (void *pPrivRef, u32 ulDspAddr,
++ void *pBuf, u32 ulNumBytes,
++ u32 nMemSpace);
++
++
++/*
++ * ======== COD_Close ========
++ * Purpose:
++ * Close a library opened with COD_Open().
++ * Parameters:
++ * lib - Library handle returned by COD_Open().
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid lib.
++ * Ensures:
++ *
++ */
++ extern void COD_Close(struct COD_LIBRARYOBJ *lib);
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system. This object can be
++ * used to load an initial program image with arguments that can later
++ * be expanded with dynamically loaded object files.
++ * Symbol table information is managed by this object and can be retrieved
++ * using the COD_GetSymValue() function.
++ * Parameters:
++ * phManager: created manager object
++ * pstrZLFile: ZL DLL filename, of length < COD_MAXPATHLENGTH.
++ * attrs: attributes to be used by this object. A NULL value
++ * will cause default attrs to be used.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOZLFUNCTIONS: Could not initialize ZL functions.
++ * COD_E_ZLCREATEFAILED: ZL_Create failed.
++ * DSP_ENOTIMPL: attrs was not NULL. We don't yet support
++ * non default values of attrs.
++ * Requires:
++ * COD module initialized.
++ * pstrZLFile != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Create(OUT struct COD_MANAGER **phManager,
++ char *pstrZLFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs);
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * Ensures:
++ */
++ extern void COD_Delete(struct COD_MANAGER *hManager);
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ * Parameters:
++ * None.
++ * Returns:
++ * None.
++ * Requires:
++ * COD initialized.
++ * Ensures:
++ * Resources acquired in COD_Init(void) are freed.
++ */
++ extern void COD_Exit(void);
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * plib: location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * plib != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib);
++
++/*
++ * ======== COD_GetBaseName ========
++ * Purpose:
++ * Get the name of the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pszName: location to store library name on output.
++ * uSize: size of name buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Buffer too small.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pszName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager,
++ char *pszName, u32 uSize);
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pulEntry: pointer to location for entry point
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pulEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager,
++ u32 *pulEntry);
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBL loader.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * phLoader: location to store loader handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * phLoader != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader);
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ * Parameters:
++ * lib Library handle returned from COD_Open().
++ * pstrSect: name of the section, with or without leading "."
++ * puAddr: Location to store address.
++ * puLen: Location to store length.
++ * Returns:
++ * DSP_SOK: Success
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * puAddr != NULL;
++ * puLen != NULL;
++ * Ensures:
++ * DSP_SOK: *puAddr and *puLen contain the address and length of the
++ * section.
++ * else: *puAddr == 0 and *puLen == 0;
++ *
++ */
++ extern DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT u32 *puAddr,
++ OUT u32 *puLen);
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ * Parameters:
++ * lib: library handle returned from COD_Open().
++ * pstrSymbol: name of the symbol
++ * value: value of the symbol
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * Valid hManager.
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hManager,
++ IN char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ * Parameters:
++ * None.
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public COD functions.
++ */
++ extern bool COD_Init(void);
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * nArgc: number of arguments in the args array
++ * args: array of strings for arguments to DSP program
++ * writeFxn: board-specific function to write data to DSP system
++ * pArb: arbitrary pointer to be passed as first arg to writeFxn
++ * envp: array of environment strings for DSP exec.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * COD_E_LOADFAILED: Failed to load code onto target.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * nArgc > 0.
++ * aArgs != NULL.
++ * aArgs[0] != NULL.
++ * pfnWrite != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_LoadBase(struct COD_MANAGER *hManager,
++ u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb,
++ char *envp[]);
++
++
++/*
++ * ======== COD_Open ========
++ * Purpose:
++ * Open a library for reading sections. Does not load or set the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: COD_NOLOAD (don't load symbols) or COD_SYMB (load
++ * symbols).
++ * pLib: Handle returned that can be used in calls to COD_Close
++ * and COD_GetSection.
++ * Returns:
++ * S_OK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * flags == COD_NOLOAD || flags == COD_SYMB.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Open(struct COD_MANAGER *hMgr,
++ IN char *pszCoffPath,
++ COD_FLAGS flags,
++ OUT struct COD_LIBRARYOBJ **pLib);
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections. Does not load the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: Specifies whether to load symbols.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++extern DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags);
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ * Parameters:
++ * hManager - manager in which to search for the symbol
++ * pstrSect - name of the section, with or without leading "."
++ * pstrContent - buffer to store content of the section.
++ * Returns:
++ * DSP_SOK: on success, error code on failure
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_READFAILED: Failed to read content of code section.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * pstrContent != NULL;
++ * Ensures:
++ * DSP_SOK: *pstrContent stores the content of the named section.
++ */
++ extern DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT char *pstrContent,
++ IN u32 cContentSize);
++
++
++
++#endif /* COD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/csl.h b/arch/arm/plat-omap/include/dspbridge/csl.h
+new file mode 100644
+index 0000000..b90d6ff
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/csl.h
+@@ -0,0 +1,135 @@
++/*
++ * csl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== csl.h ========
++ * Purpose:
++ * Platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_AnsiToWchar
++ * CSL_ByteSwap
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtok
++ * CSL_Strtokr
++ * CSL_WcharToAnsi
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap().
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen().
++ *! 20-Sep-1999 ag: Added CSL_Wchar2Ansi().
++ *! 19-Jan-1998 cr: Code review cleanup (mostly documentation fixes).
++ *! 29-Dec-1997 cr: Changed CSL_lowercase to CSL_Uppercase, added
++ *! CSL_AnsiToWchar.
++ *! 30-Sep-1997 cr: Added explicit cdecl descriptors to fxn definitions.
++ *! 25-Jun-1997 cr: Added CSL_strcmp.
++ *! 12-Jun-1996 gp: Created.
++ */
++
++#ifndef CSL_
++#define CSL_
++
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CSL initialized.
++ * Ensures:
++ * Resources acquired in CSL_Init(void) are freed.
++ */
++ extern void CSL_Exit(void);
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CSL functions.
++ */
++ extern bool CSL_Init(void);
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ * Parameters:
++ * pstrNumber: Buffer to store converted string.
++ * dwNum: Number to convert.
++ * Returns:
++ * Requires:
++ * pstrNumber must be able to hold at least three characters.
++ * Ensures:
++ * pstrNumber will be null terminated.
++ */
++ extern void CSL_NumToAscii(OUT char *pstrNumber, IN u32 dwNum);
++
++
++/*
++ * ======== CSL_Strtok ========
++ * Purpose:
++ * Tokenize a NULL terminated string
++ * Parameters:
++ * ptstrSrc: pointer to string.
++ * szSeparators: pointer to a string of seperators
++ * Returns:
++ * char *
++ * Requires:
++ * CSL initialized.
++ * ptstrSrc is a valid string pointer.
++ * szSeparators is a valid string pointer.
++ * Ensures:
++ */
++ extern char *CSL_Strtok(IN char *ptstrSrc,
++ IN CONST char *szSeparators);
++
++/*
++ * ======== CSL_Strtokr ========
++ * Purpose:
++ * Re-entrant version of strtok.
++ * Parameters:
++ * pstrSrc: Pointer to string. May be NULL on subsequent calls.
++ * szSeparators: Pointer to a string of seperators
++ * ppstrCur: Location to store start of string for next call to
++ * to CSL_Strtokr.
++ * Returns:
++ * char * (the token)
++ * Requires:
++ * CSL initialized.
++ * szSeparators != NULL
++ * ppstrCur != NULL
++ * Ensures:
++ */
++ extern char *CSL_Strtokr(IN char *pstrSrc,
++ IN CONST char *szSeparators,
++ OUT char **ppstrCur);
++
++#endif /* CSL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbc.h b/arch/arm/plat-omap/include/dspbridge/dbc.h
+new file mode 100644
+index 0000000..0e6a67d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbc.h
+@@ -0,0 +1,66 @@
++/*
++ * dbc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbc.h ========
++ * Purpose:
++ * "Design by Contract" programming macros.
++ *
++ * Public Functions:
++ * DBC_Assert
++ * DBC_Require
++ * DBC_Ensure
++ *
++ * Notes:
++ * Requires that the GT->ERROR function has been defaulted to a valid
++ * error handler for the given execution environment.
++ *
++ * Does not require that GT_init() be called.
++ *
++ *! Revision History:
++ *! ================
++ *! 11-Aug-2000 ag: Removed include <dspbridge/std.h>
++ *! 22-Apr-1996 gp: Created.
++ */
++
++#ifndef DBC_
++#define DBC_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++/* Assertion Macros: */
++#if GT_TRACE
++
++#include <dspbridge/gt.h>
++
++#define DBC_Assert(exp) \
++ if (!(exp)) \
++ printk("%s, line %d: Assertion (" #exp ") failed.\n", \
++ __FILE__, __LINE__)
++#define DBC_Require DBC_Assert /* Function Precondition. */
++#define DBC_Ensure DBC_Assert /* Function Postcondition. */
++
++#else
++
++#define DBC_Assert(exp)
++#define DBC_Require(exp)
++#define DBC_Ensure(exp)
++
++#endif /* DEBUG */
++
++#endif /* DBC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcd.h b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+new file mode 100644
+index 0000000..fbc3870
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+@@ -0,0 +1,388 @@
++/*
++ * dbdcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdcd.h ========
++ * Description:
++ * Defines the DSP/BIOS Bridge Configuration Database (DCD) API.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 24-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 05-Aug-2002 jeh Added DCD_GetObjects().
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 22-Apr-2002 jeh Added DCD_GetLibraryName().
++ *! 03-Apr-2001 sg Changed error names to have DCD_E* format.
++ *! 13-Feb-2001 kc Name changed from dcdbs.h to dbdcd.h.
++ *! 12-Dec-2000 kc Added DCD_AutoUnregister.
++ *! 09-Nov-2000 kc Updated usage of DCD_EnumerateObject.
++ *! 30-Oct-2000 kc Added DCD_AutoRegister. Updated error DCD error codes.
++ *! 29-Sep-2000 kc Incorporated code review comments. See
++ *! /src/reviews/dcd_review.txt.
++ *! 26-Jul-2000 kc Created.
++ *!
++ */
++
++#ifndef DBDCD_
++#define DBDCD_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/host_os.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * This function automatically registers DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects to be registered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * This function automatically unregisters DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing
++ * DCD objects to be unregistered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto unregistration.
++ */
++ extern DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * This function creates a DCD module manager.
++ * Parameters:
++ * pszZlDllName: Pointer to a DLL name string.
++ * phDcdMgr: A pointer to a DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for DCD manager handle.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * pszZlDllName is non-NULL.
++ * phDcdMgr is non-NULL.
++ * Ensures:
++ * A DCD manager handle is created.
++ */
++ extern DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr);
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * This function destroys a DCD module manager.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid DCD manager handle.
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr);
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * This function enumerates currently visible DSP/BIOS Bridge objects
++ * and returns the UUID and type of each enumerated object.
++ * Parameters:
++ * cIndex: The object enumeration index.
++ * objType: Type of object to enumerate.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to enumerate through the DCD database.
++ * DSP_SENUMCOMPLETE: Enumeration completed. This is not an error code.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a valid pointer.
++ * Ensures:
++ * Details:
++ * This function can be used in conjunction with DCD_GetObjectDef to
++ * retrieve object properties.
++ */
++ extern DSP_STATUS DCD_EnumerateObject(IN s32 cIndex,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid);
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * This function cleans up the DCD module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern void DCD_Exit(void);
++
++/*
++ * ======== DCD_GetDepLibs ========
++ * Purpose:
++ * Given the uuid of a library and size of array of uuids, this function
++ * fills the array with the uuids of all dependent libraries of the input
++ * library.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * numLibs: Size of uuid array (number of library uuids).
++ * pDepLibUuids: Array of dependent library uuids to be filled in.
++ * pPersistentDepLibs: Array indicating if corresponding lib is persistent.
++ * phase: phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pDepLibUuids != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs,
++ OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ * Purpose:
++ * Given the uuid of a library, determine its number of dependent
++ * libraries.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * pNumLibs: Size of uuid array (number of library uuids).
++ * pNumPersLibs: number of persistent dependent library.
++ * phase: Phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pNumLibs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * This function returns the name of a (dynamic) library for a given
++ * UUID.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique DSP/BIOS
++ * Bridge object.
++ * pstrLibName: Buffer to hold library name.
++ * pdwSize: Contains buffer size. Set to string size on output.
++ * phase: Which phase to load
++ * fPhaseSplit: Are phases in multiple libraries
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pstrLibName != NULL.
++ * pUuid != NULL
++ * pdwSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName,
++ IN OUT u32 *pdwSize,
++ IN enum NLDR_PHASE phase,
++ OUT bool *fPhaseSplit);
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * This function returns the properties/attributes of a DSP/BIOS Bridge
++ * object.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique
++ * DSP/BIOS Bridge object.
++ * objType: The type of DSP/BIOS Bridge object to be
++ * referenced (node, processor, etc).
++ * pObjDef: Pointer to an object definition structure. A
++ * union of various possible DCD object types.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDPARSESECT: Unable to parse content of object code section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDGETSECT: Unable to access object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EFAIL: General failure.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle.
++ * Requires:
++ * DCD initialized.
++ * pObjUuid is non-NULL.
++ * pObjDef is non-NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef);
++
++/*
++ * ======== DCD_GetObjects ========
++ * Purpose:
++ * This function finds all DCD objects specified in a special
++ * COFF section called ".dcd_register", and for each object,
++ * call a "register" function. The "register" function may perform
++ * various actions, such as 1) register nodes in the node database, 2)
++ * unregister nodes from the node database, and 3) add overlay nodes.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects.
++ * registerFxn: Callback fxn to be applied on each located
++ * DCD object.
++ * handle: Handle to pass to callback.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find .dcd_register section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn,
++ void *handle);
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * This function initializes DCD.
++ * Parameters:
++ * Returns:
++ * FALSE: Initialization failed.
++ * TRUE: Initialization succeeded.
++ * Requires:
++ * Ensures:
++ * DCD initialized.
++ */
++ extern bool DCD_Init(void);
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * This function registers a DSP/BIOS Bridge object in the DCD database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS
++ * Bridge object.
++ * objType: Type of object.
++ * pszPathName: Path to the object's COFF file.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to register object.
++ * Requires:
++ * DCD initialized.
++ * pUuid and szPathName are non-NULL values.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName);
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Purpose:
++ * This function de-registers a valid DSP/BIOS Bridge object from the DCD
++ * database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS Bridge
++ * object.
++ * objType: Type of object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to de-register the specified object.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a non-NULL value.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType);
++
++#endif /* _DBDCD_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcddef.h b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+new file mode 100644
+index 0000000..91b1c45
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+@@ -0,0 +1,94 @@
++/*
++ * dbdcddef.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcddef.h ========
++ * Description:
++ * DCD (DSP/BIOS Bridge Configuration Database) constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Dec-2003 map Moved and renamed DCD_OBJTYPE to DSP_DCDOBJTYPE in dbdefs.h
++ *! 05-Dec-2002 map Added DCD_CREATELIBTYPE, DCD_EXECUTELIBTYPE,
++ * DCD_DELETELIBTYPE
++ *! 24-Feb-2003 kc Updated REG entry names to DspBridge.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! 05-Aug-2002 jeh Added DCD_REGISTERFXN.
++ *! 19-Apr-2002 jeh Added DCD_LIBRARYTYPE to DCD_OBJTYPE, dynamic load
++ *! properties to DCD_NODEPROPS.
++ *! 29-Jul-2001 ag Added extended procObj.
++ *! 13-Feb-2001 kc: Named changed from dcdbsdef.h dbdcddef.h.
++ *! 12-Dec-2000 jeh Added DAIS iAlg name to DCD_NODEPROPS.
++ *! 30-Oct-2000 kc: Added #defines for DCD_AutoRegister function.
++ *! 05-Sep-2000 jeh Added DCD_NODEPROPS.
++ *! 12-Aug-2000 kc: Incoroporated the use of types defined in <dspdefs.h>.
++ *! 29-Jul-2000 kc: Created.
++ */
++
++#ifndef DBDCDDEF_
++#define DBDCDDEF_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/mgrpriv.h> /* for MGR_PROCESSOREXTINFO */
++
++/*
++ * The following defines are critical elements for the DCD module:
++ *
++ * - DCD_REGKEY enables DCD functions to locate registered DCD objects.
++ * - DCD_REGISTER_SECTION identifies the COFF section where the UUID of
++ * registered DCD objects are stored.
++ */
++#define DCD_REGKEY "Software\\TexasInstruments\\DspBridge\\DCD"
++#define DCD_REGISTER_SECTION ".dcd_register"
++
++/* DCD Manager Object */
++ struct DCD_MANAGER;
++
++/* DCD Node Properties */
++ struct DCD_NODEPROPS {
++ struct DSP_NDBPROPS ndbProps;
++ u32 uMsgSegid;
++ u32 uMsgNotifyType;
++ char *pstrCreatePhaseFxn;
++ char *pstrDeletePhaseFxn;
++ char *pstrExecutePhaseFxn;
++ char *pstrIAlgName;
++
++ /* Dynamic load properties */
++ u16 usLoadType; /* Static, dynamic, overlay */
++ u32 ulDataMemSegMask; /* Data memory requirements */
++ u32 ulCodeMemSegMask; /* Code memory requirements */
++ } ;
++
++/* DCD Generic Object Type */
++ struct DCD_GENERICOBJ {
++ union dcdObjUnion {
++ struct DCD_NODEPROPS nodeObj; /* node object. */
++ /* processor object. */
++ struct DSP_PROCESSORINFO procObj;
++ /* extended proc object (private) */
++ struct MGR_PROCESSOREXTINFO extProcObj;
++ } objData;
++ } ;
++
++/* DCD Internal Callback Type */
++ typedef DSP_STATUS(*DCD_REGISTERFXN) (IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++
++#endif /* DBDCDDEF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+new file mode 100644
+index 0000000..9782693
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+@@ -0,0 +1,580 @@
++/*
++ * dbdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdefs.h ========
++ * Description:
++ * Global definitions and constants for DSP/BIOS Bridge.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added MAPATTR & ELEM_SIZE for Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Added processor ID numbers for DSP and IVA
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE. Updated IsValid*Event macros.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! Removed unused DSP_ENUMLASTNODE define.
++ *! 13-Feb-2002 jeh Added uSysStackSize to DSP_NDBPROPS.
++ *! 23-Jan-2002 ag Added #define DSP_SHMSEG0.
++ *! 12-Dec-2001 ag Added DSP_ESTRMMODE error code.
++ *! 04-Dec-2001 jeh Added DSP_ENOTCONNECTED error code.
++ *! 10-Dec-2001 kc: Modified macros and definitions to disable DSP_POSTMESSAGE.
++ *! 01-Nov-2001 jeh Added DSP_EOVERLAYMEMORY.
++ *! 18-Oct-2001 ag Added DSP_STRMMODE type.
++ *! Added DSP_ENOTSHAREDMEM.
++ *! 21-Sep-2001 ag Added additional error codes.
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 11-May-2001 jeh Changed DSP_NODE_MIN_PRIORITY from 0 to 1. Removed hNode
++ *! from DSP_NODEINFO.
++ *! 02-Apr-2001 sg Added missing error codes, rearranged codes, switched to
++ *! hex offsets, renamed some codes to match API spec.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Dec-2000 ag: Added DSP_RMSxxx user available message command codes.
++ *! 09-Nov-2000 rr: Added DSP_PROCEESORRESTART define; Removed DSP_PBUFFER.
++ *! Added DSP_DCD_ENOAUTOREGISTER, DSP_EUSER1-16, DSP_ESTRMFUL
++ *! Removed DSP_EDONE. Macros's modified.
++ *! 23-Oct-2000 jeh Replaced DSP_STREAMSTATECHANGE with DSP_STREAMDONE.
++ *! 09-Oct-2000 jeh Updated to version 0.9 DSP Bridge API spec.
++ *! 29-Sep-2000 kc Added error codes for DCD and REG to simplify use of
++ *! these codes within the RM module.
++ *! 27-Sep-2000 jeh Added segid, alignment, uNumBufs to DSP_STREAMATTRIN.
++ *! 29-Aug-2000 jeh Added DSP_NODETYPE enum, changed DSP_EALREADYATTACHED to
++ *! DSP_EALREADYCONNECTED. Changed scStreamConnection[1]
++ *! to scStreamConnection[16] in DSP_NODEINFO structure.
++ *! Added DSP_NOTIFICATION, DSP_STRMATTR. PSTRING changed
++ *! back to TCHAR * and moved to dbtype.h.
++ *! 11-Aug-2000 rr: Macros to check valid events and notify masks added.
++ *! 09-Aug-2000 rr: Changed PSTRING to *s8
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! 20-Jul-2000 rr: Updated to version 0.8
++ *! 17-Jul-2000 rr: New PROC states added to the DSP_PROCSTATE.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef DBDEFS_
++#define DBDEFS_
++
++#include <linux/types.h>
++
++#include <dspbridge/dbtype.h> /* GPP side type definitions */
++#include <dspbridge/std.h> /* DSP/BIOS type definitions */
++#include <dspbridge/rms_sh.h> /* Types shared between GPP and DSP */
++
++#define PG_SIZE_4K 4096
++#define PG_MASK(pg_size) (~((pg_size)-1))
++#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
++#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
++
++/* API return value and calling convention */
++#define DBAPI DSP_STATUS
++
++/* Infinite time value for the uTimeout parameter to DSPStream_Select() */
++#define DSP_FOREVER (-1)
++
++/* Maximum length of node name, used in DSP_NDBPROPS */
++#define DSP_MAXNAMELEN 32
++
++/* uNotifyType values for the RegisterNotify() functions. */
++#define DSP_SIGNALEVENT 0x00000001
++
++/* Types of events for processors */
++#define DSP_PROCESSORSTATECHANGE 0x00000001
++#define DSP_PROCESSORATTACH 0x00000002
++#define DSP_PROCESSORDETACH 0x00000004
++#define DSP_PROCESSORRESTART 0x00000008
++
++/* DSP exception events (DSP/BIOS and DSP MMU fault) */
++#define DSP_MMUFAULT 0x00000010
++#define DSP_SYSERROR 0x00000020
++#define DSP_EXCEPTIONABORT 0x00000300
++
++/* IVA exception events (IVA MMU fault) */
++#define IVA_MMUFAULT 0x00000040
++/* Types of events for nodes */
++#define DSP_NODESTATECHANGE 0x00000100
++#define DSP_NODEMESSAGEREADY 0x00000200
++
++/* Types of events for streams */
++#define DSP_STREAMDONE 0x00001000
++#define DSP_STREAMIOCOMPLETION 0x00002000
++
++/* Handle definition representing the GPP node in DSPNode_Connect() calls */
++#define DSP_HGPPNODE 0xFFFFFFFF
++
++/* Node directions used in DSPNode_Connect() */
++#define DSP_TONODE 1
++#define DSP_FROMNODE 2
++
++/* Define Node Minimum and Maximum Priorities */
++#define DSP_NODE_MIN_PRIORITY 1
++#define DSP_NODE_MAX_PRIORITY 15
++
++/* Pre-Defined Message Command Codes available to user: */
++#define DSP_RMSUSERCODESTART RMS_USER /* Start of RMS user cmd codes */
++/* end of user codes */
++#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
++#define DSP_RMSBUFDESC RMS_BUFDESC /* MSG contains SM buffer description */
++
++/* Shared memory identifier for MEM segment named "SHMSEG0" */
++#define DSP_SHMSEG0 (u32)(-1)
++
++/* Processor ID numbers */
++#define DSP_UNIT 0
++#define IVA_UNIT 1
++
++#define DSPWORD unsigned char
++#define DSPWORDSIZE sizeof(DSPWORD)
++
++/* Success & Failure macros */
++#define DSP_SUCCEEDED(Status) likely((s32)(Status) >= 0)
++#define DSP_FAILED(Status) unlikely((s32)(Status) < 0)
++
++/* Power control enumerations */
++#define PROC_PWRCONTROL 0x8070
++
++#define PROC_PWRMGT_ENABLE (PROC_PWRCONTROL + 0x3)
++#define PROC_PWRMGT_DISABLE (PROC_PWRCONTROL + 0x4)
++
++/* Bridge Code Version */
++#define BRIDGE_VERSION_CODE 333
++
++#define MAX_PROFILES 16
++
++/* Types defined for 'Bridge API */
++ typedef u32 DSP_STATUS; /* API return code type */
++
++ typedef HANDLE DSP_HNODE; /* Handle to a DSP Node object */
++ typedef HANDLE DSP_HPROCESSOR; /* Handle to a Processor object */
++ typedef HANDLE DSP_HSTREAM; /* Handle to a Stream object */
++
++ typedef u32 DSP_PROCFAMILY; /* Processor family */
++ typedef u32 DSP_PROCTYPE; /* Processor type (w/in family) */
++ typedef u32 DSP_RTOSTYPE; /* Type of DSP RTOS */
++
++/* Handy Macros */
++#define IsValidProcEvent(x) (((x) == 0) || (((x) & (DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR)) && \
++ !((x) & ~(DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR))))
++
++#define IsValidNodeEvent(x) (((x) == 0) || (((x) & (DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY)) && \
++ !((x) & ~(DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY))))
++
++#define IsValidStrmEvent(x) (((x) == 0) || (((x) & (DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION)) && \
++ !((x) & ~(DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION))))
++
++#define IsValidNotifyMask(x) ((x) & DSP_SIGNALEVENT)
++
++/* The Node UUID structure */
++ struct DSP_UUID {
++ u32 ulData1;
++ u16 usData2;
++ u16 usData3;
++ u8 ucData4;
++ u8 ucData5;
++ u8 ucData6[6];
++ };
++
++/* DCD types */
++ enum DSP_DCDOBJTYPE {
++ DSP_DCDNODETYPE,
++ DSP_DCDPROCESSORTYPE,
++ DSP_DCDLIBRARYTYPE,
++ DSP_DCDCREATELIBTYPE,
++ DSP_DCDEXECUTELIBTYPE,
++ DSP_DCDDELETELIBTYPE
++ } ;
++
++/* Processor states */
++ enum DSP_PROCSTATE {
++ PROC_STOPPED,
++ PROC_LOADED,
++ PROC_RUNNING,
++ PROC_ERROR
++ } ;
++
++/*
++ * Node types: Message node, task node, xDAIS socket node, and
++ * device node. _NODE_GPP is used when defining a stream connection
++ * between a task or socket node and the GPP.
++ *
++ */
++ enum NODE_TYPE {
++ NODE_DEVICE,
++ NODE_TASK,
++ NODE_DAISSOCKET,
++ NODE_MESSAGE,
++ NODE_GPP
++ } ;
++
++/*
++ * ======== NODE_STATE ========
++ * Internal node states.
++ */
++ enum NODE_STATE {
++ NODE_ALLOCATED,
++ NODE_CREATED,
++ NODE_RUNNING,
++ NODE_PAUSED,
++ NODE_DONE,
++ NODE_CREATING,
++ NODE_STARTING,
++ NODE_PAUSING,
++ NODE_TERMINATING,
++ NODE_DELETING,
++ } ;
++
++/* Stream states */
++ enum DSP_STREAMSTATE {
++ STREAM_IDLE,
++ STREAM_READY,
++ STREAM_PENDING,
++ STREAM_DONE
++ } ;
++
++/* Stream connect types */
++ enum DSP_CONNECTTYPE {
++ CONNECTTYPE_NODEOUTPUT,
++ CONNECTTYPE_GPPOUTPUT,
++ CONNECTTYPE_NODEINPUT,
++ CONNECTTYPE_GPPINPUT
++ } ;
++
++/* Stream mode types */
++ enum DSP_STRMMODE {
++ STRMMODE_PROCCOPY, /* Processor(s) copy stream data payloads */
++ STRMMODE_ZEROCOPY, /* Strm buffer ptrs swapped no data copied */
++ STRMMODE_LDMA, /* Local DMA : OMAP's System-DMA device */
++ STRMMODE_RDMA /* Remote DMA: OMAP's DSP-DMA device */
++ } ;
++
++/* Resource Types */
++ enum DSP_RESOURCEINFOTYPE {
++ DSP_RESOURCE_DYNDARAM = 0,
++ DSP_RESOURCE_DYNSARAM,
++ DSP_RESOURCE_DYNEXTERNAL,
++ DSP_RESOURCE_DYNSRAM,
++ DSP_RESOURCE_PROCLOAD
++ } ;
++
++/* Memory Segment Types */
++ enum DSP_MEMTYPE {
++ DSP_DYNDARAM = 0,
++ DSP_DYNSARAM,
++ DSP_DYNEXTERNAL,
++ DSP_DYNSRAM
++ } ;
++
++/* Memory Flush Types */
++ enum DSP_FLUSHTYPE {
++ PROC_INVALIDATE_MEM = 0,
++ PROC_WRITEBACK_MEM,
++ PROC_WRITEBACK_INVALIDATE_MEM,
++ } ;
++
++/* Memory Segment Status Values */
++ struct DSP_MEMSTAT {
++ u32 ulSize;
++ u32 ulTotalFreeSize;
++ u32 ulLenMaxFreeBlock;
++ u32 ulNumFreeBlocks;
++ u32 ulNumAllocBlocks;
++ } ;
++
++/* Processor Load information Values */
++ struct DSP_PROCLOADSTAT {
++ u32 uCurrLoad;
++ u32 uPredictedLoad;
++ u32 uCurrDspFreq;
++ u32 uPredictedFreq;
++ } ;
++
++/* Attributes for STRM connections between nodes */
++ struct DSP_STRMATTR {
++ u32 uSegid; /* Memory segment on DSP to allocate buffers */
++ u32 uBufsize; /* Buffer size (DSP words) */
++ u32 uNumBufs; /* Number of buffers */
++ u32 uAlignment; /* Buffer alignment */
++ u32 uTimeout; /* Timeout for blocking STRM calls */
++ enum DSP_STRMMODE lMode; /* mode of stream when opened */
++ /* DMA chnl id if DSP_STRMMODE is LDMA or RDMA */
++ u32 uDMAChnlId;
++ u32 uDMAPriority; /* DMA channel priority 0=lowest, >0=high */
++ } ;
++
++/* The DSP_CBDATA structure */
++ struct DSP_CBDATA {
++ u32 cbData;
++ u8 cData[1];
++ } ;
++
++/* The DSP_MSG structure */
++ struct DSP_MSG {
++ u32 dwCmd;
++ u32 dwArg1;
++ u32 dwArg2;
++ } ;
++
++/* The DSP_RESOURCEREQMTS structure for node's resource requirements */
++ struct DSP_RESOURCEREQMTS {
++ u32 cbStruct;
++ u32 uStaticDataSize;
++ u32 uGlobalDataSize;
++ u32 uProgramMemSize;
++ u32 uWCExecutionTime;
++ u32 uWCPeriod;
++ u32 uWCDeadline;
++ u32 uAvgExectionTime;
++ u32 uMinimumPeriod;
++ } ;
++
++/*
++ * The DSP_STREAMCONNECT structure describes a stream connection
++ * between two nodes, or between a node and the GPP
++ */
++ struct DSP_STREAMCONNECT {
++ u32 cbStruct;
++ enum DSP_CONNECTTYPE lType;
++ u32 uThisNodeStreamIndex;
++ DSP_HNODE hConnectedNode;
++ struct DSP_UUID uiConnectedNodeID;
++ u32 uConnectedNodeStreamIndex;
++ } ;
++
++ struct DSP_NODEPROFS {
++ u32 ulHeapSize;
++ } ;
++
++/* The DSP_NDBPROPS structure reports the attributes of a node */
++ struct DSP_NDBPROPS {
++ u32 cbStruct;
++ struct DSP_UUID uiNodeID;
++ char acName[DSP_MAXNAMELEN];
++ enum NODE_TYPE uNodeType;
++ u32 bCacheOnGPP;
++ struct DSP_RESOURCEREQMTS dspResourceReqmts;
++ s32 iPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uMessageDepth;
++ u32 uNumInputStreams;
++ u32 uNumOutputStreams;
++ u32 uTimeout;
++ u32 uCountProfiles; /* Number of supported profiles */
++ /* Array of profiles */
++ struct DSP_NODEPROFS aProfiles[MAX_PROFILES];
++ u32 uStackSegName; /* Stack Segment Name */
++ } ;
++
++ /* The DSP_NODEATTRIN structure describes the attributes of a
++ * node client */
++ struct DSP_NODEATTRIN {
++ u32 cbStruct;
++ s32 iPriority;
++ u32 uTimeout;
++ u32 uProfileID;
++ /* Reserved, for Bridge Internal use only */
++ u32 uHeapSize;
++ void *pGPPVirtAddr; /* Reserved, for Bridge Internal use only */
++ } ;
++
++ /* The DSP_NODEINFO structure is used to retrieve information
++ * about a node */
++ struct DSP_NODEINFO {
++ u32 cbStruct;
++ struct DSP_NDBPROPS nbNodeDatabaseProps;
++ u32 uExecutionPriority;
++ enum NODE_STATE nsExecutionState;
++ DSP_HNODE hDeviceOwner;
++ u32 uNumberStreams;
++ struct DSP_STREAMCONNECT scStreamConnection[16];
++ u32 uNodeEnv;
++ } ;
++
++ /* The DSP_NODEATTR structure describes the attributes of a node */
++ struct DSP_NODEATTR {
++ u32 cbStruct;
++ struct DSP_NODEATTRIN inNodeAttrIn;
++ u32 uInputs;
++ u32 uOutputs;
++ struct DSP_NODEINFO iNodeInfo;
++ } ;
++
++/*
++ * Notification type: either the name of an opened event, or an event or
++ * window handle.
++ */
++ struct DSP_NOTIFICATION {
++ char *psName;
++ HANDLE handle;
++ } ;
++
++/* The DSP_PROCESSORATTRIN structure describes the attributes of a processor */
++ struct DSP_PROCESSORATTRIN{
++ u32 cbStruct;
++ u32 uTimeout;
++ } ;
++
++ enum chipTypes {
++ DSPTYPE_55 = 6,
++ IVA_ARM7 = 0x97,
++ DSPTYPE_64 = 0x99
++ };
++
++/*
++ * The DSP_PROCESSORINFO structure describes basic capabilities of a
++ * DSP processor
++ */
++ struct DSP_PROCESSORINFO {
++ u32 cbStruct;
++ DSP_PROCFAMILY uProcessorFamily;
++ DSP_PROCTYPE uProcessorType;
++ u32 uClockRate;
++ u32 ulInternalMemSize;
++ u32 ulExternalMemSize;
++ u32 uProcessorID;
++ DSP_RTOSTYPE tyRunningRTOS;
++ s32 nNodeMinPriority;
++ s32 nNodeMaxPriority;
++ } ;
++
++/* Error information of last DSP exception signalled to the GPP */
++ struct DSP_ERRORINFO {
++ u32 dwErrMask;
++ u32 dwVal1;
++ u32 dwVal2;
++ u32 dwVal3;
++ } ;
++
++/* The DSP_PROCESSORSTATE structure describes the state of a DSP processor */
++ struct DSP_PROCESSORSTATE {
++ u32 cbStruct;
++ enum DSP_PROCSTATE iState;
++ struct DSP_ERRORINFO errInfo;
++ } ;
++
++/*
++ * The DSP_RESOURCEINFO structure is used to retrieve information about a
++ * processor's resources
++ */
++ struct DSP_RESOURCEINFO {
++ u32 cbStruct;
++ enum DSP_RESOURCEINFOTYPE uResourceType;
++ union {
++ u32 ulResource;
++ struct DSP_MEMSTAT memStat;
++ struct DSP_PROCLOADSTAT procLoadStat;
++ } result;
++ } ;
++
++/*
++ * The DSP_STREAMATTRIN structure describes the attributes of a stream,
++ * including segment and alignment of data buffers allocated with
++ * DSPStream_AllocateBuffers(), if applicable
++ */
++ struct DSP_STREAMATTRIN {
++ u32 cbStruct;
++ u32 uTimeout;
++ u32 uSegment;
++ u32 uAlignment;
++ u32 uNumBufs;
++ enum DSP_STRMMODE lMode;
++ u32 uDMAChnlId;
++ u32 uDMAPriority;
++ } ;
++
++/* The DSP_BUFFERATTR structure describes the attributes of a data buffer */
++ struct DSP_BUFFERATTR {
++ u32 cbStruct;
++ u32 uSegment;
++ u32 uAlignment;
++ } ;
++
++/*
++ * The DSP_STREAMINFO structure is used to retrieve information
++ * about a stream.
++ */
++ struct DSP_STREAMINFO {
++ u32 cbStruct;
++ u32 uNumberBufsAllowed;
++ u32 uNumberBufsInStream;
++ u32 ulNumberBytes;
++ HANDLE hSyncObjectHandle;
++ enum DSP_STREAMSTATE ssStreamState;
++ } ;
++
++/* DMM MAP attributes
++It is a bit mask with each bit value indicating a specific attribute
++bit 0 - GPP address type (user virtual=0, physical=1)
++bit 1 - MMU Endianism (Big Endian=1, Little Endian=0)
++bit 2 - MMU mixed page attribute (Mixed/ CPUES=1, TLBES =0)
++bit 3 - MMU element size = 8bit (valid only for non mixed page entries)
++bit 4 - MMU element size = 16bit (valid only for non mixed page entries)
++bit 5 - MMU element size = 32bit (valid only for non mixed page entries)
++bit 6 - MMU element size = 64bit (valid only for non mixed page entries)
++*/
++
++/* Types of mapping attributes */
++
++/* MPU address is virtual and needs to be translated to physical addr */
++#define DSP_MAPVIRTUALADDR 0x00000000
++#define DSP_MAPPHYSICALADDR 0x00000001
++
++/* Mapped data is big endian */
++#define DSP_MAPBIGENDIAN 0x00000002
++#define DSP_MAPLITTLEENDIAN 0x00000000
++
++/* Element size is based on DSP r/w access size */
++#define DSP_MAPMIXEDELEMSIZE 0x00000004
++
++/*
++ * Element size for MMU mapping (8, 16, 32, or 64 bit)
++ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
++ */
++#define DSP_MAPELEMSIZE8 0x00000008
++#define DSP_MAPELEMSIZE16 0x00000010
++#define DSP_MAPELEMSIZE32 0x00000020
++#define DSP_MAPELEMSIZE64 0x00000040
++
++#define DSP_MAPVMALLOCADDR 0x00000080
++
++#define DSP_MAPDONOTLOCK 0x00000100
++
++
++#define GEM_CACHE_LINE_SIZE 128
++#define GEM_L1P_PREFETCH_SIZE 128
++
++#endif /* DBDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbg.h b/arch/arm/plat-omap/include/dspbridge/dbg.h
+new file mode 100644
+index 0000000..7f44ff9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbg.h
+@@ -0,0 +1,110 @@
++/*
++ * dbg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbg.h ========
++ * Purpose:
++ * Provide debugging services for 'Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Printf
++ * DBG_Trace
++ *
++ * Notes:
++ * WMD's must not call DBG_Init or DBG_Exit.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Feb-2000 rr: DBG Levels redefined.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 15-May-1996 gp: Created.
++ */
++
++#ifndef DBG_
++#define DBG_
++#include <dspbridge/host_os.h>
++#include <linux/types.h>
++
++/* Levels of trace debug messages: */
++#define DBG_ENTER (u8)(0x01) /* Function entry point. */
++#define DBG_LEVEL1 (u8)(0x02) /* Display debugging state/varibles */
++#define DBG_LEVEL2 (u8)(0x04) /* Display debugging state/varibles */
++#define DBG_LEVEL3 (u8)(0x08) /* Display debugging state/varibles */
++#define DBG_LEVEL4 (u8)(0x10) /* Display debugging state/varibles */
++#define DBG_LEVEL5 (u8)(0x20) /* Module Init, Exit */
++#define DBG_LEVEL6 (u8)(0x40) /* Warn SERVICES Failures */
++#define DBG_LEVEL7 (u8)(0x80) /* Warn Critical Errors */
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void DBG_Exit(void);
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Initializes private state of DBG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ */
++ extern bool DBG_Init(void);
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ * Parameters:
++ * bLevel: Trace level.
++ * pstrFormat: sprintf-style format string.
++ * ...: Arguments for format string.
++ * Returns:
++ * DSP_SOK: Success, or trace level masked.
++ * DSP_EFAIL: On Error.
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Debug message is printed to debugger output window, if trace level
++ * is unmasked.
++ */
++ extern DSP_STATUS DBG_Trace(IN u8 bLevel, IN char *pstrFormat, ...);
++#else
++
++#define DBG_Exit(void)
++#define DBG_Init(void) true
++#define DBG_Trace(bLevel, pstrFormat, args...)
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++#endif /* DBG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbl.h b/arch/arm/plat-omap/include/dspbridge/dbl.h
+new file mode 100644
+index 0000000..19847f9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbl.h
+@@ -0,0 +1,354 @@
++/*
++ * dbl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Pass DBL_Symbol pointer to DBL_getAddr, DBL_getCAddr
++ *! to accomodate dynamic loader library.
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 24-Sep-2001 jeh Code review changes.
++ *! 07-Sep-2001 jeh Added DBL_LoadSect(), DBL_UnloadSect().
++ *! 05-Jun-2001 jeh Created based on zl.h.
++ */
++
++#ifndef DBL_
++#define DBL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbldefs.h>
++
++/*
++ * ======== DBL_close ========
++ * Close library opened with DBL_open.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_close(struct DBL_LibraryObj *lib);
++
++/*
++ * ======== DBL_create ========
++ * Create a target object by specifying the alloc, free, and write
++ * functions for the target.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++ extern DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++ extern void DBL_delete(struct DBL_TargetObj *target);
++
++/*
++ * ======== DBL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++ extern void DBL_exit(void);
++
++/*
++ * ======== DBL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_getAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_getCAddr ========
++ * Get address of "C" name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getEntry ========
++ * Get program entry point.
++ *
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * pEntry - Location to store entry address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry);
++
++/*
++ * ======== DBL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++
++/*
++ * ======== DBL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++ extern bool DBL_init(void);
++
++/*
++ * ======== DBL_load ========
++ * Add symbols/code/data defined in file to that already present on
++ * the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * flags - Specifies whether loading code, data, and/or symbols.
++ * attrs - May contain write, alloc, and free functions.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry);
++
++/*
++ * ======== DBL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_open ========
++ * DBL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBL_load()/DBL_unload().
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * file - Name of file to open.
++ * flags - Specifies whether to load symbols now.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * struct DBL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++ extern DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file,
++ DBL_Flags flags,
++ struct DBL_LibraryObj **pLib);
++
++/*
++ * ======== DBL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name,
++ char *pBuf, u32 size);
++
++/*
++ * ======== DBL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_setAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_unload ========
++ * Remove the symbols/code/data corresponding to the library lib.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_unload(struct DBL_LibraryObj *lib,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++#endif /* DBL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbldefs.h b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+new file mode 100644
+index 0000000..79b9e54
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+@@ -0,0 +1,155 @@
++/*
++ * dbldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLDEFS_
++#define DBLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBL_SYMB 0x1 /* load symbols */
++#define DBL_CODE 0x2 /* load code */
++#define DBL_DATA 0x4 /* load data */
++#define DBL_DYNAMIC 0x8 /* dynamic load */
++#define DBL_BSS 0x20 /* Unitialized section */
++
++#define DBL_MAXPATHLENGTH 255
++
++
++
++/*
++ * ======== DBL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBL_Flags;
++
++/*
++ * ======== DBL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req, bool reserved);
++
++
++
++/*
++ * ======== DBL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBL_LogWriteFxn) (void *handle, struct DBL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++
++/*
++ * ======== DBL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBL_Symbol **sym);
++
++
++/*
++ * ======== DBL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBL_Attrs ========
++ */
++struct DBL_Attrs {
++ DBL_AllocFxn alloc;
++ DBL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++
++ DBL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbll.h b/arch/arm/plat-omap/include/dspbridge/dbll.h
+new file mode 100644
+index 0000000..c3aa212
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbll.h
+@@ -0,0 +1,70 @@
++/*
++ * dbll.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbll.h ========
++ * DSP/BIOS Bridge Dynamic load library module interface. Function header
++ * comments are in the file dblldefs.h.
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function comments (now in dblldefs.h).
++ *! 17-Apr-2002 jeh Created based on zl.h.
++ */
++
++#ifndef DBLL_
++#define DBLL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dblldefs.h>
++
++ extern void DBLL_close(struct DBLL_LibraryObj *lib);
++ extern DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_delete(struct DBLL_TarObj *target);
++ extern void DBLL_exit(void);
++ extern bool DBLL_getAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern void DBLL_getAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern bool DBLL_getCAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++ extern bool DBLL_init(void);
++ extern DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry);
++ extern DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++ extern DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib,
++ char *name,
++ char *pBuf, u32 size);
++ extern void DBLL_setAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_unload(struct DBLL_LibraryObj *lib,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++
++#endif /* DBLL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dblldefs.h b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+new file mode 100644
+index 0000000..2361ce8
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+@@ -0,0 +1,509 @@
++/*
++ * dblldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dblldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map Consolidated DBL into DBLL name
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLLDEFS_
++#define DBLLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBLL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBLL_SYMB 0x1 /* load symbols */
++#define DBLL_CODE 0x2 /* load code */
++#define DBLL_DATA 0x4 /* load data */
++#define DBLL_DYNAMIC 0x8 /* dynamic load */
++#define DBLL_BSS 0x20 /* Unitialized section */
++
++#define DBLL_MAXPATHLENGTH 255
++
++
++/*
++ * ======== DBLL_Target ========
++ *
++ */
++struct DBLL_TarObj;
++
++/*
++ * ======== DBLL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBLL_Flags;
++
++/*
++ * ======== DBLL_Library ========
++ *
++ */
++struct DBLL_LibraryObj;
++
++/*
++ * ======== DBLL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBLL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBLL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBLL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBLL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBLL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBLL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req,
++ bool reserved);
++
++/*
++ * ======== DBLL_CloseFxn ========
++ */
++typedef s32(*DBLL_FCloseFxn) (void *);
++
++/*
++ * ======== DBLL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBLL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBLL_FOpenFxn ========
++ */
++typedef void *(*DBLL_FOpenFxn) (const char *, const char *);
++
++/*
++ * ======== DBLL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBLL_LogWriteFxn)(void *handle, struct DBLL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++/*
++ * ======== DBLL_ReadFxn ========
++ */
++typedef s32(*DBLL_ReadFxn) (void *, size_t, size_t, void *);
++
++/*
++ * ======== DBLL_SeekFxn ========
++ */
++typedef s32(*DBLL_SeekFxn) (void *, long, int);
++
++/*
++ * ======== DBLL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBLL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBLL_Symbol **sym);
++
++/*
++ * ======== DBLL_TellFxn ========
++ */
++typedef s32(*DBLL_TellFxn) (void *);
++
++/*
++ * ======== DBLL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBLL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBLL_Attrs ========
++ */
++struct DBLL_Attrs {
++ DBLL_AllocFxn alloc;
++ DBLL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBLL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++ bool baseImage;
++ DBLL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBLL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++/*
++ * ======== DBLL_close ========
++ * Close library opened with DBLL_open.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_CloseFxn) (struct DBLL_LibraryObj *library);
++
++/*
++ * ======== DBLL_create ========
++ * Create a target object, specifying the alloc, free, and write functions.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++typedef DSP_STATUS(*DBLL_CreateFxn)(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++typedef void(*DBLL_DeleteFxn) (struct DBLL_TarObj *target);
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++typedef void(*DBLL_ExitFxn) (void);
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid library.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_GetAttrsFxn) (struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of "C" name on the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetCAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_GetSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ u32 *addr, u32 *size);
++
++/*
++ * ======== DBLL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++typedef bool(*DBLL_InitFxn) (void);
++
++/*
++ * ======== DBLL_load ========
++ * Load library onto the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * flags - Load code, data and/or symbols.
++ * attrs - May contain alloc, free, and write function.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadFxn) (struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *entry);
++
++/*
++ * ======== DBLL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * DSP_ENOTIMPL: Function not implemented.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_open ========
++ * DBLL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBLL_load()/DBLL_unload().
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * file - Name of file to open.
++ * flags - If flags & DBLL_SYMB, load symbols.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * DBLL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++typedef DSP_STATUS(*DBLL_OpenFxn) (struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++
++/*
++ * ======== DBLL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_ReadSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ char *content, u32 uContentSize);
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_SetAttrsFxn)(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unload ========
++ * Unload library loaded with DBLL_load().
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_UnloadFxn) (struct DBLL_LibraryObj *library,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * DSP_ENOTIMPL
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_UnloadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++struct DBLL_Fxns {
++ DBLL_CloseFxn closeFxn;
++ DBLL_CreateFxn createFxn;
++ DBLL_DeleteFxn deleteFxn;
++ DBLL_ExitFxn exitFxn;
++ DBLL_GetAttrsFxn getAttrsFxn;
++ DBLL_GetAddrFxn getAddrFxn;
++ DBLL_GetCAddrFxn getCAddrFxn;
++ DBLL_GetSectFxn getSectFxn;
++ DBLL_InitFxn initFxn;
++ DBLL_LoadFxn loadFxn;
++ DBLL_LoadSectFxn loadSectFxn;
++ DBLL_OpenFxn openFxn;
++ DBLL_ReadSectFxn readSectFxn;
++ DBLL_SetAttrsFxn setAttrsFxn;
++ DBLL_UnloadFxn unloadFxn;
++ DBLL_UnloadSectFxn unloadSectFxn;
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbof.h b/arch/arm/plat-omap/include/dspbridge/dbof.h
+new file mode 100644
+index 0000000..54f4250
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbof.h
+@@ -0,0 +1,117 @@
++/*
++ * dbof.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbof.h ========
++ * Description:
++ * Defines and typedefs for DSP/BIOS Bridge Object File Format (DBOF).
++ *
++ *! Revision History
++ *! ================
++ *! 12-Jul-2002 jeh Added defines for DBOF_SectHdr page.
++ *! 12-Oct-2001 jeh Converted to std.h format.
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 06-Jul-2001 jeh Created.
++ */
++
++#ifndef DBOF_
++#define DBOF_
++
++/* Enough to hold DCD section names: 32 digit ID + underscores */
++#define DBOF_DCDSECTNAMELEN 40
++
++/* Values for DBOF_SectHdr page field. */
++#define DBOF_PROGRAM 0
++#define DBOF_DATA 1
++#define DBOF_CINIT 2
++
++/*
++ * ======== DBOF_FileHdr ========
++ */
++ struct DBOF_FileHdr {
++ u32 magic; /* COFF magic number */
++ u32 entry; /* Program entry point */
++ u16 numSymbols; /* Number of bridge symbols */
++ u16 numDCDSects; /* Number of DCD sections */
++ u16 numSects; /* Number of sections to load */
++ u16 numOvlySects; /* Number of overlay sections */
++ u32 symOffset; /* Offset in file to symbols */
++ u32 dcdSectOffset; /* Offset to DCD sections */
++ u32 loadSectOffset; /* Offset to loadable sections */
++ u32 ovlySectOffset; /* Offset to overlay data */
++ u16 version; /* DBOF version number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_DCDSectHdr ========
++ */
++ struct DBOF_DCDSectHdr {
++ u32 size; /* Sect size (target MAUs) */
++ char name[DBOF_DCDSECTNAMELEN]; /* DCD section name */
++ } ;
++
++/*
++ * ======== DBOF_OvlySectHdr ========
++ */
++ struct DBOF_OvlySectHdr {
++ u16 nameLen; /* Length of section name */
++ u16 numCreateSects; /* # of sects loaded for create phase */
++ u16 numDeleteSects; /* # of sects loaded for delete phase */
++ u16 numExecuteSects; /* # of sects loaded for execute phase */
++
++ /*
++ * Number of sections where load/unload phase is not specified.
++ * These sections will be loaded when create phase sects are
++ * loaded, and unloaded when the delete phase is unloaded.
++ */
++ u16 numOtherSects;
++ u16 resvd; /* Reserved for future use */
++ };
++
++/*
++ * ======== DBOF_OvlySectData ========
++ */
++ struct DBOF_OvlySectData {
++ u32 loadAddr; /* Section load address */
++ u32 runAddr; /* Section run address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Memory page number */
++ u16 resvd; /* Reserved */
++ } ;
++
++/*
++ * ======== DBOF_SectHdr ========
++ */
++ struct DBOF_SectHdr {
++ u32 addr; /* Section address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Page number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_SymbolHdr ========
++ */
++ struct DBOF_SymbolHdr {
++ u32 value; /* Symbol value */
++ u16 nameLen; /* Length of symbol name */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++#endif /* DBOF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbreg.h b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+new file mode 100644
+index 0000000..d311b88
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+@@ -0,0 +1,113 @@
++/*
++ * dbreg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbreg.h ========
++ * Purpose:
++ * Registry keys for use in Linux. This is the clearinghouse for
++ * registry definitions, hopefully eliminating overlapping between
++ * modules.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Apr-2003 vp: Added macro for subkey TCWORDSWAP.
++ *! 21-Mar-2003 sb: Added macro for subkey SHMSize
++ *! 27-Aug-2001 jeh Added WSXREG_LOADERFILENAME.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 29-Nov-2000 rr: Added WSXREG_DSPTYPE_55 as 6.
++ *! 06-Sep-2000 jeh: Added WSXREG_CHNLOFFSET, WSXREG_NUMCHNLS,
++ *! WSXREG_CHNLBUFSIZE.
++ *! 26-Aug-2000 rr: MEMBASE expanded to 9 entries.
++ *! 26-Jul-2000 rr: Added WSXREG_DCDNAME for the DCD Dll name. It will
++ *! live under WSXREG_WINSPOXCONFIG.
++ *! 17-Jul-2000 rr: REG_MGR_OBJECT and REG_DRV_OBJECT defined. They
++ *! are stored in the Registrty under WSXREG_WINSPOXCONFIG
++ *! when they are created in DSP_Init. WSXREG_DEVOBJECT
++ *! and WSXREG_MGROBJECT defined.
++ *! 11-Dec-1999 ag: Renamed Isa to IsaBus due to conflict with ceddk.h.
++ *! 12-Nov-1999 rr: New Registry Defnitions.
++ *! 15-Oct-1999 rr: New entry for DevObject created. WSXREG_DEVOBJECT
++ *! under WSXREG_DDSPDRIVERPATH
++ *! 10-Nov-1997 cr: Added WSXREG_INFPATH, WSXREG_WINDEVICEPATH,
++ *! WSXREG_WINCURVERSION
++ *! 21-Oct-1997 cr: Added WSXREG_BUSTYPE.
++ *! 08-Sep-1997 cr: Added WSXREG_SERVICES, WSXREG_SERVICENAME and
++ *! WSXREG_CLASSINDEX.
++ *! 30-Aug-1997 cr: Added WSXREG_SOFTWAREPATHNT & WSXREG_WBCLASSGUID.
++ *! 24-Mar-1997 gp: Added MAXCHIPINFOSUBKEY def.
++ *! 18-Feb-1997 cr: Changed Version1.1 -> Version1.0
++ *! 12-Feb-1997 cr: Changed WinSPOX -> WinBRIDGE.
++ *! 11-Dec-1996 gp: Added Perf key name in WinSPOX Config.
++ *! 22-Jul-1996 gp: Added Trace key name.
++ *! 30-May-1996 cr: Created.
++ */
++
++#ifndef DBREG_
++#define DBREG_ 1 /* Defined as "1" so InstallShield programs compile. */
++
++#define REG_MGR_OBJECT 1
++#define REG_DRV_OBJECT 2
++/* general registry definitions */
++#define MAXREGPATHLENGTH 255 /* Max registry path length. Also the
++ max registry value length. */
++#define DSPTYPE_55 6 /* This is the DSP Chip type for 55 */
++#define DSPTYPE_64 0x99
++#define IVA_ARM7 0x97 /* This is the DSP Chip type for IVA/ARM7 */
++
++#define DSPPROCTYPE_C55 5510
++#define DSPPROCTYPE_C64 6410
++#define IVAPROCTYPE_ARM7 470
++/* registry */
++#define DEVNODESTRING "DevNode" /* u32 devnode */
++#define CONFIG "Software\\TexasInstruments\\DirectDSP\\Config"
++#define DRVOBJECT "DrvObject"
++#define MGROBJECT "MgrObject"
++#define CLASS "Device" /* device class */
++#define TRACE "Trace" /* GT Trace settings. */
++#define PERFR "Perf" /* Enable perf bool. */
++#define ROOT "Root" /* root dir */
++
++/* MiniDriver related definitions */
++/* The following definitions are under "Drivers\\DirectDSP\\Device\\XXX "
++ * Where XXX is the device or board name */
++
++#define WMDFILENAME "MiniDriver" /* WMD entry name */
++#define CHIPTYPE "ChipType" /* Chip type */
++#define CHIPNUM "NumChips" /* Number of chips */
++#define NUMPROCS "NumOfProcessors" /* Number of processors */
++#define DEFEXEC "DefaultExecutable" /* Default executable */
++#define AUTOSTART "AutoStart" /* Statically load flag */
++#define IVAAUTOSTART "IvaAutoStart" /* Statically load flag */
++#define BOARDNAME "BoardName" /* Name of the Board */
++#define UNITNUMBER "UnitNumber" /* Unit # of the Board */
++#define BUSTYPE "BusType" /* Bus type board is on */
++#define BUSNUMBER "BusNumber" /* Bus number board is on */
++#define CURRENTCONFIG "CurrentConfig" /* Current resources */
++#define PCIVENDEVID "VendorDeviceId" /* The board's id */
++#define INFPATH "InfPath" /* wmd's inf filename */
++#define DEVOBJECT "DevObject"
++#define ZLFILENAME "ZLFileName" /* Name of ZL file */
++#define WORDSIZE "WordSize" /* NumBytes in DSP Word */
++#define SHMSIZE "SHMSize" /* Size of SHM reservd on MPU */
++#define IVAEXTMEMSIZE "IVAEXTMEMSize" /* IVA External Memeory size */
++#define TCWORDSWAP "TCWordSwap" /* Traffic Contoller Word Swap */
++#define DSPRESOURCES "DspTMSResources" /* C55 DSP resurces on OMAP */
++#define IVA1RESOURCES "ARM7IvaResources" /* ARM7 IVA resurces on OMAP */
++#define PHYSMEMPOOLBASE "PhysicalMemBase" /* Physical mem passed to driver */
++#define PHYSMEMPOOLSIZE "PhysicalMemSize" /* Physical mem passed to driver */
++
++#endif /* DBREG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbtype.h b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+new file mode 100644
+index 0000000..b4953a0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+@@ -0,0 +1,103 @@
++/*
++ * dbtype.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbtype.h ========
++ * Description:
++ * This header defines data types for DSP/BIOS Bridge APIs and device
++ * driver modules. It also defines the Hungarian
++ * prefix to use for each base type.
++ *
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Nov-2002 gp: Purpose -> Description in file header.
++ *! 13-Feb-2001 kc: Name changed from ddsptype.h dbtype.h.
++ *! 09-Oct-2000 jeh Added CHARACTER.
++ *! 11-Aug-2000 ag: Added 'typedef void void'.
++ *! 08-Apr-2000 ww: Cloned.
++ */
++
++#ifndef DBTYPE_
++#define DBTYPE_
++
++/*============================================================================*/
++/* Argument specification syntax */
++/*============================================================================*/
++
++#ifndef IN
++#define IN /* Following parameter is for input. */
++#endif
++
++#ifndef OUT
++#define OUT /* Following parameter is for output. */
++#endif
++
++#ifndef OPTIONAL
++#define OPTIONAL /* Function may optionally use previous parameter. */
++#endif
++
++#ifndef CONST
++#define CONST const
++#endif
++
++/*============================================================================*/
++/* Boolean constants */
++/*============================================================================*/
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++/*============================================================================*/
++/* NULL (Definition is language specific) */
++/*============================================================================*/
++
++#ifndef NULL
++#define NULL ((void *)0) /* Null pointer. */
++#endif
++
++/*============================================================================*/
++/* NULL character (normally used for string termination) */
++/*============================================================================*/
++
++#ifndef NULL_CHAR
++#define NULL_CHAR '\0' /* Null character. */
++#endif
++
++/*============================================================================*/
++/* Basic Type definitions (with Prefixes for Hungarian notation) */
++/*============================================================================*/
++
++#ifndef OMAPBRIDGE_TYPES
++#define OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++
++typedef void *HANDLE; /* h */
++
++#define TEXT(x) x
++
++#define DLLIMPORT
++#define DLLEXPORT
++
++/* Define DSPAPIDLL correctly in dspapi.h */
++#define _DSPSYSDLL32_
++
++#endif /* DBTYPE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dehdefs.h b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+new file mode 100644
+index 0000000..06e5582
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+@@ -0,0 +1,42 @@
++/*
++ * dehdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dehdefs.h ========
++ * Purpose:
++ * Definition for mini-driver module DEH.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Dec-2001 ag: added #include <dspbridge/mbx_sh.h> for shared mailbox codes.
++ *! 10-Dec-2001 kc: added DEH error base value and error max value.
++ *! 11-Sep-2001 kc: created.
++ */
++
++#ifndef DEHDEFS_
++#define DEHDEFS_
++
++#include <dspbridge/mbx_sh.h> /* shared mailbox codes */
++
++/* DEH object manager */
++ struct DEH_MGR;
++
++/* Magic code used to determine if DSP signaled exception. */
++#define DEH_BASE MBX_DEH_BASE
++#define DEH_USERS_BASE MBX_DEH_USERS_BASE
++#define DEH_LIMIT MBX_DEH_LIMIT
++
++#endif /* _DEHDEFS_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dev.h b/arch/arm/plat-omap/include/dspbridge/dev.h
+new file mode 100644
+index 0000000..5f468c9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dev.h
+@@ -0,0 +1,785 @@
++/*
++ * dev.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.h ========
++ * Description:
++ * 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetMsgMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ *! Revision History:
++ *! ================
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature - Dev_GetDmmMgr
++ *! 09-Feb-2004 vp Added functions required for IVA
++ *! 25-Feb-2003 swa PMGR Code Review changes incorporated
++ *! 05-Nov-2001 kc: Added DEV_GetDehMgr.
++ *! 05-Dec-2000 jeh Added DEV_SetMsgMgr.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added DEV_GetMsgMgr.
++ *! 05-Oct-2000 rr: DEV_Create2 & DEV_Destroy2 Added.
++ *! 02-Oct-2000 rr: Added DEV_GetNodeManager.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr() for shared memory management.
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 05-Nov-1999 kc: Updated function prototypes.
++ *! 08-Oct-1997 cr: Added explicit CDECL function identifiers.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 22-Oct-1996 gp: Added DEV_CleanupProcessState().
++ *! 29-May-1996 gp: Changed DEV_HDEVNODE --> CFG_HDEVNODE.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef DEV_
++#define DEV_
++
++/* ----------------------------------- Module Dependent Headers */
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dmm.h>
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/devdefs.h>
++
++
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject by ZL in pArb, then calls the
++ * device's WMD_BRD_Write() function.
++ * Parameters:
++ * pArb: Handle to a Device Object.
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * Number of bytes written. Returns 0 if the DEV_hObject passed in via
++ * pArb is invalid.
++ * Requires:
++ * DEV Initialized.
++ * pHostBuf != NULL
++ * Ensures:
++ */
++ extern u32 DEV_BrdWriteFxn(void *pArb,
++ u32 ulDspAddr,
++ void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for a
++ * 'Bridge device.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES
++ *pHostConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_CreateIVADevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for IVA.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateIVADevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr != NULL
++ * else hDevObject->hNodeMgr == NULL
++ */
++ extern DSP_STATUS DEV_Create2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr == NULL
++ * else DSP_EFAIL.
++ */
++ extern DSP_STATUS DEV_Destroy2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * DSP_EFAIL: The WMD failed it's WMD_DEV_Destroy() function.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr);
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phCodMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phCodMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phCodMgr contains a handle to a COD manager object.
++ * else: *phCodMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr);
++
++/*
++ * ======== DEV_GetDehMgr ========
++ * Purpose:
++ * Retrieve the DEH manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * *phDehMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDehMgr != NULL.
++ * DEH Initialized.
++ * Ensures:
++ * DSP_SOK: *phDehMgr contains a handle to a DEH manager object.
++ * else: *phDehMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr);
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: In Win95, returns a DEVNODE in *hDevNode; In NT, ???
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode);
++
++/*
++ * ======== DEV_GetDevType ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject,
++ u32 *devType);
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV.
++ * Parameters:
++ * Returns:
++ * NULL if there are no device objects stored; else
++ * a valid DEV_HOBJECT.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetFirst(void);
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *ppIntfFxns: Ptr to location to store fxn interface.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * ppIntfFxns != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *ppIntfFxns contains a pointer to the WMD interface;
++ * else: *ppIntfFxns is NULL.
++ */
++ extern DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns);
++
++/*
++ * ======== DEV_GetIOMgr ========
++ * Purpose:
++ * Retrieve the handle to the IO manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to an IO manager object.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phMgr);
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ * Parameters:
++ * hDevObject: Handle to the device object returned from a previous
++ * call to DEV_GetFirst() or DEV_GetNext().
++ * Returns:
++ * NULL if there are no further device objects on the list or hDevObject
++ * was invalid;
++ * else the next valid DEV_HOBJECT in the list.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ * Purpose:
++ * Retrieve the MSG Manager Handle from the DevObject.
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phMsgMgr: Location where MSG Manager handle will be returned.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Valid hDevObject.
++ * phNodeMgr != NULL.
++ * Ensures:
++ */
++ extern void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr);
++
++/*
++ * ========= DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle from the DevObject. It is an
++ * accessor function
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phNodeMgr: Location where Handle to the Node Manager will be
++ * returned..
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid Dev Object handle.
++ * Requires:
++ * DEV Initialized.
++ * phNodeMgr is not null
++ * Ensures:
++ * DSP_SOK: *phNodeMgr contains a handle to a Node manager object.
++ * else: *phNodeMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT
++ *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr);
++
++/*
++ * ======== DEV_GetSymbol ========
++ * Purpose:
++ * Get the value of a symbol in the currently loaded program.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * pstrSym: Name of symbol to look up.
++ * pulValue: Ptr to symbol value.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *pulValue contains the symbol value;
++ */
++ extern DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice()
++ * *phWmdContext: Ptr to location to store context handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phWmdContext != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phWmdContext contains context handle;
++ * else: *phWmdContext is NULL;
++ */
++ extern DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext);
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DEV is initialized.
++ * Ensures:
++ * When reference count == 0, DEV's private resources are freed.
++ */
++ extern void DEV_Exit(void);
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public DEV functions.
++ */
++ extern bool DEV_Init(void);
++
++/*
++ * ======== DEV_IsLocked ========
++ * Purpose:
++ * Predicate function to determine if the device has been
++ * locked by a client for exclusive access.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: TRUE: device has been locked.
++ * DSP_SFALSE: FALSE: device not locked.
++ * DSP_EHANDLE: hDevObject was invalid.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_IsLocked(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Inserts the Processor Object into the List of PROC Objects
++ * kept in the DEV Object
++ * Parameters:
++ * hProcObject: Handle to the Proc Object
++ * hDevObject Handle to the Dev Object
++ * bAttachedNew Specifies if there are already processors attached
++ * Returns:
++ * DSP_SOK: Successfully inserted into the list
++ * Requires:
++ * hProcObject is not NULL
++ * hDevObject is a valid handle to the DEV.
++ * DEV Initialized.
++ * List(of Proc object in Dev) Exists.
++ * Ensures:
++ * DSP_SOK & the PROC Object is inserted and the list is not empty
++ * Details:
++ * If the List of Proc Object is empty bAttachedNew is TRUE, it indicated
++ * this is the first Processor attaching.
++ * If it is False, there are already processors attached.
++ */
++ extern DSP_STATUS DEV_InsertProcObject(IN struct DEV_OBJECT
++ *hDevObject,
++ IN u32 hProcObject,
++ OUT bool *
++ pbAlreadyAttached);
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL Failure to Remove the PROC Object from the list
++ * Requires:
++ * DevObject is Valid
++ * hProcObject != 0
++ * pDevObject->procList != NULL
++ * !LST_IsEmpty(pDevObject->procList)
++ * pbAlreadyAttached !=NULL
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ *
++ */
++ extern DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT
++ *hDevObject,
++ u32 hProcObject);
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ * Clients may include multiple users of BRD, as well as CHNL.
++ * This function is asychronous, and may be called by a timer event
++ * set up by a watchdog timer.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * ulStatus: A status word, most likely a BRD_STATUS.
++ * Returns:
++ * DSP_SOK: All registered clients were asynchronously notified.
++ * DSP_EINVALIDARG: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: Notifications are queued by the operating system to be
++ * delivered to clients. This function does not ensure that
++ * the notifications will ever be delivered.
++ */
++ extern DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject,
++ u32 ulStatus);
++
++
++
++/*
++ * ======== DEV_RemoveDevice ========
++ * Purpose:
++ * Destroys the Device Object created by DEV_StartDevice.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * hMgr: Handle to a channel manager, or NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject,
++ struct CHNL_MGR *hMgr);
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the Message manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * hMgr: Handle to a message manager, or NULL.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject,
++ struct MSG_MGR *hMgr);
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the WinBRIDGE environment. This
++ * involves querying CM for allocated resources, querying the registry
++ * for necessary dsp resources (requested in the INF file), and using
++ * this information to create a WinBRIDGE device object.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * DEV initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode);
++
++#endif /* DEV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/devdefs.h b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+new file mode 100644
+index 0000000..e9ff725
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+@@ -0,0 +1,35 @@
++/*
++ * devdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== devdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and dev.h. Required
++ * to break circular dependency between WMD and DEV include files.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-1996 gp: Renamed from dev1.h.
++ *! 30-May-1996 gp: Broke out from dev.h
++ */
++
++#ifndef DEVDEFS_
++#define DEVDEFS_
++
++/* WCD Device Object */
++ struct DEV_OBJECT;
++
++#endif /* DEVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/disp.h b/arch/arm/plat-omap/include/dspbridge/disp.h
+new file mode 100644
+index 0000000..e116734
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/disp.h
+@@ -0,0 +1,236 @@
++/*
++ * disp.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Dispatcher.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 28-Jan-2003 map Removed DISP_DoCinit().
++ *! 15-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 07-Sep-2001 jeh Added DISP_MemCopy().
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 08-Aug-2000 jeh Removed DISP_NodeTerminate since it no longer uses RMS.
++ *! 17-Jul-2000 jeh Updates to function headers.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef DISP_
++#define DISP_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/dispdefs.h>
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target, through communication
++ * with the Resource Manager Server running on the target. Each NODE
++ * Manager object should have exactly one NODE Dispatcher.
++ *
++ * Parameters:
++ * phDispObject: Location to store node dispatcher object on output.
++ * hDevObject: Device for this processor.
++ * pDispAttrs: Node dispatcher attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Unable to create dispatcher.
++ * Requires:
++ * DISP_Init(void) called.
++ * pDispAttrs != NULL.
++ * hDevObject != NULL.
++ * phDispObject != NULL.
++ * Ensures:
++ * DSP_SOK: IsValid(*phDispObject).
++ * error: *phDispObject == NULL.
++ */
++ extern DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs);
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * Returns:
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * Ensures:
++ * hDispObject is invalid.
++ */
++ extern void DISP_Delete(struct DISP_OBJECT *hDispObject);
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DISP_Init(void) previously called.
++ * Ensures:
++ * Any resources acquired in DISP_Init(void) will be freed when last DISP
++ * client calls DISP_Exit(void).
++ */
++ extern void DISP_Exit(void);
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool DISP_Init(void);
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * allocated or running on the DSP.
++ * ulFxnAddress: Address of RMS function for changing priority.
++ * nodeEnv: Address of node's environment structure.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT
++ *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ NODE_ENV nodeEnv,
++ s32 nPriority);
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node handle obtained from NODE_Allocate().
++ * ulFxnAddr: Address or RMS create node function.
++ * ulCreateFxn: Address of node's create function.
++ * pArgs: Arguments to pass to RMS node create function.
++ * pNodeEnv: Location to store node environment pointer on
++ * output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETASK: Unable to create the node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER: A user-defined failure occurred.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * pArgs != NULL.
++ * hNode != NULL.
++ * pNodeEnv != NULL.
++ * NODE_GetType(hNode) != NODE_DEVICE.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS
++ *pArgs,
++ OUT NODE_ENV *pNodeEnv);
++
++/*
++ * ======== DISP_NodeDelete ========
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * loaded on the DSP.
++ * ulFxnAddr: Address or RMS delete node function.
++ * ulDeleteFxn: Address of node's delete function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulDeleteFxn, NODE_ENV nodeEnv);
++
++/*
++ * ======== DISP_NodeRun ========
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node to be executed
++ * on the DSP.
++ * ulFxnAddr: Address or RMS node execute function.
++ * ulExecuteFxn: Address of node's execute function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulExecuteFxn, NODE_ENV nodeEnv);
++
++#endif /* DISP_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dispdefs.h b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+new file mode 100644
+index 0000000..401ad4f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+@@ -0,0 +1,45 @@
++/*
++ * dispdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dispdefs.h ========
++ * Description:
++ * Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Aug-2000 jeh Added fields to DISP_ATTRS.
++ *! 06-Jul-2000 jeh Created.
++ */
++
++#ifndef DISPDEFS_
++#define DISPDEFS_
++
++ struct DISP_OBJECT;
++
++/* Node Dispatcher attributes */
++ struct DISP_ATTRS {
++ u32 ulChnlOffset; /* Offset of channel ids reserved for RMS */
++ /* Size of buffer for sending data to RMS */
++ u32 ulChnlBufSize;
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++ } ;
++
++#endif /* DISPDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dmm.h b/arch/arm/plat-omap/include/dspbridge/dmm.h
+new file mode 100644
+index 0000000..ef37668
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dmm.h
+@@ -0,0 +1,85 @@
++/*
++ * dmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dmm.h ========
++ * Purpose:
++ * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ *
++ *! Revision History:
++ *! ================
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++#ifndef DMM_
++#define DMM_
++
++#include <dspbridge/dbdefs.h>
++
++ struct DMM_OBJECT;
++
++/* DMM attributes used in DMM_Create() */
++ struct DMM_MGRATTRS {
++ u32 reserved;
++ } ;
++
++#define DMMPOOLSIZE 0x4000000
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++
++ extern DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr);
++
++ extern DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 size,
++ u32 *pRsvAddr);
++
++ extern DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 rsvAddr);
++
++ extern DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr,
++ u32 size);
++
++ extern DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 addr,
++ u32 *pSize);
++
++ extern DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs);
++
++ extern bool DMM_Init(void);
++
++ extern void DMM_Exit(void);
++
++ extern DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr,
++ u32 addr, u32 size);
++ extern u32 *DMM_GetPhysicalAddrTable(void);
++#endif /* DMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dpc.h b/arch/arm/plat-omap/include/dspbridge/dpc.h
+new file mode 100644
+index 0000000..8c20506
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dpc.h
+@@ -0,0 +1,167 @@
++/*
++ * dpc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpc.h ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ * Public Functions:
++ * DPC_Cancel
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: DPC_Destroy ensures Suceess and DPC Object is NULL.
++ *! 21-Jan-2000 ag: Updated comments per code review.
++ *! 06-Jan-2000 ag: Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 14-Jan-1998 gp: Added DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 18-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 28-Jul-1996 gp: Created.
++ */
++
++#ifndef DPC_
++#define DPC_
++
++ struct DPC_OBJECT;
++
++/*
++ * ======== DPC_PROC ========
++ * Purpose:
++ * Deferred processing routine. Typically scheduled from an ISR to
++ * complete I/O processing.
++ * Parameters:
++ * pRefData: Ptr to user data: passed in via ISR_ScheduleDPC.
++ * Returns:
++ * Requires:
++ * The DPC should not block, or otherwise acquire resources.
++ * Interrupts to the processor are enabled.
++ * DPC_PROC executes in a critical section.
++ * Ensures:
++ * This DPC will not be reenterred on the same thread.
++ * However, the DPC may take hardware interrupts during execution.
++ * Interrupts to the processor are enabled.
++ */
++ typedef void(*DPC_PROC) (void *pRefData);
++
++/*
++ * ======== DPC_Cancel ========
++ * Purpose:
++ * Cancel a DPC previously scheduled by DPC_Schedule.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Scheduled DPC, if any, is cancelled.
++ * DSP_SFALSE: No DPC is currently scheduled for execution.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * Ensures:
++ * If the DPC has already executed, is executing, or was not yet
++ * scheduled, this function will have no effect.
++ */
++ extern DSP_STATUS DPC_Cancel(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ * Parameters:
++ * phDPC: Pointer to location to store DPC object.
++ * pfnDPC: Client's DPC procedure.
++ * pRefData: Pointer to user-defined reference data.
++ * Returns:
++ * DSP_SOK: DPC object created.
++ * DSP_EPOINTER: phDPC == NULL or pfnDPC == NULL.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Must not be called at interrupt time.
++ * Ensures:
++ * DSP_SOK: DPC object is created;
++ * else: *phDPC is set to NULL.
++ */
++ extern DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC,
++ IN DPC_PROC pfnDPC,
++ IN void *pRefData);
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create().Frees the Object only if the thread and
++ * the events are terminated successfuly.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * All DPC's scheduled for the DPC object must have completed their
++ * processing.
++ * Ensures:
++ * (SUCCESS && hDPC is NULL) or DSP_EFAILED status
++ */
++ extern DSP_STATUS DPC_Destroy(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DPC_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in DPC_Init(void) are freed.
++ */
++ extern void DPC_Exit(void);
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public DPC functions.
++ */
++ extern bool DPC_Init(void);
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: An event is scheduled for deferred processing.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * See requirements for DPC_PROC.
++ * Ensures:
++ * DSP_SOK: The DPC will not be called before this function returns.
++ */
++ extern DSP_STATUS DPC_Schedule(IN struct DPC_OBJECT *hDPC);
++
++#endif /* DPC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
+new file mode 100644
+index 0000000..c468461
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drv.h
+@@ -0,0 +1,449 @@
++/*
++ * drv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.h ========
++ * Purpose:
++ * DRV Resource allocation module. Driver Object gets Created
++ * at the time of Loading. It holds the List of Device Objects
++ * in the Syste,
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ================
++ *! 10-Feb-2004 vp: Added OMAP24xx specific definitions.
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 27-Jul-2000 rr: DRV_RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 12-Nov-1999 rr: New Flag defines for DRV_ASSIGN and DRV_RELEASE
++ *! 25-Oct-1999 rr: Resource Structure removed.
++ *! 15-Oct-1999 rr: New Resource structure created.
++ *! 05-Oct-1999 rr: Added DRV_RequestResources
++ *! Removed fxn'sDRV_RegisterMiniDriver(),
++ *! DRV_UnRegisterMiniDriver()
++ *! Removed Structures DSP_DRIVER & DRV_EXTENSION.
++ *!
++ *! 24-Sep-1999 rr: Added DRV_EXTENSION and DSP_DRIVER structures.
++ *!
++ */
++
++#ifndef DRV_
++#define DRV_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/drvdefs.h>
++
++#define DRV_ASSIGN 1
++#define DRV_RELEASE 0
++
++/* Provide the DSP Internal memory windows that can be accessed from L3 address
++ * space */
++
++#define OMAP_GEM_BASE 0x107F8000
++#define OMAP_DSP_SIZE 0x00720000
++
++/* MEM1 is L2 RAM + L2 Cache space */
++#define OMAP_DSP_MEM1_BASE 0x5C7F8000
++#define OMAP_DSP_MEM1_SIZE 0x18000
++#define OMAP_DSP_GEM1_BASE 0x107F8000
++
++
++/* MEM2 is L1P RAM/CACHE space */
++#define OMAP_DSP_MEM2_BASE 0x5CE00000
++#define OMAP_DSP_MEM2_SIZE 0x8000
++#define OMAP_DSP_GEM2_BASE 0x10E00000
++
++/* MEM3 is L1D RAM/CACHE space */
++#define OMAP_DSP_MEM3_BASE 0x5CF04000
++#define OMAP_DSP_MEM3_SIZE 0x14000
++#define OMAP_DSP_GEM3_BASE 0x10F04000
++
++
++#define OMAP_IVA2_PRM_BASE 0x48306000
++#define OMAP_IVA2_PRM_SIZE 0x1000
++
++#define OMAP_IVA2_CM_BASE 0x48004000
++#define OMAP_IVA2_CM_SIZE 0x1000
++
++#define OMAP_PER_CM_BASE 0x48005000
++#define OMAP_PER_CM_SIZE 0x1000
++
++#define OMAP_PER_PRM_BASE 0x48307000
++#define OMAP_PER_PRM_SIZE 0x1000
++
++#define OMAP_CORE_PRM_BASE 0x48306A00
++#define OMAP_CORE_PRM_SIZE 0x1000
++
++#define OMAP_SYSC_BASE 0x48002000
++#define OMAP_SYSC_SIZE 0x1000
++
++#define OMAP_MBOX_BASE 0x48094000
++#define OMAP_MBOX_SIZE 0x1000
++
++#define OMAP_DMMU_BASE 0x5D000000
++#define OMAP_DMMU_SIZE 0x1000
++
++#define OMAP_PRCM_VDD1_DOMAIN 1
++#define OMAP_PRCM_VDD2_DOMAIN 2
++
++#ifndef RES_CLEANUP_DISABLE
++
++/* GPP PROCESS CLEANUP Data structures */
++
++/* New structure (member of process context) abstracts NODE resource info */
++struct NODE_RES_OBJECT {
++ DSP_HNODE hNode;
++ s32 nodeAllocated; /* Node status */
++ s32 heapAllocated; /* Heap status */
++ s32 streamsAllocated; /* Streams status */
++ struct NODE_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DMM_RES_OBJECT {
++ s32 dmmAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 dmmSize;
++ HANDLE hProcessor;
++ struct DMM_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DSPHEAP_RES_OBJECT {
++ s32 heapAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 heapSize;
++ HANDLE hProcessor;
++ struct DSPHEAP_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts stream resource info */
++struct STRM_RES_OBJECT {
++ s32 streamAllocated; /* Stream status */
++ DSP_HSTREAM hStream;
++ u32 uNumBufs;
++ u32 uDir;
++ struct STRM_RES_OBJECT *next;
++} ;
++
++/* Overall Bridge process resource usage state */
++enum GPP_PROC_RES_STATE {
++ PROC_RES_ALLOCATED,
++ PROC_RES_FREED
++} ;
++
++/* Process Context */
++struct PROCESS_CONTEXT{
++ /* Process State */
++ enum GPP_PROC_RES_STATE resState;
++
++ /* Process ID (Same as UNIX process ID) */
++ u32 pid;
++
++ /* Pointer to next process context
++ * (To maintain a linked list of process contexts) */
++ struct PROCESS_CONTEXT *next;
++
++ /* Processor info to which the process is related */
++ DSP_HPROCESSOR hProcessor;
++
++ /* DSP Node resources */
++ struct NODE_RES_OBJECT *pNodeList;
++
++ /* DMM resources */
++ struct DMM_RES_OBJECT *pDMMList;
++
++ /* DSP Heap resources */
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
++
++ /* Stream resources */
++ struct STRM_RES_OBJECT *pSTRMList;
++} ;
++#endif
++
++/*
++ * ======== DRV_Create ========
++ * Purpose:
++ * Creates the Driver Object. This is done during the driver loading.
++ * There is only one Driver Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phDrvObject: Location to store created DRV Object handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EMEMORY: Failed in Memory allocation
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * DRV Initialized (cRefs > 0 )
++ * phDrvObject != NULL.
++ * Ensures:
++ * DSP_SOK: - *phDrvObject is a valid DRV interface to the device.
++ * - List of DevObject Created and Initialized.
++ * - List of DevNode String created and intialized.
++ * - Registry is updated with the DRV Object.
++ * !DSP_SOK: DRV Object not created
++ * Details:
++ * There is one Driver Object for the Driver representing
++ * the driver itself. It contains the list of device
++ * Objects and the list of Device Extensions in the system.
++ * Also it can hold other neccessary
++ * information in its storage area.
++ */
++ extern DSP_STATUS DRV_Create(struct DRV_OBJECT **phDrvObject);
++
++/*
++ * ======== DRV_Destroy ========
++ * Purpose:
++ * destroys the Dev Object list, DrvExt list
++ * and destroy the DRV object
++ * Called upon driver unLoading.or unsuccesful loading of the driver.
++ * Parameters:
++ * hDrvObject: Handle to Driver object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to destroy DRV Object
++ * Requires:
++ * DRV Initialized (cRegs > 0 )
++ * hDrvObject is not NULL and a valid DRV handle .
++ * List of DevObject is Empty.
++ * List of DrvExt is Empty
++ * Ensures:
++ * DSP_SOK: - DRV Object destroyed and hDrvObject is not a valid
++ * DRV handle.
++ * - Registry is updated with "0" as the DRV Object.
++ */
++ extern DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Exit the DRV module, freeing any modules initialized in DRV_Init.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern void DRV_Exit(void);
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Returns the Ptr to the FirstDev Object in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevObject: Ptr to the First Dev Object as a u32
++ * 0 if it fails to retrieve the First Dev Object
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevObject(void);
++
++/*
++ * ======== DRV_GetFirstDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the First Device Extension in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevExtension: Ptr to the First Device Extension as a u32
++ * 0: Failed to Get the Device Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevExtension(void);
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list
++ * Parameters:
++ * hDrvObject: Handle to the Manager
++ * phDevObject: Location to store the Dev Handle
++ * Requires:
++ * DRV Initialized
++ * uIndex >= 0
++ * hDrvObject is not NULL and Valid DRV Object
++ * phDevObject is not NULL
++ * Device Object List not Empty
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Failed to Get the Dev Object
++ * Ensures:
++ * DSP_SOK: *phDevObject != NULL
++ * DSP_EFAIL: *phDevObject = NULL
++ */
++ extern DSP_STATUS DRV_GetDevObject(u32 uIndex,
++ struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Object from the the List
++ * Parameters:
++ * hDevObject: Handle to the Device Object
++ * Requires:
++ * DRV Initialized
++ * hDevObject != 0
++ * Returns:
++ * dwDevObject: Ptr to the Next Dev Object as a u32
++ * 0: If it fail to get the next Dev Object.
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevObject(u32 hDevObject);
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Extension from the the List
++ * Parameters:
++ * hDevExtension: Handle to the Device Extension
++ * Requires:
++ * DRV Initialized
++ * hDevExtension != 0.
++ * Returns:
++ * dwDevExtension: Ptr to the Next Dev Extension
++ * 0: If it fail to Get the next Dev Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevExtension(u32 hDevExtension);
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize the DRV module.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DRV_Init(void);
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DeviceObject into the list of Driver object.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DeviceObject to insert.
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL: General Failure:
++ * Requires:
++ * hDrvObject != NULL and Valid DRV Handle.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Device Object is inserted and the List is not empty.
++ */
++ extern DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a Device object from the given list of Device Obj
++ * objects.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DevObject to Remove
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to find pDevObject.
++ * Requires:
++ * hDrvObject != NULL and a Valid DRV Handle.
++ * hDevObject != NULL.
++ * List exists and is not empty.
++ * Ensures:
++ * List either does not exist (NULL), or is not empty if it does exist.
++*/
++ extern DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * pDevNodeString: Ptr to DevNode String stored in the Device Ext.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are assigned based on Bus type.
++ * The hardware is initialized. Resource information is
++ * gathered from the Registry(ISA, PCMCIA)or scanned(PCI)
++ * Resource structure is stored in the registry which will be
++ * later used by the CFG module.
++ */
++ extern DSP_STATUS DRV_RequestResources(IN u32 dwContext,
++ OUT u32 *pDevNodeString);
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * hDrvObject: Handle to the Driver Object.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are released based on Bus type.
++ * Resource structure is deleted from the registry
++ */
++ extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
++ struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_ProcFreeDMMRes ========
++ * Purpose:
++ * Actual DMM De-Allocation.
++ * Parameters:
++ * hPCtxt: Path to the driver Registry Key.
++ * Returns:
++ * DSP_SOK if success;
++ */
++
++
++ extern DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt);
++
++#endif /* DRV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drvdefs.h b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+new file mode 100644
+index 0000000..ed86010
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+@@ -0,0 +1,34 @@
++/*
++ * drvdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drvdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and drv.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Jul-2000 rr: Created
++ */
++
++#ifndef DRVDEFS_
++#define DRVDEFS_
++
++/* WCD Driver Object */
++ struct DRV_OBJECT;
++
++#endif /* DRVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dspdrv.h b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+new file mode 100644
+index 0000000..f500ffb
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+@@ -0,0 +1,106 @@
++/*
++ * dspdrv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.h ========
++ * Purpose:
++ * This is the Stream Interface for the DDSP Class driver.
++ * All Device operations are performed via DeviceIOControl.
++ * Read, Seek and Write not used.
++ *
++ * Public Functions
++ * DSP_Close
++ * DSP_Deinit
++ * DSP_Init
++ * DSP_IOControl
++ * DSP_Open
++ * DSP_PowerUp
++ * DSP_PowerDown
++ *
++ *! Revision History
++ *! ================
++ *! 28-Jan-2000 rr: Type void changed to Void.
++ *! 02-Dec-1999 rr: MAX_DEV define moved from wcdce.c file.Code cleaned up.
++ *! 12-Nov-1999 rr: "#include<wncnxerr.h> removed.
++ *! 05-Oct-1999 rr Renamed the file name to wcdce.h Removed Bus Specific
++ *! code and #defines to PCCARD.h.
++ *! 24-Sep-1999 rr Changed the DSP_COMMON_WINDOW_SIZE to 0x4000(16k) for the
++ *! Memory windows.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet driver.
++ *!
++ */
++
++#if !defined __DSPDRV_h__
++#define __DSPDRV_h__
++
++#define MAX_DEV 10 /* Max support of 10 devices */
++
++/*
++ * ======== DSP_Close ========
++ * Purpose:
++ * Called when the client application/driver unloads the DDSP DLL. Upon
++ * unloading, the DDSP DLL will call CloseFile().
++ * Parameters:
++ * dwDeviceContext: Handle returned by XXX_Open used to identify
++ * the open context of the device
++ * Returns:
++ * TRUE indicates the device is successfully closed. FALSE indicates
++ * otherwise.
++ * Requires:
++ * dwOpenContext!= NULL.
++ * Ensures:The Application instance owned objects are cleaned up.
++ */
++extern bool DSP_Close(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Deinit ========
++ * Purpose:
++ * This function is called by Device Manager to de-initialize a device.
++ * This function is not called by applications.
++ * Parameters:
++ * dwDeviceContext:Handle to the device context. The XXX_Init function
++ * creates and returns this identifier.
++ * Returns:
++ * TRUE indicates the device successfully de-initialized. Otherwise it
++ * returns FALSE.
++ * Requires:
++ * dwDeviceContext!= NULL. For a built in device this should never
++ * get called.
++ * Ensures:
++ */
++extern bool DSP_Deinit(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Init ========
++ * Purpose:
++ * This function is called by Device Manager to initialize a device.
++ * This function is not called by applications
++ * Parameters:
++ * dwContext: Specifies a pointer to a string containing the registry
++ * path to the active key for the stream interface driver.
++ * HKEY_LOCAL_MACHINE\Drivers\Active
++ * Returns:
++ * Returns a handle to the device context created. This is the our actual
++ * Device Object representing the DSP Device instance.
++ * Requires:
++ * Ensures:
++ * Succeeded: device context > 0
++ * Failed: device Context = 0
++ */
++extern u32 DSP_Init(OUT u32 *initStatus);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+new file mode 100644
+index 0000000..ea5f77f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+@@ -0,0 +1,505 @@
++/*
++ * dynamic_loader.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DYNAMIC_LOADER_H_
++#define _DYNAMIC_LOADER_H_
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++/*
++ * Dynamic Loader
++ *
++ * The function of the dynamic loader is to load a "module" containing
++ * instructions for a "target" processor into that processor. In the process
++ * it assigns memory for the module, resolves symbol references made by the
++ * module, and remembers symbols defined by the module.
++ *
++ * The dynamic loader is parameterized for a particular system by 4 classes
++ * that supply the module and system specific functions it requires
++ */
++ /* The read functions for the module image to be loaded */
++ struct Dynamic_Loader_Stream;
++
++ /* This class defines "host" symbol and support functions */
++ struct Dynamic_Loader_Sym;
++
++ /* This class defines the allocator for "target" memory */
++ struct Dynamic_Loader_Allocate;
++
++ /* This class defines the copy-into-target-memory functions */
++ struct Dynamic_Loader_Initialize;
++
++/*
++ * Option flags to modify the behavior of module loading
++ */
++#define DLOAD_INITBSS 0x1 /* initialize BSS sections to zero */
++#define DLOAD_BIGEND 0x2 /* require big-endian load module */
++#define DLOAD_LITTLE 0x4 /* require little-endian load module */
++
++ typedef void *DLOAD_mhandle; /* module handle for loaded modules */
++
++/*****************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Load_Module(
++ /* the source for the module image*/
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage*/
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags*/
++ /* the returned module handle*/
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Open_Module(
++ /* the source for the module image */
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator */
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer */
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags */
++ /* the returned module handle */
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Unload_Module(DLOAD_mhandle mhandle, /* the module
++ * handle*/
++ /* host support for symbols and
++ * storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init
++ );
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for input of the module image
++ *****************************************************************************
++ *****************************************************************************/
++ struct Dynamic_Loader_Stream {
++/* public: */
++ /*************************************************************************
++ * read_buffer
++ *
++ * PARAMETERS :
++ * buffer Pointer to the buffer to fill
++ * bufsiz Amount of data desired in sizeof() units
++ *
++ * EFFECT :
++ * Reads the specified amount of data from the module input stream
++ * into the specified buffer. Returns the amount of data read in sizeof()
++ * units (which if less than the specification, represents an error).
++ *
++ * NOTES:
++ * In release 1 increments the file position by the number of bytes read
++ *
++ *************************************************************************/
++ int (*read_buffer) (struct Dynamic_Loader_Stream *thisptr,
++ void *buffer, unsigned bufsiz);
++
++ /*************************************************************************
++ * set_file_posn (release 1 only)
++ *
++ * PARAMETERS :
++ * posn Desired file position relative to start of file in sizeof() units.
++ *
++ * EFFECT :
++ * Adjusts the internal state of the stream object so that the next
++ * read_buffer call will begin to read at the specified offset from
++ * the beginning of the input module. Returns 0 for success, non-zero
++ * for failure.
++ *
++ *************************************************************************/
++ int (*set_file_posn) (struct Dynamic_Loader_Stream *thisptr,
++ /* to be eliminated in release 2*/
++ unsigned int posn);
++
++ };
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for symbol table support and
++ * miscellaneous host-side functions
++ *****************************************************************************
++ *****************************************************************************/
++
++ typedef u32 LDR_ADDR;
++
++/*
++ * the structure of a symbol known to the dynamic loader
++ */
++ struct dynload_symbol {
++ LDR_ADDR value;
++ } ;
++
++ struct Dynamic_Loader_Sym {
++/* public: */
++ /*************************************************************************
++ * Find_Matching_Symbol
++ *
++ * PARAMETERS :
++ * name The name of the desired symbol
++ *
++ * EFFECT :
++ * Locates a symbol matching the name specified. A pointer to the
++ * symbol is returned if it exists; 0 is returned if no such symbol is
++ * found.
++ *
++ *************************************************************************/
++ struct dynload_symbol *(*Find_Matching_Symbol)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *name);
++
++ /*************************************************************************
++ * Add_To_Symbol_Table
++ *
++ * PARAMETERS :
++ * nname Pointer to the name of the new symbol
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * The new symbol is added to the table. A pointer to the symbol is
++ * returned, or NULL is returned for failure.
++ *
++ * NOTES:
++ * It is permissible for this function to return NULL; the effect is that
++ * the named symbol will not be available to resolve references in
++ * subsequent loads. Returning NULL will not cause the current load
++ * to fail.
++ *************************************************************************/
++ struct dynload_symbol *(*Add_To_Symbol_Table)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *nname,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Purge_Symbol_Table
++ *
++ * PARAMETERS :
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * Each symbol in the symbol table whose moduleid matches the argument
++ * is removed from the table.
++ *************************************************************************/
++ void (*Purge_Symbol_Table) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Allocate
++ *
++ * PARAMETERS :
++ * memsiz size of desired memory in sizeof() units
++ *
++ * EFFECT :
++ * Returns a pointer to some "host" memory for use by the dynamic
++ * loader, or NULL for failure.
++ * This function is serves as a replaceable form of "malloc" to
++ * allow the user to configure the memory usage of the dynamic loader.
++ *************************************************************************/
++ void *(*Allocate) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned memsiz);
++
++ /*************************************************************************
++ * Deallocate
++ *
++ * PARAMETERS :
++ * memptr pointer to previously allocated memory
++ *
++ * EFFECT :
++ * Releases the previously allocated "host" memory.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Sym *thisptr,
++ void *memptr);
++
++ /*************************************************************************
++ * Error_Report
++ *
++ * PARAMETERS :
++ * errstr pointer to an error string
++ * args additional arguments
++ *
++ * EFFECT :
++ * This function provides an error reporting interface for the dynamic
++ * loader. The error string and arguments are designed as for the
++ * library function vprintf.
++ *************************************************************************/
++ void (*Error_Report) (struct Dynamic_Loader_Sym *thisptr,
++ const char *errstr, va_list args);
++
++ }; /* class Dynamic_Loader_Sym */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to allocate and deallocate target memory.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct LDR_SECTION_INFO {
++ /* Name of the memory section assigned at build time */
++ const char *name;
++ LDR_ADDR run_addr; /* execution address of the section */
++ LDR_ADDR load_addr; /* load address of the section */
++ LDR_ADDR size; /* size of the section in addressable units */
++#ifndef _BIG_ENDIAN
++ u16 page; /* memory page or view */
++ u16 type; /* one of the section types below */
++#else
++ u16 type; /* one of the section types below */
++ u16 page; /* memory page or view */
++#endif
++ /* a context field for use by Dynamic_Loader_Allocate;
++ * ignored but maintained by the dynamic loader */
++ u32 context;
++ } ;
++
++/* use this macro to extract type of section from LDR_SECTION_INFO.type field */
++#define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
++
++/* type of section to be allocated */
++#define DLOAD_TEXT 0
++#define DLOAD_DATA 1
++#define DLOAD_BSS 2
++ /* internal use only, run-time cinit will be of type DLOAD_DATA */
++#define DLOAD_CINIT 3
++
++ struct Dynamic_Loader_Allocate {
++/* public: */
++
++ /*************************************************************************
++ * Function allocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ * align The alignment of the storage in target AUs
++ *
++ * Effect:
++ * Allocates target memory for the specified section and fills in the
++ * load_addr and run_addr fields of the section info structure. Returns TRUE
++ * for success, FALSE for failure.
++ *
++ * Notes:
++ * Frequently load_addr and run_addr are the same, but if they are not
++ * load_addr is used with Dynamic_Loader_Initialize, and run_addr is
++ * used for almost all relocations. This function should always initialize
++ * both fields.
++ *************************************************************************/
++ int (*Allocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info, unsigned align);
++
++ /*************************************************************************
++ * Function deallocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ *
++ * Effect:
++ * Releases the target memory previously allocated.
++ *
++ * Notes:
++ * The content of the info->name field is undefined on call to this function.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info);
++
++ }; /* class Dynamic_Loader_Allocate */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to load data into a target. This class
++ * provides the interface-specific functions needed to load data.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct Dynamic_Loader_Initialize {
++/* public: */
++ /*************************************************************************
++ * Function connect
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Connect to the initialization interface. Returns TRUE for success,
++ * FALSE for failure.
++ *
++ * Notes:
++ * This function is called prior to use of any other functions in
++ * this interface.
++ *************************************************************************/
++ int (*connect) (struct Dynamic_Loader_Initialize *thisptr);
++
++ /*************************************************************************
++ * Function readmem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer for the result
++ * locn Target address of first data element
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be read in sizeof() units
++ *
++ * Effect:
++ * Fills the specified buffer with data from the target. Returns TRUE for
++ * success, FALSE for failure.
++ *************************************************************************/
++ int (*readmem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function writemem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer of data
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ *
++ * Effect:
++ * Writes the specified buffer to the target. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*writemem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function fillmem
++ *
++ * Parameters:
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ * val Value to be written in each byte
++ * Effect:
++ * Fills the specified area of target memory. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*fillmem) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info,
++ unsigned bytsiz, unsigned val);
++
++ /*************************************************************************
++ * Function execute
++ *
++ * Parameters:
++ * start Starting address
++ *
++ * Effect:
++ * The target code at the specified starting address is executed.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process
++ * if the input module has specified a starting address.
++ *************************************************************************/
++ int (*execute) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR start);
++
++ /*************************************************************************
++ * Function release
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Releases the connection to the load interface.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process.
++ *************************************************************************/
++ void (*release) (struct Dynamic_Loader_Initialize *thisptr);
++
++ }; /* class Dynamic_Loader_Initialize */
++
++#endif /* _DYNAMIC_LOADER_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/errbase.h b/arch/arm/plat-omap/include/dspbridge/errbase.h
+new file mode 100644
+index 0000000..f04c005
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/errbase.h
+@@ -0,0 +1,509 @@
++/*
++ * errbase.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== errbase.h ========
++ * Description:
++ * Central repository for DSP/BIOS Bridge error and status code.
++ *
++ * Error codes are of the form:
++ * [<MODULE>]_E<ERRORCODE>
++ *
++ * Success codes are of the form:
++ * [<MODULE>]_S<SUCCESSCODE>
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Jan-2003 map Added DSP_SALREADYLOADED for persistent library checking
++ *! 23-Nov-2002 gp: Minor comment cleanup.
++ *! 13-May-2002 sg Added DSP_SALREADYASLEEP and DSP_SALREADYWAKE.
++ *! 18-Feb-2002 mk: Added DSP_EOVERLAYMEMORY, EFWRITE, ENOSECT.
++ *! 31-Jan-2002 mk: Added definitions of DSP_STRUE and DSP_SFALSE.
++ *! 29-Jan-2002 mk: Added definition of CFG_E_INSUFFICIENTBUFSIZE.
++ *! 24-Oct-2001 sp: Consolidated all the error codes into this file.
++ *! 24-Jul-2001 mk: Type-casted all definitions of WSX_STATUS types for
++ *! removal of compile warnings.
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 18-Aug-1999 rr: Ported From WSX.
++ *! 29-May-1996 gp: Removed WCD_ and WMD_ error ranges. Redefined format of
++ *! error codes.
++ *! 10-May-1996 gp: Created.
++ */
++
++#ifndef ERRBASE_
++#define ERRBASE_
++
++/* Base of generic errors and component errors */
++#define DSP_SBASE (DSP_STATUS)0x00008000
++#define DSP_EBASE (DSP_STATUS)0x80008000
++
++#define DSP_COMP_EBASE (DSP_STATUS)0x80040200
++#define DSP_COMP_ELAST (DSP_STATUS)0x80047fff
++
++/* SUCCESS Codes */
++
++/* Generic success code */
++#define DSP_SOK (DSP_SBASE + 0)
++
++/* GPP is already attached to this DSP processor */
++#define DSP_SALREADYATTACHED (DSP_SBASE + 1)
++
++/* This is the last object available for enumeration. */
++#define DSP_SENUMCOMPLETE (DSP_SBASE + 2)
++
++/* The DSP is already asleep. */
++#define DSP_SALREADYASLEEP (DSP_SBASE + 3)
++
++/* The DSP is already awake. */
++#define DSP_SALREADYAWAKE (DSP_SBASE + 4)
++
++/* TRUE */
++#define DSP_STRUE (DSP_SBASE + 5)
++
++/* FALSE */
++#define DSP_SFALSE (DSP_SBASE + 6)
++
++/* A library contains no dependent library references */
++#define DSP_SNODEPENDENTLIBS (DSP_SBASE + 7)
++
++/* A persistent library is already loaded by the dynamic loader */
++#define DSP_SALREADYLOADED (DSP_SBASE + 8)
++
++/* Some error occured, but it is OK to continue */
++#define DSP_OKTO_CONTINUE (DSP_SBASE + 9)
++
++/* FAILURE Codes */
++
++/* The caller does not have access privileges to call this function */
++#define DSP_EACCESSDENIED (DSP_EBASE + 0)
++
++/* The Specified Connection already exists */
++#define DSP_EALREADYCONNECTED (DSP_EBASE + 1)
++
++/* The GPP must be detached from the DSP before this function is called */
++#define DSP_EATTACHED (DSP_EBASE + 2)
++
++/* During enumeration a change in the number or properties of the objects
++ * has occurred. */
++#define DSP_ECHANGEDURINGENUM (DSP_EBASE + 3)
++
++/* An error occurred while parsing the DSP executable file */
++#define DSP_ECORRUPTFILE (DSP_EBASE + 4)
++
++/* A failure occurred during a delete operation */
++#define DSP_EDELETE (DSP_EBASE + 5)
++
++/* The specified direction is invalid */
++#define DSP_EDIRECTION (DSP_EBASE + 6)
++
++/* A stream has been issued the maximum number of buffers allowed in the
++ * stream at once ; buffers must be reclaimed from the stream before any
++ * more can be issued. */
++#define DSP_ESTREAMFULL (DSP_EBASE + 7)
++
++/* A general failure occurred */
++#define DSP_EFAIL (DSP_EBASE + 8)
++
++/* The specified executable file could not be found. */
++#define DSP_EFILE (DSP_EBASE + 9)
++
++/* The specified handle is invalid. */
++#define DSP_EHANDLE (DSP_EBASE + 0xa)
++
++/* An invalid argument was specified. */
++#define DSP_EINVALIDARG (DSP_EBASE + 0xb)
++
++/* A memory allocation failure occurred. */
++#define DSP_EMEMORY (DSP_EBASE + 0xc)
++
++/* The requested operation is invalid for this node type. */
++#define DSP_ENODETYPE (DSP_EBASE + 0xd)
++
++/* No error text was found for the specified error code. */
++#define DSP_ENOERRTEXT (DSP_EBASE + 0xe)
++
++/* No more connections can be made for this node. */
++#define DSP_ENOMORECONNECTIONS (DSP_EBASE + 0xf)
++
++/* The indicated operation is not supported. */
++#define DSP_ENOTIMPL (DSP_EBASE + 0x10)
++
++/* I/O is currently pending. */
++#define DSP_EPENDING (DSP_EBASE + 0x11)
++
++/* An invalid pointer was specified. */
++#define DSP_EPOINTER (DSP_EBASE + 0x12)
++
++/* A parameter is specified outside its valid range. */
++#define DSP_ERANGE (DSP_EBASE + 0x13)
++
++/* An invalid size parameter was specified. */
++#define DSP_ESIZE (DSP_EBASE + 0x14)
++
++/* A stream creation failure occurred on the DSP. */
++#define DSP_ESTREAM (DSP_EBASE + 0x15)
++
++/* A task creation failure occurred on the DSP. */
++#define DSP_ETASK (DSP_EBASE + 0x16)
++
++/* A timeout occurred before the requested operation could complete. */
++
++#define DSP_ETIMEOUT (DSP_EBASE + 0x17)
++
++/* A data truncation occurred, e.g., when requesting a descriptive error
++ * string, not enough space was allocated for the complete error message. */
++
++#define DSP_ETRUNCATED (DSP_EBASE + 0x18)
++
++/* A parameter is invalid. */
++#define DSP_EVALUE (DSP_EBASE + 0x1a)
++
++/* The state of the specified object is incorrect for the requested
++ * operation. */
++#define DSP_EWRONGSTATE (DSP_EBASE + 0x1b)
++
++/* Symbol not found in the COFF file. DSPNode_Create will return this if
++ * the iAlg function table for an xDAIS socket is not found in the COFF file.
++ * In this case, force the symbol to be linked into the COFF file.
++ * DSPNode_Create, DSPNode_Execute, and DSPNode_Delete will return this if
++ * the create, execute, or delete phase function, respectively, could not be
++ * found in the COFF file. */
++#define DSP_ESYMBOL (DSP_EBASE + 0x1c)
++
++/* UUID not found in registry. */
++#define DSP_EUUID (DSP_EBASE + 0x1d)
++
++/* Unable to read content of DCD data section ; this is typically caused by
++ * improperly configured nodes. */
++#define DSP_EDCDREADSECT (DSP_EBASE + 0x1e)
++
++/* Unable to decode DCD data section content ; this is typically caused by
++ * changes to DSP/BIOS Bridge data structures. */
++#define DSP_EDCDPARSESECT (DSP_EBASE + 0x1f)
++
++/* Unable to get pointer to DCD data section ; this is typically caused by
++ * improperly configured UUIDs. */
++#define DSP_EDCDGETSECT (DSP_EBASE + 0x20)
++
++/* Unable to load file containing DCD data section ; this is typically
++ * caused by a missing COFF file. */
++#define DSP_EDCDLOADBASE (DSP_EBASE + 0x21)
++
++/* The specified COFF file does not contain a valid node registration
++ * section. */
++#define DSP_EDCDNOAUTOREGISTER (DSP_EBASE + 0x22)
++
++/* A requested resource is not available. */
++#define DSP_ERESOURCE (DSP_EBASE + 0x28)
++
++/* A critical error has occurred, and the DSP is being re-started. */
++#define DSP_ERESTART (DSP_EBASE + 0x29)
++
++/* A DSP memory free operation failed. */
++#define DSP_EFREE (DSP_EBASE + 0x2a)
++
++/* A DSP I/O free operation failed. */
++#define DSP_EIOFREE (DSP_EBASE + 0x2b)
++
++/* Multiple instances are not allowed. */
++#define DSP_EMULINST (DSP_EBASE + 0x2c)
++
++/* A specified entity was not found. */
++#define DSP_ENOTFOUND (DSP_EBASE + 0x2d)
++
++/* A DSP I/O resource is not available. */
++#define DSP_EOUTOFIO (DSP_EBASE + 0x2e)
++
++/* A shared memory buffer contained in a message or stream could not be
++ * mapped to the GPP client process's virtual space. */
++#define DSP_ETRANSLATE (DSP_EBASE + 0x2f)
++
++/* File or section load write function failed to write to DSP */
++#define DSP_EFWRITE (DSP_EBASE + 0x31)
++
++/* Unable to find a named section in DSP executable */
++#define DSP_ENOSECT (DSP_EBASE + 0x32)
++
++/* Unable to open file */
++#define DSP_EFOPEN (DSP_EBASE + 0x33)
++
++/* Unable to read file */
++#define DSP_EFREAD (DSP_EBASE + 0x34)
++
++/* A non-existent memory segment identifier was specified */
++#define DSP_EOVERLAYMEMORY (DSP_EBASE + 0x37)
++
++/* Invalid segment ID */
++#define DSP_EBADSEGID (DSP_EBASE + 0x38)
++
++/* Invalid alignment */
++#define DSP_EALIGNMENT (DSP_EBASE + 0x39)
++
++/* Invalid stream mode */
++#define DSP_ESTRMMODE (DSP_EBASE + 0x3a)
++
++/* Nodes not connected */
++#define DSP_ENOTCONNECTED (DSP_EBASE + 0x3b)
++
++/* Not shared memory */
++#define DSP_ENOTSHAREDMEM (DSP_EBASE + 0x3c)
++
++/* Error occurred in a dynamic loader library function */
++#define DSP_EDYNLOAD (DSP_EBASE + 0x3d)
++
++/* Device in 'sleep/suspend' mode due to DPM */
++#define DSP_EDPMSUSPEND (DSP_EBASE + 0x3e)
++
++/* A node-specific error has occurred. */
++#define DSP_EUSER1 (DSP_EBASE + 0x40)
++#define DSP_EUSER2 (DSP_EBASE + 0x41)
++#define DSP_EUSER3 (DSP_EBASE + 0x42)
++#define DSP_EUSER4 (DSP_EBASE + 0x43)
++#define DSP_EUSER5 (DSP_EBASE + 0x44)
++#define DSP_EUSER6 (DSP_EBASE + 0x45)
++#define DSP_EUSER7 (DSP_EBASE + 0x46)
++#define DSP_EUSER8 (DSP_EBASE + 0x47)
++#define DSP_EUSER9 (DSP_EBASE + 0x48)
++#define DSP_EUSER10 (DSP_EBASE + 0x49)
++#define DSP_EUSER11 (DSP_EBASE + 0x4a)
++#define DSP_EUSER12 (DSP_EBASE + 0x4b)
++#define DSP_EUSER13 (DSP_EBASE + 0x4c)
++#define DSP_EUSER14 (DSP_EBASE + 0x4d)
++#define DSP_EUSER15 (DSP_EBASE + 0x4e)
++#define DSP_EUSER16 (DSP_EBASE + 0x4f)
++
++/* FAILURE Codes : DEV */
++#define DEV_EBASE (DSP_COMP_EBASE + 0x000)
++
++/* The mini-driver expected a newer version of the class driver. */
++#define DEV_E_NEWWMD (DEV_EBASE + 0x00)
++
++/* WMD_DRV_Entry function returned a NULL function interface table. */
++#define DEV_E_NULLWMDINTF (DEV_EBASE + 0x01)
++
++/* FAILURE Codes : LDR */
++#define LDR_EBASE (DSP_COMP_EBASE + 0x100)
++
++/* Insufficient memory to export class driver services. */
++#define LDR_E_NOMEMORY (LDR_EBASE + 0x00)
++
++/* Unable to find WMD file in system directory. */
++#define LDR_E_FILEUNABLETOOPEN (LDR_EBASE + 0x01)
++
++/* FAILURE Codes : CFG */
++#define CFG_EBASE (DSP_COMP_EBASE + 0x200)
++
++/* Invalid pointer passed into a configuration module function */
++#define CFG_E_INVALIDPOINTER (CFG_EBASE + 0x00)
++
++/* Invalid device node handle passed into a configuration module function. */
++#define CFG_E_INVALIDHDEVNODE (CFG_EBASE + 0x01)
++
++/* Unable to retrieve resource information from the registry. */
++#define CFG_E_RESOURCENOTAVAIL (CFG_EBASE + 0x02)
++
++/* Unable to find board name key in registry. */
++#define CFG_E_INVALIDBOARDNAME (CFG_EBASE + 0x03)
++
++/* Unable to find a device node in registry with given unit number. */
++#define CFG_E_INVALIDUNITNUM (CFG_EBASE + 0x04)
++
++/* Insufficient buffer size */
++#define CFG_E_INSUFFICIENTBUFSIZE (CFG_EBASE + 0x05)
++
++/* FAILURE Codes : BRD */
++#define BRD_EBASE (DSP_COMP_EBASE + 0x300)
++
++/* Board client does not have sufficient access rights for this operation. */
++#define BRD_E_ACCESSDENIED (BRD_EBASE + 0x00)
++
++/* Unable to find trace buffer symbols in the DSP executable COFF file. */
++#define BRD_E_NOTRACEBUFFER (BRD_EBASE + 0x01)
++
++/* Attempted to auto-start board, but no default DSP executable configured. */
++#define BRD_E_NOEXEC (BRD_EBASE + 0x02)
++
++/* The operation failed because it was started from a wrong state */
++#define BRD_E_WRONGSTATE (BRD_EBASE + 0x03)
++
++/* FAILURE Codes : COD */
++#define COD_EBASE (DSP_COMP_EBASE + 0x400)
++
++/* No symbol table is loaded for this board. */
++#define COD_E_NOSYMBOLSLOADED (COD_EBASE + 0x00)
++
++/* Symbol not found in for this board. */
++#define COD_E_SYMBOLNOTFOUND (COD_EBASE + 0x01)
++
++/* ZL DLL module is not exporting the correct function interface. */
++#define COD_E_NOZLFUNCTIONS (COD_EBASE + 0x02)
++
++/* Unable to initialize the ZL COFF parsing module. */
++#define COD_E_ZLCREATEFAILED (COD_EBASE + 0x03)
++
++/* Unable to open DSP executable COFF file. */
++#define COD_E_OPENFAILED (COD_EBASE + 0x04)
++
++/* Unable to parse DSP executable COFF file. */
++#define COD_E_LOADFAILED (COD_EBASE + 0x05)
++
++/* Unable to read DSP executable COFF file. */
++#define COD_E_READFAILED (COD_EBASE + 0x06)
++
++/* FAILURE Codes : CHNL */
++#define CHNL_EBASE (DSP_COMP_EBASE + 0x500)
++
++/* Attempt to created channel manager with too many channels. */
++#define CHNL_E_MAXCHANNELS (CHNL_EBASE + 0x00)
++
++/* No channel manager exists for this mini-driver. */
++#define CHNL_E_NOMGR (CHNL_EBASE + 0x01)
++
++/* No free channels are available. */
++#define CHNL_E_OUTOFSTREAMS (CHNL_EBASE + 0x02)
++
++/* Channel ID is out of range. */
++#define CHNL_E_BADCHANID (CHNL_EBASE + 0x03)
++
++/* Channel is already in use. */
++#define CHNL_E_CHANBUSY (CHNL_EBASE + 0x04)
++
++/* Invalid channel mode argument. */
++#define CHNL_E_BADMODE (CHNL_EBASE + 0x05)
++
++/* dwTimeOut parameter was CHNL_IOCNOWAIT, yet no I/O completions were
++ * queued. */
++#define CHNL_E_NOIOC (CHNL_EBASE + 0x06)
++
++/* I/O has been cancelled on this channel. */
++#define CHNL_E_CANCELLED (CHNL_EBASE + 0x07)
++
++/* End of stream was already requested on this output channel. */
++#define CHNL_E_EOS (CHNL_EBASE + 0x09)
++
++/* Unable to create the channel event object. */
++#define CHNL_E_CREATEEVENT (CHNL_EBASE + 0x0A)
++
++/* Board name and unit number do not identify a valid board name. */
++#define CHNL_E_BRDID (CHNL_EBASE + 0x0B)
++
++/* Invalid IRQ configured for this WMD for this system. */
++#define CHNL_E_INVALIDIRQ (CHNL_EBASE + 0x0C)
++
++/* DSP word size of zero configured for this device. */
++#define CHNL_E_INVALIDWORDSIZE (CHNL_EBASE + 0x0D)
++
++/* A zero length memory base was specified for a shared memory class driver. */
++#define CHNL_E_INVALIDMEMBASE (CHNL_EBASE + 0x0E)
++
++/* Memory map is not configured, or unable to map physical to linear
++ * address. */
++#define CHNL_E_NOMEMMAP (CHNL_EBASE + 0x0F)
++
++/* Attempted to create a channel manager when one already exists. */
++#define CHNL_E_MGREXISTS (CHNL_EBASE + 0x10)
++
++/* Unable to plug channel ISR for configured IRQ. */
++#define CHNL_E_ISR (CHNL_EBASE + 0x11)
++
++/* No free I/O request packets are available. */
++#define CHNL_E_NOIORPS (CHNL_EBASE + 0x12)
++
++/* Buffer size is larger than the size of physical channel. */
++#define CHNL_E_BUFSIZE (CHNL_EBASE + 0x13)
++
++/* User cannot mark end of stream on an input channel. */
++#define CHNL_E_NOEOS (CHNL_EBASE + 0x14)
++
++/* Wait for flush operation on an output channel timed out. */
++#define CHNL_E_WAITTIMEOUT (CHNL_EBASE + 0x15)
++
++/* User supplied hEvent must be specified with pstrEventName attribute */
++#define CHNL_E_BADUSEREVENT (CHNL_EBASE + 0x16)
++
++/* Illegal user event name specified */
++#define CHNL_E_USEREVENTNAME (CHNL_EBASE + 0x17)
++
++/* Unable to prepare buffer specified */
++#define CHNL_E_PREPFAILED (CHNL_EBASE + 0x18)
++
++/* Unable to Unprepare buffer specified */
++#define CHNL_E_UNPREPFAILED (CHNL_EBASE + 0x19)
++
++/* FAILURE Codes : SYNC */
++#define SYNC_EBASE (DSP_COMP_EBASE + 0x600)
++
++/* Wait on a kernel event failed. */
++#define SYNC_E_FAIL (SYNC_EBASE + 0x00)
++
++/* Timeout expired while waiting for event to be signalled. */
++#define SYNC_E_TIMEOUT (SYNC_EBASE + 0x01)
++
++/* FAILURE Codes : WMD */
++#define WMD_EBASE (DSP_COMP_EBASE + 0x700)
++
++/* A test of hardware assumptions or integrity failed. */
++#define WMD_E_HARDWARE (WMD_EBASE + 0x00)
++
++/* One or more configuration parameters violated WMD hardware assumptions. */
++#define WMD_E_BADCONFIG (WMD_EBASE + 0x01)
++
++/* Timeout occurred waiting for a response from the hardware. */
++#define WMD_E_TIMEOUT (WMD_EBASE + 0x02)
++
++/* FAILURE Codes : REG */
++#define REG_EBASE (DSP_COMP_EBASE + 0x800)
++
++/* Invalid subkey parameter. */
++#define REG_E_INVALIDSUBKEY (REG_EBASE + 0x00)
++
++/* Invalid entry parameter. */
++#define REG_E_INVALIDENTRY (REG_EBASE + 0x01)
++
++/* No more registry values. */
++#define REG_E_NOMOREITEMS (REG_EBASE + 0x02)
++
++/* Insufficient space to hold data in registry value. */
++#define REG_E_MOREDATA (REG_EBASE + 0x03)
++
++/* FAILURE Codes : KFILE */
++#define KFILE_EBASE (DSP_COMP_EBASE + 0x900)
++
++/* Invalid file handle. */
++#define E_KFILE_INVALIDHANDLE (KFILE_EBASE + 0x01)
++
++/* Bad file name. */
++#define E_KFILE_BADFILENAME (KFILE_EBASE + 0x02)
++
++/* Invalid file mode. */
++#define E_KFILE_INVALIDMODE (KFILE_EBASE + 0x03)
++
++/* No resources available. */
++#define E_KFILE_NORESOURCES (KFILE_EBASE + 0x04)
++
++/* Invalid file buffer . */
++#define E_KFILE_INVALIDBUFFER (KFILE_EBASE + 0x05)
++
++/* Bad origin argument. */
++#define E_KFILE_BADORIGINFLAG (KFILE_EBASE + 0x06)
++
++/* Invalid file offset value. */
++#define E_KFILE_INVALIDOFFSET (KFILE_EBASE + 0x07)
++
++/* General KFILE error condition */
++#define E_KFILE_ERROR (KFILE_EBASE + 0x08)
++
++#endif /* ERRBASE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gb.h b/arch/arm/plat-omap/include/dspbridge/gb.h
+new file mode 100644
+index 0000000..f147751
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gb.h
+@@ -0,0 +1,85 @@
++/*
++ * gb.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gb.h ========
++ * Generic bitmap manager.
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GB_
++#define GB_
++
++#define GB_NOBITS (~0)
++#include <dspbridge/host_os.h>
++typedef s32 GB_BitNum;
++struct GB_TMap;
++
++/*
++ * ======== GB_clear ========
++ * Clear the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_clear(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_create ========
++ * Create a bit map with len bits. Initially all bits are cleared.
++ */
++
++extern struct GB_TMap *GB_create(GB_BitNum len);
++
++/*
++ * ======== GB_delete ========
++ * Delete previously created bit map
++ */
++
++extern void GB_delete(struct GB_TMap *map);
++
++/*
++ * ======== GB_findandset ========
++ * Finds a clear bit, sets it, and returns the position
++ */
++
++extern GB_BitNum GB_findandset(struct GB_TMap *map);
++
++/*
++ * ======== GB_minclear ========
++ * GB_minclear returns the minimum clear bit position. If no bit is
++ * clear, GB_minclear returns -1.
++ */
++extern GB_BitNum GB_minclear(struct GB_TMap *map);
++
++/*
++ * ======== GB_set ========
++ * Set the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_set(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_test ========
++ * Returns TRUE if the bit in position bitn is set in map; otherwise
++ * GB_test returns FALSE. Bit positions are zero based.
++ */
++
++extern bool GB_test(struct GB_TMap *map, GB_BitNum bitn);
++
++#endif /*GB_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/getsection.h b/arch/arm/plat-omap/include/dspbridge/getsection.h
+new file mode 100644
+index 0000000..33ff50d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/getsection.h
+@@ -0,0 +1,118 @@
++/*
++ * getsection.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _GETSECTION_H_
++#define _GETSECTION_H_
++
++
++#include "dynamic_loader.h"
++
++/*
++ * Get Section Information
++ *
++ * This file provides an API add-on to the dynamic loader that allows the user
++ * to query section information and extract section data from dynamic load
++ * modules.
++ *
++ * NOTE:
++ * Functions in this API assume that the supplied Dynamic_Loader_Stream object
++ * supports the set_file_posn method.
++ */
++
++ /* opaque handle for module information */
++ typedef void *DLOAD_module_info;
++
++/*
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ */
++ extern DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream
++ *module,
++ struct Dynamic_Loader_Sym
++ *syms);
++
++/*
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and fills in
++ * the provided LDR_SECTION_INFO structure.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSectionInfo(DLOAD_module_info minfo,
++ const char *sectionName,
++ const struct LDR_SECTION_INFO
++ ** const sectionInfo);
++
++/*
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo,
++ void *sectionData);
++
++/*
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ */
++ extern void DLOAD_module_close(DLOAD_module_info minfo);
++
++#endif /* _GETSECTION_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gh.h b/arch/arm/plat-omap/include/dspbridge/gh.h
+new file mode 100644
+index 0000000..089a042
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gh.h
+@@ -0,0 +1,37 @@
++/*
++ * gh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GH_
++#define GH_
++#include <dspbridge/host_os.h>
++
++extern struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash) (void *, u16), bool(*match) (void *, void *),
++ void(*delete) (void *));
++extern void GH_delete(struct GH_THashTab *hashTab);
++extern void GH_exit(void);
++extern void *GH_find(struct GH_THashTab *hashTab, void *key);
++extern void GH_init(void);
++extern void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value);
++#endif /* GH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gs.h b/arch/arm/plat-omap/include/dspbridge/gs.h
+new file mode 100644
+index 0000000..fd5ef27
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gs.h
+@@ -0,0 +1,64 @@
++/*
++ * gs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gs.h ========
++ * Memory allocation/release wrappers. This module allows clients to
++ * avoid OS spacific issues related to memory allocation. It also provides
++ * simple diagnostic capabilities to assist in the detection of memory
++ * leaks.
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GS_
++#define GS_
++
++/*
++ * ======== GS_alloc ========
++ * Alloc size bytes of space. Returns pointer to space
++ * allocated, otherwise NULL.
++ */
++extern void *GS_alloc(u32 size);
++
++/*
++ * ======== GS_exit ========
++ * Module exit. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_exit(void);
++
++/*
++ * ======== GS_free ========
++ * Free space allocated by GS_alloc() or GS_calloc().
++ */
++extern void GS_free(void *ptr);
++
++/*
++ * ======== GS_frees ========
++ * Free space allocated by GS_alloc() or GS_calloc() and assert that
++ * the size of the allocation is size bytes.
++ */
++extern void GS_frees(void *ptr, u32 size);
++
++/*
++ * ======== GS_init ========
++ * Module initialization. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_init(void);
++
++#endif /*GS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gt.h b/arch/arm/plat-omap/include/dspbridge/gt.h
+new file mode 100644
+index 0000000..456c866
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gt.h
+@@ -0,0 +1,315 @@
++/*
++ * gt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.h ========
++ * Purpose:
++ * There are two definitions that affect which portions of trace
++ * are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
++ * GT_TRACE is set to 0 then all trace statements (except for assertions)
++ * will be compiled out of the client. If GT_ASSERT is set to 0 then
++ * assertions will be compiled out of the client. GT_ASSERT can not be
++ * set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
++ * GT_ASSERT == 1).
++ *
++ *! Revision History
++ *! ================
++ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace definitions
++ *! are WinCE Specific.
++ *! 03-Jan-1997 ge Replaced "GT_" prefix to GT_Config structure members
++ *! to eliminate preprocessor confusion with other macros.
++ */
++#include <linux/types.h>
++#ifndef GT_
++#define GT_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++#include <dspbridge/host_os.h>
++
++#if !defined(GT_ASSERT) || GT_TRACE
++#define GT_ASSERT 1
++#endif
++
++struct GT_Config {
++ Fxn PRINTFXN;
++ Fxn PIDFXN;
++ Fxn TIDFXN;
++ Fxn ERRORFXN;
++};
++
++extern struct GT_Config *GT;
++
++struct GT_Mask {
++ char *modName;
++ u8 *flags;
++} ;
++
++/*
++ * New GT Class defenitions.
++ *
++ * The following are the explanations and how it could be used in the code
++ *
++ * - GT_ENTER On Entry to Functions
++ *
++ * - GT_1CLASS Display level of debugging status- Object/Automatic
++ * variables
++ * - GT_2CLASS ---- do ----
++ *
++ * - GT_3CLASS ---- do ---- + It can be used(recommended) for debug
++ * status in the ISR, IST
++ * - GT_4CLASS ---- do ----
++ *
++ * - GT_5CLASS Display entry for module init/exit functions
++ *
++ * - GT_6CLASS Warn whenever SERVICES function fails
++ *
++ * - GT_7CLASS Warn failure of Critical failures
++ *
++ */
++
++#define GT_ENTER ((u8)0x01)
++#define GT_1CLASS ((u8)0x02)
++#define GT_2CLASS ((u8)0x04)
++#define GT_3CLASS ((u8)0x08)
++#define GT_4CLASS ((u8)0x10)
++#define GT_5CLASS ((u8)0x20)
++#define GT_6CLASS ((u8)0x40)
++#define GT_7CLASS ((u8)0x80)
++
++#ifdef _LINT_
++
++/* LINTLIBRARY */
++
++/*
++ * ======== GT_assert ========
++ */
++/* ARGSUSED */
++void GT_assert(struct GT_Mask mask, s32 expr)
++{
++}
++
++/*
++ * ======== GT_config ========
++ */
++/* ARGSUSED */
++void GT_config(struct GT_Config config)
++{
++}
++
++/*
++ * ======== GT_create ========
++ */
++/* ARGSUSED */
++void GT_create(struct GT_Mask *mask, char *modName)
++{
++}
++
++/*
++ * ======== GT_curLine ========
++ * Purpose:
++ * Returns the current source code line number. Is useful for performing
++ * branch testing using trace. For example,
++ *
++ * GT_1trace(curTrace, GT_1CLASS,
++ * "in module XX_mod, executing line %u\n", GT_curLine());
++ */
++/* ARGSUSED */
++u16 GT_curLine(void)
++{
++ return (u16)NULL;
++}
++
++/*
++ * ======== GT_exit ========
++ */
++/* ARGSUSED */
++void GT_exit(void)
++{
++}
++
++/*
++ * ======== GT_init ========
++ */
++/* ARGSUSED */
++void GT_init(void)
++{
++}
++
++/*
++ * ======== GT_query ========
++ */
++/* ARGSUSED */
++bool GT_query(struct GT_Mask mask, u8 class)
++{
++ return false;
++}
++
++/*
++ * ======== GT_set ========
++ * sets trace mask according to settings
++ */
++
++/* ARGSUSED */
++void GT_set(char *settings)
++{
++}
++
++/*
++ * ======== GT_setprintf ========
++ * sets printf function
++ */
++
++/* ARGSUSED */
++void GT_setprintf(Fxn fxn)
++{
++}
++
++/* ARGSUSED */
++void GT_0trace(struct GT_Mask mask, u8 class, char *format)
++{
++}
++
++/* ARGSUSED */
++void GT_1trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_2trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_3trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_4trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_5trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_6trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++#else
++
++#define GT_BOUND 26 /* 26 letters in alphabet */
++
++extern void _GT_create(struct GT_Mask *mask, char *modName);
++
++#define GT_exit()
++
++extern void GT_init(void);
++extern void _GT_set(char *str);
++extern s32 _GT_trace(struct GT_Mask *mask, char *format, ...);
++
++#if GT_ASSERT == 0
++
++#define GT_assert(mask, expr)
++#define GT_config(config)
++#define GT_configInit(config)
++#define GT_seterror(fxn)
++
++#else
++
++extern struct GT_Config _GT_params;
++
++#define GT_assert(mask, expr) \
++ (!(expr) ? \
++ printk("assertion violation: %s, line %d\n", \
++ __FILE__, __LINE__), NULL : NULL)
++
++#define GT_config(config) (_GT_params = *(config))
++#define GT_configInit(config) (*(config) = _GT_params)
++#define GT_seterror(fxn) (_GT_params.ERRORFXN = (Fxn)(fxn))
++
++#endif
++
++#if GT_TRACE == 0
++
++#define GT_curLine() ((u16)__LINE__)
++#define GT_create(mask, modName)
++#define GT_exit()
++#define GT_init()
++#define GT_set(settings)
++#define GT_setprintf(fxn)
++
++#define GT_query(mask, class) false
++
++#define GT_0trace(mask, class, format)
++#define GT_1trace(mask, class, format, arg1)
++#define GT_2trace(mask, class, format, arg1, arg2)
++#define GT_3trace(mask, class, format, arg1, arg2, arg3)
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4)
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
++
++#else /* GT_TRACE == 1 */
++
++
++#define GT_create(mask, modName) _GT_create((mask), (modName))
++#define GT_curLine() ((u16)__LINE__)
++#define GT_set(settings) _GT_set(settings)
++#define GT_setprintf(fxn) (_GT_params.PRINTFXN = (Fxn)(fxn))
++
++#define GT_query(mask, class) ((*(mask).flags & (class)))
++
++#define GT_0trace(mask, class, format) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format)) : 0)
++
++#define GT_1trace(mask, class, format, arg1) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1)) : 0)
++
++#define GT_2trace(mask, class, format, arg1, arg2) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
++
++#define GT_3trace(mask, class, format, arg1, arg2, arg3) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
++
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
++
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) : 0)
++
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
++ (arg6)) : 0)
++
++#endif /* GT_TRACE */
++
++#endif /* _LINT_ */
++
++#endif /* GTCE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/host_os.h b/arch/arm/plat-omap/include/dspbridge/host_os.h
+new file mode 100644
+index 0000000..f539bd0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/host_os.h
+@@ -0,0 +1,96 @@
++/*
++ * host_os.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== windows.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
++ *! 16-Feb-2004 sb Added headers required for consistent_alloc
++ */
++
++#ifndef _HOST_OS_H_
++#define _HOST_OS_H_
++
++#include <linux/autoconf.h>
++#include <asm/system.h>
++#include <asm/atomic.h>
++#include <linux/semaphore.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/syscalls.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/device.h>
++#include <linux/vmalloc.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <dspbridge/dbtype.h>
++#include <mach/clock.h>
++#include <linux/clk.h>
++#include <linux/pagemap.h>
++#include <asm/cacheflush.h>
++#include <linux/dma-mapping.h>
++
++/* ----------------------------------- Macros */
++
++#define SEEK_SET 0 /* Seek from beginning of file. */
++#define SEEK_CUR 1 /* Seek from current position. */
++#define SEEK_END 2 /* Seek from end of file. */
++
++/* TODO -- Remove, once BP defines them */
++#define INT_MAIL_MPU_IRQ 26
++#define INT_DSP_MMU_IRQ 28
++
++struct dspbridge_platform_data {
++ void (*dsp_set_min_opp)(u8 opp_id);
++ u8 (*dsp_get_opp)(void);
++ void (*cpu_set_freq)(unsigned long f);
++ unsigned long (*cpu_get_freq)(void);
++ unsigned long mpu_speed[6];
++
++ u32 phys_mempool_base;
++ u32 phys_mempool_size;
++};
++
++#define PRCM_VDD1 1
++
++extern struct platform_device *omap_dspbridge_dev;
++
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++extern void dspbridge_reserve_sdram(void);
++#else
++static inline void dspbridge_reserve_sdram(void) {}
++#endif
++
++extern unsigned long dspbridge_get_mempool_base(void);
++#endif
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/io.h b/arch/arm/plat-omap/include/dspbridge/io.h
+new file mode 100644
+index 0000000..6dc63f2
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io.h
+@@ -0,0 +1,132 @@
++/*
++ * io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.h ========
++ * Description:
++ * The io module manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IO_
++#define IO_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/iodefs.h>
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on
++ * output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: IO manager attributes.
++ * pMgrAttrs->bIRQ: I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * Requires:
++ * IO_Init(void) called.
++ * phIOMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Destroy the IO manager.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr);
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * IO_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in IO_Init(void), are freed when the last
++ * client of IO calls IO_Exit(void).
++ */
++ extern void IO_Exit(void);
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool IO_Init(void);
++
++/*
++ * ======== IO_OnLoaded ========
++ * Purpose:
++ * Called when a program is loaded so IO manager can update its
++ * internal state.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/io_sm.h b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+new file mode 100644
+index 0000000..3dcbf74
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+@@ -0,0 +1,335 @@
++/*
++ * io_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io_sm.h ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ * Also, includes macros to simulate SHM via port io calls.
++ *
++ * Public Functions:
++ * IO_Dispatch
++ * IO_DPC
++ * IO_ISR
++ * IO_RequestChnl
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Mar-2004 vp: Added IVA releated functions.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 06-Feb-2003 kc Added IO_DDMAClearChnlDesc and IO_DDZCClearChnlDesc.
++ *! 21-Dec-2001 ag Removed unused param in IO_DDMAInitChnlDesc().
++ * Updated comments. Removed #ifdef CHNL_NOIPCINTR.
++ *! 05-Nov-2001 kc Updated IO_CALLISR macro.
++ *! 01-May-2001 jeh Removed IO_RequestMsg.
++ *! 29-Mar-2001 ag Added #ifdef CHNL_NOIPCINTR.
++ *! 04-Dec-2000 jeh Added IO_RequestMsg.
++ *! 26-Oct-2000 jeh Added IO_GetLong, IO_SetLong, IO_ReadValueLong, and
++ *! IO_WriteValueLong, for passing arg in SHM structure.
++ *! 20-Jan-2000 ag: Updated header comments per code review.
++ *! 05-Jan-2000 ag: Text format clean-up.
++ *! 02-Nov-1999 ag: Updated header descriptions.
++ *! 25-May-1999 jg: Removed assumption of 4 bytes / word.
++ *! 12-Aug-1996 gp: Created.
++ */
++
++#ifndef IOSM_
++#define IOSM_
++
++#include <dspbridge/_chnl_sm.h>
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/iodefs.h>
++
++#define IO_INPUT 0
++#define IO_OUTPUT 1
++#define IO_SERVICE 2
++#define IO_MAXSERVICE IO_SERVICE
++
++#define IO_MGRSIGNATURE 0x494f4D43 /* "IOGR" */
++
++#define DSPFieldAddr(type, field, base, wordsize) \
++ ((((s32)&(((type *)0)->field)) / wordsize) + (u32)base)
++
++/* Access can be different SM access word size (e.g. 16/32 bit words) */
++#define IO_SetValue(pContext, type, base, field, value) (base->field = value)
++#define IO_GetValue(pContext, type, base, field) (base->field)
++#define IO_OrValue(pContext, type, base, field, value) (base->field |= value)
++#define IO_AndValue(pContext, type, base, field, value) (base->field &= value)
++#define IO_SetLong(pContext, type, base, field, value) (base->field = value)
++#define IO_GetLong(pContext, type, base, field) (base->field)
++
++#define IO_DisableInterrupt(h) CHNLSM_DisableInterrupt(h)
++#define IO_EnableInterrupt(h) CHNLSM_EnableInterrupt(h)
++#define IO_CALLISR(h, pFlag, pwMBRegVal) CHNLSM_ISR(h, pFlag, pwMBRegVal)
++
++/*
++ * ======== IO_CancelChnl ========
++ * Purpose:
++ * Cancel IO on a given channel.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * ulChnl: Index of channel to cancel IO on.
++ * Returns:
++ * Requires:
++ * Valid hIOMgr.
++ * Ensures:
++ */
++ extern void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl);
++
++/*
++ * ======== IO_DPC ========
++ * Purpose:
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O.
++ * Parameters:
++ * pRefData: Pointer to reference data registered via a call to
++ * DPC_Create().
++ * Returns:
++ * Requires:
++ * Must not block.
++ * Must not acquire resources.
++ * All data touched must be locked in memory if running in kernel mode.
++ * Ensures:
++ * Non-preemptible (but interruptible).
++ */
++ extern void IO_DPC(IN OUT void *pRefData);
++
++/*
++ * ======== IO_ISR ========
++ * Purpose:
++ * Main interrupt handler for the shared memory WMD channel manager.
++ * Calls the WMD's CHNLSM_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O..
++ * Parameters:
++ * pRefData: Pointer to the channel manager object for this board.
++ * Set in an initial call to ISR_Install().
++ * Returns:
++ * TRUE if interrupt handled; FALSE otherwise.
++ * Requires:
++ * Must be in locked memory if executing in kernel mode.
++ * Must only call functions which are in locked memory if Kernel mode.
++ * Must only call asynchronous services.
++ * Interrupts are disabled and EOI for this interrupt has been sent.
++ * Ensures:
++ */
++ irqreturn_t IO_ISR(int irq, IN void *pRefData);
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request I/O from the DSP. Sets flags in shared memory, then interrupts
++ * the DSP.
++ * Parameters:
++ * hIOMgr: IO manager handle.
++ * pChnl: Ptr to the channel requesting I/O.
++ * iMode: Mode of channel: {IO_INPUT | IO_OUTPUT}.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_RequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_Schedule ========
++ * Purpose:
++ * Schedule DPC for IO.
++ * Parameters:
++ * pIOMgr: Ptr to a I/O manager.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_Schedule(struct IO_MGR *hIOMgr);
++
++/*
++ * DSP-DMA IO functions
++ */
++
++/*
++ * ======== IO_DDMAInitChnlDesc ========
++ * Purpose:
++ * Initialize DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * uNumDesc: Number of buffer descriptors(equals # of IOReqs &
++ * Chirps)
++ * pDsp: Dsp address;
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * uNumDesc > 0
++ * pVa != NULL
++ * pDspPa != NULL
++ *
++ * Ensures:
++ */
++ extern void IO_DDMAInitChnlDesc(struct IO_MGR *hIOMgr, u32 uDDMAChnlId,
++ u32 uNumDesc, void *pDsp);
++
++/*
++ * ======== IO_DDMAClearChnlDesc ========
++ * Purpose:
++ * Clear DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * Ensures:
++ */
++ extern void IO_DDMAClearChnlDesc(struct IO_MGR *hIOMgr,
++ u32 uDDMAChnlId);
++
++/*
++ * ======== IO_DDMARequestChnl ========
++ * Purpose:
++ * Request channel DSP-DMA from the DSP. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDMARequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * Zero-copy IO functions
++ */
++
++/*
++ * ======== IO_DDZCInitChnlDesc ========
++ * Purpose:
++ * Initialize ZCPY channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uZId: zero-copy channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXZCPYCHNLS
++ * hIOMgr != Null
++ * Ensures:
++ */
++ extern void IO_DDZCInitChnlDesc(struct IO_MGR *hIOMgr, u32 uZId);
++
++/*
++ * ======== IO_DDZCClearChnlDesc ========
++ * Purpose:
++ * Clear DSP ZC channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uChnlId: ZC channel identifier.
++ * Returns:
++ * Requires:
++ * hIOMgr is valid
++ * uChnlId < DDMA_MAXZCPYCHNLS
++ * Ensures:
++ */
++ extern void IO_DDZCClearChnlDesc(struct IO_MGR *hIOMgr, u32 uChnlId);
++
++/*
++ * ======== IO_DDZCRequestChnl ========
++ * Purpose:
++ * Request zero-copy channel transfer. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDZCRequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_SHMsetting ========
++ * Purpose:
++ * Sets the shared memory setting
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * desc: Shared memory type
++ * pArgs: Ptr to SHM setting
++ * Returns:
++ * Requires:
++ * hIOMgr != NULL
++ * pArgs != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr,
++ IN enum SHM_DESCTYPE desc,
++ IN void *pArgs);
++
++/*
++ * Misc functions for the CHNL_IO shared memory library:
++ */
++
++/* Maximum channel bufsize that can be used. */
++ extern u32 IO_BufSize(struct IO_MGR *hIOMgr);
++
++ extern u32 IO_ReadValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern u32 IO_ReadValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_OrSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_AndSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal);
++
++ extern void IO_SM_init(void);
++
++/*
++ * ========PrintDspTraceBuffer ========
++ * Print DSP tracebuffer.
++ */
++ extern DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT
++ *hWmdContext);
++
++#endif /* IOSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/iodefs.h b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+new file mode 100644
+index 0000000..f45890a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+@@ -0,0 +1,45 @@
++/*
++ * iodefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== iodefs.h ========
++ * Description:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IODEFS_
++#define IODEFS_
++
++#define IO_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* IO Objects: */
++ struct IO_MGR;
++
++/* IO manager attributes: */
++ struct IO_ATTRS {
++ u8 bIRQ; /* Channel's I/O IRQ number. */
++ bool fShared; /* TRUE if the IRQ is shareable. */
++ u32 uWordSize; /* DSP Word size. */
++ u32 dwSMBase; /* Physical base address of shared memory. */
++ u32 uSMLength; /* Size (in bytes) of shared memory. */
++ } ;
++
++#endif /* IODEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/kfile.h b/arch/arm/plat-omap/include/dspbridge/kfile.h
+new file mode 100644
+index 0000000..23c89b0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/kfile.h
+@@ -0,0 +1,216 @@
++/*
++ * kfile.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfile.h ========
++ * Purpose:
++ * Provide file I/O management capabilities.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ * KFILE_Write
++ *
++ * Notes:
++ * The KFILE module is not like most of the other DSP/BIOS Bridge modules
++ * in that it doesn't return WSX_STATUS type values. Rather, it's
++ * prototypes are meant to match the stdio file prototypes
++ * (ie, fopen, fclose, etc.).
++ *
++ *! Revision History
++ *! ================
++ *! 29-Oct-1999 kc: Clean up for code review.
++ *! 07-Jan-1998 cr: Clean up for code review.
++ *! 15-Aug-1997 cr: Added E_KFILE_ERROR for general error condition.
++ *! 04-Aug-1997 cr: Added explicit CDECL descriptions.
++ *! 11-Nov-1996 cr: Implemented changes based on code review.
++ *! 05-Nov-1996 cr: Cleaned up for code review.
++ *! 29-May-1996 gp: Added requirement that size != 0 in _Write() and _Read().
++ *! 28-May-1996 mg: Changed return values for Read/Write.
++ *! 14-Dec-1995 cr: Created.
++ */
++
++#ifndef KFILE_
++#define KFILE_
++
++/*
++ * Constants for KFILE_Seek. Note that these MUST be the same definitions as
++ * those defined for fseek.
++ */
++#define KFILE_SEEK_SET 0x00 /* seek from beginning of file */
++#define KFILE_SEEK_CUR 0x01 /* seek from current position */
++#define KFILE_SEEK_END 0x02 /* seek from end of file */
++
++ struct KFILE_FileObj;
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * 0: success.
++ * E_KFILE_ERROR: unable to close specified handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Close(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void KFILE_Exit(void);
++
++/*
++ * ======== KFILE_Init ========
++ * Purpose:
++ * Initializes private state of KFILE module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * KFILE initialized.
++ */
++ extern bool KFILE_Init(void);
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Opens a file for use.
++ * Parameters:
++ * pszFileName: Full path to name of the file to open.
++ * pszMode: String containing open status. Only the first
++ * character of the string is examined, for either
++ * "r" (read) or "w" (write) mode.
++ * Returns:
++ * A valid file handle if success, else NULL.
++ * Requires:
++ * - KFILE initialized.
++ * - pszMode != NULL.
++ * - pszFileName != NULL.
++ * Ensures:
++ */
++ extern struct KFILE_FileObj *KFILE_Open(IN CONST char *filename,
++ IN CONST char *mode);
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * This function reads a specified number of bytes into a buffer.
++ * Parameters:
++ * pBuffer: Array to which the file data is copied.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to read in.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects read from file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer is a valid pointer.
++ * Ensures:
++ */
++ extern s32 KFILE_Read(OUT void __user*buffer,
++ IN s32 size, IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * This function sets the file position indicator. NOTE: we don't
++ * support seeking beyond the boundaries of a file.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * offset: Number of bytes from the origin to move.
++ * origin: File reference point, one of the following values:
++ * KFILE_SEEK_SET: Seek from beginning of file.
++ * KFILE_SEEK_CUR: Seek from current position.
++ * KFILE_SEEK_END: Seek from end of file.
++ * Returns:
++ * 0: success.
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * E_KFILE_BADORIGIN: invalid origin paramater.
++ * E_KFILE_ERROR: general failure.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Seek(IN struct KFILE_FileObj *hFile,
++ IN s32 offset, IN s32 origin);
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * This function reports the current value of the position indicator.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Return value:
++ * > 0: success; returns # of bytes the position indicator is from
++ * beginning of file.
++ * E_KFILE_ERROR: general failure.
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Tell(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Write ========
++ * Purpose:
++ * This function writes a number of objects to the stream.
++ * Parameters:
++ * pBuffer: Array from which the file data is written.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to write out.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects written to file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer != NULL.
++ * Postcondition:
++ * The file position indicator is advanced by the number of
++ * characters written.
++ */
++ extern s32 KFILE_Write(OUT void *buffer,
++ IN s32 size,
++ IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++#endif /* KFILE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ldr.h b/arch/arm/plat-omap/include/dspbridge/ldr.h
+new file mode 100644
+index 0000000..7e13c93
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ldr.h
+@@ -0,0 +1,51 @@
++/*
++ * ldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ldr.h ========
++ * Purpose:
++ * Provide module loading services and symbol export services.
++ *
++ * Public Functions:
++ * LDR_Exit
++ * LDR_FreeModule
++ * LDR_GetProcAddress
++ * LDR_Init
++ * LDR_LoadModule
++ *
++ * Notes:
++ * This service is meant to be used by modules of the DSP/BIOS Bridge
++ * class driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 12-Nov-1999 kc: Removed declaration of unused loader object.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 12-Jan-1998 cr: Cleaned up for code review.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 11-Nov-1996 cr: Cleaned up for code review.
++ *! 16-May-1996 gp: Created.
++ */
++
++#ifndef LDR_
++#define LDR_
++
++/* Loader objects: */
++ struct LDR_MODULE;
++
++#endif /* LDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/list.h b/arch/arm/plat-omap/include/dspbridge/list.h
+new file mode 100644
+index 0000000..2e3f995
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/list.h
+@@ -0,0 +1,296 @@
++/*
++ * list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== list.h ========
++ * Purpose:
++ * Declarations of list management control structures and definitions
++ * of inline list management functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_InitElem
++ * LST_Init
++ * LST_InsertBefore
++ * LST_IsEmpty
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 16-Aug-1997 cr: added explicit identifiers.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v.1.1; renamed identifiers.
++ *! 21-Oct-1994 dh4: Cleaned / commented for code review.
++ *! 08-Jun-1994 dh4: Converted to SPM (added extern "C").
++ */
++
++#ifndef LIST_
++#define LIST_
++
++#include <dspbridge/host_os.h>
++
++#define LST_IsEmpty(l) (((l)->head.next == &(l)->head))
++
++ struct LST_ELEM {
++ struct LST_ELEM *next;
++ struct LST_ELEM *prev;
++ struct LST_ELEM *self;
++ } ;
++
++ struct LST_LIST {
++ struct LST_ELEM head;
++ } ;
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ * Details:
++ * Uses portable MEM_Calloc() function to allocate a list containing
++ * a single element and initializes that element to indicate that it
++ * is the "end of the list" (i.e., the list is empty).
++ * An empty list is indicated by the "next" pointer in the element
++ * at the head of the list pointing to the head of the list, itself.
++ * Parameters:
++ * Returns:
++ * Pointer to beginning of created list (success)
++ * NULL --> Allocation failed
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * The created list contains a single element. This element is the
++ * "empty" element, because its "next" and "prev" pointers point at
++ * the same location (the element itself).
++ */
++ extern struct LST_LIST *LST_Create(void);
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ * Details:
++ * Uses portable MEM_Free() function to deallocate the memory
++ * block pointed at by the input parameter.
++ * Parameters:
++ * pList: Pointer to list control structure of list to be deleted
++ * Returns:
++ * Void
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Must ONLY be used for empty lists, because it does not walk the
++ * chain of list elements. Calling this function on a non-empty list
++ * will cause a memory leak.
++ */
++ extern void LST_Delete(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void LST_Exit(void);
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the list
++ * is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * Returns:
++ * Pointer to first list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_First(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * Pops the head off the list and returns a pointer to it.
++ * Details:
++ * If the list is empty, returns NULL.
++ * Else, removes the element at the head of the list, making the next
++ * element the head of the list.
++ * The head is removed by making the tail element of the list point its
++ * "next" pointer at the next element after the head, and by making the
++ * "prev" pointer of the next element after the head point at the tail
++ * element. So the next element after the head becomes the new head of
++ * the list.
++ * Parameters:
++ * pList: Pointer to list control structure of list whose head
++ * element is to be removed
++ * Returns:
++ * Pointer to element that was at the head of the list (success)
++ * NULL No elements in list
++ * Requires:
++ * - head.self must be correctly set to &head.
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Because the tail of the list points forward (its "next" pointer) to
++ * the head of the list, and the head of the list points backward (its
++ * "prev" pointer) to the tail of the list, this list is circular.
++ */
++ extern struct LST_ELEM *LST_GetHead(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initializes private state of LST module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * LST initialized.
++ */
++ extern bool LST_Init(void);
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ * Details:
++ * Parameters:
++ * pElem: Pointer to list element to be reset
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * This function must not be called to "reset" an element in the middle
++ * of a list chain -- that would break the chain.
++ *
++ */
++ extern void LST_InitElem(IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pElem: Pointer to element in list to insert.
++ * pElemExisting: Pointer to existing list element.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pElem != NULL.
++ * - pElemExisting != NULL.
++ * Ensures:
++ */
++ extern void LST_InsertBefore(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pElem,
++ IN struct LST_ELEM *pElemExisting);
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the next
++ * element is the head of the list or the list is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Pointer to list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_Next(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ * Details:
++ * Sets new element's "prev" pointer to the address previously held by
++ * the head element's prev pointer. This is the previous tail member of
++ * the list.
++ * Sets the new head's prev pointer to the address of the element.
++ * Sets next pointer of the previous tail member of the list to point to
++ * the new element (rather than the head, which it had been pointing at).
++ * Sets new element's next pointer to the address of the head element.
++ * Sets head's prev pointer to the address of the new element.
++ * Parameters:
++ * pList: Pointer to list control structure to which *pElem will be
++ * added
++ * pElem: Pointer to list element to be added
++ * Returns:
++ * Void
++ * Requires:
++ * *pElem and *pList must both exist.
++ * pElem->self = pElem before pElem is passed to this function.
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * Because the tail is always "just before" the head of the list (the
++ * tail's "next" pointer points at the head of the list, and the head's
++ * "prev" pointer points at the tail of the list), the list is circular.
++ * Warning: if pElem->self is not set beforehand, LST_GetHead() will
++ * return an erroneous pointer when it is called for this element.
++ */
++ extern void LST_PutTail(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++extern void LST_RemoveElem(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++#endif /* LIST_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mbx_sh.h b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+new file mode 100644
+index 0000000..be0909e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+@@ -0,0 +1,213 @@
++/*
++ * mbx_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mbx_sh.h ========
++ * Definitions for shared mailbox cmd/data values.(used on both
++ * the GPP and DSP sides).
++ *
++ * Bridge usage of OMAP mailbox 1 is determined by the "class" of the
++ * mailbox interrupt's cmd value received. The class value are defined
++ * as a bit (10 thru 15) being set.
++ *
++ * Note: Only 16 bits of each is used. Other 16 bit data reg available.
++ *
++ * 16 bit Mbx bit defns:
++ *
++ * A). Exception/Error handling (Module DEH) : class = 0.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ *
++ * B: DSP-DMA link driver channels (DDMA) : class = 1.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|1|b|b|b|b|b|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where b -> buffer index (32 DDMA buffers/chnl max)
++ * c -> channel Id (32 DDMA chnls max)
++ *
++ *
++ *
++ *
++ * C: Proc-copy link driver channels (PCPY) : class = 2.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|1|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ * D: Zero-copy link driver channels (DDZC) : class = 4.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|1|0|0|x|x|x|x|x|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> channel Id (32 ZCPY chnls max)
++ *
++ *
++ * E: Power management : class = 8.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|x|x|x|x|x|c|c|c|c|c|
++
++ * 0010 00xx xxxc cccc
++ * 0010 00nn pppp qqqq
++ * nn:
++ * 00 = reserved
++ * 01 = pwr state change
++ * 10 = opp pre-change
++ * 11 = opp post-change
++ *
++ * if nn = pwr state change:
++ * pppp = don't care
++ * qqqq:
++ * 0010 = hibernate
++ * 0010 0001 0000 0010
++ * 0110 = retention
++ * 0010 0001 0000 0110
++ * others reserved
++ *
++ * if nn = opp pre-change:
++ * pppp = current opp
++ * qqqq = next opp
++ *
++ * if nn = opp post-change:
++ * pppp = prev opp
++ * qqqq = current opp
++ *
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> Power management command
++ *
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Sep-2002 mr Added DEH reset const
++ *! 24-Apr-2002 sg Added more PM commands.
++ *! 04-Mar-2002 gv Added MBX_PM_CLASS
++ *! 22-Jan-2002 ag Bug fix in MBX_SETZCPYVAL(x) macro.
++ *! 21-Dec-2001 ag Added bit masks defns.
++ *! 17-Dec-2001 ag: created.
++ */
++
++#ifndef _MBX_SH_H
++#define _MBX_SH_H
++
++#define MBX_CLASS_MSK 0xFC00 /* Class bits are 10 thru 15 */
++#define MBX_VALUE_MSK 0x03FF /* Value is 0 thru 9 */
++
++#define MBX_DEH_CLASS 0x0000 /* DEH owns Mbx INTR */
++#define MBX_DDMA_CLASS 0x0400 /* DSP-DMA link drvr chnls owns INTR */
++#define MBX_PCPY_CLASS 0x0800 /* PROC-COPY " */
++#define MBX_ZCPY_CLASS 0x1000 /* ZERO-COPY " */
++#define MBX_PM_CLASS 0x2000 /* Power Management */
++#define MBX_DBG_CLASS 0x4000 /* For debugging purpose */
++
++/*
++ * Exception Handler codes
++ * Magic code used to determine if DSP signaled exception.
++ */
++#define MBX_DEH_BASE 0x0
++#define MBX_DEH_USERS_BASE 0x100 /* 256 */
++#define MBX_DEH_LIMIT 0x3FF /* 1023 */
++#define MBX_DEH_RESET 0x101 /* DSP RESET (DEH) */
++#define MBX_DEH_EMMU 0X103 /*DSP MMU FAULT RECOVERY*/
++
++/*
++ * Link driver command/status codes.
++ */
++/* DSP-DMA */
++#define MBX_DDMA_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_DDMA_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_DDMA_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++#define MBX_DDMA_NUMBUFBITS 5 /* buffer index: # of bits avail */
++#define MBX_DDMA_BUFSHIFT (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
++#define MBX_DDMA_BUFMSK 0x3E0 /* bits 5 thru 9 */
++
++/* Zero-Copy */
++#define MBX_ZCPY_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_ZCPY_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_ZCPY_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++/* Power Management Commands */
++#define MBX_PM_DSPIDLE (MBX_PM_CLASS + 0x0)
++#define MBX_PM_DSPWAKEUP (MBX_PM_CLASS + 0x1)
++#define MBX_PM_EMERGENCYSLEEP (MBX_PM_CLASS + 0x2)
++#define MBX_PM_SLEEPUNTILRESTART (MBX_PM_CLASS + 0x3)
++#define MBX_PM_DSPGLOBALIDLE_OFF (MBX_PM_CLASS + 0x4)
++#define MBX_PM_DSPGLOBALIDLE_ON (MBX_PM_CLASS + 0x5)
++#define MBX_PM_SETPOINT_PRENOTIFY (MBX_PM_CLASS + 0x6)
++#define MBX_PM_SETPOINT_POSTNOTIFY (MBX_PM_CLASS + 0x7)
++#define MBX_PM_DSPRETN (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPRETENTION (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPHIBERNATE (MBX_PM_CLASS + 0x9)
++#define MBX_PM_HIBERNATE_EN (MBX_PM_CLASS + 0xA)
++#define MBX_PM_OPP_REQ (MBX_PM_CLASS + 0xB)
++#define MBX_PM_OPP_CHG (MBX_PM_CLASS + 0xC)
++
++#define MBX_PM_TYPE_MASK 0x0300
++#define MBX_PM_TYPE_PWR_CHNG 0x0100
++#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
++#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
++#define MBX_PM_TYPE_OPP_MASK 0x0300
++#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
++/* DSP to MPU */
++#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
++#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
++#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
++#define MBX_PM_OPP_1 0
++#define MBX_PM_OPP_2 1
++#define MBX_PM_OPP_3 2
++#define MBX_PM_OPP_4 3
++#define MBX_OLDOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_NEWOPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++#define MBX_PREVOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_CUROPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++
++/* Bridge Debug Commands */
++#define MBX_DBG_SYSPRINTF (MBX_DBG_CLASS + 0x0)
++
++/*
++ * Useful macros
++ */
++/* DSP-DMA channel */
++#define MBX_SETDDMAVAL(x, y) (MBX_DDMA_CLASS | (x << MBX_DDMA_BUFSHIFT) | \
++ (y << MBX_DDMA_CHNLSHIFT))
++
++/* Zero-Copy channel */
++#define MBX_SETZCPYVAL(x) (MBX_ZCPY_CLASS | (x << MBX_ZCPY_CHNLSHIFT))
++
++#endif /* _MBX_SH_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mem.h b/arch/arm/plat-omap/include/dspbridge/mem.h
+new file mode 100644
+index 0000000..535ac3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mem.h
+@@ -0,0 +1,340 @@
++/*
++ * mem.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.h ========
++ * Purpose:
++ * Memory management and address mapping services for the DSP/BIOS Bridge
++ * class driver and mini-driver.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocObject
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreeObject
++ * MEM_FreePhysMem
++ * MEM_GetNumPages
++ * MEM_Init
++ * MEM_IsValidHandle
++ * MEM_LinearAddress
++ * MEM_PageLock
++ * MEM_PageUnlock
++ * MEM_UnMapLinearAddress
++ * MEM_VirtualToPhysical
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Cleaned up notes for MEM_LinearAddress() does not
++ *! require phys address to be page aligned!
++ *! 02-Dec-1999 rr: stdwin.h included for retail build
++ *! 12-Nov-1999 kc: Added warning about use of MEM_LinearAddress.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 07-Jan-1998 gp: Added MEM_AllocUMB and MEM_UMBFree for User Mapped Buffers
++ *! used by WMD_CHNL.
++ *! 23-Dec-1997 cr: Code review cleanup, removed dead Ring 3 code.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 01-Nov-1996 gp: Updated based on code review.
++ *! 04-Sep-1996 gp: Added MEM_PageLock() and MEM_PageUnlock() services.
++ *! 14-Aug-1996 mg: Added MEM_GetPhysAddr() and MEM_GetNumPages()
++ *! 25-Jul-1996 gp: Added MEM_IsValidHandle() macro.
++ *! 10-May-1996 gp: Added MEM_Calloc().
++ *! 25-Apr-1996 gp: Added MEM_PhysicalAddress()
++ *! 17-Apr-1996 gp: Added MEM_Exit function; updated to latest naming standard.
++ *! 08-Apr-1996 gp: Created.
++ */
++
++#ifndef MEM_
++#define MEM_
++
++#include <dspbridge/host_os.h>
++#include <dspbridge/memdefs.h>
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ */
++ extern void *MEM_Alloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_AllocObject ========
++ * Purpose:
++ * Allocate an object, and set it's signature.
++ * Parameters:
++ * pObj: Pointer to the new object.
++ * Obj: Type of the object to allocate.
++ * Signature: Magic field value. Must be non-zero.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Calloc(); and
++ * The object structure has a dwSignature field. The compiler ensures
++ * this requirement.
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will succeed for this object.
++ */
++#define MEM_AllocObject(pObj, Obj, Signature) \
++{ \
++ pObj = MEM_Calloc(sizeof(Obj), MEM_NONPAGED); \
++ if (pObj) { \
++ pObj->dwSignature = Signature; \
++ } \
++}
++
++/* ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * ulAlign: Alignment Mask.
++ * pPhysicalAddress: Physical address of allocated memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, or if cBytes == 0.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested. Returned physical address refers to physical
++ * location of memory.
++ */
++ extern void *MEM_AllocPhysMem(IN u32 cBytes,
++ IN u32 ulAlign,
++ OUT u32 *pPhysicalAddress);
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of zeroed memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block
++ * of the size requested.
++ */
++ extern void *MEM_Calloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void MEM_Exit(void);
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Performs system cache sync with discard
++ * Parameters:
++ * pMemBuf: Pointer to memory region to be flushed.
++ * pMemBuf: Size of the memory region to be flushed.
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Cache is synchronized
++ */
++ extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ * Parameters:
++ * pMemBuf: Pointer to memory allocated by MEM_Calloc/Alloc().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pMemBuf is a valid memory address returned by MEM_Calloc/Alloc().
++ * Ensures:
++ * pMemBuf is no longer a valid pointer to memory.
++ */
++ extern void MEM_Free(IN void *pMemBuf);
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ * Parameters:
++ * pVirtualAddress: Pointer to virtual memory region allocated
++ * by MEM_AllocPhysMem().
++ * pPhysicalAddress: Pointer to physical memory region allocated
++ * by MEM_AllocPhysMem().
++ * cBytes: Size of the memory region allocated by MEM_AllocPhysMem().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pVirtualAddress is a valid memory address returned by
++ * MEM_AllocPhysMem()
++ * Ensures:
++ * pVirtualAddress is no longer a valid pointer to memory.
++ */
++ extern void MEM_FreePhysMem(void *pVirtualAddress,
++ u32 pPhysicalAddress, u32 cBytes);
++
++/*
++ * ======== MEM_FreeObject ========
++ * Purpose:
++ * Utility macro to invalidate an object's signature, and deallocate it.
++ * Parameters:
++ * pObj: Pointer to the object to free.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Free().
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will fail for this object.
++ */
++#define MEM_FreeObject(pObj) \
++{ \
++ pObj->dwSignature = 0x00; \
++ MEM_Free(pObj); \
++}
++
++/*
++ * ======== MEM_GetNumPages ========
++ * Purpose:
++ * Calculate the number of pages corresponding to the supplied buffer.
++ * Parameters:
++ * pAddr: Linear (virtual) address of the buffer.
++ * cBytes: Number of bytes in the buffer.
++ * Returns:
++ * Number of pages.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * If cBytes > 0, number of pages returned > 0.
++ */
++ extern s32 MEM_GetNumPages(IN void *pAddr, IN u32 cBytes);
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initializes private state of MEM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * MEM initialized.
++ */
++ extern bool MEM_Init(void);
++
++/*
++ * ======== MEM_IsValidHandle ========
++ * Purpose:
++ * Validate the object handle.
++ * Parameters:
++ * hObj: Handle to object created with MEM_AllocObject().
++ * Sig: Expected signature u32.
++ * Returns:
++ * TRUE if handle is valid; FALSE otherwise.
++ * Requires:
++ * The object structure has a dwSignature field. Ensured by compiler.
++ * Ensures:
++ */
++#define MEM_IsValidHandle(hObj, Sig) \
++ ((hObj != NULL) && (hObj->dwSignature == Sig))
++
++/*
++ * ======== MEM_LinearAddress ========
++ * Purpose:
++ * Get the linear address corresponding to the given physical address.
++ * Parameters:
++ * pPhysAddr: Physical address to be mapped.
++ * cBytes: Number of bytes in physical range to map.
++ * Returns:
++ * The corresponding linear address, or NULL if unsuccessful.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * Notes:
++ * If valid linear address is returned, be sure to call
++ * MEM_UnmapLinearAddress().
++ */
++#define MEM_LinearAddress(pPhyAddr, cBytes) pPhyAddr
++
++/*
++ * ======== MEM_UnmapLinearAddress ========
++ * Purpose:
++ * Unmap the linear address mapped in MEM_LinearAddress.
++ * Parameters:
++ * pBaseAddr: Ptr to mapped memory (as returned by MEM_LinearAddress()).
++ * Returns:
++ * Requires:
++ * - MEM initialized.
++ * - pBaseAddr is a valid linear address mapped in MEM_LinearAddress.
++ * Ensures:
++ * - pBaseAddr no longer points to a valid linear address.
++ */
++#define MEM_UnmapLinearAddress(pBaseAddr)
++
++/*
++ * ======== MEM_ExtPhysPoolInit ========
++ * Purpose:
++ * Uses the physical memory chunk passed for internal consitent memory
++ * allocations.
++ * physical address based on the page frame address.
++ * Parameters:
++ * poolPhysBase starting address of the physical memory pool.
++ * poolSize size of the physical memory pool.
++ * Returns:
++ * none.
++ * Requires:
++ * - MEM initialized.
++ * - valid physical address for the base and size > 0
++ */
++ extern void MEM_ExtPhysPoolInit(IN u32 poolPhysBase,
++ IN u32 poolSize);
++
++#endif /* MEM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/memdefs.h b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+new file mode 100644
+index 0000000..a5bb259
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+@@ -0,0 +1,52 @@
++/*
++ * memdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== memdefs.h ========
++ * Purpose:
++ * Global MEM constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Aug-2001 ag: Added MEM_[SET][GET]VIRTUALSEGID.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 15-Nov-1996 gp: Renamed from wsxmem.h and moved to kwinos.
++ *! 21-Aug-1996 cr: Created from mem.h.
++ */
++
++#ifndef MEMDEFS_
++#define MEMDEFS_
++
++/* Memory Pool Attributes: */
++ enum MEM_POOLATTRS {
++ MEM_PAGED = 0,
++ MEM_NONPAGED = 1,
++ MEM_LARGEVIRTMEM = 2
++ } ;
++
++/*
++ * MEM_VIRTUALSEGID is used by Node & Strm to access virtual address space in
++ * the correct client process context.
++ */
++#define MEM_SETVIRTUALSEGID 0x10000000
++#define MEM_GETVIRTUALSEGID 0x20000000
++#define MEM_MASKVIRTUALSEGID (MEM_SETVIRTUALSEGID | MEM_GETVIRTUALSEGID)
++
++#define TO_VIRTUAL_UNCACHED(x) x
++#define INTREG_TO_VIRTUAL_UNCACHED(x) x
++
++#endif /* MEMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgr.h b/arch/arm/plat-omap/include/dspbridge/mgr.h
+new file mode 100644
+index 0000000..24c4472
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgr.h
+@@ -0,0 +1,234 @@
++/*
++ * mgr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * MGR_Create
++ * MGR_Destroy
++ * MGR_EnumNodeInfo
++ * MGR_EnumProcessorInfo
++ * MGR_Exit
++ * MGR_GetDCDHandle
++ * MGR_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc: Removed legacy PERF definitions.
++ *! 11-Jul-2001 jeh Added CFG_HDEVNODE parameter to MGR_Create().
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData for acquiring PERF stats.
++ *! 03-Nov-2000 rr: Added MGR_GetDCDHandle. Modified after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types).
++ *! 20-Jun-2000 rr: Created.
++ */
++
++#ifndef MGR_
++#define MGR_
++
++#include <dspbridge/mgrpriv.h>
++
++#define MAX_EVENTS 32
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Purpose:
++ * Block on any Bridge event(s)
++ * Parameters:
++ * aNotifications : array of pointers to notification objects.
++ * uCount : number of elements in above array
++ * puIndex : index of signaled event object
++ * uTimeout : timeout interval in milliseocnds
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_ETIMEOUT : Wait timed out. *puIndex is undetermined.
++ * Details:
++ */
++
++ DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION
++ **aNotifications,
++ u32 uCount, OUT u32 *puIndex,
++ u32 uTimeout);
++
++/*
++ * ======== MGR_Create ========
++ * Purpose:
++ * Creates the Manager Object. This is done during the driver loading.
++ * There is only one Manager Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phMgrObject: Location to store created MGR Object handle.
++ * hDevNode: Device object as known to Windows system.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EMEMORY: Failed to Create the Object
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * phMgrObject != NULL.
++ * Ensures:
++ * DSP_SOK: *phMgrObject is a valid MGR interface to the device.
++ * MGR Object stores the DCD Manager Handle.
++ * MGR Object stored in the Regsitry.
++ * !DSP_SOK: MGR Object not created
++ * Details:
++ * DCD Dll is loaded and MGR Object stores the handle of the DLL.
++ */
++ extern DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **hMgrObject,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== MGR_Destroy ========
++ * Purpose:
++ * Destroys the MGR object. Called upon driver unloading.
++ * Parameters:
++ * hMgrObject: Handle to Manager object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DCD Manager freed; MGR Object destroyed;
++ * MGR Object deleted from the Registry.
++ * DSP_EFAIL: Failed to destroy MGR Object
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * hMgrObject is a valid MGR handle .
++ * Ensures:
++ * DSP_SOK: MGR Object destroyed and hMgrObject is Invalid MGR
++ * Handle.
++ */
++ extern DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject);
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ * Parameters:
++ * uNode: The node index (base 0).
++ * pNDBProps: Ptr to the DSP_NDBPROPS structure for output.
++ * uNDBPropsSize: Size of the DSP_NDBPROPS structure.
++ * puNumNodes: Location where the number of nodes configured
++ * in the database will be returned.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uNode is > than the number of nodes.
++ * configutred in the system
++ * DSP_ECHANGEDURINGENUM: During Enumeration there has been a change in
++ * the number of nodes configured or in the
++ * the properties of the enumerated nodes.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pNDBPROPS is not null
++ * uNDBPropsSize >= sizeof(DSP_NDBPROPS)
++ * puNumNodes is not null
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumNodes > 0 OR
++ * DSP_FAILED && *puNumNodes == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumNodeInfo(u32 uNode,
++ OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize,
++ OUT u32 *puNumNodes);
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about available DSP
++ * processors
++ * Parameters:
++ * uProcessor: The processor index (zero-based).
++ * pProcessorInfo: Ptr to the DSP_PROCESSORINFO structure .
++ * uProcessorInfoSize: Size of DSP_PROCESSORINFO structure.
++ * puNumProcs: Location where the number of DSPs configured
++ * in the database will be returned
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uProcessor is > than the number of
++ * DSP Processors in the system.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pProcessorInfo is not null
++ * puNumProcs is not null
++ * uProcessorInfoSize >= sizeof(DSP_PROCESSORINFO)
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumProcs > 0 OR
++ * DSP_FAILED && *puNumProcs == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *
++ pProcessorInfo,
++ u32 uProcessorInfoSize,
++ OUT u32 *puNumProcs);
++/*
++ * ======== MGR_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MGR is initialized.
++ * Ensures:
++ * When reference count == 0, MGR's private resources are freed.
++ */
++ extern void MGR_Exit(void);
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Purpose:
++ * Retrieves the MGR handle. Accessor Function
++ * Parameters:
++ * hMGRHandle: Handle to the Manager Object
++ * phDCDHandle: Ptr to receive the DCD Handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EFAIL: Failure to get the Handle
++ * Requires:
++ * MGR is initialized.
++ * phDCDHandle != NULL
++ * Ensures:
++ * DSP_SOK and *phDCDHandle != NULL ||
++ * DSP_EFAIL and *phDCDHandle == NULL
++ */
++ extern DSP_STATUS MGR_GetDCDHandle(IN struct MGR_OBJECT
++ *hMGRHandle,
++ OUT u32 *phDCDHandle);
++
++/*
++ * ======== MGR_Init ========
++ * Purpose:
++ * Initialize MGR's private state, keeping a reference count on each
++ * call. Intializes the DCD.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public MGR functions.
++ */
++ extern bool MGR_Init(void);
++
++#endif /* MGR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgrpriv.h b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+new file mode 100644
+index 0000000..4a34086
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+@@ -0,0 +1,55 @@
++/*
++ * mgrpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgrpriv.h ========
++ * Description:
++ * Global MGR constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 29-July-2001 ag: added MGR_PROCESSOREXTINFO.
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef MGRPRIV_
++#define MGRPRIV_
++
++/*
++ * OMAP1510 specific
++ */
++#define MGR_MAXTLBENTRIES 32
++
++/* RM MGR Object */
++ struct MGR_OBJECT;
++
++ struct MGR_TLBENTRY {
++ u32 ulDspVirt; /* DSP virtual address */
++ u32 ulGppPhys; /* GPP physical address */
++ } ;
++
++/*
++ * The DSP_PROCESSOREXTINFO structure describes additional extended
++ * capabilities of a DSP processor not exposed to user.
++ */
++ struct MGR_PROCESSOREXTINFO {
++ struct DSP_PROCESSORINFO tyBasic; /* user processor info */
++ /* private dsp mmu entries */
++ struct MGR_TLBENTRY tyTlb[MGR_MAXTLBENTRIES];
++ } ;
++
++#endif /* MGRPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msg.h b/arch/arm/plat-omap/include/dspbridge/msg.h
+new file mode 100644
+index 0000000..f2872cc
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msg.h
+@@ -0,0 +1,106 @@
++/*
++ * msg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.h ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 17-Nov-2000 jeh Removed MSG_Get, MSG_Put, MSG_CreateQueue,
++ *! MSG_DeleteQueue, and MSG_RegisterNotify, since these
++ *! are now part of mini-driver.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSG_
++#define MSG_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object. The MSG manager must be created before
++ * the IO Manager.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager handle on output.
++ * hDevObject: The device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * phMsgMgr != NULL.
++ * hDevObject != NULL.
++ * msgCallback != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from MSG_Create().
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ extern void MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== MSG_Exit ========
++ * Purpose:
++ * Discontinue usage of MSG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MSG_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in MSG_Init(void) will be freed when last MSG
++ * client calls MSG_Exit(void).
++ */
++ extern void MSG_Exit(void);
++
++/*
++ * ======== MSG_Init ========
++ * Purpose:
++ * Initialize the MSG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool MSG_Init(void);
++
++#endif /* MSG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msgdefs.h b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+new file mode 100644
+index 0000000..8ea4551
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+@@ -0,0 +1,43 @@
++/*
++ * msgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgdefs.h ========
++ * Description:
++ * Global MSG constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 09-May-2001 jeh Removed MSG_TODSP, MSG_FROMDSP.
++ *! 17-Nov-2000 jeh Added MSGMGR_SIGNATURE.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSGDEFS_
++#define MSGDEFS_
++
++#define MSGMGR_SIGNATURE 0x4d47534d /* "MGSM" */
++
++/* MSG Objects: */
++ struct MSG_MGR;
++ struct MSG_QUEUE;
++
++/* Function prototype for callback to be called on RMS_EXIT message received */
++ typedef void(*MSG_ONEXIT) (HANDLE h, s32 nStatus);
++
++#endif /* MSGDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldr.h b/arch/arm/plat-omap/include/dspbridge/nldr.h
+new file mode 100644
+index 0000000..0915846
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldr.h
+@@ -0,0 +1,81 @@
++/*
++ * nldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge dynamic loader interface. See the file dldrdefs.h
++ * for a description of these functions.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function header comments.
++ *! 17-Apr-2002 jeh Created.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/nldrdefs.h>
++
++#ifndef NLDR_
++#define NLDR_
++
++ extern DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit);
++
++ extern DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs);
++
++ extern void NLDR_Delete(struct NLDR_OBJECT *hNldr);
++ extern void NLDR_Exit(void);
++ extern void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode);
++
++ extern DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++ extern DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj
++ **phRmmMgr);
++
++ extern bool NLDR_Init(void);
++ extern DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++ extern DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++#endif /* NLDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldrdefs.h b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+new file mode 100644
+index 0000000..84b36a3
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+@@ -0,0 +1,307 @@
++/*
++ * nldrdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldrdefs.h ========
++ * Description:
++ * Global Dynamic + static/overlay Node loader (NLDR) constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Consolidated dldrdefs.h into nldrdefs.h
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#ifndef NLDRDEFS_
++#define NLDRDEFS_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/devdefs.h>
++
++#define NLDR_MAXPATHLENGTH 255
++/* NLDR Objects: */
++ struct NLDR_OBJECT;
++ struct NLDR_NODEOBJECT;
++
++/*
++ * ======== NLDR_LOADTYPE ========
++ * Load types for a node. Must match values in node.h55.
++ */
++ enum NLDR_LOADTYPE {
++ NLDR_STATICLOAD, /* Linked in base image, not overlay */
++ NLDR_DYNAMICLOAD, /* Dynamically loaded node */
++ NLDR_OVLYLOAD /* Linked in base image, overlay node */
++ } ;
++
++/*
++ * ======== NLDR_OVLYFXN ========
++ * Causes code or data to be copied from load address to run address. This
++ * is the "COD_WRITEFXN" that gets passed to the DBLL_Library and is used as
++ * the ZL write function.
++ *
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspRunAddr: Run address of code or data.
++ * ulDspLoadAddr: Load address of code or data.
++ * ulNumBytes: Number of (GPP) bytes to copy.
++ * nMemSpace: RMS_CODE or RMS_DATA.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_OVLYFXN) (void *pPrivRef, u32 ulDspRunAddr,
++ u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_WRITEFXN ========
++ * Write memory function. Used for dynamic load writes.
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspAddr: Address of code or data.
++ * pBuf: Code or data to be written
++ * ulNumBytes: Number of (GPP) bytes to write.
++ * nMemSpace: DBLL_DATA or DBLL_CODE.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_WRITEFXN) (void *pPrivRef,
++ u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_ATTRS ========
++ * Attributes passed to NLDR_Create function.
++ */
++ struct NLDR_ATTRS {
++ NLDR_OVLYFXN pfnOvly;
++ NLDR_WRITEFXN pfnWrite;
++ u16 usDSPWordSize;
++ u16 usDSPMauSize;
++ } ;
++
++/*
++ * ======== NLDR_PHASE ========
++ * Indicates node create, delete, or execute phase function.
++ */
++ enum NLDR_PHASE {
++ NLDR_CREATE,
++ NLDR_DELETE,
++ NLDR_EXECUTE,
++ NLDR_NOPHASE
++ } ;
++
++/*
++ * Typedefs of loader functions imported from a DLL, or defined in a
++ * function table.
++ */
++
++/*
++ * ======== NLDR_Allocate ========
++ * Allocate resources to manage the loading of a node on the DSP.
++ *
++ * Parameters:
++ * hNldr: Handle of loader that will load the node.
++ * pPrivRef: Handle to identify the node.
++ * pNodeProps: Pointer to a DCD_NODEPROPS for the node.
++ * phNldrNode: Location to store node handle on output. This handle
++ * will be passed to NLDR_Load/NLDR_Unload.
++ * pfPhaseSplit: pointer to boolean variable referenced in node.c
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * pNodeProps != NULL.
++ * phNldrNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNldrNode).
++ * error: *phNldrNode == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_ALLOCATEFXN) (struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT
++ **phNldrNode,
++ OUT bool *pfPhaseSplit);
++
++/*
++ * ======== NLDR_Create ========
++ * Create a loader object. This object handles the loading and unloading of
++ * create, delete, and execute phase functions of nodes on the DSP target.
++ *
++ * Parameters:
++ * phNldr: Location to store loader handle on output.
++ * hDevObject: Device for this processor.
++ * pAttrs: Loader attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * Requires:
++ * NLDR_Init(void) called.
++ * phNldr != NULL.
++ * hDevObject != NULL.
++ * pAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phNldr.
++ * error: *phNldr == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_CREATEFXN) (OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS
++ *pAttrs);
++
++/*
++ * ======== NLDR_Delete ========
++ * Delete the NLDR loader.
++ *
++ * Parameters:
++ * hNldr: Node manager object.
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * Ensures:
++ * hNldr invalid
++ */
++ typedef void(*NLDR_DELETEFXN) (struct NLDR_OBJECT *hNldr);
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NLDR_Init(void) will be freed when last NLDR
++ * client calls NLDR_Exit(void).
++ */
++ typedef void(*NLDR_EXITFXN) (void);
++
++/*
++ * ======== NLDR_Free ========
++ * Free resources allocated in NLDR_Allocate.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef void(*NLDR_FREEFXN) (struct NLDR_NODEOBJECT *hNldrNode);
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ * Get address of create, delete, or execute phase function of a node on
++ * the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * pstrFxn: Name of function.
++ * pulAddr: Location to store function address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESYMBOL: Address of function not found.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * pulAddr != NULL;
++ * pstrFxn != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_GETFXNADDRFXN) (struct NLDR_NODEOBJECT
++ *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ typedef bool(*NLDR_INITFXN) (void);
++
++/*
++ * ======== NLDR_Load ========
++ * Load create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Type of function to load (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EOVERLAYMEMORY: Can't overlay phase because overlay memory
++ * is already in use.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * DSP_EFWRITE: Failed to write phase's code or date to target.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_LOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_Unload ========
++ * Unload create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Node function to unload (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_UNLOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_FXNS ========
++ */
++ struct NLDR_FXNS {
++ NLDR_ALLOCATEFXN pfnAllocate;
++ NLDR_CREATEFXN pfnCreate;
++ NLDR_DELETEFXN pfnDelete;
++ NLDR_EXITFXN pfnExit;
++ NLDR_FREEFXN pfnFree;
++ NLDR_GETFXNADDRFXN pfnGetFxnAddr;
++ NLDR_INITFXN pfnInit;
++ NLDR_LOADFXN pfnLoad;
++ NLDR_UNLOADFXN pfnUnload;
++ } ;
++
++#endif /* NLDRDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/node.h b/arch/arm/plat-omap/include/dspbridge/node.h
+new file mode 100644
+index 0000000..d253962
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/node.h
+@@ -0,0 +1,619 @@
++/*
++ * node.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== node.h ========
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetMessage
++ * NODE_GetProcessor
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Apr-2001 jeh Updated with code review changes.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID to return codes.
++ *! 17-Nov-2000 jeh Added NODE_OnExit().
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GetMessage, NODE_PutMessage.
++ *! 12-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Removed
++ *! NODE_RegisterAllNodes().
++ *! 07-Sep-2000 jeh Changed type HANDLE in NODE_RegisterNotify to
++ *! DSP_HNOTIFICATION. Added DSP_STRMATTR param to
++ *! NODE_Connect(). Removed NODE_GetMessageStream().
++ *! 17-Jul-2000 jeh Updated function header descriptions.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef NODE_
++#define NODE_
++
++#include <dspbridge/procpriv.h>
++
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ * Parameters:
++ * hProcessor: Handle of processor that is allocating the node.
++ * pNodeId: Pointer to a DSP_UUID for the node.
++ * pArgs: Optional arguments to be passed to the node.
++ * pAttrIn: Optional pointer to node attributes (priority,
++ * timeout...)
++ * phNode: Location to store node handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EUUID: Node UUID has not been registered.
++ * DSP_ESYMBOL: iAlg functions not found for a DAIS node.
++ * DSP_ERANGE: pAttrIn != NULL and pAttrIn->iPriority out of
++ * range.
++ * DSP_EFAIL: A failure occured, unable to allocate node.
++ * DSP_EWRONGSTATE: Proccessor is not in the running state.
++ * Requires:
++ * NODE_Init(void) called.
++ * hProcessor != NULL.
++ * pNodeId != NULL.
++ * phNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNode).
++ * error: *phNode == NULL.
++ */
++ extern DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA
++ *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN
++ *pAttrIn,
++ OUT struct NODE_OBJECT **phNode);
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocate and Prepare a buffer whose descriptor will be passed to a
++ * Node within a (DSP_MSG)message
++ * Parameters:
++ * hNode: The node handle.
++ * uSize: The size of the buffer to be allocated.
++ * pAttr: Pointer to a DSP_BUFFERATTR structure.
++ * pBuffer: Location to store the address of the allocated
++ * buffer on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EMEMORY: Insufficent memory.
++ * DSP_EFAIL: General Failure.
++ * DSP_ESIZE: Invalid Size.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_AllocMsgBuf(struct NODE_OBJECT *hNode,
++ u32 uSize,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr,
++ OUT u8 **pBuffer);
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of an allocated node.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ERANGE: nPriority is out of range.
++ * DSP_ENODETYPE: The specified node is not a task node.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED, NODE_PAUSED,
++ * or NODE_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ERESTART: A critical error has occurred and the DSP is
++ * being restarted.
++ * DSP_EFAIL: Unable to change node's runtime priority level.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK && (Node's current priority == nPriority)
++ */
++ extern DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode,
++ s32 nPriority);
++
++/*
++ * ======== NODE_CloseOrphans ========
++ * Purpose:
++ * Delete all nodes whose owning processor is being destroyed.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * hProc: Handle to processor object being destroyed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to delete all nodes belonging to hProc.
++ * Requires:
++ * Valid hNodeMgr.
++ * hProc != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_CloseOrphans(struct NODE_MGR *hNodeMgr,
++ struct PROC_OBJECT *hProc);
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
++ * case that the connnection is being made between a node on the DSP and
++ * the GPP, one of the node handles (either hNode1 or hNode2) must be
++ * the constant NODE_HGPPNODE.
++ * Parameters:
++ * hNode1: Handle of first node to connect to second node. If
++ * this is a connection from the GPP to hNode2, hNode1
++ * must be the constant NODE_HGPPNODE. Otherwise, hNode1
++ * must be a node handle returned from a successful call
++ * to Node_Allocate().
++ * hNode2: Handle of second node. Must be either NODE_HGPPNODE
++ * if this is a connection from DSP node to GPP, or a
++ * node handle returned from a successful call to
++ * NODE_Allocate().
++ * uStream1: Output stream index on first node, to be connected
++ * to second node's input stream. Value must range from
++ * 0 <= uStream1 < number of output streams.
++ * uStream2: Input stream index on second node. Value must range
++ * from 0 <= uStream2 < number of input streams.
++ * pAttrs: Stream attributes (NULL ==> use defaults).
++ * pConnParam: A pointer to a DSP_CBDATA structure that defines
++ * connection parameter for device nodes to pass to DSP
++ * side.
++ * If the value of this parameter is NULL, then this API
++ * behaves like DSPNode_Connect. This parameter will have
++ * length of the string and the null terminated string in
++ * DSP_CBDATA struct. This can be extended in future tp
++ * pass binary data.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode1 or hNode2.
++ * DSP_EMEMORY: Insufficient host memory.
++ * DSP_EVALUE: A stream index parameter is invalid.
++ * DSP_EALREADYCONNECTED: A connection already exists for one of the
++ * indices uStream1 or uStream2.
++ * DSP_EWRONGSTATE: Either hNode1 or hNode2 is not in the
++ * NODE_ALLOCATED state.
++ * DSP_ENOMORECONNECTIONS: No more connections available.
++ * DSP_EFAIL: Attempt to make an illegal connection (eg,
++ * Device node to device node, or device node to
++ * GPP), the two nodes are on different DSPs.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1,
++ u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2,
++ OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA
++ *pConnParam);
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create
++ * function. If necessary, load code that contains the node's create
++ * function.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ESYMBOL: Create function not found in the COFF file.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED state.
++ * DSP_EMEMORY: Memory allocation failure on the DSP.
++ * DSP_ETASK: Unable to create node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER1-16: A user-defined failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target. The NODE Manager
++ * also maintains a pipe map of used and available node connections.
++ * Each DEV object should have exactly one NODE Manager object.
++ *
++ * Parameters:
++ * phNodeMgr: Location to store node manager handle on output.
++ * hDevObject: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * NODE_Init(void) called.
++ * phNodeMgr != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Valide *phNodeMgr.
++ * error: *phNodeMgr == NULL.
++ */
++ extern DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete resources allocated in NODE_Allocate(). If the node was
++ * created, delete the node on the DSP by remotely calling the node's
++ * delete function. Loads the node's delete function if necessary.
++ * GPP side resources are freed after node's delete function returns.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EDELETE: A deletion failure occurred.
++ * DSP_EUSER1-16: Node specific failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred in deleting the node.
++ * DSP_ESYMBOL: Delete function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK: hNode is invalid.
++ */
++ extern DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid hNodeMgr.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr);
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated for the DSP.
++ * Parameters:
++ * hNodeMgr: Node manager returned from NODE_CreateMgr().
++ * aNodeTab: Array to copy node handles into.
++ * uNodeTabSize: Number of handles that can be written to aNodeTab.
++ * puNumNodes: Location where number of node handles written to
++ * aNodeTab will be written.
++ * puAllocated: Location to write total number of allocated nodes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESIZE: aNodeTab is too small to hold all node handles.
++ * Requires:
++ * Valid hNodeMgr.
++ * aNodeTab != NULL || uNodeTabSize == 0.
++ * puNumNodes != NULL.
++ * puAllocated != NULL.
++ * Ensures:
++ * - (DSP_ESIZE && *puNumNodes == 0)
++ * - || (DSP_SOK && *puNumNodes <= uNodeTabSize) &&
++ * (*puAllocated == *puNumNodes)
++ */
++ extern DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr,
++ IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NODE_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NODE_Init(void) will be freed when last NODE
++ * client calls NODE_Exit(void).
++ */
++ extern void NODE_Exit(void);
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Free a message buffer previously allocated with NODE_AllocMsgBuf.
++ * Parameters:
++ * hNode: The node handle.
++ * pBuffer: (Address) Buffer allocated by NODE_AllocMsgBuf.
++ * pAttr: Same buffer attributes passed to NODE_AllocMsgBuf.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EFAIL: Failure to free the buffer.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode,
++ IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr);
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * pAttr: Pointer to DSP_NODEATTR structure to copy node's
++ * attributes.
++ * uAttrSize: Size of pAttr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * NODE_Init(void) called.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *pAttrs contains the node's current attributes.
++ */
++ extern DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr,
++ u32 uAttrSize);
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP. The node must be either a
++ * message node, task node, or XDAIS socket node.
++ * If a message is not available, this function will block until a
++ * message is available, or the node's timeout value is reached.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * pMessage: Pointer to DSP_MSG structure to copy the
++ * message into.
++ * uTimeout: Timeout in milliseconds to wait for message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Cannot retrieve messages from this type of node.
++ * DSP_ETIMEOUT: Timeout occurred and no message is available.
++ * DSP_EFAIL: Error occurred while trying to retrieve a message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMessage != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode,
++ OUT struct DSP_MSG *pMessage,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_GetNldrObj ========
++ * Purpose:
++ * Retrieve the Nldr manager
++ * Parameters:
++ * hNodeMgr: Node Manager
++ * phNldrObj: Pointer to a Nldr manager handle
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ OUT struct NLDR_OBJECT **phNldrObj);
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NODE_Init(void);
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node. PROC needs to pass
++ * this function as a parameter to MSG_Create(). This function then gets
++ * called by the mini-driver when an exit message for a node is received.
++ * Parameters:
++ * hNode: Handle of the node that the exit message is for.
++ * nStatus: Return status of the node's execute phase.
++ * Returns:
++ * Ensures:
++ */
++ void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus);
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Node is not a task or socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_RUNNING state.
++ * DSP_EFAIL: Failed to pause node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node.
++ * This function will block until the message stream can accommodate
++ * the message, or a timeout occurs. The message will be copied, so Msg
++ * can be re-used immediately after return.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * pMsg: Location of message to be sent to the node.
++ * uTimeout: Timeout in msecs to wait.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Messages can't be sent to this type of node.
++ * DSP_ETIMEOUT: Timeout occurred before message could be set.
++ * DSP_EWRONGSTATE: Node is in invalid state for sending messages.
++ * DSP_EFAIL: Unable to send message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * NODE_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of
++ * a node that has been suspended (via NODE_Pause()) on the DSP. Load
++ * the node's execute function if necessary.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: hNode doesn't represent a message, task or dais
++ * socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_PAUSED or NODE_CREATED state.
++ * DSP_EFAIL: Unable to start or resume execution.
++ * DSP_ESYMBOL: Execute function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute
++ * phase function.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * pStatus: Location to store execute-phase function return
++ * value (DSP_EUSER1-16).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ENODETYPE: Type of node specified cannot be terminated.
++ * DSP_EWRONGSTATE: Operation not valid for the current node state.
++ * DSP_EFAIL: Unable to terminate the node.
++ * Requires:
++ * NODE_Init(void) called.
++ * pStatus != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode,
++ OUT DSP_STATUS *pStatus);
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node properties given the UUID
++ * Parameters:
++ *
++ */
++ extern DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS
++ *pNodeProps);
++
++#endif /* NODE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodedefs.h b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+new file mode 100644
+index 0000000..cdc0c4b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+@@ -0,0 +1,40 @@
++/*
++ * nodedefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nodedefs.h ========
++ * Description:
++ * Global NODE constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Apr-2001 jeh Removed NODE_MGRATTRS.
++ *! 21-Sep-2000 jeh Removed NODE_TYPE enum.
++ *! 17-Jul-2000 jeh Changed order of node types to match rms_sh.h.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEDEFS_
++#define NODEDEFS_
++
++#define NODE_SUSPENDEDPRI -1
++
++/* NODE Objects: */
++ struct NODE_MGR;
++ struct NODE_OBJECT;
++
++#endif /* NODEDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodepriv.h b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+new file mode 100644
+index 0000000..d28b29b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+@@ -0,0 +1,202 @@
++/*
++ * nodepriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== nodepriv.h ========
++ * Description:
++ * Private node header shared by NODE and DISP.
++ *
++ * Public Functions:
++ * NODE_GetChannelId
++ * NODE_GetStrmMgr
++ * NODE_GetTimeout
++ * NODE_GetType
++ * NODE_GetLoadType
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2002 map Added NODE_GetLoadType
++ *! 13-Feb-2002 jeh Added uSysStackSize to NODE_TASKARGS.
++ *! 23-Apr-2001 jeh Removed unused typedefs, defines.
++ *! 10-Oct-2000 jeh Added alignment to NODE_STRMDEF.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEPRIV_
++#define NODEPRIV_
++
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/* DSP address of node environment structure */
++ typedef u32 NODE_ENV;
++
++/*
++ * Node create structures
++ */
++
++/* Message node */
++ struct NODE_MSGARGS {
++ u32 uMaxMessages; /* Max # of simultaneous messages for node */
++ u32 uSegid; /* Segment for allocating message buffers */
++ u32 uNotifyType; /* Notify type (SEM_post, SWI_post, etc.) */
++ u32 uArgLength; /* Length in 32-bit words of arg data block */
++ u8 *pData; /* Argument data for node */
++ } ;
++
++ struct NODE_STRMDEF {
++ u32 uBufsize; /* Size of buffers for SIO stream */
++ u32 uNumBufs; /* max # of buffers in SIO stream at once */
++ u32 uSegid; /* Memory segment id to allocate buffers */
++ u32 uTimeout; /* Timeout for blocking SIO calls */
++ u32 uAlignment; /* Buffer alignment */
++ char *szDevice; /* Device name for stream */
++ } ;
++
++/* Task node */
++ struct NODE_TASKARGS {
++ struct NODE_MSGARGS msgArgs;
++ s32 nPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uDSPHeapResAddr; /* DSP virtual heap address */
++ u32 uDSPHeapAddr; /* DSP virtual heap address */
++ u32 uHeapSize; /* Heap size */
++ u32 uGPPHeapAddr; /* GPP virtual heap address */
++ u32 uProfileID; /* Profile ID */
++ u32 uNumInputs;
++ u32 uNumOutputs;
++ u32 ulDaisArg; /* Address of iAlg object */
++ struct NODE_STRMDEF *strmInDef;
++ struct NODE_STRMDEF *strmOutDef;
++ } ;
++
++/*
++ * ======== NODE_CREATEARGS ========
++ */
++ struct NODE_CREATEARGS {
++ union {
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ } asa;
++ } ;
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node. This index is reserved when NODE_Connect() is called
++ * to connect the node with the host. This index should be passed to
++ * the CHNL_Open function when the stream is actually opened.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * uDir: Input (DSP_TONODE) or output (DSP_FROMNODE).
++ * uIndex: Stream index.
++ * pulId: Location to store channel index.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Not a task or DAIS socket node.
++ * DSP_EVALUE: The node's stream corresponding to uIndex and uDir
++ * is not a stream to or from the host.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid uDir.
++ * pulId != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode,
++ u32 uDir,
++ u32 uIndex, OUT u32 *pulId);
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Get the STRM manager for a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate().
++ * phStrmMgr: Location to store STRM manager on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * phStrmMgr != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr);
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Get the timeout value of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node's timeout value.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern u32 NODE_GetTimeout(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Get the type (device, message, task, or XDAIS socket) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NODE_DEVICE, NODE_TASK, NODE_XDAIS, or NODE_GPP.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Get node information without holding semaphore.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node info: priority, device owner, no. of streams, execution state
++ * NDB properties.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern void GetNodeInfo(struct NODE_OBJECT *hNode,
++ struct DSP_NODEINFO *pNodeInfo);
++
++/*
++ * ======== NODE_GetLoadType ========
++ * Purpose:
++ * Get the load type (dynamic, overlay, static) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NLDR_DYNAMICLOAD, NLDR_OVLYLOAD, NLDR_STATICLOAD
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode);
++
++#endif /* NODEPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+new file mode 100644
+index 0000000..5a0992a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+@@ -0,0 +1,146 @@
++/*
++ * ntfy.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfy.h ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 05-Nov-2001 kc: Updated NTFY_Register.
++ *! 07-Sep-2000 jeh Created.
++ */
++
++#ifndef NTFY_
++#define NTFY_
++
++ struct NTFY_OBJECT;
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ * Parameters:
++ * phNtfy: Location to store handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * Requires:
++ * NTFY_Init(void) called.
++ * phNtfy != NULL.
++ * Ensures:
++ * DSP_SUCCEEDED(status) <==> IsValid(*phNtfy).
++ */
++ extern DSP_STATUS NTFY_Create(OUT struct NTFY_OBJECT **phNtfy);
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Delete(IN struct NTFY_OBJECT *hNtfy);
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void NTFY_Exit(void);
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NTFY_Init(void);
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event or post message) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * uEventMask: The type of event that has occurred.
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Notify(IN struct NTFY_OBJECT *hNtfy,
++ IN u32 uEventMask);
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * hNotification: Handle to a DSP_NOTIFICATION object.
++ * uEventMask: Events to be notified about.
++ * uNotifyType: Type of notification: DSP_SIGNALEVENT.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * hNotification != NULL.
++ * uNotifyType is DSP_SIGNALEVENT
++ * Ensures:
++ */
++ extern DSP_STATUS NTFY_Register(IN struct NTFY_OBJECT *hNtfy,
++ IN struct DSP_NOTIFICATION
++ *hNotification,
++ IN u32 uEventMask,
++ IN u32 uNotifyType);
++
++#endif /* NTFY_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/proc.h b/arch/arm/plat-omap/include/dspbridge/proc.h
+new file mode 100644
+index 0000000..486652e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/proc.h
+@@ -0,0 +1,648 @@
++/*
++ * proc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Create
++ * PROC_Ctrl (OEM-function)
++ * PROC_Destroy
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetDevObject (OEM-function)
++ * PROC_GetResourceInfo
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace (OEM-function)
++ * PROC_Init
++ * PROC_Load (OEM-function)
++ * PROC_Map
++ * PROC_NotifyAllclients
++ * PROC_NotifyClients (OEM-function)
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start (OEM-function)
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 09-Feb-2003 vp: Added PROC_GetProcessorID function
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 28-Sep-2000 rr: Updated to Version 0.9.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types). GetTrace added.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef PROC_
++#define PROC_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object. The PROC Object gets created
++ * Parameters:
++ * uProcessor : The processor index (zero-based).
++ * hMgrObject : Handle to the Manager Object
++ * pAttrIn : Ptr to the DSP_PROCESSORATTRIN structure.
++ * A NULL value means use default values.
++ * phProcessor : Ptr to location to store processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFAIL : General failure.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_SALREADYATTACHED: Success; Processor already attached.
++ * Requires:
++ * phProcessor != NULL.
++ * PROC Initialized.
++ * Ensures:
++ * DSP_EFAIL, and *phProcessor == NULL, OR
++ * Success and *phProcessor is a Valid Processor handle OR
++ * DSP_SALREADYATTACHED and *phProcessor is a Valid Processor.
++ * Details:
++ * When pAttrIn is NULL, the default timeout value is 10 seconds.
++ */
++ extern DSP_STATUS PROC_Attach(u32 uProcessor,
++ OPTIONAL CONST struct DSP_PROCESSORATTRIN
++ *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor);
++
++/*
++ * ======== PROC_AutoStart =========
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject : Handle to the Device
++ * Returns:
++ * DSP_SOK : On Successful Loading
++ * DSP_EFILE : No DSP exec file found.
++ * DSP_EFAIL : General Failure
++ * Requires:
++ * hDevObject != NULL.
++ * hDevNode != NULL.
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the DSP
++ * processor. This will be an OEM-only function, and not part of the
++ * 'Bridge application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * dwCmd : Private driver IOCTL cmd ID.
++ * pArgs : Ptr to an driver defined argument structure.
++ * Returns:
++ * DSP_SOK : SUCCESS
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ETIMEOUT: A Timeout Occured before the Control information
++ * could be sent.
++ * DSP_EACCESSDENIED: Client does not have the access rights required
++ * to call this function.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : General Failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures
++ * Details:
++ * This function Calls WMD_BRD_Ioctl.
++ */
++ extern DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor,
++ u32 dwCmd, IN struct DSP_CBDATA *pArgs);
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Close a DSP processor and de-allocate all (GPP) resources reserved
++ * for it. The Processor Object is deleted.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : InValid Handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * PROC Object is destroyed.
++ */
++ extern DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * aNodeTab : The first Location of an array allocated for node
++ * handles.
++ * uNodeTabSize: The number of (DSP_HNODE) handles that can be held
++ * to the memory the client has allocated for aNodeTab
++ * puNumNodes : Location where DSPProcessor_EnumNodes will return
++ * the number of valid handles written to aNodeTab
++ * puAllocated : Location where DSPProcessor_EnumNodes will return
++ * the number of nodes that are allocated on the DSP.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ESIZE : The amount of memory allocated for aNodeTab is
++ * insufficent. That is the number of nodes actually
++ * allocated on the DSP is greater than the value
++ * specified for uNodeTabSize.
++ * DSP_EFAIL : Unable to get Resource Information.
++ * Details:
++ * Requires
++ * puNumNodes is not NULL.
++ * puAllocated is not NULL.
++ * aNodeTab is not NULL.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor,
++ IN DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uResourceType: Type of resource .
++ * pResourceInfo: Ptr to the DSP_RESOURCEINFO structure.
++ * uResourceInfoSize: Size of the structure.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: The processor is not in the PROC_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occured before the DSP responded to the
++ * querry.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : Unable to get Resource Information
++ * Requires:
++ * pResourceInfo is not NULL.
++ * Parameter uResourceType is Valid.[TBD]
++ * uResourceInfoSize is >= sizeof DSP_RESOURCEINFO struct.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * This function currently returns
++ * DSP_ENOTIMPL, and does not write any data to the pResourceInfo struct.
++ */
++ extern DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor,
++ u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *
++ pResourceInfo,
++ u32 uResourceInfoSize);
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * PROC is initialized.
++ * Ensures:
++ * When reference count == 0, PROC's private resources are freed.
++ */
++ extern void PROC_Exit(void);
++
++/*
++ * ======== PROC_GetDevObject =========
++ * Purpose:
++ * Returns the DEV Hanlde for a given Processor handle
++ * Parameters:
++ * hProcessor : Processor Handle
++ * phDevObject : Location to store the DEV Handle.
++ * Returns:
++ * DSP_SOK : Success; *phDevObject has Dev handle
++ * DSP_EFAIL : Failure; *phDevObject is zero.
++ * Requires:
++ * phDevObject is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * DSP_SOK : *phDevObject is not NULL
++ * DSP_EFAIL : *phDevObject is NULL.
++ */
++ extern DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each
++ * call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public PROC functions.
++ */
++ extern bool PROC_Init(void);
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pProcStatus : Ptr to location to store the DSP_PROCESSORSTATE
++ * structure.
++ * uStateInfoSize: Size of DSP_PROCESSORSTATE.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE
++ *pProcStatus,
++ u32 uStateInfoSize);
++
++/*
++ * ======== PROC_GetProcessorID ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * procID : Processor ID
++ *
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProcessor,
++ u32 *procID);
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the trace buffer from the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pBuf : Ptr to buffer to hold trace output.
++ * uMaxSize : Maximum size of the output buffer.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while retireving processor trace
++ * Buffer.
++ * Requires:
++ * pBuf is not NULL
++ * uMaxSize is > 0.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf,
++ u32 uMaxSize);
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * iArgc : The number of Arguments(strings)in the aArgV[]
++ * aArgv : An Array of Arguments(Unicode Strings)
++ * aEnvp : An Array of Environment settings(Unicode Strings)
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFILE : The DSP Execuetable was not found.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ECORRUTFILE: Unable to Parse the DSP Execuetable
++ * DSP_EATTACHED: Abort because a GPP Client is attached to the
++ * specified Processor
++ * DSP_EACCESSDENIED: Client does not have the required access rights
++ * to reset and load the Processor
++ * DSP_EFAIL : Unable to Load the Processor
++ * Requires:
++ * aArgv is not NULL
++ * iArgc is > 0
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_LOADED
++ * or DSP_FAILED status.
++ * Details:
++ * Does not implement access rights to control which GPP application
++ * can load the processor.
++ */
++ extern DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor,
++ IN CONST s32 iArgc, IN CONST char **aArgv,
++ IN CONST char **aEnvp);
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uEventMask : Mask of types of events to be notified about.
++ * uNotifyType : Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle or hNotification.
++ * DSP_EVALUE : Parameter uEventMask is Invalid
++ * DSP_ENOTIMP : The notification type specified in uNotifyMask
++ * is not supported.
++ * DSP_EFAIL : Unable to register for notification.
++ * Requires:
++ * hNotification is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * NODE And STRM would use this function to notify their clients
++ * about the state changes in NODE or STRM.
++ */
++ extern DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flushes a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * ulFlags : Reserved.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize, u32 ulFlags);
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize);
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Starting address of the memory region to map.
++ * ulSize : Size of the memory region to map.
++ * pReqAddr : Requested DSP start address. Offset-adjusted actual
++ * mapped address is in the last argument.
++ * ppMapAddr : Ptr to DSP side mapped u8 address.
++ * ulMapAttr : Optional endianness attributes, virt to phys flag.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : MPU side memory allocation error.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pMpuAddr is not NULL
++ * ulSize is not zero
++ * ppMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize,
++ void *pReqAddr,
++ void **ppMapAddr, u32 ulMapAttr);
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * ulSize : Size of the address space to reserve.
++ * ppRsvAddr : Ptr to DSP side reserved u8 address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : Cannot reserve chunk of this size.
++ * Requires:
++ * ppRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
++ u32 ulSize, void **ppRsvAddr);
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMapAddr : Starting address of the mapped memory region.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a mapped region starting with this
++ * : address.
++ * Requires:
++ * pMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr);
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pRsvAddr : Ptr to DSP side reservedBYTE address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
++ void *pRsvAddr);
++
++#endif /* PROC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/procpriv.h b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+new file mode 100644
+index 0000000..21d4b3e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+@@ -0,0 +1,35 @@
++/*
++ * procpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== procpriv.h ========
++ * Description:
++ * Global PROC constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef PROCPRIV_
++#define PROCPRIV_
++
++/* RM PROC Object */
++ struct PROC_OBJECT;
++
++#endif /* PROCPRIV_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr.h b/arch/arm/plat-omap/include/dspbridge/pwr.h
+new file mode 100644
+index 0000000..a6645ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr.h
+@@ -0,0 +1,129 @@
++/*
++ * pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== pwr.h ========
++ *
++ * Public Functions:
++ *
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Jun-2002 sg Replaced dspdefs.h with includes of dbdefs.h and errbase.h.
++ *! 13-May-2002 sg Added DSP_SAREADYASLEEP and DSP_SALREADYAWAKE.
++ *! 09-May-2002 sg Updated, added timeouts.
++ *! 02-May-2002 sg Initial.
++ */
++
++#ifndef PWR_
++#define PWR_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/pwr_sh.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Signal the DSP to go to sleep.
++ *
++ * Parameters:
++ * sleepCode: New sleep state for DSP. (Initially, valid codes
++ * are PWR_DEEPSLEEP or PWR_EMERGENCYDEEPSLEEP; both of
++ * these codes will simply put the DSP in deep sleep.)
++ *
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP sleep state has been
++ * reached. If PWR should simply send the command to
++ * the DSP to go to sleep and then return (i.e.,
++ * asynchrounous sleep), the timeout should be
++ * specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYASLEEP: Success, but the DSP was already asleep.
++ * DSP_EINVALIDARG: The specified sleepCode is not supported.
++ * DSP_ETIMEOUT: A timeout occured while waiting for DSP sleep
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send sleep command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode,
++ IN CONST u32 timeout);
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Signal the DSP to wake from sleep.
++ *
++ * Parameters:
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP is awake. If PWR should
++ * simply send a command to the DSP to wake and then
++ * return (i.e., asynchrounous wake), timeout should
++ * be specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout);
++
++/*
++ * ======== PWR_PM_PreScale ========
++ * Prescale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level);
++
++/*
++ * ======== PWR_PM_PostScale ========
++ * PostScale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain,
++ u32 level);
++
++#endif /* PWR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr_sh.h b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+new file mode 100644
+index 0000000..40f1b84
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+@@ -0,0 +1,41 @@
++/*
++ * pwr_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== pwr_sh.h ========
++ *
++ * Power Manager shared definitions (used on both GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 17-Apr-2002 sg: Initial.
++ */
++
++#ifndef PWR_SH_
++#define PWR_SH_
++
++#include <dspbridge/mbx_sh.h>
++
++/* valid sleep command codes that can be sent by GPP via mailbox: */
++#define PWR_DEEPSLEEP MBX_PM_DSPIDLE
++#define PWR_EMERGENCYDEEPSLEEP MBX_PM_EMERGENCYSLEEP
++#define PWR_SLEEPUNTILRESTART MBX_PM_SLEEPUNTILRESTART
++#define PWR_WAKEUP MBX_PM_DSPWAKEUP
++#define PWR_AUTOENABLE MBX_PM_PWRENABLE
++#define PWR_AUTODISABLE MBX_PM_PWRDISABLE
++#define PWR_RETENTION MBX_PM_DSPRETN
++
++#endif /* PWR_SH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/reg.h b/arch/arm/plat-omap/include/dspbridge/reg.h
+new file mode 100644
+index 0000000..5b34952
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/reg.h
+@@ -0,0 +1,257 @@
++/*
++ * reg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== reg.h ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumKey
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! =================
++ *! 30-Oct-2000 kc: Updated REG_SetValue & REG_GetValue; renamed
++ *! REG_DeleteEntry to REG_DeleteValue.
++ *! 29-Sep-2000 kc: Updated a REG functions for code review.
++ *! 12-Aug-2000 kc: Renamed REG_EnumValue to REG_EnumKey. Re-implemented
++ *! REG_EnumValue.
++ *! 03-Feb-2000 rr: REG_EnumValue Fxn Added
++ *! 13-Dec-1999 rr: windows.h removed
++ *! 02-Dec-1999 rr: windows.h included for retail build
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 29-Dec-1997 cr: Changes from code review.
++ *! 27-Oct-1997 cr: Added REG_DeleteValue.
++ *! 20-Oct-1997 cr: Added ability to pass bValue = NULL to REG_GetValue
++ *! and return size of reg entry in pdwValueSize.
++ *! 29-Sep-1997 cr: Added REG_SetValue
++ *! 29-Aug-1997 cr: Created.
++ */
++
++#ifndef _REG_H
++#define _REG_H
++
++#include <linux/types.h>
++
++/* ------------------------- Defines, Data Structures, Typedefs for Linux */
++#ifndef UNDER_CE
++
++#ifndef REG_SZ
++#define REG_SZ 1
++#endif
++
++#ifndef REG_BINARY
++#define REG_BINARY 3
++#endif
++
++#ifndef REG_DWORD
++#define REG_DWORD 4
++#endif
++
++#endif /* UNDER_CE */
++
++#define REG_MAXREGPATHLENGTH 255
++
++/*
++ * ======== REG_DeleteValue ========
++ * Purpose:
++ * Deletes a registry entry. NOTE: A registry entry is not the same as
++ * a registry key.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrValue: Name of entry to delete.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrValue are non-NULL values.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrValue < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++
++/*
++ * ======== REG_EnumKey ========
++ * Purpose:
++ * Enumerates subkeys of the specified path to the registry key
++ * Retrieves the name of the subkey(given the index) and
++ * appends with the orignal path to form the full path.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrKey The name of the registry key to be enumerated.
++ * dwIndex Specifies the index of the subkey to retrieve.
++ * pstrSubkey: Pointer to buffer that receives full path name of the
++ * specified key + the sub-key
++ * pdwValueSize: Specifies bytes of memory pstrSubkey points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If there is no sub key,pdwValueSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrKey is non-NULL value.
++ * - pdwValueSize is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrKey < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * - strlen(pstrSubkey) is > strlen(pstrKey) &&
++ * - strlen(pstrSubkey) is < REG_MAXREGPATHLENGTH
++ */
++ extern DSP_STATUS REG_EnumKey(OPTIONAL IN HANDLE *phKey,
++ IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrSubkey,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_EnumValue ========
++ * Purpose:
++ * Enumerates values of a specified key. Retrieves each value name and
++ * the data associated with the value.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * dwIndex: Specifies the index of the value to retrieve.
++ * pstrKey: The name of the registry key to be enumerated.
++ * pstrValue: Pointer to buffer that receives the name of the value.
++ * pdwValueSize: Specifies bytes of memory pstrValue points to on input,
++ * On output, specifies actual memory bytes written into.
++ * If there is no value, pdwValueSize returns NULL
++ * pstrData: Pointer to buffer that receives the data of a value.
++ * pdwDataSize: Specifies bytes of memory in pstrData on input and
++ * bytes of memory written into pstrData on output.
++ * If there is no data, pdwDataSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * REG initialized.
++ * phKey is NULL.
++ * pstrKey is a non-NULL value.
++ * pstrValue, pstrData, pdwValueSize and pdwDataSize are valid pointers.
++ * Length of pstrKey is less than REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_EnumValue(IN HANDLE *phKey,
++ IN u32 dwIndex,
++ IN CONST char *pstrKey,
++ IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize);
++
++/*
++ * ======== REG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * REG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void REG_Exit(void);
++
++/*
++ * ======== REG_GetValue ========
++ * Purpose:
++ * Retrieve a value from the registry.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrEntry: Name of entry to retrieve.
++ * pbValue: Upon return, points to retrieved value.
++ * pdwValueSize: Specifies bytes of memory pbValue points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If pbValue is NULL, pdwValueSize reports the size of
++ * the entry in pstrEntry.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrEntry,
++ OUT u8 *pbValue,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_Init ========
++ * Purpose:
++ * Initializes private state of REG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * REG initialized.
++ */
++ extern bool REG_Init(void);
++
++/*
++ * ======== REG_SetValue ========
++ * Purpose:
++ * Set a value in the registry.
++ * Parameters:
++ * phKey: Handle to open reg key, or NULL if pSubkey is full path.
++ * pstrSubkey: Path to key to open, could be based on phKey.
++ * pstrEntry: Name of entry to set.
++ * dwType: Data type of new registry value.
++ * pbValue: Points to buffer containing new data.
++ * dwValueSize: Specifies bytes of memory bValue points to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - dwValuSize > 0.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubKey,
++ IN CONST char *pstrEntry,
++ IN CONST u32 dwType,
++ IN u8 *pbValue, IN u32 dwValueSize);
++
++#endif /* _REG_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+new file mode 100644
+index 0000000..b43fa16
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+@@ -0,0 +1,88 @@
++/*
++ * resourcecleanup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef RES_CLEANUP_DISABLE
++
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/drv.h>
++
++
++extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject);
++
++extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
++ HANDLE hPCtxt);
++
++extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdatestate(HANDLE pCtxt,
++ enum GPP_PROC_RES_STATE resState);
++
++extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
++
++extern DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr);
++
++extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
++
++extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess);
++
++extern DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_RemoveNodeResElement(HANDLE nodeRes, HANDLE status);
++
++extern void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_UpdateDMMResElement(HANDLE dmmRes, u32 pMpuAddr,
++ u32 ulSize, u32 pReqAddr,
++ u32 ppMapAddr, HANDLE hProcesso);
++
++extern DSP_STATUS DRV_InsertDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE dmmRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pPctxt);
++
++extern DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE STRMRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf, u32 *pSize);
++
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmm.h b/arch/arm/plat-omap/include/dspbridge/rmm.h
+new file mode 100644
+index 0000000..5b14b8f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmm.h
+@@ -0,0 +1,199 @@
++/*
++ * rmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.h ========
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments, and management of overlay
++ * memory.
++ *
++ * Public functions:
++ * RMM_alloc
++ * RMM_create
++ * RMM_delete
++ * RMM_exit
++ * RMM_free
++ * RMM_init
++ *
++ *! Revision History
++ *! ================
++ *! 25-Jun-2002 jeh Added RMM_Addr. Removed RMM_reserve, RMM_stat.
++ *! 15-Oct-2001 jeh Based on rm.h in gen tree.
++ */
++
++#ifndef RMM_
++#define RMM_
++
++/*
++ * ======== RMM_Addr ========
++ * DSP address + segid
++ */
++struct RMM_Addr {
++ u32 addr;
++ s32 segid;
++} ;
++
++/*
++ * ======== RMM_Segment ========
++ * Memory segment on the DSP available for remote allocations.
++ */
++struct RMM_Segment {
++ u32 base; /* Base of the segment */
++ u32 length; /* Size of the segment (target MAUs) */
++ s32 space; /* Code or data */
++ u32 number; /* Number of Allocated Blocks */
++} ;
++
++/*
++ * ======== RMM_Target ========
++ */
++struct RMM_TargetObj;
++
++/*
++ * ======== RMM_alloc ========
++ *
++ * RMM_alloc is used to remotely allocate or reserve memory on the DSP.
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * segid - Memory segment to allocate from.
++ * size - Size (target MAUS) to allocate.
++ * align - alignment.
++ * dspAddr - If reserve is FALSE, the location to store allocated
++ * address on output, otherwise, the DSP address to
++ * reserve.
++ * reserve - If TRUE, reserve the memory specified by dspAddr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation on GPP failed.
++ * DSP_EOVERLAYMEMORY: Cannot "allocate" overlay memory because it's
++ * already in use.
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * dspAddr != NULL.
++ * size > 0
++ * reserve || target->numSegs > 0.
++ * Ensures:
++ */
++extern DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAdr, bool reserve);
++
++/*
++ * ======== RMM_create ========
++ * Create a target object with memory segments for remote allocation. If
++ * segTab == NULL or numSegs == 0, memory can only be reserved through
++ * RMM_alloc().
++ *
++ * Parameters:
++ * pTarget: - Location to store target on output.
++ * segTab: - Table of memory segments.
++ * numSegs: - Number of memory segments.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * RMM initialized.
++ * pTarget != NULL.
++ * numSegs == 0 || segTab != NULL.
++ * Ensures:
++ * Success: Valid *pTarget.
++ * Failure: *pTarget == NULL.
++ */
++extern DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs);
++
++/*
++ * ======== RMM_delete ========
++ * Delete target allocated in RMM_create().
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * Ensures:
++ */
++extern void RMM_delete(struct RMM_TargetObj *target);
++
++/*
++ * ======== RMM_exit ========
++ * Exit the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * RMM_init successfully called.
++ * Ensures:
++ */
++extern void RMM_exit(void);
++
++/*
++ * ======== RMM_free ========
++ * Free or unreserve memory allocated through RMM_alloc().
++ *
++ * Parameters:
++ * target: - Target returned from RMM_create().
++ * segid: - Segment of memory to free.
++ * dspAddr: - Address to free or unreserve.
++ * size: - Size of memory to free or unreserve.
++ * reserved: - TRUE if memory was reserved only, otherwise FALSE.
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * reserved || segid < target->numSegs.
++ * reserve || [dspAddr, dspAddr + size] is a valid memory range.
++ * Ensures:
++ */
++extern bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 dspAddr,
++ u32 size, bool reserved);
++
++/*
++ * ======== RMM_init ========
++ * Initialize the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * Ensures:
++ */
++extern bool RMM_init(void);
++
++/*
++ * ======== RMM_stat ========
++ * Obtain memory segment status
++ *
++ * Parameters:
++ * segid: Segment ID of the dynamic loading segment.
++ * pMemStatBuf: Pointer to allocated buffer into which memory stats are
++ * placed.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * segid < target->numSegs
++ * Ensures:
++ */
++extern bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf);
++
++#endif /* RMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/rms_sh.h b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+new file mode 100644
+index 0000000..5d4b49a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+@@ -0,0 +1,125 @@
++/*
++ * rms_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rms_sh.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared definitions (used on both
++ * GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Merged updates required for CCS2.2 transition.
++ *! 24-Feb-2003 kc Rearranged order of node types to temporarily support
++ *! legacy message node code
++ *! 23-Nov-2002 gp Converted tabs -> spaces, to fix formatting.
++ *! 13-Feb-2002 jeh Added sysstacksize element to RMS_MoreTaskArgs.
++ *! 11-Dec-2000 sg Added 'misc' element to RMS_MoreTaskArgs.
++ *! 04-Dec-2000 ag Added RMS_BUFDESC command code.
++ *! C/R code value changed to allow ORing of system/user codes.
++ *! 10-Oct-2000 sg Added 'align' field to RMS_StrmDef.
++ *! 09-Oct-2000 sg Moved pre-defined message codes here from rmsdefs.h.
++ *! 02-Oct-2000 sg Changed ticks to msec.
++ *! 24-Aug-2000 sg Moved definitions that will be exposed to app developers
++ *! to a separate file, rmsdefs.h.
++ *! 10-Aug-2000 sg Added RMS_COMMANDBUFSIZE and RMS_RESPONSEBUFSIZE; added
++ *! pre-defined command/response codes; more comments.
++ *! 09-Aug-2000 sg Added RMS_ETASK.
++ *! 08-Aug-2000 jeh Define RMS_WORD for GPP, rename DSP_MSG to RMS_DSPMSG.
++ *! Added RMS_MsgArgs, RMS_MoreTaskArgs.
++ *! 25-Jul-2000 sg: Changed SIO to STRM.
++ *! 30-Jun-2000 sg: Initial.
++ */
++
++#ifndef RMS_SH_
++#define RMS_SH_
++
++#include <dspbridge/rmstypes.h>
++
++/* Node Types: */
++#define RMS_TASK 1 /* Task node */
++#define RMS_DAIS 2 /* xDAIS socket node */
++#define RMS_MSG 3 /* Message node */
++
++/* Memory Types: */
++#define RMS_CODE 0 /* Program space */
++#define RMS_DATA 1 /* Data space */
++#define RMS_IO 2 /* I/O space */
++
++/* RM Server Command and Response Buffer Sizes: */
++#define RMS_COMMANDBUFSIZE 256 /* Size of command buffer */
++#define RMS_RESPONSEBUFSIZE 16 /* Size of response buffer */
++
++/* Pre-Defined Command/Response Codes: */
++#define RMS_EXIT 0x80000000 /* GPP->Node: shutdown */
++#define RMS_EXITACK 0x40000000 /* Node->GPP: ack shutdown */
++#define RMS_BUFDESC 0x20000000 /* Arg1 SM buf, Arg2 is SM size */
++#define RMS_KILLTASK 0x10000000 /* GPP->Node: Kill Task */
++#define RMS_USER 0x0 /* Start of user-defined msg codes */
++#define RMS_MAXUSERCODES 0xfff /* Maximum user defined C/R Codes */
++
++
++/* RM Server RPC Command Structure: */
++ struct RMS_Command {
++ RMS_WORD fxn; /* Server function address */
++ RMS_WORD arg1; /* First argument */
++ RMS_WORD arg2; /* Second argument */
++ RMS_WORD data; /* Function-specific data array */
++ } ;
++
++/*
++ * The RMS_StrmDef structure defines the parameters for both input and output
++ * streams, and is passed to a node's create function.
++ */
++ struct RMS_StrmDef {
++ RMS_WORD bufsize; /* Buffer size (in DSP words) */
++ RMS_WORD nbufs; /* Max number of bufs in stream */
++ RMS_WORD segid; /* Segment to allocate buffers */
++ RMS_WORD align; /* Alignment for allocated buffers */
++ RMS_WORD timeout; /* Timeout (msec) for blocking calls */
++ RMS_CHAR name[1]; /* Device Name (terminated by '\0') */
++ } ;
++
++/* Message node create args structure: */
++ struct RMS_MsgArgs {
++ RMS_WORD maxMessages; /* Max # simultaneous msgs to node */
++ RMS_WORD segid; /* Mem segment for NODE_allocMsgBuf */
++ RMS_WORD notifyType; /* Type of message notification */
++ RMS_WORD argLength; /* Length (in DSP chars) of arg data */
++ RMS_WORD argData; /* Arg data for node */
++ } ;
++
++/* Partial task create args structure */
++ struct RMS_MoreTaskArgs {
++ RMS_WORD priority; /* Task's runtime priority level */
++ RMS_WORD stackSize; /* Task's stack size */
++ RMS_WORD sysstackSize; /* Task's system stack size (55x) */
++ RMS_WORD stackSeg; /* Memory segment for task's stack */
++ RMS_WORD heapAddr; /* base address of the node memory heap in
++ * external memory (DSP virtual address) */
++ RMS_WORD heapSize; /* size in MAUs of the node memory heap in
++ * external memory */
++ RMS_WORD misc; /* Misc field. Not used for 'normal'
++ * task nodes; for xDAIS socket nodes
++ * specifies the IALG_Fxn pointer.
++ */
++ /* # input STRM definition structures */
++ RMS_WORD numInputStreams;
++ } ;
++
++#endif /* RMS_SH_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmstypes.h b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+new file mode 100644
+index 0000000..13d752e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+@@ -0,0 +1,40 @@
++/*
++ * rmstypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== rmstypes.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared data type definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 06-Oct-2000 sg Added LgFxn type.
++ *! 05-Oct-2000 sg Changed RMS_STATUS to LgUns.
++ *! 31-Aug-2000 sg Added RMS_DSPMSG.
++ *! 25-Aug-2000 sg Initial.
++ */
++
++#ifndef RMSTYPES_
++#define RMSTYPES_
++#include <linux/types.h>
++/*
++ * DSP-side definitions.
++ */
++#include <dspbridge/std.h>
++typedef u32 RMS_WORD;
++typedef char RMS_CHAR;
++
++#endif /* RMSTYPES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/services.h b/arch/arm/plat-omap/include/dspbridge/services.h
+new file mode 100644
+index 0000000..35bab0d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/services.h
+@@ -0,0 +1,63 @@
++/*
++ * services.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.h ========
++ * Purpose:
++ * Provide loading and unloading of SERVICES modules.
++ *
++ * Public Functions:
++ * SERVICES_Exit(void)
++ * SERVICES_Init(void)
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#ifndef SERVICES_
++#define SERVICES_
++
++#include <dspbridge/host_os.h>
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SERVICES initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SERVICES_Exit(void);
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ * Parameters:
++ * Returns:
++ * TRUE if all modules initialized; otherwise FALSE.
++ * Requires:
++ * Ensures:
++ * SERVICES modules initialized.
++ */
++ extern bool SERVICES_Init(void);
++
++#endif /* SERVICES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/std.h b/arch/arm/plat-omap/include/dspbridge/std.h
+new file mode 100644
+index 0000000..ec849f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/std.h
+@@ -0,0 +1,143 @@
++/*
++ * std.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== std.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp GNU compiler 3.x defines inline keyword. Added
++ *! appropriate macros not to redefine inline keyword in
++ *! this file.
++ *! 24-Oct-2002 ashu defined _TI_ and _FIXED_ symbols for 28x.
++ *! 24-Oct-2002 ashu defined _TI_ for 24x.
++ *! 01-Mar-2002 kln changed LARGE_MODEL and Arg definition for 28x
++ *! 01-Feb-2002 kln added definitions for 28x
++ *! 08-Dec-2000 kw: added 'ArgToInt' and 'ArgToPtr' macros
++ *! 30-Nov-2000 mf: Added _64_, _6x_; removed _7d_
++ *! 30-May-2000 srid: Added __TMS320C55X__ for 55x; Arg is void * for 55 .
++ *! 18-Jun-1999 dr: Added '_TI_', fixed __inline for SUN4, added inline
++ *! 10-Feb-1999 rt: Added '55' support, changed 54's symbol to _TMS320C5XX
++ *! 29-Aug-1998 mf: fixed typo, removed obsolete targets
++ *! 08-Jun-1998 mf: _67_ is synonym for _7d_
++ *! 10-Oct-1997 rt; added _7d_ for Raytheon C7DSP triggered by _TMS320C6700
++ *! 04-Aug-1997 cc: added _29_ for _TMS320C2XX
++ *! 11-Jul-1997 dlr: _5t_, and STD_SPOXTASK keyword for Tasking
++ *! 12-Jun-1997 mf: _TMS320C60 -> _TMS320C6200
++ *! 13-Feb-1997 mf: _62_, with 32-bit LgInt
++ *! 26-Nov-1996 kw: merged bios-c00's and wsx-a27's <dspbridge/std.h> changes
++ *! *and* revision history
++ *! 12-Sep-1996 kw: added C54x #ifdef's
++ *! 21-Aug-1996 mf: removed #define main smain for _21_
++ *! 14-May-1996 gp: def'd out INT, FLOAT, and COMPLEX defines for WSX.
++ *! 11-Apr-1996 kw: define _W32_ based on _WIN32 (defined by MS compiler)
++ *! 07-Mar-1996 mg: added Win32 support
++ *! 06-Sep-1995 dh: added _77_ dynamic stack support via fxns77.h
++ *! 27-Jun-1995 dh: added _77_ support
++ *! 16-Mar-1995 mf: for _21_: #define main smain
++ *! 01-Mar-1995 mf: set _20_ and _60_ (as well as _21_ for both)
++ *! 22-Feb-1995 mf: Float is float for _SUN_ and _80_
++ *! 22-Dec-1994 mf: Added _80_ definition, for PP or MP.
++ *! 09-Dec-1994 mf: Added _53_ definition.
++ *! Added definitions of _30_, etc.
++ *! 23-Aug-1994 dh removed _21_ special case (kw)
++ *! 17-Aug-1994 dh added _51_ support
++ *! 03-Aug-1994 kw updated _80_ support
++ *! 30-Jun-1994 kw added _80_ support
++ *! 05-Apr-1994 kw: Added _SUN_ to _FLOAT_ definition
++ *! 01-Mar-1994 kw: Made Bool an int (was u16) for _56_ (more efficient).
++ *! Added _53_ support.
++ */
++
++#ifndef STD_
++#define STD_
++
++#include <linux/types.h>
++
++/*
++ * ======== _TI_ ========
++ * _TI_ is defined for all TI targets
++ */
++#if defined(_29_) || defined(_30_) || defined(_40_) || defined(_50_) || \
++ defined(_54_) || defined(_55_) || defined(_6x_) || defined(_80_) || \
++ defined(_28_) || defined(_24_)
++#define _TI_ 1
++#endif
++
++/*
++ * ======== _FLOAT_ ========
++ * _FLOAT_ is defined for all targets that natively support floating point
++ */
++#if defined(_SUN_) || defined(_30_) || defined(_40_) || defined(_67_) || \
++ defined(_80_)
++#define _FLOAT_ 1
++#endif
++
++/*
++ * ======== _FIXED_ ========
++ * _FIXED_ is defined for all fixed point target architectures
++ */
++#if defined(_29_) || defined(_50_) || defined(_54_) || defined(_55_) || \
++ defined(_62_) || defined(_64_) || defined(_28_)
++#define _FIXED_ 1
++#endif
++
++/*
++ * ======== _TARGET_ ========
++ * _TARGET_ is defined for all target architectures (as opposed to
++ * host-side software)
++ */
++#if defined(_FIXED_) || defined(_FLOAT_)
++#define _TARGET_ 1
++#endif
++
++/*
++ * 8, 16, 32-bit type definitions
++ *
++ * Sm* - 8-bit type
++ * Md* - 16-bit type
++ * Lg* - 32-bit type
++ *
++ * *s32 - signed type
++ * *u32 - unsigned type
++ * *Bits - unsigned type (bit-maps)
++ */
++
++/*
++ * Aliases for standard C types
++ */
++
++typedef s32(*Fxn) (void); /* generic function type */
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++
++/*
++ * These macros are used to cast 'Arg' types to 's32' or 'Ptr'.
++ * These macros were added for the 55x since Arg is not the same
++ * size as s32 and Ptr in 55x large model.
++ */
++#if defined(_28l_) || defined(_55l_)
++#define ArgToInt(A) ((s32)((long)(A) & 0xffff))
++#define ArgToPtr(A) ((Ptr)(A))
++#else
++#define ArgToInt(A) ((s32)(A))
++#define ArgToPtr(A) ((Ptr)(A))
++#endif
++
++#endif /* STD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strm.h b/arch/arm/plat-omap/include/dspbridge/strm.h
+new file mode 100644
+index 0000000..5825615
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strm.h
+@@ -0,0 +1,441 @@
++/*
++ * strm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.h ========
++ * Description:
++ * DSPBridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 15-Nov-2001 ag Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Added DSP_ESIZE error to STRM_AllocateBuffer().
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 06-Feb-2001 kc Updated DBC_Ensure for STRM_Select().
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open().
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRM_
++#define STRM_
++
++#include <dspbridge/dev.h>
++
++#include <dspbridge/strmdefs.h>
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocate data buffer(s) for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer(s).
++ * uNumBufs: Number of buffers to allocate.
++ * apBuffer: Array to hold buffer addresses.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EFAIL: Failure occurred, unable to allocate buffers.
++ * DSP_ESIZE: uSize must be > 0 bytes.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ OUT u8 **apBuffer,
++ u32 uNumBufs);
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EPENDING: Some data buffers issued to the stream have not
++ * been reclaimed.
++ * DSP_EFAIL: Failure to close stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm);
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object. This object holds information about the
++ * device needed to open streams.
++ * Parameters:
++ * phStrmMgr: Location to store handle to STRM manager object on
++ * output.
++ * hDev: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrmMgr != NULL.
++ * hDev != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phStrmMgr.
++ * error: *phStrmMgr == NULL.
++ */
++ extern DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr,
++ struct DEV_OBJECT *hDev);
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Object.
++ * Parameters:
++ * hStrmMgr: Handle to STRM manager object from STRM_Create.
++ * Returns:
++ * Requires:
++ * STRM_Init(void) called.
++ * Valid hStrmMgr.
++ * Ensures:
++ * hStrmMgr is not valid.
++ */
++ extern void STRM_Delete(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * STRM_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void STRM_Exit(void);
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Free buffer(s) allocated with STRM_AllocateBuffer.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * apBuffer: Array containing buffer addresses.
++ * uNumBufs: Number of buffers to be freed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid stream handle.
++ * DSP_EFAIL: Failure occurred, unable to free buffers.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm,
++ u8 **apBuffer, u32 uNumBufs);
++
++/*
++ * ======== STRM_GetEventHandle ========
++ * Purpose:
++ * Get stream's user event handle. This function is used when closing
++ * a stream, so the event can be closed.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * phEvent: Location to store event handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * Requires:
++ * STRM_Init(void) called.
++ * phEvent != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetEventHandle(struct STRM_OBJECT *hStrm,
++ OUT HANDLE *phEvent);
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Get information about a stream. User's DSP_STREAMINFO is contained
++ * in STRM_INFO struct. STRM_INFO also contains Bridge private info.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pStreamInfo: Location to store stream info on output.
++ * uSteamInfoSize: Size of user's DSP_STREAMINFO structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESIZE: uStreamInfoSize < sizeof(DSP_STREAMINFO).
++ * DSP_EFAIL: Unable to get stream info.
++ * Requires:
++ * STRM_Init(void) called.
++ * pStreamInfo != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize);
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idle a stream and optionally flush output data buffers.
++ * If this is an output stream and fFlush is TRUE, all data currently
++ * enqueued will be discarded.
++ * If this is an output stream and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ * After a successful call to STRM_Idle(), all buffers can immediately
++ * be reclaimed.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * fFlush: If TRUE, discard output buffers.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before the stream could be idled.
++ * DSP_ERESTART: A critical error occurred, DSP is being restarted.
++ * DSP_EFAIL: Unable to idle stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush);
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool STRM_Init(void);
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Send a buffer of data to a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBuf: Pointer to buffer of data to be sent to the stream.
++ * ulBytes: Number of bytes of data in the buffer.
++ * ulBufSize: Actual buffer size in bytes.
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESTREAMFULL: The stream is full.
++ * DSP_EFAIL: Failure occurred, unable to issue buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuf != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf,
++ u32 ulBytes, u32 ulBufSize,
++ IN u32 dwArg);
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task of
++ * DAIS socket node on the DSP.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * uDir: DSP_TONODE or DSP_FROMNODE.
++ * uIndex: Stream index.
++ * pAttr: Pointer to structure containing attributes to be
++ * applied to stream. Cannot be NULL.
++ * phStrm: Location to store stream handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EDIRECTION: Invalid uDir.
++ * DSP_EVALUE: Invalid uIndex.
++ * DSP_ENODETYPE: hNode is not a task or DAIS socket node.
++ * DSP_EFAIL: Unable to open stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrm != NULL.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *phStrm is valid.
++ * error: *phStrm == NULL.
++ */
++ extern DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir,
++ u32 uIndex, IN struct STRM_ATTR *pAttr,
++ OUT struct STRM_OBJECT **phStrm);
++
++/*
++ * ======== STRM_PrepareBuffer ========
++ * Purpose:
++ * Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
++ * for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to prepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_PrepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Request a buffer back from a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBufPtr: Location to store pointer to reclaimed buffer.
++ * pulBytes: Location where number of bytes of data in the
++ * buffer will be written.
++ * pulBufSize: Location where actual buffer size will be written.
++ * pdwArg: Location where user argument that travels with
++ * the buffer will be written.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before a buffer could be
++ * retrieved.
++ * DSP_EFAIL: Failure occurred, unable to reclaim buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBufPtr != NULL.
++ * pulBytes != NULL.
++ * pdwArg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm,
++ OUT u8 **pBufPtr, u32 *pulBytes,
++ u32 *pulBufSize, u32 *pdwArg);
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ * Parameters:
++ * hStrm: Stream handle returned by STRM_Open().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * STRM_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Select a ready stream.
++ * Parameters:
++ * aStrmTab: Array of stream handles returned from STRM_Open().
++ * nStrms: Number of stream handles in array.
++ * pMask: Location to store mask of ready streams on output.
++ * uTimeout: Timeout value (milliseconds).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ERANGE: nStrms out of range.
++
++ * DSP_EHANDLE: Invalid stream handle in array.
++ * DSP_ETIMEOUT: A timeout occurred before a stream became ready.
++ * DSP_EFAIL: Failure occurred, unable to select a stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * aStrmTab != NULL.
++ * nStrms > 0.
++ * pMask != NULL.
++ * Ensures:
++ * DSP_SOK: *pMask != 0 || uTimeout == 0.
++ * Error: *pMask == 0.
++ */
++ extern DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab,
++ u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout);
++
++/*
++ * ======== STRM_UnprepareBuffer ========
++ * Purpose:
++ * Unprepare a data buffer that was previously prepared for a stream
++ * with DSPStream_PrepareBuffer(), and that will no longer be used with
++ * the stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to unprepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_UnprepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++#endif /* STRM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strmdefs.h b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+new file mode 100644
+index 0000000..44d217a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+@@ -0,0 +1,57 @@
++/*
++ * strmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strmdefs.h ========
++ * Purpose:
++ * Global STRM constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2001 ag Added STRM_INFO..
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRMDEFS_
++#define STRMDEFS_
++
++#define STRM_MAXEVTNAMELEN 32
++
++ struct STRM_MGR;
++
++ struct STRM_OBJECT;
++
++ struct STRM_ATTR {
++ HANDLE hUserEvent;
++ char *pstrEventName;
++ void *pVirtBase; /* Process virtual base address of
++ * mapped SM */
++ u32 ulVirtSize; /* Size of virtual space in bytes */
++ struct DSP_STREAMATTRIN *pStreamAttrIn;
++ } ;
++
++ struct STRM_INFO {
++ enum DSP_STRMMODE lMode; /* transport mode of
++ * stream(DMA, ZEROCOPY..) */
++ u32 uSegment; /* Segment strm allocs from. 0 is local mem */
++ void *pVirtBase; /* " " Stream'process virt base */
++ struct DSP_STREAMINFO *pUser; /* User's stream information
++ * returned */
++ } ;
++
++#endif /* STRMDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/sync.h b/arch/arm/plat-omap/include/dspbridge/sync.h
+new file mode 100644
+index 0000000..fa3ff8d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/sync.h
+@@ -0,0 +1,340 @@
++/*
++ * sync.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.h ========
++ * Purpose:
++ * Provide synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_PostMessage
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 01-Dec-1999 ag: Added #define SYNC_MAXNAMELENGTH.
++ *! 04-Nov-1999 kc: Added critical section functions and objects to SYNC.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 24-Sep-1999 kc: Added WinCE notes.
++ *! 20-Oct-1997 gp: Removed unused SYNC_ critical section and must complete fxns
++ *! Added SYNC_HOBJECT, SYNC_ATTRS, and object validation, and
++ *! merged SYNC_DestroyEvent into SYNC_CloseEvent, and merged
++ *! SYNC_CreateEvent into SYNC_OpenEvent.
++ *! 07-Oct-1997 gp: Added SYNC_Create/DestroyEvent (for NT testing).
++ *! 06-Oct-1997 gp: Added SYNC_OpenEvent.
++ *! 03-Jun-1997 gp: Added SYNC_{Begin|End}CritSection() functions.
++ *! 03-Jan-1997 gp: Added SYNC_INFINITE define.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++#ifndef _SYNC_H
++#define _SYNC_H
++
++#define SIGNATURECS 0x53435953 /* "SYCS" (in reverse) */
++#define SIGNATUREDPCCS 0x53445953 /* "SYDS" (in reverse) */
++
++/* Special timeout value indicating an infinite wait: */
++#define SYNC_INFINITE 0xffffffff
++
++/* Maximum string length of a named event */
++#define SYNC_MAXNAMELENGTH 32
++
++/* Generic SYNC object: */
++ struct SYNC_OBJECT;
++
++/* Generic SYNC CS object: */
++struct SYNC_CSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ struct semaphore sem;
++} ;
++
++/* SYNC object attributes: */
++ struct SYNC_ATTRS {
++ HANDLE hUserEvent; /* Platform's User Mode synch. object. */
++ HANDLE hKernelEvent; /* Platform's Kernel Mode sync. object. */
++ u32 dwReserved1; /* For future expansion. */
++ u32 dwReserved2; /* For future expansion. */
++ } ;
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close this event handle, freeing resources allocated in SYNC_OpenEvent
++ * if necessary.
++ * Parameters:
++ * hEvent: Handle to a synchronization event, created/opened in
++ * SYNC_OpenEvent.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to close event handle.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Any subsequent usage of hEvent would be invalid.
++ */
++ extern DSP_STATUS SYNC_CloseEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_DeleteCS ========
++ * Purpose:
++ * Delete a critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_DeleteCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_EnterCS ========
++ * Purpose:
++ * Enter the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_EnterCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SYNC_Exit(void);
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initializes private state of SYNC module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * SYNC initialized.
++ */
++ extern bool SYNC_Init(void);
++
++/*
++ * ======== SYNC_InitializeCS ========
++ * Purpose:
++ * Initialize the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj);
++
++/*
++ * ======== SYNC_InitializeDPCCS ========
++ * Purpose:
++ * Initialize the critical section between process context and DPC.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT
++ **phCSObj);
++
++/*
++ * ======== SYNC_LeaveCS ========
++ * Purpose:
++ * Leave the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_LeaveCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Create/open and initialize an event object for thread synchronization,
++ * which is initially in the non-signalled state.
++ * Parameters:
++ * phEvent: Pointer to location to receive the event object handle.
++ * pAttrs: Pointer to SYNC_ATTRS object containing initial SYNC
++ * SYNC_OBJECT attributes. If this pointer is NULL, then
++ * SYNC_OpenEvent will create and manage an OS specific
++ * syncronization object.
++ * pAttrs->hUserEvent: Platform's User Mode synchronization object.
++ *
++ * The behaviour of the SYNC methods depend on the value of
++ * the hUserEvent attr:
++ *
++ * 1. (hUserEvent == NULL):
++ * A user mode event is created.
++ * 2. (hUserEvent != NULL):
++ * A user mode event is supplied by the caller of SYNC_OpenEvent().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to create user mode event.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EINVALIDARG SYNC_ATTRS values are invalid.
++ * Requires:
++ * - SYNC initialized.
++ * - phEvent != NULL.
++ * Ensures:
++ * If function succeeded, pEvent->hEvent must be a valid event handle.
++ */
++ extern DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS
++ *pAttrs);
++
++/*
++ * ========= SYNC_PostMessage ========
++ * Purpose:
++ * To post a windows message
++ * Parameters:
++ * hWindow: Handle to the window
++ * uMsg: Message to be posted
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Post message failed
++ * DSP_EHANDLE: Invalid Window handle
++ * Requires:
++ * SYNC initialized
++ * Ensures
++ */
++ extern DSP_STATUS SYNC_PostMessage(IN HANDLE hWindow, IN u32 uMsg);
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset a syncronization event object state to non-signalled.
++ * Parameters:
++ * hEvent: Handle to a sync event.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to reset event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_ResetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Signal the event. Will unblock one waiting thread.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to signal event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_SetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * the object's state is nonsignaled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * DSP_EHANDLE: Invalid handle.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired while waiting for event to be signalled.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnEvent(IN struct SYNC_OBJECT *hEvent,
++ IN u32 dwTimeOut);
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ * Note: dwTimeOut must be SYNC_INFINITE to signal infinite wait.
++ * Parameters:
++ * hSyncEvents: Array of handles to event objects.
++ * uCount: Number of event handles.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * no event is signalled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * puIndex: Location to store index of event that was signalled.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired before event was signalled.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnMultipleEvents(IN struct SYNC_OBJECT
++ **hSyncEvents,
++ IN u32 uCount,
++ IN u32 dwTimeout,
++ OUT u32 *puIndex);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/util.h b/arch/arm/plat-omap/include/dspbridge/util.h
+new file mode 100644
+index 0000000..e6815ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/util.h
+@@ -0,0 +1,122 @@
++/*
++ * util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== util.h ========
++ * Purpose:
++ * Provide general purpose utility functions.
++ *
++ * Public Functions:
++ * UTIL_CDTestDll
++ * UTIL_CmdLineToArgs
++ * UTIL_Exit
++ * UTIL_GetSysInfo
++ * UTIL_Init
++ */
++
++#ifndef _UTIL_H
++#define _UTIL_H
++
++#include <linux/delay.h>
++#include <linux/sched.h>
++
++#include <dspbridge/utildefs.h>
++
++/*
++ * ======== UTIL_CDTestDll ========
++ * Purpose:
++ * Provides test entry point in class driver context.
++ * Parameters:
++ * cArgc: test module command line input count.
++ * ppArgv: test module command line args.
++ * Returns:
++ * 0 if successful, a negative value otherwise.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern u32 UTIL_CDTestDll(IN s32 cArgc, IN char **ppArgv);
++
++/*
++ * ======== UTIL_CmdLineToArgs ========
++ * Purpose:
++ * This function re-creates C-style cmd line argc & argv from WinMain()
++ * cmd line args.
++ * Parameters:
++ * s8 *pszProgName - The name of the program currently being executed.
++ * s8 *argv[] - The argument vector.
++ * s8 *pCmdLine - The pointer to the command line.
++ * bool fHasProgName - Indicats whether a program name is supplied.
++ * Returns:
++ * Returns the number of arguments found.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern s32 UTIL_CmdLineToArgs(IN char *pszProgName,
++ IN char *argv[UTIL_MAXARGVS],
++ IN char *pCmdLine, IN bool fHasProgName);
++
++/*
++ * ======== UTIL_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern inline void UTIL_Exit(void)
++ {
++ }
++/*
++ * ======== UTIL_GetSysInfo ========
++ * Purpose:
++ * This function return platform specific system information.
++ *
++ * Parameters:
++ * pSysInfo - address to store the system information.
++ * Returns:
++ * DSP_SOK
++ * S_FAIL
++ * Requires:
++ * UTIL initialized.
++ * pSysInfo != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS UTIL_GetSysInfo(OUT struct UTIL_SYSINFO *pSysInfo);
++
++/*
++ * ======== UTIL_Init ========
++ * Purpose:
++ * Initializes private state of UTIL module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * UTIL initialized.
++ */
++ extern inline bool UTIL_Init(void)
++ {
++ return true;
++ }
++
++#endif /* _UTIL_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/utildefs.h b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+new file mode 100644
+index 0000000..bd53a5a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+@@ -0,0 +1,51 @@
++/*
++ * utildefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== utildefs.h ========
++ * Purpose:
++ * Global UTIL constants and types, shared between WCD and DSPSYS.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* entries from UTIL_HOSTCONFIG.
++ *! 12-Aug-2000 ag Added UTIL_SYSINFO typedef.
++ *! 08-Oct-1999 rr Adopted for WinCE where test fxns will be added in util.h
++ *! 26-Dec-1996 cr Created.
++ */
++
++#ifndef UTILDEFS_
++#define UTILDEFS_
++
++/* constants taken from configmg.h */
++#define UTIL_MAXMEMREGS 9
++#define UTIL_MAXIOPORTS 20
++#define UTIL_MAXIRQS 7
++#define UTIL_MAXDMACHNLS 7
++
++/* misc. constants */
++#define UTIL_MAXARGVS 10
++
++/* Platform specific important info */
++ struct UTIL_SYSINFO {
++ /* Granularity of page protection; usually 1k or 4k */
++ u32 dwPageSize;
++ u32 dwAllocationGranularity; /* VM granularity, usually 64K */
++ u32 dwNumberOfProcessors; /* Used as sanity check */
++ } ;
++
++#endif /* UTILDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/uuidutil.h b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+new file mode 100644
+index 0000000..af4aaec
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+@@ -0,0 +1,74 @@
++/*
++ * uuidutil.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.h ========
++ * Description:
++ * This file contains the specification of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 09-Nov-2000 kc: Modified description of UUID utility functions.
++ *! 29-Sep-2000 kc: Appended "UUID_" prefix to UUID helper functions.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++#ifndef UUIDUTIL_
++#define UUIDUTIL_
++
++#define MAXUUIDLEN 37
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a DSP_UUID to an ANSI string.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID object.
++ * pszUuid: Pointer to a buffer to receive a NULL-terminated UUID
++ * string.
++ * size: Maximum size of the pszUuid string.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Lenghth of pszUuid is less than MAXUUIDLEN.
++ * Details:
++ * UUID string limit currently set at MAXUUIDLEN.
++ */
++ void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ s32 size);
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts an ANSI string to a DSP_UUID.
++ * Parameters:
++ * pszUuid: Pointer to a string that represents a DSP_UUID object.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Details:
++ * We assume the string representation of a UUID has the following format:
++ * "12345678_1234_1234_1234_123456789abc".
++ */
++ extern void UUID_UuidFromString(IN char *pszUuid,
++ OUT struct DSP_UUID *pUuid);
++
++#endif /* UUIDUTIL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcd.h b/arch/arm/plat-omap/include/dspbridge/wcd.h
+new file mode 100644
+index 0000000..5a7d47a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcd.h
+@@ -0,0 +1,61 @@
++/*
++ * wcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcd.h ========
++ * Description:
++ * 'Bridge class driver library functions, object definitions, and
++ * return error/status codes. To be included by 'Bridge mini drivers.
++ *
++ * Public Functions:
++ * See mem.h and dbg.h.
++ *
++ * Notes:
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD. WMD's must not call module Init/Exit
++ * functions.
++ *
++ * To ensure WMD binary compatibility across different platforms,
++ * for the same processor, a WMD must restrict its usage of system
++ * services to those exported by the 'Bridge class library.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jun-2000 jeh Added dev.h
++ *! 01-Nov-1999 ag: #WINCE# WCD_MAJOR_VERSION=8 & WCD_MINOR_VERSION=0 to match
++ *! dll stamps.
++ *! 0.80 - 0.89 Alpha, 0.90 - 0.99 Beta, 1.00 - 1.10 FCS.
++ *! 17-Sep-1997 gp: Changed size of CFG_HOSTRES structure; and ISR_Install API;
++ *! Changed WCD_MINOR_VERSION 3 -> 4.
++ *! 15-Sep-1997 gp: Moved WCD_(Un)registerMinidriver to drv.
++ *! 25-Jul-1997 cr: Added WCD_UnregisterMinidriver.
++ *! 22-Jul-1997 cr: Added WCD_RegisterMinidriver, WCD_MINOR_VERSION 2 -> 3.
++ *! 12-Nov-1996 gp: Defined port io macros.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 16-Jul-1996 gp: Added CHNL fxns; updated WCD lib version to 2.
++ *! 10-May-1996 gp: Separated WMD def.s' into wmd.h.
++ *! 03-May-1996 gp: Created.
++ */
++
++#ifndef WCD_
++#define WCD_
++
++/* This WCD Library Version: */
++#define WCD_MAJOR_VERSION (u32)8 /* .8x - Alpha, .9x - Beta, 1.x FCS */
++#define WCD_MINOR_VERSION (u32)0
++
++#endif /* WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcdioctl.h b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+new file mode 100644
+index 0000000..04b13ab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+@@ -0,0 +1,519 @@
++/*
++ * wcdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcdioctl.h ========
++ * Purpose:
++ * Contains structures and commands that are used for interaction
++ * between the DDSP API and class driver.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping structs & offsets
++ *! 15-Oct-2002 kc Updated definitions for private PERF module.
++ *! 16-Aug-2002 map Added ARGS_MGR_REGISTEROBJECT & ARGS_MGR_UNREGISTEROBJECT
++ *! Added CMD_MGR_REGISTEROBJECT_OFFSET &
++ *! CMD_MGR_UNREGISTEROBJECT_OFFSET
++ *! 15-Jan-2002 ag Added actaul bufSize to ARGS_STRM_[RECLAIM][ISSUE].
++ *! 15-Nov-2001 ag change to STRMINFO in ARGS_STRM_GETINFO.
++ *! 11-Sep-2001 ag ARGS_CMM_GETHANDLE defn uses DSP_HPROCESSOR.
++ *! 23-Apr-2001 jeh Added pStatus to NODE_TERMINATE args.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added CMD_MGR_GETPERF_DATA_OFFSET for acquiring PERF stats.
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GETMESSAGE, NODE_PUTMESSAGE args.
++ *! Removed NODE_GETMESSAGESTRM args.
++ *! 11-Oct-2000 ag: Added SM mgr(CMM) args.
++ *! 27-Sep-2000 jeh Removed struct DSP_BUFFERATTR param from
++ *! ARGS_STRM_ALLOCATEBUFFER.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 07-Sep-2000 jeh Changed HANDLE to DSP_HNOTIFICATION in RegisterNotify args.
++ *! Added DSP_STRMATTR to DSPNode_Connect args.
++ *! 04-Aug-2000 rr: MEM and UTIL added to RM.
++ *! 27-Jul-2000 rr: NODE, MGR,STRM and PROC added
++ *! 27-Jun-2000 rr: Modifed to Use either PM or DSP/BIOS Bridge
++ *! IFDEF to build for PM or DSP/BIOS Bridge
++ *! 28-Jan-2000 rr: NT_CMD_FROM_OFFSET moved out to dsptrap.h
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-2000 sg: In ARGS_CHNL_GETMODE changed mode to be u32 to be
++ *! consistent with chnldefs.h.
++ *! 11-Jan-2000 rr: CMD_CFG_GETCDVERSION_OFFSET added.
++ *! 12-Nov-1999 rr: CMD_BRD_MONITOR_OFFSET added
++ *! 09-Nov-1999 kc: Added MEMRY and enabled CMD_BRD_IOCTL_OFFSET.
++ *! 05-Nov-1999 ag: Added CHNL.
++ *! 02-Nov-1999 kc: Removed field from ARGS_UTIL_TESTDLL.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 08-Oct-1999 rr: Util control offsets added.
++ *! 13-Sep-1999 kc: Added ARGS_UTIL_TESTDLL for PM test infrastructure.
++ *! 19-Aug-1999 rr: Created from WSX. Minimal Implementaion of BRD_Start and BRD
++ *! and BRD_Stop. IOCTL Offsets and CTRL Code.
++ */
++
++#ifndef WCDIOCTL_
++#define WCDIOCTL_
++
++#include <dspbridge/mem.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/dbdcd.h>
++
++union Trapped_Args {
++
++ /* MGR Module */
++ struct {
++ u32 uNode;
++ struct DSP_NDBPROPS __user *pNDBProps;
++ u32 uNDBPropsSize;
++ u32 __user *puNumNodes;
++ } ARGS_MGR_ENUMNODE_INFO;
++
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORINFO __user *pProcessorInfo;
++ u32 uProcessorInfoSize;
++ u32 __user *puNumProcs;
++ } ARGS_MGR_ENUMPROC_INFO;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ char *pszPathName;
++ } ARGS_MGR_REGISTEROBJECT;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ } ARGS_MGR_UNREGISTEROBJECT;
++
++ struct {
++ struct DSP_NOTIFICATION __user*__user *aNotifications;
++ u32 uCount;
++ u32 __user *puIndex;
++ u32 uTimeout;
++ } ARGS_MGR_WAIT;
++
++ /* PROC Module */
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORATTRIN __user *pAttrIn;
++ DSP_HPROCESSOR __user *phProcessor;
++ } ARGS_PROC_ATTACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 dwCmd;
++ struct DSP_CBDATA __user *pArgs;
++ } ARGS_PROC_CTRL;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_DETACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ DSP_HNODE __user *aNodeTab;
++ u32 uNodeTabSize;
++ u32 __user *puNumNodes;
++ u32 __user *puAllocated;
++ } ARGS_PROC_ENUMNODE_INFO;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uResourceType;
++ struct DSP_RESOURCEINFO *pResourceInfo;
++ u32 uResourceInfoSize;
++ } ARGS_PROC_ENUMRESOURCES;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_PROCESSORSTATE __user *pProcStatus;
++ u32 uStateInfoSize;
++ } ARGS_PROC_GETSTATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u8 __user *pBuf;
++
++ #ifndef RES_CLEANUP_DISABLE
++ u8 __user *pSize;
++ #endif
++ u32 uMaxSize;
++ } ARGS_PROC_GETTRACE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ s32 iArgc;
++ char __user*__user *aArgv;
++ char *__user *aEnvp;
++ } ARGS_PROC_LOAD;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_PROC_REGISTER_NOTIFY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_START;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *__user *ppRsvAddr;
++ } ARGS_PROC_RSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pRsvAddr;
++ } ARGS_PROC_UNRSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ void *pReqAddr;
++ void *__user *ppMapAddr;
++ u32 ulMapAttr;
++ } ARGS_PROC_MAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pMapAddr;
++ } ARGS_PROC_UNMAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ u32 ulFlags;
++ } ARGS_PROC_FLUSHMEMORY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_STOP;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ } ARGS_PROC_INVALIDATEMEMORY;
++
++
++ /* NODE Module */
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_CBDATA __user *pArgs;
++ struct DSP_NODEATTRIN __user *pAttrIn;
++ DSP_HNODE __user *phNode;
++ } ARGS_NODE_ALLOCATE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uSize;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *__user *pBuffer;
++ } ARGS_NODE_ALLOCMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ s32 iPriority;
++ } ARGS_NODE_CHANGEPRIORITY;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uStream;
++ DSP_HNODE hOtherNode;
++ u32 uOtherStream;
++ struct DSP_STRMATTR __user *pAttrs;
++ struct DSP_CBDATA __user *pConnParam;
++ } ARGS_NODE_CONNECT;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_CREATE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_DELETE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *pBuffer;
++ } ARGS_NODE_FREEMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_NODEATTR __user *pAttr;
++ u32 uAttrSize;
++ } ARGS_NODE_GETATTR;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_GETMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_PAUSE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_PUTMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_NODE_REGISTERNOTIFY;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_RUN;
++
++ struct {
++ DSP_HNODE hNode;
++ DSP_STATUS __user *pStatus;
++ } ARGS_NODE_TERMINATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_NDBPROPS __user *pNodeProps;
++ } ARGS_NODE_GETUUIDPROPS;
++
++ /* STRM module */
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uSize;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_ALLOCATEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ } ARGS_STRM_CLOSE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_FREEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ HANDLE *phEvent;
++ } ARGS_STRM_GETEVENTHANDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ struct STRM_INFO __user *pStreamInfo;
++ u32 uStreamInfoSize;
++ } ARGS_STRM_GETINFO;
++
++ struct {
++ DSP_HSTREAM hStream;
++ bool bFlush;
++ } ARGS_STRM_IDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *pBuffer;
++ u32 dwBytes;
++ u32 dwBufSize;
++ u32 dwArg;
++ } ARGS_STRM_ISSUE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uDirection;
++ u32 uIndex;
++ struct STRM_ATTR __user *pAttrIn;
++ DSP_HSTREAM __user *phStream;
++ } ARGS_STRM_OPEN;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *pBufPtr;
++ u32 __user *pBytes;
++ u32 __user *pBufSize;
++ u32 __user *pdwArg;
++ } ARGS_STRM_RECLAIM;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_STRM_REGISTERNOTIFY;
++
++ struct {
++ DSP_HSTREAM __user *aStreamTab;
++ u32 nStreams;
++ u32 __user *pMask;
++ u32 uTimeout;
++ } ARGS_STRM_SELECT;
++
++ /* CMM Module */
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ u32 uSize;
++ struct CMM_ATTRS *pAttrs;
++ OUT void **ppBufVA;
++ } ARGS_CMM_ALLOCBUF;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ void *pBufPA;
++ u32 ulSegId;
++ } ARGS_CMM_FREEBUF;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct CMM_OBJECT *__user *phCmmMgr;
++ } ARGS_CMM_GETHANDLE;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ struct CMM_INFO __user *pCmmInfo;
++ } ARGS_CMM_GETINFO;
++
++ /* MEM Module */
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_ALLOC;
++
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_CALLOC;
++
++ struct {
++ void *pMem;
++ } ARGS_MEM_FREE;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ void *pLockedBuffer;
++ } ARGS_MEM_PAGELOCK;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ } ARGS_MEM_PAGEUNLOCK;
++
++ /* UTIL module */
++ struct {
++ s32 cArgc;
++ char **ppArgv;
++ } ARGS_UTIL_TESTDLL;
++} ;
++
++#define CMD_BASE 1
++
++/* MGR module offsets */
++#define CMD_MGR_BASE_OFFSET CMD_BASE
++#define CMD_MGR_ENUMNODE_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 0)
++#define CMD_MGR_ENUMPROC_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 1)
++#define CMD_MGR_REGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 2)
++#define CMD_MGR_UNREGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 3)
++#define CMD_MGR_WAIT_OFFSET (CMD_MGR_BASE_OFFSET + 4)
++
++#ifndef RES_CLEANUP_DISABLE
++#define CMD_MGR_RESOUCES_OFFSET (CMD_MGR_BASE_OFFSET + 5)
++#define CMD_MGR_END_OFFSET CMD_MGR_RESOUCES_OFFSET
++#else
++#define CMD_MGR_END_OFFSET CMD_MGR_WAIT_OFFSET
++#endif
++
++#define CMD_PROC_BASE_OFFSET (CMD_MGR_END_OFFSET + 1)
++#define CMD_PROC_ATTACH_OFFSET (CMD_PROC_BASE_OFFSET + 0)
++#define CMD_PROC_CTRL_OFFSET (CMD_PROC_BASE_OFFSET + 1)
++#define CMD_PROC_DETACH_OFFSET (CMD_PROC_BASE_OFFSET + 2)
++#define CMD_PROC_ENUMNODE_OFFSET (CMD_PROC_BASE_OFFSET + 3)
++#define CMD_PROC_ENUMRESOURCES_OFFSET (CMD_PROC_BASE_OFFSET + 4)
++#define CMD_PROC_GETSTATE_OFFSET (CMD_PROC_BASE_OFFSET + 5)
++#define CMD_PROC_GETTRACE_OFFSET (CMD_PROC_BASE_OFFSET + 6)
++#define CMD_PROC_LOAD_OFFSET (CMD_PROC_BASE_OFFSET + 7)
++#define CMD_PROC_REGISTERNOTIFY_OFFSET (CMD_PROC_BASE_OFFSET + 8)
++#define CMD_PROC_START_OFFSET (CMD_PROC_BASE_OFFSET + 9)
++#define CMD_PROC_RSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 10)
++#define CMD_PROC_UNRSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 11)
++#define CMD_PROC_MAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 12)
++#define CMD_PROC_UNMAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 13)
++#define CMD_PROC_FLUSHMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 14)
++#define CMD_PROC_STOP_OFFSET (CMD_PROC_BASE_OFFSET + 15)
++#define CMD_PROC_INVALIDATEMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 16)
++#define CMD_PROC_END_OFFSET CMD_PROC_INVALIDATEMEMORY_OFFSET
++
++
++#define CMD_NODE_BASE_OFFSET (CMD_PROC_END_OFFSET + 1)
++#define CMD_NODE_ALLOCATE_OFFSET (CMD_NODE_BASE_OFFSET + 0)
++#define CMD_NODE_ALLOCMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 1)
++#define CMD_NODE_CHANGEPRIORITY_OFFSET (CMD_NODE_BASE_OFFSET + 2)
++#define CMD_NODE_CONNECT_OFFSET (CMD_NODE_BASE_OFFSET + 3)
++#define CMD_NODE_CREATE_OFFSET (CMD_NODE_BASE_OFFSET + 4)
++#define CMD_NODE_DELETE_OFFSET (CMD_NODE_BASE_OFFSET + 5)
++#define CMD_NODE_FREEMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 6)
++#define CMD_NODE_GETATTR_OFFSET (CMD_NODE_BASE_OFFSET + 7)
++#define CMD_NODE_GETMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 8)
++#define CMD_NODE_PAUSE_OFFSET (CMD_NODE_BASE_OFFSET + 9)
++#define CMD_NODE_PUTMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 10)
++#define CMD_NODE_REGISTERNOTIFY_OFFSET (CMD_NODE_BASE_OFFSET + 11)
++#define CMD_NODE_RUN_OFFSET (CMD_NODE_BASE_OFFSET + 12)
++#define CMD_NODE_TERMINATE_OFFSET (CMD_NODE_BASE_OFFSET + 13)
++#define CMD_NODE_GETUUIDPROPS_OFFSET (CMD_NODE_BASE_OFFSET + 14)
++#define CMD_NODE_END_OFFSET CMD_NODE_GETUUIDPROPS_OFFSET
++
++#define CMD_STRM_BASE_OFFSET (CMD_NODE_END_OFFSET + 1)
++#define CMD_STRM_ALLOCATEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 0)
++#define CMD_STRM_CLOSE_OFFSET (CMD_STRM_BASE_OFFSET + 1)
++#define CMD_STRM_FREEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 2)
++#define CMD_STRM_GETEVENTHANDLE_OFFSET (CMD_STRM_BASE_OFFSET + 3)
++#define CMD_STRM_GETINFO_OFFSET (CMD_STRM_BASE_OFFSET + 4)
++#define CMD_STRM_IDLE_OFFSET (CMD_STRM_BASE_OFFSET + 5)
++#define CMD_STRM_ISSUE_OFFSET (CMD_STRM_BASE_OFFSET + 6)
++#define CMD_STRM_OPEN_OFFSET (CMD_STRM_BASE_OFFSET + 7)
++#define CMD_STRM_RECLAIM_OFFSET (CMD_STRM_BASE_OFFSET + 8)
++#define CMD_STRM_REGISTERNOTIFY_OFFSET (CMD_STRM_BASE_OFFSET + 9)
++#define CMD_STRM_SELECT_OFFSET (CMD_STRM_BASE_OFFSET + 10)
++#define CMD_STRM_END_OFFSET CMD_STRM_SELECT_OFFSET
++
++/* Communication Memory Manager (UCMM) */
++#define CMD_CMM_BASE_OFFSET (CMD_STRM_END_OFFSET + 1)
++#define CMD_CMM_ALLOCBUF_OFFSET (CMD_CMM_BASE_OFFSET + 0)
++#define CMD_CMM_FREEBUF_OFFSET (CMD_CMM_BASE_OFFSET + 1)
++#define CMD_CMM_GETHANDLE_OFFSET (CMD_CMM_BASE_OFFSET + 2)
++#define CMD_CMM_GETINFO_OFFSET (CMD_CMM_BASE_OFFSET + 3)
++#define CMD_CMM_END_OFFSET CMD_CMM_GETINFO_OFFSET
++
++#define CMD_BASE_END_OFFSET CMD_CMM_END_OFFSET
++#endif /* WCDIOCTL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmd.h b/arch/arm/plat-omap/include/dspbridge/wmd.h
+new file mode 100644
+index 0000000..f584038
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmd.h
+@@ -0,0 +1,1193 @@
++/*
++ * wmd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmd.h ========
++ * Purpose:
++ * 'Bridge mini driver entry point and interface function declarations.
++ *
++ * Public Functions:
++ * WMD_DRV_Entry
++ *
++ * Notes:
++ * The 'Bridge class driver obtains it's function interface to
++ * the 'Bridge mini driver via a call to WMD_DRV_Entry().
++ *
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD.
++ *
++ * WMD function DBC Requires and Ensures are also made by the WCD on
++ * behalf of the WMD, to simplify the WMD code.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs - WMD_BRD_MemMap/UnMap
++ *! 01-Mar-2004 vp Added filename argument to WMD_DRV_Entry function.
++ *! 29-Aug-2002 map Added WMD_BRD_MemWrite()
++ *! 26-Aug-2002 map Added WMD_BRD_MemCopy()
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 05-Nov-2001 kc: Added error handling DEH functions.
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify().
++ *! 17-Nov-2000 jeh Added WMD_MSG and WMD_IO definitions.
++ *! 01-Nov-2000 jeh Added more error codes to WMD_CHNL_RegisterNotify().
++ *! 13-Oct-2000 jeh Added dwArg to WMD_CHNL_AddIOReq(), added WMD_CHNL_IDLE
++ *! and WMD_CHNL_RegisterNotify for DSPStream support.
++ *! 17-Jan-2000 rr: WMD_BRD_SETSTATE Added.
++ *! 30-Jul-1997 gp: Split wmd IOCTL space into reserved and private.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 18-Oct-1996 gp: Added WMD_E_HARDWARE return code from WMD_BRD_Monitor.
++ *! 09-Sep-1996 gp: Subtly altered the semantics of WMD_CHNL_GetInfo().
++ *! 02-Aug-1996 gp: Ensured on BRD_Start that interrupts to the PC are enabled.
++ *! 11-Jul-1996 gp: Added CHNL interface. Note stronger DBC_Require conditions.
++ *! 29-May-1996 gp: Removed WCD_ prefix from functions imported from WCD.LIB.
++ *! 29-May-1996 gp: Made OUT param first in WMD_DEV_Create().
++ *! 09-May-1996 gp: Created.
++ */
++
++#ifndef WMD_
++#define WMD_
++
++#include <dspbridge/brddefs.h>
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/chnlpriv.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * Any IOCTLS at or above this value are reserved for standard WMD
++ * interfaces.
++ */
++#define WMD_RESERVEDIOCTLBASE 0x8000
++
++/* Handle to mini-driver's private device context. */
++ struct WMD_DEV_CONTEXT;
++
++/*---------------------------------------------------------------------------*/
++/* 'Bridge MINI DRIVER FUNCTION TYPES */
++/*---------------------------------------------------------------------------*/
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * Purpose:
++ * Bring the board to the BRD_IDLE (monitor) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_HARDWARE: A test of hardware assumptions/integrity failed.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_IDLE state;
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_MONITOR) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_SETSTATE ========
++ * Purpose:
++ * Sets the Mini driver state
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulBrdState: Board state
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * ulBrdState <= BRD_LASTSTATE.
++ * Ensures:
++ * ulBrdState <= BRD_LASTSTATE.
++ * Update the Board state to the specified state.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_SETSTATE) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulBrdState);
++
++/*
++ * ======== WMD_BRD_Start ========
++ * Purpose:
++ * Bring board to the BRD_RUNNING (start) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * dwDSPAddr: DSP address at which to start execution.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Board is in monitor (BRD_IDLE) state.
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_START) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 dwDSPAddr);
++
++/*
++ * ======== WMD_BRD_MemCopy ========
++ * Purpose:
++ * Copy memory from one DSP address to another
++ * Parameters:
++ * pDevContext: Pointer to context handle
++ * ulDspDestAddr: DSP address to copy to
++ * ulDspSrcAddr: DSP address to copy from
++ * ulNumBytes: Number of bytes to copy
++ * ulMemType: What section of memory to copy to
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * pDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMCOPY) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulDspDestAddr,
++ u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++/*
++ * ======== WMD_BRD_MemWrite ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space. Unlike WMD_BRD_Write, this API does reset the DSP
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMWRITE) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * Purpose:
++ * Map a MPU memory region to a DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulMpuAddr: MPU memory region start address.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to map.
++ * mapAttrs: Mapping attributes (e.g. endianness).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulMpuAddr,
++ u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttrs);
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Purpose:
++ * UnMap an MPU memory region from DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to unmap.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMUNMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulVirtAddr,
++ u32 ulNumBytes);
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * Purpose:
++ * Bring board to the BRD_STOPPED state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_STOPPED (stop) state;
++ * Interrupts to the PC are disabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_STOP) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Purpose:
++ * Report the current state of the board.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * pdwState: Ptr to BRD status variable.
++ * Returns:
++ * DSP_SOK:
++ * Requires:
++ * pdwState != NULL;
++ * hDevContext != NULL
++ * Ensures:
++ * *pdwState is one of {BRD_STOPPED, BRD_IDLE, BRD_RUNNING, BRD_UNKNOWN};
++ */
++ typedef DSP_STATUS(*
++ WMD_BRD_STATUS) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS * pdwState);
++
++/*
++ * ======== WMD_BRD_Read ========
++ * Purpose:
++ * Read a block of DSP memory, from a given memory space, into a host
++ * buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP from which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ * Will not write more than ulNumBytes bytes into pHostBuf.
++ */
++typedef DSP_STATUS(*WMD_BRD_READ) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_BRD_WRITE)(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * pMgrAttrs->dwSMBase: Base physical address of shared memory, if any.
++ * pMgrAttrs->uSMLength: Bytes of shared memory block.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug ISR for given IRQ.
++ * CHNL_E_NOMEMMAP: Couldn't map physical address to a virtual one.
++ * Requires:
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL
++ * pMgrAttrs field are all valid:
++ * 0 < cChannels <= CHNL_MAXCHANNELS.
++ * bIRQ <= 15.
++ * uWordSize > 0.
++ * IsValidHandle(hDevObject)
++ * No channel manager exists for this board.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CREATE)(OUT struct CHNL_MGR
++ **phChnlMgr,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct
++ CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel. Closes each open channel.
++ * CHNL_Create may subsequently be called for the same device.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_DESTROY) (struct CHNL_MGR
++ *hChnlMgr);
++/*
++ * ======== WMD_DEH_Notify ========
++ * Purpose:
++ * When notified of DSP error, take appropriate action.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * ulEventMask: Indicate the type of exception
++ * dwErrInfo: Error information
++ * Returns:
++ *
++ * Requires:
++ * hDehMgr != NULL;
++ * ulEventMask with a valid exception
++ * Ensures:
++ */
++ typedef void (*WMD_DEH_NOTIFY)(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Purpose:
++ * Open a new half-duplex channel to the DSP board.
++ * Parameters:
++ * phChnl: Location to store a channel object handle.
++ * hChnlMgr: Handle to channel manager, as returned by CHNL_GetMgr().
++ * uMode: One of {CHNL_MODETODSP, CHNL_MODEFROMDSP} specifies
++ * direction of data transfer.
++ * uChnlId: If CHNL_PICKFREE is specified, the channel manager will
++ * select a free channel id (default);
++ * otherwise this field specifies the id of the channel.
++ * pAttrs: Channel attributes. Attribute fields are as follows:
++ * pAttrs->uIOReqs: Specifies the maximum number of I/O requests which can
++ * be pending at any given time. All request packets are
++ * preallocated when the channel is opened.
++ * pAttrs->hEvent: This field allows the user to supply an auto reset
++ * event object for channel I/O completion notifications.
++ * It is the responsibility of the user to destroy this
++ * object AFTER closing the channel.
++ * This channel event object can be retrieved using
++ * CHNL_GetEventHandle().
++ * pAttrs->hReserved: The kernel mode handle of this event object.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr is invalid.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EINVALIDARG: Invalid number of IOReqs.
++ * CHNL_E_OUTOFSTREAMS: No free channels available.
++ * CHNL_E_BADCHANID: Channel ID is out of range.
++ * CHNL_E_CHANBUSY: Channel is in use.
++ * CHNL_E_NOIORPS: No free IO request packets available for
++ * queuing.
++ * Requires:
++ * phChnl != NULL.
++ * pAttrs != NULL.
++ * pAttrs->hEvent is a valid event handle.
++ * pAttrs->hReserved is the kernel mode handle for pAttrs->hEvent.
++ * Ensures:
++ * DSP_SOK: *phChnl is a valid channel.
++ * else: *phChnl is set to NULL if (phChnl != NULL);
++ */
++ typedef DSP_STATUS(*WMD_CHNL_OPEN) (OUT struct CHNL_OBJECT
++ **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct
++ CHNL_ATTRS *pAttrs);
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Handle to a channel object.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: hChnl is no longer valid.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CLOSE) (struct CHNL_OBJECT *hChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Purpose:
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * pHostBuf: Host buffer address source.
++ * cBytes: Number of PC bytes to transfer. A zero value indicates
++ * that this buffer is the last in the output channel.
++ * A zero value is invalid for an input channel.
++ *! cBufSize: Actual buffer size in host bytes.
++ * dwDspAddr: DSP address for transfer. (Currently ignored).
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pHostBuf is invalid.
++ * CHNL_E_NOEOS: User cannot mark EOS on an input channel.
++ * CHNL_E_CANCELLED: I/O has been cancelled on this channel. No further
++ * I/O is allowed.
++ * CHNL_E_EOS: End of stream was already marked on a previous
++ * IORequest on this channel. No further I/O is expected.
++ * CHNL_E_BUFSIZE: Buffer submitted to this output channel is larger than
++ * the size of the physical shared memory output window.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: The buffer will be transferred if the channel is ready;
++ * otherwise, will be queued for transfer when the channel becomes
++ * ready. In any case, notifications of I/O completion are
++ * asynchronous.
++ * If cBytes is 0 for an output channel, subsequent CHNL_AddIOReq's
++ * on this channel will fail with error code CHNL_E_EOS. The
++ * corresponding IOC for this I/O request will have its status flag
++ * set to CHNL_IOCSTATEOS.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_ADDIOREQ) (struct CHNL_OBJECT
++ *hChnl,
++ void *pHostBuf,
++ u32 cBytes,
++ u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Purpose:
++ * Dequeue an I/O completion record, which contains information about the
++ * completed I/O request.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: A value of CHNL_IOCNOWAIT will simply dequeue the
++ * first available IOC.
++ * pIOC: On output, contains host buffer address, bytes
++ * transferred, and status of I/O completion.
++ * pIOC->status: See chnldefs.h.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pIOC is invalid.
++ * CHNL_E_NOIOC: CHNL_IOCNOWAIT was specified as the dwTimeOut parameter
++ * yet no I/O completions were queued.
++ * Requires:
++ * dwTimeOut == CHNL_IOCNOWAIT.
++ * Ensures:
++ * DSP_SOK: if there are any remaining IOC's queued before this call
++ * returns, the channel event object will be left in a signalled
++ * state.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETIOC) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Purpose:
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * Subsequent I/O requests to this channel will not be accepted.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CANCELIO) (struct CHNL_OBJECT
++ *hChnl);
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * Purpose:
++ * For an output stream (to the DSP), indicates if any IO requests are in
++ * the output request queue. For input streams (from the DSP), will
++ * cancel all pending IO requests.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: Timeout value for flush operation.
++ * Returns:
++ * DSP_SOK: Success;
++ * S_CHNLIOREQUEST: Returned if any IORequests are in the output queue.
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: No I/O requests will be pending on this channel.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_FLUSHIO) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ * Parameters:
++ * hChnl: Handle to a valid channel object, or NULL.
++ * pInfo: Location to store channel info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pInfo == NULL.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pInfo points to a filled in CHNL_INFO struct,
++ * if (pInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETINFO) (struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO
++ *pChnlInfo);
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Purpose:
++ * Retrieve information related to the channel manager.
++ * Parameters:
++ * hChnlMgr: Handle to a valid channel manager, or NULL.
++ * uChnlID: Channel ID.
++ * pMgrInfo: Location to store channel manager info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnlMgr.
++ * DSP_EPOINTER: pMgrInfo == NULL.
++ * CHNL_E_BADCHANID: Invalid channel ID.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pMgrInfo points to a filled in CHNL_MGRINFO
++ * struct, if (pMgrInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETMGRINFO) (struct CHNL_MGR
++ *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Purpose:
++ * Idle a channel. If this is an input channel, or if this is an output
++ * channel and fFlush is TRUE, all currently enqueued buffers will be
++ * dequeued (data discarded for output channel).
++ * If this is an output channel and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ *
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: If output channel and fFlush is FALSE, timeout value
++ * to wait for buffers to be output. (Not used for
++ * input channel).
++ * fFlush: If output channel and fFlush is TRUE, discard any
++ * currently buffered data. If FALSE, wait for currently
++ * buffered data to be output, or timeout, whichever
++ * occurs first. fFlush is ignored for input channel.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * CHNL_E_WAITTIMEOUT: Timeout occured before channel could be idled.
++ * Requires:
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_IDLE) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ bool fFlush);
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Purpose:
++ * Register for notification of events on a channel.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * uEventMask: Type of events to be notified about: IO completion
++ * (DSP_STREAMIOCOMPLETION) or end of stream
++ * (DSP_STREAMDONE).
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of a DSP_NOTIFICATION object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * Valid hChnl.
++ * hNotification != NULL.
++ * (uEventMask & ~(DSP_STREAMIOCOMPLETION | DSP_STREAMDONE)) == 0.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_REGISTERNOTIFY)
++ (struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Purpose:
++ * Complete creation of the device object for this board.
++ * Parameters:
++ * phDevContext: Ptr to location to store a WMD device context.
++ * hDevObject: Handle to a Device Object, created and managed by WCD.
++ * pConfig: Ptr to configuration parameters provided by the Windows
++ * Configuration Manager during device loading.
++ * pDspConfig: DSP resources, as specified in the registry key for this
++ * device.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for device context.
++ * WMD_E_BADCONFIG: One or more of the host or DSP configuration
++ * parameters did not satisfy hardware assumptions
++ * made by this WMD.
++ * Requires:
++ * phDevContext != NULL;
++ * hDevObject != NULL;
++ * pConfig != NULL;
++ * pDspConfig != NULL;
++ * Fields in pConfig and pDspConfig contain valid values.
++ * Ensures:
++ * DSP_SOK: All mini-driver specific DSP resource and other
++ * board context has been allocated.
++ * DSP_EMEMORY: WMD failed to allocate resources.
++ * Any acquired resources have been freed. The WCD will
++ * not call WMD_DEV_Destroy() if WMD_DEV_Create() fails.
++ * Details:
++ * Called during the CONFIGMG's Device_Init phase. Based on host and
++ * DSP configuration information, create a board context, a handle to
++ * which is passed into other WMD BRD and CHNL functions. The
++ * board context contains state information for the device. Since the
++ * addresses of all IN pointer parameters may be invalid when this
++ * function returns, they must not be stored into the device context
++ * structure.
++ */
++ typedef DSP_STATUS(*WMD_DEV_CREATE) (OUT struct WMD_DEV_CONTEXT
++ **phDevContext,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct CFG_HOSTRES
++ *pConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig);
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Purpose:
++ * Mini-driver specific interface.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwCmd: WMD defined command code.
++ * pArgs: Pointer to an arbitrary argument structure.
++ * Returns:
++ * DSP_SOK or DSP_EFAIL. Actual command error codes should be passed back
++ * in the pArgs structure, and are defined by the WMD implementor.
++ * Requires:
++ * All calls are currently assumed to be synchronous. There are no
++ * IOCTL completion routines provided.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_DEV_CTRL)(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwCmd,
++ IN OUT void *pArgs);
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Purpose:
++ * Deallocate WMD device extension structures and all other resources
++ * acquired by the mini-driver.
++ * No calls to other mini driver functions may subsequently
++ * occur, except for WMD_DEV_Create().
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device information.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to release a resource previously acquired.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ * DSP_SOK: Device context is freed.
++ */
++ typedef DSP_STATUS(*WMD_DEV_DESTROY) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_DEH_Create ========
++ * Purpose:
++ * Create an object that manages DSP exceptions from the GPP.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * hDevObject: Handle to DEV object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * phDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_CREATE) (OUT struct DEH_MGR
++ **phDehMgr,
++ struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Purpose:
++ * Destroy the DEH object.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_DESTROY) (struct DEH_MGR *hDehMgr);
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Purpose:
++ * Register for DEH event notification.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_REGISTERNOTIFY)
++ (struct DEH_MGR *hDehMgr,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Purpose:
++ * Get DSP exception info.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * pErrInfo: Ptr to error info structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * phDehMgr != NULL;
++ * pErrorInfo != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_GETINFO) (struct DEH_MGR *phDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++/*
++ * ======== WMD_IO_Create ========
++ * Purpose:
++ * Create an object that manages I/O between CHNL and MSG.
++ * Parameters:
++ * phIOMgr: Location to store IO manager on output.
++ * hChnlMgr: Handle to channel manager.
++ * hMsgMgr: Handle to message manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * Channel manager already created;
++ * Message manager already created;
++ * pMgrAttrs != NULL;
++ * phIOMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_CREATE) (OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Destroy object created in WMD_IO_Create.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_DESTROY) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called whenever a program is loaded to update internal data. For
++ * example, if shared memory is used, this function would update the
++ * shared memory location and address.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_ONLOADED) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_GETPROCLOAD ========
++ * Purpose:
++ * Called to get the Processor's current and predicted load
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * pProcLoadStat Processor Load statistics
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_GETPROCLOAD)(struct IO_MGR *hIOMgr,
++ struct DSP_PROCLOADSTAT *pProcLoadStat);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager on output.
++ * hDevObject: Handle to a device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgMgr != NULL.
++ * msgCallback != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATE)
++ (OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Purpose:
++ * Create a MSG queue for sending or receiving messages from a Message
++ * node on the DSP.
++ * Parameters:
++ * hMsgMgr: MSG queue manager handle returned from
++ * WMD_MSG_Create.
++ * phMsgQueue: Location to store MSG queue on output.
++ * dwId: Identifier for messages (node environment pointer).
++ * uMaxMsgs: Max number of simultaneous messages for the node.
++ * h: Handle passed to hMsgMgr->msgCallback().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgQueue != NULL.
++ * h != NULL.
++ * uMaxMsgs > 0.
++ * Ensures:
++ * phMsgQueue !=NULL <==> DSP_SOK.
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATEQUEUE)
++ (struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE h);
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from WMD_MSG_Create().
++ * Returns:
++ * Requires:
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETE) (struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Purpose:
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETEQUEUE) (struct MSG_QUEUE *hMsgQueue);
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Purpose:
++ * Get a message from a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Location to copy message into.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_GET) (struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Purpose:
++ * Put a message onto a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Pointer to message.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_PUT) (struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ * Purpose:
++ * Register notification for when a message is ready.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * uEventMask: Type of events to be notified about: Must be
++ * DSP_NODEMESSAGEREADY, or 0 to unregister.
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of notification object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Valid hMsgQueue.
++ * hNotification != NULL.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_REGISTERNOTIFY)
++ (struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ * Purpose:
++ * Set message queue id to node environment. Allows WMD_MSG_CreateQueue
++ * to be called in NODE_Allocate, before the node environment is known.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * dwId: Node environment pointer.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * dwId != 0.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_SETQUEUEID) (struct MSG_QUEUE *hMsgQueue,
++ u32 dwId);
++
++/*
++ * 'Bridge Mini Driver (WMD) interface function table.
++ *
++ * The information in this table is filled in by the specific mini-driver,
++ * and copied into the 'Bridge class driver's own space. If any interface
++ * function field is set to a value of NULL, then the class driver will
++ * consider that function not implemented, and return the error code
++ * DSP_ENOTIMPL when a WMD client attempts to call that function.
++ *
++ * This function table contains WCD version numbers, which are used by the
++ * WMD loader to help ensure backwards compatility between older WMD's and a
++ * newer 'Bridge Class Driver. These must be set to WCD_MAJOR_VERSION
++ * and WCD_MINOR_VERSION, respectively.
++ *
++ * A mini-driver need not export a CHNL interface. In this case, *all* of
++ * the WMD_CHNL_* entries must be set to NULL.
++ */
++ struct WMD_DRV_INTERFACE {
++ u32 dwWCDMajorVersion; /* Set to WCD_MAJOR_VERSION. */
++ u32 dwWCDMinorVersion; /* Set to WCD_MINOR_VERSION. */
++ WMD_DEV_CREATE pfnDevCreate; /* Create device context */
++ WMD_DEV_DESTROY pfnDevDestroy; /* Destroy device context */
++ WMD_DEV_CTRL pfnDevCntrl; /* Optional vendor interface */
++ WMD_BRD_MONITOR pfnBrdMonitor; /* Load and/or start monitor */
++ WMD_BRD_START pfnBrdStart; /* Start DSP program. */
++ WMD_BRD_STOP pfnBrdStop; /* Stop/reset board. */
++ WMD_BRD_STATUS pfnBrdStatus; /* Get current board status. */
++ WMD_BRD_READ pfnBrdRead; /* Read board memory */
++ WMD_BRD_WRITE pfnBrdWrite; /* Write board memory. */
++ WMD_BRD_SETSTATE pfnBrdSetState; /* Sets the Board State */
++ WMD_BRD_MEMCOPY pfnBrdMemCopy; /* Copies DSP Memory */
++ WMD_BRD_MEMWRITE pfnBrdMemWrite; /* Write DSP Memory w/o halt */
++ WMD_BRD_MEMMAP pfnBrdMemMap; /* Maps MPU mem to DSP mem */
++ WMD_BRD_MEMUNMAP pfnBrdMemUnMap; /* Unmaps MPU mem to DSP mem */
++ WMD_CHNL_CREATE pfnChnlCreate; /* Create channel manager. */
++ WMD_CHNL_DESTROY pfnChnlDestroy; /* Destroy channel manager. */
++ WMD_CHNL_OPEN pfnChnlOpen; /* Create a new channel. */
++ WMD_CHNL_CLOSE pfnChnlClose; /* Close a channel. */
++ WMD_CHNL_ADDIOREQ pfnChnlAddIOReq; /* Req I/O on a channel. */
++ WMD_CHNL_GETIOC pfnChnlGetIOC; /* Wait for I/O completion. */
++ WMD_CHNL_CANCELIO pfnChnlCancelIO; /* Cancl I/O on a channel. */
++ WMD_CHNL_FLUSHIO pfnChnlFlushIO; /* Flush I/O. */
++ WMD_CHNL_GETINFO pfnChnlGetInfo; /* Get channel specific info */
++ /* Get channel manager info. */
++ WMD_CHNL_GETMGRINFO pfnChnlGetMgrInfo;
++ WMD_CHNL_IDLE pfnChnlIdle; /* Idle the channel */
++ /* Register for notif. */
++ WMD_CHNL_REGISTERNOTIFY pfnChnlRegisterNotify;
++ WMD_DEH_CREATE pfnDehCreate; /* Create DEH manager */
++ WMD_DEH_DESTROY pfnDehDestroy; /* Destroy DEH manager */
++ WMD_DEH_NOTIFY pfnDehNotify; /* Notify of DSP error */
++ /* register for deh notif. */
++ WMD_DEH_REGISTERNOTIFY pfnDehRegisterNotify;
++ WMD_DEH_GETINFO pfnDehGetInfo; /* register for deh notif. */
++ WMD_IO_CREATE pfnIOCreate; /* Create IO manager */
++ WMD_IO_DESTROY pfnIODestroy; /* Destroy IO manager */
++ WMD_IO_ONLOADED pfnIOOnLoaded; /* Notify of program loaded */
++ /* Get Processor's current and predicted load */
++ WMD_IO_GETPROCLOAD pfnIOGetProcLoad;
++ WMD_MSG_CREATE pfnMsgCreate; /* Create message manager */
++ /* Create message queue */
++ WMD_MSG_CREATEQUEUE pfnMsgCreateQueue;
++ WMD_MSG_DELETE pfnMsgDelete; /* Delete message manager */
++ /* Delete message queue */
++ WMD_MSG_DELETEQUEUE pfnMsgDeleteQueue;
++ WMD_MSG_GET pfnMsgGet; /* Get a message */
++ WMD_MSG_PUT pfnMsgPut; /* Send a message */
++ /* Register for notif. */
++ WMD_MSG_REGISTERNOTIFY pfnMsgRegisterNotify;
++ /* Set message queue id */
++ WMD_MSG_SETQUEUEID pfnMsgSetQueueId;
++ } ;
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * Purpose:
++ * Registers WMD functions with the class driver. Called only once
++ * by the WCD. The caller will first check WCD version compatibility, and
++ * then copy the interface functions into its own memory space.
++ * Parameters:
++ * ppDrvInterface Pointer to a location to receive a pointer to the
++ * mini driver interface.
++ * Returns:
++ * Requires:
++ * The code segment this function resides in must expect to be discarded
++ * after completion.
++ * Ensures:
++ * ppDrvInterface pointer initialized to WMD's function interface.
++ * No system resources are acquired by this function.
++ * Details:
++ * Win95: Called during the Device_Init phase.
++ */
++ void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName);
++
++#endif /* WMD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdchnl.h b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+new file mode 100644
+index 0000000..2c1f072
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+@@ -0,0 +1,90 @@
++/*
++ * wmdchnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdchnl.h ========
++ * Description:
++ * Declares the upper edge channel class library functions required by
++ * all WMD / WCD driver interface tables. These functions are implemented
++ * by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * The function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream
++ *! support.
++ *! 11-Jul-1996 gp: Created.
++ */
++
++#ifndef WMDCHNL_
++#define WMDCHNL_
++
++ extern DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS
++ *pMgrAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++ extern DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct CHNL_ATTRS
++ *pAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl,
++ void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++ extern DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++ extern DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++ extern DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo);
++
++ extern DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++ extern DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut, bool fFlush);
++
++ extern DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++#endif /* WMDCHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmddeh.h b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+new file mode 100644
+index 0000000..dd50a3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+@@ -0,0 +1,64 @@
++/*
++ * wmddeh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmddeh.h ========
++ * Description:
++ * Defines upper edge DEH functions required by all WMD/WCD driver
++ * interface tables.
++ *
++ * Public Functions:
++ * WMD_DEH_Create
++ * IVA_DEH_Create
++ * WMD_DEH_Destroy
++ * WMD_DEH_GetInfo
++ * WMD_DEH_RegisterNotify
++ * WMD_DEH_Notify
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: added IVA_DEH_Create.
++ *! 13-Sep-2001 kc: created.
++ */
++
++#ifndef WMDDEH_
++#define WMDDEH_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/dehdefs.h>
++
++ extern DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject);
++
++ extern DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr);
++
++ extern DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++ extern DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_DEH_Notify(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++#endif /* WMDDEH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdio.h b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+new file mode 100644
+index 0000000..8525474
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+@@ -0,0 +1,53 @@
++/*
++ * wmdio.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdio.h ========
++ * Description:
++ * Declares the upper edge IO functions required by
++ * all WMD / WCD driver interface tables.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 27-Feb-2004 vp Added IVA releated function.
++ *! 06-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDIO_
++#define WMDIO_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++
++ extern DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++ extern DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS IVA_IO_OnLoaded(struct IO_MGR *hIOMgr);
++ extern DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat);
++
++#endif /* WMDIO_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdioctl.h b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+new file mode 100644
+index 0000000..a41c61a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+@@ -0,0 +1,91 @@
++/*
++ * wmdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdioctl.h ========
++ * Description:
++ * BRIDGE Minidriver BRD_IOCtl reserved command definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Updated HW typedefs
++ *! 16-Feb-2004 vp Added MMU endianness attributes to WMDIOCTL_EXTPROC
++ *! 21-Mar-2003 sb Changed WMDIOCTL_NUMOFMMUTLB from 7 to 32
++ *! 14-May-2001 sg Added codes for PWR.
++ *! 10-Aug-2001 ag Added _SETMMUCONFIG ioctl used for DSP-MMU init.
++ *! 16-Nov-1999 rajesh ?
++ *! 18-Jun-1998 ag Moved EMIF, SDRAM_C, & CE space init to ENBLEXTMEM ioctl.
++ *! Added ENBLEXTMEM, RESETDSP, UNRESETDSP & ASSERTSIG ioctls.
++ *! 07-Jun-1998 ag Added JTAG_SELECT, MAP_TBC, GET_CONFIGURATION ioctls.
++ *! 26-Jan-1998 jeh: Added START, RECV, and SEND ioctls.
++ *! 07-Nov-1997 nn: Added command to interrupt DSP for interrupt test.
++ *! 20-Oct-1997 nn: Added commands for getting and resetting interrupt count.
++ *! 17-Oct-1997 gp: Moved to src/wmd. Standardized prefix.
++ *! 08-Oct-1997 nn: Created.
++ */
++
++#ifndef WMDIOCTL_
++#define WMDIOCTL_
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* Any IOCTLS at or above this value are reserved for standard WMD interfaces.*/
++#define WMDIOCTL_RESERVEDBASE 0x8000
++
++#define WMDIOCTL_CHNLREAD (WMDIOCTL_RESERVEDBASE + 0x10)
++#define WMDIOCTL_CHNLWRITE (WMDIOCTL_RESERVEDBASE + 0x20)
++#define WMDIOCTL_GETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x30)
++#define WMDIOCTL_RESETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x40)
++#define WMDIOCTL_INTERRUPTDSP (WMDIOCTL_RESERVEDBASE + 0x50)
++#define WMDIOCTL_SETMMUCONFIG (WMDIOCTL_RESERVEDBASE + 0x60) /* DMMU */
++#define WMDIOCTL_PWRCONTROL (WMDIOCTL_RESERVEDBASE + 0x70) /* PWR */
++
++/* attention, modifiers:
++ * Some of these control enumerations are made visible to user for power
++ * control, so any changes to this list, should also be updated in the user
++ * header file 'dbdefs.h' ***/
++/* These ioctls are reserved for PWR power commands for the DSP */
++#define WMDIOCTL_DEEPSLEEP (WMDIOCTL_PWRCONTROL + 0x0)
++#define WMDIOCTL_EMERGENCYSLEEP (WMDIOCTL_PWRCONTROL + 0x1)
++#define WMDIOCTL_WAKEUP (WMDIOCTL_PWRCONTROL + 0x2)
++#define WMDIOCTL_PWRENABLE (WMDIOCTL_PWRCONTROL + 0x3)
++#define WMDIOCTL_PWRDISABLE (WMDIOCTL_PWRCONTROL + 0x4)
++#define WMDIOCTL_CLK_CTRL (WMDIOCTL_PWRCONTROL + 0x7)
++#define WMDIOCTL_PWR_HIBERNATE (WMDIOCTL_PWRCONTROL + 0x8) /*DSP Initiated
++ * Hibernate*/
++#define WMDIOCTL_PRESCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0x9)
++#define WMDIOCTL_POSTSCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0xA)
++#define WMDIOCTL_CONSTRAINT_REQUEST (WMDIOCTL_PWRCONTROL + 0xB)
++
++/* Number of actual DSP-MMU TLB entrries */
++#define WMDIOCTL_NUMOFMMUTLB 32
++
++struct WMDIOCTL_EXTPROC {
++ u32 ulDspVa; /* DSP virtual address */
++ u32 ulGppPa; /* GPP physical address */
++ /* GPP virtual address. __va does not work for ioremapped addresses */
++ u32 ulGppVa;
++ u32 ulSize; /* Size of the mapped memory in bytes */
++ enum HW_Endianism_t endianism;
++ enum HW_MMUMixedSize_t mixedMode;
++ enum HW_ElementSize_t elemSize;
++};
++
++#endif /* WMDIOCTL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdmsg.h b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+new file mode 100644
+index 0000000..81198d4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+@@ -0,0 +1,70 @@
++/*
++ * wmdmsg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdmsg.h ========
++ * Description:
++ * Declares the upper edge message class library functions required by
++ * all WMD / WCD driver interface tables. These functions are
++ * implemented by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify(). Added
++ *! WMD_MSG_SetQueueId().
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDMSG_
++#define WMDMSG_
++
++#include <dspbridge/msgdefs.h>
++
++ extern DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++ extern DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs,
++ HANDLE h);
++
++ extern void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++ extern void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue);
++
++ extern DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId);
++
++#endif /* WMDMSG_ */
+diff --git a/drivers/Makefile b/drivers/Makefile
+index fec4d8e..6fcee09 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_PARPORT) += parport/
+ obj-y += base/ block/ misc/ mfd/ net/ media/
+ obj-y += i2c/
+ obj-y += cbus/
++obj-$(CONFIG_MPU_BRIDGE) += dsp/bridge/
+ obj-$(CONFIG_NUBUS) += nubus/
+ obj-$(CONFIG_ATM) += atm/
+ obj-y += macintosh/
+diff --git a/drivers/dsp/bridge/Kbuild b/drivers/dsp/bridge/Kbuild
+new file mode 100644
+index 0000000..3432ff2
+--- /dev/null
++++ b/drivers/dsp/bridge/Kbuild
+@@ -0,0 +1,39 @@
++obj-$(CONFIG_MPU_BRIDGE) += bridgedriver.o
++
++libgen = gen/gb.o gen/gt.o gen/gs.o gen/gh.o gen/_gt_para.o gen/uuidutil.o
++libservices = services/csl.o services/mem.o services/list.o services/dpc.o \
++ services/kfile.o services/sync.o \
++ services/clk.o services/cfg.o services/reg.o \
++ services/regsup.o services/ntfy.o \
++ services/dbg.o services/services.o
++libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \
++ wmd/tiomap3430_pwr.o wmd/tiomap_sm.o wmd/tiomap_io.o \
++ wmd/mmu_fault.o wmd/ue_deh.o
++libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/wcd.o \
++ pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
++librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
++ rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
++ rmgr/nldr.o rmgr/drv_interface.o
++libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o
++libhw = hw/hw_prcm.o hw/hw_dspssC64P.o hw/hw_mmu.o hw/hw_mbox.o
++
++bridgedriver-objs = $(libgen) $(libservices) $(libwmd) $(libpmgr) $(librmgr) \
++ $(libdload) $(libhw)
++
++# Debug
++ifeq ($(CONFIG_BRIDGE_DEBUG),y)
++ccflags-y += -DGT_TRACE -DDEBUG
++endif
++
++#Machine dependent
++ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
++ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
++ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS
++
++#Header files
++ccflags-y += -Idrivers/dsp/bridge/services
++ccflags-y += -Idrivers/dsp/bridge/wmd
++ccflags-y += -Idrivers/dsp/bridge/pmgr
++ccflags-y += -Idrivers/dsp/bridge/rmgr
++ccflags-y += -Idrivers/dsp/bridge/hw
++ccflags-y += -Iarch/arm
+diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig
+new file mode 100644
+index 0000000..2fed82c
+--- /dev/null
++++ b/drivers/dsp/bridge/Kconfig
+@@ -0,0 +1,36 @@
++#
++# DSP Bridge Driver Support
++#
++
++menuconfig MPU_BRIDGE
++ tristate "DSP Bridge driver"
++ default n
++ help
++ DSP/BIOS Bridge is designed for platforms that contain a GPP and
++ one or more attached DSPs. The GPP is considered the master or
++ "host" processor, and the attached DSPs are processing resources
++ that can be utilized by applications and drivers running on the GPP.
++
++config BRIDGE_DVFS
++ bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
++ depends on MPU_BRIDGE && OMAP_PM_SRF
++ default n
++ help
++ DVFS allows DSP Bridge to initiate the operating point change to
++ scale the chip voltage and frequency in order to match the
++ performance and power consumption to the current processing
++ requirements.
++
++config BRIDGE_MEMPOOL_SIZE
++ hex "Physical memory pool size (Byte)"
++ depends on MPU_BRIDGE
++ default 0x600000
++ help
++ Allocate specified size of memory at booting time to avoid allocation
++ failure under heavy memory fragmentation after some use time.
++
++config BRIDGE_DEBUG
++ bool "DSP Bridge Debug Support"
++ depends on MPU_BRIDGE
++ help
++ Say Y to enable Bridge debugging capabilities
+diff --git a/drivers/dsp/bridge/dynload/cload.c b/drivers/dsp/bridge/dynload/cload.c
+new file mode 100644
+index 0000000..271ab81
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/cload.c
+@@ -0,0 +1,1854 @@
++/*
++ * cload.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#include "module_list.h"
++#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. This macro marks
++ * the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++
++/*
++ * forward references
++ */
++static void dload_symbols(struct dload_state *dlthis);
++static void dload_data(struct dload_state *dlthis);
++static void allocate_sections(struct dload_state *dlthis);
++static void string_table_free(struct dload_state *dlthis);
++static void symbol_table_free(struct dload_state *dlthis);
++static void section_table_free(struct dload_state *dlthis);
++static void init_module_handle(struct dload_state *dlthis);
++#if BITS_PER_AU > BITS_PER_BYTE
++static char *unpack_name(struct dload_state *dlthis, u32 soffset);
++#endif
++
++static const char CINITNAME[] = { ".cinit" };
++static const char LOADER_DLLVIEW_ROOT[] = { "?DLModules?" };
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_TGTALLOC[] =
++ { "Target memory allocate failed, section %s size " FMT_UI32 };
++static const char E_INITFAIL[] = { "%s to target address " FMT_UI32 " failed" };
++static const char E_DLVWRITE[] = { "Write to DLLview list failed" };
++static const char E_ICONNECT[] = { "Connect call to init interface failed" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++
++/*************************************************************************
++ * Procedure dload_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ dlthis->mysym->Error_Report(dlthis->mysym, errtxt, args);
++ va_end(args);
++ dlthis->dload_errcount += 1;
++
++} /* dload_error */
++
++#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
++
++/*************************************************************************
++ * Procedure dload_syms_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_syms_error(struct Dynamic_Loader_Sym *syms, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ syms->Error_Report(syms, errtxt, args);
++ va_end(args);
++}
++
++/*************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int Dynamic_Load_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms ,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ if (init && !dl_state.dload_errcount)
++ dload_data(&dl_state);
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount) &&
++ (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF)) {
++ if (init != NULL) {
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ } else {
++ dload_error(&dl_state, "init is NULL");
++ }
++ }
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int
++Dynamic_Open_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount)
++ && (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF))
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure dload_headers
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the DOFF header and verify record. Deals with any byte-order
++ * issues and checks them for validity.
++ ************************************************************************/
++#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
++ sizeof(struct doff_verify_rec_t))
++
++void dload_headers(struct dload_state *dlthis)
++{
++ u32 map;
++
++ /* Read the header and the verify record as one. If we don't get it
++ all, we're done */
++ if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
++ COMBINED_HEADER_SIZE) != COMBINED_HEADER_SIZE) {
++ DL_ERROR(E_READSTRM, "File Headers");
++ return;
++ }
++ /*
++ * Verify that we have the byte order of the file correct.
++ * If not, must fix it before we can continue
++ */
++ map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
++ if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
++ /* input is either byte-shuffled or bad */
++ if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
++ dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
++ map);
++ }
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ BYTE_RESHUFFLE_VALUE) {
++ /* didn't fix the problem, the byte swap map is bad */
++ dload_error(dlthis,
++ "Bad byte swap map " FMT_UI32 " in header",
++ dlthis->dfile_hdr.df_byte_reshuffle);
++ return;
++ }
++ dlthis->reorder_map = map; /* keep map for future use */
++ }
++
++ /*
++ * Verify checksum of header and verify record
++ */
++ if (~dload_checksum(&dlthis->dfile_hdr,
++ sizeof(struct doff_filehdr_t)) ||
++ ~dload_checksum(&dlthis->verify,
++ sizeof(struct doff_verify_rec_t))) {
++ DL_ERROR(E_CHECKSUM, "header or verify record");
++ return;
++ }
++#if HOST_ENDIANNESS
++ dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
++#endif
++
++ /* Check for valid target ID */
++ if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
++ -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
++ dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
++ dlthis->dfile_hdr.df_target_id, TARGET_ID);
++ return;
++ }
++ /* Check for valid file format */
++ if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
++ dload_error(dlthis, "Bad DOFF version 0x%x",
++ dlthis->dfile_hdr.df_doff_version);
++ return;
++ }
++
++ /*
++ * Apply reasonableness checks to count fields
++ */
++ if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
++ dload_error(dlthis, "Excessive string table size " FMT_UI32,
++ dlthis->dfile_hdr.df_strtab_size);
++ return;
++ }
++ if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
++ dload_error(dlthis, "Excessive section count 0x%x",
++ dlthis->dfile_hdr.df_no_scns);
++ return;
++ }
++#ifndef TARGET_ENDIANNESS
++ /*
++ * Check that endianness does not disagree with explicit specification
++ */
++ if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
++ dlthis->myoptions & ENDIANNESS_MASK) {
++ dload_error(dlthis,
++ "Input endianness disagrees with specified option");
++ return;
++ }
++ dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
++#endif
++
++} /* dload_headers */
++
++/* COFF Section Processing
++ *
++ * COFF sections are read in and retained intact. Each record is embedded
++ * in a new structure that records the updated load and
++ * run addresses of the section */
++
++static const char SECN_ERRID[] = { "section" };
++
++/*************************************************************************
++ * Procedure dload_sections
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the section records into an internal table.
++ ************************************************************************/
++void
++dload_sections(struct dload_state *dlthis)
++{
++ s16 siz;
++ struct doff_scnhdr_t *shp;
++ unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
++
++ /* allocate space for the DOFF section records */
++ siz = nsecs * sizeof(struct doff_scnhdr_t);
++ shp = (struct doff_scnhdr_t *)dlthis->mysym->Allocate(dlthis->mysym,
++ siz);
++ if (!shp) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->sect_hdrs = shp;
++
++ /* read in the section records */
++ if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
++ DL_ERROR(E_READSTRM, SECN_ERRID);
++ return;
++ }
++
++ /* if we need to fix up byte order, do it now */
++ if (dlthis->reorder_map)
++ dload_reorder(shp, siz, dlthis->reorder_map);
++
++ /* check for validity */
++ if (~dload_checksum(dlthis->sect_hdrs, siz) !=
++ dlthis->verify.dv_scn_rec_checksum) {
++ DL_ERROR(E_CHECKSUM, SECN_ERRID);
++ return;
++ }
++
++} /* dload_sections */
++
++/*****************************************************************************
++ * Procedure allocate_sections
++ *
++ * Parameters:
++ * alloc target memory allocator class
++ *
++ * Effect:
++ * Assigns new (target) addresses for sections
++ *****************************************************************************/
++static void allocate_sections(struct dload_state *dlthis)
++{
++ u16 curr_sect, nsecs, siz;
++ struct doff_scnhdr_t *shp;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ nsecs = dlthis->dfile_hdr.df_no_scns;
++ if (!nsecs)
++ return;
++ if ((dlthis->myalloc == NULL) &&
++ (dlthis->dfile_hdr.df_target_scns > 0)) {
++ DL_ERROR("Arg 3 (alloc) required but NULL", 0);
++ return;
++ }
++ /* allocate space for the module handle, which we will
++ * keep for unload purposes */
++ siz = dlthis->dfile_hdr.df_target_scns *
++ sizeof(struct LDR_SECTION_INFO) + MY_HANDLE_SIZE;
++ hndl = (struct my_handle *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!hndl) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ /* initialize the handle header */
++ hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
++ hndl->dm.hroot = NULL;
++ hndl->dm.dbthis = 0;
++ dlthis->myhandle = hndl; /* save away for return */
++ /* pointer to the section list of allocated sections */
++ dlthis->ldr_sections = asecs = hndl->secns;
++ /* * Insert names into all sections, make copies of
++ the sections we allocate */
++ shp = dlthis->sect_hdrs;
++ for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
++ u32 soffset = shp->ds_offset;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ /* attempt to insert the name of this section */
++ if (soffset < dlthis->dfile_hdr.df_strtab_size)
++ DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
++ soffset;
++ else {
++ dload_error(dlthis, "Bad name offset in section %d",
++ curr_sect);
++ DOFFSEC_IS_LDRSEC(shp)->name = NULL;
++ }
++#endif
++ /* allocate target storage for sections that require it */
++ if (DS_NEEDS_ALLOCATION(shp)) {
++ *asecs = *DOFFSEC_IS_LDRSEC(shp);
++ asecs->context = 0; /* zero the context field */
++#if BITS_PER_AU > BITS_PER_BYTE
++ asecs->name = unpack_name(dlthis, soffset);
++ dlthis->debug_string_size = soffset + dlthis->temp_len;
++#else
++ dlthis->debug_string_size = soffset;
++#endif
++ if (dlthis->myalloc != NULL) {
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, asecs,
++ DS_ALIGNMENT(asecs->type))) {
++ dload_error(dlthis, E_TGTALLOC, asecs->name,
++ asecs->size);
++ return;
++ }
++ }
++ /* keep address deltas in original section table */
++ shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
++ shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
++ dlthis->allocated_secn_count += 1;
++ } /* allocate target storage */
++ shp += 1;
++ asecs += 1;
++ }
++#if BITS_PER_AU <= BITS_PER_BYTE
++ dlthis->debug_string_size +=
++ strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
++#endif
++} /* allocate sections */
++
++/*************************************************************************
++ * Procedure section_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ ************************************************************************/
++static void section_table_free(struct dload_state *dlthis)
++{
++ struct doff_scnhdr_t *shp;
++
++ shp = dlthis->sect_hdrs;
++ if (shp)
++ dlthis->mysym->Deallocate(dlthis->mysym, shp);
++
++} /* section_table_free */
++
++/*************************************************************************
++ * Procedure dload_strings
++ *
++ * Parameters:
++ * sec_names_only If true only read in the "section names"
++ * portion of the string table
++ *
++ * Effect:
++ * Loads the DOFF string table into memory. DOFF keeps all strings in a
++ * big unsorted array. We just read that array into memory in bulk.
++ ************************************************************************/
++static const char S_STRINGTBL[] = { "string table" };
++void dload_strings(struct dload_state *dlthis, boolean sec_names_only)
++{
++ u32 ssiz;
++ char *strbuf;
++
++ if (sec_names_only) {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_scn_name_size));
++ } else {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_strtab_size));
++ }
++ if (ssiz == 0)
++ return;
++
++ /* get some memory for the string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz +
++ dlthis->dfile_hdr.df_max_str_len);
++#else
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz);
++#endif
++ if (strbuf == NULL) {
++ DL_ERROR(E_ALLOC, ssiz);
++ return;
++ }
++ dlthis->str_head = strbuf;
++#if BITS_PER_AU > BITS_PER_BYTE
++ dlthis->str_temp = strbuf + ssiz;
++#endif
++ /* read in the strings and verify them */
++ if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
++ ssiz)) != ssiz) {
++ DL_ERROR(E_READSTRM, S_STRINGTBL);
++ }
++ /* if we need to fix up byte order, do it now */
++#ifndef _BIG_ENDIAN
++ if (dlthis->reorder_map)
++ dload_reorder(strbuf, ssiz, dlthis->reorder_map);
++
++ if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put strings in big-endian order, not in PC order */
++ dload_reorder(strbuf, ssiz, HOST_BYTE_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++ if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#endif
++} /* dload_strings */
++
++/*************************************************************************
++ * Procedure string_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the string table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *************************************************************************/
++static void string_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++} /* string_table_free */
++
++/*
++ * Symbol Table Maintenance Functions
++ *
++ * COFF symbols are read by dload_symbols(), which is called after
++ * sections have been allocated. Symbols which might be used in
++ * relocation (ie, not debug info) are retained in an internal temporary
++ * compressed table (type Local_Symbol). A particular symbol is recovered
++ * by index by calling dload_find_symbol(). dload_find_symbol
++ * reconstructs a more explicit representation (type SLOTVEC) which is
++ * used by reloc.c
++ */
++/* real size of debug header */
++#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
++
++static const char SYM_ERRID[] = { "symbol" };
++
++/**************************************************************************
++ * Procedure dload_symbols
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Reads in symbols and retains ones that might be needed for relocation
++ * purposes.
++ ************************************************************************/
++/* size of symbol buffer no bigger than target data buffer, to limit stack
++ * usage*/
++#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
++ sizeof(struct doff_syment_t))
++
++static void dload_symbols(struct dload_state *dlthis)
++{
++ u32 s_count, siz, dsiz, symbols_left;
++ u32 checks;
++ struct Local_Symbol *sp;
++ struct dynload_symbol *symp;
++ struct dynload_symbol *newsym;
++
++ s_count = dlthis->dfile_hdr.df_no_syms;
++ if (s_count == 0)
++ return;
++
++ /* We keep a local symbol table for all of the symbols in the input.
++ * This table contains only section & value info, as we do not have
++ * to do any name processing for locals. We reuse this storage
++ * as a temporary for .dllview record construction.
++ * Allocate storage for the whole table.*/
++ siz = s_count * sizeof(struct Local_Symbol);
++ dsiz = DBG_HDR_SIZE +
++ (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
++ BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
++ if (dsiz > siz)
++ siz = dsiz; /* larger of symbols and .dllview temp */
++ sp = (struct Local_Symbol *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!sp) {
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->local_symtab = sp;
++ /* Read the symbols in the input, store them in the table, and post any
++ * globals to the global symbol table. In the process, externals
++ become defined from the global symbol table */
++ checks = dlthis->verify.dv_sym_tab_checksum;
++ symbols_left = s_count;
++ do { /* read all symbols */
++ char *sname;
++ u32 val;
++ s32 delta;
++ struct doff_syment_t *input_sym;
++ unsigned syms_in_buf;
++ struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
++ input_sym = my_sym_buf;
++ syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
++ MY_SYM_BUF_SIZ : symbols_left;
++ siz = syms_in_buf * sizeof(struct doff_syment_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
++ siz) {
++ DL_ERROR(E_READSTRM, SYM_ERRID);
++ return;
++ }
++ if (dlthis->reorder_map)
++ dload_reorder(input_sym, siz, dlthis->reorder_map);
++
++ checks += dload_checksum(input_sym, siz);
++ do { /* process symbols in buffer */
++ symbols_left -= 1;
++ /* attempt to derive the name of this symbol */
++ sname = NULL;
++ if (input_sym->dn_offset > 0) {
++#if BITS_PER_AU <= BITS_PER_BYTE
++ if ((u32) input_sym->dn_offset <
++ dlthis->dfile_hdr.df_strtab_size)
++ sname = dlthis->str_head +
++ BYTE_TO_HOST(input_sym->dn_offset);
++ else
++ dload_error(dlthis,
++ "Bad name offset in symbol %d",
++ symbols_left);
++#else
++ sname = unpack_name(dlthis,
++ input_sym->dn_offset);
++#endif
++ }
++ val = input_sym->dn_value;
++ delta = 0;
++ sp->sclass = input_sym->dn_sclass;
++ sp->secnn = input_sym->dn_scnum;
++ /* if this is an undefined symbol,
++ * define it (or fail) now */
++ if (sp->secnn == DN_UNDEF) {
++ /* pointless for static undefined */
++ if (input_sym->dn_sclass != DN_EXT)
++ goto loop_cont;
++
++ /* try to define symbol from previously
++ * loaded images */
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp) {
++ DL_ERROR
++ ("Undefined external symbol %s",
++ sname);
++ goto loop_cont;
++ }
++ val = delta = symp->value;
++ goto loop_cont;
++ }
++ /* symbol defined by this module */
++ if (sp->secnn > 0) { /* symbol references a section */
++ if ((unsigned)sp->secnn <=
++ dlthis->allocated_secn_count) {
++ /* section was allocated */
++ struct doff_scnhdr_t *srefp =
++ &dlthis->sect_hdrs
++ [sp->secnn - 1];
++
++ if (input_sym->dn_sclass ==
++ DN_STATLAB ||
++ input_sym->dn_sclass == DN_EXTLAB){
++ /* load */
++ delta = srefp->ds_vaddr;
++ } else {
++ /* run */
++ delta = srefp->ds_paddr;
++ }
++ val += delta;
++ }
++ goto loop_itr;
++ }
++ /* This symbol is an absolute symbol */
++ if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
++ (sp->sclass == DN_EXTLAB))) {
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp)
++ goto loop_itr;
++ /* This absolute symbol is already defined. */
++ if (symp->value == input_sym->dn_value) {
++ /* If symbol values are equal, continue
++ * but don't add to the global symbol
++ * table */
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ continue;
++ } else {
++ /* If symbol values are not equal,
++ * return with redefinition error */
++ DL_ERROR("Absolute symbol %s is "
++ "defined multiple times with "
++ "different values", sname);
++ return;
++ }
++ }
++loop_itr:
++ /* if this is a global symbol, post it to the
++ * global table */
++ if (input_sym->dn_sclass == DN_EXT ||
++ input_sym->dn_sclass == DN_EXTLAB) {
++ /* Keep this global symbol for subsequent
++ * modules. Don't complain on error, to allow
++ * symbol API to suppress global symbols */
++ if (!sname)
++ goto loop_cont;
++
++ newsym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, sname,
++ (unsigned)dlthis->myhandle);
++ if (newsym)
++ newsym->value = val;
++
++ } /* global */
++loop_cont:
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ } while ((syms_in_buf -= 1) > 0); /* process sym in buffer */
++ } while (symbols_left > 0); /* read all symbols */
++ if (~checks)
++ dload_error(dlthis, "Checksum of symbols failed");
++
++} /* dload_symbols */
++
++/*****************************************************************************
++ * Procedure symbol_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *****************************************************************************/
++static void symbol_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->local_symtab) {
++ if (dlthis->dload_errcount) { /* blow off our symbols */
++ dlthis->mysym->Purge_Symbol_Table(dlthis->mysym,
++ (unsigned)dlthis->myhandle);
++ }
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->local_symtab);
++ }
++} /* symbol_table_free */
++
++/* .cinit Processing
++ *
++ * The dynamic loader does .cinit interpretation. cload_cinit()
++ * acts as a special write-to-target function, in that it takes relocated
++ * data from the normal data flow, and interprets it as .cinit actions.
++ * Because the normal data flow does not necessarily process the whole
++ * .cinit section in one buffer, cload_cinit() must be prepared to
++ * interpret the data piecemeal. A state machine is used for this
++ * purpose.
++ */
++
++/* The following are only for use by reloc.c and things it calls */
++static const struct LDR_SECTION_INFO CINIT_INFO_INIT = { CINITNAME, 0, 0,
++ (LDR_ADDR) -1, 0, DLOAD_BSS, 0 };
++
++/*************************************************************************
++ * Procedure cload_cinit
++ *
++ * Parameters:
++ * ipacket Pointer to data packet to be loaded
++ *
++ * Effect:
++ * Interprets the data in the buffer as .cinit data, and performs the
++ * appropriate initializations.
++ ************************************************************************/
++static void cload_cinit(struct dload_state *dlthis,
++ struct image_packet_t *ipacket)
++{
++#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
++ s32 init_count, left;
++#else
++ s16 init_count, left;
++#endif
++ unsigned char *pktp = ipacket->i_bits;
++ unsigned char *pktend = pktp +
++ BYTE_TO_HOST_ROUND(ipacket->i_packet_size);
++ int temp;
++ LDR_ADDR atmp;
++ struct LDR_SECTION_INFO cinit_info;
++
++ /* PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
++ while (true) {
++ left = pktend - pktp;
++ switch (dlthis->cinit_state) {
++ case CI_count: /* count field */
++ if (left < TDATA_TO_HOST(CINIT_COUNT))
++ goto loopexit;
++ temp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_COUNT * TDATA_AU_BITS, 0,
++ ROP_SGN);
++ pktp += TDATA_TO_HOST(CINIT_COUNT);
++ /* negative signifies BSS table, zero means done */
++ if (temp <= 0) {
++ dlthis->cinit_state = CI_done;
++ break;
++ }
++ dlthis->cinit_count = temp;
++ dlthis->cinit_state = CI_address;
++ break;
++#if CINIT_ALIGN < CINIT_ADDRESS
++ case CI_partaddress:
++ pktp -= TDATA_TO_HOST(CINIT_ALIGN);
++ /* back up pointer into space courtesy of caller */
++ *(uint16_t *)pktp = dlthis->cinit_addr;
++ /* stuff in saved bits !! FALL THRU !! */
++#endif
++ case CI_address: /* Address field for a copy packet */
++ if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
++#if CINIT_ALIGN < CINIT_ADDRESS
++ if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
++ /* address broken into halves */
++ dlthis->cinit_addr = *(uint16_t *)pktp;
++ /* remember 1st half */
++ dlthis->cinit_state = CI_partaddress;
++ left = 0;
++ }
++#endif
++ goto loopexit;
++ }
++ atmp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_ADDRESS * TDATA_AU_BITS, 0,
++ ROP_UNS);
++ pktp += TDATA_TO_HOST(CINIT_ADDRESS);
++#if CINIT_PAGE_BITS > 0
++ dlthis->cinit_page = atmp &
++ ((1 << CINIT_PAGE_BITS) - 1);
++ atmp >>= CINIT_PAGE_BITS;
++#else
++ dlthis->cinit_page = CINIT_DEFAULT_PAGE;
++#endif
++ dlthis->cinit_addr = atmp;
++ dlthis->cinit_state = CI_copy;
++ break;
++ case CI_copy: /* copy bits to the target */
++ init_count = HOST_TO_TDATA(left);
++ if (init_count > dlthis->cinit_count)
++ init_count = dlthis->cinit_count;
++ if (init_count == 0)
++ goto loopexit; /* get more bits */
++ cinit_info = CINIT_INFO_INIT;
++ cinit_info.page = dlthis->cinit_page;
++ if (!dlthis->myio->writemem(dlthis->myio, pktp,
++ TDATA_TO_TADDR(dlthis->cinit_addr),
++ &cinit_info,
++ TDATA_TO_HOST(init_count))) {
++ dload_error(dlthis, E_INITFAIL, "write",
++ dlthis->cinit_addr);
++ }
++ dlthis->cinit_count -= init_count;
++ if (dlthis->cinit_count <= 0) {
++ dlthis->cinit_state = CI_count;
++ init_count = (init_count + CINIT_ALIGN - 1) &
++ -CINIT_ALIGN;
++ /* align to next init */
++ }
++ pktp += TDATA_TO_HOST(init_count);
++ dlthis->cinit_addr += init_count;
++ break;
++ case CI_done: /* no more .cinit to do */
++ return;
++ } /* switch (cinit_state) */
++ } /* while */
++
++loopexit:
++ if (left > 0) {
++ dload_error(dlthis, "%d bytes left over in cinit packet", left);
++ dlthis->cinit_state = CI_done; /* left over bytes are bad */
++ }
++} /* cload_cinit */
++
++/* Functions to interface to reloc.c
++ *
++ * reloc.c is the relocation module borrowed from the linker, with
++ * minimal (we hope) changes for our purposes. cload_sect_data() invokes
++ * this module on a section to relocate and load the image data for that
++ * section. The actual read and write actions are supplied by the global
++ * routines below.
++ */
++
++/************************************************************************
++ * Procedure relocate_packet
++ *
++ * Parameters:
++ * ipacket Pointer to an image packet to relocate
++ *
++ * Effect:
++ * Performs the required relocations on the packet. Returns a checksum
++ * of the relocation operations.
++ ************************************************************************/
++#define MY_RELOC_BUF_SIZ 8
++/* careful! exists at the same time as the image buffer*/
++static int relocate_packet(struct dload_state *dlthis,
++ struct image_packet_t *ipacket, u32 *checks)
++{
++ u32 rnum;
++
++ rnum = ipacket->i_num_relocs;
++ do { /* all relocs */
++ unsigned rinbuf;
++ int siz;
++ struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
++ rp = rrec;
++ rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
++ siz = rinbuf * sizeof(struct reloc_record_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
++ DL_ERROR(E_READSTRM, "relocation");
++ return 0;
++ }
++ /* reorder the bytes if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(rp, siz, dlthis->reorder_map);
++
++ *checks += dload_checksum(rp, siz);
++ do {
++ /* perform the relocation operation */
++ dload_relocate(dlthis, (TgtAU_t *) ipacket->i_bits, rp);
++ rp += 1;
++ rnum -= 1;
++ } while ((rinbuf -= 1) > 0);
++ } while (rnum > 0); /* all relocs */
++ return 1;
++} /* dload_read_reloc */
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++
++/* VERY dangerous */
++static const char IMAGEPAK[] = { "image packet" };
++
++/*************************************************************************
++ * Procedure dload_data
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Read image data from input file, relocate it, and download it to the
++ * target.
++ ************************************************************************/
++static void dload_data(struct dload_state *dlthis)
++{
++ u16 curr_sect;
++ struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
++ struct LDR_SECTION_INFO *lptr = dlthis->ldr_sections;
++#ifdef OPT_ZERO_COPY_LOADER
++ boolean bZeroCopy = false;
++#endif
++ u8 *pDest;
++
++ struct {
++ struct image_packet_t ipacket;
++ u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
++ } ibuf;
++
++ /* Indicates whether CINIT processing has occurred */
++ boolean cinit_processed = false;
++
++ /* Loop through the sections and load them one at a time.
++ */
++ for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
++ curr_sect += 1) {
++ if (DS_NEEDS_DOWNLOAD(sptr)) {
++ s32 nip;
++ LDR_ADDR image_offset = 0;
++ /* set relocation info for this section */
++ if (curr_sect < dlthis->allocated_secn_count)
++ dlthis->delta_runaddr = sptr->ds_paddr;
++ else {
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++ dlthis->delta_runaddr = 0;
++ }
++ dlthis->image_secn = lptr;
++#if BITS_PER_AU > BITS_PER_BYTE
++ lptr->name = unpack_name(dlthis, sptr->ds_offset);
++#endif
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* process packets */
++
++ s32 ipsize;
++ u32 checks;
++ /* get the fixed header bits */
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ &ibuf.ipacket, IPH_SIZE) != IPH_SIZE) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map) {
++ dload_reorder(&ibuf.ipacket, IPH_SIZE,
++ dlthis->reorder_map);
++ }
++ /* now read the rest of the packet */
++ ipsize =
++ BYTE_TO_HOST(DOFF_ALIGN
++ (ibuf.ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ DL_ERROR("Bad image packet size %d",
++ ipsize);
++ return;
++ }
++ pDest = ibuf.bufr;
++#ifdef OPT_ZERO_COPY_LOADER
++ bZeroCopy = false;
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
++ dlthis->myio->writemem(dlthis->myio,
++ &pDest, lptr->load_addr +
++ image_offset, lptr, 0);
++ bZeroCopy = (pDest != ibuf.bufr);
++ }
++#endif
++ /* End of determination */
++
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ ibuf.bufr, ipsize) != ipsize) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ ibuf.ipacket.i_bits = pDest;
++
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map) {
++ dload_reorder(pDest, ipsize,
++ dlthis->reorder_map);
++ }
++ checks = dload_checksum(pDest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP
++ (BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order,
++ * not PC order */
++ dload_reorder(pDest, ipsize,
++ TARGET_ORDER
++ (dlthis->dfile_hdr.df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(pDest,
++ ipsize);
++#else
++ checks = dload_reverse_checksum(pDest,
++ ipsize);
++#endif
++#endif
++
++ checks += dload_checksum(&ibuf.ipacket,
++ IPH_SIZE);
++ /* relocate the image bits as needed */
++ if (ibuf.ipacket.i_num_relocs) {
++ dlthis->image_offset = image_offset;
++ if (!relocate_packet(dlthis,
++ &ibuf.ipacket, &checks))
++ return; /* serious error */
++ }
++ if (~checks)
++ DL_ERROR(E_CHECKSUM, IMAGEPAK);
++ /* stuff the result into target memory */
++ if (DLOAD_SECT_TYPE(sptr) == DLOAD_CINIT) {
++ cload_cinit(dlthis, &ibuf.ipacket);
++ cinit_processed = true;
++ } else {
++#ifdef OPT_ZERO_COPY_LOADER
++ if (!bZeroCopy) {
++#endif
++
++ if (!dlthis->myio->writemem
++ (dlthis->myio, ibuf.bufr,
++ lptr->load_addr + image_offset, lptr,
++ BYTE_TO_HOST
++ (ibuf.ipacket.i_packet_size))) {
++ DL_ERROR(
++ "Write to " FMT_UI32 " failed",
++ lptr->load_addr + image_offset);
++ }
++#ifdef OPT_ZERO_COPY_LOADER
++ }
++#endif
++
++ }
++ image_offset +=
++ BYTE_TO_TADDR(ibuf.ipacket.i_packet_size);
++ } /* process packets */
++ /* if this is a BSS section, we may want to fill it */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (cinit_processed) {
++ /* Don't clear BSS after load-time
++ * initialization */
++ DL_ERROR
++ ("Zero-initialization at " FMT_UI32 " after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr),
++ lptr, TADDR_TO_HOST(lptr->size),
++ dload_fill_bss);
++ goto loop_cont;
++ } /* if DS_DOWNLOAD_MASK */
++ /* If not loading, but BSS, zero initialize */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (curr_sect >= dlthis->allocated_secn_count)
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++
++ if (cinit_processed) {
++ /*Don't clear BSS after load-time initialization */
++ DL_ERROR(
++ "Zero-initialization at " FMT_UI32 " attempted after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr), lptr,
++ TADDR_TO_HOST(lptr->size), dload_fill_bss);
++loop_cont:
++ sptr += 1;
++ lptr += 1;
++ } /* load sections */
++} /* dload_data */
++
++/*************************************************************************
++ * Procedure dload_reorder
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be byte-swapped
++ * dsiz size of the data to be reordered in sizeof() units.
++ * map 32-bit map defining how to reorder the data. Value
++ * must be REORDER_MAP() of some permutation
++ * of 0x00 01 02 03
++ *
++ * Effect:
++ * Re-arranges the bytes in each word according to the map specified.
++ *
++ ************************************************************************/
++/* mask for byte shift count */
++#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
++
++void dload_reorder(void *data, int dsiz, unsigned int map)
++{
++ register u32 tmp, tmap, datv;
++ u32 *dp = (u32 *)data;
++
++ map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
++ do {
++ tmp = 0;
++ datv = *dp;
++ tmap = map;
++ do {
++ tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
++ tmap >>= BITS_PER_BYTE;
++ } while (datv >>= BITS_PER_BYTE);
++ *dp++ = tmp;
++ } while ((dsiz -= sizeof(u32)) > 0);
++} /* dload_reorder */
++
++/*************************************************************************
++ * Procedure dload_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block
++ *
++ ************************************************************************/
++u32 dload_checksum(void *data, unsigned siz)
++{
++ u32 sum;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++ for (left = siz; left > 0; left -= sizeof(u32))
++ sum += *dp++;
++ return sum;
++} /* dload_checksum */
++
++#if HOST_ENDIANNESS
++/*************************************************************************
++ * Procedure dload_reverse_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block, which is assumed to be bytes
++ * in big-endian order.
++ *
++ * Notes:
++ * In a big-endian host, things like the string table are stored as bytes
++ * in host order. But dllcreate always checksums in little-endian order.
++ * It is most efficient to just handle the difference a word at a time.
++ *
++ ***********************************************************************/
++u32 dload_reverse_checksum(void *data, unsigned siz)
++{
++ u32 sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 3;
++ sum += temp >> BITS_PER_BYTE * 3;
++ sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
++ sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
++ }
++
++ return sum;
++} /* dload_reverse_checksum */
++
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++u32 dload_reverse_checksum_16(void *data, unsigned siz)
++{
++ uint_fast32_t sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 2;
++ sum += temp >> BITS_PER_BYTE * 2;
++ }
++
++ return sum;
++} /* dload_reverse_checksum_16 */
++#endif
++#endif
++
++/*************************************************************************
++ * Procedure swap_words
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be swapped
++ * siz size of the data to be swapped.
++ * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
++ * 0 => 1 long
++ *
++ * Effect:
++ * Swaps the specified data according to the specified map
++ *
++ ************************************************************************/
++static void swap_words(void *data, unsigned siz, unsigned bitmap)
++{
++ register int i;
++#if TARGET_AU_BITS < 16
++ register u16 *sp;
++#endif
++ register u32 *lp;
++
++ siz /= sizeof(u16);
++
++#if TARGET_AU_BITS < 16
++ /* pass 1: do all the bytes */
++ i = siz;
++ sp = (u16 *) data;
++ do {
++ register u16 tmp;
++ tmp = *sp;
++ *sp++ = SWAP16BY8(tmp);
++ } while ((i -= 1) > 0);
++#endif
++
++#if TARGET_AU_BITS < 32
++ /* pass 2: fixup the 32-bit words */
++ i = siz >> 1;
++ lp = (u32 *) data;
++ do {
++ if ((bitmap & 1) == 0) {
++ register u32 tmp;
++ tmp = *lp;
++ *lp = SWAP32BY16(tmp);
++ }
++ lp += 1;
++ bitmap >>= 1;
++ } while ((i -= 1) > 0);
++#endif
++} /* swap_words */
++
++/*************************************************************************
++ * Procedure copy_tgt_strings
++ *
++ * Parameters:
++ * dstp Destination address. Assumed to be 32-bit aligned
++ * srcp Source address. Assumed to be 32-bit aligned
++ * charcount Number of characters to copy.
++ *
++ * Effect:
++ * Copies strings from the source (which is in usual .dof file order on
++ * the loading processor) to the destination buffer (which should be in proper
++ * target addressable unit order). Makes sure the last string in the
++ * buffer is NULL terminated (for safety).
++ * Returns the first unused destination address.
++ ************************************************************************/
++static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
++{
++ register TgtAU_t *src = (TgtAU_t *)srcp;
++ register TgtAU_t *dst = (TgtAU_t *)dstp;
++ register int cnt = charcount;
++ do {
++#if TARGET_AU_BITS <= BITS_PER_AU
++ /* byte-swapping issues may exist for strings on target */
++ *dst++ = *src++;
++#elif TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)
++ register TgtAU_t tmp;
++ tmp = *src++;
++ *dst++ = SWAP16BY8(tmp); /* right for TARGET_AU_BITS == 16 */
++#else
++ *dst++ = *src++;
++#endif
++ } while ((cnt -= (sizeof(TgtAU_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
++ /*apply force to make sure that the string table has null terminator */
++#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
++ dst[-1] = 0;
++#elif TARGET_BIG_ENDIAN
++ dst[-1] &= ~BYTE_MASK; /* big-endian */
++#else
++ dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1; /* little endian */
++#endif
++ return (char *)dst;
++} /* copy_tgt_strings */
++
++/*************************************************************************
++ * Procedure init_module_handle
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Initializes the module handle we use to enable unloading, and installs
++ * the debug information required by the target.
++ *
++ * Notes:
++ * The handle returned from Dynamic_Load_Module needs to encapsulate all the
++ * allocations done for the module, and enable them plus the modules symbols to
++ * be deallocated.
++ *
++ ************************************************************************/
++#ifndef _BIG_ENDIAN
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DBG_LIST_PAGE, DLOAD_DATA, 0 };
++#else
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DLOAD_DATA, DBG_LIST_PAGE, 0 };
++#endif
++static void init_module_handle(struct dload_state *dlthis)
++{
++ struct my_handle *hndl;
++ u16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct dll_module *dbmod;
++ struct dll_sect *dbsec;
++ struct dbg_mirror_root *mlist;
++ register char *cp;
++ struct modules_header mhdr;
++ struct LDR_SECTION_INFO dllview_info;
++ struct dynload_symbol *debug_mirror_sym;
++ hndl = dlthis->myhandle;
++ if (!hndl)
++ return; /* must be errors detected, so forget it */
++ hndl->secn_count = dlthis->allocated_secn_count << 1;
++#ifndef TARGET_ENDIANNESS
++ if (dlthis->big_e_target)
++ hndl->secn_count += 1; /* flag for big-endian */
++#endif
++ if (dlthis->dload_errcount)
++ return; /* abandon if errors detected */
++ /* Locate the symbol that names the header for the CCS debug list
++ of modules. If not found, we just don't generate the debug record.
++ If found, we create our modules list. We make sure to create the
++ LOADER_DLLVIEW_ROOT even if there is no relocation info to record,
++ just to try to put both symbols in the same symbol table and
++ module.*/
++ debug_mirror_sym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LOADER_DLLVIEW_ROOT);
++ if (!debug_mirror_sym) {
++ struct dynload_symbol *dlmodsym;
++ struct dbg_mirror_root *mlst;
++
++ /* our root symbol is not yet present;
++ check if we have DLModules defined */
++ dlmodsym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LINKER_MODULES_HEADER);
++ if (!dlmodsym)
++ return; /* no DLModules list so no debug info */
++ /* if we have DLModules defined, construct our header */
++ mlst = (struct dbg_mirror_root *)
++ dlthis->mysym->Allocate(dlthis->mysym,
++ sizeof(struct dbg_mirror_root));
++ if (!mlst) {
++ DL_ERROR(E_ALLOC, sizeof(struct dbg_mirror_root));
++ return;
++ }
++ mlst->hnext = NULL;
++ mlst->changes = 0;
++ mlst->refcount = 0;
++ mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
++ /* add our root symbol */
++ debug_mirror_sym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, LOADER_DLLVIEW_ROOT,
++ (unsigned)dlthis->myhandle);
++ if (!debug_mirror_sym) {
++ /* failed, recover memory */
++ dlthis->mysym->Deallocate(dlthis->mysym, mlst);
++ return;
++ }
++ debug_mirror_sym->value = (u32)mlst;
++ }
++ /* First create the DLLview record and stuff it into the buffer.
++ Then write it to the DSP. Record pertinent locations in our hndl,
++ and add it to the per-processor list of handles with debug info.*/
++#ifndef DEBUG_HEADER_IN_LOADER
++ mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
++ if (!mlist)
++ return;
++#else
++ mlist = (struct dbg_mirror_root *)&debug_list_header;
++#endif
++ hndl->dm.hroot = mlist; /* set pointer to root into our handle */
++ if (!dlthis->allocated_secn_count)
++ return; /* no load addresses to be recorded */
++ /* reuse temporary symbol storage */
++ dbmod = (struct dll_module *) dlthis->local_symtab;
++ /* Create the DLLview record in the memory we retain for our handle*/
++ dbmod->num_sects = dlthis->allocated_secn_count;
++ dbmod->timestamp = dlthis->verify.dv_timdat;
++ dbmod->version = INIT_VERSION;
++ dbmod->verification = VERIFICATION;
++ asecs = dlthis->ldr_sections;
++ dbsec = dbmod->sects;
++ for (curr_sect = dlthis->allocated_secn_count;
++ curr_sect > 0; curr_sect -= 1) {
++ dbsec->sect_load_adr = asecs->load_addr;
++ dbsec->sect_run_adr = asecs->run_addr;
++ dbsec += 1;
++ asecs += 1;
++ }
++ /* now cram in the names */
++ cp = copy_tgt_strings(dbsec, dlthis->str_head,
++ dlthis->debug_string_size);
++
++ /* round off the size of the debug record, and remember same */
++ hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
++ *cp = 0; /* strictly to make our test harness happy */
++ dllview_info = DLLVIEW_INFO_INIT;
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ /* Initialize memory context to default heap */
++ dllview_info.context = 0;
++ hndl->dm.context = 0;
++ /* fill in next pointer and size */
++ if (mlist->hnext) {
++ dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
++ dbmod->next_module_size = mlist->hnext->dm.dbsiz;
++ } else {
++ dbmod->next_module_size = 0;
++ dbmod->next_module = 0;
++ }
++ /* allocate memory for on-DSP DLLview debug record */
++ if (!dlthis->myalloc)
++ return;
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, &dllview_info,
++ HOST_TO_TADDR(sizeof(u32)))) {
++ return;
++ }
++ /* Store load address of .dllview section */
++ hndl->dm.dbthis = dllview_info.load_addr;
++ /* Store memory context (segid) in which .dllview section
++ * was allocated */
++ hndl->dm.context = dllview_info.context;
++ mlist->refcount += 1;
++ /* swap bytes in the entire debug record, but not the string table */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(dbmod, (char *)dbsec - (char *)dbmod,
++ DLL_MODULE_BITMAP);
++ }
++ /* Update the DLLview list on the DSP write new record */
++ if (!dlthis->myio->writemem(dlthis->myio, dbmod,
++ dllview_info.load_addr, &dllview_info,
++ TADDR_TO_HOST(dllview_info.size))) {
++ return;
++ }
++ /* write new header */
++ mhdr.first_module_size = hndl->dm.dbsiz;
++ mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ dllview_info = DLLVIEW_INFO_INIT;
++ if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(u16))) {
++ return;
++ }
++ /* Add the module handle to this processor's list
++ of handles with debug info */
++ hndl->dm.hnext = mlist->hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl;
++ hndl->dm.hprev = (struct my_handle *) mlist;
++ mlist->hnext = hndl; /* insert after root*/
++} /* init_module_handle */
++
++/*************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ ************************************************************************/
++int Dynamic_Unload_Module(DLOAD_mhandle mhandle,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init)
++{
++ s16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ struct dbg_mirror_root *root;
++ unsigned errcount = 0;
++ struct LDR_SECTION_INFO dllview_info = DLLVIEW_INFO_INIT;
++ struct modules_header mhdr;
++
++ hndl = (struct my_handle *)mhandle;
++ if (!hndl)
++ return 0; /* if handle is null, nothing to do */
++ /* Clear out the module symbols
++ * Note that if this is the module that defined MODULES_HEADER
++ (the head of the target debug list)
++ * then this operation will blow away that symbol.
++ It will therefore be impossible for subsequent
++ * operations to add entries to this un-referenceable list.*/
++ if (!syms)
++ return 1;
++ syms->Purge_Symbol_Table(syms, (unsigned) hndl);
++ /* Deallocate target memory for sections */
++ asecs = hndl->secns;
++ if (alloc)
++ for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
++ curr_sect -= 1) {
++ asecs->name = NULL;
++ alloc->Deallocate(alloc, asecs++);
++ }
++ root = hndl->dm.hroot;
++ if (!root) {
++ /* there is a debug list containing this module */
++ goto func_end;
++ }
++ if (!hndl->dm.dbthis) { /* target-side dllview record exists */
++ goto loop_end;
++ }
++ /* Retrieve memory context in which .dllview was allocated */
++ dllview_info.context = hndl->dm.context;
++ if (hndl->dm.hprev == hndl)
++ goto exitunltgt;
++
++ /* target-side dllview record is in list */
++ /* dequeue this record from our GPP-side mirror list */
++ hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
++ /* Update next_module of previous entry in target list
++ * We are using mhdr here as a surrogate for either a
++ struct modules_header or a dll_module */
++ if (hndl->dm.hnext) {
++ mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
++ mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
++ } else {
++ mhdr.first_module = 0;
++ mhdr.first_module_size = 0;
++ }
++ if (!init)
++ goto exitunltgt;
++
++ if (!init->connect(init)) {
++ dload_syms_error(syms, E_ICONNECT);
++ errcount += 1;
++ goto exitunltgt;
++ }
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ /* update change counter */
++ root->changes += 1;
++ if (!init->writemem(init, &(root->changes),
++ root->dbthis + HOST_TO_TADDR
++ (sizeof(mhdr.first_module) +
++ sizeof(mhdr.first_module_size)),
++ &dllview_info,
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ init->release(init);
++exitunltgt:
++ /* release target storage */
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ dllview_info.load_addr = hndl->dm.dbthis;
++ if (alloc)
++ alloc->Deallocate(alloc, &dllview_info);
++ root->refcount -= 1;
++ /* target-side dllview record exists */
++loop_end:
++#ifndef DEBUG_HEADER_IN_LOADER
++ if (root->refcount <= 0) {
++ /* if all references gone, blow off the header */
++ /* our root symbol may be gone due to the Purge above,
++ but if not, do not destroy the root */
++ if (syms->Find_Matching_Symbol
++ (syms, LOADER_DLLVIEW_ROOT) == NULL)
++ syms->Deallocate(syms, root);
++ }
++#endif
++func_end:
++ /* there is a debug list containing this module */
++ syms->Deallocate(syms, mhandle); /* release our storage */
++ return errcount;
++} /* Dynamic_Unload_Module */
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/*************************************************************************
++ * Procedure unpack_name
++ *
++ * Parameters:
++ * soffset Byte offset into the string table
++ *
++ * Effect:
++ * Returns a pointer to the string specified by the offset supplied, or
++ * NULL for error.
++ *
++ ************************************************************************/
++static char *unpack_name(struct dload_state *dlthis, u32 soffset)
++{
++ u8 tmp, *src;
++ char *dst;
++
++ if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
++ dload_error(dlthis, "Bad string table offset " FMT_UI32,
++ soffset);
++ return NULL;
++ }
++ src = (uint_least8_t *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ dst = dlthis->str_temp;
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE);
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++ dlthis->temp_len = dst - dlthis->str_temp;
++ /* squirrel away length including terminating null */
++ return dlthis->str_temp;
++} /* unpack_name */
++#endif
+diff --git a/drivers/dsp/bridge/dynload/dlclasses_hdr.h b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+new file mode 100644
+index 0000000..04f136e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+@@ -0,0 +1,41 @@
++/*
++ * dlclasses_hdr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DLCLASSES_HDR_H
++#define _DLCLASSES_HDR_H
++
++/*****************************************************************************
++ *****************************************************************************
++ *
++ * DLCLASSES_HDR.H
++ *
++ * Sample classes in support of the dynamic loader
++ *
++ * These are just concrete derivations of the virtual ones in dynamic_loader.h
++ * with a few additional interfaces for init, etc.
++ *****************************************************************************
++ *****************************************************************************/
++
++#include <dspbridge/dynamic_loader.h>
++
++#include "DLstream.h"
++#include "DLsymtab.h"
++#include "DLalloc.h"
++#include "DLinit.h"
++
++#endif /* _DLCLASSES_HDR_H */
+diff --git a/drivers/dsp/bridge/dynload/dload_internal.h b/drivers/dsp/bridge/dynload/dload_internal.h
+new file mode 100644
+index 0000000..78f5058
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dload_internal.h
+@@ -0,0 +1,237 @@
++/*
++ * dload_internal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __DLOAD_INTERNAL__
++#define __DLOAD_INTERNAL__
++
++#include <linux/types.h>
++
++/*
++ * Internal state definitions for the dynamic loader
++ */
++
++#define TRUE 1
++#define FALSE 0
++typedef int boolean;
++
++
++/* type used for relocation intermediate results */
++typedef s32 RVALUE;
++
++/* unsigned version of same; must have at least as many bits */
++typedef u32 URVALUE;
++
++/*
++ * Dynamic loader configuration constants
++ */
++/* error issued if input has more sections than this limit */
++#define REASONABLE_SECTION_LIMIT 100
++
++/* (Addressable unit) value used to clear BSS section */
++#define dload_fill_bss 0
++
++/*
++ * Reorder maps explained (?)
++ *
++ * The doff file format defines a 32-bit pattern used to determine the
++ * byte order of an image being read. That value is
++ * BYTE_RESHUFFLE_VALUE == 0x00010203
++ * For purposes of the reorder routine, we would rather have the all-is-OK
++ * for 32-bits pattern be 0x03020100. This first macro makes the
++ * translation from doff file header value to MAP value: */
++#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++/* This translation is made in dload_headers. Thereafter, the all-is-OK
++ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
++ * But sadly, not all bits of the doff file are 32-bit integers.
++ * The notable exceptions are strings and image bits.
++ * Strings obey host byte order: */
++#if defined(_BIG_ENDIAN)
++#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#else
++#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
++#endif
++/* Target bits consist of target AUs (could be bytes, or 16-bits,
++ * or 32-bits) stored as an array in host order. A target order
++ * map is defined by: */
++#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
++#define TARGET_ORDER(cookedmap) (cookedmap)
++#elif TARGET_AU_BITS > 8
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
++#else
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#endif
++
++/* forward declaration for handle returned by dynamic loader */
++struct my_handle;
++
++/*
++ * a list of module handles, which mirrors the debug list on the target
++ */
++struct dbg_mirror_root {
++ /* must be same as dbg_mirror_list; __DLModules address on target */
++ u32 dbthis;
++ struct my_handle *hnext; /* must be same as dbg_mirror_list */
++ u16 changes; /* change counter */
++ u16 refcount; /* number of modules referencing this root */
++} ;
++
++struct dbg_mirror_list {
++ u32 dbthis;
++ struct my_handle *hnext, *hprev;
++ struct dbg_mirror_root *hroot;
++ u16 dbsiz;
++ u32 context; /* Save context for .dllview memory allocation */
++} ;
++
++#define VARIABLE_SIZE 1
++/*
++ * the structure we actually return as an opaque module handle
++ */
++struct my_handle {
++ struct dbg_mirror_list dm; /* !!! must be first !!! */
++ /* sections following << 1, LSB is set for big-endian target */
++ u16 secn_count;
++ struct LDR_SECTION_INFO secns[VARIABLE_SIZE];
++} ;
++#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
++ sizeof(struct LDR_SECTION_INFO))
++/* real size of my_handle */
++
++/*
++ * reduced symbol structure used for symbols during relocation
++ */
++struct Local_Symbol {
++ s32 value; /* Relocated symbol value */
++ s32 delta; /* Original value in input file */
++ s16 secnn; /* section number */
++ s16 sclass; /* symbol class */
++} ;
++
++/*
++ * States of the .cinit state machine
++ */
++enum cinit_mode {
++ CI_count = 0, /* expecting a count */
++ CI_address, /* expecting an address */
++#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
++ CI_partaddress, /* have only part of the address */
++#endif
++ CI_copy, /* in the middle of copying data */
++ CI_done /* end of .cinit table */
++};
++
++/*
++ * The internal state of the dynamic loader, which is passed around as
++ * an object
++ */
++struct dload_state {
++ struct Dynamic_Loader_Stream *strm; /* The module input stream */
++ struct Dynamic_Loader_Sym *mysym; /* Symbols for this session */
++ struct Dynamic_Loader_Allocate *myalloc; /* target memory allocator */
++ struct Dynamic_Loader_Initialize *myio; /* target memory initializer */
++ unsigned myoptions; /* Options parameter Dynamic_Load_Module */
++
++ char *str_head; /* Pointer to string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ char *str_temp; /* Pointer to temporary buffer for strings */
++ /* big enough to hold longest string */
++ unsigned temp_len; /* length of last temporary string */
++ char *xstrings; /* Pointer to buffer for expanded */
++ /* strings for sec names */
++#endif
++ /* Total size of strings for DLLView section names */
++ unsigned debug_string_size;
++ /* Pointer to parallel section info for allocated sections only */
++ struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
++ struct LDR_SECTION_INFO *ldr_sections;
++#if TMS32060
++ /* The address of the start of the .bss section */
++ LDR_ADDR bss_run_base;
++#endif
++ struct Local_Symbol *local_symtab; /* Relocation symbol table */
++
++ /* pointer to DL section info for the section being relocated */
++ struct LDR_SECTION_INFO *image_secn;
++ /* change in run address for current section during relocation */
++ LDR_ADDR delta_runaddr;
++ LDR_ADDR image_offset; /* offset of current packet in section */
++ enum cinit_mode cinit_state; /* current state of cload_cinit() */
++ int cinit_count; /* the current count */
++ LDR_ADDR cinit_addr; /* the current address */
++ s16 cinit_page; /* the current page */
++ /* Handle to be returned by Dynamic_Load_Module */
++ struct my_handle *myhandle;
++ unsigned dload_errcount; /* Total # of errors reported so far */
++ /* Number of target sections that require allocation and relocation */
++ unsigned allocated_secn_count;
++#ifndef TARGET_ENDIANNESS
++ boolean big_e_target; /* Target data in big-endian format */
++#endif
++ /* map for reordering bytes, 0 if not needed */
++ u32 reorder_map;
++ struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
++ struct doff_verify_rec_t verify; /* Verify record */
++
++ int relstkidx; /* index into relocation value stack */
++ /* relocation value stack used in relexp.c */
++ RVALUE relstk[STATIC_EXPR_STK_SIZE];
++
++} ;
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
++#else
++#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
++#endif
++
++/*
++ * Exports from cload.c to rest of the world
++ */
++extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
++extern void dload_syms_error(struct Dynamic_Loader_Sym *syms,
++ const char *errtxt, ...);
++extern void dload_headers(struct dload_state *dlthis);
++extern void dload_strings(struct dload_state *dlthis, boolean sec_names_only);
++extern void dload_sections(struct dload_state *dlthis);
++extern void dload_reorder(void *data, int dsiz, u32 map);
++extern u32 dload_checksum(void *data, unsigned siz);
++
++#if HOST_ENDIANNESS
++extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++extern uint32_t dload_reverse_checksum_16(void *data, unsigned siz);
++#endif
++#endif
++
++#define is_data_scn(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
++#define is_data_scn_num(zzz) \
++ (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
++
++/*
++ * exported by reloc.c
++ */
++extern void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp);
++
++extern RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++extern int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++#endif /* __DLOAD_INTERNAL__ */
+diff --git a/drivers/dsp/bridge/dynload/doff.h b/drivers/dsp/bridge/dynload/doff.h
+new file mode 100644
+index 0000000..2b8fc37
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/doff.h
+@@ -0,0 +1,347 @@
++/*
++ * doff.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*****************************************************************************/
++/* DOFF.H - Structures & definitions used for dynamically */
++/* loaded modules file format. This format is a reformatted */
++/* version of COFF.(see coff.h for details) It optimizes the */
++/* layout for the dynamic loader. */
++/* */
++/* .dof files, when viewed as a sequence of 32-bit integers, look the same */
++/* on big-endian and little-endian machines. */
++/*****************************************************************************/
++#ifndef _DOFF_H
++#define _DOFF_H
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((u32)zzz)
++#endif
++
++#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
++
++/* DOFF file header containing fields categorizing the remainder of the file */
++struct doff_filehdr_t {
++
++ /* string table size, including filename, in bytes */
++ u32 df_strtab_size;
++
++ /* entry point if one exists */
++ u32 df_entrypt;
++
++ /* identifies byte ordering of file;
++ * always set to BYTE_RESHUFFLE_VALUE */
++ u32 df_byte_reshuffle;
++
++ /* Size of the string table up to and including the last section name */
++ /* Size includes the name of the COFF file also */
++ u32 df_scn_name_size;
++
++#ifndef _BIG_ENDIAN
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* length in bytes of the longest string, including terminating NULL */
++ /* excludes the name of the file */
++ u16 df_max_str_len;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* useful file flags */
++ u16 df_flags;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++#else
++ /* length of the longest string, including terminating NULL */
++ u16 df_max_str_len;
++
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++
++ /* useful file flags */
++ u16 df_flags;
++#endif
++ /* checksum for file header record */
++ u32 df_checksum;
++
++} ;
++
++/* flags in the df_flags field */
++#define DF_LITTLE 0x100
++#define DF_BIG 0x200
++#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
++
++/* Supported processors */
++#define TMS470_ID 0x97
++#define LEAD_ID 0x98
++#define TMS32060_ID 0x99
++#define LEAD3_ID 0x9c
++
++/* Primary processor for loading */
++#if TMS32060
++#define TARGET_ID TMS32060_ID
++#endif
++
++/* Verification record containing values used to test integrity of the bits */
++struct doff_verify_rec_t {
++
++ /* time and date stamp */
++ u32 dv_timdat;
++
++ /* checksum for all section records */
++ u32 dv_scn_rec_checksum;
++
++ /* checksum for string table */
++ u32 dv_str_tab_checksum;
++
++ /* checksum for symbol table */
++ u32 dv_sym_tab_checksum;
++
++ /* checksum for verification record */
++ u32 dv_verify_rec_checksum;
++
++} ;
++
++/* String table is an array of null-terminated strings. The first entry is
++ * the filename, which is added by DLLcreate. No new structure definitions
++ * are required.
++ */
++
++/* Section Records including information on the corresponding image packets */
++/*
++ * !!WARNING!!
++ *
++ * This structure is expected to match in form LDR_SECTION_INFO in
++ * dynamic_loader.h
++ */
++
++struct doff_scnhdr_t {
++
++ s32 ds_offset; /* offset into string table of name */
++ s32 ds_paddr; /* RUN address, in target AU */
++ s32 ds_vaddr; /* LOAD address, in target AU */
++ s32 ds_size; /* section size, in target AU */
++#ifndef _BIG_ENDIAN
++ u16 ds_page; /* memory page id */
++ u16 ds_flags; /* section flags */
++#else
++ u16 ds_flags; /* section flags */
++ u16 ds_page; /* memory page id */
++#endif
++ u32 ds_first_pkt_offset;
++ /* Absolute byte offset into the file */
++ /* where the first image record resides */
++
++ s32 ds_nipacks; /* number of image packets */
++
++};
++
++/* Symbol table entry */
++struct doff_syment_t {
++
++ s32 dn_offset; /* offset into string table of name */
++ s32 dn_value; /* value of symbol */
++#ifndef _BIG_ENDIAN
++ s16 dn_scnum; /* section number */
++ s16 dn_sclass; /* storage class */
++#else
++ s16 dn_sclass; /* storage class */
++ s16 dn_scnum; /* section number, 1-based */
++#endif
++
++} ;
++
++/* special values for dn_scnum */
++#define DN_UNDEF 0 /* undefined symbol */
++#define DN_ABS (-1) /* value of symbol is absolute */
++/* special values for dn_sclass */
++#define DN_EXT 2
++#define DN_STATLAB 20
++#define DN_EXTLAB 21
++
++/* Default value of image bits in packet */
++/* Configurable by user on the command line */
++#define IMAGE_PACKET_SIZE 1024
++
++/* An image packet contains a chunk of data from a section along with */
++/* information necessary for its processing. */
++struct image_packet_t {
++
++ s32 i_num_relocs; /* number of relocations for */
++ /* this packet */
++
++ s32 i_packet_size; /* number of bytes in array */
++ /* "bits" occupied by */
++ /* valid data. Could be */
++ /* < IMAGE_PACKET_SIZE to */
++ /* prevent splitting a */
++ /* relocation across packets. */
++ /* Last packet of a section */
++ /* will most likely contain */
++ /* < IMAGE_PACKET_SIZE bytes */
++ /* of valid data */
++
++ s32 i_checksum; /* Checksum for image packet */
++ /* and the corresponding */
++ /* relocation records */
++
++ u8 *i_bits; /* Actual data in section */
++
++};
++
++/* The relocation structure definition matches the COFF version. Offsets */
++/* however are relative to the image packet base not the section base. */
++struct reloc_record_t {
++
++ s32 r_vaddr;
++
++ /* expressed in target AUs */
++
++ union {
++ struct {
++#ifndef _BIG_ENDIAN
++ u8 _offset; /* bit offset of rel fld */
++ u8 _fieldsz; /* size of rel fld */
++ u8 _wordsz; /* # bytes containing rel fld */
++ u8 _dum1;
++ u16 _dum2;
++ u16 _type;
++#else
++ unsigned _dum1:8;
++ unsigned _wordsz:8; /* # bytes containing rel fld */
++ unsigned _fieldsz:8; /* size of rel fld */
++ unsigned _offset:8; /* bit offset of rel fld */
++ u16 _type;
++ u16 _dum2;
++#endif
++ } _r_field;
++
++ struct {
++ u32 _spc; /* image packet relative PC */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_spc;
++
++ struct {
++ u32 _uval; /* constant value */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_uval;
++
++ struct {
++ s32 _symndx; /* 32-bit sym tbl index */
++#ifndef _BIG_ENDIAN
++ u16 _disp; /* extra addr encode data */
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _disp; /* extra addr encode data */
++#endif
++ } _r_sym;
++ } _u_reloc;
++
++} ;
++
++/* abbreviations for convenience */
++#ifndef r_type
++#define r_type _u_reloc._r_sym._type
++#define r_uval _u_reloc._r_uval._uval
++#define r_symndx _u_reloc._r_sym._symndx
++#define r_offset _u_reloc._r_field._offset
++#define r_fieldsz _u_reloc._r_field._fieldsz
++#define r_wordsz _u_reloc._r_field._wordsz
++#define r_disp _u_reloc._r_sym._disp
++#endif
++
++/*****************************************************************************/
++/* */
++/* Important DOFF macros used for file processing */
++/* */
++/*****************************************************************************/
++
++/* DOFF Versions */
++#define DOFF0 0
++
++/* Return the address/size >= to addr that is at a 32-bit boundary */
++/* This assumes that a byte is 8 bits */
++#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
++
++/*****************************************************************************/
++/* */
++/* The DOFF section header flags field is laid out as follows: */
++/* */
++/* Bits 0-3 : Section Type */
++/* Bit 4 : Set when section requires target memory to be allocated by DL */
++/* Bit 5 : Set when section requires downloading */
++/* Bits 8-11: Alignment, same as COFF */
++/* */
++/*****************************************************************************/
++
++/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
++
++/* Macros to help processing of sections */
++#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
++
++/* DS_ALLOCATE indicates whether a section needs space on the target */
++#define DS_ALLOCATE_MASK 0x10
++#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
++
++/* DS_DOWNLOAD indicates that the loader needs to copy bits */
++#define DS_DOWNLOAD_MASK 0x20
++#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
++
++/* Section alignment requirement in AUs */
++#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
++
++#endif /* _DOFF_H */
+diff --git a/drivers/dsp/bridge/dynload/getsection.c b/drivers/dsp/bridge/dynload/getsection.c
+new file mode 100644
+index 0000000..78a301a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/getsection.c
+@@ -0,0 +1,412 @@
++/*
++ * getsection.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#include <dspbridge/getsection.h>
++#include "header.h"
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_SEEK[] = { "Set file position to %d failed" };
++static const char E_ISIZ[] = { "Bad image packet size %d" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++static const char E_RELOC[] = { "DLOAD_GetSection unable to read"
++ "sections containing relocation entries"};
++#if BITS_PER_AU > BITS_PER_BYTE
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_STBL[] = { "Bad string table offset " FMT_UI32 };
++#endif
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. These macros
++ * marks the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
++
++/***************************************************************/
++/********************* SUPPORT FUNCTIONS ***********************/
++/***************************************************************/
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/**************************************************************************
++ * Procedure unpack_sec_name
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ * soffset Byte offset into the string table
++ * dst Place to store the expanded string
++ *
++ * Effect:
++ * Stores a string from the string table into the destination, expanding
++ * it in the process. Returns a pointer just past the end of the stored
++ * string on success, or NULL on failure.
++ *
++ *************************************************************************/
++static char *unpack_sec_name(struct dload_state *dlthis,
++ u32 soffset, char *dst)
++{
++ u8 tmp, *src;
++
++ if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
++ dload_error(dlthis, E_STBL, soffset);
++ return NULL;
++ }
++ src = (u8 *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE)
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++
++ return dst;
++}
++
++/**************************************************************************
++ * Procedure expand_sec_names
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Allocates a buffer, unpacks and copies strings from string table into it.
++ * Stores a pointer to the buffer into a state variable.
++ **************************************************************************/
++static void expand_sec_names(struct dload_state *dlthis)
++{
++ char *xstrings, *curr, *next;
++ u32 xsize;
++ u16 sec;
++ struct LDR_SECTION_INFO *shp;
++ /* assume worst-case size requirement */
++ xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
++ xstrings = (char *)dlthis->mysym->Allocate(dlthis->mysym, xsize);
++ if (xstrings == NULL) {
++ dload_error(dlthis, E_ALLOC, xsize);
++ return;
++ }
++ dlthis->xstrings = xstrings;
++ /* For each sec, copy and expand its name */
++ curr = xstrings;
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
++ if (next == NULL)
++ break; /* error */
++ shp->name = curr;
++ curr = next;
++ }
++}
++
++#endif
++
++/***************************************************************/
++/********************* EXPORTED FUNCTIONS **********************/
++/***************************************************************/
++
++/**************************************************************************
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the
++ specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ **************************************************************************/
++DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms)
++{
++ struct dload_state *dlthis; /* internal state for this call */
++ unsigned *dp, sz;
++ u32 sec_start;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ u16 sec;
++#endif
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ if (syms != NULL)
++ dload_syms_error(syms, "Required parameter is NULL");
++
++ return NULL;
++ }
++
++ dlthis = (struct dload_state *)
++ syms->Allocate(syms, sizeof(struct dload_state));
++ if (!dlthis) {
++ /* not enough storage */
++ dload_syms_error(syms, "Can't allocate module info");
++ return NULL;
++ }
++
++ /* clear our internal state */
++ dp = (unsigned *)dlthis;
++ for (sz = sizeof(struct dload_state) / sizeof(unsigned);
++ sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ dlthis->strm = module;
++ dlthis->mysym = syms;
++
++ /* read in the doff image and store in our state variable */
++ dload_headers(dlthis);
++
++ if (!dlthis->dload_errcount)
++ dload_strings(dlthis, true);
++
++ /* skip ahead past the unread portion of the string table */
++ sec_start = sizeof(struct doff_filehdr_t) +
++ sizeof(struct doff_verify_rec_t) +
++ BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
++
++ if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
++ dload_error(dlthis, E_SEEK, sec_start);
++ return NULL;
++ }
++
++ if (!dlthis->dload_errcount)
++ dload_sections(dlthis);
++
++ if (dlthis->dload_errcount) {
++ DLOAD_module_close(dlthis); /* errors, blow off our state */
++ dlthis = NULL;
++ return NULL;
++ }
++#if BITS_PER_AU > BITS_PER_BYTE
++ /* Expand all section names from the string table into the */
++ /* state variable, and convert section names from a relative */
++ /* string table offset to a pointers to the expanded string. */
++ expand_sec_names(dlthis);
++#else
++ /* Convert section names from a relative string table offset */
++ /* to a pointer into the string table. */
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ struct LDR_SECTION_INFO *shp =
++ DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ shp->name = dlthis->str_head + *(u32 *)&shp->name;
++ }
++#endif
++
++ return dlthis;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be
++ * initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and initializes
++ * the provided struct LDR_SECTION_INFO pointer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSectionInfo(DLOAD_module_info minfo, const char *sectionName,
++ const struct LDR_SECTION_INFO **const sectionInfo)
++{
++ struct dload_state *dlthis;
++ struct LDR_SECTION_INFO *shp;
++ u16 sec;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ if (strcmp(sectionName, shp->name) == 0) {
++ *sectionInfo = shp;
++ return true;
++ }
++ }
++
++ return false;
++}
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++
++/**************************************************************************
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired
++ * section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo, void *sectionData)
++{
++ struct dload_state *dlthis;
++ u32 pos;
++ struct doff_scnhdr_t *sptr = NULL;
++ s32 nip;
++ struct image_packet_t ipacket;
++ s32 ipsize;
++ u32 checks;
++ s8 *dest = (s8 *)sectionData;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++ sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
++ if (sptr == NULL)
++ return false;
++
++ /* skip ahead to the start of the first packet */
++ pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
++ if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
++ dload_error(dlthis, E_SEEK, pos);
++ return false;
++ }
++
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* for each packet */
++ /* get the fixed header bits */
++ if (dlthis->strm->
++ read_buffer(dlthis->strm, &ipacket, IPH_SIZE) != IPH_SIZE) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
++
++ /* Now read the packet image bits. Note: round the size up to
++ * the next multiple of 4 bytes; this is what checksum
++ * routines want. */
++ ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ dload_error(dlthis, E_ISIZ, ipsize);
++ return false;
++ }
++ if (dlthis->strm->read_buffer
++ (dlthis->strm, dest, ipsize) != ipsize) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map)
++ dload_reorder(dest, ipsize, dlthis->reorder_map);
++
++ checks = dload_checksum(dest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order, not PC order */
++ dload_reorder(dest, ipsize,
++ TARGET_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(dest, ipsize);
++#else
++ checks = dload_reverse_checksum(dest, ipsize);
++#endif
++#endif
++ checks += dload_checksum(&ipacket, IPH_SIZE);
++
++ /* NYI: unable to handle relocation entries here. Reloc
++ * entries referring to fields that span the packet boundaries
++ * may result in packets of sizes that are not multiple of
++ * 4 bytes. Our checksum implementation works on 32-bit words
++ * only. */
++ if (ipacket.i_num_relocs != 0) {
++ dload_error(dlthis, E_RELOC, ipsize);
++ return false;
++ }
++
++ if (~checks) {
++ dload_error(dlthis, E_CHECKSUM, "image packet");
++ return false;
++ }
++
++ /*Advance destination ptr by the size of the just-read packet*/
++ dest += ipsize;
++ }
++
++ return true;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ **************************************************************************/
++void DLOAD_module_close(DLOAD_module_info minfo)
++{
++ struct dload_state *dlthis;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return;
++
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++ if (dlthis->sect_hdrs)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->sect_hdrs);
++
++#if BITS_PER_AU > BITS_PER_BYTE
++ if (dlthis->xstrings)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->xstrings);
++
++#endif
++
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis);
++}
+diff --git a/drivers/dsp/bridge/dynload/header.h b/drivers/dsp/bridge/dynload/header.h
+new file mode 100644
+index 0000000..0de744b
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/header.h
+@@ -0,0 +1,59 @@
++/*
++ * header.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#define TRUE 1
++#define FALSE 0
++#ifndef NULL
++#define NULL 0
++#endif
++
++#include <linux/string.h>
++#define DL_STRCMP strcmp
++
++/* maximum parenthesis nesting in relocation stack expressions */
++#define STATIC_EXPR_STK_SIZE 10
++
++#include <linux/types.h>
++typedef unsigned int uint_least32_t;
++typedef unsigned short int uint_least16_t;
++
++#include "doff.h"
++#include <dspbridge/dynamic_loader.h>
++#include "params.h"
++#include "dload_internal.h"
++#include "reloc_table.h"
++
++/*
++ * Plausibility limits
++ *
++ * These limits are imposed upon the input DOFF file as a check for validity.
++ * They are hard limits, in that the load will fail if they are exceeded.
++ * The numbers selected are arbitrary, in that the loader implementation does
++ * not require these limits.
++ */
++
++/* maximum number of bytes in string table */
++#define MAX_REASONABLE_STRINGTAB (0x100000)
++/* maximum number of code,data,etc. sections */
++#define MAX_REASONABLE_SECTIONS (200)
++/* maximum number of linker symbols */
++#define MAX_REASONABLE_SYMBOLS (100000)
++
++/* shift count to align F_BIG with DLOAD_LITTLE */
++#define ALIGN_COFF_ENDIANNESS 7
++#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
+diff --git a/drivers/dsp/bridge/dynload/module_list.h b/drivers/dsp/bridge/dynload/module_list.h
+new file mode 100644
+index 0000000..9c4876a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/module_list.h
+@@ -0,0 +1,161 @@
++/*
++ * dspbridge/mpu_driver/src/dynload/module_list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*============================================================================
++ Filename: module_list.h
++
++ Copyright (C) 2002 Texas Instruments Incorporated
++
++
++ This C header file gives the layout of the data structure created by the
++ dynamic loader to describe the set of modules loaded into the DSP.
++
++ Linked List Structure:
++ ----------------------
++ The data structure defined here is a singly-linked list. The list
++ represents the set of modules which are currently loaded in the DSP memory.
++ The first entry in the list is a header record which contains a flag
++ representing the state of the list. The rest of the entries in the list
++ are module records.
++
++ Global symbol _DLModules designates the first record in the list (i.e. the
++ header record). This symbol must be defined in any program that wishes to
++ use DLLview plug-in.
++
++ String Representation:
++ ----------------------
++ The string names of the module and its sections are stored in a block of
++ memory which follows the module record itself. The strings are ordered:
++ module name first, followed by section names in order from the first
++ section to the last. String names are tightly packed arrays of 8-bit
++ characters (two characters per 16-bit word on the C55x). Strings are
++ zero-byte-terminated.
++
++ Creating and updating the list:
++-------------------------------
++ Upon loading a new module into the DSP memory the dynamic loader inserts a
++new module record as the first module record in the list. The fields of
++ this module record are initialized to reflect the properties of the module.
++ The dynamic loader does NOT increment the flag/counter in the list's header
++ record.
++
++ Upon unloading a module from the DSP memory the dynamic loader removes the
++module's record from this list. The dynamic loader also increments the
++ flag/counter in the list's header record to indicate that the list has been
++ changed.
++
++============================================================================*/
++
++#ifndef _MODULE_LIST_H_
++#define _MODULE_LIST_H_
++
++#include <linux/types.h>
++
++/* Global pointer to the modules_header structure*/
++#define MODULES_HEADER "_DLModules"
++#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
++
++/* Initial version number*/
++#define INIT_VERSION 1
++
++/* Verification number -- to be recorded in each module record */
++#define VERIFICATION 0x79
++
++/* forward declarations */
++struct dll_module;
++struct dll_sect;
++
++/* the first entry in the list is the modules_header record;
++ * its address is contained in the global _DLModules pointer */
++struct modules_header {
++
++ /* Address of the first dll_module record in the list or NULL.
++ Note: for C55x this is a word address (C55x data is word-addressable)*/
++ u32 first_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this header record, or zero
++ * if the list is empty. This size includes the module's string table.
++ * Note: for C55x the unit is a 16-bit word */
++ u16 first_module_size;
++
++ /* Counter is incremented whenever a module record is removed from
++ * the list */
++ u16 update_flag;
++
++} ;
++
++/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define MODULES_HEADER_BITMAP 0x2 /* swapping bitmap for type modules_header */
++
++/* information recorded about each section in a module */
++struct dll_sect {
++
++ /* Load-time address of the section.
++ * Note: for C55x this is a byte address for program sections, and
++ * a word address for data sections. C55x program memory is
++ * byte-addressable, while data memory is word-addressable. */
++ u32 sect_load_adr;
++
++ /* Run-time address of the section.
++ * Note 1: for C55x this is a byte address for program sections, and
++ * a word address for data sections.
++ * Note 2: for C55x two most significant bits of this field indicate
++ * the section type: '00' for a code section, '11' for a data section
++ * (C55 addresses are really only 24-bits wide). */
++ u32 sect_run_adr;
++
++} ;
++
++/* the rest of the entries in the list are module records */
++struct dll_module {
++
++ /* Address of the next dll_module record in the list, or 0 if this is
++ * the last record in the list.
++ * Note: for C55x this is a word address (C55x data is
++ * word-addressable) */
++ u32 next_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this one, or zero if this is the
++ * last record in the list. This size includes the module's string
++ * table.
++ * Note: for C55x the unit is a 16-bit word. */
++ u16 next_module_size;
++
++ /* version number of the tooling; set to INIT_VERSION for Phase 1 */
++ u16 version;
++
++ /* the verification word; set to VERIFICATION */
++ u16 verification;
++
++ /* Number of sections in the sects array */
++ u16 num_sects;
++
++ /* Module's "unique" id; copy of the timestamp from the host
++ * COFF file */
++ u32 timestamp;
++
++ /* Array of num_sects elements of the module's section records */
++ struct dll_sect sects[1];
++} ;
++
++/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
++
++#endif /* _MODULE_LIST_H_ */
+diff --git a/drivers/dsp/bridge/dynload/params.h b/drivers/dsp/bridge/dynload/params.h
+new file mode 100644
+index 0000000..ade430d
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/params.h
+@@ -0,0 +1,231 @@
++/*
++ * params.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++/******************************************************************************
++ *
++ * This file defines host and target properties for all machines
++ * supported by the dynamic loader. To be tedious...
++ *
++ * host == the machine on which the dynamic loader runs
++ * target == the machine that the dynamic loader is loading
++ *
++ * Host and target may or may not be the same, depending upon the particular
++ * use.
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ * Host Properties
++ *
++ *****************************************************************************/
++
++#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
++#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
++#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
++
++#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
++#define BITS_PER_AU 16
++#define LOG_BITS_PER_AU 4
++ /* use this print string in error messages for uint32_t */
++#define FMT_UI32 "0x%lx"
++#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
++#else
++#define BITS_PER_AU 8 /* bits in the smallest addressable data storage unit */
++#define LOG_BITS_PER_AU 3 /* log base 2 of the same; useful for shift counts */
++#define FMT_UI32 "0x%x"
++#define FMT8_UI32 "%08x"
++#endif
++
++/* generic fastest method for swapping bytes and shorts */
++#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
++#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
++
++/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
++
++/******************************************************************************
++ *
++ * Target Properties
++ *
++ *****************************************************************************/
++
++
++/*--------------------------------------------------------------------------*/
++/* TMS320C6x Target Specific Parameters (byte-addressable) */
++/*--------------------------------------------------------------------------*/
++#if TMS32060
++#define MEMORG 0x0L /* Size of configured memory */
++#define MEMSIZE 0x0L /* (full address space) */
++
++#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
++#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
++#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
++#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
++ * are page number */
++
++#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
++
++#undef TARGET_ENDIANNESS /* may be big or little endian */
++
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
++#endif
++
++
++/*--------------------------------------------------------------------------
++ *
++ * DEFAULT SETTINGS and DERIVED PROPERTIES
++ *
++ * This section establishes defaults for values not specified above
++ *--------------------------------------------------------------------------*/
++#ifndef TARGET_AU_BITS
++#define TARGET_AU_BITS 8 /* width of the target addressable unit */
++#define LOG_TARGET_AU_BITS 3 /* log2 of same */
++#endif
++
++#ifndef CINIT_DEFAULT_PAGE
++#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
++#endif
++
++#ifndef DATA_RUN2LOAD
++#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
++#endif
++
++#ifndef DBG_LIST_PAGE
++#define DBG_LIST_PAGE 0 /* page number for .dllview section */
++#endif
++
++#ifndef TARGET_WORD_ALIGN
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (zz)
++#endif
++
++#ifndef TDATA_TO_TADDR
++#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
++#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
++#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
++#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
++#endif
++
++/*
++ *
++ * Useful properties and conversions derived from the above
++ *
++ */
++
++/*
++ * Conversions between host and target addresses
++ */
++#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
++/* translate target addressable unit to host address */
++#define TADDR_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TADDR(x) (x)
++#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
++#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#else
++#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#endif
++
++#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
++/* translate target addressable unit to host address */
++#define TDATA_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TDATA(x) (x)
++/* translate host address to target addressable unit, round up */
++#define HOST_TO_TDATA_ROUND(x) (x)
++/* byte offset to host offset, rounded up for TDATA size */
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
++#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#else
++#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA_ROUND(x) (((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
++ (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
++ -(TDATA_AU_BITS/BITS_PER_AU))
++#endif
++
++/*
++ * Input in DOFF format is always expresed in bytes, regardless of loading host
++ * so we wind up converting from bytes to target and host units even when the
++ * host is not a byte machine.
++ */
++#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) (x)
++#define BYTE_TO_HOST_ROUND(x) (x)
++#define HOST_TO_BYTE(x) (x)
++#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
++ (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
++/* translate target addressable unit to byte address */
++#define TADDR_TO_BYTE(x) (x)
++/* translate byte address to target addressable unit */
++#define BYTE_TO_TADDR(x) (x)
++#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
++#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#ifdef _BIG_ENDIAN
++#define HOST_ENDIANNESS 1
++#else
++#define HOST_ENDIANNESS 0
++#endif
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
++#elif HOST_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
++#else
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
++#endif
++
++/* the unit in which we process target image data */
++#if TARGET_AU_BITS <= 8
++typedef u8 TgtAU_t;
++#elif TARGET_AU_BITS <= 16
++typedef u16 TgtAU_t;
++#else
++typedef u32 TgtAU_t;
++#endif
++
++/* size of that unit */
++#if TARGET_AU_BITS < BITS_PER_AU
++#define TGTAU_BITS BITS_PER_AU
++#define LOG_TGTAU_BITS LOG_BITS_PER_AU
++#else
++#define TGTAU_BITS TARGET_AU_BITS
++#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
++#endif
+diff --git a/drivers/dsp/bridge/dynload/reloc.c b/drivers/dsp/bridge/dynload/reloc.c
+new file mode 100644
+index 0000000..54e460e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc.c
+@@ -0,0 +1,425 @@
++/*
++ * reloc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#if TMS32060
++/* the magic symbol for the start of BSS */
++static const char BSSSYMBOL[] = {".bss"};
++#endif
++
++#if TMS32060
++#include "reloc_table_c6000.c"
++#endif
++
++#if TMS32060
++/* From coff.h - ignore these relocation operations */
++#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
++#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
++#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
++#endif
++
++/**************************************************************************
++ * Procedure dload_unpack
++ *
++ * Parameters:
++ * data pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Extracts the specified field and returns it.
++ **************************************************************************/
++RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data, int fieldsz,
++ int offset, unsigned sgn)
++{
++ register RVALUE objval;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value*/
++ /* * collect up enough bits to contain the desired field */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++ objval = *dp >> offset;
++ shift = TGTAU_BITS - offset;
++ while (shift <= fieldsz) {
++ dp += direction;
++ objval += (RVALUE)*dp << shift;
++ shift += TGTAU_BITS;
++ }
++
++ /* * sign or zero extend the value appropriately */
++ if (sgn == ROP_UNS)
++ objval &= (2 << fieldsz) - 1;
++ else {
++ shift = sizeof(RVALUE) * BITS_PER_AU-1 - fieldsz;
++ objval = (objval << shift) >> shift;
++ }
++
++ return objval;
++
++} /* dload_unpack */
++
++
++/**************************************************************************
++ * Procedure dload_repack
++ *
++ * Parameters:
++ * val Value to insert
++ * data Pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Stuffs the specified value in the specified field. Returns 0 for
++ * success
++ * or 1 if the value will not fit in the specified field according to the
++ * specified signedness rule.
++ **************************************************************************/
++static const unsigned char ovf_limit[] = {1, 2, 2};
++int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn)
++{
++ register URVALUE objval, mask;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
++ /* clip the bits */
++ mask = ((UINT32_C(2) << fieldsz) - 1);
++ objval = (val & mask);
++ /* * store the bits through the specified mask */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++
++ /* insert LSBs */
++ *dp = (*dp & ~(mask << offset)) + (objval << offset);
++ shift = TGTAU_BITS-offset;
++ /* align mask and objval with AU boundary */
++ objval >>= shift;
++ mask >>= shift;
++
++ while (mask) {
++ dp += direction;
++ *dp = (*dp & ~mask) + objval;
++ objval >>= TGTAU_BITS;
++ mask >>= TGTAU_BITS;
++ }
++
++ /*
++ * check for overflow
++ */
++ if (sgn) {
++ unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
++ if (tmp > ovf_limit[sgn-1])
++ return 1;
++ }
++ return 0;
++
++} /* dload_repack */
++
++/* lookup table for the scaling amount in a C6x instruction */
++#if TMS32060
++#define SCALE_BITS 4 /* there are 4 bits in the scale field */
++#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
++static const u8 C60_Scale[SCALE_MASK+1] = {
++ 1, 0, 0, 0, 1, 1, 2, 2
++};
++#endif
++
++/**************************************************************************
++ * Procedure dload_relocate
++ *
++ * Parameters:
++ * data Pointer to base of image data
++ * rp Pointer to relocation operation
++ *
++ * Effect:
++ * Performs the specified relocation operation
++ **************************************************************************/
++void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp)
++{
++ RVALUE val = 0;
++ RVALUE reloc_amt = 0;
++ unsigned int fieldsz = 0;
++ unsigned int offset = 0;
++ unsigned int reloc_info = 0;
++ unsigned int reloc_action = 0;
++ register int rx = 0;
++ RVALUE *stackp = NULL;
++ int top;
++ struct Local_Symbol *svp = NULL;
++#ifdef RFV_SCALE
++ unsigned int scale = 0;
++#endif
++
++ rx = HASH_FUNC(rp->r_type);
++ while (rop_map1[rx] != rp->r_type) {
++ rx = HASH_L(rop_map2[rx]);
++ if (rx < 0) {
++#if TMS32060
++ switch (rp->r_type) {
++ case R_C60ALIGN:
++ case R_C60NOCMP:
++ case R_C60FPHEAD:
++ /* Ignore these reloc types and return */
++ break;
++ default:
++ /* Unknown reloc type, print error and return */
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++ }
++#else
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++#endif
++ return;
++ }
++ }
++ rx = HASH_I(rop_map2[rx]);
++ if ((rx < (sizeof(rop_action)/sizeof(uint_least16_t)))
++ && (rx < (sizeof(rop_info)/sizeof(uint_least16_t))) && (rx > 0)) {
++ reloc_action = rop_action[rx]; reloc_info = rop_info[rx];
++ } else {
++ dload_error(dlthis, "Buffer Overflow - Array Index Out of Bounds");
++ }
++
++ /* Compute the relocation amount for the referenced symbol, if any */
++ reloc_amt = rp->r_uval;
++ if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
++ if ((u32)rp->r_symndx < dlthis->dfile_hdr.df_no_syms) {
++ /* real symbol reference */
++ svp = &dlthis->local_symtab[rp->r_symndx];
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ svp->delta : svp->value;
++ }
++ /* reloc references current section */
++ else if (rp->r_symndx == -1)
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ dlthis->delta_runaddr : dlthis->image_secn->run_addr;
++ } /* relocation uses a symbol reference */
++ /* Handle stack adjustment */
++ val = 0;
++ top = RFV_STK(reloc_info);
++ if (top) {
++ top += dlthis->relstkidx - RSTK_UOP;
++ if (top >= STATIC_EXPR_STK_SIZE) {
++ dload_error(dlthis,
++ "Expression stack overflow in %s at offset "
++ FMT_UI32, dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ return;
++ }
++ val = dlthis->relstk[dlthis->relstkidx];
++ dlthis->relstkidx = top;
++ stackp = &dlthis->relstk[top];
++ }
++ /* Derive field position and size, if we need them */
++ if (reloc_info & ROP_RW) { /* read or write action in our future */
++ fieldsz = RFV_WIDTH(reloc_action);
++ if (fieldsz) { /* field info from table */
++ offset = RFV_POSN(reloc_action);
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ * address containing bits */
++ rp->r_vaddr += RFV_BIGOFF(reloc_info);
++ } else { /* field info from relocation op */
++ fieldsz = rp->r_fieldsz; offset = rp->r_offset;
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ address containing bits */
++ rp->r_vaddr += (rp->r_wordsz - offset - fieldsz)
++ >> LOG_TARGET_AU_BITS;
++ }
++ data = (TgtAU_t *)((char *)data + TADDR_TO_HOST(rp->r_vaddr));
++ /* compute lowest host location of referenced data */
++#if BITS_PER_AU > TARGET_AU_BITS
++ /* conversion from target address to host address may lose
++ address bits; add loss to offset */
++ if (TARGET_BIG_ENDIAN) {
++ offset += -((rp->r_vaddr << LOG_TARGET_AU_BITS) +
++ offset + fieldsz) &
++ (BITS_PER_AU-TARGET_AU_BITS);
++ } else {
++ offset += (rp->r_vaddr << LOG_TARGET_AU_BITS) &
++ (BITS_PER_AU-1);
++ }
++#endif
++#ifdef RFV_SCALE
++ scale = RFV_SCALE(reloc_info);
++#endif
++ }
++ /* read the object value from the current image, if so ordered */
++ if (reloc_info & ROP_R) { /* relocation reads current image value */
++ val = dload_unpack(dlthis, data, fieldsz, offset,
++ RFV_SIGN(reloc_info));
++#ifdef RFV_SCALE
++ val <<= scale;
++#endif
++ }
++ /* perform the necessary arithmetic */
++ switch (RFV_ACTION(reloc_action)) { /* relocation actions */
++ case RACT_VAL:
++ break;
++ case RACT_ASGN:
++ val = reloc_amt;
++ break;
++ case RACT_ADD:
++ val += reloc_amt;
++ break;
++ case RACT_PCR:
++ /*-----------------------------------------------------------
++ * Handle special cases of jumping from absolute sections
++ * (special reloc type) or to absolute destination
++ * (symndx == -1). In either case, set the appropriate
++ * relocation amount to 0.
++ *-----------------------------------------------------------*/
++ if (rp->r_symndx == -1)
++ reloc_amt = 0;
++ val += reloc_amt - dlthis->delta_runaddr;
++ break;
++ case RACT_ADDISP:
++ val += rp->r_disp + reloc_amt;
++ break;
++ case RACT_ASGPC:
++ val = dlthis->image_secn->run_addr + reloc_amt;
++ break;
++ case RACT_PLUS:
++ if (stackp != NULL)
++ val += *stackp;
++ break;
++ case RACT_SUB:
++ if (stackp != NULL)
++ val = *stackp - val;
++ break;
++ case RACT_NEG:
++ val = -val;
++ break;
++ case RACT_MPY:
++ if (stackp != NULL)
++ val *= *stackp;
++ break;
++ case RACT_DIV:
++ if (stackp != NULL)
++ val = *stackp / val;
++ break;
++ case RACT_MOD:
++ if (stackp != NULL)
++ val = *stackp % val;
++ break;
++ case RACT_SR:
++ if (val >= sizeof(RVALUE) * BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = (URVALUE)*stackp >> val;
++ break;
++ case RACT_ASR:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = sizeof(RVALUE)*BITS_PER_AU - 1;
++ else if (stackp != NULL)
++ val = *stackp >> val;
++ break;
++ case RACT_SL:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = *stackp << val;
++ break;
++ case RACT_AND:
++ if (stackp != NULL)
++ val &= *stackp;
++ break;
++ case RACT_OR:
++ if (stackp != NULL)
++ val |= *stackp;
++ break;
++ case RACT_XOR:
++ if (stackp != NULL)
++ val ^= *stackp;
++ break;
++ case RACT_NOT:
++ val = ~val;
++ break;
++#if TMS32060
++ case RACT_C6SECT:
++ /* actually needed address of secn containing symbol */
++ if (svp != NULL) {
++ if (rp->r_symndx >= 0)
++ if (svp->secnn > 0)
++ reloc_amt = dlthis->ldr_sections
++ [svp->secnn-1].run_addr;
++ }
++ /* !!! FALL THRU !!! */
++ case RACT_C6BASE:
++ if (dlthis->bss_run_base == 0) {
++ struct dynload_symbol *symp;
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, BSSSYMBOL);
++ /* lookup value of global BSS base */
++ if (symp)
++ dlthis->bss_run_base = symp->value;
++ else
++ dload_error(dlthis,
++ "Global BSS base referenced in %s offset"\
++ FMT_UI32 " but not defined",
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ }
++ reloc_amt -= dlthis->bss_run_base;
++ /* !!! FALL THRU !!! */
++ case RACT_C6DSPL:
++ /* scale factor determined by 3 LSBs of field */
++ scale = C60_Scale[val & SCALE_MASK];
++ offset += SCALE_BITS;
++ fieldsz -= SCALE_BITS;
++ val >>= SCALE_BITS; /* ignore the scale field hereafter */
++ val <<= scale;
++ val += reloc_amt; /* do the usual relocation */
++ if (((1 << scale)-1) & val)
++ dload_error(dlthis,
++ "Unaligned reference in %s offset " FMT_UI32,
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ break;
++#endif
++ } /* relocation actions */
++ /* * Put back result as required */
++ if (reloc_info & ROP_W) { /* relocation writes image value */
++#ifdef RFV_SCALE
++ val >>= scale;
++#endif
++ if (dload_repack(dlthis, val, data, fieldsz, offset,
++ RFV_SIGN(reloc_info))) {
++ dload_error(dlthis, "Relocation value " FMT_UI32
++ " overflows %d bits in %s offset " FMT_UI32, val,
++ fieldsz, dlthis->image_secn->name,
++ dlthis->image_offset + rp->r_vaddr);
++ }
++ } else if (top)
++ *stackp = val;
++} /* reloc_value */
++
+diff --git a/drivers/dsp/bridge/dynload/reloc_table.h b/drivers/dsp/bridge/dynload/reloc_table.h
+new file mode 100644
+index 0000000..6326146
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table.h
+@@ -0,0 +1,102 @@
++/*
++ * reloc_table.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __RELOC_TABLE_H__
++#define __RELOC_TABLE_H__
++/*
++ * Table of relocation operator properties
++ */
++#include <linux/types.h>
++
++/* How does this relocation operation access the program image? */
++#define ROP_N 0 /* does not access image */
++#define ROP_R 1 /* read from image */
++#define ROP_W 2 /* write to image */
++#define ROP_RW 3 /* read from and write to image */
++
++/* For program image access, what are the overflow rules for the bit field? */
++/* Beware! Procedure repack depends on this encoding */
++#define ROP_ANY 0 /* no overflow ever, just truncate the value */
++#define ROP_SGN 1 /* signed field */
++#define ROP_UNS 2 /* unsigned field */
++#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
++
++/* How does the relocation operation use the symbol reference */
++#define ROP_IGN 0 /* no symbol is referenced */
++#define ROP_LIT 0 /* use rp->r_uval literal field */
++#define ROP_SYM 1 /* symbol value is used in relocation */
++#define ROP_SYMD 2 /* delta value vs last link is used */
++
++/* How does the reloc op use the stack? */
++#define RSTK_N 0 /* Does not use */
++#define RSTK_POP 1 /* Does a POP */
++#define RSTK_UOP 2 /* Unary op, stack position unaffected */
++#define RSTK_PSH 3 /* Does a push */
++
++/*
++ * Computational actions performed by the dynamic loader
++ */
++enum Dload_Actions {
++ RACT_VAL, /* don't alter the current val (from stack or mem fetch) */
++ RACT_ASGN, /* set value to reference amount (from symbol reference) */
++ RACT_ADD, /* add reference to value */
++ RACT_PCR, /* add reference minus PC delta to value */
++ RACT_ADDISP, /* add reference plus r_disp */
++ RACT_ASGPC, /* set value to section address plus reference */
++
++ RACT_PLUS, /* stack + */
++ RACT_SUB, /* stack - */
++ RACT_NEG, /* stack unary - */
++
++ RACT_MPY, /* stack * */
++ RACT_DIV, /* stack / */
++ RACT_MOD, /* stack % */
++
++ RACT_SR, /* stack unsigned >> */
++ RACT_ASR, /* stack signed >> */
++ RACT_SL, /* stack << */
++ RACT_AND, /* stack & */
++ RACT_OR, /* stack | */
++ RACT_XOR, /* stack ^ */
++ RACT_NOT, /* stack ~ */
++ RACT_C6SECT, /* for C60 R_SECT op */
++ RACT_C6BASE, /* for C60 R_BASE op */
++ RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
++ RACT_PCR23T /* for ARM Thumb long branch */
++};
++
++/*
++ * macros used to extract values
++ */
++#define RFV_POSN(aaa) ((aaa) & 0xF)
++#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
++#define RFV_ACTION(aaa) ((aaa) >> 10)
++
++#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
++#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
++#define RFV_STK(iii) (((iii) >> 6) & 0x3)
++#define RFV_ACCS(iii) ((iii) & 0x3)
++
++#if (TMS32060)
++#define RFV_SCALE(iii) ((iii) >> 11)
++#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
++#else
++#define RFV_BIGOFF(iii) ((iii) >> 8)
++#endif
++
++#endif /* __RELOC_TABLE_H__ */
+diff --git a/drivers/dsp/bridge/dynload/reloc_table_c6000.c b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+new file mode 100644
+index 0000000..978834c
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+@@ -0,0 +1,258 @@
++/*
++ * reloc_table_c6000.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/* Tables generated for c6000 */
++
++#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
++#define HASH_L(zz) ((zz) >> 8)
++#define HASH_I(zz) ((zz) & 0xFF)
++
++static const u16 rop_map1[] = {
++ 0,
++ 1,
++ 2,
++ 20,
++ 4,
++ 5,
++ 6,
++ 15,
++ 80,
++ 81,
++ 82,
++ 83,
++ 84,
++ 85,
++ 86,
++ 87,
++ 17,
++ 18,
++ 19,
++ 21,
++ 16,
++ 16394,
++ 16404,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 32,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 40,
++ 112,
++ 113,
++ 65535,
++ 16384,
++ 16385,
++ 16386,
++ 16387,
++ 16388,
++ 16389,
++ 16390,
++ 16391,
++ 16392,
++ 16393,
++ 16395,
++ 16396,
++ 16397,
++ 16398,
++ 16399,
++ 16400,
++ 16401,
++ 16402,
++ 16403,
++ 16405,
++ 16406,
++ 65535,
++ 65535,
++ 65535
++};
++
++static const s16 rop_map2[] = {
++ -256,
++ -255,
++ -254,
++ -245,
++ -253,
++ -252,
++ -251,
++ -250,
++ -241,
++ -240,
++ -239,
++ -238,
++ -237,
++ -236,
++ 1813,
++ 5142,
++ -248,
++ -247,
++ 778,
++ -244,
++ -249,
++ -221,
++ -211,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -243,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -242,
++ -233,
++ -232,
++ -1,
++ -231,
++ -230,
++ -229,
++ -228,
++ -227,
++ -226,
++ -225,
++ -224,
++ -223,
++ 5410,
++ -220,
++ -219,
++ -218,
++ -217,
++ -216,
++ -215,
++ -214,
++ -213,
++ 5676,
++ -210,
++ -209,
++ -1,
++ -1,
++ -1
++};
++
++static const u16 rop_action[] = {
++ 2560,
++ 2304,
++ 2304,
++ 2432,
++ 2432,
++ 2560,
++ 2176,
++ 2304,
++ 2560,
++ 3200,
++ 3328,
++ 3584,
++ 3456,
++ 2304,
++ 4208,
++ 20788,
++ 21812,
++ 3415,
++ 3245,
++ 2311,
++ 4359,
++ 19764,
++ 2311,
++ 3191,
++ 3280,
++ 6656,
++ 7680,
++ 8704,
++ 9728,
++ 10752,
++ 11776,
++ 12800,
++ 13824,
++ 14848,
++ 15872,
++ 16896,
++ 17920,
++ 18944,
++ 0,
++ 0,
++ 0,
++ 0,
++ 1536,
++ 1536,
++ 1536,
++ 5632,
++ 512,
++ 0
++};
++
++static const u16 rop_info[] = {
++ 0,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 39,
++ 39,
++ 39,
++ 39,
++ 35,
++ 34,
++ 283,
++ 299,
++ 4135,
++ 4391,
++ 291,
++ 33059,
++ 283,
++ 295,
++ 4647,
++ 4135,
++ 64,
++ 64,
++ 128,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 128,
++ 201,
++ 197,
++ 74,
++ 70,
++ 208,
++ 196,
++ 200,
++ 192,
++ 192,
++ 66
++};
+diff --git a/drivers/dsp/bridge/gen/_gt_para.c b/drivers/dsp/bridge/gen/_gt_para.c
+new file mode 100644
+index 0000000..181fe41
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/_gt_para.c
+@@ -0,0 +1,107 @@
++/*
++ * _gt_para.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _gt_para.c ========
++ * Description:
++ * Configuration parameters for GT. This file is separated from
++ * gt.c so that GT_assert() can reference the error function without
++ * forcing the linker to include all the code for GT_set(), GT_init(),
++ * etc. into a fully bound image. Thus, GT_assert() can be retained in
++ * a program for which GT_?trace() has been compiled out.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 03-Jul-2001 rr: Removed kfuncs.h because of build errors.
++ *! 07-Dec-1999 ag: Fxn error now causes a WinCE DebugBreak;
++ *! 30-Aug-1999 ag: Now uses GP_printf for printf and error.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Function Prototypes */
++static void error(char *msg, ...);
++static s32 GT_nop(void);
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++struct GT_Config _GT_params = {
++ (Fxn) printk, /* printf */
++ (Fxn) NULL, /* procid */
++ (Fxn) GT_nop, /* taskid */
++ (Fxn) error, /* error */
++};
++
++/* ----------------------------------- Globals */
++struct GT_Config *GT = &_GT_params;
++
++/*
++ * ======== GT_nop ========
++ */
++static s32 GT_nop(void)
++{
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints error onto the standard output.
++ */
++static void error(char *fmt, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++
++ va_list va;
++
++ va_start(va, fmt);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ printk("ERROR: ");
++ printk(fmt, arg1, arg2, arg3, arg4, arg5, arg6);
++
++#if defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)
++ if (in_interrupt()) {
++ printk(KERN_INFO "Not stopping after error since ISR/DPC "
++ "are disabled\n");
++ } else {
++ set_current_state(TASK_INTERRUPTIBLE);
++ flush_signals(current);
++ schedule();
++ flush_signals(current);
++ printk(KERN_INFO "Signaled in error function\n");
++ }
++#endif
++}
+diff --git a/drivers/dsp/bridge/gen/gb.c b/drivers/dsp/bridge/gen/gb.c
+new file mode 100644
+index 0000000..1d21e97
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gb.c
+@@ -0,0 +1,182 @@
++/*
++ * gb.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gb.c ========
++ * Description: Generic bitmap operations.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 vp Code review updates.
++ *! 17-Dec-2002 map Fixed GB_minset(), GB_empty(), and GB_full(),
++ *! to ensure only 'len' bits are considered in the map
++ *! 18-Oct-2002 sb Ported to Linux platform.
++ *! 06-Dec-2001 jeh Fixed bug in GB_minclear().
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <linux/types.h>
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++#include <dspbridge/gb.h>
++
++typedef GB_BitNum GB_WordNum;
++
++struct GB_TMap {
++ GB_BitNum len;
++ GB_WordNum wcnt;
++ u32 *words;
++};
++
++/*
++ * ======== GB_clear ========
++ * purpose:
++ * Clears a bit in the bit map.
++ */
++
++void GB_clear(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] &= ~mask;
++}
++
++/*
++ * ======== GB_create ========
++ * purpose:
++ * Creates a bit map.
++ */
++
++struct GB_TMap *GB_create(GB_BitNum len)
++{
++ struct GB_TMap *map;
++ GB_WordNum i;
++ map = (struct GB_TMap *)GS_alloc(sizeof(struct GB_TMap));
++ if (map != NULL) {
++ map->len = len;
++ map->wcnt = len / BITS_PER_LONG + 1;
++ map->words = (u32 *)GS_alloc(map->wcnt * sizeof(u32));
++ if (map->words != NULL) {
++ for (i = 0; i < map->wcnt; i++)
++ map->words[i] = 0L;
++
++ } else {
++ GS_frees(map, sizeof(struct GB_TMap));
++ map = NULL;
++ }
++ }
++
++ return map;
++}
++
++/*
++ * ======== GB_delete ========
++ * purpose:
++ * Frees a bit map.
++ */
++
++void GB_delete(struct GB_TMap *map)
++{
++ GS_frees(map->words, map->wcnt * sizeof(u32));
++ GS_frees(map, sizeof(struct GB_TMap));
++}
++
++/*
++ * ======== GB_findandset ========
++ * purpose:
++ * Finds a free bit and sets it.
++ */
++GB_BitNum GB_findandset(struct GB_TMap *map)
++{
++ GB_BitNum bitn;
++
++ bitn = GB_minclear(map);
++
++ if (bitn != GB_NOBITS)
++ GB_set(map, bitn);
++
++ return bitn;
++}
++
++/*
++ * ======== GB_minclear ========
++ * purpose:
++ * returns the location of the first unset bit in the bit map.
++ */
++GB_BitNum GB_minclear(struct GB_TMap *map)
++{
++ GB_BitNum bit_location = 0;
++ GB_BitNum bitAcc = 0;
++ GB_WordNum i;
++ GB_BitNum bit;
++ u32 *word;
++
++ for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
++ if (~*word) {
++ for (bit = 0; bit < BITS_PER_LONG; bit++, bitAcc++) {
++ if (bitAcc == map->len)
++ return GB_NOBITS;
++
++ if (~*word & (1L << bit)) {
++ bit_location = i * BITS_PER_LONG + bit;
++ return bit_location;
++ }
++
++ }
++ } else {
++ bitAcc += BITS_PER_LONG;
++ }
++ }
++
++ return GB_NOBITS;
++}
++
++/*
++ * ======== GB_set ========
++ * purpose:
++ * Sets a bit in the bit map.
++ */
++
++void GB_set(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] |= mask;
++}
++
++/*
++ * ======== GB_test ========
++ * purpose:
++ * Returns true if the bit is set in the specified location.
++ */
++
++bool GB_test(struct GB_TMap *map, GB_BitNum bitn)
++{
++ bool state;
++ u32 mask;
++ u32 word;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ word = map->words[bitn / BITS_PER_LONG];
++ state = word & mask ? TRUE : FALSE;
++
++ return state;
++}
+diff --git a/drivers/dsp/bridge/gen/gh.c b/drivers/dsp/bridge/gen/gh.c
+new file mode 100644
+index 0000000..a20ae16
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gh.c
+@@ -0,0 +1,191 @@
++/*
++ * gh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.c ========
++ */
++
++#include <dspbridge/std.h>
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/gs.h>
++
++#include <dspbridge/gh.h>
++
++struct Elem {
++ struct Elem *next;
++ u8 data[1];
++};
++
++struct GH_THashTab {
++ u16 maxBucket;
++ u16 valSize;
++ struct Elem **buckets;
++ u16(*hash) (void *, u16);
++ bool(*match) (void *, void *);
++ void(*delete) (void *);
++};
++
++static void Nop(void *p);
++static s32 curInit;
++static void myfree(void *ptr, s32 size);
++
++/*
++ * ======== GH_create ========
++ */
++
++struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash)(void *, u16), bool(*match)(void *, void *),
++ void(*delete)(void *))
++{
++ struct GH_THashTab *hashTab;
++ u16 i;
++ hashTab = (struct GH_THashTab *)GS_alloc(sizeof(struct GH_THashTab));
++ if (hashTab == NULL)
++ return NULL;
++ hashTab->maxBucket = maxBucket;
++ hashTab->valSize = valSize;
++ hashTab->hash = hash;
++ hashTab->match = match;
++ hashTab->delete = delete == NULL ? Nop : delete;
++
++ hashTab->buckets = (struct Elem **)
++ GS_alloc(sizeof(struct Elem *) * maxBucket);
++ if (hashTab->buckets == NULL) {
++ GH_delete(hashTab);
++ return NULL;
++ }
++
++ for (i = 0; i < maxBucket; i++)
++ hashTab->buckets[i] = NULL;
++
++ return hashTab;
++}
++
++/*
++ * ======== GH_delete ========
++ */
++void GH_delete(struct GH_THashTab *hashTab)
++{
++ struct Elem *elem, *next;
++ u16 i;
++
++ if (hashTab != NULL) {
++ if (hashTab->buckets != NULL) {
++ for (i = 0; i < hashTab->maxBucket; i++) {
++ for (elem = hashTab->buckets[i]; elem != NULL;
++ elem = next) {
++ next = elem->next;
++ (*hashTab->delete) (elem->data);
++ myfree(elem, sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ }
++ }
++
++ myfree(hashTab->buckets, sizeof(struct Elem *)
++ * hashTab->maxBucket);
++ }
++
++ myfree(hashTab, sizeof(struct GH_THashTab));
++ }
++}
++
++/*
++ * ======== GH_exit ========
++ */
++
++void GH_exit(void)
++{
++ if (curInit-- == 1)
++ GS_exit();
++
++}
++
++/*
++ * ======== GH_find ========
++ */
++
++void *GH_find(struct GH_THashTab *hashTab, void *key)
++{
++ struct Elem *elem;
++
++ elem = hashTab->buckets[(*hashTab->hash)(key, hashTab->maxBucket)];
++
++ for (; elem; elem = elem->next) {
++ if ((*hashTab->match)(key, elem->data))
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== GH_init ========
++ */
++
++void GH_init(void)
++{
++ if (curInit++ == 0)
++ GS_init();
++}
++
++/*
++ * ======== GH_insert ========
++ */
++
++void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value)
++{
++ struct Elem *elem;
++ u16 i;
++ char *src, *dst;
++
++ elem = (struct Elem *)GS_alloc(sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ if (elem != NULL) {
++
++ dst = (char *)elem->data;
++ src = (char *)value;
++ for (i = 0; i < hashTab->valSize; i++)
++ *dst++ = *src++;
++
++ i = (*hashTab->hash)(key, hashTab->maxBucket);
++ elem->next = hashTab->buckets[i];
++ hashTab->buckets[i] = elem;
++
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== Nop ========
++ */
++/* ARGSUSED */
++static void Nop(void *p)
++{
++ p = p; /* stifle compiler warning */
++}
++
++/*
++ * ======== myfree ========
++ */
++static void myfree(void *ptr, s32 size)
++{
++ GS_free(ptr);
++}
+diff --git a/drivers/dsp/bridge/gen/gs.c b/drivers/dsp/bridge/gen/gs.c
+new file mode 100644
+index 0000000..ef5f923
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gs.c
+@@ -0,0 +1,108 @@
++/*
++ * gs.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gs.c ========
++ * Description:
++ * General storage memory allocator services.
++ *
++ *! Revision History
++ *! ================
++ *! 29-Sep-1999 ag: Un-commented MEM_Init in GS_init().
++ *! 14-May-1997 mg: Modified to use new GS API for GS_free() and GS_frees().
++ *! 06-Nov-1996 gp: Re-commented MEM_Init in GS_init(). GS needs GS_Exit().
++ *! 21-Oct-1996 db: Un-commented MEM_Init in GS_init().
++ *! 21-May-1996 mg: Created from original stdlib implementation.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <linux/types.h>
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++
++/* ----------------------------------- Globals */
++static u32 cumsize;
++
++/*
++ * ======== GS_alloc ========
++ * purpose:
++ * Allocates memory of the specified size.
++ */
++void *GS_alloc(u32 size)
++{
++ void *p;
++
++ p = MEM_Calloc(size, MEM_PAGED);
++ if (p == NULL)
++ return NULL;
++ cumsize += size;
++ return p;
++}
++
++/*
++ * ======== GS_exit ========
++ * purpose:
++ * Discontinue the usage of the GS module.
++ */
++void GS_exit(void)
++{
++ MEM_Exit();
++}
++
++/*
++ * ======== GS_free ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_free(void *ptr)
++{
++ MEM_Free(ptr);
++ /* ack! no size info */
++ /* cumsize -= size; */
++}
++
++/*
++ * ======== GS_frees ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_frees(void *ptr, u32 size)
++{
++ MEM_Free(ptr);
++ cumsize -= size;
++}
++
++/*
++ * ======== GS_init ========
++ * purpose:
++ * Initializes the GS module.
++ */
++void GS_init(void)
++{
++ static bool curInit;
++
++ if (curInit == false) {
++ curInit = true;
++
++ MEM_Init();
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/gt.c b/drivers/dsp/bridge/gen/gt.c
+new file mode 100644
+index 0000000..452d6e6
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gt.c
+@@ -0,0 +1,348 @@
++/*
++ * gt.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.c ========
++ * Description: This module implements the trace mechanism for bridge.
++ *
++ *! Revision History
++ *! ================
++ *! 16-May-1997 dr Changed GT_Config member names to conform to coding
++ *! standards.
++ *! 23-Apr-1997 ge Check for GT->TIDFXN for NULL before calling it.
++ *! 03-Jan-1997 ge Changed GT_Config structure member names to eliminate
++ *! preprocessor confusion with other macros.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gt.h>
++
++#define GT_WILD '*'
++
++#define GT_CLEAR '='
++#define GT_ON '+'
++#define GT_OFF '-'
++
++enum GT_State {
++ GT_SEP,
++ GT_FIRST,
++ GT_SECOND,
++ GT_OP,
++ GT_DIGITS
++} ;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_1format = "%s - %d: ";
++static char *GT_2format = "%s - %d(%d): ";
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static unsigned char *GT_tMask[GT_BOUND];
++
++static bool curInit;
++static char *separator;
++static unsigned char tabMem[GT_BOUND][sizeof(unsigned char) * GT_BOUND];
++
++static void error(char *string);
++static void setMask(s16 index1, s16 index2, char op, unsigned char mask);
++
++/*
++ * ======== _GT_create ========
++ * purpose:
++ * Creates GT mask.
++ */
++void _GT_create(struct GT_Mask *mask, char *modName)
++{
++ mask->modName = modName;
++ mask->flags = &(GT_tMask[modName[0] - 'A'][modName[1] - 'A']);
++}
++
++/*
++ * ======== GT_init ========
++ * purpose:
++ * Initializes GT module.
++ */
++#ifdef GT_init
++#undef GT_init
++#endif
++void GT_init(void)
++{
++ register unsigned char index1;
++ register unsigned char index2;
++
++ if (!curInit) {
++ curInit = true;
++
++ separator = " ,;/";
++
++ for (index1 = 0; index1 < GT_BOUND; index1++) {
++ GT_tMask[index1] = tabMem[index1];
++ for (index2 = 0; index2 < GT_BOUND; index2++) {
++ /* no tracing */
++ GT_tMask[index1][index2] = 0x00;
++ }
++ }
++ }
++}
++
++/*
++ * ======== _GT_set ========
++ * purpose:
++ * Sets the trace string format.
++ */
++
++void _GT_set(char *str)
++{
++ enum GT_State state;
++ char *sep;
++ s16 index1 = GT_BOUND; /* indicates all values */
++ s16 index2 = GT_BOUND; /* indicates all values */
++ char op = GT_CLEAR;
++ bool maskValid;
++ s16 digit;
++ register unsigned char mask = 0x0; /* no tracing */
++
++ if (str == NULL)
++ return;
++
++ maskValid = false;
++ state = GT_SEP;
++ while (*str != '\0') {
++ switch ((s32) state) {
++ case (s32) GT_SEP:
++ maskValid = false;
++ sep = separator;
++ while (*sep != '\0') {
++ if (*str == *sep) {
++ str++;
++ break;
++ } else {
++ sep++;
++ }
++ }
++ if (*sep == '\0')
++ state = GT_FIRST;
++
++ break;
++ case (s32) GT_FIRST:
++ if (*str == GT_WILD) {
++ /* indicates all values */
++ index1 = GT_BOUND;
++ /* indicates all values */
++ index2 = GT_BOUND;
++ state = GT_OP;
++ } else {
++ if (*str >= 'a')
++ index1 = (s16) (*str - 'a');
++ else
++ index1 = (s16) (*str - 'A');
++ if ((index1 >= 0) && (index1 < GT_BOUND))
++ state = GT_SECOND;
++ else
++ state = GT_SEP;
++ }
++ str++;
++ break;
++ case (s32) GT_SECOND:
++ if (*str == GT_WILD) {
++ index2 = GT_BOUND; /* indicates all values */
++ state = GT_OP;
++ str++;
++ } else {
++ if (*str >= 'a')
++ index2 = (s16) (*str - 'a');
++ else
++ index2 = (s16) (*str - 'A');
++ if ((index2 >= 0) && (index2 < GT_BOUND)) {
++ state = GT_OP;
++ str++;
++ } else {
++ state = GT_SEP;
++ }
++ }
++ break;
++ case (s32) GT_OP:
++ op = *str;
++ mask = 0x0; /* no tracing */
++ switch (op) {
++ case (s32) GT_CLEAR:
++ maskValid = true;
++ case (s32) GT_ON:
++ case (s32) GT_OFF:
++ state = GT_DIGITS;
++ str++;
++ break;
++ default:
++ state = GT_SEP;
++ break;
++ }
++ break;
++ case (s32) GT_DIGITS:
++ digit = (s16) (*str - '0');
++ if ((digit >= 0) && (digit <= 7)) {
++ mask |= (0x01 << digit);
++ maskValid = true;
++ str++;
++ } else {
++ if (maskValid == true) {
++ setMask(index1, index2, op, mask);
++ maskValid = false;
++ }
++ state = GT_SEP;
++ }
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++
++ if (maskValid)
++ setMask(index1, index2, op, mask);
++}
++
++/*
++ * ======== _GT_trace ========
++ * purpose:
++ * Prints the input string onto standard output
++ */
++
++s32 _GT_trace(struct GT_Mask *mask, char *format, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, format);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++#ifdef DEBUG
++ if (GT->PIDFXN == NULL) {
++ printk(GT_1format, mask->modName, GT->TIDFXN ?
++ (*GT->TIDFXN)() : 0);
++ } else {
++ printk(GT_2format, mask->modName, (*GT->PIDFXN)(),
++ GT->TIDFXN ? (*GT->TIDFXN)() : 0);
++ }
++#endif
++ printk(format, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints errors onto the standard output.
++ */
++static void error(char *string)
++{
++ printk("GT: %s", string);
++}
++
++/*
++ * ======== setmask ========
++ * purpose:
++ * Sets mask for the GT module.
++ */
++
++static void setMask(s16 index1, s16 index2, char op, u8 mask)
++{
++ register s16 index;
++
++ if (index1 < GT_BOUND) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ for (index2--; index2 >= 0; index2--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ } else {
++ for (index1--; index1 >= 0; index1--) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ index = GT_BOUND;
++ for (index--; index >= 0; index--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index] &=
++ ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ }
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/uuidutil.c b/drivers/dsp/bridge/gen/uuidutil.c
+new file mode 100644
+index 0000000..a45f448
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/uuidutil.c
+@@ -0,0 +1,238 @@
++/*
++ * uuidutil.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.c ========
++ * Description:
++ * This file contains the implementation of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2003 vp: Ported to Linux platform.
++ *! 31-Aug-2000 rr: UUID_UuidFromString bug fixed.
++ *! 29-Aug-2000 rr: Modified UUID_UuidFromString.
++ *! 09-Nov-2000 kc: Modified UUID_UuidFromString to simplify implementation.
++ *! 30-Oct-2000 kc: Modified UUID utility module function prefix.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/uuidutil.h>
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a struct DSP_UUID to a string.
++ * Note: snprintf format specifier is:
++ * %[flags] [width] [.precision] [{h | l | I64 | L}]type
++ */
++void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ IN s32 size)
++{
++ s32 i; /* return result from snprintf. */
++
++ DBC_Require(pUuid && pszUuid);
++
++ i = snprintf(pszUuid, size,
++ "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
++ pUuid->ulData1, pUuid->usData2, pUuid->usData3,
++ pUuid->ucData4, pUuid->ucData5, pUuid->ucData6[0],
++ pUuid->ucData6[1], pUuid->ucData6[2], pUuid->ucData6[3],
++ pUuid->ucData6[4], pUuid->ucData6[5]);
++
++ DBC_Ensure(i != -1);
++}
++
++/*
++ * ======== htoi ========
++ * Purpose:
++ * Converts a hex value to a decimal integer.
++ */
++
++static int htoi(char c)
++{
++ switch (c) {
++ case '0':
++ return 0;
++ case '1':
++ return 1;
++ case '2':
++ return 2;
++ case '3':
++ return 3;
++ case '4':
++ return 4;
++ case '5':
++ return 5;
++ case '6':
++ return 6;
++ case '7':
++ return 7;
++ case '8':
++ return 8;
++ case '9':
++ return 9;
++ case 'A':
++ return 10;
++ case 'B':
++ return 11;
++ case 'C':
++ return 12;
++ case 'D':
++ return 13;
++ case 'E':
++ return 14;
++ case 'F':
++ return 15;
++ case 'a':
++ return 10;
++ case 'b':
++ return 11;
++ case 'c':
++ return 12;
++ case 'd':
++ return 13;
++ case 'e':
++ return 14;
++ case 'f':
++ return 15;
++ }
++ return 0;
++}
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts a string to a struct DSP_UUID.
++ */
++void UUID_UuidFromString(IN char *pszUuid, OUT struct DSP_UUID *pUuid)
++{
++ char c;
++ s32 i, j;
++ s32 result;
++ char *temp = pszUuid;
++
++ result = 0;
++ for (i = 0; i < 8; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ulData1 = result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData2 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData3 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData4 = (u8)result;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData5 = (u8)result;
++
++ /* Step over underscore */
++ temp++;
++
++ for (j = 0; j < 6; j++) {
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData6[j] = (u8)result;
++ }
++}
+diff --git a/drivers/dsp/bridge/hw/EasiGlobal.h b/drivers/dsp/bridge/hw/EasiGlobal.h
+new file mode 100644
+index 0000000..b023826
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/EasiGlobal.h
+@@ -0,0 +1,42 @@
++/*
++ * EasiGlobal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef __EASIGLOBAL_H
++#define __EASIGLOBAL_H
++#include <linux/types.h>
++
++/*
++ * DEFINE: READ_ONLY, WRITE_ONLY & READ_WRITE
++ *
++ * DESCRIPTION: Defines used to describe register types for EASI-checker tests.
++ */
++
++#define READ_ONLY 1
++#define WRITE_ONLY 2
++#define READ_WRITE 3
++
++/*
++ * MACRO: _DEBUG_LEVEL_1_EASI
++ *
++ * DESCRIPTION: A MACRO which can be used to indicate that a particular beach
++ * register access function was called.
++ *
++ * NOTE: We currently dont use this functionality.
++ */
++#define _DEBUG_LEVEL_1_EASI(easiNum) ((void)0)
++
++#endif /* __EASIGLOBAL_H */
++
+diff --git a/drivers/dsp/bridge/hw/GlobalTypes.h b/drivers/dsp/bridge/hw/GlobalTypes.h
+new file mode 100644
+index 0000000..9004a37
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/GlobalTypes.h
+@@ -0,0 +1,325 @@
++/*
++ * GlobalTypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== GlobalTypes.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __GLOBALTYPES_H
++#define __GLOBALTYPES_H
++
++/*
++ * Definition: TRUE, FALSE
++ *
++ * DESCRIPTION: Boolean Definitions
++ */
++#ifndef TRUE
++#define FALSE 0
++#define TRUE (!(FALSE))
++#endif
++
++/*
++ * Definition: NULL
++ *
++ * DESCRIPTION: Invalid pointer
++ */
++#ifndef NULL
++#define NULL (void *)0
++#endif
++
++/*
++ * Definition: RET_CODE_BASE
++ *
++ * DESCRIPTION: Base value for return code offsets
++ */
++#define RET_CODE_BASE 0
++
++/*
++ * Definition: *BIT_OFFSET
++ *
++ * DESCRIPTION: offset in bytes from start of 32-bit word.
++ */
++#define LOWER_16BIT_OFFSET 0
++#define UPPER_16BIT_OFFSET 2
++
++#define LOWER_8BIT_OFFSET 0
++#define LOWER_MIDDLE_8BIT_OFFSET 1
++#define UPPER_MIDDLE_8BIT_OFFSET 2
++#define UPPER_8BIT_OFFSET 3
++
++#define LOWER_8BIT_OF16_OFFSET 0
++#define UPPER_8BIT_OF16_OFFSET 1
++
++/*
++ * Definition: *BIT_SHIFT
++ *
++ * DESCRIPTION: offset in bits from start of 32-bit word.
++ */
++#define LOWER_16BIT_SHIFT 0
++#define UPPER_16BIT_SHIFT 16
++
++#define LOWER_8BIT_SHIFT 0
++#define LOWER_MIDDLE_8BIT_SHIFT 8
++#define UPPER_MIDDLE_8BIT_SHIFT 16
++#define UPPER_8BIT_SHIFT 24
++
++#define LOWER_8BIT_OF16_SHIFT 0
++#define UPPER_8BIT_OF16_SHIFT 8
++
++
++/*
++ * Definition: LOWER_16BIT_MASK
++ *
++ * DESCRIPTION: 16 bit mask used for inclusion of lower 16 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_16BIT_MASK 0x0000FFFF
++
++
++/*
++ * Definition: LOWER_8BIT_MASK
++ *
++ * DESCRIPTION: 8 bit masks used for inclusion of 8 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_8BIT_MASK 0x000000FF
++
++/*
++ * Definition: RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given a 16 bit lower value and a 16
++ * bit upper value
++ */
++#define RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits,upper16Bits)\
++ (((((u32)lower16Bits) & LOWER_16BIT_MASK)) | \
++ (((((u32)upper16Bits) & LOWER_16BIT_MASK) << UPPER_16BIT_SHIFT)))
++
++/*
++ * Definition: RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 16 bit value given a 8 bit lower value and a 8
++ * bit upper value
++ */
++#define RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower8Bits,upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) << UPPER_8BIT_OF16_SHIFT)))
++
++/*
++ * Definition: RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,
++ * lowerUpper8Bits, upper8Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given four 8 bit values
++ */
++#define RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,\
++ lowerUpper8Bits, upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)lowerMiddle8Bits) & LOWER_8BIT_MASK) <<\
++ LOWER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)lowerUpper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_8BIT_SHIFT)))
++
++/*
++ * Definition: READ_LOWER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_LOWER_16BITS_OF_32(value32bits)\
++ ((u16)((u32)(value32bits) & LOWER_16BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_UPPER_16BITS_OF_32(value32bits)\
++ (((u16)((u32)(value32bits) >> UPPER_16BIT_SHIFT)) &\
++ LOWER_16BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 32bit value
++ */
++#define READ_LOWER_8BITS_OF_32(value32bits)\
++ ((u8)((u32)(value32bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_UPPER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 32bit value
++ */
++#define READ_UPPER_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_16(value16bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 16bit value
++ */
++#define READ_LOWER_8BITS_OF_16(value16bits)\
++ ((u8)((u16)(value16bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_16(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 16bit value
++ */
++#define READ_UPPER_8BITS_OF_16(value16bits)\
++ (((u8)((u32)(value16bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++
++/* UWORD16: 16 bit tpyes */
++
++
++/* REG_UWORD8, REG_WORD8: 8 bit register types */
++typedef volatile unsigned char REG_UWORD8;
++typedef volatile signed char REG_WORD8;
++
++/* REG_UWORD16, REG_WORD16: 16 bit register types */
++#ifndef OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++typedef volatile short REG_WORD16;
++
++/* REG_UWORD32, REG_WORD32: 32 bit register types */
++typedef volatile unsigned long REG_UWORD32;
++
++/* FLOAT
++ *
++ * Type to be used for floating point calculation. Note that floating point
++ * calculation is very CPU expensive, and you should only use if you
++ * absolutely need this. */
++
++
++/* boolean_t: Boolean Type True, False */
++/* ReturnCode_t: Return codes to be returned by all library functions */
++typedef enum ReturnCode_label {
++ RET_OK = 0,
++ RET_FAIL = -1,
++ RET_BAD_NULL_PARAM = -2,
++ RET_PARAM_OUT_OF_RANGE = -3,
++ RET_INVALID_ID = -4,
++ RET_EMPTY = -5,
++ RET_FULL = -6,
++ RET_TIMEOUT = -7,
++ RET_INVALID_OPERATION = -8,
++
++ /* Add new error codes at end of above list */
++
++ RET_NUM_RET_CODES /* this should ALWAYS be LAST entry */
++} ReturnCode_t, *pReturnCode_t;
++
++/* MACRO: RD_MEM_8, WR_MEM_8
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_8(addr) ((u8)(*((u8 *)(addr))))
++#define WR_MEM_8(addr, data) (*((u8 *)(addr)) = (u8)(data))
++
++/* MACRO: RD_MEM_8_VOLATILE, WR_MEM_8_VOLATILE
++ *
++ * DESCRIPTION: 8 bit register access macros
++ */
++#define RD_MEM_8_VOLATILE(addr) ((u8)(*((REG_UWORD8 *)(addr))))
++#define WR_MEM_8_VOLATILE(addr, data) (*((REG_UWORD8 *)(addr)) = (u8)(data))
++
++
++/*
++ * MACRO: RD_MEM_16, WR_MEM_16
++ *
++ * DESCRIPTION: 16 bit memory access macros
++ */
++#define RD_MEM_16(addr) ((u16)(*((u16 *)(addr))))
++#define WR_MEM_16(addr, data) (*((u16 *)(addr)) = (u16)(data))
++
++/*
++ * MACRO: RD_MEM_16_VOLATILE, WR_MEM_16_VOLATILE
++ *
++ * DESCRIPTION: 16 bit register access macros
++ */
++#define RD_MEM_16_VOLATILE(addr) ((u16)(*((REG_UWORD16 *)(addr))))
++#define WR_MEM_16_VOLATILE(addr, data) (*((REG_UWORD16 *)(addr)) =\
++ (u16)(data))
++
++/*
++ * MACRO: RD_MEM_32, WR_MEM_32
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_32(addr) ((u32)(*((u32 *)(addr))))
++#define WR_MEM_32(addr, data) (*((u32 *)(addr)) = (u32)(data))
++
++/*
++ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
++ *
++ * DESCRIPTION: 32 bit register access macros
++ */
++#define RD_MEM_32_VOLATILE(addr) ((u32)(*((REG_UWORD32 *)(addr))))
++#define WR_MEM_32_VOLATILE(addr, data) (*((REG_UWORD32 *)(addr)) =\
++ (u32)(data))
++
++/* Not sure if this all belongs here */
++
++#define CHECK_RETURN_VALUE(actualValue, expectedValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET(actualValue, expectedValue, returnCodeIfMismatch)
++#define CHECK_RETURN_VALUE_RES(actualValue, expectedValue, spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET_VOID(actualValue, expectedValue,\
++ spyCodeIfMisMatch)
++
++#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch)
++
++#endif /* __GLOBALTYPES_H */
+diff --git a/drivers/dsp/bridge/hw/IPIAccInt.h b/drivers/dsp/bridge/hw/IPIAccInt.h
+new file mode 100644
+index 0000000..b88a58c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IPIAccInt.h
+@@ -0,0 +1,41 @@
++/*
++ * IPIAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _IPI_ACC_INT_H
++#define _IPI_ACC_INT_H
++
++/* Bitfield mask and offset declarations */
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++#define SYSC_IVA2BOOTADDR_MASK 0xfffffc00
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum IPIIPI_SYSCONFIGAutoIdleE {
++ IPIIPI_SYSCONFIGAutoIdleclkfree = 0x0000,
++ IPIIPI_SYSCONFIGAutoIdleautoclkgate = 0x0001
++} ;
++
++enum IPIIPI_ENTRYElemSizeValueE {
++ IPIIPI_ENTRYElemSizeValueElemSz8b = 0x0000,
++ IPIIPI_ENTRYElemSizeValueElemSz16b = 0x0001,
++ IPIIPI_ENTRYElemSizeValueElemSz32b = 0x0002,
++ IPIIPI_ENTRYElemSizeValueReserved = 0x0003
++} ;
++
++#endif /* _IPI_ACC_INT_H */
++/* EOF */
+diff --git a/drivers/dsp/bridge/hw/IVA2RegAcM.h b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+new file mode 100644
+index 0000000..6c1e300
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+@@ -0,0 +1,28 @@
++/*
++ * IVA1RegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _IVA2_REG_ACM_H
++#define _IVA2_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++
++#endif
+diff --git a/drivers/dsp/bridge/hw/MLBAccInt.h b/drivers/dsp/bridge/hw/MLBAccInt.h
+new file mode 100644
+index 0000000..7a03c6a
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBAccInt.h
+@@ -0,0 +1,132 @@
++/*
++ * MLBAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MLB_ACC_INT_H
++#define _MLB_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32 (MLB_BASE_EASIL1 + 3)
++#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32 (MLB_BASE_EASIL1 + 4)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32 (MLB_BASE_EASIL1 + 7)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32 (MLB_BASE_EASIL1 + 17)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
++ (MLB_BASE_EASIL1 + 33)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32 (MLB_BASE_EASIL1 + 39)
++#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32 (MLB_BASE_EASIL1 + 44)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 50)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32 \
++ (MLB_BASE_EASIL1 + 51)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 56)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
++ (MLB_BASE_EASIL1 + 57)
++#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32 \
++ (MLB_BASE_EASIL1 + 60)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 62)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 63)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 192)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 193)
++
++/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (u32)(0x0040)
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MESSAGE___REGSET_0_15 */
++
++#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (u32)(0x0080)
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (u32)(0x00c0)
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MSGSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (u32)(0x0100)
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQSTATUS___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (u32)(0x0104)
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQENABLE___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (u32)(0x0)
++
++
++/* Register offset address definitions */
++
++#define MLB_MAILBOX_SYSCONFIG_OFFSET (u32)(0x10)
++#define MLB_MAILBOX_SYSSTATUS_OFFSET (u32)(0x14)
++
++
++/* Bitfield mask and offset declarations */
++
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (u32)(0x18)
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (u32)(3)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (u32)(0x2)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (u32)(1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (u32)(0)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (u32)(0)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (u32)(0x1)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (u32)(0)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (u32)(0x7f)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (u32)(0)
++
++#endif /* _MLB_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MLBRegAcM.h b/drivers/dsp/bridge/hw/MLBRegAcM.h
+new file mode 100644
+index 0000000..747a2e1
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBRegAcM.h
+@@ -0,0 +1,200 @@
++/*
++ * MLBRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MLB_REG_ACM_H
++#define _MLB_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++#include "MLBAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+ \
++ MLB_MAILBOX_SYSCONFIG_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress)) +\
++ offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSSTATUSResetDoneRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
++
++
++#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
++ (bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
++ ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
++
++
++#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MLB_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/MMUAccInt.h b/drivers/dsp/bridge/hw/MMUAccInt.h
+new file mode 100644
+index 0000000..6ca1573
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMUAccInt.h
+@@ -0,0 +1,76 @@
++/*
++ * MMUAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MMU_ACC_INT_H
++#define _MMU_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MMUMMU_SYSCONFIGReadRegister32 (MMU_BASE_EASIL1 + 3)
++#define EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32 (MMU_BASE_EASIL1 + 17)
++#define EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32 (MMU_BASE_EASIL1 + 39)
++#define EASIL1_MMUMMU_IRQSTATUSWriteRegister32 (MMU_BASE_EASIL1 + 51)
++#define EASIL1_MMUMMU_IRQENABLEReadRegister32 (MMU_BASE_EASIL1 + 102)
++#define EASIL1_MMUMMU_IRQENABLEWriteRegister32 (MMU_BASE_EASIL1 + 103)
++#define EASIL1_MMUMMU_WALKING_STTWLRunningRead32 (MMU_BASE_EASIL1 + 156)
++#define EASIL1_MMUMMU_CNTLTWLEnableRead32 (MMU_BASE_EASIL1 + 174)
++#define EASIL1_MMUMMU_CNTLTWLEnableWrite32 (MMU_BASE_EASIL1 + 180)
++#define EASIL1_MMUMMU_CNTLMMUEnableWrite32 (MMU_BASE_EASIL1 + 190)
++#define EASIL1_MMUMMU_FAULT_ADReadRegister32 (MMU_BASE_EASIL1 + 194)
++#define EASIL1_MMUMMU_TTBWriteRegister32 (MMU_BASE_EASIL1 + 198)
++#define EASIL1_MMUMMU_LOCKReadRegister32 (MMU_BASE_EASIL1 + 203)
++#define EASIL1_MMUMMU_LOCKWriteRegister32 (MMU_BASE_EASIL1 + 204)
++#define EASIL1_MMUMMU_LOCKBaseValueRead32 (MMU_BASE_EASIL1 + 205)
++#define EASIL1_MMUMMU_LOCKCurrentVictimRead32 (MMU_BASE_EASIL1 + 209)
++#define EASIL1_MMUMMU_LOCKCurrentVictimWrite32 (MMU_BASE_EASIL1 + 211)
++#define EASIL1_MMUMMU_LOCKCurrentVictimSet32 (MMU_BASE_EASIL1 + 212)
++#define EASIL1_MMUMMU_LD_TLBReadRegister32 (MMU_BASE_EASIL1 + 213)
++#define EASIL1_MMUMMU_LD_TLBWriteRegister32 (MMU_BASE_EASIL1 + 214)
++#define EASIL1_MMUMMU_CAMWriteRegister32 (MMU_BASE_EASIL1 + 226)
++#define EASIL1_MMUMMU_RAMWriteRegister32 (MMU_BASE_EASIL1 + 268)
++#define EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32 (MMU_BASE_EASIL1 + 322)
++
++/* Register offset address definitions */
++#define MMU_MMU_SYSCONFIG_OFFSET 0x10
++#define MMU_MMU_IRQSTATUS_OFFSET 0x18
++#define MMU_MMU_IRQENABLE_OFFSET 0x1c
++#define MMU_MMU_WALKING_ST_OFFSET 0x40
++#define MMU_MMU_CNTL_OFFSET 0x44
++#define MMU_MMU_FAULT_AD_OFFSET 0x48
++#define MMU_MMU_TTB_OFFSET 0x4c
++#define MMU_MMU_LOCK_OFFSET 0x50
++#define MMU_MMU_LD_TLB_OFFSET 0x54
++#define MMU_MMU_CAM_OFFSET 0x58
++#define MMU_MMU_RAM_OFFSET 0x5c
++#define MMU_MMU_GFLUSH_OFFSET 0x60
++#define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64
++/* Bitfield mask and offset declarations */
++#define MMU_MMU_SYSCONFIG_IdleMode_MASK 0x18
++#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET 3
++#define MMU_MMU_SYSCONFIG_AutoIdle_MASK 0x1
++#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET 0
++#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
++#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET 0
++#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
++#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
++#define MMU_MMU_CNTL_MMUEnable_MASK 0x2
++#define MMU_MMU_CNTL_MMUEnable_OFFSET 1
++#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
++#define MMU_MMU_LOCK_BaseValue_OFFSET 10
++#define MMU_MMU_LOCK_CurrentVictim_MASK 0x3f0
++#define MMU_MMU_LOCK_CurrentVictim_OFFSET 4
++
++#endif /* _MMU_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MMURegAcM.h b/drivers/dsp/bridge/hw/MMURegAcM.h
+new file mode 100644
+index 0000000..e46fdcb
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMURegAcM.h
+@@ -0,0 +1,253 @@
++/*
++ * MMURegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MMU_REG_ACM_H
++#define _MMU_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "MMUAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++
++#define MMUMMU_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_SYSCONFIG_OFFSET))
++
++
++#define MMUMMU_SYSCONFIGIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_IdleMode_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_IdleMode_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_IdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQSTATUSReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQSTATUS_OFFSET))
++
++
++#define MMUMMU_IRQSTATUSWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQENABLEReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQENABLE_OFFSET))
++
++
++#define MMUMMU_IRQENABLEWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_WALKING_STTWLRunningRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_WALKING_STTWLRunningRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_WALKING_ST_OFFSET))))\
++ & MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
++ MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_CNTL_OFFSET)))) &\
++ MMU_MMU_CNTL_TWLEnable_MASK) >>\
++ MMU_MMU_CNTL_TWLEnable_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_CNTLMMUEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLMMUEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_FAULT_ADReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FAULT_ADReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_FAULT_AD_OFFSET))
++
++
++#define MMUMMU_TTBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_TTB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_TTBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LOCK_OFFSET))
++
++
++#define MMUMMU_LOCKWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKBaseValueRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_BaseValue_MASK) >>\
++ MMU_MMU_LOCK_BaseValue_OFFSET))
++
++
++#define MMUMMU_LOCKBaseValueWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueWrite32);\
++ data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
++ newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
++ newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK) >>\
++ MMU_MMU_LOCK_CurrentVictim_OFFSET))
++
++
++#define MMUMMU_LOCKCurrentVictimWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimWrite32);\
++ data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
++ newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
++ newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimSet32),\
++ (((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
++ (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK)))
++
++
++#define MMUMMU_LD_TLBReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LD_TLB_OFFSET))
++
++
++#define MMUMMU_LD_TLBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_CAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_RAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_RAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_RAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MMU_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMAccInt.h b/drivers/dsp/bridge/hw/PRCMAccInt.h
+new file mode 100644
+index 0000000..42baa68
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMAccInt.h
+@@ -0,0 +1,300 @@
++/*
++ * PRCMAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_ACC_INT_H
++#define _PRCM_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32 \
++ (PRCM_BASE_EASIL1 + 349)
++#define EASIL1_PRCMCM_FCLKEN1_COREReadRegister32 (PRCM_BASE_EASIL1 + 743)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32 (PRCM_BASE_EASIL1 + 951)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32 (PRCM_BASE_EASIL1 + 961)
++#define EASIL1_PRCMCM_ICLKEN1_COREReadRegister32 \
++ (PRCM_BASE_EASIL1 + 1087)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32 \
++ (PRCM_BASE_EASIL1 + 1105)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32 \
++ (PRCM_BASE_EASIL1 + 1305)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32 \
++ (PRCM_BASE_EASIL1 + 1315)
++#define EASIL1_PRCMCM_CLKSEL1_CORECLKSEL_L3ReadIssel132 \
++ (PRCM_BASE_EASIL1 + 2261)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32 \
++ (PRCM_BASE_EASIL1 + 2364)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2365)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2366)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32 \
++ (PRCM_BASE_EASIL1 + 2380)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2381)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2382)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2397)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2398)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2413)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2414)
++#define EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32 \
++ (PRCM_BASE_EASIL1 + 3747)
++#define EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32 (PRCM_BASE_EASIL1 + 3834)
++#define EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3846)
++#define EASIL1_PRCMCM_IDLEST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3850)
++#define EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32 (PRCM_BASE_EASIL1 + 3857)
++#define EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32 (PRCM_BASE_EASIL1 + 3863)
++#define EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3877)
++#define EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32 (PRCM_BASE_EASIL1 + 3927)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32 \
++ (PRCM_BASE_EASIL1 + 3941)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3965)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32 \
++ (PRCM_BASE_EASIL1 + 3987)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3993)
++#define EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3997)
++#define EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 4025)
++#define EASIL1_PRCMRM_RSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4029)
++#define EASIL1_PRCMRM_RSTST_DSPWriteRegister32 (PRCM_BASE_EASIL1 + 4030)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32 \
++ (PRCM_BASE_EASIL1 + 4165)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32 \
++ (PRCM_BASE_EASIL1 + 4193)
++#define EASIL1_PRCMPM_PWSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4197)
++#define EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4198)
++#define EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4235)
++#define EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4368)
++#define EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4370)
++#define EASIL1_CM_CLKSEL_PER_GPT5Write32k32 (PRCM_BASE_EASIL1 + 4372)
++#define EASIL1_CM_CLKSEL_PER_GPT6Write32k32 (PRCM_BASE_EASIL1 + 4373)
++#define EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4374)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32 \
++ (PRCM_BASE_EASIL1 + 4375)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32 \
++ (PRCM_BASE_EASIL1 + 4376)
++#define EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4377)
++#define EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4378)
++#define EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32 (PRCM_BASE_EASIL1 + 4379)
++
++/* Register offset address definitions */
++
++#define PRCM_PRCM_CLKCFG_CTRL_OFFSET (u32)(0x80)
++#define PRCM_CM_FCLKEN1_CORE_OFFSET (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_OFFSET (u32)(0x210)
++#define PRCM_CM_CLKSEL2_CORE_OFFSET (u32)(0x244)
++#define PRCM_CM_CLKSEL1_PLL_OFFSET (u32)(0x540)
++#define PRCM_CM_ICLKEN_DSP_OFFSET (u32)(0x810)
++#define PRCM_CM_IDLEST_DSP_OFFSET (u32)(0x820)
++#define PRCM_CM_AUTOIDLE_DSP_OFFSET (u32)(0x830)
++#define PRCM_CM_CLKSEL_DSP_OFFSET (u32)(0x840)
++#define PRCM_CM_CLKSTCTRL_DSP_OFFSET (u32)(0x848)
++#define PRCM_RM_RSTCTRL_DSP_OFFSET (u32)(0x850)
++#define PRCM_RM_RSTST_DSP_OFFSET (u32)(0x858)
++#define PRCM_PM_PWSTCTRL_DSP_OFFSET (u32)(0x8e0)
++#define PRCM_PM_PWSTST_DSP_OFFSET (u32)(0x8e4)
++#define PRCM_PM_PWSTST_IVA2_OFFSET (u32)(0xE4)
++#define PRCM_PM_PWSTCTRL_IVA2_OFFSET (u32)(0xE0)
++#define PRCM_CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x48)
++#define CM_CLKSEL_PER_OFFSET (u32)(0x40)
++
++/* Bitfield mask and offset declarations */
++
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK (u32)(0x1)
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET (u32)(0)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK (u32)(0xc000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET (u32)(14)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK (u32)(0x3000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET (u32)(12)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK (u32)(0xc00)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET (u32)(10)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK (u32)(0x300)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET (u32)(8)
++
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK (u32)(0x3800000)
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET (u32)(23)
++
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_IDLEST_DSP_ST_IPI_MASK (u32)(0x2)
++#define PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK (u32)(0x80)
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET (u32)(7)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK (u32)(0x60)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET (u32)(5)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK (u32)(0x1f)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET (u32)(0)
++
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK (u32)(0x1)
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_MASK (u32)(0x40000)
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET (u32)(18)
++
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_DSP_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_DSP_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_IVA2_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_IVA2_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET (u32)(0)
++
++#define CM_FCLKEN_PER_OFFSET (u32)(0x0)
++#define CM_FCLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_FCLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_FCLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_FCLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_ICLKEN_PER_OFFSET (u32)(0x10)
++#define CM_ICLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_ICLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_ICLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_ICLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_CLKSEL_PER_GPT5_OFFSET (u32)(3)
++#define CM_CLKSEL_PER_GPT5_MASK (u32)(0x8)
++
++#define CM_CLKSEL_PER_GPT6_OFFSET (u32)(4)
++#define CM_CLKSEL_PER_GPT6_MASK (u32)(0x10)
++
++
++#define CM_FCLKEN_IVA2_OFFSET (u32)(0x0)
++#define CM_FCLKEN_IVA2_EN_MASK (u32)(0x1)
++#define CM_FCLKEN_IVA2_EN_OFFSET (u32)(0x0)
++
++#define CM_IDLEST_IVA2_OFFSET (u32)(0x20)
++#define CM_IDLEST_IVA2_ST_IVA2_MASK (u32) (0x01)
++#define CM_IDLEST_IVA2_ST_IVA2_OFFSET (u32) (0x00)
++
++#define CM_FCLKEN1_CORE_OFFSET (u32)(0xA00)
++
++#define CM_ICLKEN1_CORE_OFFSET (u32)(0xA10)
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_MASK (u32)(0x00000080) /* bit 7 */
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET (u32)(7)
++
++#define CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x0)
++#define CM_CLKSTCTRL_IVA2_MASK (u32)(0x3)
++
++
++#define PRM_RSTCTRL_IVA2_OFFSET (u32)(0x50)
++#define PRM_RSTCTRL_IVA2_RST1_MASK (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST1_OFFSET (u32)(0x0)
++#define PRM_RSTCTRL_IVA2_RST2_MASK (u32)(0x2)
++#define PRM_RSTCTRL_IVA2_RST2_OFFSET (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST3_MASK (u32)(0x4)
++#define PRM_RSTCTRL_IVA2_RST3_OFFSET (u32)(0x2)
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum PRCMPRCM_CLKCFG_CTRLValid_configE {
++ PRCMPRCM_CLKCFG_CTRLValid_configUpdated = 0x0000,
++ PRCMPRCM_CLKCFG_CTRLValid_configClk_valid = 0x0001
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT8E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT832k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT7E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT732k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT6E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT632k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT5E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT532k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Reserved = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_DSPPowerStateE {
++ PRCMPM_PWSTCTRL_DSPPowerStateON = 0x0000,
++ PRCMPM_PWSTCTRL_DSPPowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_DSPPowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_DSPPowerStateOFF = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_IVA2PowerStateE {
++ PRCMPM_PWSTCTRL_IVA2PowerStateON = 0x0003,
++ PRCMPM_PWSTCTRL_IVA2PowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_IVA2PowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_IVA2PowerStateOFF = 0x0000
++} ;
++
++#endif /* _PRCM_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMRegAcM.h b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+new file mode 100644
+index 0000000..91cb33c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+@@ -0,0 +1,669 @@
++/*
++ * PRCMRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_REG_ACM_H
++#define _PRCM_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "PRCMAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32(baseAddress)\
++{\
++ const u32 offset = PRCM_PRCM_CLKCFG_CTRL_OFFSET;\
++ const u32 newValue = \
++ (u32)PRCMPRCM_CLKCFG_CTRLValid_configClk_valid <<\
++ PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(\
++ EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32);\
++ data &= ~(PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_FCLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN_PER_OFFSET))
++
++
++#define CM_ICLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN_PER_OFFSET))
++
++
++#define CM_FCLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN1_CORE_OFFSET))
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT8Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT7Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define CM_ICLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN1_CORE_OFFSET))
++
++
++#define CM_ICLKEN1_COREEN_MAILBOXESWrite32(baseAddress, value)\
++{\
++ const u32 offset = CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32);\
++ data &= ~(CM_ICLKEN1_CORE_EN_MAILBOXES_MASK);\
++ newValue <<= CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET;\
++ newValue &= CM_ICLKEN1_CORE_EN_MAILBOXES_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT8Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT7Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT832k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT732k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT5Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT5Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT6Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT6Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSEL1_PLL_OFFSET)))) &\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK) >>\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET))
++
++
++#define CM_FCLKEN_IVA2EN_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32);\
++ data &= ~(CM_FCLKEN_IVA2_EN_MASK);\
++ newValue <<= CM_FCLKEN_IVA2_EN_OFFSET;\
++ newValue &= CM_FCLKEN_IVA2_EN_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_IDLEST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_CM_IDLEST_DSP_OFFSET))
++
++
++#define PRCMCM_IDLEST_DSPST_IPIRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_IDLEST_DSP_OFFSET)))) &\
++ PRCM_CM_IDLEST_DSP_ST_IPI_MASK) >>\
++ PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET))
++
++
++#define PRM_IDLEST_IVA2ST_IVA2Read32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (CM_IDLEST_IVA2_OFFSET)))) &\
++ CM_IDLEST_IVA2_ST_IVA2_MASK) >>\
++ CM_IDLEST_IVA2_ST_IVA2_OFFSET))
++
++
++#define PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_AUTOIDLE_DSP_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPSYNC_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32);\
++ data &= ~(CM_CLKSTCTRL_IVA2_MASK);\
++ newValue <<= CM_CLKSTCTRL_IVA2_OFFSET;\
++ newValue &= CM_CLKSTCTRL_IVA2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSTCTRL_DSP_OFFSET)))) &\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK) >>\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET))
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTCTRL_DSP_OFFSET))
++
++
++#define PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST1_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST1_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST1_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST2_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST2_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST3_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST3_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST3_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTST_DSP_OFFSET))
++
++
++#define PRCMRM_RSTST_DSPWriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_RM_RSTST_DSP_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPForceStateWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_ForceState_MASK);\
++ newValue <<= PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET;\
++ newValue &= PRCM_PM_PWSTCTRL_DSP_ForceState_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateON <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateOFF <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_DSPPowerStateRET <<\
++ PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_DSP_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_IVA2_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPInTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_DSP_OFFSET)))) &\
++ PRCM_PM_PWSTST_DSP_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_DSP_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2InTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_IVA2_OFFSET)))) &\
++ PRCM_PM_PWSTST_IVA2_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPPowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_DSP_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2PowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET))
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _PRCM_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/hw_defs.h b/drivers/dsp/bridge/hw/hw_defs.h
+new file mode 100644
+index 0000000..a973f5c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_defs.h
+@@ -0,0 +1,73 @@
++/*
++ * hw_defs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_defs.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Added generic page size, endianness and element size defns
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_DEFS_H
++#define __HW_DEFS_H
++
++#include <GlobalTypes.h>
++
++/* Page size */
++#define HW_PAGE_SIZE_4KB 0x1000
++#define HW_PAGE_SIZE_64KB 0x10000
++#define HW_PAGE_SIZE_1MB 0x100000
++#define HW_PAGE_SIZE_16MB 0x1000000
++
++/* HW_STATUS: return type for HW API */
++typedef long HW_STATUS;
++
++/* HW_SetClear_t: Enumerated Type used to set and clear any bit */
++enum HW_SetClear_t {
++ HW_CLEAR,
++ HW_SET
++} ;
++
++/* HW_Endianism_t: Enumerated Type used to specify the endianism
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_Endianism_t {
++ HW_LITTLE_ENDIAN,
++ HW_BIG_ENDIAN
++
++} ;
++
++/* HW_ElementSize_t: Enumerated Type used to specify the element size
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_ElementSize_t {
++ HW_ELEM_SIZE_8BIT,
++ HW_ELEM_SIZE_16BIT,
++ HW_ELEM_SIZE_32BIT,
++ HW_ELEM_SIZE_64BIT
++
++} ;
++
++/* HW_IdleMode_t: Enumerated Type used to specify Idle modes */
++ enum HW_IdleMode_t {
++ HW_FORCE_IDLE,
++ HW_NO_IDLE,
++ HW_SMART_IDLE
++ } ;
++
++#endif /* __HW_DEFS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.c b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+new file mode 100644
+index 0000000..a4b7c30
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+@@ -0,0 +1,55 @@
++/*
++ * hw_dspss64P.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_dspss64P.c ========
++ * Description:
++ * API definitions to configure DSP Subsystem modules like IPI
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Implemented HW_DSPSS_IPIEndianismSet
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++/* PROJECT SPECIFIC INCLUDE FILES */
++#include <GlobalTypes.h>
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <IVA2RegAcM.h>
++#include <IPIAccInt.h>
++
++/* HW FUNCTIONS */
++HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 offset = SYSC_IVA2BOOTMOD_OFFSET;
++ u32 alignedBootAddr;
++
++ /* if Boot mode it DIRECT BOOT, check that the bootAddress is
++ * aligned to atleast 1K :: TODO */
++ WR_MEM_32_VOLATILE((baseAddress) + offset, bootMode);
++
++ offset = SYSC_IVA2BOOTADDR_OFFSET;
++
++ alignedBootAddr = bootAddress & SYSC_IVA2BOOTADDR_MASK;
++
++ WR_MEM_32_VOLATILE((baseAddress) + offset, alignedBootAddr);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.h b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+new file mode 100644
+index 0000000..493effd
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+@@ -0,0 +1,48 @@
++/*
++ * hw_dspssC64P.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_dspss.h ========
++ * Description:
++ * DSP Subsystem API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Removed redundant argument from HW_DSPSS_IPIEndianismSet
++ *! Moved endianness and element size to generic hw_defs.h
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_DSPSS_H
++#define __HW_DSPSS_H
++#include <linux/types.h>
++
++ enum HW_DSPSYSC_BootMode_t {
++ HW_DSPSYSC_DIRECTBOOT = 0x0,
++ HW_DSPSYSC_IDLEBOOT = 0x1,
++ HW_DSPSYSC_SELFLOOPBOOT = 0x2,
++ HW_DSPSYSC_USRBOOTSTRAP = 0x3,
++ HW_DSPSYSC_DEFAULTRESTORE = 0x4
++ } ;
++
++#define HW_DSP_IDLEBOOT_ADDR 0x007E0000
++
++ extern HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress);
++
++#endif /* __HW_DSPSS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c
+new file mode 100644
+index 0000000..9f14f34
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.c
+@@ -0,0 +1,244 @@
++/*
++ * hw_mbox.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mbox.c ========
++ * Description:
++ * Mailbox messaging & configuration API definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MLBRegAcM.h"
++#include <hw_defs.h>
++#include <hw_mbox.h>
++
++/* width in bits of MBOX Id */
++#define HW_MBOX_ID_WIDTH 2
++
++struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1};
++
++/* Saves the mailbox context */
++HW_STATUS HW_MBOX_saveSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Restores the mailbox context */
++HW_STATUS HW_MBOX_restoreSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ /* Restor IRQ enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U0_ARM,
++ mboxsetting.irqEnable0);
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U1_DSP1,
++ mboxsetting.irqEnable1);
++ /* Restore Sysconfig register */
++ MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, mboxsetting.sysconfig);
++ return status;
++}
++
++/* Reads a u32 from the sub module message box Specified. if there are no
++ * messages in the mailbox then and error is returned. */
++HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pReadValue, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Read 32-bit message in mail box */
++ *pReadValue = MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Writes a u32 from the sub module message box Specified. */
++HW_STATUS HW_MBOX_MsgWrite(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Write 32-bit value to mailbox */
++ MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, (u32)mailBoxId,
++ (u32)writeValue);
++
++ return status;
++}
++
++/* Gets number of messages in a specified mailbox. */
++HW_STATUS HW_MBOX_NumMsgGet(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pNumMsg, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get number of messages available for MailBox */
++ *pNumMsg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Enables the specified IRQ. */
++HW_STATUS HW_MBOX_EventEnable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqEnableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(enableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqEnableReg |= ((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqEnableReg);
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Disables the specified IRQ. */
++HW_STATUS HW_MBOX_EventDisable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqDisableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(disableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqDisableReg &= ~(((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH));
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqDisableReg);
++
++ return status;
++}
++
++/* Sets the status of the specified IRQ. */
++HW_STATUS HW_MBOX_EventAck(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId, const u32 event)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqStatusReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(irqStatus, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* calculate status to write */
++ irqStatusReg = ((u32)event) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* clear Irq Status for specified mailbox/User Id */
++ MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqStatusReg);
++
++ /*
++ * FIXME: Replace all this custom register access with standard
++ * __raw_read/write().
++ *
++ * FIXME: Replace all interrupt handlers with standard linux style
++ * interrupt handlers.
++ *
++ * FIXME: Replace direct access to PRCM registers with omap standard
++ * PRCM register access.
++ *
++ * Flush posted write for the irq status to avoid spurious interrupts.
++ */
++ MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, (u32)userId);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.h b/drivers/dsp/bridge/hw/hw_mbox.h
+new file mode 100644
+index 0000000..d2981d3
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.h
+@@ -0,0 +1,323 @@
++/*
++ * hw_mbox.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mbox.h ========
++ * Description:
++ * HW Mailbox API and types definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __MBOX_H
++#define __MBOX_H
++
++/* Bitmasks for Mailbox interrupt sources */
++#define HW_MBOX_INT_NEW_MSG 0x1
++#define HW_MBOX_INT_NOT_FULL 0x2
++#define HW_MBOX_INT_ALL 0x3
++
++/* Maximum number of messages that mailbox can hald at a time. */
++#define HW_MBOX_MAX_NUM_MESSAGES 4
++
++/* HW_MBOX_Id_t: Enumerated Type used to specify Mailbox Sub Module Id Number */
++typedef enum HW_MBOX_Id_label {
++ HW_MBOX_ID_0,
++ HW_MBOX_ID_1,
++ HW_MBOX_ID_2,
++ HW_MBOX_ID_3,
++ HW_MBOX_ID_4,
++ HW_MBOX_ID_5
++
++} HW_MBOX_Id_t, *pHW_MBOX_Id_t;
++
++/* HW_MBOX_UserId_t: Enumerated Type used to specify Mail box User Id */
++typedef enum HW_MBOX_UserId_label {
++ HW_MBOX_U0_ARM,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_U2_DSP2,
++ HW_MBOX_U3_ARM
++
++} HW_MBOX_UserId_t, *pHW_MBOX_UserId_t;
++
++/* Mailbox context settings */
++struct MAILBOX_CONTEXT {
++ u32 sysconfig;
++ u32 irqEnable0;
++ u32 irqEnable1;
++};
++
++/*
++* FUNCTION : HW_MBOX_MsgRead
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to read
++*
++* OUTPUTS:
++*
++* Identifier : pReadValue
++* Type : u32 *const
++* Description : Value read from MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/ptr Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function reads a u32 from the sub module message
++* box Specified. if there are no messages in the mailbox
++* then and error is returned.
++*/
++extern HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue);
++
++/*
++* FUNCTION : HW_MBOX_MsgWrite
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to write
++*
++* Identifier : writeValue
++* Type : const u32
++* Description : Value to write to MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function writes a u32 from the sub module message
++* box Specified.
++*/
++extern HW_STATUS HW_MBOX_MsgWrite(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue
++ );
++
++/*
++* FUNCTION : HW_MBOX_NumMsgGet
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to get num messages
++*
++* OUTPUTS:
++*
++* Identifier : pNumMsg
++* Type : u32 *const
++* Description : Number of messages in mailbox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Inavlid ID input at parameter
++*
++* PURPOSE: : this function gets number of messages in a specified mailbox.
++*/
++extern HW_STATUS HW_MBOX_NumMsgGet(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventEnable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to enable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to enable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to enable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function enables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventEnable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventDisable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to disable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to disable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to disable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function disables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventDisable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventAck
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to set
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to set
++*
++* Identifier : irqStatus
++* Type : const u32
++* Description : The value to write IRQ status
++*
++* OUTPUTS:
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address Paramater was set to 0
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function sets the status of the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventAck(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 event
++ );
++
++/*
++* FUNCTION : HW_MBOX_saveSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function saves the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_saveSettings(u32 baseAddres);
++
++/*
++* FUNCTION : HW_MBOX_restoreSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function restores the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_restoreSettings(u32 baseAddres);
++
++#endif /* __MBOX_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.c b/drivers/dsp/bridge/hw/hw_mmu.c
+new file mode 100644
+index 0000000..ab65de0
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.c
+@@ -0,0 +1,598 @@
++/*
++ * hw_mmu.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mmu.c ========
++ * Description:
++ * API definitions to setup MMU TLB and PTE
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb TLBAdd and TLBFlush input the page size in bytes instead
++ of an enum. TLBAdd inputs mapping attributes struct instead
++ of individual arguments.
++ Removed MMU.h and other cosmetic updates.
++ *! 08-Mar-2004 sb Added the Page Table Management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MMURegAcM.h"
++#include <hw_defs.h>
++#include <hw_mmu.h>
++#include <linux/types.h>
++
++#define MMU_BASE_VAL_MASK 0xFC00
++#define MMU_PAGE_MAX 3
++#define MMU_ELEMENTSIZE_MAX 3
++#define MMU_ADDR_MASK 0xFFFFF000
++#define MMU_TTB_MASK 0xFFFFC000
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++
++#define MMU_LOAD_TLB 0x00000001
++
++/* HW_MMUPageSize_t: Enumerated Type used to specify the MMU Page Size(SLSS) */
++enum HW_MMUPageSize_t {
++ HW_MMU_SECTION,
++ HW_MMU_LARGE_PAGE,
++ HW_MMU_SMALL_PAGE,
++ HW_MMU_SUPERSECTION
++} ;
++
++/*
++* FUNCTION : MMU_FlushEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer
++* Paramater was set to NULL
++*
++* PURPOSE: : Flush the TLB entry pointed by the
++* lock counter register
++* even if this entry is set protected
++*
++* METHOD: : Check the Input parameter and Flush a
++* single entry in the TLB.
++*/
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress);
++
++/*
++* FUNCTION : MMU_SetCAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* TypE : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : pageSize
++* TypE : const u32
++* Description : It indicates the page size
++*
++* Identifier : preservedBit
++* Type : const u32
++* Description : It indicates the TLB entry is preserved entry
++* or not
++*
++* Identifier : validBit
++* Type : const u32
++* Description : It indicates the TLB entry is valid entry or not
++*
++*
++* Identifier : virtualAddrTag
++* Type : const u32
++* Description : virtual Address
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter out
++* of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the CAM entry.
++*/
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag);
++
++/*
++* FUNCTION : MMU_SetRAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : physicalAddr
++* Type : const u32
++* Description : Physical Address to which the corresponding
++* virtual Address shouldpoint
++*
++* Identifier : endianism
++* Type : HW_Endianism_t
++* Description : endianism for the given page
++*
++* Identifier : elementSize
++* Type : HW_ElementSize_t
++* Description : The element size ( 8,16, 32 or 64 bit)
++*
++* Identifier : mixedSize
++* Type : HW_MMUMixedSize_t
++* Description : Element Size to follow CPU or TLB
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter
++* out of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the RAM entry.
++*/
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++/* HW FUNCTIONS */
++
++HW_STATUS HW_MMU_Enable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_Disable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKBaseValueWrite32(baseAddress, numLockedEntries);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, victimEntryNum);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventAck(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_IRQSTATUSWriteRegister32(baseAddress, irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg & ~irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventEnable(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg | irqMask);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_EventStatus(const u32 baseAddress, u32 *irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ *irqMask = MMUMMU_IRQSTATUSReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress, u32 *addr)
++{
++ HW_STATUS status = RET_OK;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* read values from register */
++ *addr = MMUMMU_FAULT_ADReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TTBSet(const u32 baseAddress, u32 TTBPhysAddr)
++{
++ HW_STATUS status = RET_OK;
++ u32 loadTTB;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ loadTTB = TTBPhysAddr & ~0x7FUL;
++ /* write values to register */
++ MMUMMU_TTBWriteRegister32(baseAddress, loadTTB);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress, u32 virtualAddr,
++ u32 pageSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t pgSizeBits;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pgSizeBits = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ pgSizeBits = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pgSizeBits = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ pgSizeBits = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ MMU_SetCAMEntry(baseAddress, pgSizeBits, 0, 0, virtualAddrTag);
++
++ MMU_FlushEntry(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit)
++{
++ HW_STATUS status = RET_OK;
++ u32 lockReg;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t mmuPgSize;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(pageSize, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mapAttrs->elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ mmuPgSize = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ mmuPgSize = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ mmuPgSize = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ mmuPgSize = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ lockReg = MMUMMU_LOCKReadRegister32(baseAddress);
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ /* Write the fields in the CAM Entry Register */
++ MMU_SetCAMEntry(baseAddress, mmuPgSize, preservedBit, validBit,
++ virtualAddrTag);
++
++ /* Write the different fields of the RAM Entry Register */
++ /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit)*/
++ MMU_SetRAMEntry(baseAddress, physicalAddr, mapAttrs->endianism,
++ mapAttrs->elementSize, mapAttrs->mixedSize);
++
++ /* Update the MMU Lock Register */
++ /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1)*/
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, entryNum);
++
++ /* Enable loading of an entry in TLB by writing 1
++ into LD_TLB_REG register */
++ MMUMMU_LD_TLBWriteRegister32(baseAddress, MMU_LOAD_TLB);
++
++
++ MMUMMU_LOCKWriteRegister32(baseAddress, lockReg);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr, pteVal;
++ s32 numEntries = 1;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_SMALL_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 2
++ );
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_LARGE_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 1
++ );
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = ((((physicalAddr & MMU_SECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)) &
++ ~0x40000) | 0x2
++ );
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ pteVal = (((physicalAddr & MMU_SSECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)
++ ) | 0x40000 | 0x2
++ );
++ break;
++
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = (physicalAddr & MMU_PAGE_TABLE_MASK) | 1;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = pteVal;
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 virtualAddr,
++ u32 pgSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr;
++ s32 numEntries = 1;
++
++ switch (pgSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = 0;
++
++ return status;
++}
++
++/* MMU_FlushEntry */
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 flushEntryData = 0x1;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* write values to register */
++ MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, flushEntryData);
++
++ return status;
++}
++
++/* MMU_SetCAMEntry */
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuCamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ mmuCamReg = (virtualAddrTag << 12);
++ mmuCamReg = (mmuCamReg) | (pageSize) | (validBit << 2) |
++ (preservedBit << 3) ;
++
++ /* write values to register */
++ MMUMMU_CAMWriteRegister32(baseAddress, mmuCamReg);
++
++ return status;
++}
++
++/* MMU_SetRAMEntry */
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuRamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++
++ mmuRamReg = (physicalAddr & MMU_ADDR_MASK);
++ mmuRamReg = (mmuRamReg) | ((endianism << 9) | (elementSize << 7) |
++ (mixedSize << 6));
++
++ /* write values to register */
++ MMUMMU_RAMWriteRegister32(baseAddress, mmuRamReg);
++
++ return status;
++
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h
+new file mode 100644
+index 0000000..a3dd2a8
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.h
+@@ -0,0 +1,177 @@
++/*
++ * hw_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mmu.h ========
++ * Description:
++ * MMU types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Moved & renamed endianness, page size, element size
++ TLBAdd takes in MMUMapAttrs instead of separate arguments
++ *! 08-Mar-2004 sb Added the Page Table management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_MMU_H
++#define __HW_MMU_H
++
++#include <linux/types.h>
++
++/* Bitmasks for interrupt sources */
++#define HW_MMU_TRANSLATION_FAULT 0x2
++#define HW_MMU_ALL_INTERRUPTS 0x1F
++
++#define HW_MMU_COARSE_PAGE_SIZE 0x400
++
++/* HW_MMUMixedSize_t: Enumerated Type used to specify whether to follow
++ CPU/TLB Element size */
++enum HW_MMUMixedSize_t {
++ HW_MMU_TLBES,
++ HW_MMU_CPUES
++
++} ;
++
++/* HW_MMUMapAttrs_t: Struct containing MMU mapping attributes */
++struct HW_MMUMapAttrs_t {
++ enum HW_Endianism_t endianism;
++ enum HW_ElementSize_t elementSize;
++ enum HW_MMUMixedSize_t mixedSize;
++ bool donotlockmpupage;
++} ;
++
++extern HW_STATUS HW_MMU_Enable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_Disable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries);
++
++extern HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum);
++
++/* For MMU faults */
++extern HW_STATUS HW_MMU_EventAck(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventEnable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventStatus(const u32 baseAddress,
++ u32 *irqMask);
++
++extern HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress,
++ u32 *addr);
++
++/* Set the TT base address */
++extern HW_STATUS HW_MMU_TTBSet(const u32 baseAddress,
++ u32 TTBPhysAddr);
++
++extern HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress,
++ u32 virtualAddr,
++ u32 pageSize);
++
++extern HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit);
++
++
++/* For PTEs */
++extern HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++
++extern HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 pgSize,
++ u32 virtualAddr);
++
++static inline u32 HW_MMU_PteAddrL1(u32 L1_base, u32 va)
++{
++ u32 pteAddr;
++ u32 VA_31_to_20;
++
++ VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
++ VA_31_to_20 &= 0xFFFFFFFCUL;
++ pteAddr = L1_base + VA_31_to_20;
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteAddrL2(u32 L2_base, u32 va)
++{
++ u32 pteAddr;
++
++ pteAddr = (L2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteCoarseL1(u32 pteVal)
++{
++ u32 pteCoarse;
++
++ pteCoarse = pteVal & 0xFFFFFC00;
++
++ return pteCoarse;
++}
++
++static inline u32 HW_MMU_PteSizeL1(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if ((pteVal & 0x3) == 0x1) {
++ /* Points to L2 PT */
++ pteSize = HW_MMU_COARSE_PAGE_SIZE;
++ }
++
++ if ((pteVal & 0x3) == 0x2) {
++ if (pteVal & (1 << 18))
++ pteSize = HW_PAGE_SIZE_16MB;
++ else
++ pteSize = HW_PAGE_SIZE_1MB;
++ }
++
++ return pteSize;
++}
++
++static inline u32 HW_MMU_PteSizeL2(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if (pteVal & 0x2)
++ pteSize = HW_PAGE_SIZE_4KB;
++ else if (pteVal & 0x1)
++ pteSize = HW_PAGE_SIZE_64KB;
++
++ return pteSize;
++}
++
++#endif /* __HW_MMU_H */
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.c b/drivers/dsp/bridge/hw/hw_prcm.c
+new file mode 100644
+index 0000000..61ff08f
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.c
+@@ -0,0 +1,167 @@
++/*
++ * hw_prcm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.c ========
++ * Description:
++ * API definitions to configure PRCM (Power, Reset & Clocks Manager)
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "PRCMRegAcM.h"
++#include <hw_defs.h>
++#include <hw_prcm.h>
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val);
++
++HW_STATUS HW_RST_Reset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_SET);
++}
++
++HW_STATUS HW_RST_UnReset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_CLEAR);
++}
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (r) {
++ case HW_RST1_IVA2:
++ PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST2_IVA2:
++ PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST3_IVA2:
++ PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress, val);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress, enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value)
++{
++ HW_STATUS status = RET_OK;
++ u32 temp;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ /* wait until Transition is complete */
++ do {
++ /* mdelay(1); */
++ temp = PRCMPM_PWSTST_IVA2InTransitionRead32
++ (baseAddress);
++
++ } while (temp);
++
++ temp = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++ *value = PRCMPM_PWSTST_IVA2PowerStateStGet32(temp);
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ switch (value) {
++ case HW_PWR_STATE_ON:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress);
++ break;
++ case HW_PWR_STATE_RET:
++ PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress);
++ break;
++ case HW_PWR_STATE_OFF:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++
++ return status;
++}
++
++HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, val);
++
++ return status;
++
++}
++
++HW_STATUS HW_RSTST_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTST_DSPReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.h b/drivers/dsp/bridge/hw/hw_prcm.h
+new file mode 100644
+index 0000000..928486c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.h
+@@ -0,0 +1,168 @@
++/*
++ * hw_prcm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.h ========
++ * Description:
++ * PRCM types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_PRCM_H
++#define __HW_PRCM_H
++
++/* HW_ClkModule: Enumerated Type used to specify the clock domain */
++
++enum HW_ClkModule_t {
++/* DSP Domain */
++ HW_CLK_DSP_CPU,
++ HW_CLK_DSP_IPI_MMU,
++ HW_CLK_IVA_ARM,
++ HW_CLK_IVA_COP, /* IVA Coprocessor */
++
++/* Core Domain */
++ HW_CLK_FN_WDT4, /* Functional Clock */
++ HW_CLK_FN_WDT3,
++ HW_CLK_FN_UART2,
++ HW_CLK_FN_UART1,
++ HW_CLK_GPT5,
++ HW_CLK_GPT6,
++ HW_CLK_GPT7,
++ HW_CLK_GPT8,
++
++ HW_CLK_IF_WDT4, /* Interface Clock */
++ HW_CLK_IF_WDT3,
++ HW_CLK_IF_UART2,
++ HW_CLK_IF_UART1,
++ HW_CLK_IF_MBOX
++
++} ;
++
++enum HW_ClkSubsys_t {
++ HW_CLK_DSPSS,
++ HW_CLK_IVASS
++} ;
++
++/* HW_GPtimers: General purpose timers */
++enum HW_GPtimer_t {
++ HW_GPT5 = 5,
++ HW_GPT6 = 6,
++ HW_GPT7 = 7,
++ HW_GPT8 = 8
++} ;
++
++
++/* GP timers Input clock type: General purpose timers */
++enum HW_Clocktype_t {
++ HW_CLK_32KHz = 0,
++ HW_CLK_SYS = 1,
++ HW_CLK_EXT = 2
++} ;
++
++/* HW_ClkDiv: Clock divisors */
++enum HW_ClkDiv_t {
++ HW_CLK_DIV_1 = 0x1,
++ HW_CLK_DIV_2 = 0x2,
++ HW_CLK_DIV_3 = 0x3,
++ HW_CLK_DIV_4 = 0x4,
++ HW_CLK_DIV_6 = 0x6,
++ HW_CLK_DIV_8 = 0x8,
++ HW_CLK_DIV_12 = 0xC
++} ;
++
++/* HW_RstModule: Enumerated Type used to specify the module to be reset */
++enum HW_RstModule_t {
++ HW_RST1_IVA2, /* Reset the DSP */
++ HW_RST2_IVA2, /* Reset MMU and LEON HWa */
++ HW_RST3_IVA2 /* Reset LEON sequencer */
++} ;
++
++/* HW_PwrModule: Enumerated Type used to specify the power domain */
++enum HW_PwrModule_t {
++/* Domains */
++ HW_PWR_DOMAIN_CORE,
++ HW_PWR_DOMAIN_MPU,
++ HW_PWR_DOMAIN_WAKEUP,
++ HW_PWR_DOMAIN_DSP,
++
++/* Sub-domains */
++ HW_PWR_DSP_IPI, /* IPI = Intrusive Port Interface */
++ HW_PWR_IVA_ISP /* ISP = Intrusive Slave Port */
++} ;
++
++enum HW_PwrState_t {
++ HW_PWR_STATE_OFF,
++ HW_PWR_STATE_RET,
++ HW_PWR_STATE_INACT,
++ HW_PWR_STATE_ON = 3
++} ;
++
++enum HW_ForceState_t {
++ HW_FORCE_OFF,
++ HW_FORCE_ON
++} ;
++
++enum HW_IdleState_t {
++ HW_ACTIVE,
++ HW_STANDBY
++
++} ;
++
++enum HW_TransitionState_t {
++ HW_AUTOTRANS_DIS,
++ HW_SW_SUP_SLEEP,
++ HW_SW_SUP_WAKEUP,
++ HW_AUTOTRANS_EN
++} ;
++
++
++extern HW_STATUS HW_RST_Reset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RST_UnReset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p,
++ u32 *value);
++extern HW_STATUS HW_RSTST_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p, u32 *value);
++
++extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_CLK_SetInputClock(const u32 baseAddress,
++ enum HW_GPtimer_t gpt,
++ enum HW_Clocktype_t c);
++
++extern HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value);
++
++extern HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value);
++
++extern HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val);
++
++#endif /* __HW_PRCM_H */
+diff --git a/drivers/dsp/bridge/pmgr/chnl.c b/drivers/dsp/bridge/pmgr/chnl.c
+new file mode 100644
+index 0000000..6b5a0d9
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnl.c
+@@ -0,0 +1,260 @@
++/*
++ * chnl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.c ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a 'Bridge mini-driver.
++ *
++ * Public Functions:
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_GetHandle
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD CHNL functions,
++ * except for the CHNL_Get() accessor functions which call
++ * WMD_CHNL_GetInfo().
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 07-Jan-2002 ag CHNL_CloseOrphans() now closes supported # of channels.
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory stuff from CHNL_Create.
++ *! 28-Feb-2000 rr: New GT USage Implementation
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 21-Jan-2000 ag: Added code review comments.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! 08-Dec-1999 ag: CHNL_[Alloc|Free]Buffer bufs taken from client process heap.
++ *! 02-Dec-1999 ag: Implemented CHNL_GetEventHandle().
++ *! 17-Nov-1999 ag: CHNL_AllocBuffer() allocs extra word for process mapping.
++ *! 28-Oct-1999 ag: WinCE port. Search for "WinCE" for changes(TBR).
++ *! 07-Jan-1998 gp: CHNL_[Alloc|Free]Buffer now call MEM_UMB functions.
++ *! 22-Oct-1997 gp: Removed requirement in CHNL_Open that hReserved1 != NULL.
++ *! 30-Aug-1997 cr: Renamed cfg.h wbwcd.h b/c of WINNT file name collision.
++ *! 10-Mar-1997 gp: Added GT trace.
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Moved CHNL_AllocBuffer/CHNL_FreeBuffer code from udspsys.
++ *! 14-Dec-1996 gp: Added uChnlId parameter to CHNL_Open().
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessHandle().
++ *! 15-Jul-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/proc.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/chnlpriv.h>
++#include <chnlobj.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/chnl.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++#if GT_TRACE
++static struct GT_Mask CHNL_DebugMask = { NULL, NULL }; /* WCD CHNL Mask */
++#endif
++
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ */
++DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status;
++ struct CHNL_MGR *hChnlMgr;
++ struct CHNL_MGR_ *pChnlMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Create: phChnlMgr: 0x%x\t"
++ "hDevObject: 0x%x\tpMgrAttrs:0x%x\n",
++ phChnlMgr, hDevObject, pMgrAttrs);
++
++ *phChnlMgr = NULL;
++
++ /* Validate args: */
++ if ((0 < pMgrAttrs->cChannels) &&
++ (pMgrAttrs->cChannels <= CHNL_MAXCHANNELS)) {
++ status = DSP_SOK;
++ } else if (pMgrAttrs->cChannels == 0) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Args\n");
++ } else {
++ status = CHNL_E_MAXCHANNELS;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Error Max Channels\n");
++ }
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Word size\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ if (DSP_SUCCEEDED(status) && hChnlMgr != NULL)
++ status = CHNL_E_MGREXISTS;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnChnlCreate)(&hChnlMgr, hDevObject,
++ pMgrAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD channel module's fields of the
++ * CHNL_MGR structure */
++ pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ pChnlMgr->pIntfFxns = pIntfFxns;
++ /* Finally, return the new channel manager handle: */
++ *phChnlMgr = hChnlMgr;
++ GT_1trace(CHNL_DebugMask, GT_1CLASS,
++ "CHNL_Create: Success pChnlMgr:"
++ "0x%x\n", pChnlMgr);
++ }
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Create: pChnlMgr: 0x%x,"
++ "status: 0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ struct CHNL_MGR_ *pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Destroy: hChnlMgr: 0x%x\n", hChnlMgr);
++ if (CHNL_IsValidMgr(pChnlMgr)) {
++ pIntfFxns = pChnlMgr->pIntfFxns;
++ /* Let WMD channel module destroy the CHNL_MGR: */
++ status = (*pIntfFxns->pfnChnlDestroy)(hChnlMgr);
++ } else {
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Destroy:Invalid Handle\n");
++ status = DSP_EHANDLE;
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Destroy: pChnlMgr: 0x%x,"
++ " status:0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || !CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ */
++void CHNL_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ */
++bool CHNL_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!CHNL_DebugMask.flags);
++ GT_create(&CHNL_DebugMask, "CH"); /* "CH" for CHannel */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++
+diff --git a/drivers/dsp/bridge/pmgr/chnlobj.h b/drivers/dsp/bridge/pmgr/chnlobj.h
+new file mode 100644
+index 0000000..da74c96
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnlobj.h
+@@ -0,0 +1,71 @@
++/*
++ * chnlobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library channel objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Removed some fields from CHNL_MGR_ to match CHNL_MGR
++ *! structure defined in _chnl_sm.h.
++ *! 16-Jan-1997 gp: Created from chnlpriv.h
++ */
++
++#ifndef CHNLOBJ_
++#define CHNLOBJ_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/wmd.h>
++
++/* Object validateion macros: */
++#define CHNL_IsValidMgr(h) \
++ ((h != NULL) && ((h)->dwSignature == CHNL_MGRSIGNATURE))
++
++#define CHNL_IsValidChnl(h)\
++ ((h != NULL) && ((h)->dwSignature == CHNL_SIGNATURE))
++
++/*
++ * This struct is the first field in a CHNL_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_MGR_ {
++ /* These must be the first fields in a CHNL_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++} ;
++
++/*
++ * This struct is the first field in a CHNL_OBJECT struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_OBJECT_ {
++ /* These must be the first fields in a CHNL_OBJECT struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct CHNL_MGR_ *pChnlMgr; /* Pointer back to channel manager. */
++} ;
++
++#endif /* CHNLOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/cmm.c b/drivers/dsp/bridge/pmgr/cmm.c
+new file mode 100644
+index 0000000..99a2432
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cmm.c
+@@ -0,0 +1,1291 @@
++/*
++ * cmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmm.c ========
++ * Purpose:
++ * The Communication(Shared) Memory Management(CMM) module provides
++ * shared memory management services for DSP/BIOS Bridge data streaming
++ * and messaging.
++ *
++ * Multiple shared memory segments can be registered with CMM.
++ * Each registered SM segment is represented by a SM "allocator" that
++ * describes a block of physically contiguous shared memory used for
++ * future allocations by CMM.
++ *
++ * Memory is coelesced back to the appropriate heap when a buffer is
++ * freed.
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ *
++ * The CMM_Xlator[xxx] routines below are used by Node and Stream
++ * to perform SM address translation to the client process address space.
++ * A "translator" object is created by a node/stream for each SM seg used.
++ *
++ * Translator Routines:
++ * CMM_XlatorAllocBuf
++ * CMM_XlatorCreate
++ * CMM_XlatorDelete
++ * CMM_XlatorFreeBuf
++ * CMM_XlatorInfo
++ * CMM_XlatorTranslate
++ *
++ * Private Functions:
++ * AddToFreeList
++ * GetAllocator
++ * GetFreeBlock
++ * GetNode
++ * GetSlot
++ * UnRegisterGPPSMSeg
++ *
++ * Notes:
++ * Va: Virtual address.
++ * Pa: Physical or kernel system address.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 16-Feb-2002 ag Code review cleanup.
++ *! PreOMAP address translation no longner supported.
++ *! 30-Jan-2002 ag Updates to CMM_XlatorTranslate() per TII, ANSI C++
++ *! warnings.
++ *! 27-Jan-2002 ag Removed unused CMM_[Alloc][Free]Desc() & #ifdef USELOOKUP,
++ *! & unused VALIDATECMM and VaPaConvert().
++ *! Removed bFastXlate from CMM_XLATOR. Always fast lookup.
++ *! 03-Jan-2002 ag Clear SM in CMM_AllocBuf(). Renamed to CMM_CallocBuf().
++ *! 13-Nov-2001 ag Now delete pNodeFreeListHead and nodes in CMM_Destroy().
++ *! 28-Aug-2001 ag CMM_GetHandle() returns CMM Mgr hndle given HPROCESSOR.
++ *! Removed unused CMM_[Un]RegisterDSPSMSeg() &
++ * CMM_[Un}ReserveVirtSpace fxns. Some cleanup.
++ *! 12-Aug-2001 ag Exposed CMM_UnRegisterGPP[DSP]SMSeg.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name update.
++ *! 21-Dec-2000 rr GetFreeBlock checks for pAllocator.
++ *! 09-Dec-2000 ag Added GPPPA2DSPPA, DSPPA2GPPPA macros.
++ *! 05-Dec-2000 ag CMM_XlatorDelete() optionally frees SM bufs and descriptors.
++ *! 30-Oct-2000 ag Buf size bug fixed in CMM_AllocBuf() causing leak.
++ *! Revamped XlatorTranslate() routine.
++ *! 10-Oct-2000 ag Added CMM_Xlator[xxx] functions.
++ *! 02-Aug-2000 ag Created.
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define CMMSIGNATURE 0x004d4d43 /* "CMM" (in reverse) */
++#define SMEMSIGNATURE 0x4D454D53 /* "SMEM" SM space */
++#define CMMXLATESIGNATURE 0x584d4d43 /* "CMMX" CMM Xlator */
++
++#define NEXT_PA(pNode) (pNode->dwPA + pNode->ulSize)
++
++/* Other bus/platform translations */
++#define DSPPA2GPPPA(base, x, y) ((x)+(y))
++#define GPPPA2DSPPA(base, x, y) ((x)-(y))
++
++/*
++ * Allocators define a block of contiguous memory used for future allocations.
++ *
++ * sma - shared memory allocator.
++ * vma - virtual memory allocator.(not used).
++ */
++struct CMM_ALLOCATOR { /* sma */
++ u32 dwSignature; /* SMA allocator signature SMEMSIGNATURE */
++ unsigned int dwSmBase; /* Start of physical SM block */
++ u32 ulSmSize; /* Size of SM block in bytes */
++ unsigned int dwVmBase; /* Start of VM block. (Dev driver
++ * context for 'sma') */
++ u32 dwDSPPhysAddrOffset; /* DSP PA to GPP PA offset for this
++ * SM space */
++ /* CMM_ADDTO[SUBFROM]DSPPA, _POMAPEMIF2DSPBUS */
++ enum CMM_CNVTTYPE cFactor;
++ unsigned int dwDSPBase; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ struct CMM_OBJECT *hCmmMgr; /* back ref to parent mgr */
++ struct LST_LIST *pFreeListHead; /* node list of available memory */
++ struct LST_LIST *pInUseListHead; /* node list of memory in use */
++} ;
++
++struct CMM_XLATOR { /* Pa<->Va translator object */
++ u32 dwSignature; /* "CMMX" */
++ struct CMM_OBJECT *hCmmMgr; /* CMM object this translator associated */
++ /*
++ * Client process virtual base address that corresponds to phys SM
++ * base address for translator's ulSegId.
++ * Only 1 segment ID currently supported.
++ */
++ unsigned int dwVirtBase; /* virtual base address */
++ u32 ulVirtSize; /* size of virt space in bytes */
++ u32 ulSegId; /* Segment Id */
++} ;
++
++/* CMM Mgr */
++struct CMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /*
++ * Cmm Lock is used to serialize access mem manager for multi-threads.
++ */
++ struct SYNC_CSOBJECT *hCmmLock; /* Lock to access cmm mgr */
++ struct LST_LIST *pNodeFreeListHead; /* Free list of memory nodes */
++ u32 ulMinBlockSize; /* Min SM block; default 16 bytes */
++ u32 dwPageSize; /* Memory Page size (1k/4k) */
++ /* GPP SM segment ptrs */
++ struct CMM_ALLOCATOR *paGPPSMSegTab[CMM_MAXGPPSEGS];
++} ;
++
++/* Default CMM Mgr attributes */
++static struct CMM_MGRATTRS CMM_DFLTMGRATTRS = {
++ 16 /* ulMinBlockSize, min block size(bytes) allocated by cmm mgr */
++};
++
++/* Default allocation attributes */
++static struct CMM_ATTRS CMM_DFLTALCTATTRS = {
++ 1 /* ulSegId, default segment Id for allocator */
++};
++
++/* Address translator default attrs */
++static struct CMM_XLATORATTRS CMM_DFLTXLATORATTRS = {
++ 1, /* ulSegId, does not have to match CMM_DFLTALCTATTRS ulSegId */
++ 0, /* dwDSPBufs */
++ 0, /* dwDSPBufSize */
++ NULL, /* pVmBase */
++ 0, /* dwVmSize */
++};
++
++/* SM node representing a block of memory. */
++struct CMM_MNODE {
++ struct LST_ELEM link; /* must be 1st element */
++ u32 dwPA; /* Phys addr */
++ u32 dwVA; /* Virtual address in device process context */
++ u32 ulSize; /* SM block size in bytes */
++ u32 hClientProc; /* Process that allocated this mem block */
++} ;
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode);
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId);
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize);
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize);
++/* get available slot for new allocator */
++static s32 GetSlot(struct CMM_OBJECT *hCmmMgr);
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA);
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate a SM buffer, zero contents, and return the physical address
++ * and optional driver context virtual address(ppBufVA).
++ *
++ * The freelist is sorted in increasing size order. Get the first
++ * block that satifies the request and sort the remaining back on
++ * the freelist; if large enough. The kept block is placed on the
++ * inUseList.
++ */
++void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr, u32 uSize,
++ struct CMM_ATTRS *pAttrs, OUT void **ppBufVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ void *pBufPA = NULL;
++ struct CMM_MNODE *pNode = NULL;
++ struct CMM_MNODE *pNewNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ u32 uDeltaSize;
++ u8 *pByte = NULL;
++ s32 cnt;
++
++ if (pAttrs == NULL)
++ pAttrs = &CMM_DFLTALCTATTRS;
++
++ if (ppBufVA != NULL)
++ *ppBufVA = NULL;
++
++ if ((MEM_IsValidHandle(pCmmMgr, CMMSIGNATURE)) && (uSize != 0)) {
++ if (pAttrs->ulSegId > 0) {
++ /* SegId > 0 is SM */
++ /* get the allocator object for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, pAttrs->ulSegId);
++ /* keep block size a multiple of ulMinBlockSize */
++ uSize = ((uSize - 1) & ~(pCmmMgr->ulMinBlockSize - 1))
++ + pCmmMgr->ulMinBlockSize;
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pNode = GetFreeBlock(pAllocator, uSize);
++ }
++ if (pNode) {
++ uDeltaSize = (pNode->ulSize - uSize);
++ if (uDeltaSize >= pCmmMgr->ulMinBlockSize) {
++ /* create a new block with the leftovers and
++ * add to freelist */
++ pNewNode = GetNode(pCmmMgr, pNode->dwPA + uSize,
++ pNode->dwVA + uSize,
++ (u32)uDeltaSize);
++ /* leftovers go free */
++ AddToFreeList(pAllocator, pNewNode);
++ /* adjust our node's size */
++ pNode->ulSize = uSize;
++ }
++ /* Tag node with client process requesting allocation
++ * We'll need to free up a process's alloc'd SM if the
++ * client process goes away.
++ */
++ /* Return PID instead of process handle */
++ pNode->hClientProc = current->pid;
++
++ /* put our node on InUse list */
++ LST_PutTail(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pNode);
++ pBufPA = (void *)pNode->dwPA; /* physical address */
++ /* clear mem */
++ pByte = (u8 *)pNode->dwVA;
++ for (cnt = 0; cnt < (s32) uSize; cnt++, pByte++)
++ *pByte = 0;
++
++ if (ppBufVA != NULL) {
++ /* Virtual address */
++ *ppBufVA = (void *)pNode->dwVA;
++ }
++ }
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_CallocBuf dwPA %x, dwVA %x uSize"
++ "%x\n", pNode->dwPA, pNode->dwVA, uSize);
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return pBufPA;
++}
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ */
++DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs)
++{
++ struct CMM_OBJECT *pCmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct UTIL_SYSINFO sysInfo;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_Create: phCmmMgr: 0x%x\thDevObject: "
++ "0x%x\tpMgrAttrs: 0x%x\n", phCmmMgr, hDevObject, pMgrAttrs);
++ *phCmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pCmmObject, struct CMM_OBJECT, CMMSIGNATURE);
++ if (pCmmObject != NULL) {
++ if (pMgrAttrs == NULL)
++ pMgrAttrs = &CMM_DFLTMGRATTRS; /* set defaults */
++
++ /* 4 bytes minimum */
++ DBC_Assert(pMgrAttrs->ulMinBlockSize >= 4);
++ /* save away smallest block allocation for this cmm mgr */
++ pCmmObject->ulMinBlockSize = pMgrAttrs->ulMinBlockSize;
++ /* save away the systems memory page size */
++ sysInfo.dwPageSize = PAGE_SIZE;
++ sysInfo.dwAllocationGranularity = PAGE_SIZE;
++ sysInfo.dwNumberOfProcessors = 1;
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CMM_debugMask, GT_5CLASS,
++ "CMM_Create: Got system page size"
++ "= 0x%x\t\n", sysInfo.dwPageSize);
++ pCmmObject->dwPageSize = sysInfo.dwPageSize;
++ } else {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: failed to get system"
++ "page size\n");
++ pCmmObject->dwPageSize = 0;
++ status = DSP_EFAIL;
++ }
++ /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
++ * MEM_AllocObject */
++ if (DSP_SUCCEEDED(status)) {
++ /* create node free list */
++ pCmmObject->pNodeFreeListHead = LST_Create();
++ if (pCmmObject->pNodeFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: LST_Create() "
++ "failed \n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pCmmObject->hCmmLock);
++
++ if (DSP_SUCCEEDED(status))
++ *phCmmMgr = pCmmObject;
++ else
++ CMM_Destroy(pCmmObject, true);
++
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_Create: Object Allocation "
++ "Failure(CMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_INFO tempInfo;
++ DSP_STATUS status = DSP_SOK;
++ s32 nSlot;
++ struct CMM_MNODE *pNode;
++
++ DBC_Require(cRefs > 0);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* If not force then fail if outstanding allocations exist */
++ if (!bForce) {
++ /* Check for outstanding memory allocations */
++ status = CMM_GetInfo(hCmmMgr, &tempInfo);
++ if (DSP_SUCCEEDED(status)) {
++ if (tempInfo.ulTotalInUseCnt > 0) {
++ /* outstanding allocations */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* UnRegister SM allocator */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] != NULL) {
++ UnRegisterGPPSMSeg(pCmmMgr->
++ paGPPSMSegTab[nSlot]);
++ /* Set slot to NULL for future reuse */
++ pCmmMgr->paGPPSMSegTab[nSlot] = NULL;
++ }
++ }
++ }
++ if (pCmmMgr->pNodeFreeListHead != NULL) {
++ /* Free the free nodes */
++ while (!LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ /* (struct LST_ELEM*) pNode =
++ * LST_GetHead(pCmmMgr->pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ MEM_Free(pNode);
++ }
++ /* delete NodeFreeList list */
++ LST_Delete(pCmmMgr->pNodeFreeListHead);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (DSP_SUCCEEDED(status)) {
++ /* delete CS & cmm mgr object */
++ SYNC_DeleteCS(pCmmMgr->hCmmLock);
++ MEM_FreeObject(pCmmMgr);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void CMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "exiting CMM_Exit,ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ */
++DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr, void *pBufPA, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_EPOINTER;
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ struct CMM_ATTRS *pAttrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPA != NULL);
++ GT_1trace(CMM_debugMask, GT_ENTER, "CMM_FreeBuf pBufPA %x\n", pBufPA);
++ if (ulSegId == 0) {
++ pAttrs = &CMM_DFLTALCTATTRS;
++ ulSegId = pAttrs->ulSegId;
++ }
++ if (!(MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) || !(ulSegId > 0)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* get the allocator for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, ulSegId);
++ if (pAllocator != NULL) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->
++ pInUseListHead);
++ while (pCurNode) {
++ if ((u32)pBufPA == pCurNode->dwPA) {
++ /* Found it */
++ LST_RemoveElem(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ /* back to freelist */
++ AddToFreeList(pAllocator, pCurNode);
++ status = DSP_SOK; /* all right! */
++ break;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pInUseListHead, (struct LST_ELEM *)pCurNode);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the communication memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetCmmMgr(hDevObject, phCmmMgr);
++
++ return status;
++}
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current memory utilization information.
++ */
++DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ u32 ulSeg;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pAltr;
++ struct CMM_MNODE *pCurNode = NULL;
++
++ DBC_Require(pCmmInfo != NULL);
++
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCmmInfo->ulNumGPPSMSegs = 0; /* # of SM segments */
++ pCmmInfo->ulTotalInUseCnt = 0; /* Total # of outstanding alloc */
++ pCmmInfo->ulMinBlockSize = pCmmMgr->ulMinBlockSize; /* min block size */
++ /* check SM memory segments */
++ for (ulSeg = 1; ulSeg <= CMM_MAXGPPSEGS; ulSeg++) {
++ /* get the allocator object for this segment id */
++ pAltr = GetAllocator(pCmmMgr, ulSeg);
++ if (pAltr != NULL) {
++ pCmmInfo->ulNumGPPSMSegs++;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBasePa =
++ pAltr->dwSmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulTotalSegSize =
++ pAltr->ulDSPSize + pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwGPPBasePA =
++ pAltr->dwSmBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulGPPSize =
++ pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwDSPBaseVA =
++ pAltr->dwDSPBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulDSPSize =
++ pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBaseVa =
++ pAltr->dwVmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt = 0;
++ pCurNode = (struct CMM_MNODE *)LST_First(pAltr->
++ pInUseListHead);
++ /* Count inUse blocks */
++ while (pCurNode) {
++ pCmmInfo->ulTotalInUseCnt++;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt++;
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAltr->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ }
++ }
++ } /* end for */
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ */
++bool CMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /* "CM" for Comm Memory manager */
++ GT_create(&CMM_debugMask, "CM");
++ }
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "Entered CMM_Init,ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM to be used for later GPP SM
++ * allocations.
++ */
++DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 dwGPPBasePA,
++ u32 ulSize, u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor, u32 dwDSPBase,
++ u32 ulDSPSize, u32 *pulSegId,
++ u32 dwGPPBaseVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_ALLOCATOR *pSMA = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_MNODE *pNewNode;
++ s32 nSlot;
++
++ DBC_Require(ulSize > 0);
++ DBC_Require(pulSegId != NULL);
++ DBC_Require(dwGPPBasePA != 0);
++ DBC_Require(dwGPPBaseVA != 0);
++ DBC_Require((cFactor <= CMM_ADDTODSPPA) &&
++ (cFactor >= CMM_SUBFROMDSPPA));
++ GT_6trace(CMM_debugMask, GT_ENTER,
++ "CMM_RegisterGPPSMSeg dwGPPBasePA %x "
++ "ulSize %x dwDSPAddrOffset %x dwDSPBase %x ulDSPSize %x "
++ "dwGPPBaseVA %x\n", dwGPPBasePA, ulSize, dwDSPAddrOffset,
++ dwDSPBase, ulDSPSize, dwGPPBaseVA);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* make sure we have room for another allocator */
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ nSlot = GetSlot(pCmmMgr);
++ if (nSlot < 0) {
++ /* get a slot number */
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* Check if input ulSize is big enough to alloc at least one block */
++ if (DSP_SUCCEEDED(status)) {
++ if (ulSize < pCmmMgr->ulMinBlockSize) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "ulSize too small\n");
++ status = DSP_EINVALIDARG;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create, zero, and tag an SM allocator object */
++ MEM_AllocObject(pSMA, struct CMM_ALLOCATOR, SMEMSIGNATURE);
++ }
++ if (pSMA != NULL) {
++ pSMA->hCmmMgr = hCmmMgr; /* ref to parent */
++ pSMA->dwSmBase = dwGPPBasePA; /* SM Base phys */
++ pSMA->ulSmSize = ulSize; /* SM segment size in bytes */
++ pSMA->dwVmBase = dwGPPBaseVA;
++ pSMA->dwDSPPhysAddrOffset = dwDSPAddrOffset;
++ pSMA->cFactor = cFactor;
++ pSMA->dwDSPBase = dwDSPBase;
++ pSMA->ulDSPSize = ulDSPSize;
++ if (pSMA->dwVmBase == 0) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Error"
++ "MEM_LinearAddress()\n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* return the actual segment identifier */
++ *pulSegId = (u32) nSlot + 1;
++ /* create memory free list */
++ pSMA->pFreeListHead = LST_Create();
++ if (pSMA->pFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "Out Of Memory \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create memory in-use list */
++ pSMA->pInUseListHead = LST_Create();
++ if (pSMA->pInUseListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "LST_Create failed\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a mem node for this hunk-o-memory */
++ pNewNode = GetNode(pCmmMgr, dwGPPBasePA,
++ pSMA->dwVmBase, ulSize);
++ /* Place node on the SM allocator's free list */
++ if (pNewNode) {
++ LST_PutTail(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pNewNode);
++ } else {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Cleanup allocator */
++ UnRegisterGPPSMSeg(pSMA);
++ }
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_RegisterGPPSMSeg: SMA Object "
++ "Allocation Failure\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ /* make entry */
++ if (DSP_SUCCEEDED(status))
++ pCmmMgr->paGPPSMSegTab[nSlot] = pSMA;
++
++func_end:
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister GPP SM segments with the CMM.
++ */
++DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pSMA;
++ u32 ulId = ulSegId;
++
++ DBC_Require(ulSegId > 0);
++ if (MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ if (ulSegId == CMM_ALLSEGMENTS)
++ ulId = 1;
++
++ if ((ulId > 0) && (ulId <= CMM_MAXGPPSEGS)) {
++ while (ulId <= CMM_MAXGPPSEGS) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* slot = segId-1 */
++ pSMA = pCmmMgr->paGPPSMSegTab[ulId - 1];
++ if (pSMA != NULL) {
++ UnRegisterGPPSMSeg(pSMA);
++ /* Set alctr ptr to NULL for future
++ * reuse */
++ pCmmMgr->paGPPSMSegTab[ulId - 1] = NULL;
++ } else if (ulSegId != CMM_ALLSEGMENTS) {
++ status = DSP_EFAIL;
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (ulSegId != CMM_ALLSEGMENTS)
++ break;
++
++ ulId++;
++ } /* end while */
++ } else {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_UnRegisterGPPSMSeg: Bad "
++ "segment Id\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister the SM allocator by freeing all its resources and
++ * nulling cmm mgr table entry.
++ * Note:
++ * This routine is always called within cmm lock crit sect.
++ */
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA)
++{
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_MNODE *pNextNode = NULL;
++
++ DBC_Require(pSMA != NULL);
++ if (pSMA->pFreeListHead != NULL) {
++ /* free nodes on free list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pFreeListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pFreeListHead); /* delete freelist */
++ /* free nodes on InUse list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pInUseListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pInUseListHead); /* delete InUse list */
++ }
++ if ((void *) pSMA->dwVmBase != NULL)
++ MEM_UnmapLinearAddress((void *) pSMA->dwVmBase);
++
++ /* Free allocator itself */
++ MEM_FreeObject(pSMA);
++}
++
++/*
++ * ======== GetSlot ========
++ * Purpose:
++ * An available slot # is returned. Returns negative on failure.
++ */
++static s32 GetSlot(struct CMM_OBJECT *pCmmMgr)
++{
++ s32 nSlot = -1; /* neg on failure */
++ DBC_Require(pCmmMgr != NULL);
++ /* get first available slot in cmm mgr SMSegTab[] */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] == NULL)
++ break;
++
++ }
++ if (nSlot == CMM_MAXGPPSEGS) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Allocator "
++ "entry failure, max exceeded\n");
++ nSlot = -1; /* failed */
++ }
++ return nSlot;
++}
++
++/*
++ * ======== GetNode ========
++ * Purpose:
++ * Get a memory node from freelist or create a new one.
++ */
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize)
++{
++ struct CMM_MNODE *pNode = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require(dwPA != 0);
++ DBC_Require(dwVA != 0);
++ DBC_Require(ulSize != 0);
++ /* Check cmm mgr's node freelist */
++ if (LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ pNode = (struct CMM_MNODE *)MEM_Calloc(sizeof(struct CMM_MNODE),
++ MEM_PAGED);
++ } else {
++ /* surely a valid element */
++ /* (struct LST_ELEM*) pNode = LST_GetHead(pCmmMgr->
++ * pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ }
++ if (pNode == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS, "GetNode: Out Of Memory\n");
++ } else {
++ LST_InitElem((struct LST_ELEM *) pNode); /* set self */
++ pNode->dwPA = dwPA; /* Physical addr of start of block */
++ pNode->dwVA = dwVA; /* Virtual " " */
++ pNode->ulSize = ulSize; /* Size of block */
++ }
++ return pNode;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Put a memory node on the cmm nodelist for later use.
++ * Doesn't actually delete the node. Heap thrashing friendly.
++ */
++static void DeleteNode(struct CMM_OBJECT *pCmmMgr, struct CMM_MNODE *pNode)
++{
++ DBC_Require(pNode != NULL);
++ LST_InitElem((struct LST_ELEM *) pNode); /* init .self ptr */
++ LST_PutTail(pCmmMgr->pNodeFreeListHead, (struct LST_ELEM *) pNode);
++}
++
++/*
++ * ====== GetFreeBlock ========
++ * Purpose:
++ * Scan the free block list and return the first block that satisfies
++ * the size.
++ */
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize)
++{
++ if (pAllocator) {
++ struct CMM_MNODE *pCurNode = (struct CMM_MNODE *)
++ LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (uSize <= (u32) pCurNode->ulSize) {
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ return pCurNode;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ }
++ return NULL;
++}
++
++/*
++ * ======== AddToFreeList ========
++ * Purpose:
++ * Coelesce node into the freelist in ascending size order.
++ */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode)
++{
++ struct CMM_MNODE *pNodePrev = NULL;
++ struct CMM_MNODE *pNodeNext = NULL;
++ struct CMM_MNODE *pCurNode;
++ u32 dwThisPA;
++ u32 dwNextPA;
++
++ DBC_Require(pNode != NULL);
++ DBC_Require(pAllocator != NULL);
++ dwThisPA = pNode->dwPA;
++ dwNextPA = NEXT_PA(pNode);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (dwThisPA == NEXT_PA(pCurNode)) {
++ /* found the block ahead of this one */
++ pNodePrev = pCurNode;
++ } else if (dwNextPA == pCurNode->dwPA) {
++ pNodeNext = pCurNode;
++ }
++ if ((pNodePrev == NULL) || (pNodeNext == NULL)) {
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ } else {
++ /* got 'em */
++ break;
++ }
++ } /* while */
++ if (pNodePrev != NULL) {
++ /* combine with previous block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodePrev);
++ /* grow node to hold both */
++ pNode->ulSize += pNodePrev->ulSize;
++ pNode->dwPA = pNodePrev->dwPA;
++ pNode->dwVA = pNodePrev->dwVA;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodePrev);
++ }
++ if (pNodeNext != NULL) {
++ /* combine with next block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodeNext);
++ /* grow da node */
++ pNode->ulSize += pNodeNext->ulSize;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodeNext);
++ }
++ /* Now, let's add to freelist in increasing size order */
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (pNode->ulSize <= pCurNode->ulSize)
++ break;
++
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ /* if pCurNode is NULL then add our pNode to the end of the freelist */
++ if (pCurNode == NULL) {
++ LST_PutTail(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode);
++ } else {
++ /* insert our node before the current traversed node */
++ LST_InsertBefore(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode,
++ (struct LST_ELEM *)pCurNode);
++ }
++}
++
++/*
++ * ======== GetAllocator ========
++ * Purpose:
++ * Return the allocator for the given SM Segid.
++ * SegIds: 1,2,3..max.
++ */
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId)
++{
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require((ulSegId > 0) && (ulSegId <= CMM_MAXGPPSEGS));
++ pAllocator = pCmmMgr->paGPPSMSegTab[ulSegId - 1];
++ if (pAllocator != NULL) {
++ /* make sure it's for real */
++ if (!MEM_IsValidHandle(pAllocator, SMEMSIGNATURE)) {
++ pAllocator = NULL;
++ DBC_Assert(false);
++ }
++ }
++ return pAllocator;
++}
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create an address translator object.
++ */
++DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs)
++{
++ struct CMM_XLATOR *pXlatorObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phXlator != NULL);
++ DBC_Require(hCmmMgr != NULL);
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_XlatorCreate: phXlator: 0x%x\t"
++ "phCmmMgr: 0x%x\tpXlAttrs: 0x%x\n", phXlator,
++ hCmmMgr, pXlatorAttrs);
++ *phXlator = NULL;
++ if (pXlatorAttrs == NULL)
++ pXlatorAttrs = &CMM_DFLTXLATORATTRS; /* set defaults */
++
++ MEM_AllocObject(pXlatorObject, struct CMM_XLATOR, CMMXLATESIGNATURE);
++ if (pXlatorObject != NULL) {
++ pXlatorObject->hCmmMgr = hCmmMgr; /* ref back to CMM */
++ pXlatorObject->ulSegId = pXlatorAttrs->ulSegId; /* SM segId */
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_XlatorCreate: Object Allocation"
++ "Failure(CMM Xlator)\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status))
++ *phXlator = (struct CMM_XLATOROBJECT *) pXlatorObject;
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Free the Xlator resources.
++ * VM gets freed later.
++ */
++DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator, bool bForce)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ MEM_FreeObject(pXlator);
++ } else {
++ status = DSP_EHANDLE;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ */
++void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator, void *pVaBuf,
++ u32 uPaSize)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ void *pBuf = NULL;
++ struct CMM_ATTRS attrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hXlator != NULL);
++ DBC_Require(pXlator->hCmmMgr != NULL);
++ DBC_Require(pVaBuf != NULL);
++ DBC_Require(uPaSize > 0);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ attrs.ulSegId = pXlator->ulSegId;
++ *(volatile u32 *)pVaBuf = 0;
++ /* Alloc SM */
++ pBuf = CMM_CallocBuf(pXlator->hCmmMgr, uPaSize, &attrs, NULL);
++ if (pBuf) {
++ /* convert to translator(node/strm) process Virtual
++ * address */
++ *(volatile u32 **)pVaBuf =
++ (u32 *)CMM_XlatorTranslate(hXlator,
++ pBuf, CMM_PA2VA);
++ }
++ }
++ return pBuf;
++}
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free the given SM buffer and descriptor.
++ * Does not free virtual memory.
++ */
++DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator, void *pBufVa)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_EFAIL;
++ void *pBufPa = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufVa != NULL);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ /* convert Va to Pa so we can free it. */
++ pBufPa = CMM_XlatorTranslate(hXlator, pBufVa, CMM_VA2PA);
++ if (pBufPa) {
++ status = CMM_FreeBuf(pXlator->hCmmMgr, pBufPa,
++ pXlator->ulSegId);
++ if (DSP_FAILED(status)) {
++ /* Uh oh, this shouldn't happen. Descriptor
++ * gone! */
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "Cannot free DMA/ZCPY buffer"
++ "not allocated by MPU. PA %x, VA %x\n",
++ pBufPa, pBufVa);
++ DBC_Assert(false); /* CMM is leaking mem! */
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get translator info.
++ */
++DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator, IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId, bool bSetInfo)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((uSegId > 0) && (uSegId <= CMM_MAXGPPSEGS));
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ if (bSetInfo) {
++ /* set translators virtual address range */
++ pXlator->dwVirtBase = (u32)*pAddr;
++ pXlator->ulVirtSize = ulSize;
++ GT_2trace(CMM_debugMask, GT_3CLASS,
++ "pXlator->dwVirtBase %x, "
++ "ulVirtSize %x\n", pXlator->dwVirtBase,
++ pXlator->ulVirtSize);
++ } else { /* return virt base address */
++ *pAddr = (u8 *)pXlator->dwVirtBase;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ */
++void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator, void *pAddr,
++ enum CMM_XLATETYPE xType)
++{
++ u32 dwAddrXlate = 0;
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ struct CMM_OBJECT *pCmmMgr = NULL;
++ struct CMM_ALLOCATOR *pAlctr = NULL;
++ u32 dwOffset = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA));
++
++ if (!MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE))
++ goto loop_cont;
++
++ pCmmMgr = (struct CMM_OBJECT *)pXlator->hCmmMgr;
++ /* get this translator's default SM allocator */
++ DBC_Assert(pXlator->ulSegId > 0);
++ pAlctr = pCmmMgr->paGPPSMSegTab[pXlator->ulSegId - 1];
++ if (!MEM_IsValidHandle(pAlctr, SMEMSIGNATURE))
++ goto loop_cont;
++
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_VA2PA) ||
++ (xType == CMM_PA2VA)) {
++ if (xType == CMM_PA2VA) {
++ /* Gpp Va = Va Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)(pAlctr->dwSmBase -
++ pAlctr->ulDSPSize);
++ dwAddrXlate = pXlator->dwVirtBase + dwOffset;
++ /* Check if translated Va base is in range */
++ if ((dwAddrXlate < pXlator->dwVirtBase) ||
++ (dwAddrXlate >=
++ (pXlator->dwVirtBase + pXlator->ulVirtSize))) {
++ dwAddrXlate = 0; /* bad address */
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: "
++ "Virt addr out of range\n");
++ }
++ } else {
++ /* Gpp PA = Gpp Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)pXlator->dwVirtBase;
++ dwAddrXlate = pAlctr->dwSmBase - pAlctr->ulDSPSize +
++ dwOffset;
++ }
++ } else {
++ dwAddrXlate = (u32)pAddr;
++ }
++ /*Now convert address to proper target physical address if needed*/
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_PA2DSPPA)) {
++ /* Got Gpp Pa now, convert to DSP Pa */
++ dwAddrXlate = GPPPA2DSPPA((pAlctr->dwSmBase - pAlctr->
++ ulDSPSize), dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ } else if (xType == CMM_DSPPA2PA) {
++ /* Got DSP Pa, convert to GPP Pa */
++ dwAddrXlate = DSPPA2GPPPA(pAlctr->dwSmBase - pAlctr->ulDSPSize,
++ dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ }
++loop_cont:
++ if (!dwAddrXlate) {
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: Can't translate"
++ " address: 0x%x xType %x\n", pAddr, xType);
++ } else {
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_XlatorTranslate: pAddr %x, xType"
++ " %x, dwAddrXlate %x\n", pAddr, xType, dwAddrXlate);
++ }
++ return (void *)dwAddrXlate;
++}
+diff --git a/drivers/dsp/bridge/pmgr/cod.c b/drivers/dsp/bridge/pmgr/cod.c
+new file mode 100644
+index 0000000..6363f1e
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cod.c
+@@ -0,0 +1,683 @@
++/*
++ * cod.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.c ========
++ * This module implements DSP code management for the DSP/BIOS Bridge
++ * environment. It is mostly a thin wrapper.
++ *
++ * This module provides an interface for loading both static and
++ * dynamic code objects onto DSP systems.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Consolidated DBL to DBLL loader name
++ *! 24-Feb-2003 swa: PMGR Code review comments incorporated.
++ *! 18-Apr-2002 jeh: Added DBL function tables.
++ *! 20-Nov-2001 jeh: Removed call to ZL_loadArgs function.
++ *! 19-Oct-2001 jeh: Access DBL as a static library. Added COD_GetBaseLib,
++ *! COD_GetLoader, removed COD_LoadSection, COD_UnloadSection.
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 07-Aug-2001 rr: hMgr->baseLib is updated after zlopen in COD_LoadBase.
++ *! 18-Apr-2001 jeh: Check for fLoaded flag before ZL_unload, to allow
++ *! COD_OpenBase to be used.
++ *! 11-Jan-2001 jeh: Added COD_OpenBase (not used yet, since there is an
++ *! occasional crash).
++ *! 02-Aug-2000 kc: Added COD_ReadSection to COD module. Incorporates use
++ *! of ZL_readSect (new function in ZL module).
++ *! 28-Feb-2000 rr: New GT Usage Implementation
++ *! 08-Dec-1999 ag: Removed x86 specific __asm int 3.
++ *! 02-Oct-1999 ag: Added #ifdef DEBUGINT3COD for debug.
++ *! 20-Sep-1999 ag: Removed call to GT_set().
++ *! 04-Jun-1997 cr: Added validation of argc/argv pair in COD_LoadBase, as it
++ *! is a requirement to ZL_loadArgs.
++ *! 31-May-1997 cr: Changed COD_LoadBase argc value from u32 to int, added
++ *! DSP_ENOTIMPL return value to COD_Create when attrs != NULL.
++ *! 29-May-1997 cr: Added debugging support.
++ *! 24-Oct-1996 gp: Added COD_GetSection().
++ *! 18-Jun-1996 gp: Updated GetSymValue() to check for lib; updated E_ codes.
++ *! 12-Jun-1996 gp: Imported CSL_ services for strcpyn(); Added ref counting.
++ *! 20-May-1996 mg: Adapted for new MEM and LDR modules.
++ *! 08-May-1996 mg: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++/* Include appropriate loader header file */
++#include <dspbridge/dbll.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cod.h>
++
++/* magic number for handle validation */
++#define MAGIC 0xc001beef
++
++/* macro to validate COD manager handles */
++#define IsValid(h) ((h) != NULL && (h)->ulMagic == MAGIC)
++
++/*
++ * ======== COD_MANAGER ========
++ */
++struct COD_MANAGER {
++ struct DBLL_TarObj *target;
++ struct DBLL_LibraryObj *baseLib;
++ bool fLoaded; /* Base library loaded? */
++ u32 ulEntry;
++ struct LDR_MODULE *hDll;
++ struct DBLL_Fxns fxns;
++ struct DBLL_Attrs attrs;
++ char szZLFile[COD_MAXPATHLENGTH];
++ u32 ulMagic;
++} ;
++
++/*
++ * ======== COD_LIBRARYOBJ ========
++ */
++struct COD_LIBRARYOBJ {
++ struct DBLL_LibraryObj *dbllLib;
++ struct COD_MANAGER *hCodMgr;
++} ;
++
++static u32 cRefs = 0L;
++
++#if GT_TRACE
++static struct GT_Mask COD_debugMask = { NULL, NULL };
++#endif
++
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static bool NoOp(void);
++
++/*
++ * ======== COD_Close ========
++ */
++void COD_Close(struct COD_LIBRARYOBJ *lib)
++{
++ struct COD_MANAGER *hMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(((struct COD_LIBRARYOBJ *)lib)->hCodMgr));
++
++ hMgr = lib->hCodMgr;
++ hMgr->fxns.closeFxn(lib->dbllLib);
++
++ MEM_Free(lib);
++}
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system.
++ * This object can be used to load an initial program image with
++ * arguments that can later be expanded with
++ * dynamically loaded object files.
++ *
++ */
++DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs)
++{
++ struct COD_MANAGER *hMgrNew;
++ struct DBLL_Attrs zlAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Create, Args: \t\nphMgr: "
++ "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n",
++ phMgr, pstrDummyFile, attrs);
++ /* assume failure */
++ *phMgr = NULL;
++
++ /* we don't support non-default attrs yet */
++ if (attrs != NULL)
++ return DSP_ENOTIMPL;
++
++ hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED);
++ if (hMgrNew == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Create: Out Of Memory\n");
++ return DSP_EMEMORY;
++ }
++
++ hMgrNew->ulMagic = MAGIC;
++
++ /* Set up loader functions */
++ hMgrNew->fxns = dbllFxns;
++
++ /* initialize the ZL module */
++ hMgrNew->fxns.initFxn();
++
++ zlAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ zlAttrs.free = (DBLL_FreeFxn)NoOp;
++ zlAttrs.fread = (DBLL_ReadFxn)KFILE_Read;
++ zlAttrs.fseek = (DBLL_SeekFxn)KFILE_Seek;
++ zlAttrs.ftell = (DBLL_TellFxn)KFILE_Tell;
++ zlAttrs.fclose = (DBLL_FCloseFxn)KFILE_Close;
++ zlAttrs.fopen = (DBLL_FOpenFxn)KFILE_Open;
++ zlAttrs.symLookup = NULL;
++ zlAttrs.baseImage = true;
++ zlAttrs.logWrite = NULL;
++ zlAttrs.logWriteHandle = NULL;
++ zlAttrs.write = NULL;
++ zlAttrs.rmmHandle = NULL;
++ zlAttrs.wHandle = NULL;
++ zlAttrs.symHandle = NULL;
++ zlAttrs.symArg = NULL;
++
++ hMgrNew->attrs = zlAttrs;
++
++ status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs);
++
++ if (DSP_FAILED(status)) {
++ COD_Delete(hMgrNew);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Create:ZL Create Failed: 0x%x\n", status);
++ return COD_E_ZLCREATEFAILED;
++ }
++
++ /* return the new manager */
++ *phMgr = hMgrNew;
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "COD_Create: Success CodMgr: 0x%x\n", *phMgr);
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ */
++void COD_Delete(struct COD_MANAGER *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_Delete:hMgr 0x%x\n", hMgr);
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded)
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ }
++ if (hMgr->target) {
++ hMgr->fxns.deleteFxn(hMgr->target);
++ hMgr->fxns.exitFxn();
++ }
++ hMgr->ulMagic = ~MAGIC;
++ MEM_Free(hMgr);
++}
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ *
++ */
++void COD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ */
++DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(plib != NULL);
++
++ *plib = (struct DBLL_LibraryObj *) hManager->baseLib;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetBaseName ========
++ */
++DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager, char *pszName,
++ u32 uSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pszName != NULL);
++
++ if (uSize <= COD_MAXPATHLENGTH)
++ strncpy(pszName, hManager->szZLFile, uSize);
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ *
++ */
++DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager, u32 *pulEntry)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pulEntry != NULL);
++
++ *pulEntry = hManager->ulEntry;
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_GetEntry:ulEntr 0x%x\n",
++ *pulEntry);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBLL loader.
++ */
++DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(phLoader != NULL);
++
++ *phLoader = (struct DBLL_TarObj *)hManager->target;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ */
++DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT u32 *puAddr, OUT u32 *puLen)
++{
++ struct COD_MANAGER *hManager;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(puAddr != NULL);
++ DBC_Require(puLen != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER,
++ "Entered COD_GetSection Args \t\n lib: "
++ "0x%x\t\npstrsect: 0x%x\t\npuAddr: 0x%x\t\npuLen: 0x%x\n",
++ lib, pstrSect, puAddr, puLen);
++ *puAddr = 0;
++ *puLen = 0;
++ if (lib != NULL) {
++ hManager = lib->hCodMgr;
++ status = hManager->fxns.getSectFxn(lib->dbllLib, pstrSect,
++ puAddr, puLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection: Section %s not"
++ "found\n", pstrSect);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection:No Symbols loaded\n");
++ }
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ *
++ */
++DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hMgr, char *pstrSym,
++ u32 *pulValue)
++{
++ struct DBLL_Symbol *pSym;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pstrSym != NULL);
++ DBC_Require(pulValue != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_GetSymValue Args \t\n"
++ "hMgr: 0x%x\t\npstrSym: 0x%x\t\npulValue: 0x%x\n",
++ hMgr, pstrSym, pulValue);
++ if (hMgr->baseLib) {
++ if (!hMgr->fxns.getAddrFxn(hMgr->baseLib, pstrSym, &pSym)) {
++ if (!hMgr->fxns.getCAddrFxn(hMgr->baseLib, pstrSym,
++ &pSym)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSymValue: "
++ "Symbols not found\n");
++ return COD_E_SYMBOLNOTFOUND;
++ }
++ }
++ } else {
++ GT_0trace(COD_debugMask, GT_7CLASS, "COD_GetSymValue: "
++ "No Symbols loaded\n");
++ return COD_E_NOSYMBOLSLOADED;
++ }
++
++ *pulValue = pSym->value;
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ *
++ */
++bool COD_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!COD_debugMask.flags);
++ GT_create(&COD_debugMask, "CO");
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "Entered COD_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0));
++ return fRetVal;
++}
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Details:
++ * if nArgc doesn't match the number of arguments in the aArgs array, the
++ * aArgs array is searched for a NULL terminating entry, and argc is
++ * recalculated to reflect this. In this way, we can support NULL
++ * terminating aArgs arrays, if nArgc is very large.
++ */
++DSP_STATUS COD_LoadBase(struct COD_MANAGER *hMgr, u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb, char *envp[])
++{
++ DBLL_Flags flags;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DSP_STATUS status;
++ u32 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(nArgc > 0);
++ DBC_Require(aArgs != NULL);
++ DBC_Require(aArgs[0] != NULL);
++ DBC_Require(pfnWrite != NULL);
++ DBC_Require(hMgr->baseLib != NULL);
++
++ GT_6trace(COD_debugMask, GT_ENTER,
++ "Entered COD_LoadBase, hMgr: 0x%x\n \t"
++ "nArgc: 0x%x\n\taArgs: 0x%x\n\tpfnWrite: 0x%x\n\tpArb:"
++ " 0x%x\n \tenvp: 0x%x\n", hMgr, nArgc, aArgs, pfnWrite,
++ pArb, envp);
++ /*
++ * Make sure every argv[] stated in argc has a value, or change argc to
++ * reflect true number in NULL terminated argv array.
++ */
++ for (i = 0; i < nArgc; i++) {
++ if (aArgs[i] == NULL) {
++ nArgc = i;
++ break;
++ }
++ }
++
++ /* set the write function for this operation */
++ hMgr->fxns.getAttrsFxn(hMgr->target, &saveAttrs);
++
++ newAttrs = saveAttrs;
++ newAttrs.write = (DBLL_WriteFxn)pfnWrite;
++ newAttrs.wHandle = pArb;
++ newAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ newAttrs.free = (DBLL_FreeFxn)NoOp;
++ newAttrs.logWrite = NULL;
++ newAttrs.logWriteHandle = NULL;
++
++ /* Load the image */
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = hMgr->fxns.loadFxn(hMgr->baseLib, flags, &newAttrs,
++ &hMgr->ulEntry);
++ if (DSP_FAILED(status)) {
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_LoadBase: COD Load failed: "
++ "0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status))
++ hMgr->fLoaded = true;
++ else
++ hMgr->baseLib = NULL;
++
++ return status;
++}
++
++/*
++ * ======== COD_Open ========
++ * Open library for reading sections.
++ */
++DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_LIBRARYOBJ *lib = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++ DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB);
++ DBC_Require(pLib != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t "
++ "pszCoffPath: 0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr,
++ pszCoffPath, flags, pLib);
++
++ *pLib = NULL;
++
++ lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED);
++ if (lib == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Open: Out Of Memory\n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lib->hCodMgr = hMgr;
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags,
++ &lib->dbllLib);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Open failed: 0x%x\n", status);
++ } else {
++ *pLib = lib;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections.
++ */
++DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++
++ GT_2trace(COD_debugMask, GT_ENTER,
++ "Entered COD_OpenBase, hMgr: 0x%x\n\t"
++ "pszCoffPath: 0x%x\n", hMgr, pszCoffPath);
++
++ /* if we previously opened a base image, close it now */
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "Base Image is already loaded. "
++ "Unloading it...\n");
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++ hMgr->fLoaded = false;
++ }
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ hMgr->baseLib = NULL;
++ } else {
++ GT_0trace(COD_debugMask, GT_1CLASS,
++ "COD_OpenBase: Opening the base image ...\n");
++ }
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_OpenBase: COD Open failed\n");
++ } else {
++ /* hang onto the library for subsequent sym table usage */
++ hMgr->baseLib = lib;
++ strncpy(hMgr->szZLFile, pszCoffPath, COD_MAXPATHLENGTH);
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ */
++DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT char *pstrContent, IN u32 cContentSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(pstrContent != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_ReadSection Args: 0x%x,"
++ " 0x%x, 0x%x, 0x%x\n", lib, pstrSect, pstrContent,
++ cContentSize);
++
++ if (lib != NULL) {
++ status = lib->hCodMgr->fxns.readSectFxn(lib->dbllLib, pstrSect,
++ pstrContent,
++ cContentSize);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection failed: 0x%lx\n", status);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection: No Symbols loaded\n");
++ }
++ return status;
++}
++
++/*
++ * ======== NoOp ========
++ * Purpose:
++ * No Operation.
++ *
++ */
++static bool NoOp(void)
++{
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbl.c b/drivers/dsp/bridge/pmgr/dbl.c
+new file mode 100644
+index 0000000..641b011
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbl.c
+@@ -0,0 +1,1385 @@
++/*
++ * dbl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.c ========
++ * Dynamic BOF Loader library. Contains functions related to
++ * loading and unloading symbols/code/data on DSP.
++ * Also contains other support functions.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 24-May-2002 jeh Free DCD sects in DBL_close().
++ *! 19-Mar-2002 jeh Changes made to match dynamic loader (dbll.c): Pass
++ *! DBL_Library to DBL_getAddr() instead of DBL_Target,
++ *! eliminate scope param, use DBL_Symbol. Pass attrs to
++ *! DBL_load(), DBL_unload().
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 31-Jul-2001 jeh Include windows.h.
++ *! 06-Jun-2001 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbof.h>
++#include <dspbridge/dbl.h>
++
++#define DBL_TARGSIGNATURE 0x544c4244 /* "TLBD" */
++#define DBL_LIBSIGNATURE 0x4c4c4244 /* "LLBD" */
++
++#define C54TARG 0
++#define C55TARG 1
++#define NUMTARGS 2
++
++#define C54MAGIC 0x98 /* Magic number for TI C54 COF */
++#define C55MAGIC 0x9c /* Magic number for LEAD3 (C55) COF */
++
++/* Three task phases */
++#define CREATEPHASE 0
++#define DELETEPHASE 1
++#define EXECUTEPHASE 2
++#define NONE 3 /* For overlay section with phase not specified */
++
++/* Default load buffer size */
++#define LOADBUFSIZE 0x800
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++/*
++ * Macros for accessing the following types of overlay data within a
++ * structure of type OvlyData:
++ * - Overlay data not associated with a particular phase
++ * - Create phase overlay data
++ * - Delete phase overlay data
++ * - Execute phase overlay data
++ */
++#define numOtherSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define numCreateSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numCreateSects)
++#define numDeleteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numDeleteSects)
++#define numExecuteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numExecuteSects)
++#define otherOffset(pOvlyData) 0
++#define createOffset(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define deleteOffset(pOvlyData) (createOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numCreateSects))
++#define executeOffset(pOvlyData) (deleteOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numDeleteSects))
++/*
++ * ======== OvlyHdr ========
++ */
++struct OvlyHdr {
++ struct DBOF_OvlySectHdr dbofHdr;
++ char *pName; /* Name of overlay section */
++ u16 createRef; /* Reference count for create phase */
++ u16 deleteRef; /* Reference count for delete phase */
++ u16 executeRef; /* Execute phase ref count */
++ u16 otherRef; /* Unspecified phase ref count */
++} ;
++
++/*
++ * ======== OvlyData ========
++ */
++struct OvlyData {
++ struct OvlyHdr hdr;
++ struct DBOF_OvlySectData data[1];
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBL_Symbol sym;
++ char *pSymName;
++};
++
++/*
++ * ======== DCDSect ========
++ */
++struct DCDSect {
++ struct DBOF_DCDSectHdr sectHdr;
++ char *pData;
++} ;
++
++/*
++ * ======== DBL_TargetObj ========
++ */
++struct DBL_TargetObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_Attrs dblAttrs; /* file read, write, etc. functions */
++ char *pBuf; /* Load buffer */
++};
++
++/*
++ * ======== TargetInfo ========
++ */
++struct TargetInfo {
++ u16 dspType; /* eg, C54TARG, C55TARG */
++ u32 magic; /* COFF magic number, identifies target type */
++ u16 wordSize; /* Size of a DSP word */
++ u16 mauSize; /* Size of minimum addressable unit */
++ u16 charSize; /* For C55x, mausize = 1, but charsize = 2 */
++} ;
++
++/*
++ * ======== DBL_LibraryObj ========
++ * Represents a library loaded on a target.
++ */
++struct DBL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_TargetObj *pTarget; /* Target for this library */
++ struct KFILE_FileObj *file; /* DBOF file handle */
++ bool byteSwapped; /* Are bytes swapped? */
++ struct DBOF_FileHdr fileHdr; /* Header of DBOF file */
++ u16 nSymbols; /* Number of DSP/Bridge symbols */
++ struct Symbol *symbols; /* Table of DSP/Bridge symbols */
++ u16 nDCDSects; /* Number of DCD sections */
++ u16 nOvlySects; /* Number of overlay nodes */
++ struct DCDSect *dcdSects; /* DCD section data */
++ struct OvlyData **ppOvlyData; /* Array of overlay section data */
++ struct TargetInfo *pTargetInfo; /* Entry in targetTab[] below */
++} ;
++
++#if GT_TRACE
++static struct GT_Mask DBL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static u32 magicTab[NUMTARGS] = { C54MAGIC, C55MAGIC };
++
++static struct TargetInfo targetTab[] = {
++ /* targ magic wordsize mausize charsize */
++ {C54TARG, C54MAGIC, 2, 2, 2}, /* C54 */
++ {C55TARG, C55MAGIC, 2, 1, 2}, /* C55 */
++};
++
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects);
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++
++/*
++ * ======== DBL_close ========
++ * Purpose:
++ * Close library opened with DBL_open.
++ */
++void DBL_close(struct DBL_LibraryObj *lib)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_close: lib: 0x%x\n", lib);
++
++ /* Free symbols */
++ if (pdblLib->symbols) {
++ for (i = 0; i < pdblLib->nSymbols; i++) {
++ if (pdblLib->symbols[i].pSymName)
++ MEM_Free(pdblLib->symbols[i].pSymName);
++
++ }
++ MEM_Free(pdblLib->symbols);
++ }
++
++ /* Free DCD sects */
++ if (pdblLib->dcdSects) {
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (pdblLib->dcdSects[i].pData)
++ MEM_Free(pdblLib->dcdSects[i].pData);
++
++ }
++ MEM_Free(pdblLib->dcdSects);
++ }
++
++ /* Free overlay sects */
++ if (pdblLib->ppOvlyData) {
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (pdblLib->ppOvlyData[i]) {
++ if (pdblLib->ppOvlyData[i]->hdr.pName) {
++ MEM_Free(pdblLib->ppOvlyData[i]->
++ hdr.pName);
++ }
++ MEM_Free(pdblLib->ppOvlyData[i]);
++ }
++ }
++ MEM_Free(pdblLib->ppOvlyData);
++ }
++
++ /* Close the file */
++ if (pdblLib->file)
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++
++
++ MEM_FreeObject(pdblLib);
++}
++
++/*
++ * ======== DBL_create ========
++ * Purpose:
++ * Create a target object by specifying the alloc, free, and
++ * write functions for the target.
++ */
++DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget, struct DBL_Attrs *pAttrs)
++{
++ struct DBL_TargetObj *pdblTarget = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_create: pTarget: 0x%x pAttrs: 0x%x\n",
++ pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pdblTarget, struct DBL_TargetObj, DBL_TARGSIGNATURE);
++ if (pdblTarget == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pdblTarget->dblAttrs = *pAttrs;
++ /* Allocate buffer for loading target */
++ pdblTarget->pBuf = MEM_Calloc(LOADBUFSIZE, MEM_PAGED);
++ if (pdblTarget->pBuf == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = pdblTarget;
++ } else {
++ *pTarget = NULL;
++ if (pdblTarget)
++ DBL_delete(pdblTarget);
++
++ }
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ ((MEM_IsValidHandle((*pTarget), DBL_TARGSIGNATURE)) ||
++ (DSP_FAILED(status) && *pTarget == NULL)));
++ return status;
++}
++
++/*
++ * ======== DBL_delete ========
++ * Purpose:
++ * Delete target object and free resources for any loaded libraries.
++ */
++void DBL_delete(struct DBL_TargetObj *target)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "DBL_delete: target: 0x%x\n", target);
++
++ if (target->pBuf)
++ MEM_Free(target->pBuf);
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== DBL_exit ========
++ * Purpose
++ * Discontinue usage of DBL module.
++ */
++void DBL_exit()
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(DBL_debugMask, GT_5CLASS,
++ "DBL_exit() ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBL_getAddr ========
++ * Purpose:
++ * Get address of name in the specified library.
++ */
++bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getAddr: libt: 0x%x name: %s pAddr: "
++ "0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if (CSL_Strcmp(name, symbol->pSymName) == 0) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getAttrs ========
++ * Purpose:
++ * Retrieve the attributes of the target.
++ */
++void DBL_getAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_getAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ *pAttrs = target->dblAttrs;
++}
++
++/*
++ * ======== DBL_getCAddr ========
++ * Purpose:
++ * Get address of "C" name in the specified library.
++ */
++bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getCAddr: target: 0x%x name:%s pAddr:"
++ " 0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if ((CSL_Strcmp(name, symbol->pSymName) == 0) ||
++ (CSL_Strcmp(name, symbol->pSymName + 1) == 0 &&
++ symbol->pSymName[0] == '_')) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getEntry ========
++ * Purpose:
++ * Get program entry point.
++ *
++ */
++bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_getEntry: lib: 0x%x pEntry: 0x%x\n", lib, pEntry);
++ *pEntry = pdblLib->fileHdr.entry;
++
++ return true;
++}
++
++/*
++ * ======== DBL_getSect ========
++ * Purpose:
++ * Get address and size of a named section.
++ */
++DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_4trace(DBL_debugMask, GT_ENTER,
++ "DBL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++
++ /*
++ * Check for DCD and overlay sections. Overlay loader uses DBL_getSect
++ * to determine whether or not a node has overlay sections.
++ * DCD section names begin with '.'
++ */
++ if (name[0] == '.') {
++ /* Get DCD section size (address is 0, since it's a NOLOAD). */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name,
++ name) == 0) {
++ *pAddr = 0;
++ *pSize = pdblLib->dcdSects[i].sectHdr.size *
++ pdblLib->pTargetInfo->mauSize;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ } else {
++ /* Check for overlay section */
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (CSL_Strcmp(pdblLib->ppOvlyData[i]->hdr.pName,
++ name) == 0) {
++ /* Address and size are meaningless */
++ *pAddr = 0;
++ *pSize = 0;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_init ========
++ * Purpose:
++ * Initialize DBL module.
++ */
++bool DBL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBL_debugMask.flags);
++ GT_create(&DBL_debugMask, "BL"); /* "BL" for dBL */
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBL_debugMask, GT_5CLASS, "DBL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBL_load ========
++ * Purpose:
++ * Add symbols/code/data defined in file to that already present
++ * on the target.
++ */
++DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ struct DBL_TargetObj *dbl;
++ u16 i;
++ u16 nSects;
++ DSP_STATUS status = DSP_EFAIL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_load: lib: 0x%x flags: "
++ "0x%x attrs: 0x%x pEntry: 0x%x\n", lib, flags, attrs, pEntry);
++
++ dbl = pdblLib->pTarget;
++ *pEntry = pdblLib->fileHdr.entry;
++ nSects = pdblLib->fileHdr.numSects;
++ dbl->dblAttrs = *attrs;
++
++ for (i = 0; i < nSects; i++) {
++ /* Load the section at the current file offset */
++ status = loadSect(dbl, lib);
++ if (DSP_FAILED(status))
++ break;
++
++ }
++
++ /* Done with file, we can close it */
++ if (pdblLib->file) {
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++ pdblLib->file = NULL;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_loadSect ========
++ * Purpose:
++ * Load a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ s32 allocdSects = 0;
++ u32 loadAddr;
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ u32 ulBytes;
++ u16 mauSize;
++ u16 wordSize;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *name = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++ DBC_Require(attrs != NULL);
++ DBC_Require(attrs->write != NULL);
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_loadSect: lib: 0x%x sectName: %s "
++ "attrs: 0x%x\n", lib, sectName, attrs);
++ dbl = lib->pTarget;
++ mauSize = lib->pTargetInfo->mauSize;
++ wordSize = lib->pTargetInfo->wordSize;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ name = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(name, sectName, CSL_Strlen(name))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /*
++ * If node overlay, phase will be encoded in name. If not node
++ * overlay, set phase to NONE.
++ */
++ phase = (CSL_Strcmp(name, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ /* Get reference count of node phase to be loaded, offset into
++ * overlay data array, and number of sections to overlay. */
++ switch (phase) {
++ case NONE:
++ /* Not a node overlay */
++ phaseRef = &pOvlyData->hdr.otherRef;
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ phaseRef = &pOvlyData->hdr.createRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ if (*otherRef) {
++ /* The overlay sections where node phase was
++ * not specified, have already been loaded. */
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ } else {
++ /* Overlay sections where node phase was not
++ * specified get loaded at create time, along
++ * with create sects. */
++ nSects = numCreateSects(pOvlyData) +
++ numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ }
++ break;
++ case DELETEPHASE:
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ break;
++ case EXECUTEPHASE:
++ phaseRef = &pOvlyData->hdr.executeRef;
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ /* Do overlay if reference count is 0 */
++ if (!(*phaseRef)) {
++ /* "Allocate" all sections */
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ status = (dbl->dblAttrs.alloc)(dbl->dblAttrs.
++ rmmHandle, space, size, 0,
++ &runAddr, true);
++ if (DSP_FAILED(status))
++ break;
++
++ allocdSects++;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections */
++ for (i = 0; i < nSects; i++) {
++ loadAddr = pOvlyData->data[offset + i].
++ loadAddr;
++ runAddr = pOvlyData->data[offset + i].
++ runAddr;
++ size = pOvlyData->data[offset + i].
++ size;
++ space = pOvlyData->data[offset + i].
++ page;
++ /* Convert to word address, call
++ * write function */
++ loadAddr /= (wordSize / mauSize);
++ runAddr /= (wordSize / mauSize);
++ ulBytes = size * mauSize;
++ if ((*attrs->write)(attrs->wHandle,
++ runAddr, (void *)loadAddr, ulBytes,
++ space) != ulBytes) {
++ GT_0trace(DBL_debugMask,
++ GT_6CLASS,
++ "DBL_loadSect: write"
++ " failed\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ }
++ }
++ /* Free sections on failure */
++ if (DSP_FAILED(status))
++ freeSects(dbl, pOvlyData, offset, allocdSects);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Increment reference counts */
++ if (otherRef)
++ *otherRef = *otherRef + 1;
++
++ *phaseRef = *phaseRef + 1;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_open ========
++ * Purpose:
++ * DBL_open() returns a library handle that can be used to
++ * load/unload the symbols/code/data via DBL_load()/DBL_unload().
++ */
++DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file, DBL_Flags flags,
++ struct DBL_LibraryObj **pLib)
++{
++ struct DBL_LibraryObj *pdblLib = NULL;
++ u16 nSymbols;
++ u16 nDCDSects;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(target->dblAttrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER, "DBL_open: target: 0x%x file: %s "
++ "pLib: 0x%x\n", target, file, pLib);
++ /* Allocate DBL library object */
++ MEM_AllocObject(pdblLib, struct DBL_LibraryObj, DBL_LIBSIGNATURE);
++ if (pdblLib == NULL)
++ status = DSP_EMEMORY;
++
++ /* Open the file */
++ if (DSP_SUCCEEDED(status)) {
++ pdblLib->pTarget = target;
++ pdblLib->file = (*target->dblAttrs.fopen)(file, "rb");
++ if (pdblLib->file == NULL)
++ status = DSP_EFOPEN;
++
++ }
++ /* Read file header */
++ if (DSP_SUCCEEDED(status)) {
++ status = readHeader(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read file header\n");
++ }
++ }
++ /* Allocate symbol table */
++ if (DSP_SUCCEEDED(status)) {
++ nSymbols = pdblLib->nSymbols = pdblLib->fileHdr.numSymbols;
++ pdblLib->symbols = MEM_Calloc(nSymbols * sizeof(struct Symbol),
++ MEM_PAGED);
++ if (pdblLib->symbols == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read all the symbols */
++ if (DSP_SUCCEEDED(status)) {
++ status = readSymbols(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read symbols\n");
++ }
++ }
++ /* Allocate DCD sect table */
++ if (DSP_SUCCEEDED(status)) {
++ nDCDSects = pdblLib->nDCDSects = pdblLib->fileHdr.numDCDSects;
++ pdblLib->dcdSects = MEM_Calloc(nDCDSects *
++ sizeof(struct DCDSect), MEM_PAGED);
++ if (pdblLib->dcdSects == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read DCD sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readDCDSects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read DCD sections\n");
++ }
++ }
++ /* Read overlay sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readOvlySects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read "
++ "overlay sections\n");
++ }
++ }
++ if (DSP_FAILED(status)) {
++ *pLib = NULL;
++ if (pdblLib != NULL)
++ DBL_close((struct DBL_LibraryObj *) pdblLib);
++
++ } else {
++ *pLib = pdblLib;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*pLib), DBL_LIBSIGNATURE))) ||
++ (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBL_readSect ========
++ * Purpose:
++ * Read COFF section into a character buffer.
++ */
++DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name, char *pContent,
++ u32 size)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ u32 mauSize;
++ u32 max;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++
++ mauSize = pdblLib->pTargetInfo->mauSize;
++
++ /* Attempt to find match with DCD section names. */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name, name) == 0) {
++ /* Match found */
++ max = pdblLib->dcdSects[i].sectHdr.size * mauSize;
++ max = (max > size) ? size : max;
++ memcpy(pContent, pdblLib->dcdSects[i].pData, max);
++ status = DSP_SOK;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_setAttrs ========
++ * Purpose:
++ * Set the attributes of the target.
++ */
++void DBL_setAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++
++ target->dblAttrs = *pAttrs;
++}
++
++/*
++ * ======== DBL_unload ========
++ * Purpose:
++ * Remove the symbols/code/data corresponding to the library lib.
++ */
++void DBL_unload(struct DBL_LibraryObj *lib, struct DBL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_unload: lib: 0x%x\n", lib);
++
++ /* Nothing to do for static loading */
++}
++
++/*
++ * ======== DBL_unloadSect ========
++ * Purpose:
++ * Unload a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *pName = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_unloadSect: lib: 0x%x sectName: %s\n", lib, sectName);
++ dbl = lib->pTarget;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ pName = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(pName, sectName, CSL_Strlen(pName))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /* If node overlay, phase will be encoded in name. */
++ phase = (CSL_Strcmp(pName, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ switch (phase) {
++ case NONE:
++ nSects = numOtherSects(pOvlyData);
++ phaseRef = &pOvlyData->hdr.otherRef;
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.createRef;
++ break;
++ case DELETEPHASE:
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ break;
++ case EXECUTEPHASE:
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.executeRef;
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ if (*phaseRef) {
++ *phaseRef = *phaseRef - 1;
++ if (*phaseRef == 0) {
++ /* Unload overlay sections for phase */
++ freeSects(dbl, pOvlyData, offset, nSects);
++ }
++ if (phase == DELETEPHASE) {
++ DBC_Assert(*otherRef);
++ *otherRef = *otherRef - 1;
++ if (*otherRef == 0) {
++ /* Unload other overlay sections */
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ freeSects(dbl, pOvlyData, offset,
++ nSects);
++ }
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== freeSects ========
++ * Purpose:
++ * Free section
++ */
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects)
++{
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ s32 i;
++
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ if (!(dbl->dblAttrs.free)
++ (dbl->dblAttrs.rmmHandle, space, runAddr, size, true)) {
++ /*
++ * Free function will not fail for overlay, unless
++ * address passed in is bad.
++ */
++ DBC_Assert(false);
++ }
++ }
++}
++
++/*
++ * ======== loadSect ========
++ * Purpose:
++ * Load section to target
++ */
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SectHdr sectHdr;
++ char *pBuf;
++ struct KFILE_FileObj *file;
++ u32 space;
++ u32 addr;
++ u32 total;
++ u32 nWords = 0;
++ u32 nBytes = 0;
++ u16 mauSize;
++ u32 bufSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ bufSize = LOADBUFSIZE / mauSize;
++ pBuf = dbl->pBuf;
++
++ /* Read the section header */
++ if ((*dbl->dblAttrs.fread)(&sectHdr, sizeof(struct DBOF_SectHdr),
++ 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ } else {
++ if (pdblLib->byteSwapped) {
++ sectHdr.size = SWAPLONG(sectHdr.size);
++ sectHdr.addr = SWAPLONG(sectHdr.addr);
++ sectHdr.page = SWAPWORD(sectHdr.page);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ addr = sectHdr.addr;
++ space = sectHdr.page;
++ for (total = sectHdr.size; total > 0; total -= nWords) {
++ nWords = min(total, bufSize);
++ nBytes = nWords * mauSize;
++ /* Read section data */
++ if ((*dbl->dblAttrs.fread)(pBuf, nBytes, 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Write section to target */
++ if (!(*dbl->dblAttrs.write)(dbl->dblAttrs.wHandle,
++ addr, pBuf, nBytes, space)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to write section data\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ addr += nWords;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readDCDSects ========
++ * Purpose:
++ * Read DCD sections.
++ */
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_DCDSectHdr *pSectHdr;
++ struct DCDSect *pSect;
++ struct KFILE_FileObj *file;
++ u16 nSects;
++ u16 i;
++ u16 mauSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ nSects = pdblLib->fileHdr.numDCDSects;
++ for (i = 0; i < nSects; i++) {
++ pSect = &pdblLib->dcdSects[i];
++ pSectHdr = &pdblLib->dcdSects[i].sectHdr;
++ /* Read sect header */
++ if ((*dbl->dblAttrs.fread)(pSectHdr,
++ sizeof(struct DBOF_DCDSectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped)
++ pSectHdr->size = SWAPLONG(pSectHdr->size);
++
++ pSect->pData = (char *)MEM_Calloc(pSectHdr->size *
++ mauSize, MEM_PAGED);
++ if (pSect->pData == NULL) {
++ GT_2trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation for sect %s "
++ "data failed: Size: 0x%lx\n", pSectHdr->name,
++ pSectHdr->size);
++ status = DSP_EMEMORY;
++ break;
++ }
++ /* Read DCD sect data */
++ if ((*dbl->dblAttrs.fread)(pSect->pData, mauSize,
++ pSectHdr->size, file) != pSectHdr->size) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect data\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== readHeader ========
++ * Purpose:
++ * Read Header.
++ */
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct KFILE_FileObj *file;
++ s32 i;
++ struct DBOF_FileHdr *pHdr;
++ u32 swapMagic;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->byteSwapped = false;
++ file = pdblLib->file;
++ pHdr = &pdblLib->fileHdr;
++ if ((*dbl->dblAttrs.fread)(pHdr, sizeof(struct DBOF_FileHdr), 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to read file header\n");
++ status = DSP_EFREAD;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Determine if byte swapped */
++ for (i = 0; i < NUMTARGS; i++) {
++ swapMagic = SWAPLONG(pHdr->magic);
++ if (pHdr->magic == magicTab[i] || swapMagic ==
++ magicTab[i]) {
++ if (swapMagic == magicTab[i]) {
++ pdblLib->byteSwapped = true;
++ pHdr->magic = SWAPLONG(pHdr->magic);
++ pHdr->entry = SWAPLONG(pHdr->entry);
++ pHdr->symOffset = SWAPLONG(pHdr->
++ symOffset);
++ pHdr->dcdSectOffset = SWAPLONG(pHdr->
++ dcdSectOffset);
++ pHdr->loadSectOffset = SWAPLONG(pHdr->
++ loadSectOffset);
++ pHdr->ovlySectOffset = SWAPLONG(pHdr->
++ ovlySectOffset);
++ pHdr->numSymbols = SWAPWORD(pHdr->
++ numSymbols);
++ pHdr->numDCDSects = SWAPWORD(pHdr->
++ numDCDSects);
++ pHdr->numSects = SWAPWORD(pHdr->
++ numSects);
++ pHdr->numOvlySects = SWAPWORD(pHdr->
++ numOvlySects);
++ }
++ break;
++ }
++ }
++ if (i == NUMTARGS) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to determine"
++ " target type\n");
++ status = DSP_ECORRUPTFILE;
++ } else {
++ pdblLib->pTargetInfo = &targetTab[i];
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "COF type: 0x%lx\n", pHdr->magic);
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "Entry point:0x%lx\n", pHdr->entry);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readOvlySects ========
++ * Purpose:
++ * Read Overlay Sections
++ */
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_OvlySectHdr hdr;
++ struct DBOF_OvlySectData *pData;
++ struct OvlyData *pOvlyData;
++ char *pName;
++ struct KFILE_FileObj *file;
++ u16 i, j;
++ u16 nSects;
++ u16 n;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->nOvlySects = nSects = pdblLib->fileHdr.numOvlySects;
++ file = pdblLib->file;
++ if (nSects > 0) {
++ pdblLib->ppOvlyData = MEM_Calloc(nSects * sizeof(OvlyData *),
++ MEM_PAGED);
++ if (pdblLib->ppOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate overlay "
++ "data memory\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Read overlay data for each node */
++ for (i = 0; i < nSects; i++) {
++ /* Read overlay section header */
++ if ((*dbl->dblAttrs.fread)(&hdr,
++ sizeof(struct DBOF_OvlySectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read overlay sect"
++ " header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ hdr.nameLen = SWAPWORD(hdr.nameLen);
++ hdr.numCreateSects =
++ SWAPWORD(hdr.numCreateSects);
++ hdr.numDeleteSects =
++ SWAPWORD(hdr.numDeleteSects);
++ hdr.numExecuteSects =
++ SWAPWORD(hdr.numExecuteSects);
++ hdr.numOtherSects =
++ SWAPWORD(hdr.numOtherSects);
++ hdr.resvd = SWAPWORD(hdr.resvd);
++ }
++ n = hdr.numCreateSects + hdr.numDeleteSects +
++ hdr.numExecuteSects + hdr.numOtherSects;
++
++ /* Allocate memory for node's overlay data */
++ pOvlyData = (struct OvlyData *)MEM_Calloc
++ (sizeof(struct OvlyHdr) +
++ n * sizeof(struct DBOF_OvlySectData),
++ MEM_PAGED);
++ if (pOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " data memory\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.dbofHdr = hdr;
++ pdblLib->ppOvlyData[i] = pOvlyData;
++ /* Allocate memory for section name */
++ pName = (char *)MEM_Calloc(hdr.nameLen + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " section name\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.pName = pName;
++ /* Read the overlay section name */
++ if ((*dbl->dblAttrs.fread)(pName, sizeof(char),
++ hdr.nameLen, file) != hdr.nameLen) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay name.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Read the overlay section data */
++ pData = pOvlyData->data;
++ if ((*dbl->dblAttrs.fread)(pData,
++ sizeof(struct DBOF_OvlySectData), n, file) != n) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay data.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Swap overlay data, if necessary */
++ if (pdblLib->byteSwapped) {
++ for (j = 0; j < n; j++) {
++ pData[j].loadAddr =
++ SWAPLONG(pData[j].loadAddr);
++ pData[j].runAddr =
++ SWAPLONG(pData[j].runAddr);
++ pData[j].size =
++ SWAPLONG(pData[j].size);
++ pData[j].page =
++ SWAPWORD(pData[j].page);
++ }
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readSymbols ========
++ * Purpose:
++ * Read Symbols
++ */
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SymbolHdr symHdr;
++ struct KFILE_FileObj *file;
++ u16 i;
++ u16 nSymbols;
++ u16 len;
++ char *pName = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++
++ nSymbols = pdblLib->fileHdr.numSymbols;
++
++ for (i = 0; i < nSymbols; i++) {
++ /* Read symbol value */
++ if ((*dbl->dblAttrs.fread)(&symHdr,
++ sizeof(struct DBOF_SymbolHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ symHdr.nameLen = SWAPWORD(symHdr.nameLen);
++ symHdr.value = SWAPLONG(symHdr.value);
++ }
++ /* Allocate buffer for symbol name */
++ len = symHdr.nameLen;
++ pName = (char *)MEM_Calloc(len + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pdblLib->symbols[i].pSymName = pName;
++ pdblLib->symbols[i].sym.value = symHdr.value;
++ /* Read symbol name */
++ if ((*dbl->dblAttrs.fread) (pName, sizeof(char), len, file) !=
++ len) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ } else {
++ pName[len] = '\0';
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "Symbol: %s Value: 0x%lx\n",
++ pName, symHdr.value);
++ }
++ }
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbll.c b/drivers/dsp/bridge/pmgr/dbll.c
+new file mode 100644
+index 0000000..82430a3
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbll.c
+@@ -0,0 +1,1564 @@
++/*
++ * dbll.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbll.c ========
++ *
++ *! Revision History
++ *! ================
++ *! 25-Apr-2030 map: Fixed symbol redefinition bug + unload and return error
++ *! 08-Apr-2003 map: Consolidated DBL with DBLL loader name
++ *! 24-Mar-2003 map: Updated findSymbol to support dllview update
++ *! 23-Jan-2003 map: Updated rmmAlloc to support memory granularity
++ *! 21-Nov-2002 map: Combine fopen and DLOAD_module_open to increase
++ *! performance on start.
++ *! 04-Oct-2002 map: Integrated new TIP dynamic loader w/ DOF api.
++ *! 27-Sep-2002 map: Changed handle passed to RemoteFree, instead of
++ *! RMM_free; added GT_trace to rmmDealloc
++ *! 20-Sep-2002 map: Updated from Code Review
++ *! 08-Aug-2002 jeh: Updated to support overlays.
++ *! 25-Jun-2002 jeh: Pass RMM_Addr object to alloc function in rmmAlloc().
++ *! 20-Mar-2002 jeh: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/gh.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Dynamic loader library interface */
++#include <dspbridge/dynamic_loader.h>
++#include <dspbridge/getsection.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbll.h>
++#include <dspbridge/rmm.h>
++
++#define DBLL_TARGSIGNATURE 0x544c4c44 /* "TLLD" */
++#define DBLL_LIBSIGNATURE 0x4c4c4c44 /* "LLLD" */
++
++/* Number of buckets for symbol hash table */
++#define MAXBUCKETS 211
++
++/* Max buffer length */
++#define MAXEXPR 128
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((uint32_t)zzz)
++#endif
++#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
++
++/*
++ * ======== struct DBLL_TarObj* ========
++ * A target may have one or more libraries of symbols/code/data loaded
++ * onto it, where a library is simply the symbols/code/data contained
++ * in a DOFF file.
++ */
++/*
++ * ======== DBLL_TarObj ========
++ */
++struct DBLL_TarObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_Attrs attrs;
++ struct DBLL_LibraryObj *head; /* List of all opened libraries */
++} ;
++
++/*
++ * The following 4 typedefs are "super classes" of the dynamic loader
++ * library types used in dynamic loader functions (dynamic_loader.h).
++ */
++/*
++ * ======== DBLLStream ========
++ * Contains Dynamic_Loader_Stream
++ */
++struct DBLLStream {
++ struct Dynamic_Loader_Stream dlStream;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLSymbol ========
++ */
++struct DBLLSymbol {
++ struct Dynamic_Loader_Sym dlSymbol;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLAlloc ========
++ */
++ struct DBLLAlloc {
++ struct Dynamic_Loader_Allocate dlAlloc;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLInit ========
++ */
++struct DBLLInit {
++ struct Dynamic_Loader_Initialize dlInit;
++ struct DBLL_LibraryObj *lib;
++};
++
++/*
++ * ======== DBLL_Library ========
++ * A library handle is returned by DBLL_Open() and is passed to DBLL_load()
++ * to load symbols/code/data, and to DBLL_unload(), to remove the
++ * symbols/code/data loaded by DBLL_load().
++ */
++
++/*
++ * ======== DBLL_LibraryObj ========
++ */
++ struct DBLL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_LibraryObj *next; /* Next library in target's list */
++ struct DBLL_LibraryObj *prev; /* Previous in the list */
++ struct DBLL_TarObj *pTarget; /* target for this library */
++
++ /* Objects needed by dynamic loader */
++ struct DBLLStream stream;
++ struct DBLLSymbol symbol;
++ struct DBLLAlloc allocate;
++ struct DBLLInit init;
++ DLOAD_mhandle mHandle;
++
++ char *fileName; /* COFF file name */
++ void *fp; /* Opaque file handle */
++ u32 entry; /* Entry point */
++ DLOAD_mhandle desc; /* desc of DOFF file loaded */
++ u32 openRef; /* Number of times opened */
++ u32 loadRef; /* Number of times loaded */
++ struct GH_THashTab *symTab; /* Hash table of symbols */
++ u32 ulPos;
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBLL_Symbol value;
++ char *name;
++} ;
++extern bool bSymbolsReloaded;
++
++static void dofClose(struct DBLL_LibraryObj *zlLib);
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib);
++static s32 NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsiz);
++
++/*
++ * Functions called by dynamic loader
++ *
++ */
++/* Dynamic_Loader_Stream */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize);
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos);
++/* Dynamic_Loader_Sym */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name);
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId);
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid);
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this,
++ unsigned moduleId);
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize);
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr);
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args);
++/* Dynamic_Loader_Allocate */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align);
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info);
++
++/* Dynamic_Loader_Initialize */
++static int connect(struct Dynamic_Loader_Initialize *this);
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nbytes,
++ unsigned val);
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start);
++static void release(struct Dynamic_Loader_Initialize *this);
++
++/* symbol table hash functions */
++static u16 nameHash(void *name, u16 maxBucket);
++static bool nameMatch(void *name, void *sp);
++static void symDelete(void *sp);
++
++#if GT_TRACE
++static struct GT_Mask DBLL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Symbol Redefinition */
++static int bRedefinedSymbol;
++static int bGblSearch = 1;
++
++/*
++ * ======== DBLL_close ========
++ */
++void DBLL_close(struct DBLL_LibraryObj *zlLib)
++{
++ struct DBLL_TarObj *zlTarget;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->openRef > 0);
++ zlTarget = zlLib->pTarget;
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_close: lib: 0x%x\n", zlLib);
++ zlLib->openRef--;
++ if (zlLib->openRef == 0) {
++ /* Remove library from list */
++ if (zlTarget->head == zlLib)
++ zlTarget->head = zlLib->next;
++
++ if (zlLib->prev)
++ (zlLib->prev)->next = zlLib->next;
++
++ if (zlLib->next)
++ (zlLib->next)->prev = zlLib->prev;
++
++ /* Free DOF resources */
++ dofClose(zlLib);
++ if (zlLib->fileName)
++ MEM_Free(zlLib->fileName);
++
++ /* remove symbols from symbol table */
++ if (zlLib->symTab)
++ GH_delete(zlLib->symTab);
++
++ /* remove the library object itself */
++ MEM_FreeObject(zlLib);
++ zlLib = NULL;
++ }
++}
++
++/*
++ * ======== DBLL_create ========
++ */
++DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *pzlTarget;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_create: pTarget: 0x%x pAttrs: "
++ "0x%x\n", pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pzlTarget, struct DBLL_TarObj, DBLL_TARGSIGNATURE);
++ if (pTarget != NULL) {
++ if (pzlTarget == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_create: Memory allocation"
++ " failed\n");
++ *pTarget = NULL;
++ status = DSP_EMEMORY;
++ } else {
++ pzlTarget->attrs = *pAttrs;
++ *pTarget = (struct DBLL_TarObj *)pzlTarget;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct DBLL_TarObj *)(*pTarget)),
++ DBLL_TARGSIGNATURE)) || (DSP_FAILED(status) &&
++ *pTarget == NULL));
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_delete ========
++ */
++void DBLL_delete(struct DBLL_TarObj *target)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_delete: target: 0x%x\n",
++ target);
++
++ if (zlTarget != NULL)
++ MEM_FreeObject(zlTarget);
++
++}
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue usage of DBL module.
++ */
++void DBLL_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++ MEM_Exit();
++ CSL_Exit();
++ GH_exit();
++#if GT_TRACE
++ DBLL_debugMask.flags = NULL;
++#endif
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ */
++bool DBLL_getAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getAddr: lib: 0x%x name: %s pAddr:"
++ " 0x%x\n", zlLib, name, ppSym);
++ sym = (struct Symbol *)GH_find(zlLib->symTab, name);
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ */
++void DBLL_getAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ *pAttrs = zlTarget->attrs;
++
++}
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of a "C" name in the specified library.
++ */
++bool DBLL_getCAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ char cname[MAXEXPR + 1];
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++ DBC_Require(name != NULL);
++
++ cname[0] = '_';
++
++ strncpy(cname + 1, name, sizeof(cname) - 2);
++ cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
++
++ /* Check for C name, if not found */
++ sym = (struct Symbol *)GH_find(zlLib->symTab, cname);
++
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_getSect ========
++ * Get the base address and size (in bytes) of a COFF section.
++ */
++DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ u32 uByteSize;
++ bool fOpenedDoff = false;
++ const struct LDR_SECTION_INFO *sect = NULL;
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ uByteSize = 1;
++ if (DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ *pAddr = sect->load_addr;
++ *pSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (*pSize % 2)
++ (*pSize)++;
++
++ /* Align size */
++ *pSize = DOFF_ALIGN(*pSize);
++ } else {
++ status = DSP_ENOSECT;
++ }
++ }
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_init ========
++ */
++bool DBLL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBLL_debugMask.flags);
++ GT_create(&DBLL_debugMask, "DL"); /* "DL" for dbDL */
++ GH_init();
++ CSL_Init();
++ retVal = MEM_Init();
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBLL_load ========
++ */
++DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib, DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ struct DBLL_TarObj *dbzl;
++ bool gotSymbols = true;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++ bool fOpenedDoff = false;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_load: lib: 0x%x flags: 0x%x pEntry:"
++ " 0x%x\n", lib, flags, attrs, pEntry);
++ /*
++ * Load if not already loaded.
++ */
++ if (zlLib->loadRef == 0 || !(flags & DBLL_DYNAMIC)) {
++ dbzl = zlLib->pTarget;
++ dbzl->attrs = *attrs;
++ /* Create a hash table for symbols if not already created */
++ if (zlLib->symTab == NULL) {
++ gotSymbols = false;
++ zlLib->symTab = GH_create(MAXBUCKETS,
++ sizeof(struct Symbol),
++ nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ if (gotSymbols) {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ findInSymbolTable;
++ } else {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ addToSymbolTable;
++ }
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ /* If COFF file is not open, we open it. */
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell))
++ (zlLib->fp);
++ /* Reset file cursor */
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0,
++ SEEK_SET);
++ bSymbolsReloaded = true;
++ /* The 5th argument, DLOAD_INITBSS, tells the DLL
++ * module to zero-init all BSS sections. In general,
++ * this is not necessary and also increases load time.
++ * We may want to make this configurable by the user */
++ err = Dynamic_Load_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, DLOAD_INITBSS,
++ &zlLib->mHandle);
++
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_load: "
++ "Dynamic_Load_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ } else if (bRedefinedSymbol) {
++ zlLib->loadRef++;
++ DBLL_unload(zlLib, (struct DBLL_Attrs *) attrs);
++ bRedefinedSymbol = false;
++ status = DSP_EDYNLOAD;
++ } else {
++ *pEntry = zlLib->entry;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ zlLib->loadRef++;
++
++ /* Clean up DOFF resources */
++ if (fOpenedDoff)
++ dofClose(zlLib);
++
++ DBC_Ensure(DSP_FAILED(status) || zlLib->loadRef > 0);
++ return status;
++}
++
++/*
++ * ======== DBLL_loadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *zlLib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== DBLL_open ========
++ */
++DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ struct DBLL_LibraryObj *zlLib = NULL;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(zlTarget->attrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_open: target: 0x%x file: %s pLib:"
++ " 0x%x\n", target, file, pLib);
++ zlLib = zlTarget->head;
++ while (zlLib != NULL) {
++ if (strcmp(zlLib->fileName, file) == 0) {
++ /* Library is already opened */
++ zlLib->openRef++;
++ break;
++ }
++ zlLib = zlLib->next;
++ }
++ if (zlLib == NULL) {
++ /* Allocate DBL library object */
++ MEM_AllocObject(zlLib, struct DBLL_LibraryObj,
++ DBLL_LIBSIGNATURE);
++ if (zlLib == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ zlLib->ulPos = 0;
++ /* Increment ref count to allow close on failure
++ * later on */
++ zlLib->openRef++;
++ zlLib->pTarget = zlTarget;
++ /* Keep a copy of the file name */
++ zlLib->fileName = MEM_Calloc(strlen(file) + 1,
++ MEM_PAGED);
++ if (zlLib->fileName == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(zlLib->fileName, file,
++ strlen(file) + 1);
++ }
++ zlLib->symTab = NULL;
++ }
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable;
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ if (DSP_SUCCEEDED(status) && zlLib->fp == NULL)
++ status = dofOpen(zlLib);
++
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp);
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET);
++ /* Create a hash table for symbols if flag is set */
++ if (zlLib->symTab != NULL || !(flags & DBLL_SYMB))
++ goto func_cont;
++
++ zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Do a fake load to get symbols - set write function to NoOp */
++ zlLib->init.dlInit.writemem = NoOp;
++ err = Dynamic_Open_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, 0,
++ &zlLib->mHandle);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: "
++ "Dynamic_Load_Module failed: 0x%lx\n", err);
++ status = DSP_EDYNLOAD;
++ } else {
++ /* Now that we have the symbol table, we can unload */
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: "
++ "Dynamic_Unload_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ }
++ zlLib->mHandle = NULL;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ if (zlLib->openRef == 1) {
++ /* First time opened - insert in list */
++ if (zlTarget->head)
++ (zlTarget->head)->prev = zlLib;
++
++ zlLib->prev = NULL;
++ zlLib->next = zlTarget->head;
++ zlTarget->head = zlLib;
++ }
++ *pLib = (struct DBLL_LibraryObj *)zlLib;
++ } else {
++ *pLib = NULL;
++ if (zlLib != NULL)
++ DBLL_close((struct DBLL_LibraryObj *)zlLib);
++
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) &&
++ MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)),
++ DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBLL_readSect ========
++ * Get the content of a COFF section.
++ */
++DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib, char *name,
++ char *pContent, u32 size)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ bool fOpenedDoff = false;
++ u32 uByteSize; /* size of bytes */
++ u32 ulSectSize; /* size of section */
++ const struct LDR_SECTION_INFO *sect = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ uByteSize = 1;
++ if (!DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ status = DSP_ENOSECT;
++ goto func_cont;
++ }
++ /*
++ * Ensure the supplied buffer size is sufficient to store
++ * the section content to be read.
++ */
++ ulSectSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (ulSectSize % 2)
++ ulSectSize++;
++
++ /* Align size */
++ ulSectSize = DOFF_ALIGN(ulSectSize);
++ if (ulSectSize > size) {
++ status = DSP_EFAIL;
++ } else {
++ if (!DLOAD_GetSection(zlLib->desc, sect, pContent))
++ status = DSP_EFREAD;
++
++ }
++func_cont:
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ */
++void DBLL_setAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ zlTarget->attrs = *pAttrs;
++
++}
++
++/*
++ * ======== DBLL_unload ========
++ */
++void DBLL_unload(struct DBLL_LibraryObj *lib, struct DBLL_Attrs *attrs)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ s32 err = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->loadRef > 0);
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_unload: lib: 0x%x\n", lib);
++ zlLib->loadRef--;
++ /* Unload only if reference count is 0 */
++ if (zlLib->loadRef != 0)
++ goto func_end;
++
++ zlLib->pTarget->attrs = *attrs;
++ if (zlLib != NULL) {
++ if (zlLib->mHandle) {
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc, &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_5CLASS,
++ "Dynamic_Unload_Module "
++ "failed: 0x%x\n", err);
++ }
++ }
++ /* remove symbols from symbol table */
++ if (zlLib->symTab != NULL) {
++ GH_delete(zlLib->symTab);
++ zlLib->symTab = NULL;
++ }
++ /* delete DOFF desc since it holds *lots* of host OS
++ * resources */
++ dofClose(zlLib);
++ }
++func_end:
++ DBC_Ensure(zlLib->loadRef >= 0);
++}
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(sectName != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_unloadSect: lib: 0x%x sectName: "
++ "%s\n", lib, sectName);
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== dofClose ========
++ */
++static void dofClose(struct DBLL_LibraryObj *zlLib)
++{
++ if (zlLib->desc) {
++ DLOAD_module_close(zlLib->desc);
++ zlLib->desc = NULL;
++ }
++ /* close file */
++ if (zlLib->fp) {
++ (zlLib->pTarget->attrs.fclose) (zlLib->fp);
++ zlLib->fp = NULL;
++ }
++}
++
++/*
++ * ======== dofOpen ========
++ */
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib)
++{
++ void *open = *(zlLib->pTarget->attrs.fopen);
++ DSP_STATUS status = DSP_SOK;
++
++ /* First open the file for the dynamic loader, then open COF */
++ zlLib->fp = (void *)((DBLL_FOpenFxn)(open))(zlLib->fileName, "rb");
++
++ /* Open DOFF module */
++ if (zlLib->fp && zlLib->desc == NULL) {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0, SEEK_SET);
++ zlLib->desc = DLOAD_module_open(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol);
++ if (zlLib->desc == NULL) {
++ (zlLib->pTarget->attrs.fclose)(zlLib->fp);
++ zlLib->fp = NULL;
++ status = DSP_EFOPEN;
++ }
++ } else {
++ status = DSP_EFOPEN;
++ }
++
++ return status;
++}
++
++/*
++ * ======== nameHash ========
++ */
++static u16 nameHash(void *key, u16 maxBucket)
++{
++ u16 ret;
++ u16 hash;
++ char *name = (char *)key;
++
++ DBC_Require(name != NULL);
++
++ hash = 0;
++
++ while (*name) {
++ hash <<= 1;
++ hash ^= *name++;
++ }
++
++ ret = hash % maxBucket;
++
++ return ret;
++}
++
++/*
++ * ======== nameMatch ========
++ */
++static bool nameMatch(void *key, void *value)
++{
++ DBC_Require(key != NULL);
++ DBC_Require(value != NULL);
++
++ if ((key != NULL) && (value != NULL)) {
++ if (strcmp((char *)key, ((struct Symbol *)value)->name) == 0)
++ return true;
++ }
++ return false;
++}
++
++/*
++ * ======== NoOp ========
++ */
++static int NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsize)
++{
++ return 1;
++}
++
++/*
++ * ======== symDelete ========
++ */
++static void symDelete(void *value)
++{
++ struct Symbol *sp = (struct Symbol *)value;
++
++ MEM_Free(sp->name);
++}
++
++/*
++ * Dynamic Loader Functions
++ */
++
++/* Dynamic_Loader_Stream */
++/*
++ * ======== readBuffer ========
++ */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ bytesRead = (*(lib->pTarget->attrs.fread))(buffer, 1, bufsize,
++ lib->fp);
++ }
++ return bytesRead;
++}
++
++/*
++ * ======== setFilePosn ========
++ */
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int status = 0; /* Success */
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ status = (*(lib->pTarget->attrs.fseek))(lib->fp, (long)pos,
++ SEEK_SET);
++ }
++
++ return status;
++}
++
++/* Dynamic_Loader_Sym */
++
++/*
++ * ======== findSymbol ========
++ */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_Symbol *pSym = NULL;
++ bool status = false; /* Symbol not found yet */
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ if (lib->pTarget->attrs.symLookup) {
++ /* Check current lib + base lib + dep lib +
++ * persistent lib */
++ status = (*(lib->pTarget->attrs.symLookup))
++ (lib->pTarget->attrs.symHandle,
++ lib->pTarget->attrs.symArg,
++ lib->pTarget->attrs.rmmHandle, name, &pSym);
++ } else {
++ /* Just check current lib for symbol */
++ status = DBLL_getAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ if (!status) {
++ status =
++ DBLL_getCAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ }
++ }
++ }
++
++ if (!status && bGblSearch) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "findSymbol: Symbol not found: %s\n", name);
++ }
++
++ DBC_Assert((status && (pSym != NULL)) || (!status && (pSym == NULL)));
++
++ retSym = (struct dynload_symbol *)pSym;
++ return retSym;
++}
++
++/*
++ * ======== findInSymbolTable ========
++ */
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct Symbol *sym;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ DBC_Require(lib->symTab != NULL);
++
++ sym = (struct Symbol *)GH_find(lib->symTab, (char *) name);
++
++ retSym = (struct dynload_symbol *)&sym->value;
++ return retSym;
++}
++
++/*
++ * ======== addToSymbolTable ========
++ */
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId)
++{
++ struct Symbol *symPtr = NULL;
++ struct Symbol symbol;
++ struct dynload_symbol *pSym = NULL;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct dynload_symbol *retVal;
++
++ DBC_Require(this != NULL);
++ DBC_Require(name);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* Check to see if symbol is already defined in symbol table */
++ if (!(lib->pTarget->attrs.baseImage)) {
++ bGblSearch = false;
++ pSym = findSymbol(this, name);
++ bGblSearch = true;
++ if (pSym) {
++ bRedefinedSymbol = true;
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "Symbol already defined in "
++ "symbol table: %s\n", name);
++ return NULL;
++ }
++ }
++ /* Allocate string to copy symbol name */
++ symbol.name = (char *)MEM_Calloc(strlen((char *const)name) + 1,
++ MEM_PAGED);
++ if (symbol.name == NULL)
++ return NULL;
++
++ if (symbol.name != NULL) {
++ /* Just copy name (value will be filled in by dynamic loader) */
++ strncpy(symbol.name, (char *const)name,
++ strlen((char *const)name) + 1);
++
++ /* Add symbol to symbol table */
++ symPtr = (struct Symbol *)GH_insert(lib->symTab, (void *)name,
++ (void *)&symbol);
++ if (symPtr == NULL)
++ MEM_Free(symbol.name);
++
++ }
++ if (symPtr != NULL)
++ retVal = (struct dynload_symbol *)&symPtr->value;
++ else
++ retVal = NULL;
++
++ return retVal;
++}
++
++/*
++ * ======== purgeSymbolTable ========
++ */
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this, unsigned moduleId)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* May not need to do anything */
++}
++
++/*
++ * ======== allocate ========
++ */
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ void *buf;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ buf = MEM_Calloc(memsize, MEM_PAGED);
++
++ return buf;
++}
++
++/*
++ * ======== deallocate ========
++ */
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ MEM_Free(memPtr);
++}
++
++/*
++ * ======== errorReport ========
++ */
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ char tempBuf[MAXEXPR];
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ vsnprintf((char *)tempBuf, MAXEXPR, (char *)errstr, args);
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "%s\n", tempBuf);
++}
++
++/* Dynamic_Loader_Allocate */
++
++/*
++ * ======== rmmAlloc ========
++ */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ DSP_STATUS status = DSP_SOK;
++ u32 memType;
++ struct RMM_Addr rmmAddr;
++ s32 retVal = TRUE;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ char *pToken = NULL;
++ char *szSecLastToken = NULL;
++ char *szLastToken = NULL;
++ char *szSectName = NULL;
++ char *pszCur;
++ s32 tokenLen = 0;
++ s32 segId = -1;
++ s32 req = -1;
++ s32 count = 0;
++ u32 allocSize = 0;
++
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++
++ /* Attempt to extract the segment ID and requirement information from
++ the name of the section */
++ DBC_Require(info->name);
++ tokenLen = strlen((char *)(info->name)) + 1;
++
++ szSectName = MEM_Calloc(tokenLen, MEM_PAGED);
++ szLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++ szSecLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++
++ if (szSectName == NULL || szSecLastToken == NULL ||
++ szLastToken == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ strncpy(szSectName, (char *)(info->name), tokenLen);
++ pszCur = szSectName;
++ while ((pToken = strsep(&pszCur, ":")) && *pToken != '\0') {
++ strncpy(szSecLastToken, szLastToken, strlen(szLastToken) + 1);
++ strncpy(szLastToken, pToken, strlen(pToken) + 1);
++ pToken = strsep(&pszCur, ":");
++ count++; /* optimizes processing*/
++ }
++ /* If pToken is 0 or 1, and szSecLastToken is DYN_DARAM or DYN_SARAM,
++ or DYN_EXTERNAL, then mem granularity information is present
++ within the section name - only process if there are at least three
++ tokens within the section name (just a minor optimization)*/
++ if (count >= 3)
++ strict_strtol(szLastToken, 10, (long *)&req);
++
++ if ((req == 0) || (req == 1)) {
++ if (strcmp(szSecLastToken, "DYN_DARAM") == 0) {
++ segId = 0;
++ } else {
++ if (strcmp(szSecLastToken, "DYN_SARAM") == 0) {
++ segId = 1;
++ } else {
++ if (strcmp(szSecLastToken,
++ "DYN_EXTERNAL") == 0) {
++ segId = 2;
++ }
++ }
++ }
++ if (segId != -1) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Extracted values for memory"
++ " granularity req [%d] segId [%d]\n",
++ req, segId);
++ }
++ }
++ MEM_Free(szSectName);
++ szSectName = NULL;
++ MEM_Free(szLastToken);
++ szLastToken = NULL;
++ MEM_Free(szSecLastToken);
++ szSecLastToken = NULL;
++func_cont:
++ if (memType == DBLL_CODE)
++ allocSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ allocSize = info->size;
++ /* TODO - ideally, we can pass the alignment requirement also
++ * from here */
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.alloc)(lib->pTarget->
++ attrs.rmmHandle, memType, allocSize, align,
++ (u32 *)&rmmAddr, segId, req, FALSE);
++ }
++ if (DSP_FAILED(status)) {
++ retVal = false;
++ } else {
++ /* RMM gives word address. Need to convert to byte address */
++ info->load_addr = rmmAddr.addr * DSPWORDSIZE;
++ info->run_addr = info->load_addr;
++ info->context = (u32)rmmAddr.segid;
++ GT_3trace(DBLL_debugMask, GT_5CLASS,
++ "Remote alloc: %s base = 0x%lx len"
++ "= 0x%lx\n", info->name, info->load_addr / DSPWORDSIZE,
++ info->size / DSPWORDSIZE);
++ }
++ return retVal;
++}
++
++/*
++ * ======== rmmDealloc ========
++ */
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ u32 segid;
++ DSP_STATUS status = DSP_SOK;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ u32 memType;
++ u32 freeSize = 0;
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* segid was set by alloc function */
++ segid = (u32)info->context;
++ if (memType == DBLL_CODE)
++ freeSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ freeSize = info->size;
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.free)(lib->pTarget->
++ attrs.symHandle, segid, info->load_addr / DSPWORDSIZE,
++ freeSize, false);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Remote dealloc: base = 0x%lx len ="
++ "0x%lx\n", info->load_addr / DSPWORDSIZE,
++ freeSize / DSPWORDSIZE);
++ }
++}
++
++/* Dynamic_Loader_Initialize */
++/*
++ * ======== connect ========
++ */
++static int connect(struct Dynamic_Loader_Initialize *this)
++{
++ return true;
++}
++
++/*
++ * ======== readMem ========
++ * This function does not need to be implemented.
++ */
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Need WMD_BRD_Read function */
++ return bytesRead;
++}
++
++/*
++ * ======== writeMem ========
++ */
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nBytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_SectInfo sectInfo;
++ u32 memType;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (DLOAD_SECTION_TYPE(info->type) == DLOAD_TEXT) ? DBLL_CODE :
++ DBLL_DATA;
++ if (lib != NULL) {
++ retVal = (*lib->pTarget->attrs.write)(lib->pTarget->
++ attrs.wHandle, addr, buf, nBytes, memType);
++ }
++ if (lib->pTarget->attrs.logWrite) {
++ sectInfo.name = info->name;
++ sectInfo.runAddr = info->run_addr;
++ sectInfo.loadAddr = info->load_addr;
++ sectInfo.size = info->size;
++ sectInfo.type = memType;
++ /* Pass the information about what we've written to
++ * another module */
++ (*lib->pTarget->attrs.logWrite)(lib->pTarget->
++ attrs.logWriteHandle, &sectInfo, addr, nBytes);
++ }
++ return retVal;
++}
++
++/*
++ * ======== fillMem ========
++ * Fill nBytes of memory at a given address with a given value by
++ * writing from a buffer containing the given value. Write in
++ * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
++ */
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nBytes,
++ unsigned val)
++{
++ bool retVal = true;
++ char *pBuf;
++ struct DBLL_LibraryObj *lib;
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ pBuf = NULL;
++ /* Pass the NULL pointer to writeMem to get the start address of Shared
++ memory. This is a trick to just get the start address, there is no
++ writing taking place with this Writemem
++ */
++ if ((lib->pTarget->attrs.write) != (DBLL_WriteFxn)NoOp)
++ writeMem(this, &pBuf, addr, info, 0);
++ if (pBuf)
++ memset(pBuf, val, nBytes);
++
++ return retVal;
++}
++
++/*
++ * ======== execute ========
++ */
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Save entry point */
++ if (lib != NULL)
++ lib->entry = (u32)start;
++
++ return retVal;
++}
++
++/*
++ * ======== release ========
++ */
++static void release(struct Dynamic_Loader_Initialize *this)
++{
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dev.c b/drivers/dsp/bridge/pmgr/dev.c
+new file mode 100644
+index 0000000..1c2f7d5
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dev.c
+@@ -0,0 +1,1476 @@
++/*
++ * dev.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.c ========
++ * Description:
++ * Implementation of 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ * Private Functions:
++ * FxnNotImplemented
++ * InitCodMgr
++ * InsertDevObject
++ * IsValidHandle
++ * RemoveDevObject
++ * StoreInterfaceFxns
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn Support for IVA DEH
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 29-Nov-2001 jeh Check for DSP_ENOTIMPL status of DEH create function.
++ *! 05-Nov-2001 kc Added support for DEH module.
++ *! 05-Aug-2001 ag Shared memory registration moved to WMD_IO_OnLoaded().
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 11-Apr-2001 rr: Removed CMM_RegisterGPPSMSeg.
++ *! 02-Apr-2001 rr: CHNL_Create failure is printed out.
++ *! 15-Jan-2001 jeh Removed call to IO_OnLoaded() from DEV_Create2().
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name update.
++ *! 15-Dec-2000 rr: Dev_Create2 returns error if NODE_CreateMgr fails.
++ *! 05-Dec-2000 jeh Moved IO_OnLoaded() to PROC_Load. Added DEV_SetMsgMgr.
++ *! 05-Dev-2000 ag SM Heap for messaging registered via CMM_RegisterGPPSMSeg().
++ *! SM heap base and size currently taken from registry.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added calls to get IO manager (IO_Create), IO_OnLoaded().
++ *! 06-Oct-2000 rr: DEV_Destroy2 and DEV_Create2 added.
++ *! 02-Oct-2000 rr: DEV_GetNodeManager added.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr(), CMM_Init() & CMM_Exit().
++ *! Removed <dspbridge/std.h> & <stdwin.h>, added <dspbridge/dbtype.h>
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! DEV_Cleanup calls PROC_Detach if it is a matching process.
++ *! 27-Jul-2000 rr: DEV is in new directoy DEV and produces devlib.lib
++ *! 17-Jul-2000 rr: DRV Object holds the list of Dev Objects. DEV gets
++ *! the List and Next devices through DRV.
++ *! DEV object has a back pointer to DRV Object.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 09-May-2000 rr: dwMemBase has index for multiple windows need.
++ *! 28-Feb-2000 rr: New GT Usage implemented.
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 21-Jan-2000 rr: windows.h, tchar.h, HMODULE removed. FreeLibrary replaced
++ *! with LDR_FreeModule
++ *! 17-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! StoreInterfaceFxns stores the new fxn WMD_BRD_SETSTATE.
++ *! 20-Nov-1999 ag: Actual uSMLength = total - monitor offset.
++ *! 12-Nov-1999 rr: bIRQ and IRQAttrib taken from the struct CFG_HOSTRES.
++ *! dMemBase is added with offset for monitor taken from
++ *! registry.
++ *! 31-Oct-1999 ag: Added CHNL support.
++ *! 10-Sep-1999 rr: GT Enabled. DEV_Create will Load the Mini Driver and will
++ *! find its fxn table. Right now lot of things are hardcoded
++ *! as the REG is not ready.
++ *! 10-Jun-1996 rr: Created from WSX
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++#include <dspbridge/wcd.h> /* WCD version info. */
++
++#include <dspbridge/chnl.h>
++#include <dspbridge/io.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++#define SIGNATURE 0x5f564544 /* "DEV_" (in reverse) */
++#define MAKEVERSION(major, minor) (major * 10 + minor)
++#define WCDVERSION MAKEVERSION(WCD_MAJOR_VERSION, WCD_MINOR_VERSION)
++
++/* The WMD device object: */
++struct DEV_OBJECT {
++ /* LST requires "link" to be first field! */
++ struct LST_ELEM link; /* Link to next DEV_OBJECT. */
++ u32 devType; /* Device Type */
++ u32 dwSignature; /* Used for object validation. */
++ struct CFG_DEVNODE *hDevNode; /* Platform specific device id */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE intfFxns; /* Function interface to WMD. */
++ struct BRD_OBJECT *lockOwner; /* Client with exclusive access. */
++ struct COD_MANAGER *hCodMgr; /* Code manager handle. */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager. */
++ struct DEH_MGR *hDehMgr; /* DEH manager. */
++ struct MSG_MGR *hMsgMgr; /* Message manager. */
++ struct IO_MGR *hIOMgr; /* IO manager (CHNL, MSG) */
++ struct CMM_OBJECT *hCmmMgr; /* SM memory manager. */
++ struct DMM_OBJECT *hDmmMgr; /* Dynamic memory manager. */
++ struct LDR_MODULE *hModule; /* WMD Module handle. */
++ u32 uWordSize; /* DSP word size: quick access. */
++ struct DRV_OBJECT *hDrvObject; /* Driver Object */
++ struct LST_LIST *procList; /* List of Proceeosr attached to
++ * this device */
++ struct NODE_MGR *hNodeMgr;
++} ;
++
++/* ----------------------------------- Globals */
++static u32 cRefs; /* Module reference count */
++#if GT_TRACE
++static struct GT_Mask debugMask = { NULL, NULL }; /* For debugging */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS FxnNotImplemented(int arg, ...);
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject);
++static bool IsValidHandle(struct DEV_OBJECT *hObj);
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns);
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject, then calls the
++ * device's WMD_BRD_Write() function.
++ */
++u32 DEV_BrdWriteFxn(void *pArb, u32 ulDspAddr, void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)pArb;
++ u32 ulWritten = 0;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pHostBuf != NULL); /* Required of BrdWrite(). */
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_BrdWriteFxn, pArb: 0x%x\n\t\t"
++ "ulDspAddr: 0x%x\n\t\tpHostBuf: 0x%x\n \t\tulNumBytes: 0x%x\n"
++ "\t\tnMemSpace: 0x%x\n", pArb, ulDspAddr, pHostBuf,
++ ulNumBytes, nMemSpace);
++ if (IsValidHandle(pDevObject)) {
++ /* Require of BrdWrite() */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnBrdWrite)(pDevObject->
++ hWmdContext, pHostBuf, ulDspAddr, ulNumBytes,
++ nMemSpace);
++ /* Special case of getting the address only */
++ if (ulNumBytes == 0)
++ ulNumBytes = 1;
++ if (DSP_SUCCEEDED(status))
++ ulWritten = ulNumBytes;
++
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_BrdWriteFxn ulWritten: 0x%x\n",
++ ulWritten);
++ return ulWritten;
++}
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the PM Mini Driver for a
++ * PM board (device).
++ */
++DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode)
++{
++ struct LDR_MODULE *hModule = NULL;
++ struct WMD_DRV_INTERFACE *pDrvFxns = NULL;
++ struct DEV_OBJECT *pDevObject = NULL;
++ struct CHNL_MGRATTRS mgrAttrs;
++ struct IO_ATTRS ioMgrAttrs;
++ u32 uNumWindows;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(pstrWMDFileName != NULL);
++ DBC_Require(pHostConfig != NULL);
++ DBC_Require(pDspConfig != NULL);
++
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_CreateDevice, phDevObject: 0x%x\n"
++ "\t\tpstrWMDFileName: 0x%x\n\t\tpHostConfig:0x%x\n\t\t"
++ "pDspConfig: 0x%x\n\t\tnhDevNode: 0x%x\n", phDevObject,
++ pstrWMDFileName, pHostConfig, pDspConfig, hDevNode);
++ /* Get the WMD interface functions*/
++ WMD_DRV_Entry(&pDrvFxns, pstrWMDFileName);
++ if (DSP_FAILED(CFG_GetObject((u32 *) &hDrvObject, REG_DRV_OBJECT))) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_0trace(debugMask, GT_7CLASS,
++ "Failed to get the DRV Object \n");
++ status = DSP_EFAIL;
++ }
++ /* Create the device object, and pass a handle to the WMD for
++ * storage. */
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pDrvFxns);
++ MEM_AllocObject(pDevObject, struct DEV_OBJECT, SIGNATURE);
++ if (pDevObject) {
++ /* Fill out the rest of the Dev Object structure: */
++ pDevObject->hDevNode = hDevNode;
++ pDevObject->hModule = hModule;
++ pDevObject->hCodMgr = NULL;
++ pDevObject->hChnlMgr = NULL;
++ pDevObject->hDehMgr = NULL;
++ pDevObject->lockOwner = NULL;
++ pDevObject->uWordSize = pDspConfig->uWordSize;
++ pDevObject->hDrvObject = hDrvObject;
++ pDevObject->devType = DSP_UNIT;
++ /* Store this WMD's interface functions, based on its
++ * version. */
++ StoreInterfaceFxns(pDrvFxns, &pDevObject->intfFxns);
++ /* Call WMD_DEV_CREATE() to get the WMD's device
++ * context handle. */
++ status = (pDevObject->intfFxns.pfnDevCreate)
++ (&pDevObject->hWmdContext, pDevObject,
++ pHostConfig, pDspConfig);
++ /* Assert WMD_DEV_Create()'s ensure clause: */
++ DBC_Assert(DSP_FAILED(status) || (pDevObject->
++ hWmdContext != NULL));
++ } else {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Out Of Memory");
++ status = DSP_EMEMORY;
++ }
++ }
++ /* Attempt to create the COD manager for this device: */
++ if (DSP_SUCCEEDED(status))
++ status = InitCodMgr(pDevObject);
++
++ /* Attempt to create the channel manager for this device: */
++ if (DSP_SUCCEEDED(status)) {
++ mgrAttrs.cChannels = CHNL_MAXCHANNELS;
++ ioMgrAttrs.bIRQ = pHostConfig->bIRQRegisters;
++ ioMgrAttrs.fShared = (pHostConfig->bIRQAttrib & CFG_IRQSHARED);
++ ioMgrAttrs.uWordSize = pDspConfig->uWordSize;
++ mgrAttrs.uWordSize = pDspConfig->uWordSize;
++ uNumWindows = pHostConfig->wNumMemWindows;
++ if (uNumWindows) {
++ /* Assume last memory window is for CHNL */
++ ioMgrAttrs.dwSMBase = pHostConfig->dwMemBase[1] +
++ pHostConfig->dwOffsetForMonitor;
++ ioMgrAttrs.uSMLength = pHostConfig->dwMemLength[1] -
++ pHostConfig->dwOffsetForMonitor;
++ } else {
++ ioMgrAttrs.dwSMBase = 0;
++ ioMgrAttrs.uSMLength = 0;
++ GT_0trace(debugMask, GT_7CLASS,
++ "**There is no memory reserved for "
++ "shared structures**\n");
++ }
++ status = CHNL_Create(&pDevObject->hChnlMgr, pDevObject,
++ &mgrAttrs);
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK for a device not to have a channel
++ * manager: */
++ status = DSP_SOK;
++ }
++ /* Create CMM mgr even if Msg Mgr not impl. */
++ status = CMM_Create(&pDevObject->hCmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create SM "
++ "Manager\n");
++ }
++ /* Only create IO manager if we have a channel manager */
++ if (DSP_SUCCEEDED(status) && pDevObject->hChnlMgr) {
++ status = IO_Create(&pDevObject->hIOMgr, pDevObject,
++ &ioMgrAttrs);
++ }
++ /* Only create DEH manager if we have an IO manager */
++ if (DSP_SUCCEEDED(status)) {
++ /* Instantiate the DEH module */
++ status = (*pDevObject->intfFxns.pfnDehCreate)
++ (&pDevObject->hDehMgr, pDevObject);
++ }
++ /* Create DMM mgr . */
++ status = DMM_Create(&pDevObject->hDmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create DMM "
++ "Manager\n");
++ }
++ }
++ /* Add the new DEV_Object to the global list: */
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem(&pDevObject->link);
++ status = DRV_InsertDevObject(hDrvObject, pDevObject);
++ }
++ /* Create the Processor List */
++ if (DSP_SUCCEEDED(status)) {
++ pDevObject->procList = LST_Create();
++ if (!(pDevObject->procList)) {
++ status = DSP_EFAIL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create: "
++ "Failed to Create Proc List");
++ }
++ }
++ /* If all went well, return a handle to the dev object;
++ * else, cleanup and return NULL in the OUT parameter. */
++ if (DSP_SUCCEEDED(status)) {
++ *phDevObject = pDevObject;
++ GT_1trace(debugMask, GT_1CLASS,
++ "DEV_CreateDevice Succeeded \nDevObject "
++ "0x%x\n", pDevObject);
++ } else {
++ if (pDevObject && pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ if (pDevObject && pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject && pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ if (pDevObject)
++ MEM_FreeObject(pDevObject);
++
++ *phDevObject = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_CreateDevice Failed\n");
++ }
++ GT_1trace(debugMask, GT_1CLASS, "Exiting DEV_Create: DevObject 0x%x\n",
++ *phDevObject);
++ DBC_Ensure((DSP_SUCCEEDED(status) && IsValidHandle(*phDevObject)) ||
++ (DSP_FAILED(status) && !*phDevObject));
++ return status;
++}
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ */
++DSP_STATUS DEV_Create2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Create2, hDevObject: 0x%x\n", hDevObject);
++ /* There can be only one Node Manager per DEV object */
++ DBC_Assert(!pDevObject->hNodeMgr);
++ status = NODE_CreateMgr(&pDevObject->hNodeMgr, hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_Create2: NODE_CreateMgr failed, "
++ "0x%x!\n", status);
++ pDevObject->hNodeMgr = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create2: Failed!!\n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr != NULL)
++ || (DSP_FAILED(status) && pDevObject->hNodeMgr == NULL));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Create2, hNodeMgr: 0x%x, status:"
++ " 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ */
++DSP_STATUS DEV_Destroy2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Destroy2, hDevObject: 0x%x\n",
++ hDevObject);
++ if (pDevObject->hNodeMgr) {
++ if (DSP_FAILED(NODE_DeleteMgr(pDevObject->hNodeMgr)))
++ status = DSP_EFAIL;
++ else
++ pDevObject->hNodeMgr = NULL;
++
++ }
++ if (DSP_FAILED(status))
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy2 failed!!\n");
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr == NULL) ||
++ DSP_FAILED(status));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Destroy2, hNodeMgr: 0x%x, status"
++ " = 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ */
++DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER, "Entered DEV_DestroyDevice, hDevObject: "
++ "0x%x\n", hDevObject);
++ if (IsValidHandle(hDevObject)) {
++ if (pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject->hNodeMgr)
++ NODE_DeleteMgr(pDevObject->hNodeMgr);
++
++ /* Free the io, channel, and message managers for this board: */
++ if (pDevObject->hIOMgr) {
++ IO_Destroy(pDevObject->hIOMgr);
++ pDevObject->hIOMgr = NULL;
++ }
++ if (pDevObject->hChnlMgr) {
++ CHNL_Destroy(pDevObject->hChnlMgr);
++ pDevObject->hChnlMgr = NULL;
++ }
++ if (pDevObject->hMsgMgr)
++ MSG_Delete(pDevObject->hMsgMgr);
++
++ if (pDevObject->hDehMgr) {
++ /* Uninitialize DEH module. */
++ (*pDevObject->intfFxns.pfnDehDestroy)
++ (pDevObject->hDehMgr);
++ }
++ if (pDevObject->hCmmMgr)
++ CMM_Destroy(pDevObject->hCmmMgr, true);
++
++ if (pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ /* Call the driver's WMD_DEV_Destroy() function: */
++ /* Require of DevDestroy */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnDevDestroy)
++ (pDevObject->hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ if (pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ /* Remove this DEV_Object from the global list: */
++ DRV_RemoveDevObject(pDevObject->hDrvObject, pDevObject);
++ /* Free The library * LDR_FreeModule
++ * (pDevObject->hModule);*/
++ /* Free this dev object: */
++ MEM_FreeObject(pDevObject);
++ }
++ } else {
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy: Invlaid handle");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_destroy: status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager handle created for this
++ * device.
++ */
++DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetChnlMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hChnlMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetChnlMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetChnlMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCmmMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hCmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetCmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCmmMgr: status 0x%x\t\nhMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER, "Entered DEV_GetDmmMgr, hDevObject: "
++ "0x%x\n\t\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hDmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDmmMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ */
++DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCodMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCodMgr, hDevObject: 0x%x\n\t\t"
++ "phCodMgr: 0x%x\n", hDevObject, phCodMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phCodMgr = pDevObject->hCodMgr;
++ } else {
++ *phCodMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetCodMgr, invalid handle: 0x%x\n",
++ hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCodMgr: status 0x%x\t\n hCodMgr:"
++ " 0x%x\n", status, *phCodMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phCodMgr != NULL) &&
++ (*phCodMgr == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetDehMgr ========
++ */
++DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDehMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++ if (IsValidHandle(hDevObject)) {
++ *phDehMgr = hDevObject->hDehMgr;
++ } else {
++ *phDehMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDehMgr: Invalid handle");
++ }
++ return status;
++}
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ */
++DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevNode != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetDevNode, hDevObject: 0x%x\n\t"
++ "\tphDevNode: 0x%x\n", hDevObject, phDevNode);
++ if (IsValidHandle(hDevObject)) {
++ *phDevNode = pDevObject->hDevNode;
++ } else {
++ *phDevNode = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDevNode: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDevNode: status 0x%x\t\nhDevNode:"
++ "0x%x\n", status, *phDevNode);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phDevNode != NULL) &&
++ (*phDevNode == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list
++ * DEV_OBJECTs maintained by DEV.
++ */
++struct DEV_OBJECT *DEV_GetFirst(void)
++{
++ struct DEV_OBJECT *pDevObject = NULL;
++
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++
++ DBC_Ensure((pDevObject == NULL) || IsValidHandle(pDevObject));
++
++ return pDevObject;
++}
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * ppIntfFxns != NULL.
++ */
++DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(ppIntfFxns != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetIntfFxns, hDevObject: 0x%x\n\t"
++ "\tppIntfFxns: 0x%x\n", hDevObject, ppIntfFxns);
++ if (IsValidHandle(hDevObject)) {
++ *ppIntfFxns = &pDevObject->intfFxns;
++ } else {
++ *ppIntfFxns = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetIntDxns: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetIntFxns: status 0x%x\t\n"
++ "ppIntFxns: 0x%x\n", status, *ppIntfFxns);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((ppIntfFxns != NULL) &&
++ (*ppIntfFxns == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetIOMgr ========
++ */
++DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ if (IsValidHandle(hDevObject)) {
++ *phIOMgr = hDevObject->hIOMgr;
++ } else {
++ *phIOMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_GetIOMgr: Invalid handle");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ */
++struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT *hDevObject)
++{
++ struct DEV_OBJECT *pNextDevObject = NULL;
++
++ if (IsValidHandle(hDevObject)) {
++ pNextDevObject = (struct DEV_OBJECT *)
++ DRV_GetNextDevObject((u32)hDevObject);
++ }
++ DBC_Ensure((pNextDevObject == NULL) || IsValidHandle(pNextDevObject));
++ return pNextDevObject;
++}
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ */
++void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ *phMsgMgr = hDevObject->hMsgMgr;
++}
++
++/*
++ * ======== DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle
++ */
++DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetNodeManager, hDevObject: 0x%x"
++ "\n\t\tphNodeMgr: 0x%x\n", hDevObject, phNodeMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phNodeMgr = pDevObject->hNodeMgr;
++ } else {
++ *phNodeMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetNodeManager, invalid handle: 0x"
++ "%x\n", hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetNodeManager: status 0x%x\t\nhMgr:"
++ " 0x%x\n", status, *phNodeMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNodeMgr != NULL) &&
++ (*phNodeMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetSymbol ========
++ */
++DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym, OUT u32 *pulValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_MANAGER *hCodMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pstrSym != NULL && pulValue != NULL);
++
++ GT_3trace(debugMask, GT_ENTER,
++ "Entered DEV_GetSymbol, hDevObject: 0x%x\n\t\t"
++ "pstrSym: 0x%x\n\t\tpulValue: 0x%x\n", hDevObject, pstrSym,
++ pulValue);
++ if (IsValidHandle(hDevObject)) {
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(hCodMgr != NULL);
++ status = COD_GetSymValue(hCodMgr, (char *)pstrSym,
++ pulValue);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetSymbol: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetSymbol: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *pulValue);
++ return status;
++}
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ */
++DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phWmdContext != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetWMDContext, hDevObject: 0x%x\n"
++ "\t\tphWmdContext: 0x%x\n", hDevObject, phWmdContext);
++ if (IsValidHandle(hDevObject)) {
++ *phWmdContext = pDevObject->hWmdContext;
++ } else {
++ *phWmdContext = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetWMDContext: Invalid handle");
++ }
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetWMDContext: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *phWmdContext);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phWmdContext != NULL) &&
++ (*phWmdContext == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void DEV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ if (cRefs == 0) {
++ CMM_Exit();
++ DMM_Exit();
++ }
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Exit, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ */
++bool DEV_Init(void)
++{
++ bool fCmm, fDmm, fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!debugMask.flags);
++ GT_create(&debugMask, "DV"); /* "DV" for DeVice */
++ fCmm = CMM_Init();
++ fDmm = DMM_Init();
++
++ fRetval = fCmm && fDmm;
++
++ if (!fRetval) {
++ if (fCmm)
++ CMM_Exit();
++
++
++ if (fDmm)
++ DMM_Exit();
++
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ */
++DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject, u32 ulStatus)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ struct DEV_OBJECT *pDevObject = hDevObject;
++ DSP_HPROCESSOR hProcObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_NotifyClients, hDevObject: 0x%x\n"
++ "\t\tulStatus: 0x%x\n", hDevObject, ulStatus);
++ for (hProcObject = (DSP_HPROCESSOR)LST_First(pDevObject->procList);
++ hProcObject != NULL;
++ hProcObject = (DSP_HPROCESSOR)LST_Next(pDevObject->procList,
++ (struct LST_ELEM *)hProcObject))
++ PROC_NotifyClients(hProcObject, (u32) ulStatus);
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveDevice ========
++ */
++DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject; /* handle to device object */
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject;
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_RemoveDevice, hDevNode: 0x%x\n", hDevNode);
++ /* Retrieve the device object handle originaly stored with
++ * the DevNode: */
++ status = CFG_GetDevObject(hDevNode, (u32 *)&hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Remove the Processor List */
++ pDevObject = (struct DEV_OBJECT *)hDevObject;
++ /* Destroy the device object. */
++ status = DEV_DestroyDevice(hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Null out the handle stored with the DevNode. */
++ GT_0trace(debugMask, GT_1CLASS,
++ "DEV_RemoveDevice, success");
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_RemoveDevice, status: 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ */
++DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject, struct CHNL_MGR *hMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetChnlMgr, hDevObject: 0x%x\n\t"
++ "\thMgr:0x%x\n", hDevObject, hMgr);
++ if (IsValidHandle(hDevObject)) {
++ pDevObject->hChnlMgr = hMgr;
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_SetChnlMgr, Invalid handle\n");
++ }
++ DBC_Ensure(DSP_FAILED(status) || (pDevObject->hChnlMgr == hMgr));
++ return status;
++}
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the message manager for this device.
++ */
++void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject, struct MSG_MGR *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetMsgMgr, hDevObject: 0x%x\n\t\t"
++ "hMgr: 0x%x\n", hDevObject, hMgr);
++ hDevObject->hMsgMgr = hMgr;
++}
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the BRIDGE environment.
++ */
++DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject = NULL; /* handle to 'Bridge Device */
++ struct CFG_HOSTRES hostRes; /* resources struct. */
++ struct CFG_DSPRES dspRes; /* DSP resources struct */
++ char szWMDFileName[CFG_MAXSEARCHPATHLEN] = "UMA"; /* wmd filename */
++ DSP_STATUS status;
++ struct MGR_OBJECT *hMgrObject = NULL;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_StartDevice, hDevObject: 0x%x\n", hDevNode);
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++ if (DSP_SUCCEEDED(status)) {
++ /* Get DSP resources of device from Registry: */
++ status = CFG_GetDSPResources(hDevNode, &dspRes);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD DSP resources"
++ " from registry: 0x%x ", status);
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD Host resources "
++ "from registry: 0x%x ", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Given all resources, create a device object. */
++ status = DEV_CreateDevice(&hDevObject, szWMDFileName, &hostRes,
++ &dspRes, hDevNode);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store away the hDevObject with the DEVNODE */
++ status = CFG_SetDevObject(hDevNode, (u32)hDevObject);
++ if (DSP_FAILED(status)) {
++ /* Clean up */
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to set DevObject in the "
++ "Registry: 0x%x", status);
++ DEV_DestroyDevice(hDevObject);
++ hDevObject = NULL;
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to Create Device: 0x%x",
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the Manager Object */
++ status = MGR_Create(&hMgrObject, hDevNode);
++ }
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS, "Failed to MGR object: 0x%x",
++ status);
++ status = DSP_EFAIL;
++ }
++ if (DSP_FAILED(status)) {
++ if (hDevObject)
++ DEV_DestroyDevice(hDevObject);
++
++ /* Ensure the device extension is NULL */
++ CFG_SetDevObject(hDevNode, 0L);
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exiting DEV_StartDevice status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== FxnNotImplemented ========
++ * Purpose:
++ * Takes the place of a WMD Null Function.
++ * Parameters:
++ * Multiple, optional.
++ * Returns:
++ * DSP_ENOTIMPL: Always.
++ */
++static DSP_STATUS FxnNotImplemented(int arg, ...)
++{
++ DBG_Trace(DBG_LEVEL1,
++ "WARNING: Calling a non-implemented WMD function.\n");
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== IsValidHandle ========
++ * Purpose:
++ * Validate the device object handle.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * true if handle is valid; false otherwise.
++ * Requires:
++ * Ensures:
++ */
++static bool IsValidHandle(struct DEV_OBJECT *hObj)
++{
++ bool retVal;
++
++ retVal = (hObj != NULL) && (hObj->dwSignature == SIGNATURE);
++
++ return retVal;
++}
++
++/*
++ * ======== InitCodMgr ========
++ * Purpose:
++ * Create a COD manager for this device.
++ * Parameters:
++ * pDevObject: Pointer to device object created with
++ * DEV_CreateDevice()
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * Should only be called once by DEV_CreateDevice() for a given DevObject.
++ * Ensures:
++ */
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *szDummyFile = "dummy";
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(!IsValidHandle(pDevObject) ||
++ (pDevObject->hCodMgr == NULL));
++ GT_1trace(debugMask, GT_ENTER, "Entering InitCodMgr pDevObject: 0x%x",
++ pDevObject);
++ status = COD_Create(&pDevObject->hCodMgr, szDummyFile, NULL);
++ GT_1trace(debugMask, GT_ENTER, "Exiting InitCodMgr status 0x%x\n ",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Insert a ProcObject into the list maintained by DEV.
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List Exists
++ * hDevObject is Valid handle
++ * DEV Initialized
++ * pbAlreadyAttached != NULL
++ * hProcObject != 0
++ * Ensures:
++ * DSP_SOK and List is not Empty.
++ */
++DSP_STATUS DEV_InsertProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject,
++ OUT bool *pbAlreadyAttached)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entering DEV_InsetProcObject pProcObject 0x%x"
++ "pDevObject 0x%x\n", hProcObject, hDevObject);
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(pbAlreadyAttached != NULL);
++ if (!LST_IsEmpty(pDevObject->procList))
++ *pbAlreadyAttached = true;
++
++ /* Add DevObject to tail. */
++ LST_PutTail(pDevObject->procList, (struct LST_ELEM *)hProcObject);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Exiting DEV_InsetProcObject status 0x%x\n", status);
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDevObject->procList));
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject Ptr to Dev Object where the list is.
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List exists and is not empty
++ * hProcObject != 0
++ * hDevObject is a valid Dev handle.
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ */
++DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct LST_ELEM *pCurElem;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(!LST_IsEmpty(pDevObject->procList));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entering DEV_RemoveProcObject hDevObject "
++ "0x%x\n", hDevObject);
++ /* Search list for pDevObject: */
++ for (pCurElem = LST_First(pDevObject->procList); pCurElem != NULL;
++ pCurElem = LST_Next(pDevObject->procList, pCurElem)) {
++ /* If found, remove it. */
++ if ((u32)pCurElem == hProcObject) {
++ LST_RemoveElem(pDevObject->procList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "DEV_RemoveProcObject returning 0x%x\n",
++ status);
++ return status;
++}
++
++DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject, u32 *devType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hdevObject;
++
++ *devType = pDevObject->devType;
++
++ return status;
++}
++
++/*
++ * ======== StoreInterfaceFxns ========
++ * Purpose:
++ * Copy the WMD's interface functions into the device object,
++ * ensuring that FxnNotImplemented() is set for:
++ *
++ * 1. All WMD function pointers which are NULL; and
++ * 2. All function slots in the struct DEV_OBJECT structure which have no
++ * corresponding slots in the the WMD's interface, because the WMD
++ * is of an *older* version.
++ * Parameters:
++ * pIntfFxns: Interface Fxn Structure of the WCD's Dev Object.
++ * pDrvFxns: Interface Fxns offered by the WMD during DEV_Create().
++ * Returns:
++ * Requires:
++ * Input pointers are valid.
++ * WMD is *not* written for a newer WCD.
++ * Ensures:
++ * All function pointers in the dev object's Fxn interface are not NULL.
++ */
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns)
++{
++ u32 dwWMDVersion;
++
++ /* Local helper macro: */
++#define StoreFxn(cast, pfn) \
++ (pIntfFxns->pfn = ((pDrvFxns->pfn != NULL) ? pDrvFxns->pfn : \
++ (cast)FxnNotImplemented))
++
++ DBC_Require(pIntfFxns != NULL);
++ DBC_Require(pDrvFxns != NULL);
++ DBC_Require(MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion) <= WCDVERSION);
++ dwWMDVersion = MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion);
++ pIntfFxns->dwWCDMajorVersion = pDrvFxns->dwWCDMajorVersion;
++ pIntfFxns->dwWCDMinorVersion = pDrvFxns->dwWCDMinorVersion;
++ /* Install functions up to WCD version .80 (first alpha): */
++ if (dwWMDVersion > 0) {
++ StoreFxn(WMD_DEV_CREATE, pfnDevCreate);
++ StoreFxn(WMD_DEV_DESTROY, pfnDevDestroy);
++ StoreFxn(WMD_DEV_CTRL, pfnDevCntrl);
++ StoreFxn(WMD_BRD_MONITOR, pfnBrdMonitor);
++ StoreFxn(WMD_BRD_START, pfnBrdStart);
++ StoreFxn(WMD_BRD_STOP, pfnBrdStop);
++ StoreFxn(WMD_BRD_STATUS, pfnBrdStatus);
++ StoreFxn(WMD_BRD_READ, pfnBrdRead);
++ StoreFxn(WMD_BRD_WRITE, pfnBrdWrite);
++ StoreFxn(WMD_BRD_SETSTATE, pfnBrdSetState);
++ StoreFxn(WMD_BRD_MEMCOPY, pfnBrdMemCopy);
++ StoreFxn(WMD_BRD_MEMWRITE, pfnBrdMemWrite);
++ StoreFxn(WMD_BRD_MEMMAP, pfnBrdMemMap);
++ StoreFxn(WMD_BRD_MEMUNMAP, pfnBrdMemUnMap);
++ StoreFxn(WMD_CHNL_CREATE, pfnChnlCreate);
++ StoreFxn(WMD_CHNL_DESTROY, pfnChnlDestroy);
++ StoreFxn(WMD_CHNL_OPEN, pfnChnlOpen);
++ StoreFxn(WMD_CHNL_CLOSE, pfnChnlClose);
++ StoreFxn(WMD_CHNL_ADDIOREQ, pfnChnlAddIOReq);
++ StoreFxn(WMD_CHNL_GETIOC, pfnChnlGetIOC);
++ StoreFxn(WMD_CHNL_CANCELIO, pfnChnlCancelIO);
++ StoreFxn(WMD_CHNL_FLUSHIO, pfnChnlFlushIO);
++ StoreFxn(WMD_CHNL_GETINFO, pfnChnlGetInfo);
++ StoreFxn(WMD_CHNL_GETMGRINFO, pfnChnlGetMgrInfo);
++ StoreFxn(WMD_CHNL_IDLE, pfnChnlIdle);
++ StoreFxn(WMD_CHNL_REGISTERNOTIFY, pfnChnlRegisterNotify);
++ StoreFxn(WMD_DEH_CREATE, pfnDehCreate);
++ StoreFxn(WMD_DEH_DESTROY, pfnDehDestroy);
++ StoreFxn(WMD_DEH_NOTIFY, pfnDehNotify);
++ StoreFxn(WMD_DEH_REGISTERNOTIFY, pfnDehRegisterNotify);
++ StoreFxn(WMD_DEH_GETINFO, pfnDehGetInfo);
++ StoreFxn(WMD_IO_CREATE, pfnIOCreate);
++ StoreFxn(WMD_IO_DESTROY, pfnIODestroy);
++ StoreFxn(WMD_IO_ONLOADED, pfnIOOnLoaded);
++ StoreFxn(WMD_IO_GETPROCLOAD, pfnIOGetProcLoad);
++ StoreFxn(WMD_MSG_CREATE, pfnMsgCreate);
++ StoreFxn(WMD_MSG_CREATEQUEUE, pfnMsgCreateQueue);
++ StoreFxn(WMD_MSG_DELETE, pfnMsgDelete);
++ StoreFxn(WMD_MSG_DELETEQUEUE, pfnMsgDeleteQueue);
++ StoreFxn(WMD_MSG_GET, pfnMsgGet);
++ StoreFxn(WMD_MSG_PUT, pfnMsgPut);
++ StoreFxn(WMD_MSG_REGISTERNOTIFY, pfnMsgRegisterNotify);
++ StoreFxn(WMD_MSG_SETQUEUEID, pfnMsgSetQueueId);
++ }
++ /* Add code for any additional functions in newer WMD versions here: */
++ /* Ensure postcondition: */
++ DBC_Ensure(pIntfFxns->pfnDevCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevCntrl != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdMonitor != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStart != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStop != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStatus != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdRead != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdWrite != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlOpen != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlClose != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlAddIOReq != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetIOC != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCancelIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlFlushIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetMgrInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlIdle != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnIODestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOOnLoaded != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOGetProcLoad != NULL);
++ DBC_Ensure(pIntfFxns->pfnMsgSetQueueId != NULL);
++
++#undef StoreFxn
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dmm.c b/drivers/dsp/bridge/pmgr/dmm.c
+new file mode 100644
+index 0000000..803de93
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dmm.c
+@@ -0,0 +1,692 @@
++/*
++ * dmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dmm.c ========
++ * Purpose:
++ * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ * DMM_CreateTables
++ * DMM_Create
++ * DMM_Destroy
++ * DMM_Exit
++ * DMM_Init
++ * DMM_MapMemory
++ * DMM_Reset
++ * DMM_ReserveMemory
++ * DMM_UnMapMemory
++ * DMM_UnReserveMemory
++ *
++ * Private Functions:
++ * AddRegion
++ * CreateRegion
++ * GetRegion
++ * GetFreeRegion
++ * GetMappedRegion
++ *
++ * Notes:
++ * Region: Generic memory entitiy having a start address and a size
++ * Chunk: Reserved region
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 04-Jun-2008 Hari K : Optimized DMM implementation. Removed linked list
++ *! and instead used Table approach.
++ *! 19-Apr-2004 sb: Integrated Alan's code review updates.
++ *! 17-Mar-2004 ap: Fixed GetRegion for size=0 using tighter bound.
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define DMMSIGNATURE 0x004d4d44 /* "DMM" (in reverse) */
++
++#define DMM_ADDR_VIRTUAL(a) \
++ (((struct MapPage *)(a) - pVirtualMappingTable) * PG_SIZE_4K +\
++ dynMemMapBeg)
++#define DMM_ADDR_TO_INDEX(a) (((a) - dynMemMapBeg) / PG_SIZE_4K)
++
++/* DMM Mgr */
++struct DMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Dmm Lock is used to serialize access mem manager for
++ * multi-threads. */
++ struct SYNC_CSOBJECT *hDmmLock; /* Lock to access dmm mgr */
++};
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++struct MapPage {
++ u32 RegionSize:15;
++ u32 MappedSize:15;
++ u32 bReserved:1;
++ u32 bMapped:1;
++};
++
++/* Create the free list */
++static struct MapPage *pVirtualMappingTable;
++static u32 iFreeRegion; /* The index of free region */
++static u32 iFreeSize;
++static u32 *pPhysicalAddrTable; /* Physical address of MPU buffer */
++static u32 dynMemMapBeg; /* The Beginning of dynamic memory mapping */
++static u32 TableSize;/* The size of virtual and physical pages tables */
++
++/* ----------------------------------- Function Prototypes */
++static struct MapPage *GetRegion(u32 addr);
++static struct MapPage *GetFreeRegion(u32 aSize);
++static struct MapPage *GetMappedRegion(u32 aAddr);
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++/* ======== DMM_CreateTables ========
++ * Purpose:
++ * Create table to hold the information of physical address
++ * the buffer pages that is passed by the user, and the table
++ * to hold the information of the virtual memory that is reserved
++ * for DSP.
++ */
++DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_CreateTables () hDmmMgr %x, addr"
++ " %x, size %x\n", hDmmMgr, addr, size);
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ dynMemMapBeg = addr;
++ TableSize = (size/PG_SIZE_4K) + 1;
++ /* Create the free list */
++ pVirtualMappingTable = (struct MapPage *) MEM_Calloc
++ (TableSize*sizeof(struct MapPage), MEM_NONPAGED);
++ if (pVirtualMappingTable == NULL)
++ status = DSP_EMEMORY;
++ else {
++ /* This table will be used
++ * to store the virtual to physical
++ * address translations
++ */
++ pPhysicalAddrTable = (u32 *)MEM_Calloc
++ (TableSize*sizeof(u32), MEM_NONPAGED);
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "DMM_CreateTables: Allocate"
++ "memory for pPhysicalAddrTable=%d entries\n",
++ TableSize);
++ if (pPhysicalAddrTable == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: Memory allocation for "
++ "pPhysicalAddrTable failed\n");
++ } else {
++ /* On successful allocation,
++ * all entries are zero ('free') */
++ iFreeRegion = 0;
++ iFreeSize = TableSize*PG_SIZE_4K;
++ pVirtualMappingTable[0].RegionSize = TableSize;
++ }
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: DMM_DeleteTables"
++ "Failure\n");
++
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status"
++ "0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DMM_Create ========
++ * Purpose:
++ * Create a dynamic memory manager object.
++ */
++DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs)
++{
++ struct DMM_OBJECT *pDmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "DMM_Create: phDmmMgr: 0x%x hDevObject: "
++ "0x%x pMgrAttrs: 0x%x\n", phDmmMgr, hDevObject, pMgrAttrs);
++ *phDmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pDmmObject, struct DMM_OBJECT, DMMSIGNATURE);
++ if (pDmmObject != NULL) {
++ status = SYNC_InitializeCS(&pDmmObject->hDmmLock);
++ if (DSP_SUCCEEDED(status))
++ *phDmmMgr = pDmmObject;
++ else
++ DMM_Destroy(pDmmObject);
++ } else {
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Create: Object Allocation "
++ "Failure(DMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_Create status %x pDmmObject %x\n",
++ status, pDmmObject);
++
++ return status;
++}
++
++/*
++ * ======== DMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Destroy () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ /* Delete CS & dmm mgr object */
++ SYNC_DeleteCS(pDmmObj->hDmmLock);
++ MEM_FreeObject(pDmmObj);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Destroy: DMM_DeleteTables "
++ "Failure\n");
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_Destroy status %x\n",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== DMM_DeleteTables ========
++ * Purpose:
++ * Delete DMM Tables.
++ */
++DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_DeleteTables () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ /* Delete all DMM tables */
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ if (pVirtualMappingTable != NULL)
++ MEM_Free(pVirtualMappingTable);
++
++ if (pPhysicalAddrTable != NULL)
++ MEM_Free(pPhysicalAddrTable);
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_DeleteTables status %x\n", status);
++ return status;
++}
++
++
++
++
++/*
++ * ======== DMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void DMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "exiting DMM_Exit, ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "DMM_GetHandle: hProcessor %x, phDmmMgr"
++ "%x\n", hProcessor, phDmmMgr);
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDmmMgr(hDevObject, phDmmMgr);
++
++ GT_2trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_GetHandle status %x, "
++ "*phDmmMgr %x\n", status, phDmmMgr ? *phDmmMgr : NULL);
++ return status;
++}
++
++/*
++ * ======== DMM_Init ========
++ * Purpose:
++ * Initializes private state of DMM module.
++ */
++bool DMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /*"DM" for Dymanic Memory Manager */
++ GT_create(&DMM_debugMask, "DM");
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Init, ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ pVirtualMappingTable = NULL ;
++ pPhysicalAddrTable = NULL ;
++ TableSize = 0;
++
++ return fRetval;
++}
++
++/*
++ * ======== DMM_MapMemory ========
++ * Purpose:
++ * Add a mapping block to the reserved chunk. DMM assumes that this block
++ * will be mapped in the DSP/IVA's address space. DMM returns an error if a
++ * mapping overlaps another one. This function stores the info that will be
++ * required later while unmapping the block.
++ */
++DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_MapMemory () hDmmMgr %x, "
++ "addr %x, size %x\n", hDmmMgr, addr, size);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ /* Find the Reserved memory chunk containing the DSP block to
++ * be mapped */
++ chunk = (struct MapPage *)GetRegion(addr);
++ if (chunk != NULL) {
++ /* Mark the region 'mapped', leave the 'reserved' info as-is */
++ chunk->bMapped = true;
++ chunk->MappedSize = (size/PG_SIZE_4K);
++ } else
++ status = DSP_ENOTFOUND;
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_MapMemory status %x, chunk %x\n",
++ status, chunk);
++ return status;
++}
++
++/*
++ * ======== DMM_ReserveMemory ========
++ * Purpose:
++ * Reserve a chunk of virtually contiguous DSP/IVA address space.
++ */
++DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
++ u32 *pRsvAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *node;
++ u32 rsvAddr = 0;
++ u32 rsvSize = 0;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_ReserveMemory () hDmmMgr %x, "
++ "size %x, pRsvAddr %x\n", hDmmMgr, size, pRsvAddr);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Try to get a DSP chunk from the free list */
++ node = GetFreeRegion(size);
++ if (node != NULL) {
++ /* DSP chunk of given size is available. */
++ rsvAddr = DMM_ADDR_VIRTUAL(node);
++ /* Calculate the number entries to use */
++ rsvSize = size/PG_SIZE_4K;
++ if (rsvSize < node->RegionSize) {
++ /* Mark remainder of free region */
++ node[rsvSize].bMapped = false;
++ node[rsvSize].bReserved = false;
++ node[rsvSize].RegionSize = node->RegionSize - rsvSize;
++ node[rsvSize].MappedSize = 0;
++ }
++ /* GetRegion will return first fit chunk. But we only use what
++ is requested. */
++ node->bMapped = false;
++ node->bReserved = true;
++ node->RegionSize = rsvSize;
++ node->MappedSize = 0;
++ /* Return the chunk's starting address */
++ *pRsvAddr = rsvAddr;
++ } else
++ /*dSP chunk of given size is not available */
++ status = DSP_EMEMORY;
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving ReserveMemory status %x, rsvAddr"
++ " %x, rsvSize %x\n", status, rsvAddr, rsvSize);
++ return status;
++}
++
++
++/*
++ * ======== DMM_UnMapMemory ========
++ * Purpose:
++ * Remove the mapped block from the reserved chunk.
++ */
++DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 *pSize)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnMapMemory () hDmmMgr %x, "
++ "addr %x, pSize %x\n", hDmmMgr, addr, pSize);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ chunk = GetMappedRegion(addr) ;
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND ;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Unmap the region */
++ *pSize = chunk->MappedSize * PG_SIZE_4K;
++ chunk->bMapped = false;
++ chunk->MappedSize = 0;
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnMapMemory status %x, chunk"
++ " %x, *pSize %x\n", status, chunk, *pSize);
++
++ return status;
++}
++
++/*
++ * ======== DMM_UnReserveMemory ========
++ * Purpose:
++ * Free a chunk of reserved DSP/IVA address space.
++ */
++DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 rsvAddr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 chunkSize;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnReserveMemory () hDmmMgr "
++ "%x, rsvAddr %x\n", hDmmMgr, rsvAddr);
++
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Find the chunk containing the reserved address */
++ chunk = GetMappedRegion(rsvAddr);
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Free all the mapped pages for this reserved region */
++ i = 0;
++ while (i < chunk->RegionSize) {
++ if (chunk[i].bMapped) {
++ /* Remove mapping from the page tables. */
++ chunkSize = chunk[i].MappedSize;
++ /* Clear the mapping flags */
++ chunk[i].bMapped = false;
++ chunk[i].MappedSize = 0;
++ i += chunkSize;
++ } else
++ i++;
++ }
++ /* Clear the flags (mark the region 'free') */
++ chunk->bReserved = false;
++ /* NOTE: We do NOT coalesce free regions here.
++ * Free regions are coalesced in GetRegion(), as it traverses
++ *the whole mapping table
++ */
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnReserveMemory status %x"
++ " chunk %x\n", status, chunk);
++ return status;
++}
++
++
++/*
++ * ======== GetRegion ========
++ * Purpose:
++ * Returns a region containing the specified memory region
++ */
++static struct MapPage *GetRegion(u32 aAddr)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetRegion () "
++ " aAddr %x\n", aAddr);
++
++ if (pVirtualMappingTable != NULL) {
++ /* find page mapped by this address */
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize)
++ currRegion = pVirtualMappingTable + i;
++ }
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving GetRegion currRegion %x, iFreeRegion %d\n,"
++ "iFreeSize %d\n", currRegion, iFreeRegion, iFreeSize) ;
++ return currRegion;
++}
++
++/*
++ * ======== GetFreeRegion ========
++ * Purpose:
++ * Returns the requested free region
++ */
++static struct MapPage *GetFreeRegion(u32 aSize)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++ u32 RegionSize = 0;
++ u32 nextI = 0;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetFreeRegion () "
++ "aSize 0x%x\n", aSize);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++ if (aSize > iFreeSize) {
++ /* Find the largest free region
++ * (coalesce during the traversal) */
++ while (i < TableSize) {
++ RegionSize = pVirtualMappingTable[i].RegionSize;
++ nextI = i+RegionSize;
++ if (pVirtualMappingTable[i].bReserved == false) {
++ /* Coalesce, if possible */
++ if (nextI < TableSize &&
++ pVirtualMappingTable[nextI].bReserved
++ == false) {
++ pVirtualMappingTable[i].RegionSize +=
++ pVirtualMappingTable[nextI].RegionSize;
++ continue;
++ }
++ RegionSize *= PG_SIZE_4K;
++ if (RegionSize > iFreeSize) {
++ iFreeRegion = i;
++ iFreeSize = RegionSize;
++ }
++ }
++ i = nextI;
++ }
++ }
++ if (aSize <= iFreeSize) {
++ currRegion = pVirtualMappingTable + iFreeRegion;
++ iFreeRegion += (aSize / PG_SIZE_4K);
++ iFreeSize -= aSize;
++ }
++ return currRegion;
++}
++
++/*
++ * ======== GetMappedRegion ========
++ * Purpose:
++ * Returns the requestedmapped region
++ */
++static struct MapPage *GetMappedRegion(u32 aAddr)
++{
++ u32 i = 0;
++ struct MapPage *currRegion = NULL;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetMappedRegion () "
++ "aAddr 0x%x\n", aAddr);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize && (pVirtualMappingTable[i].bMapped ||
++ pVirtualMappingTable[i].bReserved))
++ currRegion = pVirtualMappingTable + i;
++ return currRegion;
++}
++
++/*
++ * ======== DMM_GetPhysicalAddrTable ========
++ * Purpose:
++ * Returns the physical table address
++ */
++u32 *DMM_GetPhysicalAddrTable(void)
++{
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered "
++ "DMM_GetPhysicalAddrTable()- pPhysicalAddrTable 0x%x\n",
++ pPhysicalAddrTable);
++ return pPhysicalAddrTable;
++}
++
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr)
++{
++ struct MapPage *curNode = NULL;
++ u32 i;
++ u32 freemem = 0;
++ u32 bigsize = 0;
++
++ SYNC_EnterCS(hDmmMgr->hDmmLock);
++
++ if (pVirtualMappingTable != NULL) {
++ for (i = 0; i < TableSize; i +=
++ pVirtualMappingTable[i].RegionSize) {
++ curNode = pVirtualMappingTable + i;
++ if (curNode->bReserved == TRUE) {
++ /*printk("RESERVED size = 0x%x, "
++ "Map size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K),
++ (curNode->bMapped == false) ? 0 :
++ (curNode->MappedSize * PG_SIZE_4K));
++*/
++ } else {
++/* printk("UNRESERVED size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K));
++*/
++ freemem += (curNode->RegionSize * PG_SIZE_4K);
++ if (curNode->RegionSize > bigsize)
++ bigsize = curNode->RegionSize;
++ }
++ }
++ }
++ printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
++ freemem/(1024*1024));
++ printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
++ (((TableSize * PG_SIZE_4K)-freemem))/(1024*1024));
++ printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
++ (bigsize*PG_SIZE_4K/(1024*1024)));
++ SYNC_LeaveCS(hDmmMgr->hDmmLock);
++
++ return 0;
++}
++#endif
+diff --git a/drivers/dsp/bridge/pmgr/io.c b/drivers/dsp/bridge/pmgr/io.c
+new file mode 100644
+index 0000000..cdfe0dc
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/io.c
+@@ -0,0 +1,205 @@
++/*
++ * io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.c ========
++ * Description:
++ * IO manager interface: Manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD IO functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 04-Apr-2001 rr WSX_STATUS initialized in IO_Create.
++ *! 07-Nov-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <ioobj.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++
++#if GT_TRACE
++static struct GT_Mask IO_DebugMask = { NULL, NULL }; /* WCD IO Mask */
++#endif
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG
++ */
++DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr, struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr = NULL;
++ struct IO_MGR_ *pIOMgr = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(IO_DebugMask, GT_ENTER, "Entered IO_Create: phIOMgr: 0x%x\t "
++ "hDevObject: 0x%x\tpMgrAttrs: 0x%x\n",
++ phIOMgr, hDevObject, pMgrAttrs);
++
++ *phIOMgr = NULL;
++
++ /* A memory base of 0 implies no memory base: */
++ if ((pMgrAttrs->dwSMBase != 0) && (pMgrAttrs->uSMLength == 0)) {
++ status = CHNL_E_INVALIDMEMBASE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Mem Base\n");
++ }
++
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Word size\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnIOCreate)(&hIOMgr, hDevObject,
++ pMgrAttrs);
++
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr = (struct IO_MGR_ *) hIOMgr;
++ pIOMgr->pIntfFxns = pIntfFxns;
++ pIOMgr->hDevObject = hDevObject;
++
++ /* Return the new channel manager handle: */
++ *phIOMgr = hIOMgr;
++ GT_1trace(IO_DebugMask, GT_1CLASS,
++ "IO_Create: Success hIOMgr: 0x%x\n",
++ hIOMgr);
++ }
++ }
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Create: hIOMgr: 0x%x, status:"
++ " 0x%x\n", hIOMgr, status);
++
++ return status;
++}
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Delete IO manager.
++ */
++DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR_ *pIOMgr = (struct IO_MGR_ *)hIOMgr;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(IO_DebugMask, GT_ENTER, "Entered IO_Destroy: hIOMgr: 0x%x\n",
++ hIOMgr);
++
++ pIntfFxns = pIOMgr->pIntfFxns;
++
++ /* Let WMD channel module destroy the IO_MGR: */
++ status = (*pIntfFxns->pfnIODestroy) (hIOMgr);
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Destroy: pIOMgr: 0x%x, status:"
++ " 0x%x\n", pIOMgr, status);
++ return status;
++}
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ */
++void IO_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ */
++bool IO_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!IO_DebugMask.flags);
++ GT_create(&IO_DebugMask, "IO"); /* "IO" for IO */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Init, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
+diff --git a/drivers/dsp/bridge/pmgr/ioobj.h b/drivers/dsp/bridge/pmgr/ioobj.h
+new file mode 100644
+index 0000000..f473a63
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/ioobj.h
+@@ -0,0 +1,52 @@
++/*
++ * ioobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ioobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library IO objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 01/16/97 gp: Created from chnlpriv.h
++ */
++
++#ifndef IOOBJ_
++#define IOOBJ_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/wmd.h>
++
++/*
++ * This struct is the first field in a IO_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct IO_MGR_ {
++ /* These must be the first fields in a IO_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents. */
++} ;
++
++#endif /* IOOBJ_ */
+diff --git a/drivers/dsp/bridge/pmgr/msg.c b/drivers/dsp/bridge/pmgr/msg.c
+new file mode 100644
+index 0000000..bbf5174
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msg.c
+@@ -0,0 +1,173 @@
++/*
++ * msg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.c ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 15-May-2001 ag Changed SUCCEEDED to DSP_SUCCEEDED.
++ *! 16-Feb-2001 jeh Fixed some comments.
++ *! 15-Dec-2000 rr MSG_Create returns DSP_EFAIL if pfnMsgCreate fails.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <msgobj.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MSG_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct MSG_MGR_ *pMsgMgr;
++ struct MSG_MGR *hMsgMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(MSG_debugMask, GT_ENTER, "MSG_Create: phMsgMgr: 0x%x\t"
++ "hDevObject: 0x%x\tmsgCallback: 0x%x\n",
++ phMsgMgr, hDevObject, msgCallback);
++
++ *phMsgMgr = NULL;
++
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD message module finish the create: */
++ status = (*pIntfFxns->pfnMsgCreate)(&hMsgMgr, hDevObject, msgCallback);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD message module's fields of the MSG_MGR
++ * structure */
++ pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ pMsgMgr->pIntfFxns = pIntfFxns;
++
++ /* Finally, return the new message manager handle: */
++ *phMsgMgr = hMsgMgr;
++ GT_1trace(MSG_debugMask, GT_1CLASS,
++ "MSG_Create: Success pMsgMgr: 0x%x\n", pMsgMgr);
++ } else {
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ */
++void MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ struct MSG_MGR_ *pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++
++ GT_1trace(MSG_debugMask, GT_ENTER, "MSG_Delete: hMsgMgr: 0x%x\n",
++ hMsgMgr);
++
++ pIntfFxns = pMsgMgr->pIntfFxns;
++
++ /* Let WMD message module destroy the MSG_MGR: */
++ (*pIntfFxns->pfnMsgDelete)(hMsgMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++}
++
++/*
++ * ======== MSG_Exit ========
++ */
++void MSG_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(MSG_debugMask, GT_5CLASS,
++ "Entered MSG_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MSG_Init ========
++ */
++bool MSG_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!MSG_debugMask.flags);
++ GT_create(&MSG_debugMask, "MG"); /* "MG" for MsG */
++ }
++
++ cRefs++;
++
++ GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/msgobj.h b/drivers/dsp/bridge/pmgr/msgobj.h
+new file mode 100644
+index 0000000..63d025b
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msgobj.h
+@@ -0,0 +1,52 @@
++/*
++ * msgobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library MSG objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef MSGOBJ_
++#define MSGOBJ_
++
++#include <dspbridge/wmd.h>
++
++#include <dspbridge/msgdefs.h>
++
++/*
++ * This struct is the first field in a MSG_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct MSG_MGR_ {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++};
++
++#endif /* MSGOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c
+new file mode 100644
+index 0000000..859043d
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/wcd.c
+@@ -0,0 +1,1647 @@
++/*
++ * wcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== wcd.c ========
++ * Description:
++ * Common WCD functions, also includes the wrapper
++ * functions called directly by the DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ *! Revision History:
++ *! ================
++ *! 29-Apr-2004 hp Call PROC_AutoStart only for DSP device
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 03-Apr-2003 sb Process environment pointer in PROCWRAP_Load
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 30-Jan-2002 ag CMMWRAP_AllocBuf name changed to CMMWRAP_CallocBuf
++ *! 15-Jan-2002 ag Added actual bufSize param to STRMWRAP_Reclaim[issue].
++ *! 14-Dec-2001 rr ARGS_NODE_CONNECT maps the pAttr.
++ *! 03-Oct-2001 rr ARGS_NODE_ALLOCMSGBUF/FREEMSGBUF maps the pAttr.
++ *! 10-Sep-2001 ag Added CMD_CMM_GETHANDLE.
++ *! 23-Apr-2001 jeh Pass pStatus to NODE_Terminate.
++ *! 11-Apr-2001 jeh STRMWRAP_Reclaim embedded pointer is mapped and unmapped.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 06-Dec-2000 jeh WRAP_MAP2CALLER pointers in RegisterNotify calls.
++ *! 05-Dec-2000 ag: Removed MAP2CALLER in NODEWRAP_FreeMsgBuf().
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data().
++ *! 20-Nov-2000 jeh Added MSG_Init()/MSG_Exit(), IO_Init()/IO_Exit().
++ *! WRAP pointers to handles for PROC_Attach, NODE_Allocate.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 12-Oct-2000 ag: Added user CMM wrappers.
++ *! 05-Oct-2000 rr: WcdInitComplete2 will fail even if one BRD or PROC
++ *! AutoStart fails.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 13-Sep-2000 jeh Pass ARGS_NODE_CONNECT.pAttrs to NODE_Connect().
++ *! 11-Aug-2000 rr: Part of node enabled.
++ *! 31-Jul-2000 rr: UTIL_Wrap and MEM_Wrap added to RM.
++ *! 27-Jul-2000 rr: PROCWRAP, NODEWRAP and STRMWRAP implemented.
++ *! STRM and some NODE Wrappers are not implemented.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 08-Feb-2000 rr File name changed to wcd.c
++ *! 03-Feb-2000 rr: Module initialization are done by SERVICES init. GT Class
++ *! changes for module init/exit fxns.
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-1999 sg: Changed ARGS_CHNL_GETMODE field name from pdwMode to pMode.
++ *! 17-Jan-2000 rr: BRD_GetStatus does WRAP_MAP2CALLER for state.
++ *! 14-Dec-1999 ag: Removed _MAP2CALLER in CHNL_GetMgr().
++ *! 13-Dec-1999 rr: BRDWRAP_GetSymbol, BRDWRAP_GetTrace uses WRAP_MAP2CALLER
++ *! macros.BRDWRAP_Load maps and unmaps embedded pointers.
++ *! 10-Dec-1999 ag: User CHNL bufs mapped in _AddIOReq & _GetIOCompletion.
++ *! 09-Dec-1999 rr: BRDWRAP_Open and CHNLWRAP_GetMgr does not map
++ *! pointer as there was a change in config.c
++ *! 06-Dec-1999 rr: BRD_Read and Write Maps the buf pointers.
++ *! 03-Dec-1999 rr: CHNLWRAP_GetMgr and BRDWRAP_Open maps hDevNode pointer.
++ *! WCD_InitComplete2 Included for BRD_AutoStart.
++ *! 16-Nov-1999 ag: Map buf to process in CHNLWRAP_AllocBuffer().
++ *! CHNL_GetMgr() Mapping Fix.
++ *! 10-Nov-1999 ag: Removed unnecessary calls to WRAP_MAP2CALLER.
++ *! 08-Nov-1999 kc: Added MEMRY & enabled BRD_IOCtl for tests.
++ *! 29-Oct-1999 ag: Added CHNL.
++ *! 29-Oct-1999 kc: Added trace statements; added ptr mapping; updated
++ *! use of UTIL module API.
++ *! 29-Oct-1999 rr: Wrapper functions does the Mapping of the Pointers.
++ *! in WinCE all the explicit pointers will be converted
++ *! by the OS during interprocess but not the embedded pointers.
++ *! 16-Oct-1999 kc: Code review cleanup.
++ *! 07-Oct-1999 kc: Added UTILWRAP_TestDll() to run PM test harness. See
++ *! /src/doc/pmtest.doc for more detail.
++ *! 09-Sep-1999 rr: After exactly two years(!). Adopted for WinCE. GT Enabled.
++ *! 09-Sep-1997 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/services.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/chnl.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/disp.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/rmm.h>
++
++
++/* ----------------------------------- Others */
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dbdcd.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MAX_TRACEBUFLEN 255
++#define MAX_LOADARGS 16
++#define MAX_NODES 64
++#define MAX_STREAMS 16
++#define MAX_BUFS 64
++
++/* Following two macros should ideally have do{}while(0) */
++
++#define cp_fm_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(src == NULL) || \
++ unlikely(copy_from_user(dest, src, elements * sizeof(*(dest))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_from_user failed, src=0x%x\n", src); \
++ status = DSP_EPOINTER ; \
++ } \
++ }
++
++#define cp_to_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(dest == NULL) || \
++ unlikely(copy_to_user(dest, src, elements * sizeof(*(src))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_to_user failed, dest=0x%x\n", dest); \
++ status = DSP_EPOINTER ;\
++ } \
++ }
++
++/* Device IOCtl function pointer */
++struct WCD_Cmd {
++ u32(*fxn)(union Trapped_Args *args);
++ u32 dwIndex;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask WCD_debugMask = { NULL, NULL }; /* Core VxD Mask */
++#endif
++static u32 WCD_cRefs;
++
++/*
++ * Function table.
++ * The order of these functions MUST be the same as the order of the command
++ * numbers defined in wcdioctl.h This is how an IOCTL number in user mode
++ * turns into a function call in kernel mode.
++ */
++static struct WCD_Cmd WCD_cmdTable[] = {
++ /* MGR module */
++ {MGRWRAP_EnumNode_Info, CMD_MGR_ENUMNODE_INFO_OFFSET},
++ {MGRWRAP_EnumProc_Info, CMD_MGR_ENUMPROC_INFO_OFFSET},
++ {MGRWRAP_RegisterObject, CMD_MGR_REGISTEROBJECT_OFFSET},
++ {MGRWRAP_UnregisterObject, CMD_MGR_UNREGISTEROBJECT_OFFSET},
++ {MGRWRAP_WaitForBridgeEvents, CMD_MGR_WAIT_OFFSET},
++#ifndef RES_CLEANUP_DISABLE
++ {MGRWRAP_GetProcessResourcesInfo, CMD_MGR_RESOUCES_OFFSET},
++#endif
++ /* PROC Module */
++ {PROCWRAP_Attach, CMD_PROC_ATTACH_OFFSET},
++ {PROCWRAP_Ctrl, CMD_PROC_CTRL_OFFSET},
++ {PROCWRAP_Detach, CMD_PROC_DETACH_OFFSET},
++ {PROCWRAP_EnumNode_Info, CMD_PROC_ENUMNODE_OFFSET},
++ {PROCWRAP_EnumResources, CMD_PROC_ENUMRESOURCES_OFFSET},
++ {PROCWRAP_GetState, CMD_PROC_GETSTATE_OFFSET},
++ {PROCWRAP_GetTrace, CMD_PROC_GETTRACE_OFFSET},
++ {PROCWRAP_Load, CMD_PROC_LOAD_OFFSET},
++ {PROCWRAP_RegisterNotify, CMD_PROC_REGISTERNOTIFY_OFFSET},
++ {PROCWRAP_Start, CMD_PROC_START_OFFSET},
++ {PROCWRAP_ReserveMemory, CMD_PROC_RSVMEM_OFFSET},
++ {PROCWRAP_UnReserveMemory, CMD_PROC_UNRSVMEM_OFFSET},
++ {PROCWRAP_Map, CMD_PROC_MAPMEM_OFFSET},
++ {PROCWRAP_UnMap, CMD_PROC_UNMAPMEM_OFFSET},
++ {PROCWRAP_FlushMemory, CMD_PROC_FLUSHMEMORY_OFFSET},
++ {PROCWRAP_Stop, CMD_PROC_STOP_OFFSET},
++ {PROCWRAP_InvalidateMemory, CMD_PROC_INVALIDATEMEMORY_OFFSET},
++ /* NODE Module */
++ {NODEWRAP_Allocate, CMD_NODE_ALLOCATE_OFFSET},
++ {NODEWRAP_AllocMsgBuf, CMD_NODE_ALLOCMSGBUF_OFFSET},
++ {NODEWRAP_ChangePriority, CMD_NODE_CHANGEPRIORITY_OFFSET},
++ {NODEWRAP_Connect, CMD_NODE_CONNECT_OFFSET},
++ {NODEWRAP_Create, CMD_NODE_CREATE_OFFSET},
++ {NODEWRAP_Delete, CMD_NODE_DELETE_OFFSET},
++ {NODEWRAP_FreeMsgBuf, CMD_NODE_FREEMSGBUF_OFFSET},
++ {NODEWRAP_GetAttr, CMD_NODE_GETATTR_OFFSET},
++ {NODEWRAP_GetMessage, CMD_NODE_GETMESSAGE_OFFSET},
++ {NODEWRAP_Pause, CMD_NODE_PAUSE_OFFSET},
++ {NODEWRAP_PutMessage, CMD_NODE_PUTMESSAGE_OFFSET},
++ {NODEWRAP_RegisterNotify, CMD_NODE_REGISTERNOTIFY_OFFSET},
++ {NODEWRAP_Run, CMD_NODE_RUN_OFFSET},
++ {NODEWRAP_Terminate, CMD_NODE_TERMINATE_OFFSET},
++ {NODEWRAP_GetUUIDProps, CMD_NODE_GETUUIDPROPS_OFFSET},
++ /* STRM wrapper functions */
++ {STRMWRAP_AllocateBuffer, CMD_STRM_ALLOCATEBUFFER_OFFSET},
++ {STRMWRAP_Close, CMD_STRM_CLOSE_OFFSET},
++ {STRMWRAP_FreeBuffer, CMD_STRM_FREEBUFFER_OFFSET},
++ {STRMWRAP_GetEventHandle, CMD_STRM_GETEVENTHANDLE_OFFSET},
++ {STRMWRAP_GetInfo, CMD_STRM_GETINFO_OFFSET},
++ {STRMWRAP_Idle, CMD_STRM_IDLE_OFFSET},
++ {STRMWRAP_Issue, CMD_STRM_ISSUE_OFFSET},
++ {STRMWRAP_Open, CMD_STRM_OPEN_OFFSET},
++ {STRMWRAP_Reclaim, CMD_STRM_RECLAIM_OFFSET},
++ {STRMWRAP_RegisterNotify, CMD_STRM_REGISTERNOTIFY_OFFSET},
++ {STRMWRAP_Select, CMD_STRM_SELECT_OFFSET},
++ /* CMM module */
++ {CMMWRAP_CallocBuf, CMD_CMM_ALLOCBUF_OFFSET},
++ {CMMWRAP_FreeBuf, CMD_CMM_FREEBUF_OFFSET},
++ {CMMWRAP_GetHandle, CMD_CMM_GETHANDLE_OFFSET},
++ {CMMWRAP_GetInfo, CMD_CMM_GETINFO_OFFSET}
++};
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ */
++inline DSP_STATUS WCD_CallDevIOCtl(u32 cmd, union Trapped_Args *args,
++ u32 *pResult)
++{
++ if ((cmd < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)))) {
++ /* make the fxn call via the cmd table */
++ *pResult = (*WCD_cmdTable[cmd].fxn) (args);
++ return DSP_SOK;
++ } else {
++ return DSP_EINVALIDARG;
++ }
++}
++
++/*
++ * ======== WCD_Exit ========
++ */
++void WCD_Exit(void)
++{
++ DBC_Require(WCD_cRefs > 0);
++ WCD_cRefs--;
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Exit, ref count: 0x%x\n", WCD_cRefs);
++ if (WCD_cRefs == 0) {
++ /* Release all WCD modules initialized in WCD_Init(). */
++ COD_Exit();
++ DEV_Exit();
++ CHNL_Exit();
++ MSG_Exit();
++ IO_Exit();
++ STRM_Exit();
++ NTFY_Exit();
++ DISP_Exit();
++ NODE_Exit();
++ PROC_Exit();
++ MGR_Exit();
++ RMM_exit();
++ DRV_Exit();
++ SERVICES_Exit();
++ }
++ DBC_Ensure(WCD_cRefs >= 0);
++}
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Module initialization is done by SERVICES Init.
++ */
++bool WCD_Init(void)
++{
++ bool fInit = true;
++ bool fDRV, fDEV, fCOD, fSERVICES, fCHNL, fMSG, fIO;
++ bool fMGR, fPROC, fNODE, fDISP, fNTFY, fSTRM, fRMM;
++#ifdef DEBUG
++ /* runtime check of Device IOCtl array. */
++ u32 i;
++ for (i = 1; i < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)); i++)
++ DBC_Assert(WCD_cmdTable[i - 1].dwIndex == i);
++
++#endif
++ if (WCD_cRefs == 0) {
++ /* initialize all SERVICES modules */
++ fSERVICES = SERVICES_Init();
++ /* initialize debugging module */
++ DBC_Assert(!WCD_debugMask.flags);
++ GT_create(&WCD_debugMask, "CD"); /* CD for class driver */
++ /* initialize class driver and other modules */
++ fDRV = DRV_Init();
++ fMGR = MGR_Init();
++ fPROC = PROC_Init();
++ fNODE = NODE_Init();
++ fDISP = DISP_Init();
++ fNTFY = NTFY_Init();
++ fSTRM = STRM_Init();
++ fRMM = RMM_init();
++ fCHNL = CHNL_Init();
++ fMSG = MSG_Init();
++ fIO = IO_Init();
++ fDEV = DEV_Init();
++ fCOD = COD_Init();
++ fInit = fSERVICES && fDRV && fDEV && fCHNL && fCOD &&
++ fMSG && fIO;
++ fInit = fInit && fMGR && fPROC && fRMM;
++ if (!fInit) {
++ if (fSERVICES)
++ SERVICES_Exit();
++
++ if (fDRV)
++ DRV_Exit();
++
++ if (fMGR)
++ MGR_Exit();
++
++ if (fSTRM)
++ STRM_Exit();
++
++ if (fPROC)
++ PROC_Exit();
++
++ if (fNODE)
++ NODE_Exit();
++
++ if (fDISP)
++ DISP_Exit();
++
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fCHNL)
++ CHNL_Exit();
++
++ if (fMSG)
++ MSG_Exit();
++
++ if (fIO)
++ IO_Exit();
++
++ if (fDEV)
++ DEV_Exit();
++
++ if (fCOD)
++ COD_Exit();
++
++ if (fRMM)
++ RMM_exit();
++
++ }
++ }
++ if (fInit)
++ WCD_cRefs++;
++
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Init, ref count: 0x%x\n", WCD_cRefs);
++ return fInit;
++}
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init() or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++DSP_STATUS WCD_InitComplete2(void)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_DEVNODE *DevNode;
++ struct DEV_OBJECT *hDevObject;
++ u32 devType;
++
++ DBC_Require(WCD_cRefs > 0);
++ GT_0trace(WCD_debugMask, GT_ENTER, "Entered WCD_InitComplete\n");
++ /* Walk the list of DevObjects, get each devnode, and attempting to
++ * autostart the board. Note that this requires COF loading, which
++ * requires KFILE. */
++ for (hDevObject = DEV_GetFirst(); hDevObject != NULL;
++ hDevObject = DEV_GetNext(hDevObject)) {
++ if (DSP_FAILED(DEV_GetDevNode(hDevObject, &DevNode)))
++ continue;
++
++ if (DSP_FAILED(DEV_GetDevType(hDevObject, &devType)))
++ continue;
++
++ if ((devType == DSP_UNIT) || (devType == IVA_UNIT)) {
++ if (DSP_FAILED(PROC_AutoStart(DevNode, hDevObject))) {
++ GT_0trace(WCD_debugMask, GT_1CLASS,
++ "WCD_InitComplete2 Failed\n");
++ status = DSP_EFAIL;
++ /* break; */
++ }
++ } else
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Ignoring PROC_AutoStart "
++ "for Device Type = 0x%x \n", devType);
++ } /* End For Loop */
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Exiting WCD_InitComplete status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumNode_Info ========
++ */
++u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ u8 *pNDBProps;
++ u32 uNumNodes;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGR_EnumNodeInfo: entered args:\n0x%x"
++ " uNode: 0x%x\tpNDBProps: 0x%x\tuNDBPropsSize: "
++ "0x%x\tpuNumNodes\n", args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ args->ARGS_MGR_ENUMNODE_INFO.pNDBProps,
++ args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize,
++ args->ARGS_MGR_ENUMNODE_INFO.puNumNodes);
++ pNDBProps = MEM_Alloc(size, MEM_NONPAGED);
++ if (pNDBProps == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumNodeInfo(args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ (struct DSP_NDBPROPS *)pNDBProps,
++ size, &uNumNodes);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.pNDBProps, pNDBProps, status,
++ size);
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.puNumNodes, &uNumNodes, status,
++ 1);
++ if (pNDBProps)
++ MEM_Free(pNDBProps);
++
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumProc_Info ========
++ */
++u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args)
++{
++ u8 *pProcessorInfo;
++ u32 uNumProcs;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_EnumProc_Info: entered args:\n"
++ "0x%x uProcessor: 0x%x\tpProcessorInfo: 0x%x\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs \n",
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo,
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize,
++ args->ARGS_MGR_ENUMPROC_INFO.puNumProcs);
++ pProcessorInfo = MEM_Alloc(size, MEM_NONPAGED);
++ if (pProcessorInfo == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumProcessorInfo(args->
++ ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ (struct DSP_PROCESSORINFO *)pProcessorInfo,
++ size, &uNumProcs);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo, pProcessorInfo,
++ status, size);
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.puNumProcs, &uNumProcs,
++ status, 1);
++ if (pProcessorInfo)
++ MEM_Free(pProcessorInfo);
++
++ return status;
++}
++
++#define WRAP_MAP2CALLER(x) x
++/*
++ * ======== MGRWRAP_RegisterObject ========
++ */
++u32 MGRWRAP_RegisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_RegisterObject: entered pg2hMsg "
++ "0x%x\n", args->ARGS_MGR_REGISTEROBJECT.pUuid);
++ retVal = DCD_RegisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_REGISTEROBJECT.pUuid),
++ args->ARGS_MGR_REGISTEROBJECT.objType,
++ WRAP_MAP2CALLER(args->ARGS_MGR_REGISTEROBJECT.pszPathName));
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_UnregisterObject ========
++ */
++u32 MGRWRAP_UnregisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_UnregisterObject: entered pg2hMsg"
++ " 0x%x\n", args->ARGS_MGR_UNREGISTEROBJECT.pUuid);
++ retVal = DCD_UnregisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_UNREGISTEROBJECT.pUuid),
++ args->ARGS_MGR_UNREGISTEROBJECT.objType);
++
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_WaitForBridgeEvents ========
++ */
++u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS];
++ struct DSP_NOTIFICATION notifications[MAX_EVENTS];
++ u32 uIndex, i;
++ u32 uCount = args->ARGS_MGR_WAIT.uCount;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_WaitForBridgeEvents: entered\n");
++
++ if (uCount > MAX_EVENTS)
++ status = DSP_EINVALIDARG;
++
++ /* get the array of pointers to user structures */
++ cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications,
++ status, uCount);
++ /* get the events */
++ for (i = 0; i < uCount; i++) {
++ cp_fm_usr(&notifications[i], aNotifications[i], status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the array of pointers to kernel structures*/
++ aNotifications[i] = &notifications[i];
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_WaitForBridgeEvents(aNotifications, uCount,
++ &uIndex, args->ARGS_MGR_WAIT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1);
++ return status;
++}
++
++
++#ifndef RES_CLEANUP_DISABLE
++/*
++ * ======== MGRWRAP_GetProcessResourceInfo ========
++ */
++u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uSize = 0;
++ u8 *pBuf = MEM_Alloc(8092, MEM_NONPAGED);
++ status = DRV_ProcDisplayResInfo(pBuf, &uSize);
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_GetProcessResourcesInfo:uSize=%d :\n", uSize);
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, uSize);
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "123MGRWRAP_GetProcessResourcesInfo:**************\n");
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "456MGRWRAP_GetProcessResourcesInfo:**************\n");
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pSize, &uSize, status, 1);
++ MEM_Free(pBuf);
++ return status;
++}
++#endif
++
++
++/*
++ * ======== PROCWRAP_Attach ========
++ */
++u32 PROCWRAP_Attach(union Trapped_Args *args)
++{
++ DSP_HPROCESSOR processor;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_PROCESSORATTRIN attrIn, *pAttrIn = NULL;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Attach: entered args:\n" "0x%x"
++ " uProcessor: 0x%x\tpAttrIn: 0x%x\tphProcessor \n",
++ args->ARGS_PROC_ATTACH.uProcessor,
++ args->ARGS_PROC_ATTACH.pAttrIn,
++ args->ARGS_PROC_ATTACH.phProcessor);
++ /* Optional argument */
++ if (args->ARGS_PROC_ATTACH.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_PROC_ATTACH.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ status = PROC_Attach(args->ARGS_PROC_ATTACH.uProcessor, pAttrIn,
++ &processor);
++ cp_to_usr(args->ARGS_PROC_ATTACH.phProcessor, &processor, status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Ctrl ========
++ */
++u32 PROCWRAP_Ctrl(union Trapped_Args *args)
++{
++ u32 cbDataSize, __user *pSize = (u32 __user *)
++ args->ARGS_PROC_CTRL.pArgs;
++ u8 *pArgs = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Ctrl: entered args:\n 0x%x"
++ " uProcessor: 0x%x\tdwCmd: 0x%x\tpArgs \n",
++ args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ args->ARGS_PROC_CTRL.pArgs);
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_PROC_CTRL.pArgs, status,
++ cbDataSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Ctrl(args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ (struct DSP_CBDATA *)pArgs);
++ }
++
++ /* cp_to_usr(args->ARGS_PROC_CTRL.pArgs, pArgs, status, 1);*/
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Detach ========
++ */
++u32 PROCWRAP_Detach(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Detach: entered args\n0x%x "
++ "hProceesor \n", args->ARGS_PROC_DETACH.hProcessor);
++ retVal = PROC_Detach(args->ARGS_PROC_DETACH.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_EnumNode_Info ========
++ */
++u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_HNODE aNodeTab[MAX_NODES];
++ u32 uNumNodes;
++ u32 uAllocated;
++
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumNode_Info:entered args:\n0x"
++ "%xhProcessor:0x%x\taNodeTab:0x%x\tuNodeTabSize:"
++ "%0x%x\tpuNumNodes%\n0x%x puAllocated: \n",
++ args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ args->ARGS_PROC_ENUMNODE_INFO.aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ args->ARGS_PROC_ENUMNODE_INFO.puNumNodes,
++ args->ARGS_PROC_ENUMNODE_INFO.puAllocated);
++ DBC_Require(args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize <= MAX_NODES);
++ status = PROC_EnumNodes(args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ &uNumNodes, &uAllocated);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.aNodeTab, aNodeTab, status,
++ uNumNodes);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puNumNodes, &uNumNodes,
++ status, 1);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puAllocated, &uAllocated,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_FlushMemory ========
++ */
++u32 PROCWRAP_FlushMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_FlushMemory: entered\n");
++
++ status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
++ args->ARGS_PROC_FLUSHMEMORY.pMpuAddr,
++ args->ARGS_PROC_FLUSHMEMORY.ulSize,
++ args->ARGS_PROC_FLUSHMEMORY.ulFlags);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_InvalidateMemory ========
++ */
++u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_InvalidateMemory:entered\n");
++
++ status = PROC_InvalidateMemory(
++ args->ARGS_PROC_INVALIDATEMEMORY.hProcessor,
++ args->ARGS_PROC_INVALIDATEMEMORY.pMpuAddr,
++ args->ARGS_PROC_INVALIDATEMEMORY.ulSize);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_EnumResources ========
++ */
++u32 PROCWRAP_EnumResources(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumResources: entered args:\n"
++ "0x%x hProcessor: 0x%x\tuResourceMask: 0x%x\tpResourceInfo"
++ " 0x%x\tuResourceInfoSixe \n",
++ args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ args->ARGS_PROC_ENUMRESOURCES.pResourceInfo,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceInfoSize);
++ retVal = PROC_GetResourceInfo(args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ WRAP_MAP2CALLER(args->ARGS_PROC_ENUMRESOURCES.
++ pResourceInfo), args->ARGS_PROC_ENUMRESOURCES.
++ uResourceInfoSize);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_GetState ========
++ */
++u32 PROCWRAP_GetState(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_PROCESSORSTATE procStatus;
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetState: entered\n");
++ status = PROC_GetState(args->ARGS_PROC_GETSTATE.hProcessor, &procStatus,
++ args->ARGS_PROC_GETSTATE.uStateInfoSize);
++ cp_to_usr(args->ARGS_PROC_GETSTATE.pProcStatus, &procStatus, status, 1);
++ return status;
++
++}
++
++/*
++ * ======== PROCWRAP_GetTrace ========
++ */
++u32 PROCWRAP_GetTrace(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 *pBuf;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n");
++
++ DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN);
++
++ pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED);
++ if (pBuf != NULL) {
++ status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor,
++ pBuf, args->ARGS_PROC_GETTRACE.uMaxSize);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status,
++ args->ARGS_PROC_GETTRACE.uMaxSize);
++ if (pBuf)
++ MEM_Free(pBuf);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Load ========
++ */
++u32 PROCWRAP_Load(union Trapped_Args *args)
++{
++ s32 i, len;
++ DSP_STATUS status = DSP_SOK;
++ char *temp;
++ s32 argc = args->ARGS_PROC_LOAD.iArgc;
++ u8 **argv, **envp = NULL;
++
++
++ DBC_Require(argc > 0);
++ DBC_Require(argc <= MAX_LOADARGS);
++
++ argv = MEM_Alloc(argc * sizeof(u8 *), MEM_NONPAGED);
++ if (argv == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(argv, args->ARGS_PROC_LOAD.aArgv, status, argc);
++ for (i = 0; DSP_SUCCEEDED(status) && (i < argc); i++) {
++ if (argv[i] != NULL) {
++ /* User space pointer to argument */
++ temp = (char *) argv[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ argv[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (argv[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(argv[i], temp, status, len);
++ }
++ }
++ /* TODO: validate this */
++ if (args->ARGS_PROC_LOAD.aEnvp != NULL) {
++ /* number of elements in the envp array including NULL */
++ len = 0;
++ do {
++ len++;
++ get_user(temp, args->ARGS_PROC_LOAD.aEnvp);
++ } while (temp);
++ envp = MEM_Alloc(len * sizeof(u8 *), MEM_NONPAGED);
++ if (envp == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(envp, args->ARGS_PROC_LOAD.aEnvp, status, len);
++ for (i = 0; DSP_SUCCEEDED(status) && (envp[i] != NULL); i++) {
++ /* User space pointer to argument */
++ temp = (char *)envp[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ envp[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (envp[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(envp[i], temp, status, len);
++ }
++ }
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Load, hProcessor: 0x%x\n\tiArgc:"
++ "0x%x\n\taArgv: 0x%x\n\taArgv[0]: %s\n\taEnvp: 0x%0x\n",
++ args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc, args->ARGS_PROC_LOAD.aArgv,
++ argv[0], args->ARGS_PROC_LOAD.aEnvp);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Load(args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc,
++ (CONST char **)argv, (CONST char **)envp);
++ }
++ if (envp != NULL) {
++ i = 0;
++ while (envp[i] != NULL)
++ MEM_Free(envp[i++]);
++
++ MEM_Free(envp);
++ }
++ if (argv != NULL) {
++ for (i = 0; i < argc; i++) {
++ if (argv[i] != NULL)
++ MEM_Free(argv[i]);
++
++ }
++ MEM_Free(argv);
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Map ========
++ */
++u32 PROCWRAP_Map(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pMapAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Map: entered\n");
++ status = PROC_Map(args->ARGS_PROC_MAPMEM.hProcessor,
++ args->ARGS_PROC_MAPMEM.pMpuAddr,
++ args->ARGS_PROC_MAPMEM.ulSize,
++ args->ARGS_PROC_MAPMEM.pReqAddr, &pMapAddr,
++ args->ARGS_PROC_MAPMEM.ulMapAttr);
++ if (DSP_SUCCEEDED(status)) {
++ if (put_user(pMapAddr, args->ARGS_PROC_MAPMEM.ppMapAddr))
++ status = DSP_EINVALIDARG;
++
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_RegisterNotify ========
++ */
++u32 PROCWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = PROC_RegisterNotify(args->ARGS_PROC_REGISTER_NOTIFY.hProcessor,
++ args->ARGS_PROC_REGISTER_NOTIFY.uEventMask,
++ args->ARGS_PROC_REGISTER_NOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_PROC_REGISTER_NOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_ReserveMemory ========
++ */
++u32 PROCWRAP_ReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pRsvAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
++ status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
++ args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
++ if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr))
++ status = DSP_EINVALIDARG;
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Start ========
++ */
++u32 PROCWRAP_Start(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Start: entered\n");
++ retVal = PROC_Start(args->ARGS_PROC_START.hProcessor);
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_UnMap ========
++ */
++u32 PROCWRAP_UnMap(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_UnMap: entered\n");
++ status = PROC_UnMap(args->ARGS_PROC_UNMAPMEM.hProcessor,
++ args->ARGS_PROC_UNMAPMEM.pMapAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_UnReserveMemory ========
++ */
++u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_UnReserveMemory: entered\n");
++ status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
++ args->ARGS_PROC_UNRSVMEM.pRsvAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Stop ========
++ */
++u32 PROCWRAP_Stop(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Stop: entered\n");
++ retVal = PROC_Stop(args->ARGS_PROC_STOP.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Allocate ========
++ */
++u32 NODEWRAP_Allocate(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs;
++ u8 *pArgs = NULL;
++ struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL;
++ struct NODE_OBJECT *hNode;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status,
++ cbDataSize);
++ }
++ cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1);
++ /* Optional argument */
++ if (args->ARGS_NODE_ALLOCATE.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor,
++ &nodeId, (struct DSP_CBDATA *)pArgs,
++ pAttrIn, &hNode);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1);
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_AllocMsgBuf ========
++ */
++u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ u8 *pBuffer = NULL;
++
++ if (args->ARGS_NODE_ALLOCMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_ALLOCMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ /* IN OUT argument */
++ cp_fm_usr(&pBuffer, args->ARGS_NODE_ALLOCMSGBUF.pBuffer, status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_AllocMsgBuf(args->ARGS_NODE_ALLOCMSGBUF.hNode,
++ args->ARGS_NODE_ALLOCMSGBUF.uSize,
++ pAttr, &pBuffer);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCMSGBUF.pBuffer, &pBuffer, status, 1)
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_ChangePriority ========
++ */
++u32 NODEWRAP_ChangePriority(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_ChangePriority: entered\n");
++ retVal = NODE_ChangePriority(args->ARGS_NODE_CHANGEPRIORITY.hNode,
++ args->ARGS_NODE_CHANGEPRIORITY.iPriority);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Connect ========
++ */
++u32 NODEWRAP_Connect(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_STRMATTR attrs;
++ struct DSP_STRMATTR *pAttrs = NULL;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam;
++ u8 *pArgs = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status,
++ cbDataSize);
++ }
++ if (args->ARGS_NODE_CONNECT.pAttrs) { /* Optional argument */
++ cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrs = &attrs;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode,
++ args->ARGS_NODE_CONNECT.uStream,
++ args->ARGS_NODE_CONNECT.hOtherNode,
++ args->ARGS_NODE_CONNECT.uOtherStream,
++ pAttrs, (struct DSP_CBDATA *)pArgs);
++ }
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Create ========
++ */
++u32 NODEWRAP_Create(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Create: entered\n");
++ retVal = NODE_Create(args->ARGS_NODE_CREATE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Delete ========
++ */
++u32 NODEWRAP_Delete(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Delete: entered\n");
++ retVal = NODE_Delete(args->ARGS_NODE_DELETE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_FreeMsgBuf ========
++ */
++u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ if (args->ARGS_NODE_FREEMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_FREEMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_FreeMsgBuf(args->ARGS_NODE_FREEMSGBUF.hNode,
++ args->ARGS_NODE_FREEMSGBUF.pBuffer,
++ pAttr);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetAttr ========
++ */
++u32 NODEWRAP_GetAttr(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEATTR attr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetAttr: entered\n");
++
++ status = NODE_GetAttr(args->ARGS_NODE_GETATTR.hNode, &attr,
++ args->ARGS_NODE_GETATTR.uAttrSize);
++ cp_to_usr(args->ARGS_NODE_GETATTR.pAttr, &attr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetMessage ========
++ */
++u32 NODEWRAP_GetMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetMessage: entered\n");
++
++ status = NODE_GetMessage(args->ARGS_NODE_GETMESSAGE.hNode, &msg,
++ args->ARGS_NODE_GETMESSAGE.uTimeout);
++
++ cp_to_usr(args->ARGS_NODE_GETMESSAGE.pMessage, &msg, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Pause ========
++ */
++u32 NODEWRAP_Pause(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Pause: entered\n");
++ retVal = NODE_Pause(args->ARGS_NODE_PAUSE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_PutMessage ========
++ */
++u32 NODEWRAP_PutMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_PutMessage: entered\n");
++
++ cp_fm_usr(&msg, args->ARGS_NODE_PUTMESSAGE.pMessage, status, 1);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_PutMessage(args->ARGS_NODE_PUTMESSAGE.hNode, &msg,
++ args->ARGS_NODE_PUTMESSAGE.uTimeout);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_RegisterNotify ========
++ */
++u32 NODEWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = NODE_RegisterNotify(args->ARGS_NODE_REGISTERNOTIFY.hNode,
++ args->ARGS_NODE_REGISTERNOTIFY.uEventMask,
++ args->ARGS_NODE_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_NODE_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Run ========
++ */
++u32 NODEWRAP_Run(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Run: entered\n");
++ retVal = NODE_Run(args->ARGS_NODE_RUN.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Terminate ========
++ */
++u32 NODEWRAP_Terminate(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_STATUS tempstatus;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Terminate: entered\n");
++
++ status = NODE_Terminate(args->ARGS_NODE_TERMINATE.hNode, &tempstatus);
++
++ cp_to_usr(args->ARGS_NODE_TERMINATE.pStatus, &tempstatus, status, 1);
++
++ return status;
++}
++
++
++/*
++ * ======== NODEWRAP_GetUUIDProps ========
++ */
++u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ struct DSP_NDBPROPS *pnodeProps = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_GetUUIDPropste: entered\n");
++
++
++ cp_fm_usr(&nodeId, args->ARGS_NODE_GETUUIDPROPS.pNodeID, status, 1);
++ pnodeProps = MEM_Alloc(sizeof(struct DSP_NDBPROPS), MEM_NONPAGED);
++ if (pnodeProps != NULL) {
++ status = NODE_GetUUIDProps(args->
++ ARGS_NODE_GETUUIDPROPS.hProcessor,
++ &nodeId, pnodeProps);
++ cp_to_usr(args->ARGS_NODE_GETUUIDPROPS.pNodeProps, pnodeProps,
++ status, 1);
++ } else
++ status = DSP_EMEMORY;
++ if (pnodeProps)
++ MEM_Free(pnodeProps);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_AllocateBuffer ========
++ */
++u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_ALLOCATEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ status = STRM_AllocateBuffer(args->ARGS_STRM_ALLOCATEBUFFER.hStream,
++ args->ARGS_STRM_ALLOCATEBUFFER.uSize,
++ apBuffer, uNumBufs);
++ cp_to_usr(args->ARGS_STRM_ALLOCATEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Close ========
++ */
++u32 STRMWRAP_Close(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Close(args->ARGS_STRM_CLOSE.hStream);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_FreeBuffer ========
++ */
++u32 STRMWRAP_FreeBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_FREEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ cp_fm_usr(apBuffer, args->ARGS_STRM_FREEBUFFER.apBuffer, status,
++ uNumBufs);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_FreeBuffer(args->ARGS_STRM_FREEBUFFER.hStream,
++ apBuffer, uNumBufs);
++ }
++ cp_to_usr(args->ARGS_STRM_FREEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_GetEventHandle ========
++ */
++u32 STRMWRAP_GetEventHandle(union Trapped_Args *args)
++{
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== STRMWRAP_GetInfo ========
++ */
++u32 STRMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_INFO strmInfo;
++ struct DSP_STREAMINFO user;
++ struct DSP_STREAMINFO *temp;
++
++ cp_fm_usr(&strmInfo, args->ARGS_STRM_GETINFO.pStreamInfo, status, 1);
++ temp = strmInfo.pUser;
++
++ strmInfo.pUser = &user;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_GetInfo(args->ARGS_STRM_GETINFO.hStream,
++ &strmInfo, args->ARGS_STRM_GETINFO.uStreamInfoSize);
++ }
++ cp_to_usr(temp, strmInfo.pUser, status, 1);
++ strmInfo.pUser = temp;
++ cp_to_usr(args->ARGS_STRM_GETINFO.pStreamInfo, &strmInfo, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Idle ========
++ */
++u32 STRMWRAP_Idle(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Idle(args->ARGS_STRM_IDLE.hStream,
++ args->ARGS_STRM_IDLE.bFlush);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Issue ========
++ */
++u32 STRMWRAP_Issue(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Issue(args->ARGS_STRM_ISSUE.hStream,
++ args->ARGS_STRM_ISSUE.pBuffer,
++ args->ARGS_STRM_ISSUE.dwBytes,
++ args->ARGS_STRM_ISSUE.dwBufSize,
++ args->ARGS_STRM_ISSUE.dwArg);
++
++ /* This is a user space pointer */
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Open ========
++ */
++u32 STRMWRAP_Open(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_ATTR attr;
++ struct STRM_OBJECT *pStrm;
++ struct DSP_STREAMATTRIN strmAttrIn;
++
++ cp_fm_usr(&attr, args->ARGS_STRM_OPEN.pAttrIn, status, 1);
++
++ if (attr.pStreamAttrIn != NULL) { /* Optional argument */
++ cp_fm_usr(&strmAttrIn, attr.pStreamAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ attr.pStreamAttrIn = &strmAttrIn;
++
++ }
++ status = STRM_Open(args->ARGS_STRM_OPEN.hNode,
++ args->ARGS_STRM_OPEN.uDirection,
++ args->ARGS_STRM_OPEN.uIndex, &attr, &pStrm);
++ cp_to_usr(args->ARGS_STRM_OPEN.phStream, &pStrm, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Reclaim ========
++ */
++u32 STRMWRAP_Reclaim(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ u32 ulBufSize;
++
++ status = STRM_Reclaim(args->ARGS_STRM_RECLAIM.hStream, &pBufPtr,
++ &ulBytes, &ulBufSize, &dwArg);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufPtr, &pBufPtr, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBytes, &ulBytes, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pdwArg, &dwArg, status, 1);
++
++ if (args->ARGS_STRM_RECLAIM.pBufSize != NULL) {
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufSize, &ulBufSize,
++ status, 1);
++ }
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_RegisterNotify ========
++ */
++u32 STRMWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = STRM_RegisterNotify(args->ARGS_STRM_REGISTERNOTIFY.hStream,
++ args->ARGS_STRM_REGISTERNOTIFY.uEventMask,
++ args->ARGS_STRM_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_STRM_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Select ========
++ */
++u32 STRMWRAP_Select(union Trapped_Args *args)
++{
++ u32 mask;
++ struct STRM_OBJECT *aStrmTab[MAX_STREAMS];
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(args->ARGS_STRM_SELECT.nStreams <= MAX_STREAMS);
++
++ cp_fm_usr(aStrmTab, args->ARGS_STRM_SELECT.aStreamTab, status,
++ args->ARGS_STRM_SELECT.nStreams);
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_Select(aStrmTab, args->ARGS_STRM_SELECT.nStreams,
++ &mask, args->ARGS_STRM_SELECT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_STRM_SELECT.pMask, &mask, status, 1);
++ return status;
++}
++
++/* CMM */
++
++/*
++ * ======== CMMWRAP_CallocBuf ========
++ */
++u32 CMMWRAP_CallocBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_FreeBuf ========
++ */
++u32 CMMWRAP_FreeBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_GetHandle ========
++ */
++u32 CMMWRAP_GetHandle(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr;
++
++ status = CMM_GetHandle(args->ARGS_CMM_GETHANDLE.hProcessor, &hCmmMgr);
++
++ cp_to_usr(args->ARGS_CMM_GETHANDLE.phCmmMgr, &hCmmMgr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== CMMWRAP_GetInfo ========
++ */
++u32 CMMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_INFO cmmInfo;
++
++ status = CMM_GetInfo(args->ARGS_CMM_GETINFO.hCmmMgr, &cmmInfo);
++
++ cp_to_usr(args->ARGS_CMM_GETINFO.pCmmInfo, &cmmInfo, status, 1);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
+new file mode 100644
+index 0000000..c5ec8f9
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dbdcd.c
+@@ -0,0 +1,1573 @@
++/*
++ * dbdcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcd.c ========
++ * Description:
++ * This file contains the implementation of the DSP/BIOS Bridge
++ * Configuration Database (DCD).
++ *
++ * Notes:
++ * The fxn DCD_GetObjects can apply a callback fxn to each DCD object
++ * that is located in a specified COFF file. At the moment,
++ * DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
++ * DCD_GetObjects.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
++ *! to include phase information
++ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
++ *! libraries
++ *! 26-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
++ *! data. Added DCD_GetLibraryName().
++ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
++ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
++ *! DSP-MMU setup. These are private attributes.
++ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
++ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
++ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
++ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
++ *! GetAttrsFromBuf
++ *! 22-Nov-2000 kc: Replaced sprintf() calls with strncat.
++ *! 09-Nov-2000 kc: Optimized DCD module.
++ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
++ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
++ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
++ *! to replace atoi(), until cdb generation can output in
++ *! decimal format.
++ *! 26-Jul-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/uuidutil.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbdcd.h>
++
++/* ----------------------------------- Global defines. */
++#define SIGNATURE 0x5f444344 /* "DCD_" (in reverse). */
++
++#define IsValidHandle(h) (((h) != NULL) && (h->dwSignature == SIGNATURE))
++
++#define MAX_INT2CHAR_LENGTH 16 /* Maximum int2char len of 32 bit int. */
++
++/* Name of section containing dependent libraries */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* DCD specific structures. */
++struct DCD_MANAGER {
++ u32 dwSignature; /* Used for object validation. */
++ struct COD_MANAGER *hCodMgr; /* Handle to COD manager object. */
++};
++
++/* Global reference variables. */
++static u32 cRefs;
++static u32 cEnumRefs;
++
++extern struct GT_Mask curTrace;
++
++/* helper function prototypes. */
++static s32 Atoi(char *pszBuf);
++
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj);
++
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
++
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
++
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * Parses the supplied image and resigsters with DCD.
++ */
++
++DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ (void *)pszCoffPath);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * Parses the supplied DSP image and unresiters from DCD.
++ */
++DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ NULL);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoUnregister: invalid DCD manager"
++ " handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * Creates DCD manager.
++ */
++DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager handle */
++ struct DCD_MANAGER *pDcdMgr = NULL; /* DCD Manager pointer */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(phDcdMgr);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
++ phDcdMgr);
++
++ status = COD_Create(&hCodMgr, pszZlDllName, NULL);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* Create a DCD object. */
++ MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
++ if (pDcdMgr != NULL) {
++
++ /* Fill out the object. */
++ pDcdMgr->hCodMgr = hCodMgr;
++
++ /* Return handle to this DCD interface. */
++ *phDcdMgr = pDcdMgr;
++
++ GT_2trace(curTrace, GT_5CLASS,
++ "DCD_CreateManager: pDcdMgr 0x%x, "
++ " hCodMgr 0x%x", pDcdMgr, hCodMgr);
++ } else {
++ status = DSP_EMEMORY;
++
++ /*
++ * If allocation of DcdManager object failed, delete the
++ * COD manager.
++ */
++ COD_Delete(hCodMgr);
++
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: MEM_AllocObject failed\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: COD_Create failed\n");
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
++ (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
++ (status == DSP_EMEMORY)));
++
++ return status;
++}
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * Frees DCD Manager object.
++ */
++DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr;
++ DSP_STATUS status = DSP_EHANDLE;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++
++ /* Delete the COD manager. */
++ COD_Delete(pDcdMgr->hCodMgr);
++
++ /* Deallocate a DCD manager object. */
++ MEM_FreeObject(pDcdMgr);
++
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_DestroyManager: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * Enumerates objects in the DCD.
++ */
++DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szValue[REG_MAXREGPATHLENGTH];
++ char szData[REG_MAXREGPATHLENGTH];
++ u32 dwValueSize;
++ u32 dwDataSize;
++ struct DSP_UUID dspUuid;
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ u32 dwKeyLen = 0;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(cIndex >= 0);
++ DBC_Require(pUuid != NULL);
++
++ GT_3trace(curTrace, GT_ENTER,
++ "DCD_EnumerateObject: cIndex %d, objType %d, "
++ " pUuid 0x%x\n", cIndex, objType, pUuid);
++
++ if ((cIndex != 0) && (cEnumRefs == 0)) {
++ /*
++ * If an enumeration is being performed on an index greater
++ * than zero, then the current cEnumRefs must have been
++ * incremented to greater than zero.
++ */
++ status = DSP_ECHANGEDURINGENUM;
++ } else {
++ /* Enumerate a specific key in the registry by index. */
++ dwValueSize = REG_MAXREGPATHLENGTH;
++ dwDataSize = REG_MAXREGPATHLENGTH;
++
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++
++ /* Create proper REG key; concatenate DCD_REGKEY with
++ * objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++
++ /* This snprintf is guaranteed not to exceed max size of an
++ * integer. */
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
++ objType);
++
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType,
++ strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
++ &dwValueSize, szData,
++ &dwDataSize);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create UUID value using string retrieved from
++ * registry. */
++ UUID_UuidFromString(szValue, &dspUuid);
++
++ *pUuid = dspUuid;
++
++ /* Increment cEnumRefs to update reference count. */
++ cEnumRefs++;
++
++ status = DSP_SOK;
++ } else if (status == REG_E_NOMOREITEMS) {
++ /* At the end of enumeration. Reset cEnumRefs. */
++ cEnumRefs = 0;
++
++ status = DSP_SENUMCOMPLETE;
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(curTrace, GT_6CLASS,
++ "DCD_EnumerateObject: REG_EnumValue"
++ " failed, status = 0x%x\n", status);
++ }
++ }
++
++ DBC_Ensure(pUuid || (status == DSP_EFAIL));
++
++ return status;
++}
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * Discontinue usage of the DCD module.
++ */
++void DCD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ REG_Exit();
++ COD_Exit();
++ MEM_Exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DCD_GetDepLibs ========
++ */
++DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pDepLibUuids != NULL);
++ DBC_Require(pPersistentDepLibs != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
++ pPersistentDepLibs, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ */
++DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pNumPersLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
++ NULL, NULL, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * Retrieves the properties of a node or processor based on the UUID and
++ * object type.
++ */
++DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ struct COD_LIBRARYOBJ *lib = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwBufSize; /* Used by REG functions */
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char *szUuid; /*[MAXUUIDLEN];*/
++ char szRegData[REG_MAXREGPATHLENGTH];
++ char szSectName[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
++ char *pszCoffBuf;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pObjDef != NULL);
++ DBC_Require(pObjUuid != NULL);
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
++ " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
++ objType, pObjDef);
++ szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
++ if (!szUuid)
++ return status = DSP_EMEMORY;
++
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
++ "DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
++
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ /* Retrieve paths from the registry based on struct DSP_UUID */
++ dwBufSize = REG_MAXREGPATHLENGTH;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
++ &dwBufSize);
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EUUID;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "REG_GetValue() failed\n");
++ goto func_end;
++ }
++ /* Open COFF file. */
++ status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_OpenBase() failed\n");
++ goto func_end;
++ }
++ /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
++ DBC_Assert((strlen(szUuid) + 1) < sizeof(szSectName));
++ /* Create section name based on node UUID. A period is
++ * pre-pended to the UUID string to form the section name.
++ * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
++ strncpy(szSectName, ".", 2);
++ strncat(szSectName, szUuid, strlen(szUuid));
++ /* Get section information. */
++ status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDGETSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
++ " COD_GetSection() failed\n");
++ goto func_end;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(szRegData, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ } else {
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ GT_0trace(curTrace, GT_4CLASS,
++ "Skipped Byte swap for IVA !!\n");
++ }
++#else
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compres DSP buffer to conform to PC format. */
++ if (strstr(szRegData, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
++ "COFF buffer by 1 for IVA !!\n");
++ }
++ /* Parse the content of the COFF buffer. */
++ status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDPARSESECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "GetAttrsFromBuf() failed\n");
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_end:
++ if (lib)
++ COD_Close(lib);
++
++ if (szUuid)
++ MEM_Free(szUuid);
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjects ========
++ */
++DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn, void *handle)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ DSP_STATUS status = DSP_SOK;
++ char *pszCoffBuf;
++ char *pszCur;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ char seps[] = ":, ";
++ char *pToken = NULL;
++ struct DSP_UUID dspUuid;
++ s32 cObjectType;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER,
++ "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: invalid DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Open DSP coff file, don't load symbols. */
++ status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: COD_Open() failed\n");
++ goto func_cont;
++ }
++ /* Get DCD_RESIGER_SECTION section information. */
++ status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
++ if (DSP_FAILED(status) || !(ulLen > 0)) {
++ status = DSP_EDCDNOAUTOREGISTER;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: COD_GetSection() "
++ "- no auto register section\n");
++ goto func_cont;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ }
++#else
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compress DSP buffer to conform to PC format. */
++ GT_0trace(curTrace, GT_4CLASS,
++ "Successfully read section !!\n");
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
++ "with 1 word for IVA !!\n");
++ }
++ /* Read from buffer and register object in buffer. */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken, &dspUuid);
++ /* Retrieve object type */
++ pToken = strsep(&pszCur, seps);
++ /* Retrieve object type */
++ cObjectType = Atoi(pToken);
++ /*
++ * Apply registerFxn to the found DCD object.
++ * Possible actions include:
++ *
++ * 1) Register found DCD object.
++ * 2) Unregister found DCD object (when handle == NULL)
++ * 3) Add overlay node.
++ */
++ GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
++ "%d \n", cObjectType);
++ status = registerFxn(&dspUuid, cObjectType, handle);
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "DCD_GetObjects: status 0x%x\n",
++ status);
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: "
++ "registration() failed\n");
++ /* if error occurs, break from while loop. */
++ break;
++ }
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * Retrieves the library name for the given UUID.
++ *
++ */
++DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
++ enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
++{
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN];
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pstrLibName != NULL);
++ DBC_Require(pdwSize != NULL);
++ DBC_Require(IsValidHandle(hDcdMgr));
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
++ " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
++ pstrLibName, pdwSize);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ switch (phase) {
++ case NLDR_CREATE:
++ /* create phase type */
++ sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
++ break;
++ case NLDR_EXECUTE:
++ /* execute phase type */
++ sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
++ break;
++ case NLDR_DELETE:
++ /* delete phase type */
++ sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
++ break;
++ case NLDR_NOPHASE:
++ /* known to be a dependent library */
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ break;
++ default:
++ status = -1;
++ DBC_Assert(false);
++ }
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to find match in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Retrieve path from the registry based on DSP_UUID */
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++ /* If can't find, phases might be registered as generic LIBRARYTYPE */
++ if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
++ if (fPhaseSplit)
++ *fPhaseSplit = false;
++
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * Initialize the DCD module.
++ */
++bool DCD_Init(void)
++{
++ bool fInitMEM;
++ bool fInitREG;
++ bool fInitCOD;
++ bool fInit = true;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++
++ /* Initialize required modules. */
++ fInitMEM = MEM_Init();
++ fInitCOD = COD_Init();
++ fInitREG = REG_Init();
++ if (!fInitMEM || !fInitCOD || !fInitREG) {
++ fInit = false;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
++ /* Exit initialized modules. */
++ if (fInitMEM)
++ MEM_Exit();
++
++ if (fInitCOD)
++ COD_Exit();
++
++ if (fInitREG)
++ REG_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
++
++ return fInit;
++}
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * Registers a node or a processor with the DCD.
++ * If pszPathName == NULL, unregister the specified DCD object.
++ */
++DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN + 1];
++ u32 dwPathSize = 0;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
++ "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * If pszPathName != NULL, perform registration, otherwise,
++ * perform unregistration.
++ */
++ if (pszPathName) {
++ /* Add new reg value (UUID+objType) with COFF path
++ * info. */
++ dwPathSize = strlen(pszPathName) + 1;
++ status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
++ (u8 *)pszPathName, dwPathSize);
++ GT_3trace(curTrace, GT_6CLASS,
++ "REG_SetValue REG_SZ=%d, "
++ "(u8 *)pszPathName=%s, dwPathSize=%d\n",
++ REG_SZ, pszPathName, dwPathSize);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_RegisterObject: REG_SetValue failed!\n");
++ }
++ } else {
++ /* Deregister an existing object. */
++ status = REG_DeleteValue(NULL, szRegKey, szRegKey);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_UnregisterObject: "
++ "REG_DeleteValue failed!\n");
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Because the node database has been updated through a
++ * successful object registration/de-registration operation,
++ * we need to reset the object enumeration counter to allow
++ * current enumerations to reflect this update in the node
++ * database.
++ */
++
++ cEnumRefs = 0;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Call DCD_Register object with pszPathName set to NULL to
++ * perform actual object de-registration.
++ */
++DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "DCD_UnregisterObject: object UUID 0x%x, "
++ "objType %d\n", pUuid, objType);
++
++ /*
++ * When DCD_RegisterObject is called with NULL as pathname,
++ * it indicates an unregister object operation.
++ */
++ status = DCD_RegisterObject(pUuid, objType, NULL);
++
++ return status;
++}
++
++/*
++ **********************************************************************
++ * DCD Helper Functions
++ **********************************************************************
++ */
++
++/*
++ * ======== Atoi ========
++ * Purpose:
++ * This function converts strings in decimal or hex format to integers.
++ */
++static s32 Atoi(char *pszBuf)
++{
++ s32 result = 0;
++ char *pch = pszBuf;
++ char c;
++ char first;
++ s32 base = 10;
++ s32 len;
++
++ while (isspace(*pch))
++ pch++;
++
++ first = *pch;
++ if (first == '-' || first == '+') {
++ pch++;
++ } else {
++ /* Determine if base 10 or base 16 */
++ len = strlen(pch);
++ if (len > 1) {
++ c = pch[1];
++ if ((*pch == '0' && (c == 'x' || c == 'X'))) {
++ base = 16;
++ pch += 2;
++ }
++ c = pch[len - 1];
++ if (c == 'h' || c == 'H')
++ base = 16;
++
++ }
++ }
++
++ while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
++ result *= base;
++ if ('A' <= c && c <= 'F') {
++ c = c - 'A' + 10;
++ } else {
++ if ('a' <= c && c <= 'f')
++ c = c - 'a' + 10;
++ else
++ c -= '0';
++
++ }
++ result += c;
++ ++pch;
++ }
++
++ return result;
++}
++
++/*
++ * ======== GetAttrsFromBuf ========
++ * Purpose:
++ * Parse the content of a buffer filled with DSP-side data and
++ * retrieve an object's attributes from it. IMPORTANT: Assume the
++ * buffer has been converted from DSP format to GPP format.
++ */
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ char seps[] = ", ";
++ char *pszCur;
++ char *token;
++ s32 cLen = 0;
++ u32 i = 0;
++#ifdef _DB_TIOMAP
++ s32 iEntry;
++#endif
++
++ DBC_Require(pszBuf != NULL);
++ DBC_Require(ulBufSize != 0);
++ DBC_Require((objType == DSP_DCDNODETYPE)
++ || (objType == DSP_DCDPROCESSORTYPE));
++ DBC_Require(pGenObj != NULL);
++
++
++ switch (objType) {
++ case DSP_DCDNODETYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ /* u32 cbStruct */
++ pGenObj->objData.nodeObj.ndbProps.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* DSP_UUID uiNodeID */
++ UUID_UuidFromString(token,
++ &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
++ token = strsep(&pszCur, seps);
++
++ /* acName */
++ DBC_Require(token);
++ cLen = strlen(token);
++ if (cLen > DSP_MAXNAMELEN - 1)
++ cLen = DSP_MAXNAMELEN - 1;
++
++ strncpy(pGenObj->objData.nodeObj.ndbProps.acName,
++ token, cLen);
++ pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ /* u32 uNodeType */
++ pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* u32 bCacheOnGPP */
++ pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* DSP_RESOURCEREQMTS dspResourceReqmts */
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uStaticDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uGlobalDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uProgramMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCExecutionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCDeadline = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uAvgExectionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uMinimumPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* s32 iPriority */
++ pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uSysStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSeg */
++ pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uMessageDepth */
++ pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumInputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumOutputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uTimeout */
++ pGenObj->objData.nodeObj.ndbProps.uTimeout =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrCreatePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrExecutePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrDeletePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* Segment id for message buffers */
++ pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* Message notification type */
++ pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrIAlgName */
++ if (token) {
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrIAlgName =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Load type (static, dynamic, or overlay) */
++ if (token) {
++ pGenObj->objData.nodeObj.usLoadType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load data requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load code requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Extract node profiles into node properties */
++ if (token) {
++
++ pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
++ Atoi(token);
++ for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
++ uCountProfiles; i++) {
++ token = strsep(&pszCur, seps);
++ if (token) {
++ /* Heap Size for the node */
++ pGenObj->objData.nodeObj.ndbProps.
++ aProfiles[i].ulHeapSize =
++ Atoi(token);
++ }
++ }
++ }
++ token = strsep(&pszCur, seps);
++ if (token) {
++ pGenObj->objData.nodeObj.ndbProps.uStackSegName =
++ (u32)(token);
++ }
++
++ break;
++
++ case DSP_DCDPROCESSORTYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.cbStruct = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uClockRate = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorID = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
++
++#ifdef _DB_TIOMAP
++ /* Proc object may contain additional(extended) attributes. */
++ /* attr must match proc.hxx */
++ for (iEntry = 0; iEntry < 7; iEntry++) {
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
++ Atoi(token);
++
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
++ Atoi(token);
++ }
++#endif
++
++ break;
++
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CompressBuffer ========
++ * Purpose:
++ * Compress the DSP buffer, if necessary, to conform to PC format.
++ */
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
++{
++ char *p;
++ char ch;
++ char *q;
++
++ p = pszBuf;
++ if (p == NULL)
++ return;
++
++ for (q = pszBuf; q < (pszBuf + ulBufSize);) {
++
++ ch = DspChar2GppChar(q, cCharSize);
++ if (ch == '\\') {
++ q += cCharSize;
++ ch = DspChar2GppChar(q, cCharSize);
++ switch (ch) {
++ case 't':
++ *p = '\t';
++ break;
++
++ case 'n':
++ *p = '\n';
++ break;
++
++ case 'r':
++ *p = '\r';
++ break;
++
++ case '0':
++ *p = '\0';
++ break;
++
++ default:
++ *p = ch;
++ break;
++ }
++ } else {
++ *p = ch;
++ }
++ p++;
++ q += cCharSize;
++ }
++
++ /* NULL out remainder of buffer. */
++ while (p < q)
++ *p++ = '\0';
++
++}
++
++/*
++ * ======== DspChar2GppChar ========
++ * Purpose:
++ * Convert DSP char to host GPP char in a portable manner
++ */
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
++{
++ char ch = '\0';
++ char *chSrc;
++ s32 i;
++
++ for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
++ ch |= *chSrc++;
++
++ return ch;
++}
++
++/*
++ * ======== GetDepLibInfo ========
++ */
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ enum NLDR_PHASE phase)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ char *pszCoffBuf = NULL;
++ char *pszCur;
++ char *pszFileName = NULL;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwDataSize = COD_MAXPATHLENGTH;
++ char seps[] = ", ";
++ char *pToken = NULL;
++ bool fGetUuids = (pDepLibUuids != NULL);
++ u16 nDepLibs = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ /* Initialize to 0 dependent libraries, if only counting number of
++ * dependent libraries */
++ if (!fGetUuids) {
++ *pNumLibs = 0;
++ *pNumPersLibs = 0;
++ }
++
++ /* Allocate a buffer for file name */
++ pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
++ if (pszFileName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Get the name of the library */
++ status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
++ &dwDataSize, phase, NULL);
++ }
++ /* Open the library */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
++ COD_NOLOAD, &lib);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get dependent library section information. */
++ status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
++
++ if (DSP_FAILED(status)) {
++ /* Ok, no dependent libraries */
++ ulLen = 0;
++ status = DSP_SNODEPENDENTLIBS;
++ }
++ }
++
++ if (DSP_FAILED(status) || !(ulLen > 0))
++ goto func_cont;
++
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
++ if (pszCoffBuf == NULL)
++ status = DSP_EMEMORY;
++
++ /* Read section contents. */
++ status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Compress and format DSP buffer to conform to PC format. */
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ /* Read from buffer */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ if (fGetUuids) {
++ if (nDepLibs >= *pNumLibs) {
++ /* Gone beyond the limit */
++ break;
++ } else {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken,
++ &(pDepLibUuids[nDepLibs]));
++ /* Is this library persistent? */
++ pToken = strsep(&pszCur, seps);
++ pPersistentDepLibs[nDepLibs] = Atoi(pToken);
++ nDepLibs++;
++ }
++ } else {
++ /* Advanc to next token */
++ pToken = strsep(&pszCur, seps);
++ if (Atoi(pToken))
++ (*pNumPersLibs)++;
++
++ /* Just counting number of dependent libraries */
++ (*pNumLibs)++;
++ }
++ }
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++ /* Free previously allocated dynamic buffers. */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
+new file mode 100644
+index 0000000..3fbbf01
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/disp.c
+@@ -0,0 +1,916 @@
++/*
++ * disp.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.c ========
++ *
++ * Description:
++ * Node Dispatcher interface. Communicates with Resource Manager Server
++ * (RMS) on DSP. Access to RMS is synchronized in NODE.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodePause
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 16-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 13-Feb-2002 jeh Pass system stack size to RMS.
++ *! 16-Jan-2002 ag Added bufsize param to _ChnlAddIOReq() fxn
++ *! 10-May-2001 jeh Code Review cleanup.
++ *! 26-Sep-2000 jeh Fixed status values in SendMessage().
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dev.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/chnldefs.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/disp.h>
++
++#define DISP_SIGNATURE 0x50534944 /* "PSID" */
++
++/* Size of a reply from RMS */
++#define REPLYSIZE (3 * sizeof(RMS_WORD))
++
++/* Reserved channel offsets for communication with RMS */
++#define CHNLTORMSOFFSET 0
++#define CHNLFROMRMSOFFSET 1
++
++#define CHNLIOREQS 1
++
++#define SwapWord(x) (((u32)(x) >> 16) | ((u32)(x) << 16))
++
++/*
++ * ======== DISP_OBJECT ========
++ */
++struct DISP_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device for this processor */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct CHNL_OBJECT *hChnlToDsp; /* Channel for commands to RMS */
++ struct CHNL_OBJECT *hChnlFromDsp; /* Channel for replies from RMS */
++ u8 *pBuf; /* Buffer for commands, replies */
++ u32 ulBufsize; /* pBuf size in bytes */
++ u32 ulBufsizeRMS; /* pBuf size in RMS words */
++ u32 uCharSize; /* Size of DSP character */
++ u32 uWordSize; /* Size of DSP word */
++ u32 uDataMauSize; /* Size of DSP Data MAU */
++};
++
++static u32 cRefs;
++
++/* Debug msgs: */
++#if GT_TRACE
++static struct GT_Mask DISP_DebugMask = { NULL, NULL };
++#endif
++
++static void DeleteDisp(struct DISP_OBJECT *hDisp);
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord);
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, OUT u32 *pdwArg);
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object.
++ */
++DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs)
++{
++ struct DISP_OBJECT *pDisp;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDispObject != NULL);
++ DBC_Require(pDispAttrs != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
++ "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
++ hDevObject, pDispAttrs);
++
++ *phDispObject = NULL;
++
++ /* Allocate Node Dispatcher object */
++ MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
++ if (pDisp == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: MEM_AllocObject() failed!\n");
++ } else {
++ pDisp->hDevObject = hDevObject;
++ }
++
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ pDisp->pIntfFxns = pIntfFxns;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed to get "
++ "channel manager! status = 0x%x\n", status);
++ }
++ }
++
++ /* check device type and decide if streams or messag'ing is used for
++ * RMS/EDS */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = DEV_GetDevType(hDevObject, &devType);
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
++ "device = 0x%x\n", devType);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if (devType != DSP_UNIT) {
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Unkown device "
++ "type in Device object !! \n");
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDisp->uCharSize = DSPWORDSIZE;
++ pDisp->uWordSize = DSPWORDSIZE;
++ pDisp->uDataMauSize = DSPWORDSIZE;
++ /* Open channels for communicating with the RMS */
++ chnlAttrs.uIOReqs = CHNLIOREQS;
++ chnlAttrs.hEvent = NULL;
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
++ pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel to RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
++ pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
++ &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel from RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate buffer for commands, replies */
++ pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
++ pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
++ pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
++ if (pDisp->pBuf == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed "
++ "to allocate channel buffer!\n");
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status))
++ *phDispObject = pDisp;
++ else
++ DeleteDisp(pDisp);
++
++ DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
++ ((DSP_SUCCEEDED(status)) &&
++ (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
++ return status;
++}
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ */
++void DISP_Delete(struct DISP_OBJECT *hDisp)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++
++ GT_1trace(DISP_DebugMask, GT_ENTER,
++ "DISP_Delete: hDisp: 0x%x\n", hDisp);
++
++ DeleteDisp(hDisp);
++
++ DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++}
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ */
++void DISP_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "Entered DISP_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ */
++bool DISP_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DISP_DebugMask.flags);
++ GT_create(&DISP_DebugMask, "DI"); /* "DI" for DIspatcher */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "DISP_Init(), ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ */
++DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
++ struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, NODE_ENV nodeEnv,
++ s32 nPriority)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
++ "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
++ hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
++
++ /* Send message to RMS to change priority */
++ pCommand = (struct RMS_Command *)(hDisp->pBuf);
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = nPriority;
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeChangePriority failed! "
++ "status = 0x%x\n", status);
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS *pArgs,
++ OUT NODE_ENV *pNodeEnv)
++{
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ struct RMS_Command *pCommand;
++ struct RMS_MsgArgs *pMsgArgs;
++ struct RMS_MoreTaskArgs *pMoreTaskArgs;
++ enum NODE_TYPE nodeType;
++ u32 dwLength;
++ RMS_WORD *pdwBuf = NULL;
++ u32 ulBytes;
++ u32 i;
++ u32 total;
++ u32 uCharsInRMSWord;
++ s32 taskArgsOffset;
++ s32 sioInDefOffset;
++ s32 sioOutDefOffset;
++ s32 sioDefsOffset;
++ s32 argsOffset = -1;
++ s32 offset;
++ struct NODE_STRMDEF strmDef;
++ u32 max;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEINFO nodeInfo;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++ DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
++ DBC_Require(pNodeEnv != NULL);
++
++ GT_6trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeCreate: hDisp: 0x%x\thNode:"
++ " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
++ " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
++ "for device = 0x%x\n", devType);
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (devType != DSP_UNIT) {
++ GT_1trace(DISP_DebugMask, GT_7CLASS,
++ "DISP_NodeCreate unknown device "
++ "type = 0x%x\n", devType);
++ goto func_end;
++ }
++ DBC_Require(pArgs != NULL);
++ nodeType = NODE_GetType(hNode);
++ msgArgs = pArgs->asa.msgArgs;
++ max = hDisp->ulBufsizeRMS; /*Max # of RMS words that can be sent */
++ DBC_Assert(max == RMS_COMMANDBUFSIZE);
++ uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
++ /* Number of RMS words needed to hold arg data */
++ dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++ /* Make sure msg args and command fit in buffer */
++ total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
++ sizeof(struct RMS_MsgArgs)
++ / sizeof(RMS_WORD) - 1 + dwLength;
++ if (total >= max) {
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args too"
++ " large for buffer! Message args size = %d, max = %d\n",
++ total, max);
++ }
++ /*
++ * Fill in buffer to send to RMS.
++ * The buffer will have the following format:
++ *
++ * RMS command:
++ * Address of RMS_CreateNode()
++ * Address of node's create function
++ * dummy argument
++ * node type
++ *
++ * Message Args:
++ * max number of messages
++ * segid for message buffer allocation
++ * notification type to use when message is received
++ * length of message arg data
++ * message args data
++ *
++ * Task Args (if task or socket node):
++ * priority
++ * stack size
++ * system stack size
++ * stack segment
++ * misc
++ * number of input streams
++ * pSTRMInDef[] - offsets of STRM definitions for input streams
++ * number of output streams
++ * pSTRMOutDef[] - offsets of STRM definitions for output
++ * streams
++ * STRMInDef[] - array of STRM definitions for input streams
++ * STRMOutDef[] - array of STRM definitions for output streams
++ *
++ * Socket Args (if DAIS socket node):
++ *
++ */
++ if (DSP_SUCCEEDED(status)) {
++ total = 0; /* Total number of words in buffer so far */
++ pdwBuf = (RMS_WORD *)hDisp->pBuf;
++ pCommand = (struct RMS_Command *)pdwBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
++ if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
++ /* Flush ICACHE on Load */
++ pCommand->arg2 = 1; /* dummy argument */
++ } else {
++ /* Do not flush ICACHE */
++ pCommand->arg2 = 0; /* dummy argument */
++ }
++ pCommand->data = NODE_GetType(hNode);
++ /*
++ * argsOffset is the offset of the data field in struct
++ * RMS_Command structure. We need this to calculate stream
++ * definition offsets.
++ */
++ argsOffset = 3;
++ total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
++ /* Message args */
++ pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
++ pMsgArgs->maxMessages = msgArgs.uMaxMessages;
++ pMsgArgs->segid = msgArgs.uSegid;
++ pMsgArgs->notifyType = msgArgs.uNotifyType;
++ pMsgArgs->argLength = msgArgs.uArgLength;
++ total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
++ memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
++ total += dwLength;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If node is a task node, copy task create arguments into buffer */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ taskArgs = pArgs->asa.taskArgs;
++ taskArgsOffset = total;
++ total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
++ 1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
++ /* Copy task arguments */
++ if (total < max) {
++ total = taskArgsOffset;
++ pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
++ total);
++ /*
++ * Get some important info about the node. Note that we
++ * don't just reach into the hNode struct because
++ * that would break the node object's abstraction.
++ */
++ GetNodeInfo(hNode, &nodeInfo);
++ GT_2trace(DISP_DebugMask, GT_ENTER,
++ "uExecutionPriority %x, nPriority %x\n",
++ nodeInfo.uExecutionPriority,
++ taskArgs.nPriority);
++ pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
++ pMoreTaskArgs->stackSize = taskArgs.uStackSize;
++ pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
++ pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
++ pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
++ pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
++ pMoreTaskArgs->misc = taskArgs.ulDaisArg;
++ pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
++ total +=
++ sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
++ GT_2trace(DISP_DebugMask, GT_7CLASS,
++ "DISP::::uDSPHeapAddr %x, "
++ "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
++ taskArgs.uHeapSize);
++ /* Keep track of pSIOInDef[] and pSIOOutDef[]
++ * positions in the buffer, since this needs to be
++ * filled in later. */
++ sioInDefOffset = total;
++ total += taskArgs.uNumInputs;
++ pdwBuf[total++] = taskArgs.uNumOutputs;
++ sioOutDefOffset = total;
++ total += taskArgs.uNumOutputs;
++ sioDefsOffset = total;
++ /* Fill SIO defs and offsets */
++ offset = sioDefsOffset;
++ for (i = 0; i < taskArgs.uNumInputs; i++) {
++ if (DSP_FAILED(status))
++ break;
++
++ pdwBuf[sioInDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmInDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ for (i = 0; (i < taskArgs.uNumOutputs) &&
++ (DSP_SUCCEEDED(status)); i++) {
++ pdwBuf[sioOutDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmOutDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message"
++ " args to large for buffer! Message args"
++ " size = %d, max = %d\n", total, max);
++ }
++ } else {
++ /* Args won't fit */
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args "
++ " too large for buffer! Message args size = %d"
++ ", max = %d\n", total, max);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulBytes = total * sizeof(RMS_WORD);
++ DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ ulBytes, pNodeEnv);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate failed! "
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's create function
++ * on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate, "
++ "DSP-side Node Create failed: 0x%x\n",
++ status);
++ }
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== DISP_NodeDelete ========
++ * purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ */
++DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeDelete: hDisp: 0x%xthNode: "
++ "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
++ hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS
++ */
++ pCommand = (struct RMS_Command *)hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's delete
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete, "
++ "DSP-side Node Delete failed: 0x%x\n",
++ status);
++ }
++ }
++
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeRun ========
++ * purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ */
++DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
++ 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
++ hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS.
++ */
++ pCommand = (struct RMS_Command *) hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD) (ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD) nodeEnv;
++ pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's execute
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun, DSP-side Node "
++ "Execute failed: 0x%x\n",
++ status);
++ }
++ }
++
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteDisp ========
++ * purpose:
++ * Frees the resources allocated for the dispatcher.
++ */
++static void DeleteDisp(struct DISP_OBJECT *hDisp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
++ pIntfFxns = hDisp->pIntfFxns;
++
++ /* Free Node Dispatcher resources */
++ if (hDisp->hChnlFromDsp) {
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose)
++ (hDisp->hChnlFromDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel from RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->hChnlToDsp) {
++ status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel to RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->pBuf)
++ MEM_Free(hDisp->pBuf);
++
++ MEM_FreeObject(hDisp);
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * purpose:
++ * Fills stream definitions.
++ */
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord)
++{
++ struct RMS_StrmDef *pStrmDef;
++ u32 total = *ptotal;
++ u32 uNameLen;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++
++ if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
++ status = DSP_EFAIL;
++ } else {
++ pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
++ pStrmDef->bufsize = strmDef.uBufsize;
++ pStrmDef->nbufs = strmDef.uNumBufs;
++ pStrmDef->segid = strmDef.uSegid;
++ pStrmDef->align = strmDef.uAlignment;
++ pStrmDef->timeout = strmDef.uTimeout;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Since we haven't added the device name yet, subtract
++ * 1 from total.
++ */
++ total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
++ DBC_Require(strmDef.szDevice);
++ dwLength = strlen(strmDef.szDevice) + 1;
++
++ /* Number of RMS_WORDS needed to hold device name */
++ uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++
++ if (total + uNameLen >= max) {
++ status = DSP_EFAIL;
++ } else {
++ /*
++ * Zero out last word, since the device name may not
++ * extend to completely fill this word.
++ */
++ pdwBuf[total + uNameLen - 1] = 0;
++ /** TODO USE SERVICES **/
++ memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
++ total += uNameLen;
++ *ptotal = total;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== SendMessage ======
++ * Send command message to RMS, get reply from RMS.
++ */
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_OBJECT *hChnl;
++ u32 dwArg = 0;
++ u8 *pBuf;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pdwArg != NULL);
++
++ *pdwArg = (u32) NULL;
++ pIntfFxns = hDisp->pIntfFxns;
++ hChnl = hDisp->hChnlToDsp;
++ pBuf = hDisp->pBuf;
++
++ /* Send the command */
++ status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
++ 0L, dwArg);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq to"
++ " RMS failed! Status = 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage failed! "
++ "Channel IOC status = 0x%x\n",
++ chnlIOC.status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel GetIOC to"
++ " RMS failed! Status = 0x%x\n", status);
++ }
++func_cont:
++ /* Get the reply */
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hChnl = hDisp->hChnlFromDsp;
++ ulBytes = REPLYSIZE;
++ status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
++ 0, 0L, dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq "
++ "from RMS failed! Status = 0x%x\n", status);
++ goto func_end;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else if (chnlIOC.cBytes < ulBytes) {
++ /* Did not get all of the reply from the RMS */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Did not get all"
++ "of reply from RMS! Bytes received: %d\n",
++ chnlIOC.cBytes);
++ status = DSP_EFAIL;
++ } else {
++ if (CHNL_IsIOComplete(chnlIOC)) {
++ DBC_Assert(chnlIOC.pBuf == pBuf);
++ status = (*((RMS_WORD *)chnlIOC.pBuf));
++ *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* GetIOC failed */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Failed to get "
++ "reply from RMS! Status = 0x%x\n", status);
++ }
++func_end:
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
+new file mode 100644
+index 0000000..256ce12
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv.c
+@@ -0,0 +1,1893 @@
++/*
++ * drv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.c ========
++ * Description:
++ * DSP/BIOS Bridge resource allocation module.
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ======== ========
++ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
++ MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
++ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
++ *! 05-Jan-2004 vp: Updated for 24xx platform
++ *! 21-Mar-2003 sb: Get SHM size from registry
++ *! 10-Feb-2003 vp: Code review updates
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
++ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
++ *! RequestISAResources()
++ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
++ *! RequestISAResources.
++ *! 07-Aug-2000 rr: static list of dev objects removed.
++ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
++ *! instead of MEM_Alloc.
++ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
++ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
++ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
++ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
++ *! struct CFG_HOSTRES Structure.
++ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
++ *! DBC_Ensure checks for sucess and pDevice != NULL
++ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
++ *! 09-Dec-1999 rr: windows.h included to remove warnings.
++ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
++ *! status while making call to Reg functions.
++ *! 23-Nov-1999 rr: windows.h included
++ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
++ *! fixed.
++ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
++ *! Hardcoded bIRQRegister define removed.
++ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
++ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
++ *! Resource structure directly.
++ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
++ *! dwBusType taken from the registry.Hard coded
++ *! registry entries removed.
++ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
++ *! MiniDriver has been renamed to DRV_RequestResources.
++ *! DRV_UnRegisterMiniDriver fxn removed.
++ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
++ *! Now it is simpler. IT stores the dev node in the
++ *! registry, assign resources and calls the DEV_Start.
++ *! 10-Sep-1999 rr: Register Minidriver modified.
++ *! - Resource structure follows the NT model
++ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/node.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f52474d /* "DRV_" (in reverse) */
++
++struct DRV_OBJECT {
++ u32 dwSignature;
++ struct LST_LIST *devList;
++ struct LST_LIST *devNodeString;
++#ifndef RES_CLEANUP_DISABLE
++ struct PROCESS_CONTEXT *procCtxtList;
++#endif
++};
++
++/*
++ * This is the Device Extension. Named with the Prefix
++ * DRV_ since it is living in this module
++ */
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++static s32 cRefs;
++
++#if GT_TRACE
++extern struct GT_Mask curTrace;
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
++
++#ifndef RES_CLEANUP_DISABLE
++/* GPP PROCESS CLEANUP CODE */
++
++static DSP_STATUS PrintProcessInformation(void);
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt);
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt);
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++/* Get the process context list from driver object */
++
++/* Set the Process ID */
++DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hPCtxt != NULL);
++
++ pCtxt->pid = hProcess;
++ return status;
++}
++
++
++/* Getting the head of the process context list */
++DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++
++ DBC_Assert(hDrvObject != NULL);
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ *pPctxt = pDrvObject->procCtxtList;
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ return status;
++}
++
++
++
++/* Get a particular process context based on process handle (phProcess) */
++DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++ s32 pCtxtFound = 0;
++
++ DBC_Assert(pDrvObject != NULL);
++ pCtxtList = pDrvObject->procCtxtList;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
++ while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
++ }
++ if (pCtxtList == NULL) {
++ if (hNode != NULL) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempNode = pCtxtList->pNodeList;
++ while ((pTempNode != NULL) &&
++ (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempDMM = pCtxtList->pDMMList;
++ while ((pTempDMM != NULL) &&
++ (pTempDMM->ulDSPAddr != pMapAddr)) {
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ if (pCtxtList == NULL)
++ status = DSP_ENOTFOUND;
++
++ }
++ } else{
++ status = DSP_SOK;
++ }
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
++ *pCtxt = pCtxtList;
++ return status;
++}
++
++
++/* Add a new process context to process context list */
++DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *hDRVObject;
++
++ GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
++ status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ DBC_Assert(hDRVObject != NULL);
++ *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext Calling "
++ "DRV_GetProcCtxtList\n");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext After Calling "
++ "DRV_GetProcCtxtList\n");
++ if (pCtxtList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and pCtxt is "
++ "not Null\n");
++ while (pCtxtList->next != NULL)
++ pCtxtList = pCtxtList->next;
++
++ pCtxtList->next = *pCtxt;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and "
++ "pCtxt is Null\n");
++ hDRVObject->procCtxtList = *pCtxt;
++ }
++ return status;
++}
++
++/* Delete a process context from process resource context list */
++DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt2 = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++
++ DBC_Assert(hDRVObject != NULL);
++ DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
++
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
++ pTmp = pCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
++ pTmp = pCtxtList;
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_RemoveProcContext: 2");
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
++ if (hDRVObject->procCtxtList == pCtxt2)
++ hDRVObject->procCtxtList = pCtxt2->next;
++
++ if (pCtxtList == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTmp->next != NULL)
++ pTmp->next = pTmp->next->next;
++
++ MEM_Free(pCtxt2);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
++
++ return status;
++}
++
++/* Update the state of process context */
++DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status1 = DSP_SOK;
++ if (pCtxt != NULL) {
++ pCtxt->resState = status;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_ProcUpdatestate: Failed to update "
++ "process state");
++ }
++ return status1;
++}
++
++/* Allocate and add a node resource element
++* This function is called from .Node_Allocate. */
++DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
++ HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNodeRes = NULL;
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
++ *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
++ (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pNodeRes)->hNode = hNode;
++ if (pCtxt->pNodeList != NULL) {
++ pTempNodeRes = pCtxt->pNodeList;
++ while (pTempNodeRes->next != NULL)
++ pTempNodeRes = pTempNodeRes->next;
++
++ pTempNodeRes->next = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 2");
++ } else {
++ pCtxt->pNodeList = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 3");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
++ return status;
++}
++
++/* Release all Node resources and its context
++* This is called from .Node_Delete. */
++DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
++ struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
++ while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pCtxt->pNodeList == pNodeRes)
++ pCtxt->pNodeList = pNodeRes->next;
++
++ if (pTempNode == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempNode2->next != NULL)
++ pTempNode2->next = pTempNode2->next->next;
++
++ MEM_Free(pTempNode);
++ return status;
++}
++
++/* Actual Node De-Allocation */
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pNodeList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ u32 nState;
++
++ DBC_Assert(hPCtxt != NULL);
++ pNodeList = pCtxt->pNodeList;
++ while (pNodeList != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
++ pNodeRes = pNodeList;
++ pNodeList = pNodeList->next;
++ if (pNodeRes->nodeAllocated) {
++ nState = NODE_GetState(pNodeRes->hNode) ;
++ GT_1trace(curTrace, GT_5CLASS,
++ "DRV_ProcFreeNodeRes: Node state %x\n", nState);
++ if (nState <= NODE_DELETING) {
++ if ((nState == NODE_RUNNING) ||
++ (nState == NODE_PAUSED) ||
++ (nState == NODE_TERMINATING)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Terminate for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Terminate
++ (pNodeRes->hNode, &status);
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Delete for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Delete(pNodeRes->hNode);
++ GT_1trace(curTrace, GT_5CLASS,
++ "the status after the NodeDelete %x\n",
++ status);
++ } else if ((nState == NODE_ALLOCATED)
++ || (nState == NODE_CREATED))
++ status = NODE_Delete(pNodeRes->hNode);
++ }
++ }
++ pNodeRes->nodeAllocated = 0;
++ }
++ return status;
++}
++
++/* Allocate the DMM resource element
++* This is called from Proc_Map. after the actual resource is allocated */
++DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ *pDMMRes = (struct DMM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
++ if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pCtxt->pDMMList != NULL) {
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 3");
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes->next != NULL)
++ pTempDMMRes = pTempDMMRes->next;
++
++ pTempDMMRes->next = *pDMMRes;
++ } else {
++ pCtxt->pDMMList = *pDMMRes;
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 4");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
++ return status;
++}
++
++
++
++/* Release DMM resource element context
++* This is called from Proc_UnMap. after the actual resource is freed */
++DSP_STATUS DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMMRes2 = pCtxt->pDMMList;
++ pTempDMMRes = pCtxt->pDMMList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
++ while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
++ if (pCtxt->pDMMList == pTempDMMRes)
++ pCtxt->pDMMList = pTempDMMRes->next;
++
++ if (pTempDMMRes == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempDMMRes2->next != NULL)
++ pTempDMMRes2->next = pTempDMMRes2->next->next;
++
++ MEM_Free(pDMMRes);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
++ return status;
++}
++
++/* Update DMM resource status */
++DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
++ u32 pReqAddr, u32 pMapAddr,
++ HANDLE hProcessor)
++{
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hDMMRes != NULL);
++ pDMMRes->ulMpuAddr = pMpuAddr;
++ pDMMRes->ulDSPAddr = pMapAddr;
++ pDMMRes->ulDSPResAddr = pReqAddr;
++ pDMMRes->dmmSize = ulSize;
++ pDMMRes->hProcessor = hProcessor;
++ pDMMRes->dmmAllocated = 1;
++
++ return status;
++}
++
++/* Actual DMM De-Allocation */
++DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
++ while (pDMMList != NULL) {
++ pDMMRes = pDMMList;
++ pDMMList = pDMMList->next;
++ if (pDMMRes->dmmAllocated) {
++ status = PROC_UnMap(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ status = PROC_UnReserveMemory(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ pDMMRes->dmmAllocated = 0;
++ }
++ }
++ return status;
++}
++
++
++/* Release all DMM resources and its context
++* This is called from .bridge_release. */
++DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(pCtxt != NULL);
++ DRV_ProcFreeDMMRes(pCtxt);
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes != NULL) {
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ MEM_Free(pTempDMMRes2);
++ }
++ pCtxt->pDMMList = NULL;
++ return status;
++}
++
++DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMM = pCtxt->pDMMList;
++ while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
++ GT_3trace(curTrace, GT_ENTER,
++ "DRV_GetDMMResElement: 2 pTempDMM:%x "
++ "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
++ pTempDMM->ulDSPAddr, pMapAddr);
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
++ *pDMMRes = pTempDMM;
++ } else {
++ status = DSP_ENOTFOUND;
++ } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
++ return status;
++}
++
++/* Update Node allocation status */
++void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->nodeAllocated = status;
++}
++
++/* Update Node Heap status */
++void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->heapAllocated = status;
++}
++
++/* Release all Node resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeNodeRes(pCtxt);
++ pTempNode = pCtxt->pNodeList;
++ while (pTempNode != NULL) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ MEM_Free(pTempNode2);
++ }
++ pCtxt->pNodeList = NULL;
++ return status;
++}
++
++/* Getting the node resource element */
++
++DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempNode = pCtxt->pNodeList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
++ while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL)
++ *nodeRes = pTempNode;
++ else
++ status = DSP_ENOTFOUND;
++
++ return status;
++}
++
++
++
++/* Allocate the STRM resource element
++* This is called after the actual resource is allocated
++*/
++DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
++ HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++ DBC_Assert(hPCtxt != NULL);
++
++ *pSTRMRes = (struct STRM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
++ if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pSTRMRes)->hStream = hStreamHandle;
++ if (pCtxt->pSTRMList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertiSTRMResElement: 3");
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes->next != NULL)
++ pTempSTRMRes = pTempSTRMRes->next;
++
++ pTempSTRMRes->next = *pSTRMRes;
++ } else {
++ pCtxt->pSTRMList = *pSTRMRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertSTRMResElement: 4");
++ }
++ }
++ return status;
++}
++
++
++
++/* Release Stream resource element context
++* This function called after the actual resource is freed
++*/
++DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
++ struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ }
++ if (pCtxt->pSTRMList == pTempSTRMRes)
++ pCtxt->pSTRMList = pTempSTRMRes->next;
++
++ if (pTempSTRMRes == NULL)
++ status = DSP_ENOTFOUND;
++ else if (pTempSTRMRes2->next != NULL)
++ pTempSTRMRes2->next = pTempSTRMRes2->next->next;
++
++ MEM_Free(pSTRMRes);
++ return status;
++}
++
++
++/* Actual Stream De-Allocation */
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ u8 **apBuffer = NULL;
++ struct STRM_RES_OBJECT *pSTRMList = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ s32 ulBufSize;
++
++
++ DBC_Assert(hPCtxt != NULL);
++ pSTRMList = pCtxt->pSTRMList;
++ while (pSTRMList != NULL) {
++ pSTRMRes = pSTRMList;
++ pSTRMList = pSTRMList->next;
++ if (pSTRMRes->uNumBufs != 0) {
++ apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
++ sizeof(u8 *)), MEM_NONPAGED);
++ status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
++ pSTRMRes->uNumBufs);
++ MEM_Free(apBuffer);
++ }
++ status = STRM_Close(pSTRMRes->hStream);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_EPENDING) {
++ status = STRM_Reclaim(pSTRMRes->hStream,
++ &pBufPtr, &ulBytes,
++ (u32 *)&ulBufSize, &dwArg);
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Close(pSTRMRes->hStream);
++
++ }
++ }
++ }
++ return status1;
++}
++
++/* Release all Stream resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeSTRMRes(pCtxt);
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes != NULL) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ MEM_Free(pTempSTRMRes2);
++ }
++ pCtxt->pSTRMList = NULL;
++ return status;
++}
++
++
++/* Getting the stream resource element */
++DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
++ pTempSTRM2 = pTempSTRM;
++ pTempSTRM = pTempSTRM->next;
++ }
++ if (pTempSTRM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
++ *STRMRes = pTempSTRM;
++ } else {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
++ status = DSP_ENOTFOUND;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
++ return status;
++}
++
++/* Updating the stream resource element */
++DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++
++ DBC_Assert(hPCtxt != NULL);
++ (*STRMRes)->uNumBufs = uNumBufs;
++ return status;
++}
++
++/* Displaying the resources allocated by a process */
++DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
++{
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ u32 tempCount = 1;
++ HANDLE hDrvObject = NULL;
++ void *pBuf = pBuf1;
++ u8 pTempBuf[250];
++ u32 tempStrLen = 0, tempStrLen2 = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxt, (struct DRV_OBJECT *)hDrvObject);
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:*\n");
++ while (pCtxt != NULL) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "-------------------------------------"
++ "-----------------------------------\n");
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ if (pCtxt->resState == PROC_RES_ALLOCATED) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Process Resource State: "
++ "pCtxt->resState = PROC_RES_ALLOCATED, "
++ " Process ID: %d\n", pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ } else {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Resource State: pCtxt->resState"
++ " = PROC_RES_DEALLOCATED, Process ID:%d\n",
++ pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ }
++ pNodeRes = pCtxt->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pNodeList->hNode:%x\n",
++ tempCount, pNodeRes->hNode);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Node Resource Information: Node #"
++ " %d Node Handle hNode:0X%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDSPHEAPRes = pCtxt->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
++ tempCount, pDSPHEAPRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DSP Heap Resource Info: HEAP # %d"
++ " Mapped GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ (u32)pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDMMRes = pCtxt->pDMMList;
++ while (pDMMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ " pCtxt->pDMMList->ulMpuAddr:%x\n",
++ tempCount,
++ pDMMRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DMM Resource Info: DMM # %d Mapped"
++ " GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDMMRes->ulMpuAddr,
++ (u32)pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pSTRMRes = pCtxt->pSTRMList;
++ while (pSTRMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pSTRMList->hStream:%x\n", tempCount,
++ pSTRMRes->hStream);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Stream Resource info: STRM # %d "
++ "Stream Handle: 0x%x \n",
++ tempCount, (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ pCtxt = pCtxt->next;
++ }
++ *pSize = tempStrLen;
++ status = PrintProcessInformation();
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:**\n");
++ return status;
++}
++
++/*
++ * ======== PrintProcessInformation ========
++ * Purpose:
++ * This function prints the Process's information stored in
++ * the process context list. Some of the information that
++ * it displays is Process's state, Node, Stream, DMM, and
++ * Heap information.
++ */
++static DSP_STATUS PrintProcessInformation(void)
++{
++ struct DRV_OBJECT *hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 tempCount;
++ u32 procID;
++
++ /* Get the Process context list */
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
++ GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
++ " for DSP bridge ##\n");
++ GT_0trace(curTrace, GT_4CLASS, " \n ###The processes"
++ " information is as follows ### \n") ;
++ GT_0trace(curTrace, GT_4CLASS, " ====================="
++ "============ \n");
++ /* Go through the entries in the Process context list */
++ while (pCtxtList != NULL) {
++ GT_1trace(curTrace, GT_4CLASS, "\nThe process"
++ " id is %d\n", pCtxtList->pid);
++ GT_0trace(curTrace, GT_4CLASS, " -------------------"
++ "---------\n");
++ if (pCtxtList->resState == PROC_RES_ALLOCATED) {
++ GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
++ " is in Allocated state\n");
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
++ " is in DeAllocated state\n");
++ }
++ GT_1trace(curTrace, GT_4CLASS, "\nThe hProcessor"
++ " handle is: 0X%x\n",
++ (u32)pCtxtList->hProcessor);
++ if (pCtxtList->hProcessor != NULL) {
++ PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
++ if (procID == DSP_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " DSP Processor\n");
++ } else if (procID == IVA_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " IVA Processor\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "\n***ERROR:Invalid Processor Id***\n");
++ }
++ }
++ pNodeRes = pCtxtList->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Nodes allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Node # %d Node Handle hNode:0x%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Nodes"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pDSPHEAPRes = pCtxtList->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Heaps allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DSP Heap Resource Info: HEAP # %d "
++ "Mapped GPP Address:0x%x, Size: 0x%lx\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Heaps allocated"
++ " by this Process***\n");
++ tempCount = 1;
++ pDMMRes = pCtxtList->pDMMList;
++ while (pDMMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***The DMM resources allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DMM Resource Info: DMM # %d "
++ "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
++ tempCount, pDMMRes->ulMpuAddr,
++ pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no DMM resources"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pSTRMRes = pCtxtList->pSTRMList;
++ while (pSTRMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Stream resources allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Stream Resource info: STRM # %d"
++ "Stream Handle:0X%x\n", tempCount,
++ (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Stream resources"
++ "allocated by this Process***\n");
++ pCtxtList = pCtxtList->next;
++ }
++ return status;
++}
++
++/* GPP PROCESS CLEANUP CODE END */
++#endif
++
++/*
++ * ======== = DRV_Create ======== =
++ * Purpose:
++ * DRV Object gets created only once during Driver Loading.
++ */
++DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = NULL;
++
++ DBC_Require(phDRVObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
++ " phDRVObject 0x%x\n", phDRVObject);
++ MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
++ if (pDRVObject) {
++ /* Create and Initialize List of device objects */
++ pDRVObject->devList = LST_Create();
++ if (pDRVObject->devList) {
++ /* Create and Initialize List of device Extension */
++ pDRVObject->devNodeString = LST_Create();
++ if (!(pDRVObject->devNodeString)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create DRV_EXT list ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create Dev List ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory for DRV Obj");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the DRV Object in the Registry */
++ if (DSP_SUCCEEDED
++ (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
++ GT_1trace(curTrace, GT_1CLASS,
++ "DRV Obj Created pDrvObject 0x%x\n ",
++ pDRVObject);
++ *phDRVObject = pDRVObject;
++ } else {
++ /* Free the DRV Object */
++ status = DSP_EFAIL;
++ MEM_Free(pDRVObject);
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to update the Registry with "
++ "DRV Object ");
++ }
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
++ "0x%x\n", phDRVObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Discontinue usage of the DRV module.
++ */
++void DRV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
++
++ cRefs--;
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== = DRV_Destroy ======== =
++ * purpose:
++ * Invoked during bridge de-initialization
++ */
++DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
++ " hDRVObject 0x%x\n", hDRVObject);
++ /*
++ * Delete the List if it exists.Should not come here
++ * as the DRV_RemoveDevObject and the Last DRV_RequestResources
++ * removes the list if the lists are empty.
++ */
++ if (pDRVObject->devList) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devList);
++ }
++ if (pDRVObject->devNodeString) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devNodeString);
++ }
++ MEM_FreeObject(pDRVObject);
++ /* Update the DRV Object in Registry to be 0 */
++ (void)CFG_SetObject(0, REG_DRV_OBJECT);
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
++ "0x%x\n", hDRVObject, status);
++ DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list.
++ */
++DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++#if GT_TRACE /* pDrvObject is used only for Assertions and debug messages.*/
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++#endif
++ struct DEV_OBJECT *pDevObject;
++ u32 i;
++ DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(uIndex >= 0);
++ DBC_Require(cRefs > 0);
++ DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
++ GT_3trace(curTrace, GT_ENTER,
++ "Entered DRV_GetDevObject, args:\n\tuIndex: "
++ "0x%x\n\thDrvObject: 0x%x\n\tphDevObject: 0x%x\n",
++ uIndex, hDrvObject, phDevObject);
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ for (i = 0; i < uIndex; i++) {
++ pDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
++ }
++ if (pDevObject) {
++ *phDevObject = (struct DEV_OBJECT *) pDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "DRV: Could not get the DevObject\n");
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
++ "hDevObject: 0x%x\n", status, *phDevObject);
++ return status;
++}
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV.
++ */
++u32 DRV_GetFirstDevObject(void)
++{
++ u32 dwDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList))
++ dwDevObject = (u32) LST_First(pDrvObject->devList);
++ }
++
++ return dwDevObject;
++}
++
++/*
++ * ======== DRV_GetFirstDevNodeString ========
++ * Purpose:
++ * Retrieve the first Device Extension from an internal linked list of
++ * of Pointer to DevNode Strings maintained by DRV.
++ */
++u32 DRV_GetFirstDevExtension(void)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_First(pDrvObject->
++ devNodeString);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV, after having previously called
++ * DRV_GetFirstDevObject() and zero or more DRV_GetNext.
++ */
++u32 DRV_GetNextDevObject(u32 hDevObject)
++{
++ u32 dwNextDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevObject != 0);
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList)) {
++ dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
++ (struct LST_ELEM *)hDevObject);
++ }
++ }
++ return dwNextDevObject;
++}
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Retrieve the next Device Extension from an internal linked list of
++ * of pointer to DevNodeString maintained by DRV, after having previously
++ * called DRV_GetFirstDevExtension() and zero or more
++ * DRV_GetNextDevExtension().
++ */
++u32 DRV_GetNextDevExtension(u32 hDevExtension)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevExtension != 0);
++
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
++ REG_DRV_OBJECT))) {
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_Next(pDrvObject->
++ devNodeString,
++ (struct LST_ELEM *)hDevExtension);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize DRV module private state.
++ */
++DSP_STATUS DRV_Init(void)
++{
++ s32 fRetval = 1; /* function return value */
++
++ DBC_Require(cRefs >= 0);
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry crefs 0x%x \n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DevObject into the list of Manager object.
++ */
++DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Assert(pDRVObject->devList);
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_InsertProcObject hDRVObject "
++ "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
++
++ LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
++
++ GT_1trace(curTrace, GT_ENTER,
++ "Exiting InsertDevObject status 0x%x\n", status);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
++
++ return status;
++}
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a DeviceObject from the given list of DRV
++ * objects.
++ */
++DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++ struct LST_ELEM *pCurElem;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Require(hDevObject != NULL);
++
++ DBC_Require(pDRVObject->devList != NULL);
++ DBC_Require(!LST_IsEmpty(pDRVObject->devList));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_RemoveDevObject hDevObject "
++ "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
++ /* Search list for pProcObject: */
++ for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
++ pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
++ /* If found, remove it. */
++ if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
++ LST_RemoveElem(pDRVObject->devList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ /* Remove list if empty. */
++ if (LST_IsEmpty(pDRVObject->devList)) {
++ LST_Delete(pDRVObject->devList);
++ pDRVObject->devList = NULL;
++ }
++ DBC_Ensure((pDRVObject->devList == NULL) ||
++ !LST_IsEmpty(pDRVObject->devList));
++ GT_1trace(curTrace, GT_ENTER,
++ "DRV_RemoveDevObject returning 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Requests resources from the OS.
++ */
++DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject;
++ struct DRV_EXT *pszdevNode;
++
++ DBC_Require(dwContext != 0);
++ DBC_Require(pDevNodeString != NULL);
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
++ /*
++ * Allocate memory to hold the string. This will live untill
++ * it is freed in the Release resources. Update the driver object
++ * list.
++ */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
++ REG_DRV_OBJECT))) {
++ pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
++ if (pszdevNode) {
++ LST_InitElem(&pszdevNode->link);
++ strncpy((char *) pszdevNode->szString,
++ (char *)dwContext, MAXREGPATHLENGTH);
++ /* Update the Driver Object List */
++ *pDevNodeString = (u32)pszdevNode->szString;
++ LST_PutTail(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory devNodeString ");
++ status = DSP_EFAIL;
++ *pDevNodeString = 0;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to get Driver Object from Registry");
++ *pDevNodeString = 0;
++ }
++
++ if (!(strcmp((char *) dwContext, "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Allocating resources for UMA \n");
++ status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
++ }
++
++ if (DSP_FAILED(status)) {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to reserve bridge resources ");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != NULL &&
++ !LST_IsEmpty(pDRVObject->devNodeString)) ||
++ (DSP_FAILED(status) && *pDevNodeString == 0));
++
++ return status;
++}
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Releases resources from the OS.
++ */
++DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
++ struct DRV_EXT *pszdevNode;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
++
++ if (!(strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Releasing DSP-Bridge resources \n");
++ status = RequestBridgeResources(dwContext, DRV_RELEASE);
++ } else {
++ GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ "Failed to relese bridge resources\n");
++ }
++
++ /*
++ * Irrespective of the status go ahead and clean it
++ * The following will over write the status.
++ */
++ for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
++ pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
++ DRV_GetNextDevExtension((u32)pszdevNode)) {
++ if ((u32)pszdevNode == dwContext) {
++ /* Found it */
++ /* Delete from the Driver object list */
++ LST_RemoveElem(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ MEM_Free((void *) pszdevNode);
++ break;
++ }
++ /* Delete the List if it is empty */
++ if (LST_IsEmpty(pDRVObject->devNodeString)) {
++ LST_Delete(pDRVObject->devNodeString);
++ pDRVObject->devNodeString = NULL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResources ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++
++ struct DRV_EXT *driverExt;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
++
++ if (!bRequest) {
++ driverExt = (struct DRV_EXT *)dwContext;
++ /* Releasing resources by deleting the registry key */
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Failed \n");
++ } else {
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Succeeded \n");
++ }
++
++ if (pResources != NULL) {
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ if ((pResources->dwMemBase[1]) &&
++ (pResources->dwMemPhys[1])) {
++ MEM_FreePhysMem((void *)pResources->
++ dwMemBase[1], pResources->dwMemPhys[1],
++ shm_size);
++ }
++ } else {
++ GT_1trace(curTrace, GT_7CLASS,
++ "Error getting SHM size from registry: "
++ "%x. Not calling MEM_FreePhysMem\n",
++ status);
++ }
++ pResources->dwMemBase[1] = 0;
++ pResources->dwMemPhys[1] = 0;
++
++ if (pResources->dwPrmBase)
++ iounmap((void *)pResources->dwPrmBase);
++ if (pResources->dwCmBase)
++ iounmap((void *)pResources->dwCmBase);
++ if (pResources->dwMboxBase)
++ iounmap((void *)pResources->dwMboxBase);
++ if (pResources->dwMemBase[0])
++ iounmap((void *)pResources->dwMemBase[0]);
++ if (pResources->dwMemBase[2])
++ iounmap((void *)pResources->dwMemBase[2]);
++ if (pResources->dwMemBase[3])
++ iounmap((void *)pResources->dwMemBase[3]);
++ if (pResources->dwMemBase[4])
++ iounmap((void *)pResources->dwMemBase[4]);
++ if (pResources->dwWdTimerDspBase)
++ iounmap((void *)pResources->dwWdTimerDspBase);
++ if (pResources->dwDmmuBase)
++ iounmap((void *)pResources->dwDmmuBase);
++ if (pResources->dwPerBase)
++ iounmap((void *)pResources->dwPerBase);
++ if (pResources->dwPerPmBase)
++ iounmap((void *)pResources->dwPerPmBase);
++ if (pResources->dwCorePmBase)
++ iounmap((void *)pResources->dwCorePmBase);
++ if (pResources->dwSysCtrlBase) {
++ iounmap((void *)pResources->dwSysCtrlBase);
++ /* don't set pResources->dwSysCtrlBase to null
++ * as it is used in BOARD_Stop */
++ }
++ pResources->dwPrmBase = (u32) NULL;
++ pResources->dwCmBase = (u32) NULL;
++ pResources->dwMboxBase = (u32) NULL;
++ pResources->dwMemBase[0] = (u32) NULL;
++ pResources->dwMemBase[2] = (u32) NULL;
++ pResources->dwMemBase[3] = (u32) NULL;
++ pResources->dwMemBase[4] = (u32) NULL;
++ pResources->dwWdTimerDspBase = (u32) NULL;
++ pResources->dwDmmuBase = (u32) NULL;
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
++ (u32)dwBuffSize);
++ /* Set all the other entries to NULL */
++ MEM_Free(pResources);
++ }
++ GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
++ return status;
++ }
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (pResources != NULL) {
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 2;
++ /* First window is for DSP internal memory */
++
++ pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
++ OMAP_IVA2_PRM_SIZE);
++ pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
++ OMAP_IVA2_CM_SIZE);
++ pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
++ OMAP_MBOX_SIZE);
++ pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
++ OMAP_SYSC_SIZE);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++
++ /* for 24xx base port is not mapping the mamory for DSP
++ * internal memory TODO Do a ioremap here */
++ /* Second window is for DSP external memory shared with MPU */
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *) dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry "
++ "value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry "
++ "value for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResourcesDSP ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++ u32 dmaAddr;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++
++ if (pResources != NULL) {
++ if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
++ dwContext, pResources))) {
++ /* Call CFG_GetHostResources to get reserve resouces */
++ status = RequestBridgeResources(dwContext, bRequest);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources
++ ((struct CFG_DEVNODE *) dwContext,
++ pResources);
++ }
++ }
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 4;
++
++ pResources->dwMemBase[0] = 0;
++ pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
++ OMAP_DSP_MEM1_SIZE);
++ pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
++ OMAP_DSP_MEM2_SIZE);
++ pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
++ OMAP_DSP_MEM3_SIZE);
++ pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
++ OMAP_PER_CM_SIZE);
++ pResources->dwPerPmBase = (u32)ioremap(OMAP_PER_PRM_BASE,
++ OMAP_PER_PRM_SIZE);
++ pResources->dwCorePmBase = (u32)ioremap(OMAP_CORE_PRM_BASE,
++ OMAP_CORE_PRM_SIZE);
++ pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
++ OMAP_DMMU_SIZE);
++ pResources->dwWdTimerDspBase = 0;
++
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
++ pResources->dwMemBase[1]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
++ pResources->dwMemBase[2]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
++ pResources->dwMemBase[4]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate Physically contiguous,
++ * non-cacheable memory */
++ pResources->dwMemBase[1] =
++ (u32)MEM_AllocPhysMem(shm_size, 0x100000,
++ &dmaAddr);
++ if (pResources->dwMemBase[1] == 0) {
++ status = DSP_EMEMORY;
++ GT_0trace(curTrace, GT_7CLASS,
++ "SHM reservation Failed\n");
++ } else {
++ pResources->dwMemLength[1] = shm_size;
++ pResources->dwMemPhys[1] = dmaAddr;
++
++ GT_3trace(curTrace, GT_1CLASS,
++ "Bridge SHM address 0x%x dmaAddr"
++ " %x size %x\n",
++ pResources->dwMemBase[1],
++ dmaAddr, shm_size);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry"
++ " value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry value"
++ " for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
+new file mode 100644
+index 0000000..4aa7de6
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.c
+@@ -0,0 +1,777 @@
++/*
++ * drv_interface.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== linux_driver.c ========
++ * Description:
++ * DSP/BIOS Bridge driver interface.
++ *
++ * Public Functions:
++ * driver_init
++ * driver_exit
++ * driver_open
++ * driver_release
++ * driver_ioctl
++ * driver_mmap
++ *
++ *! Revision History
++ *! ================
++ *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
++ *! greater than 2.5, use module_param.
++ *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
++ *! loop after image load and waits in a loop for DSP to start
++ *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
++ *! MOD_DEC_USE_COUNT
++ *! for kernel versions greater than 2.5
++ *! 20-May-2003 vp Added unregister functions for the DPM.
++ *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
++ *! 24-Mar-2003 vp Added Power Management support.
++ *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
++ *! 10-Feb-2003 vp Updated based on code review comments
++ *! 18-Oct-2002 sb Created initial version
++ */
++
++/* ----------------------------------- Host OS */
++
++#include <dspbridge/host_os.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++
++#ifdef MODULE
++#include <linux/module.h>
++#endif
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/cdev.h>
++
++#include <mach/board-3430sdp.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/services.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/wcdioctl.h>
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dspdrv.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- This */
++#include <drv_interface.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/resourcecleanup.h>
++#include <dspbridge/chnl.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dbreg.h>
++#endif
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++#include <mach-omap2/omap3-opp.h>
++#endif
++
++#define BRIDGE_NAME "C6410"
++/* ----------------------------------- Globals */
++#define DRIVER_NAME "DspBridge"
++#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
++#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
++s32 dsp_debug;
++
++struct platform_device *omap_dspbridge_dev;
++
++struct bridge_dev {
++ struct cdev cdev;
++};
++
++static struct bridge_dev *bridge_device;
++
++static struct class *bridge_class;
++
++static u32 driverContext;
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_str;
++#endif /* CONFIG_BRIDGE_DEBUG */
++static s32 driver_major = DRIVER_MAJOR;
++static s32 driver_minor = DRIVER_MINOR;
++static char *base_img;
++char *iva_img;
++static char *num_procs = "C55=1";
++static s32 shm_size = 0x400000; /* 4 MB */
++static u32 phys_mempool_base;
++static u32 phys_mempool_size;
++static int tc_wordswapon; /* Default value is always false */
++
++#ifdef CONFIG_PM
++struct omap34xx_bridge_suspend_data {
++ int suspended;
++ wait_queue_head_t suspend_wq;
++};
++
++static struct omap34xx_bridge_suspend_data bridge_suspend_data;
++
++static int omap34xxbridge_suspend_lockout(
++ struct omap34xx_bridge_suspend_data *s, struct file *f)
++{
++ if ((s)->suspended) {
++ if ((f)->f_flags & O_NONBLOCK)
++ return DSP_EDPMSUSPEND;
++ wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
++ }
++ return 0;
++}
++
++#endif
++
++#ifdef DEBUG
++module_param(GT_str, charp, 0);
++MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
++
++module_param(dsp_debug, int, 0);
++MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
++#endif
++
++module_param(driver_major, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
++
++module_param(driver_minor, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
++
++module_param(base_img, charp, 0);
++MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
++
++module_param(shm_size, int, 0);
++MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
++
++module_param(phys_mempool_base, uint, 0);
++MODULE_PARM_DESC(phys_mempool_base,
++ "Physical memory pool base passed to driver");
++
++module_param(phys_mempool_size, uint, 0);
++MODULE_PARM_DESC(phys_mempool_size,
++ "Physical memory pool size passed to driver");
++module_param(tc_wordswapon, int, 0);
++MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_LICENSE("GPL");
++
++static char *driver_name = DRIVER_NAME;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static struct GT_Mask driverTrace;
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static struct file_operations bridge_fops = {
++ .open = bridge_open,
++ .release = bridge_release,
++ .ioctl = bridge_ioctl,
++ .mmap = bridge_mmap,
++};
++
++#ifdef CONFIG_PM
++static u32 timeOut = 1000;
++#ifdef CONFIG_BRIDGE_DVFS
++static struct clk *clk_handle;
++s32 dsp_max_opps = VDD1_OPP3;
++#endif
++
++/* Maximum Opps that can be requested by IVA*/
++/*vdd1 rate table*/
++#ifdef CONFIG_BRIDGE_DVFS
++const struct omap_opp vdd1_rate_table_bridge[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S125M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S250M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S500M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S550M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S600M, VDD1_OPP5, 0},
++};
++#endif
++#endif
++
++struct dspbridge_platform_data *omap_dspbridge_pdata;
++
++u32 vdd1_dsp_freq[6][4] = {
++ {0, 0, 0, 0},
++ /*OPP1*/
++ {0, 90000, 0, 86000},
++ /*OPP2*/
++ {0, 180000, 80000, 170000},
++ /*OPP3*/
++ {0, 360000, 160000, 340000},
++ /*OPP4*/
++ {0, 396000, 325000, 376000},
++ /*OPP5*/
++ {0, 430000, 355000, 430000},
++};
++
++#ifdef CONFIG_BRIDGE_DVFS
++static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
++ void *ptr)
++{
++ PWR_PM_PostScale(PRCM_VDD1, level);
++ return 0;
++}
++
++static struct notifier_block iva_clk_notifier = {
++ .notifier_call = dspbridge_post_scale,
++ NULL,
++};
++#endif
++
++static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
++{
++ int status;
++ u32 initStatus;
++ u32 temp;
++ dev_t dev = 0 ;
++ int result;
++#ifdef CONFIG_BRIDGE_DVFS
++ int i = 0;
++#endif
++ struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
++
++ omap_dspbridge_dev = pdev;
++
++ /* use 2.6 device model */
++ if (driver_major) {
++ dev = MKDEV(driver_major, driver_minor);
++ result = register_chrdev_region(dev, 1, driver_name);
++ } else {
++ result = alloc_chrdev_region(&dev, driver_minor, 1,
++ driver_name);
++ driver_major = MAJOR(dev);
++ }
++
++ if (result < 0) {
++ GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
++ "Can't get Major %d \n", driver_major);
++ return result;
++ }
++
++ bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
++ if (!bridge_device) {
++ result = -ENOMEM;
++ unregister_chrdev_region(dev, 1);
++ return result;
++ }
++ memset(bridge_device, 0, sizeof(struct bridge_dev));
++ cdev_init(&bridge_device->cdev, &bridge_fops);
++ bridge_device->cdev.owner = THIS_MODULE;
++ bridge_device->cdev.ops = &bridge_fops;
++
++ status = cdev_add(&bridge_device->cdev, dev, 1);
++
++ if (status) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Failed to add the bridge device \n");
++ return status;
++ }
++
++ /* udev support */
++ bridge_class = class_create(THIS_MODULE, "ti_bridge");
++
++ if (IS_ERR(bridge_class))
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Error creating bridge class \n");
++
++ device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
++ NULL, "DspBridge");
++
++ GT_init();
++ GT_create(&driverTrace, "LD");
++
++#ifdef DEBUG
++ if (GT_str)
++ GT_set(GT_str);
++#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
++ GT_set("**=67");
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
++
++#ifdef CONFIG_PM
++ /* Initialize the wait queue */
++ if (!status) {
++ bridge_suspend_data.suspended = 0;
++ init_waitqueue_head(&bridge_suspend_data.suspend_wq);
++ }
++#endif
++
++ SERVICES_Init();
++
++ /* Autostart flag. This should be set to true if the DSP image should
++ * be loaded and run during bridge module initialization */
++
++ if (base_img) {
++ temp = true;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
++ strlen(base_img) + 1);
++ } else {
++ temp = false;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
++ }
++ REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
++ strlen(num_procs) + 1);
++
++ if (shm_size >= 0x10000) { /* 64 KB */
++ initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
++ (u8 *)&shm_size, sizeof(shm_size));
++ } else {
++ initStatus = DSP_EINVALIDARG;
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "SHM size must be at least 64 KB\n");
++ }
++ GT_1trace(driverTrace, GT_7CLASS,
++ "requested shm_size = 0x%x\n", shm_size);
++
++ if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
++ phys_mempool_base = pdata->phys_mempool_base;
++ phys_mempool_size = pdata->phys_mempool_size;
++ }
++
++ if (phys_mempool_base > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
++ REG_DWORD, (u8 *)&phys_mempool_base,
++ sizeof(phys_mempool_base));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
++ phys_mempool_base);
++
++ if (phys_mempool_size > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
++ REG_DWORD, (u8 *)&phys_mempool_size,
++ sizeof(phys_mempool_size));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
++ phys_mempool_base);
++ if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
++ MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
++ if (tc_wordswapon) {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
++ (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP,
++ REG_DWORD, (u8 *)&tc_wordswapon,
++ sizeof(tc_wordswapon));
++ }
++ if (DSP_SUCCEEDED(initStatus)) {
++#ifdef CONFIG_BRIDGE_DVFS
++ for (i = 0; i < 6; i++)
++ pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
++
++ clk_handle = clk_get(NULL, "iva2_ck");
++ if (!clk_handle) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get failed to get iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get PASS to get iva2_ck \n");
++ }
++ if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register FAIL for iva2_ck \n");
++ }
++#endif
++ driverContext = DSP_Init(&initStatus);
++ if (DSP_FAILED(initStatus)) {
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "DSP/BIOS Bridge initialization Failed\n");
++ } else {
++ GT_0trace(driverTrace, GT_5CLASS,
++ "DSP/BIOS Bridge driver loaded\n");
++ }
++ }
++
++ DBC_Assert(status == 0);
++ DBC_Assert(DSP_SUCCEEDED(initStatus));
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
++ return status;
++}
++
++static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
++{
++ dev_t devno;
++ bool ret;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
++
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ goto func_cont;
++ }
++ if ((pCtxtclosed->pid == pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse = pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid == pCtxttraverse->pid)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL)
++ PROC_Detach(pCtxtclosed->hProcessor);
++ }
++func_cont:
++ pTmp = pCtxtclosed->next;
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed, (void *)pCtxtclosed->pid);
++ pCtxtclosed = pTmp;
++ }
++
++ /* unregister the clock notifier */
++#ifdef CONFIG_BRIDGE_DVFS
++ if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ }
++
++ clk_put(clk_handle);
++ clk_handle = NULL;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++
++ if (driverContext) {
++ ret = DSP_Deinit(driverContext);
++ driverContext = 0;
++
++ DBC_Assert(ret == true);
++ }
++ SERVICES_Exit();
++ GT_exit();
++
++ devno = MKDEV(driver_major, driver_minor);
++ if (bridge_device) {
++ cdev_del(&bridge_device->cdev);
++ kfree(bridge_device);
++ }
++ unregister_chrdev_region(devno, 1);
++ if (bridge_class) {
++ /* remove the device from sysfs */
++ device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
++ class_destroy(bridge_class);
++
++ }
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ u32 status;
++ u32 command = PWR_EMERGENCYDEEPSLEEP;
++
++ status = PWR_SleepDSP(command, timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 1;
++ return 0;
++}
++
++static int bridge_resume(struct platform_device *pdev)
++{
++ u32 status;
++
++ status = PWR_WakeDSP(timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 0;
++ wake_up(&bridge_suspend_data.suspend_wq);
++ return 0;
++}
++#else
++#define bridge_suspend NULL
++#define bridge_resume NULL
++#endif
++
++static struct platform_driver bridge_driver = {
++ .driver = {
++ .name = BRIDGE_NAME,
++ },
++ .probe = omap34xx_bridge_probe,
++ .remove = __devexit_p(omap34xx_bridge_remove),
++ .suspend = bridge_suspend,
++ .resume = bridge_resume,
++};
++
++static int __init bridge_init(void)
++{
++ return platform_driver_register(&bridge_driver);
++}
++
++static void __exit bridge_exit(void)
++{
++ platform_driver_unregister(&bridge_driver);
++}
++
++/* This function is called when an application opens handle to the
++ * bridge driver. */
++
++static int bridge_open(struct inode *ip, struct file *filp)
++{
++ int status = 0;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ struct PROCESS_CONTEXT *next_node = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++ struct task_struct *tsk = NULL;
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++
++ /* Checking weather task structure for all process existing
++ * in the process context list If not removing those processes*/
++ if (DSP_FAILED(dsp_status))
++ goto func_cont;
++
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ tsk = find_task_by_vpid(pCtxtclosed->pid);
++ next_node = pCtxtclosed->next;
++
++ if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
++
++ GT_1trace(driverTrace, GT_5CLASS,
++ "***Task structure not existing for "
++ "process***%d\n", pCtxtclosed->pid);
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ } else {
++ if ((pCtxtclosed->pid ==
++ pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid ==
++ pCtxttraverse->pid)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL) {
++ PROC_Detach
++ (pCtxtclosed->hProcessor);
++ }
++ }
++ }
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed,
++ (void *)pCtxtclosed->pid);
++ }
++ pCtxtclosed = next_node;
++ }
++func_cont:
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(dsp_status))
++ dsp_status = DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject, &pPctxt);
++
++ if (pPctxt != NULL) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
++ return status;
++}
++
++/* This function is called when an application closes handle to the bridge
++ * driver. */
++static int bridge_release(struct inode *ip, struct file *filp)
++{
++ int status;
++ u32 pid;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
++
++ /* Return PID instead of process handle */
++ pid = current->pid;
++
++ status = DSP_Close(pid);
++
++
++ (status == true) ? (status = 0) : (status = -1);
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
++
++ return status;
++}
++
++/* This function provides IO interface to the bridge driver. */
++static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
++ unsigned long args)
++{
++ int status;
++ u32 retval = DSP_SOK;
++ union Trapped_Args pBufIn;
++
++ DBC_Require(filp != NULL);
++#ifdef CONFIG_PM
++ status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
++ if (status != 0)
++ return status;
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
++
++ /* Deduct one for the CMD_BASE. */
++ code = (code - 1);
++
++ status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
++ sizeof(union Trapped_Args));
++
++ if (status >= 0) {
++ status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = retval;
++ } else {
++ GT_1trace(driverTrace, GT_7CLASS,
++ "IOCTL Failed, code : 0x%x\n", code);
++ status = -1;
++ }
++
++ }
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
++
++ return status;
++}
++
++/* This function maps kernel space memory to user space memory. */
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++#if GT_TRACE
++ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
++#endif
++ u32 status;
++
++ DBC_Assert(vma->vm_start < vma->vm_end);
++
++ vma->vm_flags |= VM_RESERVED | VM_IO;
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++ GT_6trace(driverTrace, GT_3CLASS,
++ "vm filp %p offset %lx start %lx end %lx"
++ " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
++ vma->vm_end, vma->vm_page_prot, vma->vm_flags);
++
++ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot);
++ if (status != 0)
++ status = -EAGAIN;
++
++ return status;
++}
++
++#ifndef RES_CLEANUP_DISABLE
++/* To remove all process resources before removing the process from the
++ * process context list*/
++DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ if (pCtxt != NULL) {
++ DRV_RemoveAllSTRMResElements(pCtxt);
++ DRV_RemoveAllNodeResElements(pCtxt);
++ DRV_RemoveAllDMMResElements(pCtxt);
++ DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
++ }
++ return status;
++}
++#endif
++
++/* Bridge driver initialization and de-initialization functions */
++module_init(bridge_init);
++module_exit(bridge_exit);
++
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
+new file mode 100644
+index 0000000..f5b068e
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.h
+@@ -0,0 +1,40 @@
++/*
++ * drv_interface.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv_interface.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Added hooks for Power Management Test
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 sb Created initial version
++
++ */
++
++#ifndef _DRV_INTERFACE_H_
++#define _DRV_INTERFACE_H_
++
++/* Prototypes for all functions in this bridge */
++static int __init bridge_init(void); /* Initialize bridge */
++static void __exit bridge_exit(void); /* Opposite of initialize */
++static int bridge_open(struct inode *, struct file *); /* Open */
++static int bridge_release(struct inode *, struct file *); /* Release */
++static int bridge_ioctl(struct inode *, struct file *, unsigned int,
++ unsigned long);
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
++#endif /* ifndef _DRV_INTERFACE_H_ */
+diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
+new file mode 100644
+index 0000000..a7a74fc
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dspdrv.c
+@@ -0,0 +1,276 @@
++/*
++ * dspdrv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.c ========
++ * Description:
++ * Interface to allocate and free bridge resources.
++ *
++ *! Revision History
++ *! ================
++ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
++ *! 09-Feb-2004 vp: Updated to support IVA.
++ *! 10-Feb-2003 vp: Code review updates.
++ *! 18-oct-2002 vp: Ported to the Linux platform.
++ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
++ *! before calling MGR_Destroy.
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
++ *! sllowing the class driver to load irrespective of
++ *! the image load.
++ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
++ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
++ *! Failure in WCD_InitComplete2 will cause the
++ *! DSP_Init to fail.
++ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
++ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
++ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
++ *! DevObjects. Static variables removed. Returns
++ *! the Driver Object in DSP_Init.
++ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
++ *! the list of Device objects.
++ *! 07-Jul-2000 rr: RM implementaion started.
++ *! 24-May-2000 ag: Cleaned up debug msgs.
++ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
++ *! 03-Feb-2000 rr: GT Changes.
++ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
++ *! DSP_Deinit checks return values.dwCode in
++ *! DSP_IO_CONTROL is decoded(not hard coded)
++ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
++ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
++ *! 29-Dec-1999 rr: Code Cleaned up
++ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
++ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and ArrayofInstalledDev
++ *! is Global.DevObject stores this pointer as hDevNode.
++ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
++ *! Comments changed.Deinit handled.Code cleaned up.
++ *! DSP_IOControl, Close, Deinit returns bool values.
++ *! Calls WCD_InitComplete2 for Board AutoStart.
++ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
++ *! Global Arrays keeps track of installed devices.
++ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
++ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
++ *! for multiple mini driver support.PCCARD flag
++ *! checking to include PCMCIA related stuff.
++ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
++ *! return value initalized to S_OK upfront in the
++ *! Process Attach.
++ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
++ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
++ *! DRV_Request Resources is used instead of the
++ *! RegisterMiniDriver as it sounds close to what we are doing.
++ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
++ *! neccessaryPCMCIA fxns are here. Soon they will move out
++ *! either to a seperate file for bus specific inits.
++ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the driver structure as
++ *! - This is the Class driver. After successfully initialized
++ *! the Class driver will attempt to load the Mini driver.
++ *! - Need to seperate the PCMCIA stuff based on bus type.
++ *! - Changed the name of the file to wcdce.c
++ *! - Made the Media Handle as Global again
++ *!
++ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
++ *! Modified the DSP_Init, now three windows are opened.
++ *! Split the driver into PDD so that hardware dependent
++ *! functions will reside in PDD.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet card driver.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/_dcd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dspdrv.h>
++
++/* ----------------------------------- Globals */
++struct GT_Mask curTrace;
++
++/*
++ * ======== DSP_Init ========
++ * Allocates bridge resources. Loads a base image onto DSP, if specified.
++ */
++u32 DSP_Init(OUT u32 *initStatus)
++{
++ char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *drvObject = NULL;
++ u32 index = 0;
++ u32 deviceNode;
++ u32 deviceNodeString;
++
++ GT_create(&curTrace, "DD");
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
++
++ if (DSP_FAILED(WCD_Init())) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
++ goto func_cont;
++ } /* End WCD_Exit */
++ if (DSP_FAILED(DRV_Create(&drvObject))) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
++ WCD_Exit();
++ goto func_cont;
++ } /* End DRV_Create */
++ GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
++
++ /* Request Resources */
++ if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
++ &deviceNodeString))) {
++ /* Attempt to Start the Device */
++ if (DSP_SUCCEEDED(DEV_StartDevice(
++ (struct CFG_DEVNODE *)deviceNodeString))) {
++ /* Retreive the DevObject from the Registry */
++ GT_2trace(curTrace, GT_1CLASS,
++ "DSP_Init Succeeded for Device1:"
++ "%d: value: %x\n", index, deviceNodeString);
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DEV_StartDevice Failed\n");
++ (void)DRV_ReleaseResources
++ ((u32) deviceNodeString, drvObject);
++ status = DSP_EFAIL;
++ }
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DRV_RequestResources Failed \r\n");
++ status = DSP_EFAIL;
++ } /* DRV_RequestResources */
++ index++;
++
++ /* Unwind whatever was loaded */
++ if (DSP_FAILED(status)) {
++ /* irrespective of the status of DEV_RemoveDevice we conitinue
++ * unloading. Get the Driver Object iterate through and remove.
++ * Reset the status to E_FAIL to avoid going through
++ * WCD_InitComplete2. */
++ status = DSP_EFAIL;
++ for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
++ deviceNode = DRV_GetNextDevExtension(deviceNode)) {
++ (void)DEV_RemoveDevice
++ ((struct CFG_DEVNODE *)deviceNode);
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ drvObject);
++ }
++ /* Remove the Driver Object */
++ (void)DRV_Destroy(drvObject);
++ drvObject = NULL;
++ WCD_Exit();
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:Logical device Failed to Load\n");
++ } /* Unwinding the loaded drivers */
++func_cont:
++ /* Attempt to Start the Board */
++ if (DSP_SUCCEEDED(status)) {
++ /* BRD_AutoStart could fail if the dsp execuetable is not the
++ * correct one. We should not propagate that error
++ * into the device loader. */
++ (void)WCD_InitComplete2();
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
++ } /* End WCD_InitComplete2 */
++ DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) ||
++ (DSP_FAILED(status) && drvObject == NULL));
++ *initStatus = status;
++ /* Return the Driver Object */
++ return (u32)drvObject;
++}
++
++/*
++ * ======== DSP_Deinit ========
++ * Frees the resources allocated for bridge.
++ */
++bool DSP_Deinit(u32 deviceContext)
++{
++ bool retVal = true;
++ u32 deviceNode;
++ struct MGR_OBJECT *mgrObject = NULL;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
++
++ while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
++ (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
++
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ (struct DRV_OBJECT *)deviceContext);
++ }
++
++ (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
++
++ /* Get the Manager Object from Registry
++ * MGR Destroy will unload the DCD dll */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
++ (void)MGR_Destroy(mgrObject);
++
++ WCD_Exit();
++
++ return retVal;
++}
++
++/*
++ * ======== DSP_Close ========
++ * The Calling Process handle is passed to DEV_CleanupProcesState
++ * for cleaning up of any resources used by the application
++ */
++bool DSP_Close(u32 dwOpenContext)
++{
++ bool retVal = false;
++
++ DBC_Require(dwOpenContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
++
++#ifdef RES_CLEANUP_DISABLE
++
++ if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
++ retVal = true;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
++ }
++#endif
++
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
+new file mode 100644
+index 0000000..943cf93
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/mgr.c
+@@ -0,0 +1,491 @@
++/*
++ * mgr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.c ========
++ * Description:
++ * Implementation of Manager interface to the device object at the
++ * driver level. This queries the NDB data base and retrieves the
++ * data about Node and Processor.
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
++ *! 03-Nov-2000 rr: Updated after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
++ *! as it is taken care by MEM_AllocObject. stdwin.h added
++ *! for retail build to succeed.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
++ *! 20-Jun-2000 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define ZLDLLNAME ""
++#define SIGNATURE 0x5f52474d /* "MGR_" (in reverse) */
++
++struct MGR_OBJECT {
++ u32 dwSignature;
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MGR_DebugMask = { NULL, NULL };
++#endif
++
++static u32 cRefs;
++
++/*
++ * ========= MGR_Create =========
++ * Purpose:
++ * MGR Object gets created only once during driver Loading.
++ */
++DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
++ struct CFG_DEVNODE *hDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(phMgrObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Create phMgrObject 0x%x\n ",
++ phMgrObject);
++ MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
++ if (pMgrObject) {
++ if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
++ &pMgrObject->hDcdMgr))) {
++ /* If succeeded store the handle in the MGR Object */
++ if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
++ REG_MGR_OBJECT))) {
++ *phMgrObject = pMgrObject;
++ GT_0trace(MGR_DebugMask, GT_1CLASS,
++ "MGR_Create:MGR Created\r\n");
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:CFG_SetObject "
++ "Failed\r\n");
++ DCD_DestroyManager(pMgrObject->hDcdMgr);
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ /* failed to Create DCD Manager */
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:DCD_ManagerCreate Failed\r\n");
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create DSP_FAILED to allocate memory \n");
++ }
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Create: phMgrObject: 0x%x\t"
++ "status: 0x%x\n", phMgrObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ========= MGR_Destroy =========
++ * This function is invoked during bridge driver unloading.Frees MGR object.
++ */
++DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
++ /* Free resources */
++ if (hMgrObject->hDcdMgr)
++ DCD_DestroyManager(hMgrObject->hDcdMgr);
++
++ MEM_FreeObject(pMgrObject);
++ /* Update the Registry with NULL for MGR Object */
++ (void)CFG_SetObject(0, REG_MGR_OBJECT);
++
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
++ "status: 0x%x\n", hMgrObject, status);
++
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ */
++DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize, OUT u32 *puNumNodes)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_UUID Uuid, uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uNodeIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(pNDBProps != NULL);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
++ "args:\n\t uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, puNumNodes);
++ *puNumNodes = 0;
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo:Failed To Get"
++ " MGR Object from Registry\r\n");
++ goto func_cont;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit failed or no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status == DSP_SOK) {
++ status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
++ &uTempUuid);
++ if (status == DSP_SOK) {
++ uNodeIndex++;
++ if (uNode == (uNodeIndex - 1))
++ Uuid = uTempUuid;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uNode > (uNodeIndex - 1)) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: uNode"
++ " is Invalid \r\n");
++ } else {
++ status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&Uuid,
++ DSP_DCDNODETYPE, &GenObj);
++ if (DSP_SUCCEEDED(status1)) {
++ /* Get the Obj def */
++ *pNDBProps = GenObj.objData.nodeObj.ndbProps;
++ *puNumNodes = uNodeIndex;
++ status = DSP_SOK;
++ } else {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: "
++ "Failed to Get Node Info \r\n");
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* This could be changed during enum, EFAIL ... */
++ GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
++ "Enumeration failure\r\n");
++ status = DSP_EFAIL;
++ }
++func_cont:
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Exiting Manager_EnumNodeInfo, args:\n\t"
++ "uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, *puNumNodes);
++ DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
++ (DSP_FAILED(status) && *puNumNodes == 0));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Enumerate and get configuration information about available
++ * DSP processors.
++ */
++DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *pProcessorInfo,
++ u32 uProcessorInfoSize, OUT u32 *puNumProcs)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ DSP_STATUS status2 = DSP_SOK;
++ struct DSP_UUID uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uProcIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++ struct MGR_PROCESSOREXTINFO *pExtInfo;
++ struct DEV_OBJECT *hDevObject;
++ struct DRV_OBJECT *hDrvObject;
++ s32 devType;
++ struct CFG_DEVNODE *devNode;
++ struct CFG_DSPRES chipResources;
++ bool procDetect = false;
++
++ DBC_Require(pProcessorInfo != NULL);
++ DBC_Require(puNumProcs != NULL);
++ DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Entered Manager_EnumProcessorInfo, "
++ "args:\n\tuProcessor: 0x%x\n\tpProcessorInfo: 0x%x\n\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
++ pProcessorInfo, uProcessorInfoSize, puNumProcs);
++ *puNumProcs = 0;
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, (u32 *) &devType);
++ status = DEV_GetDevNode(hDevObject, &devNode);
++ if (devType == DSP_UNIT) {
++ status = CFG_GetDSPResources(devNode,
++ &chipResources);
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Unsupported dev type gotten"
++ "from device object %d\n", devType);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed To Get MGR Object from Registry\r\n");
++ goto func_end;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status1 == DSP_SOK) {
++ status1 = DCD_EnumerateObject(uTempIndex++,
++ DSP_DCDPROCESSORTYPE,
++ &uTempUuid);
++ if (status1 != DSP_SOK)
++ break;
++
++ uProcIndex++;
++ /* Get the Object properties to find the Device/Processor
++ * Type */
++ if (procDetect != false)
++ continue;
++
++ status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&uTempUuid,
++ DSP_DCDPROCESSORTYPE,
++ &GenObj);
++ if (DSP_SUCCEEDED(status2)) {
++ /* Get the Obj def */
++ if (uProcessorInfoSize <
++ sizeof(struct MGR_PROCESSOREXTINFO)) {
++ *pProcessorInfo = GenObj.objData.procObj;
++ } else {
++ /* extended info */
++ pExtInfo = (struct MGR_PROCESSOREXTINFO *)
++ pProcessorInfo;
++ *pExtInfo = GenObj.objData.extProcObj;
++ }
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Got"
++ " Proctype from DCD %x \r\n",
++ pProcessorInfo->uProcessorType);
++ /* See if we got the needed processor */
++ if (devType == DSP_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ DSPPROCTYPE_C64)
++ procDetect = true;
++ } else if (devType == IVA_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ IVAPROCTYPE_ARM7)
++ procDetect = true;
++ }
++ /* User applciatiuons aonly check for chip type, so
++ * this clumsy overwrite */
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ } else {
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed to Get DCD Processor Info %x \r\n",
++ status2);
++ status = DSP_EFAIL;
++ }
++ }
++ *puNumProcs = uProcIndex;
++ if (procDetect == false) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Failed"
++ " to get Proc info from DCD , so use CFG registry\n");
++ pProcessorInfo->uProcessorType = chipResources.uChipType;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== MGR_Exit ========
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void MGR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ if (cRefs == 0)
++ DCD_Exit();
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Retrieves the MGR handle. Accessor Function.
++ */
++DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
++ OUT u32 *phDCDHandle)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDCDHandle != NULL);
++
++ *phDCDHandle = (u32)NULL;
++ if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
++ *phDCDHandle = (u32) pMgrObject->hDcdMgr;
++ status = DSP_SOK;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
++ (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
++
++ return status;
++}
++
++/*
++ * ======== MGR_Init ========
++ * Initialize MGR's private state, keeping a reference count on each call.
++ */
++bool MGR_Init(void)
++{
++ bool fRetval = true;
++ bool fInitDCD = false;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ /* Set the Trace mask */
++ DBC_Assert(!MGR_DebugMask.flags);
++
++ GT_create(&MGR_DebugMask, "MG"); /* "MG" for Manager */
++ fInitDCD = DCD_Init(); /* DCD Module */
++
++ if (!fInitDCD) {
++ fRetval = false;
++ GT_0trace(MGR_DebugMask, GT_6CLASS,
++ "MGR_Init failed\n");
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Block on any Bridge event(s)
++ */
++DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
++ u32 uCount, OUT u32 *puIndex, u32 uTimeout)
++{
++ DSP_STATUS status;
++ struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
++ u32 i;
++
++ DBC_Require(uCount < MAX_EVENTS);
++
++ for (i = 0; i < uCount; i++)
++ hSyncEvents[i] = aNotifications[i]->handle;
++
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
++ puIndex);
++
++ return status;
++
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
+new file mode 100644
+index 0000000..f3c429c
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/nldr.c
+@@ -0,0 +1,1967 @@
++/*
++ * nldr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.c ========
++ * Description:
++ * DSP/BIOS Bridge dynamic + overlay Node loader.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Removed references to dead DLDR module
++ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
++ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
++ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
++ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
++ *! sections > 1024 bytes.
++ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
++ *! libs for symbols
++ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
++ *! correct deallocation
++ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
++ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++#ifdef DEBUG
++#include <dspbridge/dbg.h>
++#endif
++
++/* OS adaptation layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Platform manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++
++/* Resource manager */
++#include <dspbridge/dbll.h>
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/uuidutil.h>
++
++#include <dspbridge/nldr.h>
++
++#define NLDR_SIGNATURE 0x52444c4e /* "RDLN" */
++#define NLDR_NODESIGNATURE 0x4e444c4e /* "NDLN" */
++
++/* Name of section containing dynamic load mem */
++#define DYNMEMSECT ".dspbridge_mem"
++
++/* Name of section containing dependent library information */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* Max depth of recursion for loading node's dependent libraries */
++#define MAXDEPTH 5
++
++/* Max number of persistent libraries kept by a node */
++#define MAXLIBS 5
++
++/*
++ * Defines for extracting packed dynamic load memory requirements from two
++ * masks.
++ * These defines must match node.cdb and dynm.cdb
++ * Format of data/code mask is:
++ * uuuuuuuu|fueeeeee|fudddddd|fucccccc|
++ * where
++ * u = unused
++ * cccccc = prefered/required dynamic mem segid for create phase data/code
++ * dddddd = prefered/required dynamic mem segid for delete phase data/code
++ * eeeeee = prefered/req. dynamic mem segid for execute phase data/code
++ * f = flag indicating if memory is preferred or required:
++ * f = 1 if required, f = 0 if preferred.
++ *
++ * The 6 bits of the segid are interpreted as follows:
++ *
++ * If the 6th bit (bit 5) is not set, then this specifies a memory segment
++ * between 0 and 31 (a maximum of 32 dynamic loading memory segments).
++ * If the 6th bit (bit 5) is set, segid has the following interpretation:
++ * segid = 32 - Any internal memory segment can be used.
++ * segid = 33 - Any external memory segment can be used.
++ * segid = 63 - Any memory segment can be used (in this case the
++ * required/preferred flag is irrelevant).
++ *
++ */
++/* Maximum allowed dynamic loading memory segments */
++#define MAXMEMSEGS 32
++
++#define MAXSEGID 3 /* Largest possible (real) segid */
++#define MEMINTERNALID 32 /* Segid meaning use internal mem */
++#define MEMEXTERNALID 33 /* Segid meaning use external mem */
++#define NULLID 63 /* Segid meaning no memory req/pref */
++#define FLAGBIT 7 /* 7th bit is pref./req. flag */
++#define SEGMASK 0x3f /* Bits 0 - 5 */
++
++#define CREATEBIT 0 /* Create segid starts at bit 0 */
++#define DELETEBIT 8 /* Delete segid starts at bit 8 */
++#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */
++
++/*
++ * Masks that define memory type. Must match defines in dynm.cdb.
++ */
++#define DYNM_CODE 0x2
++#define DYNM_DATA 0x4
++#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
++#define DYNM_INTERNAL 0x8
++#define DYNM_EXTERNAL 0x10
++
++/*
++ * Defines for packing memory requirement/preference flags for code and
++ * data of each of the node's phases into one mask.
++ * The bit is set if the segid is required for loading code/data of the
++ * given phase. The bit is not set, if the segid is preferred only.
++ *
++ * These defines are also used as indeces into a segid array for the node.
++ * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
++ * create phase data is required or preferred to be loaded into.
++ */
++#define CREATEDATAFLAGBIT 0
++#define CREATECODEFLAGBIT 1
++#define EXECUTEDATAFLAGBIT 2
++#define EXECUTECODEFLAGBIT 3
++#define DELETEDATAFLAGBIT 4
++#define DELETECODEFLAGBIT 5
++#define MAXFLAGS 6
++
++#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
++ (segid) == MEMINTERNALID)
++
++#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
++ (segid) == MEMEXTERNALID)
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++ /*
++ * These names may be embedded in overlay sections to identify which
++ * node phase the section should be overlayed.
++ */
++#define PCREATE "create"
++#define PDELETE "delete"
++#define PEXECUTE "execute"
++
++#define IsEqualUUID(uuid1, uuid2) (\
++ ((uuid1).ulData1 == (uuid2).ulData1) && \
++ ((uuid1).usData2 == (uuid2).usData2) && \
++ ((uuid1).usData3 == (uuid2).usData3) && \
++ ((uuid1).ucData4 == (uuid2).ucData4) && \
++ ((uuid1).ucData5 == (uuid2).ucData5) && \
++ (strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
++
++ /*
++ * ======== MemInfo ========
++ * Format of dynamic loading memory segment info in coff file.
++ * Must match dynm.h55.
++ */
++struct MemInfo {
++ u32 segid; /* Dynamic loading memory segment number */
++ u32 base;
++ u32 len;
++ u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
++};
++
++/*
++ * ======== LibNode ========
++ * For maintaining a tree of library dependencies.
++ */
++struct LibNode {
++ struct DBLL_LibraryObj *lib; /* The library */
++ u16 nDepLibs; /* Number of dependent libraries */
++ struct LibNode *pDepLibs; /* Dependent libraries of lib */
++};
++
++/*
++ * ======== OvlySect ========
++ * Information needed to overlay a section.
++ */
++struct OvlySect {
++ struct OvlySect *pNextSect;
++ u32 loadAddr; /* Load address of section */
++ u32 runAddr; /* Run address of section */
++ u32 size; /* Size of section */
++ u16 page; /* DBL_CODE, DBL_DATA */
++};
++
++/*
++ * ======== OvlyNode ========
++ * For maintaining a list of overlay nodes, with sections that need to be
++ * overlayed for each of the nodes phases.
++ */
++struct OvlyNode {
++ struct DSP_UUID uuid;
++ char *pNodeName;
++ struct OvlySect *pCreateSects;
++ struct OvlySect *pDeleteSects;
++ struct OvlySect *pExecuteSects;
++ struct OvlySect *pOtherSects;
++ u16 nCreateSects;
++ u16 nDeleteSects;
++ u16 nExecuteSects;
++ u16 nOtherSects;
++ u16 createRef;
++ u16 deleteRef;
++ u16 executeRef;
++ u16 otherRef;
++};
++
++/*
++ * ======== NLDR_OBJECT ========
++ * Overlay loader object.
++ */
++struct NLDR_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DBLL_TarObj *dbll; /* The DBL loader */
++ struct DBLL_LibraryObj *baseLib; /* Base image library */
++ struct RMM_TargetObj *rmm; /* Remote memory manager for DSP */
++ struct DBLL_Fxns dbllFxns; /* Loader function table */
++ struct DBLL_Attrs dbllAttrs; /* attrs to pass to loader functions */
++ NLDR_OVLYFXN ovlyFxn; /* "write" for overlay nodes */
++ NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
++ struct OvlyNode *ovlyTable; /* Table of overlay nodes */
++ u16 nOvlyNodes; /* Number of overlay nodes in base */
++ u16 nNode; /* Index for tracking overlay nodes */
++ u16 nSegs; /* Number of dynamic load mem segs */
++ u32 *segTable; /* memtypes of dynamic memory segs
++ * indexed by segid
++ */
++ u16 usDSPMauSize; /* Size of DSP MAU */
++ u16 usDSPWordSize; /* Size of DSP word */
++};
++
++/*
++ * ======== NLDR_NODEOBJECT ========
++ * Dynamic node object. This object is created when a node is allocated.
++ */
++struct NLDR_NODEOBJECT {
++ u32 dwSignature; /* For object validation */
++ struct NLDR_OBJECT *pNldr; /* Dynamic loader handle */
++ void *pPrivRef; /* Handle to pass to DBL_WriteFxn */
++ struct DSP_UUID uuid; /* Node's UUID */
++ bool fDynamic; /* Dynamically loaded node? */
++ bool fOverlay; /* Overlay node? */
++ bool *pfPhaseSplit; /* Multiple phase libraries? */
++ struct LibNode root; /* Library containing node phase */
++ struct LibNode createLib; /* Library containing create phase lib */
++ struct LibNode executeLib; /* Library containing execute phase lib */
++ struct LibNode deleteLib; /* Library containing delete phase lib */
++ struct LibNode persLib[MAXLIBS]; /* libs remain loaded until Delete */
++ s32 nPersLib; /* Number of persistent libraries */
++ /* Path in lib dependency tree */
++ struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
++ enum NLDR_PHASE phase; /* Node phase currently being loaded */
++
++ /*
++ * Dynamic loading memory segments for data and code of each phase.
++ */
++ u16 segId[MAXFLAGS];
++
++ /*
++ * Mask indicating whether each mem segment specified in segId[]
++ * is preferred or required.
++ * For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
++ * then it is required to load execute phase data into the memory
++ * specified by segId[EXECUTEDATAFLAGBIT].
++ */
++ u32 codeDataFlagMask;
++};
++
++/* Dynamic loader function table */
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static struct GT_Mask NLDR_debugMask = { NULL, NULL }; /* GT trace variable */
++static u32 cRefs; /* module reference count */
++
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes);
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes);
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype);
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc);
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *symName, struct DBLL_Symbol **sym);
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth);
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve);
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve);
++
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib);
++static u32 findLcm(u32 a, u32 b);
++static u32 findGcf(u32 a, u32 b);
++
++/*
++ * ======== NLDR_Allocate ========
++ */
++DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit)
++{
++ struct NLDR_NODEOBJECT *pNldrNode = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pNodeProps != NULL);
++ DBC_Require(phNldrNode != NULL);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
++ "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
++ pfPhaseSplit);
++
++ /* Initialize handle in case of failure */
++ *phNldrNode = NULL;
++ /* Allocate node object */
++ MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
++
++ if (pNldrNode == NULL) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pNldrNode->pfPhaseSplit = pfPhaseSplit;
++ pNldrNode->nPersLib = 0;
++ pNldrNode->pNldr = hNldr;
++ pNldrNode->pPrivRef = pPrivRef;
++ /* Save node's UUID. */
++ pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
++ /*
++ * Determine if node is a dynamically loaded node from
++ * ndbProps.
++ */
++ if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
++ /* Dynamic node */
++ pNldrNode->fDynamic = true;
++ /*
++ * Extract memory requirements from ndbProps masks
++ */
++ /* Create phase */
++ pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATEDATAFLAGBIT;
++ pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ CREATEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATECODEFLAGBIT;
++ /* Execute phase */
++ pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTEDATAFLAGBIT;
++ pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTECODEFLAGBIT;
++ /* Delete phase */
++ pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETEDATAFLAGBIT;
++ pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ DELETEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETECODEFLAGBIT;
++ } else {
++ /* Non-dynamically loaded nodes are part of the
++ * base image */
++ pNldrNode->root.lib = hNldr->baseLib;
++ /* Check for overlay node */
++ if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
++ pNldrNode->fOverlay = true;
++
++ }
++ *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
++ }
++ /* Cleanup on failure */
++ if (DSP_FAILED(status) && pNldrNode)
++ NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
++ NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
++ *phNldrNode == NULL));
++ return status;
++}
++
++/*
++ * ======== NLDR_Create ========
++ */
++DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager */
++ char *pszCoffBuf = NULL;
++ char szZLFile[COD_MAXPATHLENGTH];
++ struct NLDR_OBJECT *pNldr = NULL;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DBLL_Flags flags;
++ u32 ulEntry;
++ u16 nSegs = 0;
++ struct MemInfo *pMemInfo;
++ u32 ulLen = 0;
++ u32 ulAddr;
++ struct RMM_Segment *rmmSegs = NULL;
++ u16 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNldr != NULL);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pAttrs->pfnOvly != NULL);
++ DBC_Require(pAttrs->pfnWrite != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
++ phNldr, hDevObject, pAttrs);
++ /* Allocate dynamic loader object */
++ MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
++ if (pNldr) {
++ pNldr->hDevObject = hDevObject;
++ /* warning, lazy status checking alert! */
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetLoader(hCodMgr, &pNldr->dbll);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = DSP_SOK;
++ /* end lazy status checking */
++ pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
++ pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
++ pNldr->dbllFxns = dbllFxns;
++ if (!(pNldr->dbllFxns.initFxn()))
++ status = DSP_EMEMORY;
++
++ } else {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status))
++ status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
++
++ /* Get dynamic loading memory sections from base lib */
++ if (DSP_SUCCEEDED(status)) {
++ status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
++ &ulAddr, &ulLen);
++ if (DSP_SUCCEEDED(status)) {
++ pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
++ MEM_PAGED);
++ if (!pszCoffBuf) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Ok to not have dynamic loading memory */
++ status = DSP_SOK;
++ ulLen = 0;
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_getSect "
++ "failed (no dynamic loading mem segments): "
++ "0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Read section containing dynamic load mem segments */
++ status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
++ pszCoffBuf, ulLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_read Section"
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Parse memory segment data */
++ nSegs = (u16)(*((u32 *)pszCoffBuf));
++ if (nSegs > MAXMEMSEGS) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Invalid number of "
++ "dynamic load mem segments: 0x%lx\n", nSegs);
++ status = DSP_ECORRUPTFILE;
++ }
++ }
++ /* Parse dynamic load memory segments */
++ if (DSP_SUCCEEDED(status) && nSegs > 0) {
++ rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
++ MEM_PAGED);
++ pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
++ if (rmmSegs == NULL || pNldr->segTable == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNldr->nSegs = nSegs;
++ pMemInfo = (struct MemInfo *)(pszCoffBuf +
++ sizeof(u32));
++ for (i = 0; i < nSegs; i++) {
++ rmmSegs[i].base = (pMemInfo + i)->base;
++ rmmSegs[i].length = (pMemInfo + i)->len;
++ rmmSegs[i].space = 0;
++ pNldr->segTable[i] = (pMemInfo + i)->type;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
++ "Length: 0x%x\n", i, rmmSegs[i].base,
++ rmmSegs[i].length);
++#endif
++ }
++ }
++ }
++ /* Create Remote memory manager */
++ if (DSP_SUCCEEDED(status))
++ status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* set the alloc, free, write functions for loader */
++ pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
++ newAttrs = saveAttrs;
++ newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
++ newAttrs.free = (DBLL_FreeFxn) RemoteFree;
++ newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
++ newAttrs.symHandle = pNldr;
++ newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
++ pNldr->ovlyFxn = pAttrs->pfnOvly;
++ pNldr->writeFxn = pAttrs->pfnWrite;
++ pNldr->dbllAttrs = newAttrs;
++ }
++ if (rmmSegs)
++ MEM_Free(rmmSegs);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ /* Get overlay nodes */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ /* lazy check */
++ DBC_Assert(DSP_SUCCEEDED(status));
++ /* First count number of overlay nodes */
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
++ (void *) pNldr);
++ /* Now build table of overlay nodes */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ /* Allocate table for overlay nodes */
++ pNldr->ovlyTable =
++ MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
++ MEM_PAGED);
++ /* Put overlay nodes in the table */
++ pNldr->nNode = 0;
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
++ AddOvlyNode,
++ (void *) pNldr);
++ }
++ }
++ /* Do a fake reload of the base image to get overlay section info */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ saveAttrs.write = fakeOvlyWrite;
++ saveAttrs.logWrite = AddOvlyInfo;
++ saveAttrs.logWriteHandle = pNldr;
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
++ &saveAttrs, &ulEntry);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phNldr = (struct NLDR_OBJECT *) pNldr;
++ } else {
++ if (pNldr)
++ NLDR_Delete((struct NLDR_OBJECT *) pNldr);
++
++ *phNldr = NULL;
++ }
++ /* FIXME:Temp. Fix. Must be removed */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
++ NLDR_SIGNATURE))
++ || (DSP_FAILED(status) && (*phNldr == NULL)));
++ return status;
++}
++
++/*
++ * ======== NLDR_Delete ========
++ */
++void NLDR_Delete(struct NLDR_OBJECT *hNldr)
++{
++ struct OvlySect *pSect;
++ struct OvlySect *pNext;
++ u16 i;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
++ hNldr->dbllFxns.exitFxn();
++ if (hNldr->rmm)
++ RMM_delete(hNldr->rmm);
++
++ if (hNldr->segTable)
++ MEM_Free(hNldr->segTable);
++
++ if (hNldr->hDcdMgr)
++ DCD_DestroyManager(hNldr->hDcdMgr);
++
++ /* Free overlay node information */
++ if (hNldr->ovlyTable) {
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pSect = hNldr->ovlyTable[i].pCreateSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pDeleteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pExecuteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pOtherSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ }
++ MEM_Free(hNldr->ovlyTable);
++ }
++ MEM_FreeObject(hNldr);
++ DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++}
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ */
++void NLDR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS,
++ "Entered NLDR_Exit, ref count: 0x%x\n", cRefs);
++
++ if (cRefs == 0) {
++ RMM_exit();
++ NLDR_debugMask.flags = NULL;
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NLDR_Free ========
++ */
++void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
++
++ MEM_FreeObject(hNldrNode);
++}
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ */
++DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
++ u32 *pulAddr)
++{
++ struct DBLL_Symbol *pSym;
++ struct NLDR_OBJECT *hNldr;
++ DSP_STATUS status = DSP_SOK;
++ bool status1 = false;
++ s32 i = 0;
++ struct LibNode root = { NULL, 0, NULL };
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ DBC_Require(pulAddr != NULL);
++ DBC_Require(pstrFxn != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
++ hNldrNode, pstrFxn, pulAddr);
++
++ hNldr = hNldrNode->pNldr;
++ /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
++ if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
++ switch (hNldrNode->phase) {
++ case NLDR_CREATE:
++ root = hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ root = hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ root = hNldrNode->deleteLib;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* for Overlay nodes or non-split Dynamic nodes */
++ root = hNldrNode->root;
++ }
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
++ if (!status1)
++ status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
++
++ /* If symbol not found, check dependent libraries */
++ if (!status1) {
++ for (i = 0; i < root.nDepLibs; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
++ lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.
++ pDepLibs[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /* Check persistent libraries */
++ if (!status1) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 =
++ hNldr->dbllFxns.getCAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ if (status1) {
++ *pulAddr = pSym->value;
++ } else {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_GetFxnAddr: Symbol not found: "
++ "%s\n", pstrFxn);
++ status = DSP_ESYMBOL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_GetRmmManager ========
++ * Given a NLDR object, retrieve RMM Manager Handle
++ */
++DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj **phRmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NLDR_OBJECT *pNldrObject = hNldrObject;
++ DBC_Require(phRmmMgr != NULL);
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
++ hNldrObject, phRmmMgr);
++ if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
++ *phRmmMgr = pNldrObject->rmm;
++ } else {
++ *phRmmMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(NLDR_debugMask, GT_7CLASS,
++ "NLDR_GetRmmManager:Invalid handle");
++ }
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
++ "0x%x\n\tphRmmMgr: 0x%x\n", status, *phRmmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
++ (*phRmmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ */
++bool NLDR_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NLDR_debugMask.flags);
++ GT_create(&NLDR_debugMask, "DL"); /* "DL" for DLdr */
++
++ RMM_init();
++ }
++
++ cRefs++;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs > 0);
++ return true;
++}
++
++/*
++ * ======== NLDR_Load ========
++ */
++DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr;
++ struct DSP_UUID libUUID;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ hNldr = hNldrNode->pNldr;
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++
++ if (hNldrNode->fDynamic) {
++ hNldrNode->phase = phase;
++
++ libUUID = hNldrNode->uuid;
++
++ /* At this point, we may not know if node is split into
++ * different libraries. So we'll go ahead and load the
++ * library, and then save the pointer to the appropriate
++ * location after we know. */
++
++ status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
++ hNldrNode->libPath, phase, 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ hNldrNode->createLib = hNldrNode->root;
++ break;
++
++ case NLDR_EXECUTE:
++ hNldrNode->executeLib = hNldrNode->root;
++ break;
++
++ case NLDR_DELETE:
++ hNldrNode->deleteLib = hNldrNode->root;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ }
++ }
++ } else {
++ if (hNldrNode->fOverlay)
++ status = LoadOvly(hNldrNode, phase);
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Unload ========
++ */
++DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct LibNode *pRootLib = NULL;
++ s32 i = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++ if (hNldrNode != NULL) {
++ if (hNldrNode->fDynamic) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ pRootLib = &hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ pRootLib = &hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ pRootLib = &hNldrNode->deleteLib;
++ /* Unload persistent libraries */
++ for (i = 0; i < hNldrNode->nPersLib;
++ i++) {
++ UnloadLib(hNldrNode,
++ &hNldrNode->persLib[i]);
++ }
++ hNldrNode->nPersLib = 0;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* Unload main library */
++ pRootLib = &hNldrNode->root;
++ }
++ UnloadLib(hNldrNode, pRootLib);
++ } else {
++ if (hNldrNode->fOverlay)
++ UnloadOvly(hNldrNode, phase);
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== AddOvlyInfo ========
++ */
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes)
++{
++ char *pNodeName;
++ char *pSectName = (char *)sectInfo->name;
++ bool fExists = false;
++ char seps = ':';
++ char *pch;
++ u16 i;
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Is this an overlay section (load address != run address)? */
++ if (sectInfo->loadAddr == sectInfo->runAddr)
++ goto func_end;
++
++ /* Find the node it belongs to */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pNodeName = hNldr->ovlyTable[i].pNodeName;
++ DBC_Require(pNodeName);
++ if (strncmp(pNodeName, pSectName + 1,
++ strlen(pNodeName)) == 0) {
++ /* Found the node */
++ break;
++ }
++ }
++ if (!(i < hNldr->nOvlyNodes))
++ goto func_end;
++
++ /* Determine which phase this section belongs to */
++ for (pch = pSectName + 1; *pch && *pch != seps; pch++)
++ ;;
++
++ if (*pch) {
++ pch++; /* Skip over the ':' */
++ if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pCreateSects, sectInfo, &fExists, addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nCreateSects++;
++
++ } else
++ if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pDeleteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nDeleteSects++;
++
++ } else
++ if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pExecuteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nExecuteSects++;
++
++ } else {
++ /* Put in "other" sectins */
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pOtherSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nOtherSects++;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlyNode =========
++ * Callback function passed to DCD_GetObjects.
++ */
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ char *pNodeName = NULL;
++ char *pBuf = NULL;
++ u32 uLen;
++ struct DCD_GENERICOBJ objDef;
++ DSP_STATUS status = DSP_SOK;
++
++ if (objType != DSP_DCDNODETYPE)
++ goto func_end;
++
++ status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If overlay node, add to the list */
++ if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
++ if (hNldr->ovlyTable == NULL) {
++ hNldr->nOvlyNodes++;
++ } else {
++ /* Add node to table */
++ hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
++ DBC_Require(objDef.objData.nodeObj.ndbProps.acName);
++ uLen = strlen(objDef.objData.nodeObj.ndbProps.acName);
++ pNodeName = objDef.objData.nodeObj.ndbProps.acName;
++ pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (pBuf == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(pBuf, pNodeName, uLen);
++ hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
++ hNldr->nNode++;
++ }
++ }
++ }
++ /* These were allocated in DCD_GetObjectDef */
++ if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrIAlgName)
++ MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlySect ========
++ */
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes)
++{
++ struct OvlySect *pNewSect = NULL;
++ struct OvlySect *pLastSect;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ pSect = pLastSect = *pList;
++ *pExists = false;
++ while (pSect) {
++ /*
++ * Make sure section has not already been added. Multiple
++ * 'write' calls may be made to load the section.
++ */
++ if (pSect->loadAddr == addr) {
++ /* Already added */
++ *pExists = true;
++ break;
++ }
++ pLastSect = pSect;
++ pSect = pSect->pNextSect;
++ }
++
++ if (!pSect) {
++ /* New section */
++ pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
++ if (pNewSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNewSect->loadAddr = addr;
++ pNewSect->runAddr = pSectInfo->runAddr +
++ (addr - pSectInfo->loadAddr);
++ pNewSect->size = nBytes;
++ pNewSect->page = pSectInfo->type;
++ }
++
++ /* Add to the list */
++ if (DSP_SUCCEEDED(status)) {
++ if (*pList == NULL) {
++ /* First in the list */
++ *pList = pNewSect;
++ } else {
++ pLastSect->pNextSect = pNewSect;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== fakeOvlyWrite ========
++ */
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype)
++{
++ return (s32)nBytes;
++}
++
++/*
++ * ======== FreeSects ========
++ */
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc)
++{
++ struct OvlySect *pSect = pPhaseSects;
++ u16 i = 0;
++ bool fRet;
++
++ while (pSect && i < nAlloc) {
++ /* 'Deallocate' */
++ /* segid - page not supported yet */
++ /* Reserved memory */
++ fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
++ true);
++ DBC_Assert(fRet);
++ pSect = pSect->pNextSect;
++ i++;
++ }
++}
++
++/*
++ * ======== GetSymbolValue ========
++ * Find symbol in library's base image. If not there, check dependent
++ * libraries.
++ */
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *name, struct DBLL_Symbol **sym)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
++ struct LibNode *root = (struct LibNode *)pArg;
++ u16 i;
++ bool status = false;
++
++ /* check the base image */
++ status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
++ if (!status)
++ status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
++
++ /*
++ * Check in root lib itself. If the library consists of
++ * multiple object files linked together, some symbols in the
++ * library may need to be resolved.
++ */
++ if (!status) {
++ status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
++ if (!status) {
++ status =
++ hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
++ }
++ }
++
++ /*
++ * Check in root lib's dependent libraries, but not dependent
++ * libraries' dependents.
++ */
++ if (!status) {
++ for (i = 0; i < root->nDepLibs; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
++ lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn(root->
++ pDepLibs[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /*
++ * Check in persistent libraries
++ */
++ if (!status) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn
++ (hNldrNode->persLib[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadLib ========
++ * Recursively load library and all its dependent libraries. The library
++ * we're loading is specified by a uuid.
++ */
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 nLibs = 0; /* Number of dependent libraries */
++ u16 nPLibs = 0; /* Number of persistent libraries */
++ u16 nLoaded = 0; /* Number of dep. libraries loaded */
++ u16 i;
++ u32 entry;
++ u32 dwBufSize = NLDR_MAXPATHLENGTH;
++ DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
++ struct DBLL_Attrs newAttrs;
++ char *pszFileName = NULL;
++ struct DSP_UUID *depLibUUIDs = NULL;
++ bool *persistentDepLibs = NULL;
++ DSP_STATUS status = DSP_SOK;
++ bool fStatus = false;
++ struct LibNode *pDepLib;
++
++ if (depth > MAXDEPTH) {
++ /* Error */
++ DBC_Assert(false);
++ }
++ root->lib = NULL;
++ /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
++ pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
++ if (pszFileName == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the name of the library */
++ if (depth == 0) {
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, phase,
++ hNldrNode->pfPhaseSplit);
++ } else {
++ /* Dependent libraries are registered with a phase */
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
++ NULL);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Open the library, don't load symbols */
++ status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
++ DBLL_NOLOAD, &root->lib);
++ }
++ /* Done with file name */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ /* Check to see if library not already loaded */
++ if (DSP_SUCCEEDED(status) && rootPersistent) {
++ fStatus = findInPersistentLibArray(hNldrNode, root->lib);
++ /* Close library */
++ if (fStatus) {
++ hNldr->dbllFxns.closeFxn(root->lib);
++ return DSP_SALREADYLOADED;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check for circular dependencies. */
++ for (i = 0; i < depth; i++) {
++ if (root->lib == libPath[i]) {
++ /* This condition could be checked by a
++ * tool at build time. */
++ status = DSP_EDYNLOAD;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Add library to current path in dependency tree */
++ libPath[depth] = root->lib;
++ depth++;
++ /* Get number of dependent libraries */
++ status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
++ &nLibs, &nPLibs, phase);
++ }
++ DBC_Assert(nLibs >= nPLibs);
++ if (DSP_SUCCEEDED(status)) {
++ if (!(*hNldrNode->pfPhaseSplit))
++ nPLibs = 0;
++
++ /* nLibs = #of dependent libraries */
++ root->nDepLibs = nLibs - nPLibs;
++ if (nLibs > 0) {
++ depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
++ nLibs, MEM_PAGED);
++ persistentDepLibs =
++ MEM_Calloc(sizeof(bool) * nLibs, MEM_PAGED);
++ if (!depLibUUIDs || !persistentDepLibs)
++ status = DSP_EMEMORY;
++
++ if (root->nDepLibs > 0) {
++ /* Allocate arrays for dependent lib UUIDs,
++ * lib nodes */
++ root->pDepLibs = MEM_Calloc
++ (sizeof(struct LibNode) *
++ (root->nDepLibs), MEM_PAGED);
++ if (!(root->pDepLibs))
++ status = DSP_EMEMORY;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the dependent library UUIDs */
++ status = DCD_GetDepLibs(hNldrNode->pNldr->
++ hDcdMgr, &uuid, nLibs, depLibUUIDs,
++ persistentDepLibs, phase);
++ }
++ }
++ }
++
++ /*
++ * Recursively load dependent libraries.
++ */
++ if (DSP_SUCCEEDED(status) && persistentDepLibs) {
++ for (i = 0; i < nLibs; i++) {
++ /* If root library is NOT persistent, and dep library
++ * is, then record it. If root library IS persistent,
++ * the deplib is already included */
++ if (!rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ if ((hNldrNode->nPersLib) > MAXLIBS) {
++ status = DSP_EDYNLOAD;
++ break;
++ }
++
++ /* Allocate library outside of phase */
++ pDepLib = &hNldrNode->persLib[hNldrNode->
++ nPersLib];
++ } else {
++ if (rootPersistent)
++ persistentDepLibs[i] = true;
++
++
++ /* Allocate library within phase */
++ pDepLib = &root->pDepLibs[nLoaded];
++ }
++
++ if (depLibUUIDs) {
++ status = LoadLib(hNldrNode, pDepLib,
++ depLibUUIDs[i],
++ persistentDepLibs[i], libPath,
++ phase,
++ depth);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((status != DSP_SALREADYLOADED) &&
++ !rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ (hNldrNode->nPersLib)++;
++ } else {
++ if (!persistentDepLibs[i] ||
++ !(*hNldrNode->pfPhaseSplit)) {
++ nLoaded++;
++ }
++ }
++ } else {
++ break;
++ }
++ }
++ }
++
++ /* Now we can load the root library */
++ if (DSP_SUCCEEDED(status)) {
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.symArg = root;
++ newAttrs.rmmHandle = hNldrNode;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++
++ status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
++ &entry);
++ }
++
++ /*
++ * In case of failure, unload any dependent libraries that
++ * were loaded, and close the root library.
++ * (Persistent libraries are unloaded from the very top)
++ */
++ if (DSP_FAILED(status)) {
++ if (phase != NLDR_EXECUTE) {
++ for (i = 0; i < hNldrNode->nPersLib; i++)
++ UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
++
++ hNldrNode->nPersLib = 0;
++ }
++ for (i = 0; i < nLoaded; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ if (root->lib)
++ hNldr->dbllFxns.closeFxn(root->lib);
++
++ }
++
++ /* Going up one node in the dependency tree */
++ depth--;
++
++ if (depLibUUIDs) {
++ MEM_Free(depLibUUIDs);
++ depLibUUIDs = NULL;
++ }
++
++ if (persistentDepLibs) {
++ MEM_Free(persistentDepLibs);
++ persistentDepLibs = NULL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadOvly ========
++ */
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ u32 nBytes;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pCreateSects;
++ pOtherSects = pONode->pOtherSects;
++ break;
++
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ break;
++
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pPhaseSects = pONode->pDeleteSects;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++
++ DBC_Assert(pRefCount != NULL);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pRefCount == NULL)
++ goto func_end;
++
++ if (*pRefCount != 0)
++ goto func_end;
++
++ /* 'Allocate' memory for overlay sections of this phase */
++ pSect = pPhaseSects;
++ while (pSect) {
++ /* allocate */ /* page not supported yet */
++ /* reserve */ /* align */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
++ &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nAlloc++;
++ } else {
++ break;
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ /* 'Allocate' memory for other overlay sections
++ * (create phase) */
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pOtherSects;
++ while (pSect) {
++ /* page not supported */ /* align */
++ /* reserve */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size,
++ 0, &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nOtherAlloc++;
++ } else {
++ break;
++ }
++ }
++ }
++ }
++ if (*pRefCount == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections for this phase */
++ pSect = pPhaseSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load other sections (create phase) */
++ pSect = pOtherSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++ }
++func_end:
++ if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
++ *pRefCount += 1;
++ if (pOtherRef)
++ *pOtherRef += 1;
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== RemoteAlloc ========
++ */
++static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve)
++{
++ struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
++ struct NLDR_OBJECT *hNldr;
++ struct RMM_TargetObj *rmm;
++ u16 memPhaseBit = MAXFLAGS;
++ u16 segid = 0;
++ u16 i;
++ u16 memType;
++ u32 nWords;
++ struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
++ bool fReq = false;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++ DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
++ DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
++ space == DBLL_BSS);
++ hNldr = hNode->pNldr;
++ rmm = hNldr->rmm;
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++ /* Modify memory 'align' to account for DSP cache line size */
++ align = findLcm(GEM_CACHE_LINE_SIZE, align);
++ GT_1trace(NLDR_debugMask, GT_7CLASS,
++ "RemoteAlloc: memory align to 0x%x \n", align);
++ if (segmentId != -1) {
++ pRmmAddr->segid = segmentId;
++ segid = segmentId;
++ fReq = req;
++ } else {
++ switch (hNode->phase) {
++ case NLDR_CREATE:
++ memPhaseBit = CREATEDATAFLAGBIT;
++ break;
++ case NLDR_DELETE:
++ memPhaseBit = DELETEDATAFLAGBIT;
++ break;
++ case NLDR_EXECUTE:
++ memPhaseBit = EXECUTEDATAFLAGBIT;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (space == DBLL_CODE)
++ memPhaseBit++;
++
++ if (memPhaseBit < MAXFLAGS)
++ segid = hNode->segId[memPhaseBit];
++
++ /* Determine if there is a memory loading requirement */
++ if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
++ fReq = true;
++
++ }
++ memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
++
++ /* Find an appropriate segment based on space */
++ if (segid == NULLID) {
++ /* No memory requirements of preferences */
++ DBC_Assert(!fReq);
++ goto func_cont;
++ }
++ if (segid <= MAXSEGID) {
++ DBC_Assert(segid < hNldr->nSegs);
++ /* Attempt to allocate from segid first. */
++ pRmmAddr->segid = segid;
++ status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc:Unable allocate "
++ "from segment %d.\n", segid);
++ }
++ } else {
++ /* segid > MAXSEGID ==> Internal or external memory */
++ DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
++ /* Check for any internal or external memory segment,
++ * depending on segid.*/
++ memType |= segid == MEMINTERNALID ?
++ DYNM_INTERNAL : DYNM_EXTERNAL;
++ for (i = 0; i < hNldr->nSegs; i++) {
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid for freeing later */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++func_cont:
++ /* Haven't found memory yet, attempt to find any segment that works */
++ if (status == DSP_EMEMORY && !fReq) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc: Preferred segment "
++ "unavailable, trying another segment.\n");
++ for (i = 0; i < hNldr->nSegs; i++) {
++ /* All bits of memType must be set */
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
++ struct RMM_TargetObj *rmm;
++ u32 nWords;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ rmm = hNldr->rmm;
++
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++
++ if (RMM_free(rmm, space, dspAddr, nWords, reserve))
++ status = DSP_SOK;
++
++ return status;
++}
++
++/*
++ * ======== UnloadLib ========
++ */
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
++{
++ struct DBLL_Attrs newAttrs;
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 i;
++
++ DBC_Assert(root != NULL);
++
++ /* Unload dependent libraries */
++ for (i = 0; i < root->nDepLibs; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ root->nDepLibs = 0;
++
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.rmmHandle = hNldr->rmm;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++ newAttrs.symArg = root;
++
++ if (root->lib) {
++ /* Unload the root library */
++ hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
++ hNldr->dbllFxns.closeFxn(root->lib);
++ }
++
++ /* Free dependent library list */
++ if (root->pDepLibs) {
++ MEM_Free(root->pDepLibs);
++ root->pDepLibs = NULL;
++ }
++}
++
++/*
++ * ======== UnloadOvly ========
++ */
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pPhaseSects = pONode->pCreateSects;
++ nAlloc = pONode->nCreateSects;
++ break;
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ nAlloc = pONode->nExecuteSects;
++ break;
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pDeleteSects;
++ /* 'Other' overlay sections are unloaded in the delete phase */
++ pOtherSects = pONode->pOtherSects;
++ nAlloc = pONode->nDeleteSects;
++ nOtherAlloc = pONode->nOtherSects;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pRefCount && (*pRefCount > 0));
++ if (pRefCount && (*pRefCount > 0)) {
++ *pRefCount -= 1;
++ if (pOtherRef) {
++ DBC_Assert(*pOtherRef > 0);
++ *pOtherRef -= 1;
++ }
++ }
++ }
++ if (pRefCount && (*pRefCount == 0)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ }
++ if (pOtherRef && *pOtherRef == 0)
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++
++}
++
++/*
++ * ======== findInPersistentLibArray ========
++ */
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib)
++{
++ s32 i = 0;
++
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ if (lib == hNldrNode->persLib[i].lib)
++ return true;
++
++ }
++
++ return false;
++}
++
++/*
++ * ================ Find LCM (Least Common Multiplier ===
++ */
++static u32 findLcm(u32 a, u32 b)
++{
++ u32 retVal;
++
++ retVal = a * b / findGcf(a, b);
++
++ return retVal;
++}
++
++/*
++ * ================ Find GCF (Greatest Common Factor ) ===
++ */
++static u32 findGcf(u32 a, u32 b)
++{
++ u32 c;
++
++ /* Get the GCF (Greatest common factor between the numbers,
++ * using Euclidian Algo */
++ while ((c = (a % b))) {
++ a = b;
++ b = c;
++ }
++ return b;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
+new file mode 100644
+index 0000000..178b802
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/node.c
+@@ -0,0 +1,3544 @@
++/*
++ * node.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== node.c ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetChannelId
++ * NODE_GetMessage
++ * NODE_GetStrmMgr
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ *! Revision History:
++ *! =================
++ *! 12-Apr-2004 hp Compile IVA only for 24xx
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 07-Apr-2003 map Eliminated references to old DLDR
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in Node_Delete
++ *! function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 06-Feb-2003 kc Fixed FreeStream to release streams correctly.
++ *! 23-Jan-2003 map Removed call to DISP_DoCinit within Write()
++ *! 03-Jan-2003 map Only unload code after phase has executed if
++ *! overlay or split dynload phases
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 06-Nov-2002 map Fixed NODE_Run on NODE_PAUSED bug
++ *! 12-Oct-2002 map Fixed DeleteNode bug in NODE_Create
++ *! 11-Sep-2002 rr DeleteNode frees the memory for strmConnect and dcd obj
++ *! 29-Aug-2002 map Modified Ovly and Write to use ARM-side copy
++ *! 22-May-2002 sg Changed use of cbData for PWR calls.
++ *! 17-May-2002 jeh Removed LoadLoaderFxns(). Get address of RMS_cinit()
++ *! function. Call DISP_DoCinit() from Write(), if .cinit.
++ *! 13-May-2002 sg Added timeout to wake/sleep calls.
++ *! 02-May-2002 sg Added wake/sleep of DSP to support "nap" mode.
++ *! 18-Apr-2002 jeh Use dynamic loader if compile flag is set.
++ *! 13-Feb-2002 jeh Get uSysStackSize from DSP_NDBPROPS.
++ *! 07-Jan-2002 ag STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
++ *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
++ *! 12-Dec-2001 ag Check for valid stream mode in NODE_Connect().
++ *! 04-Dec-2001 jeh Check for node sufficiently connected in NODE_Create().
++ *! 15-Nov-2001 jeh Removed DBC_Require(pNode->hXlator != NULL) from
++ *! NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
++ *! 11-Sep-2001 ag Zero-copy messaging support.
++ *! 28-Aug-2001 jeh Overlay/dynamic loader infrastructure added. Removed
++ *! NODE_GetDispatcher, excess node states.
++ *! 07-Aug-2001 jeh Removed critical section for dispatcher.
++ *! 26-Jul-2001 jeh Get ZL dll name through CFG.
++ *! 05-Jun-2001 jeh Assume DSP_STRMATTRS.uBufsize in GPP bytes.
++ *! 11-May-2001 jeh Some code review cleanup.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 15-Dec-2000 sg Convert IALG_Fxn address from byte addr to word addr.
++ *! 04-Dec-2000 jeh Call MSG Get and Put functions.
++ *! 04-Dec-2000 ag Added SM support for node messaging.
++ *! 10-Nov-2000 rr: NODE_MIN/MAX Priority is defined in dspdefs.h.
++ *! 27-Oct-2000 jeh Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
++ *! 11-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
++ *! NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/disp.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdioctl.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/gb.h>
++#ifdef DEBUG
++#include <dspbridge/uuidutil.h>
++#include <dspbridge/dbg.h>
++#endif
++
++/* ----------------------------------- This */
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/node.h>
++
++/* Static/Dynamic Loader includes */
++#include <dspbridge/dbll.h>
++#include <dspbridge/nldr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/drv.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++
++#define NODE_SIGNATURE 0x45444f4e /* "EDON" */
++#define NODEMGR_SIGNATURE 0x52474d4e /* "RGMN" */
++
++#define HOSTPREFIX "/host"
++#define PIPEPREFIX "/dbpipe"
++
++#define MaxInputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
++#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
++
++#define NODE_GetPriority(h) ((h)->nPriority)
++#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
++#define NODE_SetState(hNode, state) ((hNode)->nState = state)
++
++#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
++#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
++
++#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
++#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
++
++#define MAXDEVNAMELEN 32 /* DSP_NDBPROPS.acName size */
++#define CREATEPHASE 1
++#define EXECUTEPHASE 2
++#define DELETEPHASE 3
++
++/* Define default STRM parameters */
++/*
++ * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
++ * or make defaults configurable.
++ */
++#define DEFAULTBUFSIZE 32
++#define DEFAULTNBUFS 2
++#define DEFAULTSEGID 0
++#define DEFAULTALIGNMENT 0
++#define DEFAULTTIMEOUT 10000
++
++#define RMSQUERYSERVER 0
++#define RMSCONFIGURESERVER 1
++#define RMSCREATENODE 2
++#define RMSEXECUTENODE 3
++#define RMSDELETENODE 4
++#define RMSCHANGENODEPRIORITY 5
++#define RMSREADMEMORY 6
++#define RMSWRITEMEMORY 7
++#define RMSCOPY 8
++#define MAXTIMEOUT 2000
++
++#define NUMRMSFXNS 9
++
++#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
++
++#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Address */
++
++/*
++ * ======== NODE_MGR ========
++ */
++struct NODE_MGR {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DISP_OBJECT *hDisp; /* Node dispatcher */
++ struct LST_LIST *nodeList; /* List of all allocated nodes */
++ u32 uNumNodes; /* Number of nodes in nodeList */
++ u32 uNumCreated; /* Number of nodes *created* on DSP */
++ struct GB_TMap *pipeMap; /* Pipe connection bit map */
++ struct GB_TMap *pipeDoneMap; /* Pipes that are half free */
++ struct GB_TMap *chnlMap; /* Channel allocation bit map */
++ struct GB_TMap *dmaChnlMap; /* DMA Channel allocation bit map */
++ struct GB_TMap *zChnlMap; /* Zero-Copy Channel alloc bit map */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++ u32 ulFxnAddrs[NUMRMSFXNS]; /* RMS function addresses */
++ struct MSG_MGR *hMsg;
++
++ /* Processor properties needed by Node Dispatcher */
++ u32 ulNumChnls; /* Total number of channels */
++ u32 ulChnlOffset; /* Offset of chnl ids rsvd for RMS */
++ u32 ulChnlBufSize; /* Buffer size for data to RMS */
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ u32 uDSPWordSize; /* Size of DSP word on host bytes */
++ u32 uDSPDataMauSize; /* Size of DSP data MAU */
++ u32 uDSPMauSize; /* Size of MAU */
++ s32 nMinPri; /* Minimum runtime priority for node */
++ s32 nMaxPri; /* Maximum runtime priority for node */
++
++ struct STRM_MGR *hStrmMgr; /* STRM manager */
++
++ /* Loader properties */
++ struct NLDR_OBJECT *hNldr; /* Handle to loader */
++ struct NLDR_FXNS nldrFxns; /* Handle to loader functions */
++ bool fLoaderInit; /* Loader Init function succeeded? */
++};
++
++/*
++ * ======== CONNECTTYPE ========
++ */
++enum CONNECTTYPE {
++ NOTCONNECTED = 0,
++ NODECONNECT,
++ HOSTCONNECT,
++ DEVICECONNECT,
++} ;
++
++/*
++ * ======== STREAM ========
++ */
++struct STREAM {
++ enum CONNECTTYPE type; /* Type of stream connection */
++ u32 devId; /* pipe or channel id */
++};
++
++/*
++ * ======== NODE_OBJECT ========
++ */
++struct NODE_OBJECT {
++ struct LST_ELEM listElem;
++ u32 dwSignature; /* For object validation */
++ struct NODE_MGR *hNodeMgr; /* The manager of this node */
++ struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
++ struct DSP_UUID nodeId; /* Node's ID */
++ s32 nPriority; /* Node's current priority */
++ u32 uTimeout; /* Timeout for blocking NODE calls */
++ u32 uHeapSize; /* Heap Size */
++ u32 uDSPHeapVirtAddr; /* Heap Size */
++ u32 uGPPHeapVirtAddr; /* Heap Size */
++ enum NODE_TYPE nType; /* Type of node: message, task, etc */
++ enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
++ u32 uNumInputs; /* Current number of inputs */
++ u32 uNumOutputs; /* Current number of outputs */
++ u32 uMaxInputIndex; /* Current max input stream index */
++ u32 uMaxOutputIndex; /* Current max output stream index */
++ struct STREAM *inputs; /* Node's input streams */
++ struct STREAM *outputs; /* Node's output streams */
++ struct NODE_CREATEARGS createArgs; /* Args for node create function */
++ NODE_ENV nodeEnv; /* Environment returned by RMS */
++ struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
++ struct DSP_CBDATA *pArgs; /* Optional args to pass to node */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ char *pstrDevName; /* device name, if device node */
++ struct SYNC_OBJECT *hSyncDone; /* Synchronize NODE_Terminate */
++ s32 nExitStatus; /* execute function return status */
++
++ /* Information needed for NODE_GetAttr() */
++ DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
++ u32 uNumGPPInputs; /* Current # of from GPP streams */
++ u32 uNumGPPOutputs; /* Current # of to GPP streams */
++ /* Current stream connections */
++ struct DSP_STREAMCONNECT *streamConnect;
++
++ /* Message queue */
++ struct MSG_QUEUE *hMsgQueue;
++
++ /* These fields used for SM messaging */
++ struct CMM_XLATOROBJECT *hXlator; /* Node's SM address translator */
++
++ /* Handle to pass to dynamic loader */
++ struct NLDR_NODEOBJECT *hNldrNode;
++ bool fLoaded; /* Code is (dynamically) loaded */
++ bool fPhaseSplit; /* Phases split in many libs or ovly */
++
++} ;
++
++/* Default buffer attributes */
++static struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
++ 0, /* cbStruct */
++ 1, /* uSegment */
++ 0, /* uAlignment */
++};
++
++static void DeleteNode(struct NODE_OBJECT *hNode);
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2, u32 uStream1,
++ u32 uStream2);
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs);
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase);
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps);
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++#if GT_TRACE
++static struct GT_Mask NODE_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++#ifdef DSP_DMM_DEBUG
++extern u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Dynamic loader functions. */
++static struct NLDR_FXNS nldrFxns = {
++ NLDR_Allocate,
++ NLDR_Create,
++ NLDR_Delete,
++ NLDR_Exit,
++ NLDR_Free,
++ NLDR_GetFxnAddr,
++ NLDR_Init,
++ NLDR_Load,
++ NLDR_Unload,
++};
++
++enum NODE_STATE NODE_GetState(HANDLE hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetState:hNode 0x%x\n", pNode);
++ return -1;
++ } else
++ return pNode->nState;
++
++}
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ */
++DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
++ OUT struct NODE_OBJECT **phNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct DEV_OBJECT *hDevObject;
++ struct NODE_OBJECT *pNode = NULL;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct NODE_MSGARGS *pmsgArgs;
++ struct NODE_TASKARGS *ptaskArgs;
++ u32 uNumStreams;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++ u32 procId;
++ char *label;
++ u32 pulValue;
++ u32 dynextBase;
++ u32 offSet = 0;
++ u32 ulStackSegAddr, ulStackSegVal;
++ u32 ulGppMemBase;
++ struct CFG_HOSTRES hostRes;
++ u32 pMappedAddr = 0;
++ u32 mapAttrs = 0x0;
++ struct DSP_PROCESSORSTATE procStatus;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#endif
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDrvObject;
++ HANDLE nodeRes;
++ u32 hProcess;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(phNode != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
++ "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
++ "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
++ phNode);
++
++ *phNode = NULL;
++
++ status = PROC_GetProcessorId(hProcessor, &procId);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL)
++ status = DSP_EFAIL;
++
++ }
++ if (procId != DSP_UNIT)
++ goto func_cont;
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ /* Assuming that 0 is not a valid function address */
++ if (hNodeMgr->ulFxnAddrs[0] == 0) {
++ /* No RMS on target - we currently can't handle this */
++ GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
++ "image. Node allocation fails.\n");
++ status = DSP_EFAIL;
++ } else {
++ /* Validate pAttrIn fields, if non-NULL */
++ if (pAttrIn) {
++ /* Check if pAttrIn->iPriority is within range */
++ if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
++ pAttrIn->iPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ }
++func_cont:
++ /* Allocate node object and fill in */
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
++ if (pNode == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont1;
++ }
++ pNode->hNodeMgr = hNodeMgr;
++ /* This critical section protects GetNodeProps */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (procId != DSP_UNIT)
++ goto func_cont3;
++
++ /* Get DSP_NDBPROPS from node database */
++ status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
++ &(pNode->dcdProps));
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ pNode->nodeId = *pNodeId;
++ pNode->hProcessor = hProcessor;
++ pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
++ pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
++ pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
++
++ /* Currently only C64 DSP builds support Node Dynamic * heaps */
++ /* Allocate memory for node heap */
++ pNode->createArgs.asa.taskArgs.uHeapSize = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
++ if (!pAttrIn)
++ goto func_cont3;
++
++ /* Check if we have a user allocated node heap */
++ if (!(pAttrIn->pGPPVirtAddr))
++ goto func_cont3;
++
++ /* check for page aligned Heap size */
++ if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_Allocate: node heap page size"
++ " not aligned to 4K page, size=0x%x \n",
++ pAttrIn->uHeapSize);
++ status = DSP_EINVALIDARG;
++ } else {
++ pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
++ (u32)pAttrIn->pGPPVirtAddr;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ status = PROC_ReserveMemory(hProcessor,
++ pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
++ (void **)&(pNode->createArgs.asa.taskArgs.
++ uDSPHeapResAddr));
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:Failed to reserve "
++ "memory for Heap: 0x%x\n", status);
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: DSPProcessor_Reserve"
++ " Memory successful: 0x%x\n", status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ mapAttrs |= DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPVIRTUALADDR;
++ status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
++ pNode->createArgs.asa.taskArgs.uHeapSize,
++ (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
++ (void **)&pMappedAddr, mapAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to map memory"
++ " for Heap: 0x%x\n", status);
++ } else {
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
++ (u32) pMappedAddr;
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:DSPProcessor_Map"
++ " successful: 0x%x\n", status);
++ }
++
++func_cont3:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_cont1:
++ if (pAttrIn != NULL) {
++ /* Overrides of NBD properties */
++ pNode->uTimeout = pAttrIn->uTimeout;
++ pNode->nPriority = pAttrIn->iPriority;
++ }
++func_cont2:
++ /* Create object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pNode->hNtfy);
++
++ if (DSP_SUCCEEDED(status)) {
++ nodeType = NODE_GetType(pNode);
++ /* Allocate DSP_STREAMCONNECT array for device, task, and
++ * dais socket nodes. */
++ if (nodeType != NODE_MESSAGE) {
++ uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
++ pNode->streamConnect = MEM_Calloc(uNumStreams *
++ sizeof(struct DSP_STREAMCONNECT),
++ MEM_PAGED);
++ if (uNumStreams > 0 && pNode->streamConnect == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
++ nodeType == NODE_DAISSOCKET)) {
++ /* Allocate arrays for maintainig stream connections */
++ pNode->inputs =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ pNode->outputs =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ ptaskArgs = &(pNode->createArgs.asa.taskArgs);
++ ptaskArgs->strmInDef =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ ptaskArgs->strmOutDef =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
++ ptaskArgs->strmInDef == NULL)) ||
++ (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
++ ptaskArgs->strmOutDef == NULL)))
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
++ /* Create an event that will be posted when RMS_EXIT is
++ * received. */
++ status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ /*Get the shared mem mgr for this nodes dev object */
++ status = CMM_GetHandle(hProcessor, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to"
++ " get CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Allocate a SM addr translator for this node
++ * w/ deflt attr */
++ status = CMM_XlatorCreate(&pNode->hXlator,
++ hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed"
++ " to create SM translator: 0x%x\n",
++ status);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in message args */
++ if ((pArgs != NULL) && (pArgs->cbData > 0)) {
++ pmsgArgs = &(pNode->createArgs.asa.msgArgs);
++ pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
++ MEM_PAGED);
++ if (pmsgArgs->pData == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pmsgArgs->uArgLength = pArgs->cbData;
++ memcpy(pmsgArgs->pData, pArgs->cData,
++ pArgs->cbData);
++ }
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
++ /* Create a message queue for this node */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
++ &pNode->hMsgQueue, 0,
++ pNode->createArgs.asa.msgArgs.uMaxMessages,
++ pNode);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create object for dynamic loading */
++
++ status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
++ (void *) pNode,
++ &pNode->dcdProps.objData.nodeObj,
++ &pNode->hNldrNode,
++ &pNode->fPhaseSplit);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to "
++ "allocate NLDR node: 0x%x\n", status);
++ }
++ }
++
++ /* Comapare value read from Node Properties and check if it is same as
++ * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
++ * GPP Address, Read the value in that address and override the
++ * uStackSeg value in task args */
++ if (DSP_SUCCEEDED(status) &&
++ (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
++ NULL) {
++ label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
++ strncpy(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
++
++ if (strcmp((char *)pNode->dcdProps.objData.nodeObj.
++ ndbProps.uStackSegName, label) == 0) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "DYNEXT_BEG", &dynextBase);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "DYNEXT_BEG: 0x%x\n", status);
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "L1DSRAM_HEAP", &pulValue);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "L1DSRAM_HEAP: 0x%x\n", status);
++ }
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get host resource "
++ "0x%x\n", status);
++ }
++
++ ulGppMemBase = hostRes.dwMemBase[1];
++ offSet = pulValue - dynextBase;
++ ulStackSegAddr = ulGppMemBase + offSet;
++ ulStackSegVal = (u32)*((REG_UWORD32 *)
++ ((u32)(ulStackSegAddr)));
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "StackSegVal =0x%x\n", ulStackSegVal);
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
++
++ pNode->createArgs.asa.taskArgs.uStackSeg =
++ ulStackSegVal;
++
++ }
++
++ if (label)
++ MEM_Free(label);
++
++ }
++
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Add the node to the node manager's list of allocated
++ * nodes. */
++ LST_InitElem((struct LST_ELEM *)pNode);
++ NODE_SetState(pNode, NODE_ALLOCATED);
++
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ LST_PutTail(hNodeMgr->nodeList,
++ (struct LST_ELEM *) pNode);
++ ++(hNodeMgr->uNumNodes);
++ }
++
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hNodeMgr->hSync);
++
++ /* Preset this to assume phases are split
++ * (for overlay and dll) */
++ pNode->fPhaseSplit = true;
++
++ if (DSP_SUCCEEDED(status))
++ *phNode = pNode;
++
++
++ /* Notify all clients registered for DSP_NODESTATECHANGE. */
++ PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
++ } else {
++ /* Cleanup */
++ if (pNode)
++ DeleteNode(pNode);
++
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt,
++ PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ pPctxt->hProcessor =
++ (DSP_HPROCESSOR)hProcessor;
++ }
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt != NULL) {
++ DRV_InsertNodeResElement(*phNode, &nodeRes,
++ pPctxt);
++ DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
++ DRV_ProcNodeUpdateStatus(nodeRes, true);
++ }
++ }
++ }
++#endif
++ DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
++ (DSP_SUCCEEDED(status)
++ && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocates buffer for zero copy messaging.
++ */
++DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
++ OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
++ OUT u8 **pBuffer)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ bool bVirtAddr = false;
++ bool bSetInfo;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++
++ DBC_Require(uSize > 0);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
++ " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
++ pBuffer);
++
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (NODE_GetType(pNode) == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pAttr == NULL)
++ pAttr = &NODE_DFLTBUFATTRS; /* set defaults */
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId != DSP_UNIT) {
++ DBC_Assert(NULL);
++ goto func_end;
++ }
++ /* If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
++ * virt address, so set this info in this node's translator
++ * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
++ * virtual address from node's translator. */
++ if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
++ (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
++ bVirtAddr = true;
++ bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
++ true : false;
++ pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
++ /* Set/get this node's translators virtual address base/size */
++ status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
++ pAttr->uSegment, bSetInfo);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf "
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
++ if (pAttr->uSegment != 1) {
++ /* Node supports single SM segment only. */
++ status = DSP_EBADSEGID;
++ }
++ /* Arbitrary SM buffer alignment not supported for host side
++ * allocs, but guaranteed for the following alignment
++ * values. */
++ switch (pAttr->uAlignment) {
++ case 0:
++ case 1:
++ case 2:
++ case 4:
++ break;
++ default:
++ /* alignment value not suportted */
++ status = DSP_EALIGNMENT;
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* allocate physical buffer from segId in node's
++ * translator */
++ (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
++ uSize);
++ if (*pBuffer == NULL) {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf: "
++ "ERROR: Out of shared memory.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of a node in the allocated state, or that is
++ * currently running or paused on the target.
++ */
++DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
++ "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "Invalid NODE Handle: 0x%x\n", hNode);
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ else if (nPriority < hNodeMgr->nMinPri ||
++ nPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
++ NODE_SetPriority(hNode, nPriority);
++ } else {
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(pNode->hProcessor,
++ &procId);
++ if (procId == DSP_UNIT) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, nPriority);
++ }
++ if (DSP_SUCCEEDED(status))
++ NODE_SetPriority(hNode, nPriority);
++
++ }
++ }
++func_cont:
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP.
++ */
++DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA *pConnParam)
++{
++ struct NODE_MGR *hNodeMgr;
++ char *pstrDevName = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++ struct NODE_STRMDEF *pstrmDef;
++ struct NODE_STRMDEF *pInput = NULL;
++ struct NODE_STRMDEF *pOutput = NULL;
++ struct NODE_OBJECT *hDevNode;
++ struct NODE_OBJECT *hNode;
++ struct STREAM *pStream;
++ GB_BitNum pipeId = GB_NOBITS;
++ GB_BitNum chnlId = GB_NOBITS;
++ CHNL_MODE uMode;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ GT_5trace(NODE_debugMask, GT_ENTER,
++ "NODE_Connect: hNode1: 0x%x\tuStream1:"
++ " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
++ uStream1, hNode2, uStream2, pAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
++ (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* The two nodes must be on the same processor */
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode1->hNodeMgr != hNode2->hNodeMgr)
++ status = DSP_EFAIL;
++ /* Cannot connect a node to itself */
++ if (hNode1 == hNode2)
++ status = DSP_EFAIL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NODE_GetType() will return NODE_GPP if hNode =
++ * DSP_HGPPNODE. */
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ /* Check stream indices ranges */
++ if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
++ uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
++ node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Only the following types of connections are allowed:
++ * task/dais socket < == > task/dais socket
++ * task/dais socket < == > device
++ * task/dais socket < == > GPP
++ *
++ * ie, no message nodes, and at least one task or dais
++ * socket node.
++ */
++ if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
++ (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
++ node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
++ status = DSP_EFAIL;
++ }
++ /*
++ * Check stream mode. Default is STRMMODE_PROCCOPY.
++ */
++ if (DSP_SUCCEEDED(status) && pAttrs) {
++ if (pAttrs->lMode != STRMMODE_PROCCOPY)
++ status = DSP_ESTRMMODE; /* illegal stream mode */
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (node1Type != NODE_GPP) {
++ hNodeMgr = hNode1->hNodeMgr;
++ } else {
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ hNodeMgr = hNode2->hNodeMgr;
++ }
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Nodes must be in the allocated state */
++ if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Check that stream indices for task and dais socket nodes
++ * are not already be used. (Device nodes checked later) */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ pOutput = &(hNode1->createArgs.asa.taskArgs.
++ strmOutDef[uStream1]);
++ if (pOutput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ pInput = &(hNode2->createArgs.asa.taskArgs.
++ strmInDef[uStream2]);
++ if (pInput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ }
++ /* Connecting two task nodes? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
++ node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
++ node2Type == NODE_DAISSOCKET))) {
++ /* Find available pipe */
++ pipeId = GB_findandset(hNodeMgr->pipeMap);
++ if (pipeId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ } else {
++ hNode1->outputs[uStream1].type = NODECONNECT;
++ hNode2->inputs[uStream2].type = NODECONNECT;
++ hNode1->outputs[uStream1].devId = pipeId;
++ hNode2->inputs[uStream2].devId = pipeId;
++ pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ if (pOutput->szDevice == NULL ||
++ pInput->szDevice == NULL) {
++ /* Undo the connection */
++ if (pOutput->szDevice)
++ MEM_Free(pOutput->szDevice);
++
++ if (pInput->szDevice)
++ MEM_Free(pInput->szDevice);
++
++ pOutput->szDevice = NULL;
++ pInput->szDevice = NULL;
++ GB_clear(hNodeMgr->pipeMap, pipeId);
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy "/dbpipe<pipId>" name to device names */
++ sprintf(pOutput->szDevice, "%s%d",
++ PIPEPREFIX, pipeId);
++ strcpy(pInput->szDevice, pOutput->szDevice);
++ }
++ }
++ }
++ /* Connecting task node to host? */
++ if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
++ node2Type == NODE_GPP)) {
++ if (node1Type == NODE_GPP) {
++ uMode = CHNL_MODETODSP;
++ } else {
++ DBC_Assert(node2Type == NODE_GPP);
++ uMode = CHNL_MODEFROMDSP;
++ }
++ /* Reserve a channel id. We need to put the name "/host<id>"
++ * in the node's createArgs, but the host
++ * side channel will not be opened until DSPStream_Open is
++ * called for this node. */
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
++ /* dma chans are 2nd transport chnl set
++ * ids(e.g. 16-31)*/
++ (chnlId != GB_NOBITS) ?
++ (chnlId = chnlId + hNodeMgr->ulNumChnls) :
++ chnlId;
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ chnlId = GB_findandset(hNodeMgr->zChnlMap);
++ /* zero-copy chans are 3nd transport set
++ * (e.g. 32-47) */
++ (chnlId != GB_NOBITS) ? (chnlId = chnlId +
++ (2 * hNodeMgr->ulNumChnls)) : chnlId;
++ } else { /* must be PROCCOPY */
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ /* e.g. 0-15 */
++ }
++ } else {
++ /* default to PROCCOPY */
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ }
++ if (chnlId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ goto func_cont2;
++ }
++ pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
++ if (pstrDevName != NULL)
++ goto func_cont2;
++
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ GB_clear(hNodeMgr->dmaChnlMap, chnlId -
++ hNodeMgr->ulNumChnls);
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ GB_clear(hNodeMgr->zChnlMap, chnlId -
++ (2*hNodeMgr->ulNumChnls));
++ } else {
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ } else {
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ status = DSP_EMEMORY;
++func_cont2:
++ if (DSP_SUCCEEDED(status)) {
++ if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
++ hNode2->inputs[uStream2].type = HOSTCONNECT;
++ hNode2->inputs[uStream2].devId = chnlId;
++ pInput->szDevice = pstrDevName;
++ } else {
++ hNode1->outputs[uStream1].type = HOSTCONNECT;
++ hNode1->outputs[uStream1].devId = chnlId;
++ pOutput->szDevice = pstrDevName;
++ }
++ sprintf(pstrDevName, "%s%d", HOSTPREFIX, chnlId);
++ }
++ }
++ /* Connecting task node to device node? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
++ (node2Type == NODE_DEVICE))) {
++ if (node2Type == NODE_DEVICE) {
++ /* node1 == > device */
++ hDevNode = hNode2;
++ hNode = hNode1;
++ pStream = &(hNode1->outputs[uStream1]);
++ pstrmDef = pOutput;
++ } else {
++ /* device == > node2 */
++ hDevNode = hNode1;
++ hNode = hNode2;
++ pStream = &(hNode2->inputs[uStream2]);
++ pstrmDef = pInput;
++ }
++ /* Set up create args */
++ pStream->type = DEVICECONNECT;
++ dwLength = strlen(hDevNode->pstrDevName);
++ if (pConnParam != NULL) {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
++ (u32) pConnParam->cbData,
++ MEM_PAGED);
++ } else {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
++ MEM_PAGED);
++ }
++ if (pstrmDef->szDevice == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy device name */
++ strncpy(pstrmDef->szDevice, hDevNode->pstrDevName,
++ dwLength);
++ if (pConnParam != NULL) {
++ strncat(pstrmDef->szDevice,
++ (char *)pConnParam->cData,
++ (u32)pConnParam->cbData);
++ }
++ hDevNode->hDeviceOwner = hNode;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ hNode1->createArgs.asa.taskArgs.uNumOutputs++;
++ FillStreamDef(hNode1, pOutput, pAttrs);
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ hNode2->createArgs.asa.taskArgs.uNumInputs++;
++ FillStreamDef(hNode2, pInput, pAttrs);
++ }
++ /* Update hNode1 and hNode2 streamConnect */
++ if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
++ hNode1->uNumOutputs++;
++ if (uStream1 > hNode1->uMaxOutputIndex)
++ hNode1->uMaxOutputIndex = uStream1;
++
++ }
++ if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
++ hNode2->uNumInputs++;
++ if (uStream2 > hNode2->uMaxInputIndex)
++ hNode2->uMaxInputIndex = uStream2;
++
++ }
++ FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
++ }
++func_cont:
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulCreateFxn;
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ bool bJustWokeDSP = false;
++ struct DSP_CBDATA cbData;
++ u32 procId = 255;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
++ hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to create
++ new node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR calls */
++ cbData.cbData = PWR_TIMEOUT;
++ nodeType = NODE_GetType(hNode);
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Get access to node dispatcher */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Check node state */
++ if (NODE_GetState(hNode) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ if (procId != DSP_UNIT)
++ goto func_cont2;
++
++ /* Make sure streams are properly connected */
++ if ((hNode->uNumInputs && hNode->uMaxInputIndex >
++ hNode->uNumInputs - 1) ||
++ (hNode->uNumOutputs && hNode->uMaxOutputIndex >
++ hNode->uNumOutputs - 1))
++ status = DSP_ENOTCONNECTED;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* If node's create function is not loaded, load it */
++ /* Boost the OPP level to max level that DSP can be requested */
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP3]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP3 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_CREATE);
++ /* Get address of node's create function */
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ if (nodeType != NODE_DEVICE) {
++ status = GetFxnAddress(hNode, &ulCreateFxn,
++ CREATEPHASE);
++ }
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Create: failed to load"
++ " create code: 0x%x\n", status);
++ }
++ /* Request the lowest OPP level*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP1 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ /* Get address of iAlg functions, if socket node */
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType == NODE_DAISSOCKET) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr
++ (hNode->hNldrNode, hNode->dcdProps.
++ objData.nodeObj.pstrIAlgName,
++ &hNode->createArgs.asa.taskArgs.
++ ulDaisArg);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType != NODE_DEVICE) {
++ status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCREATENODE],
++ ulCreateFxn, &(hNode->createArgs),
++ &(hNode->nodeEnv));
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the message queue id to the node env
++ * pointer */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
++ hNode->nodeEnv);
++ }
++ }
++ }
++ /* Phase II/Overlays: Create, execute, delete phases possibly in
++ * different files/sections. */
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ /* If create code was dynamically loaded, we can now unload
++ * it. */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_CREATE);
++ hNode->fLoaded = false;
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Create: Failed to unload "
++ "create code: 0x%x\n", status1);
++ }
++func_cont2:
++ /* Update node state and node manager state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_CREATED);
++ hNodeMgr->uNumCreated++;
++ goto func_cont;
++ }
++ if (status != DSP_EWRONGSTATE) {
++ /* Put back in NODE_ALLOCATED state if error occurred */
++ NODE_SetState(hNode, NODE_ALLOCATED);
++ }
++ if (procId == DSP_UNIT) {
++ /* If node create failed, see if should sleep DSP now */
++ if (bJustWokeDSP == true) {
++ /* Check to see if partial create happened on DSP */
++ if (hNode->nodeEnv == (u32)NULL) {
++ /* No environment allocated on DSP, re-sleep
++ * DSP now */
++ PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
++ &cbData);
++ } else {
++ /* Increment count, sleep later when node fully
++ * deleted */
++ hNodeMgr->uNumCreated++;
++ }
++ }
++ }
++func_cont:
++ /* Free access to node dispatcher */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object.
++ */
++DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ u32 i;
++ struct NODE_MGR *pNodeMgr = NULL;
++ struct DISP_ATTRS dispAttrs;
++ char *szZLFile = "";
++ struct NLDR_ATTRS nldrAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++ DBC_Require(hDevObject != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
++ "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
++ *phNodeMgr = NULL;
++ /* Allocate Node manager object */
++ MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
++ if (pNodeMgr) {
++ pNodeMgr->hDevObject = hDevObject;
++ pNodeMgr->nodeList = LST_Create();
++ pNodeMgr->pipeMap = GB_create(MAXPIPES);
++ pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
++ if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
++ pNodeMgr->pipeDoneMap == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory "
++ "allocation failed\n");
++ } else {
++ status = NTFY_Create(&pNodeMgr->hNtfy);
++ }
++ pNodeMgr->uNumCreated = 0;
++ } else {
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* get devNodeType */
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevType(hDevObject, &devType);
++
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status)) {
++ status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
++ if (DSP_SUCCEEDED(status))
++ status = GetProcProps(pNodeMgr, hDevObject);
++
++ }
++ /* Create NODE Dispatcher */
++ if (DSP_SUCCEEDED(status)) {
++ dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
++ dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
++ dispAttrs.procFamily = pNodeMgr->procFamily;
++ dispAttrs.procType = pNodeMgr->procType;
++ status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
++ }
++ /* Create a STRM Manager */
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
++ /* Get MSG queue manager */
++ DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
++ status = SYNC_InitializeCS(&pNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
++ /* dma chnl map. ulNumChnls is # per transport */
++ pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ if ((pNodeMgr->chnlMap == NULL) ||
++ (pNodeMgr->dmaChnlMap == NULL) ||
++ (pNodeMgr->zChnlMap == NULL)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Block out reserved channels */
++ for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
++ GB_set(pNodeMgr->chnlMap, i);
++
++ /* Block out channels reserved for RMS */
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NO RM Server on the IVA */
++ if (devType != IVA_UNIT) {
++ /* Get addresses of any RMS functions loaded */
++ status = GetRMSFxns(pNodeMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to"
++ " get RMS functions: status = 0x%x", status);
++ }
++ }
++ }
++
++ /* Get loader functions and create loader */
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_1CLASS,
++ "NODE_CreateMgr: using dynamic loader\n");
++ pNodeMgr->nldrFxns = nldrFxns; /* Dynamic loader functions */
++ }
++ if (DSP_SUCCEEDED(status)) {
++ nldrAttrs.pfnOvly = Ovly;
++ nldrAttrs.pfnWrite = Write;
++ nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
++ nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
++ pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
++ status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
++ hDevObject, &nldrAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to "
++ "create loader: status = 0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phNodeMgr = pNodeMgr;
++ else
++ DeleteNodeMgr(pNodeMgr);
++
++ DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ * Loads the node's delete function if necessary. Free GPP side resources
++ * after node's delete function returns.
++ */
++DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct PROC_OBJECT *hProcessor;
++ struct DISP_OBJECT *hDisp;
++ u32 ulDeleteFxn;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_CBDATA cbData;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE nodeRes;
++ HANDLE hDrvObject;
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ struct DSP_PROCESSORSTATE procStatus;
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
++ hNode);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR call */
++ cbData.cbData = PWR_TIMEOUT;
++ hNodeMgr = hNode->hNodeMgr;
++ hProcessor = hNode->hProcessor;
++ hDisp = hNodeMgr->hDisp;
++ nodeType = NODE_GetType(hNode);
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ state = NODE_GetState(hNode);
++ /* Execute delete phase code for non-device node in all cases
++ * except when the node was only allocated. Delete phase must be
++ * executed even if create phase was executed, but failed.
++ * If the node environment pointer is non-NULL, the delete phase
++ * code must be executed. */
++ if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
++ nodeType != NODE_DEVICE) {
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if (procId == DSP_UNIT || procId == IVA_UNIT) {
++ /* If node has terminated, execute phase code will
++ * have already been unloaded in NODE_OnExit(). If the
++ * node is PAUSED, the execute phase is loaded, and it
++ * is now ok to unload it. If the node is running, we
++ * will unload the execute phase only after deleting
++ * the node. */
++ if (state == NODE_PAUSED && hNode->fLoaded &&
++ hNode->fPhaseSplit) {
++ /* Ok to unload execute code as long as node
++ * is not * running */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
++ hNldrNode, NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ NODE_SetState(hNode, NODE_DONE);
++ }
++ /* Load delete phase code if not loaded or if haven't
++ * * unloaded EXECUTE phase */
++ if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
++ hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->
++ hNldrNode, NLDR_DELETE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to "
++ "load delete code: 0x%x\n",
++ status);
++ }
++ }
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Unblock a thread trying to terminate the node */
++ (void)SYNC_SetEvent(hNode->hSyncDone);
++ if (procId == DSP_UNIT) {
++ /* ulDeleteFxn = address of node's delete
++ * function */
++ status = GetFxnAddress(hNode, &ulDeleteFxn,
++ DELETEPHASE);
++ } else if (procId == IVA_UNIT)
++ ulDeleteFxn = (u32)hNode->nodeEnv;
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Delete: proc Status "
++ "0x%x\n", procStatus.iState);
++ if (procStatus.iState != PROC_ERROR) {
++ status = DISP_NodeDelete(hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSDELETENODE],
++ ulDeleteFxn, hNode->nodeEnv);
++ } else
++ NODE_SetState(hNode, NODE_DONE);
++
++ /* Unload execute, if not unloaded, and delete
++ * function */
++ if (state == NODE_RUNNING &&
++ hNode->fPhaseSplit) {
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_EXECUTE);
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload execute code: 0x%x\n",
++ status1);
++ }
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_DELETE);
++ hNode->fLoaded = false;
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload delete code: 0x%x\n",
++ status1);
++ }
++ }
++ }
++ }
++ /* Free host side resources even if a failure occurred */
++ /* Remove node from hNodeMgr->nodeList */
++ LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
++ hNodeMgr->uNumNodes--;
++ /* Decrement count of nodes created on DSP */
++ if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
++ (hNode->nodeEnv != (u32) NULL)))
++ hNodeMgr->uNumCreated--;
++ /* Free host-side resources allocated by NODE_Create()
++ * DeleteNode() fails if SM buffers not freed by client! */
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++ DRV_GetProcContext(0, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, hNode, 0);
++ if (pCtxt == NULL)
++ goto func_cont;
++ if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
++ DRV_ProcNodeUpdateStatus(nodeRes, false);
++ }
++#endif
++func_cont:
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
++ DeleteNode(hNode);
++#ifndef RES_CLEANUP_DISABLE
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
++ if (pCtxt != NULL)
++ DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
++#endif
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ */
++DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
++ hNodeMgr);
++ DeleteNodeMgr(hNodeMgr);
++
++ return status;
++}
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate currently allocated nodes.
++ */
++DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ struct NODE_OBJECT *hNode;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
++ "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
++ "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ if (hNodeMgr->uNumNodes > uNodeTabSize) {
++ *puAllocated = hNodeMgr->uNumNodes;
++ *puNumNodes = 0;
++ status = DSP_ESIZE;
++ } else {
++ hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
++ nodeList);
++ for (i = 0; i < hNodeMgr->uNumNodes; i++) {
++ DBC_Assert(MEM_IsValidHandle(hNode,
++ NODE_SIGNATURE));
++ aNodeTab[i] = hNode;
++ hNode = (struct NODE_OBJECT *)LST_Next
++ (hNodeMgr->nodeList,
++ (struct LST_ELEM *)hNode);
++ }
++ *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
++ }
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ return status;
++}
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ */
++void NODE_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "Entered NODE_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Frees the message buffer.
++ */
++DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR *pAttr)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++ DBC_Require(pNode != NULL);
++ DBC_Require(pNode->hXlator != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
++ "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId == DSP_UNIT) {
++ if (DSP_SUCCEEDED(status)) {
++ if (pAttr == NULL) {
++ /* set defaults */
++ pAttr = &NODE_DFLTBUFATTRS;
++ }
++ /* Node supports single SM segment only */
++ if (pAttr->uSegment != 1)
++ status = DSP_EBADSEGID;
++
++ /* pBuffer is clients Va. */
++ status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++ else
++ status = DSP_SOK;
++
++ }
++ } else {
++ DBC_Assert(NULL); /* BUG */
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ */
++DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
++{
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttr != NULL);
++ DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
++ "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
++ uAttrSize);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ /* Enter hNodeMgr critical section (since we're accessing
++ * data that could be changed by NODE_ChangePriority() and
++ * NODE_Connect(). */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
++ /* DSP_NODEATTRIN */
++ pAttr->inNodeAttrIn.cbStruct =
++ sizeof(struct DSP_NODEATTRIN);
++ pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
++ pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
++ pAttr->inNodeAttrIn.uHeapSize =
++ hNode->createArgs.asa.taskArgs.uHeapSize;
++ pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
++ hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
++ pAttr->uInputs = hNode->uNumGPPInputs;
++ pAttr->uOutputs = hNode->uNumGPPOutputs;
++ /* DSP_NODEINFO */
++ GetNodeInfo(hNode, &(pAttr->iNodeInfo));
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node.
++ */
++DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ OUT u32 *pulId)
++{
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_EVALUE;
++ DBC_Require(cRefs > 0);
++ DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
++ DBC_Require(pulId != NULL);
++ GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
++ "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
++ uIndex, pulId);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ return status;
++ }
++ if (uDir == DSP_TONODE) {
++ if (uIndex < MaxInputs(hNode)) {
++ if (hNode->inputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->inputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ } else {
++ DBC_Assert(uDir == DSP_FROMNODE);
++ if (uIndex < MaxOutputs(hNode)) {
++ if (hNode->outputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->outputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP.
++ */
++DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
++ u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to get the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_GetMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ goto func_end;
++ }
++ /* This function will block unless a message is available. Since
++ * DSPNode_RegisterNotify() allows notification when a message
++ * is available, the system can be designed so that
++ * DSPNode_GetMessage() is only called when a message is
++ * available. */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
++ /* Check if message contains SM descriptor */
++ if (DSP_FAILED(status) || !(pMsg->dwCmd & DSP_RMSBUFDESC))
++ goto func_end;
++
++ /* Translate DSP byte addr to GPP Va. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
++ CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
++ CMM_PA2VA);
++ if (pTmpBuf != NULL) {
++ /* Adjust SM size in msg */
++ pMsg->dwArg1 = (u32) pTmpBuf;
++ pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
++ "Failed SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
++ "SM Pa/Pa translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_GetNldrObj ========
++ */
++DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ struct NLDR_OBJECT **phNldrObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_MGR *pNodeMgr = hNodeMgr;
++ DBC_Require(phNldrObj != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Entered NODE_GetNldrObj, hNodeMgr: "
++ "0x%x\n\tphNldrObj: 0x%x\n", hNodeMgr, phNldrObj);
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phNldrObj = pNodeMgr->hNldr;
++
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Exit NODE_GetNldrObj: status 0x%x\n\t"
++ "phNldrObj: 0x%x\n", status, *phNldrObj);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
++ (*phNldrObj == NULL)));
++ return status;
++}
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Returns the Stream manager.
++ */
++DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
++
++ return status;
++}
++
++/*
++ * ======== NODE_GetLoadType ========
++ */
++enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
++{
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetLoadType: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return -1;
++ } else
++ return hNode->dcdProps.objData.nodeObj.usLoadType;
++}
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Returns the timeout value for this node.
++ */
++u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetTimeout: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return 0;
++ } else
++ return hNode->uTimeout;
++}
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Returns the node type.
++ */
++enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
++{
++ enum NODE_TYPE nodeType;
++
++ if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
++ nodeType = NODE_GPP;
++ else {
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ nodeType = -1;
++ else
++ nodeType = hNode->nType;
++ }
++ return nodeType;
++}
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ */
++bool NODE_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NODE_debugMask.flags);
++ GT_create(&NODE_debugMask, "NO"); /* "NO" for NOde */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node.
++ */
++void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
++{
++ DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ /* Set node state to done */
++ NODE_SetState(hNode, NODE_DONE);
++ hNode->nExitStatus = nStatus;
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ }
++ /* Unblock call to NODE_Terminate */
++ (void) SYNC_SetEvent(hNode->hSyncDone);
++ /* Notify clients */
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++}
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ */
++DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++
++ }
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (procId == IVA_UNIT)
++ status = DSP_ENOTIMPL;
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ /* Check node state */
++ if (state != NODE_RUNNING)
++ status = DSP_EWRONGSTATE;
++
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Pause: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, NODE_SUSPENDEDPRI);
++ }
++
++ /* Update state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_PAUSED);
++ } else {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_Pause: Failed. hNode:"
++ " 0x%x\n", hNode);
++ }
++ }
++ /* End of SYNC_EnterCS */
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node. This
++ * function will block until the message stream can accommodate the
++ * message, or a timeout occurs.
++ */
++DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_MSG newMsg;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_PutMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in bad state then don't attempt sending the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_PutMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state. Can't send messages to a node after
++ * we've sent the RMS_EXIT command. There is still the
++ * possibility that NODE_Terminate can be called after we've
++ * checked the state. Could add another SYNC object to
++ * prevent this (can't use hNodeMgr->hSync, since we don't
++ * want to block other NODE functions). However, the node may
++ * still exit on its own, before this message is sent. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state == NODE_TERMINATING || state == NODE_DONE)
++ status = DSP_EWRONGSTATE;
++
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* assign pMsg values to new msg */
++ newMsg = *pMsg;
++ /* Now, check if message contains a SM buffer descriptor */
++ if (pMsg->dwCmd & DSP_RMSBUFDESC) {
++ /* Translate GPP Va to DSP physical buf Ptr. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)newMsg.dwArg1, CMM_VA2DSPPA);
++ if (pTmpBuf != NULL) {
++ /* got translation, convert to MAUs in msg */
++ if (hNode->hNodeMgr->uDSPWordSize != 0) {
++ newMsg.dwArg1 =
++ (u32)pTmpBuf /
++ hNode->hNodeMgr->uDSPWordSize;
++ /* MAUs */
++ newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: "
++ "uDSPWordSize is zero!\n");
++ status = DSP_EFAIL; /* bad DSPWordSize */
++ }
++ } else { /* failed to translate buffer address */
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: Failed to"
++ " translate SM address\n");
++ status = DSP_ETRANSLATE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
++ &newMsg, uTimeout);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ */
++DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_RegisterNotify: hNode: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hNode, uEventMask, uNotifyType, hNotification);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Check if event mask is a valid node related event */
++ if (uEventMask & ~(DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ /* Only one Notification can be registered at a
++ * time - Limitation */
++ if (uEventMask == (DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uEventMask == DSP_NODESTATECHANGE) {
++ status = NTFY_Register(hNode->hNtfy, hNotification,
++ uEventMask & DSP_NODESTATECHANGE, uNotifyType);
++ } else {
++ /* Send Message part of event mask to MSG */
++ pIntfFxns = hNode->hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgRegisterNotify)
++ (hNode->hMsgQueue,
++ uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
++ hNotification);
++ }
++
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via NODE_NodePause()) on the DSP. Load the
++ * node's execute function if necessary.
++ */
++DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ u32 ulExecuteFxn;
++ u32 ulFxnAddr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to run the node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Run:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state != NODE_CREATED && state != NODE_PAUSED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
++ goto func_cont1;
++
++ if (state == NODE_CREATED) {
++ /* If node's execute function is not loaded, load it */
++ if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Run: failed to load "
++ "execute code:0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get address of node's execute function */
++ if (procId == IVA_UNIT)
++ ulExecuteFxn = (u32) hNode->nodeEnv;
++ else {
++ status = GetFxnAddress(hNode, &ulExecuteFxn,
++ EXECUTEPHASE);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
++ status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
++ ulExecuteFxn, hNode->nodeEnv);
++ }
++ } else if (state == NODE_PAUSED) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
++ status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
++ ulFxnAddr, hNode->nodeEnv,
++ NODE_GetPriority(hNode));
++ } else {
++ /* We should never get here */
++ DBC_Assert(false);
++ }
++func_cont1:
++ /* Update node state. */
++ if (DSP_SUCCEEDED(status))
++ NODE_SetState(hNode, NODE_RUNNING);
++ else /* Set state back to previous value */
++ NODE_SetState(hNode, state);
++ /*End of SYNC_EnterCS */
++ /* Exit critical section */
++func_cont:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute phase
++ * function.
++ */
++DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ struct DSP_MSG msg, killmsg;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId, killTimeOut;
++ struct DEH_MGR *hDehMgr;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStatus != NULL);
++
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: hNode: 0x%x\n", hNode);
++
++ if (pNode->hProcessor == NULL) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Terminate: pNode->hProcessor = 0x%x\n",
++ pNode->hProcessor);
++ goto func_end;
++ }
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType !=
++ NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ /* Set the exit status if node terminated on
++ * its own. */
++ if (state == NODE_DONE)
++ *pStatus = hNode->nExitStatus;
++
++ } else {
++ NODE_SetState(hNode, NODE_TERMINATING);
++ }
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Send exit message. Do not change state to NODE_DONE
++ * here. That will be done in callback.
++ */
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
++
++ status = PROC_GetState(pNode->hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_cont;
++ /* If processor is in error state then don't attempt to send
++ * A kill task command */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Terminate:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++
++ msg.dwCmd = RMS_EXIT;
++ msg.dwArg1 = hNode->nodeEnv;
++ killmsg.dwCmd = RMS_KILLTASK;
++ killmsg.dwArg1 = hNode->nodeEnv;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++
++ if (hNode->uTimeout > MAXTIMEOUT)
++ killTimeOut = MAXTIMEOUT;
++ else
++ killTimeOut = (hNode->uTimeout)*2;
++
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait on synchronization object that will be
++ * posted in the callback on receiving RMS_EXIT
++ * message, or by NODE_Delete. Check for valid hNode,
++ * in case posted by NODE_Delete(). */
++ status = SYNC_WaitOnEvent(hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_ETIMEOUT) {
++ status = (*pIntfFxns->pfnMsgPut)
++ (hNode->hMsgQueue, &killmsg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnEvent
++ (hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ /* Here it goes the part
++ * of the simulation of
++ * the DSP exception */
++ DEV_GetDehMgr(hNodeMgr->
++ hDevObject, &hDehMgr);
++ if (hDehMgr) {
++ (*pIntfFxns->
++ pfnDehNotify)(hDehMgr,
++ DSP_SYSERROR,
++ DSP_EXCEPTIONABORT);
++ status = DSP_EFAIL;
++ }
++ } else
++ status = DSP_SOK;
++ }
++ } else
++ status = DSP_EFAIL;
++ } else /* Convert SYNC status to DSP status */
++ status = DSP_SOK;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Enter CS before getting exit status, in case node was
++ * deleted. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ /* Make sure node wasn't deleted while we blocked */
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EFAIL;
++ } else {
++ *pStatus = hNode->nExitStatus;
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: env = 0x%x "
++ "succeeded.\n", hNode->nodeEnv);
++ }
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ } /*End of SYNC_EnterCS */
++func_end:
++ return status;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
++ */
++static void DeleteNode(struct NODE_OBJECT *hNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct CMM_XLATOROBJECT *hXlator;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 i;
++ enum NODE_TYPE nodeType;
++ struct STREAM stream;
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject =
++ (struct PROC_OBJECT *)hNode->hProcessor;
++#endif
++ DSP_STATUS status;
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ hNodeMgr = hNode->hNodeMgr;
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ return;
++ hXlator = hNode->hXlator;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_DEVICE) {
++ msgArgs = hNode->createArgs.asa.msgArgs;
++ if (msgArgs.pData)
++ MEM_Free(msgArgs.pData);
++
++ /* Free MSG queue */
++ if (hNode->hMsgQueue) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
++ hNode->hMsgQueue = NULL;
++
++ }
++ if (hNode->hSyncDone)
++ (void) SYNC_CloseEvent(hNode->hSyncDone);
++
++ /* Free all stream info */
++ if (hNode->inputs) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ stream = hNode->inputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->inputs);
++ hNode->inputs = NULL;
++ }
++ if (hNode->outputs) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ stream = hNode->outputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->outputs);
++ hNode->outputs = NULL;
++ }
++ taskArgs = hNode->createArgs.asa.taskArgs;
++ if (taskArgs.strmInDef) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ if (taskArgs.strmInDef[i].szDevice) {
++ MEM_Free(taskArgs.strmInDef[i].
++ szDevice);
++ taskArgs.strmInDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmInDef);
++ taskArgs.strmInDef = NULL;
++ }
++ if (taskArgs.strmOutDef) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ if (taskArgs.strmOutDef[i].szDevice) {
++ MEM_Free(taskArgs.strmOutDef[i].
++ szDevice);
++ taskArgs.strmOutDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmOutDef);
++ taskArgs.strmOutDef = NULL;
++ }
++ if (taskArgs.uDSPHeapResAddr) {
++ status = PROC_UnMap(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap failed."
++ " Status = 0x%x\n", (u32)status);
++ }
++ status = PROC_UnReserveMemory(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapResAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "failed. Status = 0x%x\n",
++ (u32)status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ }
++ }
++ if (nodeType != NODE_MESSAGE) {
++ if (hNode->streamConnect) {
++ MEM_Free(hNode->streamConnect);
++ hNode->streamConnect = NULL;
++ }
++ }
++ if (hNode->pstrDevName) {
++ MEM_Free(hNode->pstrDevName);
++ hNode->pstrDevName = NULL;
++ }
++
++ if (hNode->hNtfy) {
++ NTFY_Delete(hNode->hNtfy);
++ hNode->hNtfy = NULL;
++ }
++
++ /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
++ if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrIAlgName) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
++ hNode->dcdProps.objData.nodeObj.pstrIAlgName = NULL;
++ }
++
++ /* Free all SM address translator resources */
++ if (hXlator) {
++ (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
++ hXlator = NULL;
++ }
++
++ if (hNode->hNldrNode) {
++ hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
++ hNode->hNldrNode = NULL;
++ }
++
++ MEM_FreeObject(hNode);
++ hNode = NULL;
++}
++
++/*
++ * ======== DeleteNodeMgr ========
++ * Purpose:
++ * Frees the node manager.
++ */
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
++{
++ struct NODE_OBJECT *hNode;
++
++ if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
++ /* Free resources */
++ if (hNodeMgr->hDcdMgr)
++ DCD_DestroyManager(hNodeMgr->hDcdMgr);
++
++ /* Remove any elements remaining in lists */
++ if (hNodeMgr->nodeList) {
++ while ((hNode =
++ (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
++ nodeList)))
++ DeleteNode(hNode);
++
++ DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
++ LST_Delete(hNodeMgr->nodeList);
++ }
++ if (hNodeMgr->hNtfy)
++ NTFY_Delete(hNodeMgr->hNtfy);
++
++ if (hNodeMgr->pipeMap)
++ GB_delete(hNodeMgr->pipeMap);
++
++ if (hNodeMgr->pipeDoneMap)
++ GB_delete(hNodeMgr->pipeDoneMap);
++
++ if (hNodeMgr->chnlMap)
++ GB_delete(hNodeMgr->chnlMap);
++
++ if (hNodeMgr->dmaChnlMap)
++ GB_delete(hNodeMgr->dmaChnlMap);
++
++ if (hNodeMgr->zChnlMap)
++ GB_delete(hNodeMgr->zChnlMap);
++
++ if (hNodeMgr->hDisp)
++ DISP_Delete(hNodeMgr->hDisp);
++
++ if (hNodeMgr->hSync)
++ SYNC_DeleteCS(hNodeMgr->hSync);
++
++ if (hNodeMgr->hStrmMgr)
++ STRM_Delete(hNodeMgr->hStrmMgr);
++
++ /* Delete the loader */
++ if (hNodeMgr->hNldr)
++ hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
++
++ if (hNodeMgr->fLoaderInit)
++ hNodeMgr->nldrFxns.pfnExit();
++
++ MEM_FreeObject(hNodeMgr);
++ }
++}
++
++/*
++ * ======== FillStreamConnect ========
++ * Purpose:
++ * Fills stream information.
++ */
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream1, u32 uStream2)
++{
++ u32 uStrmIndex;
++ struct DSP_STREAMCONNECT *pStrm1 = NULL;
++ struct DSP_STREAMCONNECT *pStrm2 = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++
++ if (node1Type != NODE_DEVICE) {
++ uStrmIndex = hNode1->uNumInputs +
++ hNode1->uNumOutputs - 1;
++ pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
++ pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm1->uThisNodeStreamIndex = uStream1;
++ }
++
++ if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++ /* NODE == > NODE */
++ if (node1Type != NODE_DEVICE) {
++ pStrm1->hConnectedNode = hNode2;
++ pStrm1->uiConnectedNodeID = hNode2->nodeId;
++ pStrm1->uConnectedNodeStreamIndex = uStream2;
++ pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
++ }
++ if (node2Type != NODE_DEVICE) {
++ uStrmIndex = hNode2->uNumInputs +
++ hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct =
++ sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->hConnectedNode = hNode1;
++ pStrm2->uiConnectedNodeID = hNode1->nodeId;
++ pStrm2->uConnectedNodeStreamIndex = uStream1;
++ pStrm2->lType = CONNECTTYPE_NODEINPUT;
++ }
++ } else if (node1Type != NODE_DEVICE)
++ pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
++ } else {
++ /* GPP == > NODE */
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->lType = CONNECTTYPE_GPPINPUT;
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * Purpose:
++ * Fills Stream attributes.
++ */
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs)
++{
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++
++ if (pAttrs != NULL) {
++ pstrmDef->uNumBufs = pAttrs->uNumBufs;
++ pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = pAttrs->uSegid;
++ pstrmDef->uAlignment = pAttrs->uAlignment;
++ pstrmDef->uTimeout = pAttrs->uTimeout;
++ } else {
++ pstrmDef->uNumBufs = DEFAULTNBUFS;
++ pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = DEFAULTSEGID;
++ pstrmDef->uAlignment = DEFAULTALIGNMENT;
++ pstrmDef->uTimeout = DEFAULTTIMEOUT;
++ }
++}
++
++/*
++ * ======== FreeStream ========
++ * Purpose:
++ * Updates the channel mask and frees the pipe id.
++ */
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
++{
++ /* Free up the pipe id unless other node has not yet been deleted. */
++ if (stream.type == NODECONNECT) {
++ if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
++ /* The other node has already been deleted */
++ GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
++ GB_clear(hNodeMgr->pipeMap, stream.devId);
++ } else {
++ /* The other node has not been deleted yet */
++ GB_set(hNodeMgr->pipeDoneMap, stream.devId);
++ }
++ } else if (stream.type == HOSTCONNECT) {
++ if (stream.devId < hNodeMgr->ulNumChnls) {
++ GB_clear(hNodeMgr->chnlMap, stream.devId);
++ } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
++ /* dsp-dma */
++ GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
++ (1 * hNodeMgr->ulNumChnls));
++ } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
++ /* zero-copy */
++ GB_clear(hNodeMgr->zChnlMap, stream.devId -
++ (2 * hNodeMgr->ulNumChnls));
++ }
++ }
++}
++
++/*
++ * ======== GetFxnAddress ========
++ * Purpose:
++ * Retrieves the address for create, execute or delete phase for a node.
++ */
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase)
++{
++ char *pstrFxnName = NULL;
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
++ NODE_GetType(hNode) == NODE_DAISSOCKET ||
++ NODE_GetType(hNode) == NODE_MESSAGE);
++
++ switch (uPhase) {
++ case CREATEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrCreatePhaseFxn;
++ break;
++ case EXECUTEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrExecutePhaseFxn;
++ break;
++ case DELETEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrDeletePhaseFxn;
++ break;
++ default:
++ /* Should never get here */
++ DBC_Assert(false);
++ break;
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
++ pulFxnAddr);
++
++ return status;
++}
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Retrieves the node information.
++ */
++void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
++{
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(pNodeInfo != NULL);
++
++ pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
++ pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
++ ndbProps;
++ pNodeInfo->uExecutionPriority = hNode->nPriority;
++ pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
++ pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
++ pNodeInfo->uNodeEnv = hNode->nodeEnv;
++
++ pNodeInfo->nsExecutionState = NODE_GetState(hNode);
++
++ /* Copy stream connect data */
++ for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
++ pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
++
++}
++
++/*
++ * ======== GetNodeProps ========
++ * Purpose:
++ * Retrieve node properties.
++ */
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps)
++{
++ u32 uLen;
++ struct NODE_MSGARGS *pMsgArgs;
++ struct NODE_TASKARGS *pTaskArgs;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
++ DSP_STATUS status = DSP_SOK;
++#ifdef DEBUG
++ char szUuid[MAXUUIDLEN];
++#endif
++
++ status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
++ DSP_DCDNODETYPE, pdcdProps);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNode->nType = nodeType = pndbProps->uNodeType;
++
++#ifdef DEBUG
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
++ MAXUUIDLEN);
++ DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
++#endif
++
++ /* Fill in message args that come from NDB */
++ if (nodeType != NODE_DEVICE) {
++ pMsgArgs = &(hNode->createArgs.asa.msgArgs);
++ pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
++ pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
++ uMsgNotifyType;
++ pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Max Number of Messages: 0x%x\n",
++ pMsgArgs->uMaxMessages);
++#endif
++ } else {
++ /* Copy device name */
++ DBC_Require(pndbProps->acName);
++ uLen = strlen(pndbProps->acName);
++ DBC_Assert(uLen < MAXDEVNAMELEN);
++ hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (hNode->pstrDevName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(hNode->pstrDevName,
++ pndbProps->acName, uLen);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args that come from NDB */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ pTaskArgs = &(hNode->createArgs.asa.taskArgs);
++ pTaskArgs->nPriority = pndbProps->iPriority;
++ pTaskArgs->uStackSize = pndbProps->uStackSize;
++ pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
++ pTaskArgs->uStackSeg = pndbProps->uStackSeg;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Priority: 0x%x\n" "** (node) Stack"
++ " Size: 0x%x words\n" "** (node) System Stack"
++ " Size: 0x%x words\n" "** (node) Stack"
++ " Segment: 0x%x\n\n",
++ "** (node) profile count : 0x%x \n \n",
++ pTaskArgs->nPriority, pTaskArgs->uStackSize,
++ pTaskArgs->uSysStackSize,
++ pTaskArgs->uStackSeg,
++ pndbProps->uCountProfiles);
++#endif
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== GetProcProps ========
++ * Purpose:
++ * Retrieve the processor properties.
++ */
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ struct CFG_DEVNODE *hDevNode;
++ struct CFG_HOSTRES hostRes;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
++ hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
++ hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
++
++ /*
++ * PROC will add an API to get DSP_PROCESSORINFO.
++ * Fill in default values for now.
++ */
++ /* TODO -- Instead of hard coding, take from registry */
++ hNodeMgr->procFamily = 6000;
++ hNodeMgr->procType = 6410;
++ hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
++ hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
++ hNodeMgr->uDSPWordSize = DSPWORDSIZE;
++ hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
++ hNodeMgr->uDSPMauSize = 1;
++
++ }
++ return status;
++}
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node UUID properties from DCD/DOF file.
++ */
++DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS *pNodeProps)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct DEV_OBJECT *hDevObject;
++ DSP_STATUS status = DSP_SOK;
++ struct DCD_NODEPROPS dcdNodeProps;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ if (hProcessor == NULL || pNodeId == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetUUIDProps: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetUUIDProps: " "\thProcessor: "
++ "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
++ pNodeId, pNodeProps);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status) && hDevObject != NULL) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ }
++
++ /*
++ * Enter the critical section. This is needed because
++ * DCD_GetObjectDef will ultimately end up calling DBLL_open/close,
++ * which needs to be protected in order to not corrupt the zlib manager
++ * (COD).
++ */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ dcdNodeProps.pstrCreatePhaseFxn = NULL;
++ dcdNodeProps.pstrExecutePhaseFxn = NULL;
++ dcdNodeProps.pstrDeletePhaseFxn = NULL;
++ dcdNodeProps.pstrIAlgName = NULL;
++
++ status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
++ (struct DSP_UUID *) pNodeId,
++ DSP_DCDNODETYPE,
++ (struct DCD_GENERICOBJ *) &dcdNodeProps);
++ if (DSP_SUCCEEDED(status)) {
++ *pNodeProps = dcdNodeProps.ndbProps;
++ if (dcdNodeProps.pstrCreatePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
++
++ if (dcdNodeProps.pstrExecutePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
++
++ if (dcdNodeProps.pstrDeletePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
++
++ if (dcdNodeProps.pstrIAlgName)
++ MEM_Free(dcdNodeProps.pstrIAlgName);
++ }
++ /* Leave the critical section, we're done. */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== GetRMSFxns ========
++ * Purpose:
++ * Retrieve the RMS functions.
++ */
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
++{
++ s32 i;
++ struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
++ DSP_STATUS status = DSP_SOK;
++
++ static char *pszFxns[NUMRMSFXNS] = {
++ "RMS_queryServer", /* RMSQUERYSERVER */
++ "RMS_configureServer", /* RMSCONFIGURESERVER */
++ "RMS_createNode", /* RMSCREATENODE */
++ "RMS_executeNode", /* RMSEXECUTENODE */
++ "RMS_deleteNode", /* RMSDELETENODE */
++ "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
++ "RMS_readMemory", /* RMSREADMEMORY */
++ "RMS_writeMemory", /* RMSWRITEMEMORY */
++ "RMS_copy", /* RMSCOPY */
++ };
++
++ for (i = 0; i < NUMRMSFXNS; i++) {
++ status = DEV_GetSymbol(hDev, pszFxns[i],
++ &(hNodeMgr->ulFxnAddrs[i]));
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ /*
++ * May be loaded dynamically (in the future),
++ * but return an error for now.
++ */
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "RMS function: %s "
++ "currently not loaded\n", pszFxns[i]);
++ } else {
++ GT_2trace(NODE_debugMask, GT_6CLASS,
++ "GetRMSFxns: Symbol not "
++ "found: %s\tstatus = 0x%x\n",
++ pszFxns[i], status);
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== Ovly ========
++ * Purpose:
++ * Called during overlay.Sends command to RMS to copy a block of data.
++ */
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u32 ulBytes = 0;
++ u32 ulSize;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
++ ulTimeout = hNode->uTimeout;
++
++ /* Call new MemCopy function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
++ ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
++
++ if (DSP_SUCCEEDED(status))
++ ulBytes = ulNumBytes;
++
++ return ulBytes;
++}
++
++/*
++ * ======== Write ========
++ */
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u16 memType;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulTimeout = hNode->uTimeout;
++ memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
++
++ /* Call new MemWrite function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
++ ulNumBytes, memType);
++
++ return ulNumBytes;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
+new file mode 100644
+index 0000000..332e01a
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/proc.c
+@@ -0,0 +1,1985 @@
++/*
++ * proc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.c ========
++ * Description:
++ * Processor interface at the driver level.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Ctrl
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_GetResourceInfo
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace
++ * PROC_Init
++ * PROC_Load
++ * PROC_Map
++ * PROC_NotifyClients
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ * PROC_InvalidateMemory
++
++ *! Revision History
++ *! ======== ========
++ *! 04-Apr-2007 sh Added PROC_InvalidateMemory API
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! Used MEM_FlushCache instead of OS specific API
++ *! Integrated Alan's code review updates
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 08-Mar-2004 vp Added g_pszLastCoff member to PROC_OBJECT.
++ *! This is required for multiprocessor environment.
++ *! 09-Feb-2004 vp Added PROC_GetProcessorID function
++ *! 22-Apr-2003 vp Fixed issue with the string that stores coff file name
++ *! 03-Apr-2003 sb Fix DEH deregistering bug
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in PROC_Start function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
++ *! 14-May-2002 sg Use CSL_Atoi() instead of atoi().
++ *! 13-May-2002 sg Propagate PWR return codes upwards.
++ *! 07-May-2002 sg Added check for, and call to PWR functions in PROC_Ctrl.
++ *! 02-May-2002 sg Added "nap" mode: put DSP to sleep once booted.
++ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
++ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
++ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
++ *! DEH module.
++ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
++ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
++ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
++ *! to facilitate the external loading.
++ *! 14-Aug-2001 ag DCD_AutoRegister() now called before IOOnLoaded() fxn.
++ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
++ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
++ *! error other than E_NOTIMPL.
++ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
++ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
++ *! if DEV_Create2 fails; ie, no non-RMS targets can be
++ *! loaded.
++ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
++ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
++ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
++ *! WMD_BRD_STOP is always followed by DEV_Destroy2.
++ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
++ *! different way.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! WMD fxns are checked for WSX_STATUS.
++ *! PROC_Attach does not alter the state of the BRD.
++ *! PROC_Run removed.
++ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
++ *! invalid
++ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
++ *! ver 0.8 API.
++ *! 06-Jul-2000 rr: Created.
++ */
++
++/* ------------------------------------ Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/procpriv.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/nldr.h>
++#include <dspbridge/rmm.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/wmdioctl.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/proc.h>
++#include <dspbridge/pwr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define PROC_SIGNATURE 0x434F5250 /* "PROC" (in reverse). */
++#define MAXCMDLINELEN 255
++#define PROC_ENVPROCID "PROC_ID=%d"
++#define MAXPROCIDLEN (8 + 5)
++#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
++#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
++#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
++
++extern char *iva_img;
++/* The PROC_OBJECT structure. */
++struct PROC_OBJECT {
++ struct LST_ELEM link; /* Link to next PROC_OBJECT */
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device this PROC represents */
++ u32 hProcess; /* Process owning this Processor */
++ struct MGR_OBJECT *hMgrObject; /* Manager Object Handle */
++ u32 uAttachCount; /* Processor attach count */
++ u32 uProcessor; /* Processor number */
++ u32 uTimeout; /* Time out count */
++ enum DSP_PROCSTATE sState; /* Processor state */
++ u32 ulUnit; /* DDSP unit number */
++ bool bIsAlreadyAttached; /*
++ * True if the Device below has
++ * GPP Client attached
++ */
++ struct NTFY_OBJECT *hNtfy; /* Manages notifications */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ char *g_pszLastCoff;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask PROC_DebugMask = { NULL, NULL }; /* WCD MGR Mask */
++#endif
++
++static u32 cRefs;
++
++struct SYNC_CSOBJECT *hProcLock; /* For critical sections */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
++static s32 GetEnvpCount(char **envp);
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar);
++
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object.
++ */
++DSP_STATUS
++PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++ struct PROC_OBJECT *pProcObject = NULL;
++ struct MGR_OBJECT *hMgrObject = NULL;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ u32 devType;
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phProcessor != NULL);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
++ "uProcessor: 0x%x\n\tpAttrIn: 0x%x\n\tphProcessor:"
++ "0x%x\n", uProcessor, pAttrIn, phProcessor);
++ /* Get the Driver and Manager Object Handles */
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
++ if (DSP_FAILED(status)) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: DSP_FAILED to get"
++ "the Manager Object.\n", status);
++ }
++ } else {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get the"
++ " DriverObject, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the Device Object */
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevObject, 0x%x!\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, &devType);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevType, 0x%x!\n", status);
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If we made it this far, create the Proceesor object: */
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ /* Fill out the Processor Object: */
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach:Out of memeory \n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ pProcObject->uProcessor = devType;
++ /* Get Caller Process and store it */
++ /* Return PID instead of process handle */
++ pProcObject->hProcess = current->pid;
++
++ if (pAttrIn)
++ pProcObject->uTimeout = pAttrIn->uTimeout;
++ else
++ pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
++
++ status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not"
++ " get the WMD Context.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not get"
++ " the DEV_ Interface fxns.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Create the Notification Object */
++ /* This is created with no event mask, no notify mask
++ * and no valid handle to the notification. They all get
++ * filled up when PROC_RegisterNotify is called */
++ status = NTFY_Create(&pProcObject->hNtfy);
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert the Processor Object into the DEV List.
++ * Return handle to this Processor Object:
++ * Find out if the Device is already attached to a
++ * Processor. If so, return AlreadyAttached status */
++ LST_InitElem(&pProcObject->link);
++ status = DEV_InsertProcObject(pProcObject->hDevObject,
++ (u32)pProcObject,
++ &pProcObject->bIsAlreadyAttached);
++ if (DSP_SUCCEEDED(status)) {
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_SALREADYATTACHED;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Already Attached!\n");
++ }
++ } else {
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ MEM_FreeObject(pProcObject);
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to insert "
++ "Proc Object into DEV, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phProcessor = (DSP_HPROCESSOR)pProcObject;
++ (void)PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORATTACH);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Attach Success!\n");
++ }
++ } else {
++ /* Don't leak memory if DSP_FAILED */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: Could not allocate "
++ "storage for notification \n");
++ MEM_FreeObject(pProcObject);
++ }
++func_end:
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDRVObject,
++ &pPctxt, NULL, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext((struct DRV_OBJECT *)hDRVObject, &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++ }
++func_cont:
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL)
++ pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
++
++ }
++#endif
++ DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
++ (status == DSP_SALREADYATTACHED &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
++ "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
++
++ return status;
++}
++
++static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject,
++ u32 size, char *execFile)
++{
++ s32 devType;
++ s32 len;
++
++ DEV_GetDevType(hDevObject, (u32 *) &devType);
++ if (devType == DSP_UNIT) {
++ return CFG_GetExecFile(hDevNode, size, execFile);
++ } else if (devType == IVA_UNIT) {
++ if (iva_img) {
++ len = strlen(iva_img);
++ strncpy(execFile, iva_img, len + 1);
++ return DSP_SOK;
++ }
++ }
++ return DSP_EFILE;
++}
++
++/*
++ * ======== PROC_AutoStart ======== =
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject: Handle to the Device
++ * Returns:
++ * DSP_SOK: On Successful Loading
++ * DSP_EFAIL General Failure
++ * Requires:
++ * hDevObject != NULL
++ * Ensures:
++ */
++DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ u32 dwAutoStart = 0; /* autostart flag */
++ struct PROC_OBJECT *pProcObject;
++ struct PROC_OBJECT *hProcObject;
++ char szExecFile[MAXCMDLINELEN];
++ char *argv[2];
++ struct MGR_OBJECT *hMgrObject = NULL;
++ s32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevNode != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_AutoStart, args:\n\t"
++ "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
++ /* Create a Dummy PROC Object */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to "
++ "Get MGR Object\n");
++ goto func_end;
++ }
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED "
++ "to Create a dummy Processor\n");
++ goto func_end;
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ hProcObject = pProcObject;
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ &pProcObject->pIntfFxns))) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed "
++ "to get WMD Context \n");
++ }
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed to "
++ "get IntFxns \n");
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Stop the Device, put it into standby mode */
++ status = PROC_Stop(hProcObject);
++ if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
++ !dwAutoStart) {
++ status = DSP_EFAIL;
++ /* DSP_FAILED to Get s32 Fxn or Wmd Context */
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
++ "CFG_GetAutoStart DSP_FAILED \n");
++ goto func_cont;
++ }
++ /* Get the default executable for this board... */
++ DEV_GetDevType(hDevObject, (u32 *)&devType);
++ pProcObject->uProcessor = devType;
++ if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
++ sizeof(szExecFile), szExecFile))) {
++ argv[0] = szExecFile;
++ argv[1] = NULL;
++ /* ...and try to load it: */
++ status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Start(hProcObject);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_AutoStart: Processor started "
++ "running\n");
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED To "
++ "Start \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to Load\n");
++ }
++ } else {
++ status = DSP_EFILE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
++ "No Exec file found \n");
++ }
++func_cont:
++ MEM_FreeObject(hProcObject);
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_AutoStart, status:0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the
++ * DSP processor.
++ *
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ * Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
++ * Operation. arg can be null.
++ */
++DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
++ IN struct DSP_CBDATA *arg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = hProcessor;
++ u32 timeout = 0;
++
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_Ctrl, args:\n\thProcessor:"
++ " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* intercept PWR deep sleep command */
++ if (dwCmd == WMDIOCTL_DEEPSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR emergency sleep command */
++ else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
++ } else if (dwCmd == PWR_DEEPSLEEP) {
++ /* timeout = arg->cbData; */
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR wake commands */
++ else if (dwCmd == WMDIOCTL_WAKEUP) {
++ timeout = arg->cbData;
++ status = PWR_WakeDSP(timeout);
++ } else if (dwCmd == PWR_WAKEUP) {
++ /* timeout = arg->cbData; */
++ status = PWR_WakeDSP(timeout);
++ } else
++ if (DSP_SUCCEEDED
++ ((*pProcObject->pIntfFxns->pfnDevCntrl)
++ (pProcObject->hWmdContext, dwCmd, arg))) {
++ status = DSP_SOK;
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: Failed \n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Destroys the Processor Object. Removes the notification from the Dev
++ * List.
++ */
++DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* Notify the Client */
++ NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
++ /* Remove the notification memory */
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ if (pProcObject->g_pszLastCoff) {
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL) {
++ DRV_ProcFreeDMMRes(pPctxt);
++ pPctxt->hProcessor = NULL;
++ }
++ }
++#endif
++
++ /* Remove the Proc from the DEV List */
++ (void)DEV_RemoveProcObject(pProcObject->hDevObject,
++ (u32)pProcObject);
++ /* Free the Processor Object */
++ MEM_FreeObject(pProcObject);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Detach: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes allocated
++ * on a DSP processor.
++ */
++DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++
++ GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
++ hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr))) {
++ if (hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, aNodeTab,
++ uNodeTabSize,
++ puNumNodes,
++ puAllocated);
++ }
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
++ "InValid Processor Handle \n");
++ }
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
++ "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
++ puNumNodes, puAllocated, status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flush cache
++ */
++DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize, u32 ulFlags)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_FlushMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
++ hProcessor, pMpuAddr, ulSize, ulFlags);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates the memory specified
++ */
++DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_InvalidateMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
++ pMpuAddr, ulSize);
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_InvalidateMemory [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ */
++DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *pResourceInfo,
++ u32 uResourceInfoSize)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct NLDR_OBJECT *hNldr = NULL;
++ struct RMM_TargetObj *rmm = NULL;
++ struct IO_MGR *hIOMgr = NULL; /* IO manager handle */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pResourceInfo != NULL);
++ DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
++
++ GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
++ "hProcessor: 0x%x\n\tuResourceType: 0x%x\n\tpResourceInfo:"
++ " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
++ uResourceType, pResourceInfo, uResourceInfoSize);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetResourceInfo: InValid "
++ "Processor Handle \n");
++ goto func_end;
++ }
++ switch (uResourceType) {
++ case DSP_RESOURCE_DYNDARAM:
++ case DSP_RESOURCE_DYNSARAM:
++ case DSP_RESOURCE_DYNEXTERNAL:
++ case DSP_RESOURCE_DYNSRAM:
++ if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr)))
++ goto func_end;
++
++ if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
++ if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
++ DBC_Assert(rmm != NULL);
++ status = DSP_EVALUE;
++ if (RMM_stat(rmm,
++ (enum DSP_MEMTYPE)uResourceType,
++ (struct DSP_MEMSTAT *)&(pResourceInfo->
++ result.memStat)))
++ status = DSP_SOK;
++ }
++ }
++ break;
++ case DSP_RESOURCE_PROCLOAD:
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
++ (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
++ result.procLoadStat));
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Error in procLoadStat function 0x%x\n", status);
++ }
++ break;
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
++ "status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void PROC_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ if (hProcLock)
++ (void)SYNC_DeleteCS(hProcLock);
++
++ cRefs--;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Exit, ref count:0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== PROC_GetDevObject ========
++ * Purpose:
++ * Return the Dev Object handle for a given Processor.
++ *
++ */
++DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ *phDevObject = pProcObject->hDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject != NULL) ||
++ (DSP_FAILED(status) && *phDevObject == NULL));
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ */
++DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE *pProcStatus,
++ u32 uStateInfoSize)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ BRD_STATUS brdStatus;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pProcStatus != NULL);
++ DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
++ "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
++ " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* First, retrieve BRD state information */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &brdStatus))) {
++ switch (brdStatus) {
++ case BRD_STOPPED:
++ pProcStatus->iState = PROC_STOPPED;
++ break;
++ case BRD_DSP_HIBERNATION:
++ /* Fall through */
++ case BRD_RUNNING:
++ pProcStatus->iState = PROC_RUNNING;
++ break;
++ case BRD_LOADED:
++ pProcStatus->iState = PROC_LOADED;
++ break;
++ case BRD_ERROR:
++ pProcStatus->iState = PROC_ERROR;
++ break;
++ default:
++ pProcStatus->iState = 0xFF;
++ status = DSP_EFAIL;
++ break;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: General Failure"
++ " to read the PROC Status \n");
++ }
++ /* Next, retrieve error information, if any */
++ status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
++ if (DSP_SUCCEEDED(status) && hDehMgr) {
++ status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
++ (hDehMgr, &(pProcStatus->errInfo));
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed "
++ "retrieve exception info.\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed to "
++ "retrieve DEH handle.\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState:InValid Processor Handle \n");
++ }
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_GetState, results:\n\t"
++ "status: 0x%x\n\tpProcStatus: 0x%x\n", status,
++ pProcStatus->iState);
++ return status;
++}
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the current contents of the trace buffer, located on the
++ * Processor. Predefined symbols for the trace buffer must have been
++ * configured into the DSP executable.
++ * Details:
++ * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
++ * trace buffer, only. Treat it as an undocumented feature.
++ * This call is destructive, meaning the processor is placed in the monitor
++ * state as a result of this function.
++ */
++DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
++{
++ DSP_STATUS status;
++ status = DSP_ENOTIMPL;
++ return status;
++}
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each call
++ */
++bool PROC_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!PROC_DebugMask.flags);
++ GT_create(&PROC_DebugMask, "PR"); /* "PR" for Processor */
++
++ (void)SYNC_InitializeCS(&hProcLock);
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Init, ref count:0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ */
++DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
++ IN CONST char **aArgv, IN CONST char **aEnvp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct IO_MGR *hIOMgr; /* IO manager handle */
++ struct MSG_MGR *hMsgMgr;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ char *pargv0; /* temp argv[0] ptr */
++ char **newEnvp; /* Updated envp[] array. */
++ char szProcID[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
++ s32 cEnvp; /* Num elements in envp[]. */
++ s32 cNewEnvp; /* " " in newEnvp[] */
++ s32 nProcID = 0; /* Anticipate MP version. */
++ struct DCD_MANAGER *hDCDHandle;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 dwExtEnd;
++ u32 uProcId;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ struct timeval tv1;
++ struct timeval tv2;
++#endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(iArgc > 0);
++ DBC_Require(aArgv != NULL);
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv1);
++#endif
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
++ "hProcessor: 0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
++ /* Call the WMD_BRD_Load Fxn */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Invalid Processor Handle..\n");
++ goto func_end;
++ }
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_EATTACHED;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load Abort becuase a GPP "
++ "Client is already attached status 0x%x \n", status);
++ goto func_end;
++ }
++ if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
++ "DEV_GetCodMgr status 0x%x \n", status);
++ goto func_end;
++ }
++ status = PROC_Stop(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
++ status);
++ goto func_end;
++ }
++ /* Place the board in the monitor state. */
++ status = PROC_Monitor(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
++ status);
++ goto func_end;
++ }
++ /* Save ptr to original argv[0]. */
++ pargv0 = (char *)aArgv[0];
++ /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
++ cEnvp = GetEnvpCount((char **)aEnvp);
++ cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
++ newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
++ if (newEnvp) {
++ status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
++ nProcID);
++ if (status == -1) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
++ "Proc ID string overflow \n");
++ status = DSP_EFAIL;
++ } else {
++ newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
++ cNewEnvp, szProcID);
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Before proceeding with new load,
++ * check if a previously registered COFF
++ * exists.
++ * If yes, unregister nodes in previously
++ * registered COFF. If any error occurred,
++ * set previously registered COFF to NULL. */
++ if (pProcObject->g_pszLastCoff != NULL) {
++ status = DCD_AutoUnregister(hDCDHandle,
++ pProcObject->g_pszLastCoff);
++ /* Regardless of auto unregister status,
++ * free previously allocated
++ * memory. */
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++ }
++ /* On success, do COD_OpenBase() */
++ status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
++ COD_SYMB);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: COD_OpenBase "
++ "failed (0x%x)\n", status);
++ }
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ " PROC_Load:Out of Memory \n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto-register data base */
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto register nodes in specified COFF
++ * file. If registration did not fail,
++ * (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
++ * save the name of the COFF file for
++ * de-registration in the future. */
++ status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
++ if (status == DSP_EDCDNOAUTOREGISTER) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: No Auto "
++ "Register section. Proceeding..\n");
++ status = DSP_SOK;
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to "
++ "Auto Register..\n");
++ } else {
++ DBC_Assert(pProcObject->g_pszLastCoff == NULL);
++ /* Allocate memory for pszLastCoff */
++ pProcObject->g_pszLastCoff = MEM_Calloc(
++ (strlen((char *)aArgv[0]) + 1),
++ MEM_PAGED);
++ /* If memory allocated, save COFF file name*/
++ if (pProcObject->g_pszLastCoff) {
++ strncpy(pProcObject->g_pszLastCoff,
++ (char *)aArgv[0],
++ (strlen((char *)aArgv[0]) + 1));
++ }
++ }
++ }
++ }
++ /* Update shared memory address and size */
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the message manager. This must be done
++ * before calling the IOOnLoaded function. */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (!hMsgMgr) {
++ status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
++ (MSG_ONEXIT)NODE_OnExit);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
++ }
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK not to have a message manager */
++ status = DSP_SOK;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Device object's message manager */
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
++ if (status == DSP_ENOTIMPL) {
++ /* Ok not to implement this function */
++ status = DSP_SOK;
++ } else {
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to get shared "
++ "memory or message buffer address "
++ "from COFF status 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "MSG_Create status 0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Now, attempt to load an exec: */
++
++ /* Boost the OPP level to Maximum level supported by baseport*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP5]);
++#endif
++ status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
++ DEV_BrdWriteFxn,
++ pProcObject->hDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_OPENFAILED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Failure to Load the EXE\n");
++ }
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Could not parse the file\n");
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "COD_Load status 0x%x \n", status);
++ }
++ }
++ /* Requesting the lowest opp supported*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++#endif
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Processor status to loaded */
++ status = (*pProcObject->pIntfFxns->pfnBrdSetState)
++ (pProcObject->hWmdContext, BRD_LOADED);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_LOADED;
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load, pfnBrdSetState "
++ "failed: 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(hProcessor, &uProcId);
++ if (uProcId == DSP_UNIT) {
++ /* Use all available DSP address space after EXTMEM
++ * for DMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, EXTEND,
++ &dwExtEnd);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed on "
++ "COD_GetSymValue %s.\n",
++ EXTEND);
++ }
++ }
++ /* Reset DMM structs and add an initial free chunk*/
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDmmMgr(pProcObject->hDevObject,
++ &hDmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ /* Set dwExtEnd to DMM START u8
++ * address */
++ dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
++ /* DMM memory is from EXT_END */
++ status = DMM_CreateTables(hDmmMgr,
++ dwExtEnd, DMMPOOLSIZE);
++ }
++ }
++ }
++ }
++ /* Restore the original argv[0] */
++ MEM_Free(newEnvp);
++ aArgv[0] = pargv0;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Processor Loaded\n");
++ DBC_Assert(uBrdState == BRD_LOADED);
++ }
++ }
++#endif
++func_end:
++#ifdef DEBUG
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
++ "Processor Load Failed.\n");
++
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Load, status: 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
++ || DSP_FAILED(status));
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv2);
++ if (tv2.tv_usec < tv1.tv_usec) {
++ tv2.tv_usec += 1000000;
++ tv2.tv_sec--;
++ }
++ GT_2trace(PROC_DebugMask, GT_1CLASS,
++ "Proc_Load: time to load %d sec and %d usec \n",
++ tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
++#endif
++ return status;
++}
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ */
++DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
++ void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
++{
++ u32 vaAlign;
++ u32 paAlign;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 sizeAlign;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
++ "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
++ "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
++ pReqAddr, ulMapAttr, ppMapAddr);
++ /* Calculate the page-aligned PA, VA and size */
++ vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
++ paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
++ sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
++ PG_SIZE_4K);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
++ "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
++
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Map: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ } else {
++ status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
++ }
++ /* Add mapping to the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++
++ status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
++ (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
++ ulMapAttr);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Mapped address = MSB of VA | LSB of PA */
++ *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
++ (PG_SIZE_4K - 1)));
++ } else {
++ DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ if (DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt, NULL,
++ (u32)pMpuAddr) != DSP_ENOTFOUND) {
++ DRV_InsertDMMResElement(&dmmRes, pCtxt);
++ DRV_UpdateDMMResElement(dmmRes, (u32)pMpuAddr,
++ ulSize, (u32)pReqAddr,
++ (u32)*ppMapAddr, hProcessor);
++ }
++ }
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events.
++ */
++DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(hNotification != NULL);
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_RegisterNotify, args:\n\t"
++ "hProcessor: 0x%x\n\tuEventMask: 0x%x\n\tuNotifyMask:"
++ " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
++ uNotifyType, hNotification);
++
++ /* Check processor handle */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_RegsiterNotify Invalid "
++ "ProcessorHandle 0x%x\n", hProcessor);
++ goto func_end;
++ }
++ /* Check if event mask is a valid processor related event */
++ if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
++ DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
++ DSP_SYSERROR))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
++ * then register event immediately. */
++ if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
++ status = NTFY_Register(pProcObject->hNtfy,
++ hNotification, uEventMask, uNotifyType);
++ /* * Special case alert, special case alert!
++ * If we're trying to *deregister* (i.e. uEventMask
++ * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
++ * we have to deregister with the DEH manager.
++ * There's no way to know, based on uEventMask which
++ * manager the notification event was registered with,
++ * so if we're trying to deregister and NTFY_Register
++ * failed, we'll give the deh manager a shot.
++ */
++ if ((uEventMask == 0) && DSP_FAILED(status)) {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->
++ pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ }
++ } else {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ */
++DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
++ void **ppRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_ReserveMemory, args:\n\t"
++ "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
++ ulSize, ppRsvAddr);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else
++ status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ */
++DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ u32 dwDspAddr; /* Loaded code's entry point. */
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :InValid Handle \n");
++ goto func_end;
++ }
++ /* Call the WMD_BRD_Start */
++ if (pProcObject->sState != PROC_LOADED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :Wrong state \n");
++ status = DSP_EWRONGSTATE;
++ goto func_end;
++ }
++ status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED "
++ "in Getting DEV_GetCodMgr status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = COD_GetEntry(hCodMgr, &dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED in "
++ "Getting COD_GetEntry status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pProcObject->pIntfFxns->pfnBrdStart)
++ (pProcObject->hWmdContext, dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start Failed to Start the board\n");
++ goto func_cont;
++ }
++ /* Call DEV_Create2 */
++ status = DEV_Create2(pProcObject->hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_RUNNING;
++ /* Deep sleep switces off the peripheral clocks.
++ * we just put the DSP CPU in idle in the idle loop.
++ * so there is no need to send a command to DSP */
++
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
++ "Started and running \n");
++ } else {
++ /* Failed to Create Node Manager and DISP Object
++ * Stop the Processor from running. Put it in STOPPED State */
++ (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ status = DSP_EFAIL;
++ pProcObject->sState = PROC_STOPPED;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
++ "Failed to Create the Node Manager\n");
++ }
++func_cont:
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Start: Processor State is RUNNING \n");
++ DBC_Assert(uBrdState != BRD_HIBERNATION);
++ }
++ }
++#endif
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Start, status 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
++ PROC_RUNNING) || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Stop a processor running.
++ */
++DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct MSG_MGR *hMsgMgr;
++ struct NODE_MGR *hNodeMgr;
++ DSP_HNODE hNode;
++ u32 uNodeTabSize = 1;
++ u32 uNumNodes = 0;
++ u32 uNodesAllocated = 0;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop :InValid Handle \n");
++ goto func_end;
++ }
++ /* check if there are any running nodes */
++ status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
++ if (DSP_SUCCEEDED(status) && hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
++ &uNumNodes, &uNodesAllocated);
++ if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Can't stop device, Active "
++ "nodes = 0x%x \n", uNodesAllocated);
++ return DSP_EWRONGSTATE;
++ }
++ }
++ /* Call the WMD_BRD_Stop */
++ /* It is OK to stop a device that does n't have nodes OR not started */
++ status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Stop: Processor Stopped, "
++ "i.e in standby mode \n");
++ pProcObject->sState = PROC_STOPPED;
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
++ pfnBrdStatus)(pProcObject->hWmdContext,
++ &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor Stopped \n");
++ DBC_Assert(uBrdState == BRD_STOPPED);
++ }
++#endif
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Couldn't delete node manager \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Failed to Stop the processor/device \n");
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status 0x%x\n",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ */
++DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 vaAlign;
++ u32 sizeAlign;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnMap, args:\n\thProcessor:"
++ "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
++
++ vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
++
++ status = DMM_GetHandle(hProcessor, &hDmmMgr);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Update DMM structures. Get the size to unmap.
++ This function returns error if the VA is not mapped */
++ status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
++ }
++ /* Remove mapping from the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
++ (pProcObject->hWmdContext, vaAlign, sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++#ifndef RES_CLEANUP_DISABLE
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "PROC_UnMap DRV_GetDMMResElement "
++ "pMapAddr:[0x%x]", pMapAddr);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, (u32)pMapAddr);
++ if (pCtxt != NULL) {
++ if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
++ DSP_ENOTFOUND)
++ DRV_RemoveDMMResElement(dmmRes, pCtxt);
++ }
++func_end:
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnMap [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ */
++DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnReserveMemory, args:\n\t"
++ "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
++
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status))
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_UnReserveMemory: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ else
++ status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnReserveMemory [0x%x]",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== = PROC_Monitor ======== ==
++ * Purpose:
++ * Place the Processor in Monitor State. This is an internal
++ * function and a requirement before Processor is loaded.
++ * This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
++ * In DEV_Destroy2 we delete the node manager.
++ * Parameters:
++ * hProcObject: Handle to Processor Object
++ * Returns:
++ * DSP_SOK: Processor placed in monitor mode.
++ * !DSP_SOK: Failed to place processor in monitor mode.
++ * Requires:
++ * Valid Processor Handle
++ * Ensures:
++ * Success: ProcObject state is PROC_IDLE
++ */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
++ struct MSG_MGR *hMsgMgr;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
++ "hProcessor: 0x%x\n", hProcObject);
++ /* This is needed only when Device is loaded when it is
++ * already 'ACTIVE' */
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++ }
++ /* Place the Board in the Monitor State */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
++ (pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor in "
++ "Monitor State\n");
++ DBC_Assert(uBrdState == BRD_IDLE);
++ }
++#endif
++ } else {
++ /* Monitor Failure */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Monitor: Processor Could not"
++ "be put in Monitor mode \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Monitor, status 0x%x\n",
++ status);
++#ifdef DEBUG
++ DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
++ DSP_FAILED(status));
++#endif
++ return status;
++}
++
++/*
++ * ======== GetEnvpCount ========
++ * Purpose:
++ * Return the number of elements in the envp array, including the
++ * terminating NULL element.
++ */
++static s32 GetEnvpCount(char **envp)
++{
++ s32 cRetval = 0;
++ if (envp) {
++ while (*envp++)
++ cRetval++;
++
++ cRetval += 1; /* Include the terminating NULL in the count. */
++ }
++
++ return cRetval;
++}
++
++/*
++ * ======== PrependEnvp ========
++ * Purpose:
++ * Prepend an environment variable=value pair to the new envp array, and
++ * copy in the existing var=value pairs in the old envp array.
++ */
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar)
++{
++ char **ppEnvp = newEnvp;
++
++ DBC_Require(newEnvp);
++
++ /* Prepend new environ var=value string */
++ *newEnvp++ = szVar;
++
++ /* Copy user's environment into our own. */
++ while (cEnvp--)
++ *newEnvp++ = *envp++;
++
++ /* Ensure NULL terminates the new environment strings array. */
++ if (cEnvp == 0)
++ *newEnvp = NULL;
++
++ return ppEnvp;
++}
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the processor the events.
++ */
++DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ NTFY_Notify(pProcObject->hNtfy, uEvents);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the processor the events. This includes notifying all clients
++ * attached to a particulat DSP.
++ */
++DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ DEV_NotifyClients(pProcObject->hDevObject, uEvents);
++
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyAllClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetProcessorId ========
++ * Purpose:
++ * Retrieves the processor ID.
++ */
++DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ *procID = pProcObject->uProcessor;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
+new file mode 100644
+index 0000000..50a3f79
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/pwr.c
+@@ -0,0 +1,184 @@
++/*
++ * pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== PWR.c ========
++ * PWR API for controlling DSP power states.
++ *
++ * Public Functions:
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
++ *! 29-Apr-2002 sg Initial.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/devdefs.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmdioctl.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Send command to DSP to enter sleep state.
++ */
++DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 ioctlcode = 0;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ continue;
++ }
++ if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ continue;
++ }
++ if (sleepCode == PWR_DEEPSLEEP)
++ ioctlcode = WMDIOCTL_DEEPSLEEP;
++ else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
++ ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
++ else
++ status = DSP_EINVALIDARG;
++
++ if (status != DSP_EINVALIDARG) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ ioctlcode, (void *)&arg);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Send command to DSP to wake it from sleep.
++ */
++DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_WAKEUP, (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PreScale========
++ * Sends pre-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_PRESCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PostScale========
++ * Sends post-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_POSTSCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++
++}
++
++
+diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
+new file mode 100644
+index 0000000..575f675
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/rmm.c
+@@ -0,0 +1,604 @@
++/*
++ * rmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.c ========
++ * Description:
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments.
++ *
++ * Notes:
++ *
++ * Memory blocks are allocated from the end of the first free memory
++ * block large enough to satisfy the request. Alignment requirements
++ * are satisfied by "sliding" the block forward until its base satisfies
++ * the alignment specification; if this is not possible then the next
++ * free block large enough to hold the request is tried.
++ *
++ * Since alignment can cause the creation of a new free block - the
++ * unused memory formed between the start of the original free block
++ * and the start of the allocated block - the memory manager must free
++ * this memory to prevent a memory leak.
++ *
++ * Overlay memory is managed by reserving through RMM_alloc, and freeing
++ * it through RMM_free. The memory manager prevents DSP code/data that is
++ * overlayed from being overwritten as long as the memory it runs at has
++ * been allocated, and not yet freed.
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux Platform.
++ *! 24-Sep-2002 map Updated from Code Review
++ *! 25-Jun-2002 jeh Free from segid passed to RMM_free().
++ *! 24-Apr-2002 jeh Determine segid based on address in RMM_free(). (No way
++ *! to keep track of segid with dynamic loader library.)
++ *! 16-Oct-2001 jeh Based on gen tree rm.c. Added support for overlays.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/rmm.h>
++
++#define RMM_TARGSIGNATURE 0x544d4d52 /* "TMMR" */
++
++/*
++ * ======== RMM_Header ========
++ * This header is used to maintain a list of free memory blocks.
++ */
++struct RMM_Header {
++ struct RMM_Header *next; /* form a free memory link list */
++ u32 size; /* size of the free memory */
++ u32 addr; /* DSP address of memory block */
++} ;
++
++/*
++ * ======== RMM_OvlySect ========
++ * Keeps track of memory occupied by overlay section.
++ */
++struct RMM_OvlySect {
++ struct LST_ELEM listElem;
++ u32 addr; /* Start of memory section */
++ u32 size; /* Length (target MAUs) of section */
++ s32 page; /* Memory page */
++};
++
++/*
++ * ======== RMM_TargetObj ========
++ */
++struct RMM_TargetObj {
++ u32 dwSignature;
++ struct RMM_Segment *segTab;
++ struct RMM_Header **freeList;
++ u32 numSegs;
++ struct LST_LIST *ovlyList; /* List of overlay memory in use */
++};
++
++#if GT_TRACE
++static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr);
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size);
++
++/*
++ * ======== RMM_alloc ========
++ */
++DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr, bool reserve)
++{
++ struct RMM_OvlySect *sect;
++ struct RMM_OvlySect *prevSect = NULL;
++ struct RMM_OvlySect *newSect;
++ u32 addr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++ DBC_Require(dspAddr != NULL);
++ DBC_Require(size > 0);
++ DBC_Require(reserve || (target->numSegs > 0));
++ DBC_Require(cRefs > 0);
++
++ GT_6trace(RMM_debugMask, GT_ENTER,
++ "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
++ reserve);
++ if (!reserve) {
++ if (!allocBlock(target, segid, size, align, dspAddr)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Increment the number of allocated blocks in this
++ * segment */
++ target->segTab[segid].number++;
++ }
++ goto func_end;
++ }
++ /* An overlay section - See if block is already in use. If not,
++ * insert into the list in ascending address size. */
++ addr = *dspAddr;
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ /* Find place to insert new list element. List is sorted from
++ * smallest to largest address. */
++ while (sect != NULL) {
++ if (addr <= sect->addr) {
++ /* Check for overlap with sect */
++ if ((addr + size > sect->addr) || (prevSect &&
++ (prevSect->addr + prevSect->size > addr))) {
++ status = DSP_EOVERLAYMEMORY;
++ }
++ break;
++ }
++ prevSect = sect;
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* No overlap - allocate list element for new section. */
++ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
++ if (newSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ LST_InitElem((struct LST_ELEM *)newSect);
++ newSect->addr = addr;
++ newSect->size = size;
++ newSect->page = segid;
++ if (sect == NULL) {
++ /* Put new section at the end of the list */
++ LST_PutTail(target->ovlyList,
++ (struct LST_ELEM *)newSect);
++ } else {
++ /* Put new section just before sect */
++ LST_InsertBefore(target->ovlyList,
++ (struct LST_ELEM *)newSect,
++ (struct LST_ELEM *)sect);
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== RMM_create ========
++ */
++DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs)
++{
++ struct RMM_Header *hptr;
++ struct RMM_Segment *sptr, *tmp;
++ struct RMM_TargetObj *target;
++ s32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pTarget != NULL);
++ DBC_Require(numSegs == 0 || segTab != NULL);
++
++ GT_3trace(RMM_debugMask, GT_ENTER,
++ "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
++ pTarget, segTab, numSegs);
++
++ /* Allocate DBL target object */
++ MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
++
++ if (target == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ target->numSegs = numSegs;
++ if (!(numSegs > 0))
++ goto func_cont;
++
++ /* Allocate the memory for freelist from host's memory */
++ target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
++ MEM_PAGED);
++ if (target->freeList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Allocate headers for each element on the free list */
++ for (i = 0; i < (s32) numSegs; i++) {
++ target->freeList[i] =
++ MEM_Calloc(sizeof(struct RMM_Header),
++ MEM_PAGED);
++ if (target->freeList[i] == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ }
++ /* Allocate memory for initial segment table */
++ target->segTab = MEM_Calloc(numSegs *
++ sizeof(struct RMM_Segment), MEM_PAGED);
++ if (target->segTab == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Initialize segment table and free list */
++ sptr = target->segTab;
++ for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
++ *sptr = *tmp;
++ hptr = target->freeList[i];
++ hptr->addr = tmp->base;
++ hptr->size = tmp->length;
++ hptr->next = NULL;
++ tmp++;
++ sptr++;
++ }
++ }
++ }
++func_cont:
++ /* Initialize overlay memory list */
++ if (DSP_SUCCEEDED(status)) {
++ target->ovlyList = LST_Create();
++ if (target->ovlyList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = target;
++ } else {
++ *pTarget = NULL;
++ if (target)
++ RMM_delete(target);
++
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
++ RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
++ NULL));
++
++ return status;
++}
++
++/*
++ * ======== RMM_delete ========
++ */
++void RMM_delete(struct RMM_TargetObj *target)
++{
++ struct RMM_OvlySect *pSect;
++ struct RMM_Header *hptr;
++ struct RMM_Header *next;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
++
++ if (target->segTab != NULL)
++ MEM_Free(target->segTab);
++
++ if (target->ovlyList) {
++ while ((pSect = (struct RMM_OvlySect *)LST_GetHead
++ (target->ovlyList))) {
++ MEM_Free(pSect);
++ }
++ DBC_Assert(LST_IsEmpty(target->ovlyList));
++ LST_Delete(target->ovlyList);
++ }
++
++ if (target->freeList != NULL) {
++ /* Free elements on freelist */
++ for (i = 0; i < target->numSegs; i++) {
++ hptr = next = target->freeList[i];
++ while (next) {
++ hptr = next;
++ next = hptr->next;
++ MEM_Free(hptr);
++ }
++ }
++ MEM_Free(target->freeList);
++ }
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== RMM_exit ========
++ */
++void RMM_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0)
++ MEM_Exit();
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== RMM_free ========
++ */
++bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
++ bool reserved)
++
++{
++ struct RMM_OvlySect *sect;
++ bool retVal = true;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ DBC_Require(reserved || segid < target->numSegs);
++ DBC_Require(reserved || (addr >= target->segTab[segid].base &&
++ (addr + size) <= (target->segTab[segid].base +
++ target->segTab[segid].length)));
++
++ GT_5trace(RMM_debugMask, GT_ENTER,
++ "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx)\n", target, segid, addr, size, reserved);
++ /*
++ * Free or unreserve memory.
++ */
++ if (!reserved) {
++ retVal = freeBlock(target, segid, addr, size);
++ if (retVal)
++ target->segTab[segid].number--;
++
++ } else {
++ /* Unreserve memory */
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ while (sect != NULL) {
++ if (addr == sect->addr) {
++ DBC_Assert(size == sect->size);
++ /* Remove from list */
++ LST_RemoveElem(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ MEM_Free(sect);
++ break;
++ }
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (sect == NULL)
++ retVal = false;
++
++ }
++ return retVal;
++}
++
++/*
++ * ======== RMM_init ========
++ */
++bool RMM_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!RMM_debugMask.flags);
++ GT_create(&RMM_debugMask, "RM"); /* "RM" for RMm */
++
++ retVal = MEM_Init();
++
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS,
++ "RMM_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== RMM_stat ========
++ */
++bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf)
++{
++ struct RMM_Header *head;
++ bool retVal = false;
++ u32 maxFreeSize = 0;
++ u32 totalFreeSize = 0;
++ u32 freeBlocks = 0;
++
++ DBC_Require(pMemStatBuf != NULL);
++ DBC_Assert(target != NULL);
++
++ if ((u32) segid < target->numSegs) {
++ head = target->freeList[segid];
++
++ /* Collect data from freeList */
++ while (head != NULL) {
++ maxFreeSize = max(maxFreeSize, head->size);
++ totalFreeSize += head->size;
++ freeBlocks++;
++ head = head->next;
++ }
++
++ /* ulSize */
++ pMemStatBuf->ulSize = target->segTab[segid].length;
++
++ /* ulNumFreeBlocks */
++ pMemStatBuf->ulNumFreeBlocks = freeBlocks;
++
++ /* ulTotalFreeSize */
++ pMemStatBuf->ulTotalFreeSize = totalFreeSize;
++
++ /* ulLenMaxFreeBlock */
++ pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
++
++ /* ulNumAllocBlocks */
++ pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
++
++ retVal = true;
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== balloc ========
++ * This allocation function allocates memory from the lowest addresses
++ * first.
++ */
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *prevhead = NULL;
++ struct RMM_Header *next;
++ u32 tmpalign;
++ u32 alignbytes;
++ u32 hsize;
++ u32 allocsize;
++ u32 addr;
++
++ alignbytes = (align == 0) ? 1 : align;
++ prevhead = NULL;
++ head = target->freeList[segid];
++
++ do {
++ hsize = head->size;
++ next = head->next;
++
++ addr = head->addr; /* alloc from the bottom */
++
++ /* align allocation */
++ (tmpalign = (u32) addr % alignbytes);
++ if (tmpalign != 0)
++ tmpalign = alignbytes - tmpalign;
++
++ allocsize = size + tmpalign;
++
++ if (hsize >= allocsize) { /* big enough */
++ if (hsize == allocsize && prevhead != NULL) {
++ prevhead->next = next;
++ MEM_Free(head);
++ } else {
++ head->size = hsize - allocsize;
++ head->addr += allocsize;
++ }
++
++ /* free up any hole created by alignment */
++ if (tmpalign)
++ freeBlock(target, segid, addr, tmpalign);
++
++ *dspAddr = addr + tmpalign;
++ return true;
++ }
++
++ prevhead = head;
++ head = next;
++
++ } while (head != NULL);
++
++ return false;
++}
++
++/*
++ * ======== freeBlock ========
++ * TO DO: freeBlock() allocates memory, which could result in failure.
++ * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
++ * freeBlock() could use an RMM_Header from the pool, freeing as blocks
++ * are coalesced.
++ */
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *thead;
++ struct RMM_Header *rhead;
++ bool retVal = true;
++
++ /* Create a memory header to hold the newly free'd block. */
++ rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
++ if (rhead == NULL) {
++ retVal = false;
++ } else {
++ /* search down the free list to find the right place for addr */
++ head = target->freeList[segid];
++
++ if (addr >= head->addr) {
++ while (head->next != NULL && addr > head->next->addr)
++ head = head->next;
++
++ thead = head->next;
++
++ head->next = rhead;
++ rhead->next = thead;
++ rhead->addr = addr;
++ rhead->size = size;
++ } else {
++ *rhead = *head;
++ head->next = rhead;
++ head->addr = addr;
++ head->size = size;
++ thead = rhead->next;
++ }
++
++ /* join with upper block, if possible */
++ if (thead != NULL && (rhead->addr + rhead->size) ==
++ thead->addr) {
++ head->next = rhead->next;
++ thead->size = size + thead->size;
++ thead->addr = addr;
++ MEM_Free(rhead);
++ rhead = thead;
++ }
++
++ /* join with the lower block, if possible */
++ if ((head->addr + head->size) == rhead->addr) {
++ head->next = rhead->next;
++ head->size = head->size + rhead->size;
++ MEM_Free(rhead);
++ }
++ }
++
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
+new file mode 100644
+index 0000000..bd55fd3
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/strm.c
+@@ -0,0 +1,1066 @@
++/*
++ * strm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.c ========
++ * Description:
++ * DSP/BIOS Bridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 13-Mar-2002 map pStrm init'd to NULL in STRM_Open to prevent error
++ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
++ *! in DEV and CMM function calls to avoid confusion.
++ *! Return DSP_SOK instead of S_OK from API fxns.
++ *! 12-Mar-2002 map Changed FAILED(..) to DSP_FAILED(..)
++ *! 25-Jan-2002 ag Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
++ *! 15-Nov-2001 ag Added STRMMODE & SM for DMA/ZCopy streaming.
++ *! Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Use strm timeout value for dma flush timeout.
++ *! 09-May-2001 jeh Code review cleanup.
++ *! 06-Feb-2001 kc Updated DBC_Ensure in STRM_Select to check timeout.
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
++ *! tests to pass.
++ *! 25-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodepriv.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/strm.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define STRM_SIGNATURE 0x4d525453 /* "MRTS" */
++#define STRMMGR_SIGNATURE 0x5254534d /* "RTSM" */
++
++#define DEFAULTTIMEOUT 10000
++#define DEFAULTNUMBUFS 2
++
++/*
++ * ======== STRM_MGR ========
++ * The STRM_MGR contains device information needed to open the underlying
++ * channels of a stream.
++ */
++struct STRM_MGR {
++ u32 dwSignature;
++ struct DEV_OBJECT *hDev; /* Device for this processor */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++} ;
++
++/*
++ * ======== STRM_OBJECT ========
++ * This object is allocated in STRM_Open().
++ */
++ struct STRM_OBJECT {
++ u32 dwSignature;
++ struct STRM_MGR *hStrmMgr;
++ struct CHNL_OBJECT *hChnl;
++ u32 uDir; /* DSP_TONODE or DSP_FROMNODE */
++ u32 uTimeout;
++ u32 uNumBufs; /* Max # of bufs allowed in stream */
++ u32 uNBufsInStrm; /* Current # of bufs in stream */
++ u32 ulNBytes; /* bytes transferred since idled */
++ enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
++ HANDLE hUserEvent; /* Saved for STRM_GetInfo() */
++ enum DSP_STRMMODE lMode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
++ u32 uDMAChnlId; /* DMA chnl id */
++ u32 uDMAPriority; /* DMA priority:DMAPRI_[LOW][HIGH] */
++ u32 uSegment; /* >0 is SM segment.=0 is local heap */
++ u32 uAlignment; /* Alignment for stream bufs */
++ struct CMM_XLATOROBJECT *hXlator; /* Stream's SM address translator */
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask STRM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocates buffers for a stream.
++ */
++DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
++ OUT u8 **apBuffer, u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uAllocated = 0;
++ u32 i;
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
++ "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
++ hStrm, uSize, apBuffer, uNumBufs);
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ /*
++ * Allocate from segment specified at time of stream open.
++ */
++ if (uSize == 0)
++ status = DSP_ESIZE;
++
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
++ if (apBuffer[i] == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_AllocateBuffer: "
++ "DSP_FAILED to alloc shared memory.\n");
++ status = DSP_EMEMORY;
++ uAllocated = i;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
++ }
++ }
++#endif
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ */
++DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Have all buffers been reclaimed? If not, return
++ * DSP_EPENDING */
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ DBC_Assert(DSP_SUCCEEDED(status));
++
++ if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
++ status = DSP_EPENDING;
++ } else {
++
++ status = DeleteStrm(hStrm);
++
++ if (DSP_FAILED(status)) {
++ /* we already validated the handle. */
++ DBC_Assert(status != DSP_EHANDLE);
++
++ /* make sure we return a documented result */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
++ }
++ }
++func_end:
++#endif
++ DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
++ status == DSP_EPENDING || status == DSP_EFAIL);
++
++ return status;
++}
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object.
++ */
++DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
++{
++ struct STRM_MGR *pStrmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrmMgr != NULL);
++ DBC_Require(hDev != NULL);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
++ "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
++ *phStrmMgr = NULL;
++ /* Allocate STRM manager object */
++ MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
++ if (pStrmMgr == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "MEM_AllocObject() failed!\n ");
++ } else {
++ pStrmMgr->hDev = hDev;
++ }
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
++ DBC_Assert(pStrmMgr->pIntfFxns != NULL);
++ } else {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "Failed to get channel manager! status = "
++ "0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pStrmMgr->hSync);
++
++ if (DSP_SUCCEEDED(status))
++ *phStrmMgr = pStrmMgr;
++ else
++ DeleteStrmMgr(pStrmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
++ (DSP_FAILED(status) && *phStrmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Manager Object.
++ */
++void STRM_Delete(struct STRM_MGR *hStrmMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
++ hStrmMgr);
++
++ DeleteStrmMgr(hStrmMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++}
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ */
++void STRM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS,
++ "Entered STRM_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Frees the buffers allocated for a stream.
++ */
++DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
++ u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 i = 0;
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes = NULL;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
++ "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
++ if (DSP_FAILED(status)) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_FreeBuffer: DSP_FAILED"
++ " to free shared memory.\n");
++ break;
++ }
++ apBuffer[i] = NULL;
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
++ pCtxt);
++ }
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Retrieves information about a stream.
++ */
++DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++ void *pVirtBase = NULL; /* NULL if no SM used */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStreamInfo != NULL);
++ DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
++ "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
++ pStreamInfo, uStreamInfoSize);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
++ /* size of users info */
++ status = DSP_ESIZE;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (hStrm->hXlator) {
++ /* We have a translator */
++ DBC_Assert(hStrm->uSegment > 0);
++ CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
++ hStrm->uSegment, false);
++ }
++ pStreamInfo->uSegment = hStrm->uSegment;
++ pStreamInfo->lMode = hStrm->lMode;
++ pStreamInfo->pVirtBase = pVirtBase;
++ pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
++ pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
++ chnlInfo.cIOReqs;
++ /* # of bytes transferred since last call to DSPStream_Idle() */
++ pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
++ pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
++ /* Determine stream state based on channel state and info */
++ if (chnlInfo.dwState & CHNL_STATEEOS) {
++ pStreamInfo->pUser->ssStreamState = STREAM_DONE;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_READY;
++ else if (chnlInfo.cIOReqs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
++ else
++ pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
++
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idles a particular stream.
++ */
++DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
++ "fFlush: 0x%x\n", hStrm, fFlush);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
++ hStrm->uTimeout, fFlush);
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ */
++bool STRM_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++#if GT_TRACE
++ DBC_Assert(!STRM_debugMask.flags);
++ GT_create(&STRM_debugMask, "ST"); /* "ST" for STrm */
++#endif
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++
++ return fRetVal;
++}
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Issues a buffer on a stream
++ */
++DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
++ u32 ulBufSize, u32 dwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuf != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
++ "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
++ dwArg);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ if (hStrm->uSegment != 0) {
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ (void *)pBuf, CMM_VA2DSPPA);
++ if (pTmpBuf == NULL)
++ status = DSP_ETRANSLATE;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pIntfFxns->pfnChnlAddIOReq)
++ (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
++ (u32) pTmpBuf, dwArg);
++ }
++ if (DSP_FAILED(status)) {
++ if (status == CHNL_E_NOIORPS)
++ status = DSP_ESTREAMFULL;
++ else
++ status = DSP_EFAIL;
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task or
++ * XDAIS socket node on the DSP.
++ */
++DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
++{
++ struct STRM_MGR *hStrmMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct STRM_OBJECT *pStrm = NULL;
++ CHNL_MODE uMode;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrm != NULL);
++ DBC_Require(pAttr != NULL);
++ GT_5trace(STRM_debugMask, GT_ENTER,
++ "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
++ "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
++ hNode, uDir, uIndex, pAttr, phStrm);
++ *phStrm = NULL;
++ if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
++ status = DSP_EDIRECTION;
++ } else {
++ /* Get the channel id from the node (set in NODE_Connect()) */
++ status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
++ }
++ if (DSP_SUCCEEDED(status))
++ status = NODE_GetStrmMgr(hNode, &hStrmMgr);
++
++ if (DSP_SUCCEEDED(status)) {
++ MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
++ if (pStrm == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: MEM_AllocObject() failed!\n ");
++ } else {
++ pStrm->hStrmMgr = hStrmMgr;
++ pStrm->uDir = uDir;
++ pStrm->strmState = STREAM_IDLE;
++ pStrm->hUserEvent = pAttr->hUserEvent;
++ if (pAttr->pStreamAttrIn != NULL) {
++ pStrm->uTimeout = pAttr->pStreamAttrIn->
++ uTimeout;
++ pStrm->uNumBufs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ pStrm->lMode = pAttr->pStreamAttrIn->lMode;
++ pStrm->uSegment = pAttr->pStreamAttrIn->
++ uSegment;
++ pStrm->uAlignment = pAttr->pStreamAttrIn->
++ uAlignment;
++ pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
++ uDMAChnlId;
++ pStrm->uDMAPriority = pAttr->pStreamAttrIn->
++ uDMAPriority;
++ chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ } else {
++ pStrm->uTimeout = DEFAULTTIMEOUT;
++ pStrm->uNumBufs = DEFAULTNUMBUFS;
++ pStrm->lMode = STRMMODE_PROCCOPY;
++ pStrm->uSegment = 0; /* local memory */
++ pStrm->uAlignment = 0;
++ pStrm->uDMAChnlId = 0;
++ pStrm->uDMAPriority = 0;
++ chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
++ }
++ chnlAttrs.hReserved1 = NULL;
++ /* DMA chnl flush timeout */
++ chnlAttrs.hReserved2 = pStrm->uTimeout;
++ chnlAttrs.hEvent = NULL;
++ if (pAttr->hUserEvent != NULL)
++ chnlAttrs.hEvent = pAttr->hUserEvent;
++
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
++ goto func_cont;
++
++ DBC_Assert(pStrm->lMode != STRMMODE_LDMA); /* no System DMA */
++ /* Get the shared mem mgr for this streams dev object */
++ status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
++ "CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /*Allocate a SM addr translator for this strm.*/
++ status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Failed to "
++ "create SM translator: 0x%x\n", status);
++ } else {
++ DBC_Assert(pStrm->uSegment > 0);
++ /* Set translators Virt Addr attributes */
++ status = CMM_XlatorInfo(pStrm->hXlator,
++ (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
++ pStrm->uSegment, true);
++ if (status != DSP_SOK) {
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: ERROR: "
++ "in setting CMM_XlatorInfo.\n");
++ }
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Open channel */
++ uMode = (uDir == DSP_TONODE) ?
++ CHNL_MODETODSP : CHNL_MODEFROMDSP;
++ pIntfFxns = hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
++ hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ /*
++ * over-ride non-returnable status codes so we return
++ * something documented
++ */
++ if (status != DSP_EMEMORY && status !=
++ DSP_EINVALIDARG && status != DSP_EFAIL) {
++ /*
++ * We got a status that's not return-able.
++ * Assert that we got something we were
++ * expecting (DSP_EHANDLE isn't acceptable,
++ * hStrmMgr->hChnlMgr better be valid or we
++ * assert here), and then return DSP_EFAIL.
++ */
++ DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
++ status == CHNL_E_BADCHANID ||
++ status == CHNL_E_CHANBUSY ||
++ status == CHNL_E_NOIORPS);
++ status = DSP_EFAIL;
++ }
++ GT_2trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Channel open failed, "
++ "chnl id = %d, status = 0x%x\n", ulChnlId,
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phStrm = pStrm;
++ else
++ (void)DeleteStrm(pStrm);
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ hNode, 0);
++ if (pCtxt != NULL)
++ DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
++
++ }
++#endif
++
++ /* ensure we return a documented error code */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
++ (*phStrm == NULL && (status == DSP_EHANDLE ||
++ status == DSP_EDIRECTION || status == DSP_EVALUE ||
++ status == DSP_EFAIL)));
++ return status;
++}
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Relcaims a buffer from a stream.
++ */
++DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
++ u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPtr != NULL);
++ DBC_Require(pulBytes != NULL);
++ DBC_Require(pdwArg != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
++ "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
++ pdwArg);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
++ &chnlIOC);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Reclaim: GetIOC failed! "
++ "Status = 0x%x\n", status);
++ } else {
++ *pulBytes = chnlIOC.cBytes;
++ if (pulBufSize)
++ *pulBufSize = chnlIOC.cBufSize;
++
++ *pdwArg = chnlIOC.dwArg;
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ /* Allow reclaims after idle to succeed */
++ if (!CHNL_IsIOCancelled(chnlIOC))
++ status = DSP_EFAIL;
++
++ }
++ }
++ /* Translate zerocopy buffer if channel not canceled. */
++ if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
++ (hStrm->lMode == STRMMODE_ZEROCOPY)) {
++ /*
++ * This is a zero-copy channel so chnlIOC.pBuf
++ * contains the DSP address of SM. We need to
++ * translate it to a virtual address for the user
++ * thread to access.
++ * Note: Could add CMM_DSPPA2VA to CMM in the future.
++ */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ chnlIOC.pBuf, CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ pTmpBuf, CMM_PA2VA);
++ }
++ if (pTmpBuf == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_Reclaim: Failed "
++ "SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ chnlIOC.pBuf = pTmpBuf;
++ }
++ *pBufPtr = chnlIOC.pBuf;
++ }
++func_end:
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ */
++DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_RegisterNotify: hStrm: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hStrm, uEventMask, uNotifyType, hNotification);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
++ DSP_STREAMDONE)) != 0) {
++ status = DSP_EVALUE;
++ } else {
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_ENOTIMPL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
++ uEventMask, uNotifyType, hNotification);
++ }
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_ENOTIMPL || status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Selects a ready stream.
++ */
++DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout)
++{
++ u32 uIndex;
++ struct CHNL_INFO chnlInfo;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct SYNC_OBJECT **hSyncEvents = NULL;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aStrmTab != NULL);
++ DBC_Require(pMask != NULL);
++ DBC_Require(nStrms > 0);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Select: aStrmTab: 0x%x \tnStrms: "
++ "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
++ nStrms, pMask, uTimeout);
++ *pMask = 0;
++ for (i = 0; i < nStrms; i++) {
++ if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Determine which channels have IO ready */
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
++ &chnlInfo);
++ if (DSP_FAILED(status)) {
++ break;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ *pMask |= (1 << i);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
++ /* Non-zero timeout */
++ hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
++ sizeof(struct SYNC_OBJECT *), MEM_PAGED);
++ if (hSyncEvents == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)
++ (aStrmTab[i]->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ break;
++ else
++ hSyncEvents[i] = chnlInfo.hSyncEvent;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
++ uTimeout, &uIndex);
++ if (DSP_SUCCEEDED(status)) {
++ /* Since we waited on the event, we have to
++ * reset it */
++ SYNC_SetEvent(hSyncEvents[uIndex]);
++ *pMask = 1 << uIndex;
++ }
++ }
++ }
++func_end:
++ if (hSyncEvents)
++ MEM_Free(hSyncEvents);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
++ (DSP_FAILED(status) && *pMask == 0));
++
++ return status;
++}
++
++/*
++ * ======== DeleteStrm ========
++ * Purpose:
++ * Frees the resources allocated for a stream.
++ */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ if (hStrm->hChnl) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
++ /* Free all SM address translator resources */
++ if (DSP_SUCCEEDED(status)) {
++ if (hStrm->hXlator) {
++ /* force free */
++ (void)CMM_XlatorDelete(hStrm->hXlator,
++ true);
++ }
++ }
++ }
++ MEM_FreeObject(hStrm);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== DeleteStrmMgr ========
++ * Purpose:
++ * Frees stream manager.
++ */
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
++{
++ if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
++
++ if (hStrmMgr->hSync)
++ SYNC_DeleteCS(hStrmMgr->hSync);
++
++ MEM_FreeObject(hStrmMgr);
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
+new file mode 100644
+index 0000000..67656bf
+--- /dev/null
++++ b/drivers/dsp/bridge/services/cfg.c
+@@ -0,0 +1,483 @@
++/*
++ * cfg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfgce.c ========
++ * Purpose:
++ * Implementation of platform specific config services.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Arp-2004 hp Support for handling more than one Device.
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
++ *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
++ *! 10-Aug-2000 rr: Cosmetic changes.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
++ *! replaces CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Comments and bugfixes: modified after code review
++ *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks strlen of the
++ *! read value from the registry against the passed in BufSize;
++ *! CFG_GetZLFile,CFG_GetWMDFileName and
++ *! CFG_GetExecFile also modified same way.
++ *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
++ *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
++ *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
++ *! CFG_GetDevNode reads the Devnodestring from the registry.
++ *! CFG_SetDevObject stores the registry path as
++ *! DevNodestring in the registry.
++ *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
++ *! 22-Nov-1999 kc: Added windows.h to remove warnings.
++ *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
++ *! from the registry which was set by the DRV Request
++ *! Resources.
++ *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
++ *! changes for drv.h resource structure and wsxreg.h new
++ *! entry(DevObject) Hard coded entries removed for those items
++ *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
++ *! registry. CFG_Get HostResources modified for opening up
++ *! two mem winodws.
++ *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
++ *! type of Resource Structure.
++ *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
++#endif
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ */
++void CFG_Exit(void)
++{
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
++}
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ */
++DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetAutoStart: \n\thDevNode:"
++ "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
++ dwBufSize = sizeof(*pdwAutoStart);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++ if (!pdwAutoStart)
++ status = CFG_E_INVALIDPOINTER;
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
++ (u8 *)pdwAutoStart, &dwBufSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetAutoStart SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetAutoStart Failed \n");
++ }
++#endif
++ DBC_Ensure((status == DSP_SOK &&
++ (*pdwAutoStart == 0 || *pdwAutoStart == 1))
++ || status != DSP_SOK);
++ return status;
++}
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ */
++DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
++ "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
++ *pdwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pdwValue)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBufSize = sizeof(pdwValue);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* check the device string and then call the REG_SetValue*/
++ if (!(strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Fetching DSP Device from "
++ "Registry \n");
++ status = REG_GetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP",
++ (u8 *)pdwValue, &dwBufSize);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Identify the Device to Fetch \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDevObject SUCCESS DevObject"
++ ": 0x%x\n ", *pdwValue);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ */
++DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable)
++{
++ DSP_STATUS status = DSP_SOK; /* return value */
++ u32 dwResSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetDSPResources, args: "
++ "\n\thDevNode: 0x%x\n\tpDSPResTable: 0x%x\n",
++ hDevNode, pDSPResTable);
++ if (!hDevNode) {
++ status = CFG_E_INVALIDHDEVNODE;
++ } else if (!pDSPResTable) {
++ status = CFG_E_INVALIDPOINTER;
++ } else {
++ status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
++ (u8 *)pDSPResTable,
++ &dwResSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDSPResources SUCCESS\n");
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDSPResources Failed \n");
++ }
++#ifdef DEBUG
++ /* assert that resource values are reasonable */
++ DBC_Assert(pDSPResTable->uChipType < 256);
++ DBC_Assert(pDSPResTable->uWordSize > 0);
++ DBC_Assert(pDSPResTable->uWordSize < 32);
++ DBC_Assert(pDSPResTable->cChips > 0);
++ DBC_Assert(pDSPResTable->cChips < 256);
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ */
++DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
++ OUT char *pstrExecFile)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 cExecSize = ulBufSize;
++ GT_3trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetExecFile:\n\tthDevNode: "
++ "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
++ ulBufSize, pstrExecFile);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pstrExecFile)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
++ (u8 *)pstrExecFile, &cExecSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ else if (cExecSize > ulBufSize)
++ status = DSP_ESIZE;
++
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetExecFile SUCCESS Exec File"
++ "name : %s\n ", pstrExecFile);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetExecFile Failed \n");
++ }
++#endif
++ DBC_Ensure(((status == DSP_SOK) &&
++ (strlen(pstrExecFile) <= ulBufSize)) || (status != DSP_SOK));
++ return status;
++}
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host allocated resources assigned to a given device.
++ */
++DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetHostResources, args:\n\t"
++ "pHostResTable: 0x%x\n\thDevNode: 0x%x\n",
++ pHostResTable, hDevNode);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pHostResTable)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ dwBufSize = sizeof(struct CFG_HOSTRES);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
++ CURRENTCONFIG,
++ (u8 *)pHostResTable, &dwBufSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetHostResources SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetHostResources Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Object handle from the Registry
++ */
++DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBufSize;
++ DBC_Require(pdwValue != NULL);
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetObject, args:pdwValue: "
++ "0x%x\n", *pdwValue);
++ dwBufSize = sizeof(pdwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, MGROBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ default:
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetObject SUCCESS DrvObject: "
++ "0x%x\n ", *pdwValue);
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ *pdwValue = 0;
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
++ (DSP_FAILED(status) && *pdwValue == 0));
++ return status;
++}
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ */
++bool CFG_Init(void)
++{
++ struct CFG_DSPRES dspResources;
++ GT_create(&CFG_debugMask, "CF"); /* CF for ConFig */
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
++
++ dspResources.uChipType = DSPTYPE_64;
++ dspResources.cChips = 1;
++ dspResources.uWordSize = DSPWORDSIZE;
++ dspResources.cMemTypes = 0;
++ dspResources.aMemDesc[0].uMemType = 0;
++ dspResources.aMemDesc[0].ulMin = 0;
++ dspResources.aMemDesc[0].ulMax = 0;
++ if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
++ (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Initialized DSP resources in "
++ "Registry \n");
++ } else
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Failed to Initialize DSP resources"
++ " in Registry \n");
++ return true;
++}
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle and devNode pointer for a given devnode.
++ */
++DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBuffSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetDevObject, args: \n\t"
++ "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBuffSize = sizeof(dwValue);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the WCD device object in the Registry */
++
++ if (!(strcmp((char *)hDevNode, "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Registering the DSP Device \n");
++ status = REG_SetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP", REG_DWORD,\
++ (u8 *)&dwValue, dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ dwBuffSize = sizeof(hDevNode);
++ status = REG_SetValue(NULL,
++ (char *)hDevNode, "DEVNODESTRING_DSP",
++ REG_DWORD, (u8 *)&hDevNode,
++ dwBuffSize);
++ }
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Register Device \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_SetDevObject SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_SetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_SetObject ========
++ * Purpose:
++ * Store the Driver Object handle
++ */
++DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBuffSize;
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetObject, args: dwValue: "
++ "0x%x\n", dwValue);
++ dwBuffSize = sizeof(dwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
++ (u8 *)&dwValue, dwBuffSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
++ (u8 *) &dwValue, dwBuffSize);
++ break;
++ default:
++ break;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status))
++ GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
++ else
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
++
++#endif
++ return status;
++}
+diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
+new file mode 100644
+index 0000000..b499b14
+--- /dev/null
++++ b/drivers/dsp/bridge/services/clk.c
+@@ -0,0 +1,375 @@
++/*
++ * clk.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.c ========
++ * Purpose:
++ * Clock and Timer services.
++ *
++ * Public Functions:
++ * CLK_Exit
++ * CLK_Init
++ * CLK_Enable
++ * CLK_Disable
++ * CLK_GetRate
++ * CLK_Set_32KHz
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: moved all clock functions from sync module.
++ * And added CLK_Set_32KHz, CLK_Set_SysClk.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++typedef volatile unsigned long REG_UWORD32;
++
++#define SSI_Base 0x48058000
++
++#define SSI_BASE IO_ADDRESS(SSI_Base)
++
++
++struct SERVICES_Clk_t {
++ struct clk *clk_handle;
++ const char *clk_name;
++ int id;
++};
++
++/* The row order of the below array needs to match with the clock enumerations
++ * 'SERVICES_ClkId' provided in the header file.. any changes in the
++ * enumerations needs to be fixed in the array as well */
++static struct SERVICES_Clk_t SERVICES_Clks[] = {
++ {NULL, "iva2_ck", -1},
++ {NULL, "mailboxes_ick", -1},
++ {NULL, "gpt5_fck", -1},
++ {NULL, "gpt5_ick", -1},
++ {NULL, "gpt6_fck", -1},
++ {NULL, "gpt6_ick", -1},
++ {NULL, "gpt7_fck", -1},
++ {NULL, "gpt7_ick", -1},
++ {NULL, "gpt8_fck", -1},
++ {NULL, "gpt8_ick", -1},
++ {NULL, "wdt_fck", 3},
++ {NULL, "wdt_ick", 3},
++ {NULL, "mcbsp_fck", 1},
++ {NULL, "mcbsp_ick", 1},
++ {NULL, "mcbsp_fck", 2},
++ {NULL, "mcbsp_ick", 2},
++ {NULL, "mcbsp_fck", 3},
++ {NULL, "mcbsp_ick", 3},
++ {NULL, "mcbsp_fck", 4},
++ {NULL, "mcbsp_ick", 4},
++ {NULL, "mcbsp_fck", 5},
++ {NULL, "mcbsp_ick", 5},
++ {NULL, "ssi_ssr_sst_fck", -1},
++ {NULL, "ssi_ick", -1},
++ {NULL, "omap_32k_fck", -1},
++ {NULL, "sys_ck", -1},
++ {NULL, ""}
++};
++
++/* Generic TIMER object: */
++struct TIMER_OBJECT {
++ struct timer_list timer;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Cleanup CLK module.
++ */
++void CLK_Exit(void)
++{
++ int i = 0;
++
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
++ /* Relinquish the clock handles */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ if (SERVICES_Clks[i].clk_handle)
++ clk_put(SERVICES_Clks[i].clk_handle);
++
++ SERVICES_Clks[i].clk_handle = NULL;
++ i++;
++ }
++
++}
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initialize CLK module.
++ */
++bool CLK_Init(void)
++{
++ static struct platform_device dspbridge_device;
++ struct clk *clk_handle;
++ int i = 0;
++ GT_create(&CLK_debugMask, "CK"); /* CK for CLK */
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
++
++ dspbridge_device.dev.bus = &platform_bus_type;
++
++ /* Get the clock handles from base port and store locally */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ /* get the handle from BP */
++ dspbridge_device.id = SERVICES_Clks[i].id;
++
++ clk_handle = clk_get(&dspbridge_device.dev,
++ SERVICES_Clks[i].clk_name);
++
++ if (!clk_handle) {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: failed to get Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ /* should we fail here?? */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: PASS and Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ }
++ SERVICES_Clks[i].clk_handle = clk_handle;
++ i++;
++ }
++
++ return true;
++}
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enable Clock .
++ *
++*/
++DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Enable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (clk_enable(pClk) == 0x0) {
++ /* Success ? */
++ } else {
++ pr_err("CLK_Enable: failed to Enable CLK %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ } else {
++ pr_err("CLK_Enable: failed to get CLK %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ /* The SSI module need to configured not to have the Forced idle for
++ * master interface. If it is set to forced idle, the SSI module is
++ * transitioning to standby thereby causing the client in the DSP hang
++ * waiting for the SSI module to be active after enabling the clocks
++ */
++ if (clk_id == SERVICESCLK_ssi_fck)
++ SSI_Clk_Prepare(true);
++
++ return status;
++}
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * To Set parent of a clock to 32KHz.
++ */
++
++DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ struct clk *pClkParent;
++ enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
++ pClkParent = SERVICES_Clks[sys_32k_id].clk_handle;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK %s, "
++ "CLK dev id = %d is setting to 32KHz \n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_Set_32KHz: "
++ "Failed to set to 32KHz %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disable the clock.
++ *
++*/
++DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 clkUseCnt;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Disable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ clkUseCnt = CLK_Get_UseCnt(clk_id);
++ if (clkUseCnt == -1) {
++ pr_err("CLK_Disable: failed to get CLK Use count for CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ } else if (clkUseCnt == 0) {
++ pr_err("CLK_Disable: CLK %s, CLK dev id= %d is already"
++ "disabled\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ return status;
++ }
++ if (clk_id == SERVICESCLK_ssi_ick)
++ SSI_Clk_Prepare(false);
++
++ if (pClk) {
++ clk_disable(pClk);
++ } else {
++ pr_err("CLK_Disable: failed to get CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * GetClock Speed.
++ *
++ */
++
++DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ u32 clkSpeedHz;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ *speedKhz = 0x0;
++
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_GetRate: CLK %s, "
++ "CLK dev Id = %d \n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ clkSpeedHz = clk_get_rate(pClk);
++ *speedKhz = clkSpeedHz / 1000;
++ GT_2trace(CLK_debugMask, GT_6CLASS,
++ "CLK_GetRate: clkSpeedHz = %d , "
++ "speedinKhz=%d\n", clkSpeedHz, *speedKhz);
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 useCount = -1;
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ if (pClk) {
++ useCount = pClk->usecount; /* FIXME: usecount shouldn't be used */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return useCount;
++}
++
++void SSI_Clk_Prepare(bool FLAG)
++{
++ u32 ssi_sysconfig;
++ ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
++
++ if (FLAG) {
++ /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
++ * no idle
++ */
++ ssi_sysconfig = 0x1011;
++ } else {
++ /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
++ * forced idle
++ */
++ ssi_sysconfig = 0x1;
++ }
++ __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
++}
+diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
+new file mode 100644
+index 0000000..dd33c2d
+--- /dev/null
++++ b/drivers/dsp/bridge/services/csl.c
+@@ -0,0 +1,173 @@
++/*
++ * csl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cslce.c ========
++ * Purpose:
++ * Provides platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_Atoi
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtokr
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap.
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
++ *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
++ * CSP_Init().
++ *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
++ *! Removed call to GT_set().
++ *! 19-Jan-1998 cr: Code review cleanup.
++ *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
++ *! combined csl32.c csl95.c and cslnt.c into csl.c. Also
++ *! changed CSL_lowercase to CSL_Uppercase.
++ *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
++ *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/csl.h>
++
++/* Is character c in the string pstrDelim? */
++#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
++ (strchr(pstrDelim, c) != NULL))
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ */
++void CSL_Exit(void)
++{
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
++}
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ */
++bool CSL_Init(void)
++{
++ GT_create(&CSL_DebugMask, "CS");
++
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ */
++void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
++{
++ char tens;
++
++ DBC_Require(dwNum < 100);
++
++ if (dwNum < 100) {
++ tens = (char) dwNum / 10;
++ dwNum = dwNum % 10;
++
++ if (tens) {
++ pstrNumber[0] = tens + '0';
++ pstrNumber[1] = (char) dwNum + '0';
++ pstrNumber[2] = '\0';
++ } else {
++ pstrNumber[0] = (char) dwNum + '0';
++ pstrNumber[1] = '\0';
++ }
++ } else {
++ pstrNumber[0] = '\0';
++ }
++}
++
++
++
++
++/*
++ * ======= CSL_Strtokr =======
++ * Purpose:
++ * Re-entrant version of strtok.
++ */
++char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
++ OUT char **ppstrLast)
++{
++ char *pstrTemp;
++ char *pstrToken;
++
++ DBC_Require(szSeparators != NULL);
++ DBC_Require(ppstrLast != NULL);
++ DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
++
++ /*
++ * Set string location to beginning (pstrSrc != NULL) or to the
++ * beginning of the next token.
++ */
++ pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
++ if (*pstrTemp == '\0') {
++ pstrToken = NULL;
++ } else {
++ pstrToken = pstrTemp;
++ while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
++ szSeparators)) {
++ pstrTemp++;
++ }
++ if (*pstrTemp != '\0') {
++ while (IsDelimiter(*pstrTemp, szSeparators)) {
++ /* TODO: Shouldn't we do this for
++ * only 1 char?? */
++ *pstrTemp = '\0';
++ pstrTemp++;
++ }
++ }
++
++ /* Location in string for next call */
++ *ppstrLast = pstrTemp;
++ }
++
++ return pstrToken;
++}
+diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
+new file mode 100644
+index 0000000..5e1773f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dbg.c
+@@ -0,0 +1,119 @@
++/*
++ * dbg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbgce.c ========
++ * Purpose:
++ * Provide debugging services for DSP/BIOS Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Trace
++ *
++ * Notes:
++ * Requires gt.h.
++ *
++ * This implementation does not create GT masks on a per WMD basis.
++ * There is currently no facility for a WMD to alter the GT mask.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 28-May-1997 cr: Added reference counting.
++ *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 20-May-1996 gp: Remove DEBUG conditional compilation.
++ *! 15-May-1996 gp: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++#if (defined(DEBUG) || defined (DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Ensures trace capability is set up for link drivers.
++ */
++bool DBG_Init(void)
++{
++ GT_create(&DBG_debugMask, "WD"); /* for WmD (link driver) debug */
++
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ */
++DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, pstrFormat);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ if (bLevel & *(DBG_debugMask).flags)
++ printk(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of the DBG module.
++ */
++void DBG_Exit(void)
++{
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
++}
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
+new file mode 100644
+index 0000000..bd608d1
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dpc.c
+@@ -0,0 +1,274 @@
++/*
++ * dpc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpcce.c ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ *
++ * Public Functions:
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
++ *! to THREAD_PRIORITY_IDLE for polling IPC.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
++ *! modified.DPC_Destroy frees the DPC_Object only on
++ *! Successful termination of the thread and the handle.
++ *! 06-Jan-1999 ag: Format cleanup for code review.
++ *! Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
++ *! (Needed to access client(s) CHNL buffers).
++ *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dpc.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f435044 /* "DPC_" (in reverse). */
++
++/* The DPC object, passed to our priority event callback routine: */
++struct DPC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ void *pRefData; /* Argument for client's DPC. */
++ DPC_PROC pfnDPC; /* Client's DPC. */
++ u32 numRequested; /* Number of requested DPC's. */
++ u32 numScheduled; /* Number of executed DPC's. */
++ struct tasklet_struct dpc_tasklet;
++
++#ifdef DEBUG
++ u32 cEntryCount; /* Number of times DPC reentered. */
++ u32 numRequestedMax; /* Keep track of max pending DPC's. */
++#endif
++
++ spinlock_t dpc_lock;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ */
++DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
++ void *pRefData)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = NULL;
++
++ if ((phDPC != NULL) && (pfnDPC != NULL)) {
++ /*
++ * Allocate a DPC object to store information allowing our DPC
++ * callback to dispatch to the client's DPC.
++ */
++ MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
++ if (pDPCObject != NULL) {
++ tasklet_init(&pDPCObject->dpc_tasklet,
++ DPC_DeferredProcedure,
++ (u32) pDPCObject);
++ /* Fill out our DPC Object: */
++ pDPCObject->pRefData = pRefData;
++ pDPCObject->pfnDPC = pfnDPC;
++ pDPCObject->numRequested = 0;
++ pDPCObject->numScheduled = 0;
++#ifdef DEBUG
++ pDPCObject->numRequestedMax = 0;
++ pDPCObject->cEntryCount = 0;
++#endif
++ spin_lock_init(&pDPCObject->dpc_lock);
++ *phDPC = pDPCObject;
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EMEMORY\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EPOINTER\n");
++ status = DSP_EPOINTER;
++ }
++ DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
++ || DSP_SUCCEEDED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create(). Frees the Object only if the thread
++ * and the event terminated successfuly.
++ */
++DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++
++ /* Free our DPC object: */
++ if (DSP_SUCCEEDED(status)) {
++ tasklet_kill(&pDPCObject->dpc_tasklet);
++ MEM_FreeObject(pDPCObject);
++ pDPCObject = NULL;
++ GT_0trace(DPC_DebugMask, GT_2CLASS,
++ "DPC_Destroy: SUCCESS\n");
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Destroy: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
++ || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ */
++void DPC_Exit(void)
++{
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
++}
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ */
++bool DPC_Init(void)
++{
++ GT_create(&DPC_DebugMask, "DP");
++
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ */
++DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++ unsigned long flags;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++ /* Increment count of DPC's pending. Needs to be protected
++ * from ISRs since this function is called from process
++ * context also. */
++ spin_lock_irqsave(&hDPC->dpc_lock, flags);
++ pDPCObject->numRequested++;
++ spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
++ tasklet_schedule(&(hDPC->dpc_tasklet));
++#ifdef DEBUG
++ if (pDPCObject->numRequested > pDPCObject->numScheduled +
++ pDPCObject->numRequestedMax) {
++ pDPCObject->numRequestedMax = pDPCObject->numRequested -
++ pDPCObject->numScheduled;
++ }
++#endif
++ /* If an interrupt occurs between incrementing numRequested and the
++ * assertion below, then DPC will get executed while returning from
++ * ISR, which will complete all requests and make numRequested equal
++ * to numScheduled, firing this assertion. This happens only when
++ * DPC is being scheduled in process context */
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Schedule: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== DeferredProcedure ========
++ * Purpose:
++ * Main DPC routine. This is called by host OS DPC callback
++ * mechanism with interrupts enabled.
++ */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
++{
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
++ /* read numRequested in local variable */
++ u32 requested;
++ u32 serviced;
++
++ DBC_Require(pDPCObject != NULL);
++ requested = pDPCObject->numRequested;
++ serviced = pDPCObject->numScheduled;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
++ "pDeferredContext=%x\n", pDeferredContext);
++ /* Rollover taken care of using != instead of < */
++ if (serviced != requested) {
++ if (pDPCObject->pfnDPC != NULL) {
++ /* Process pending DPC's: */
++ do {
++ /* Call client's DPC: */
++ (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
++ serviced++;
++ } while (serviced != requested);
++ }
++ pDPCObject->numScheduled = requested;
++ }
++ GT_2trace(DPC_DebugMask, GT_ENTER,
++ "< DPC_DeferredProcedure requested %d"
++ " serviced %d\n", requested, serviced);
++}
++
+diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
+new file mode 100644
+index 0000000..ba1d26f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/kfile.c
+@@ -0,0 +1,338 @@
++/*
++ * kfile.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfilece.c ========
++ * Purpose:
++ * This module provides file i/o services.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ *
++ *! Revision History
++ *! ================
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
++ *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
++ *! Removed GT_set().
++ *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
++ *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x4c49464b /* hex code of KFIL (reversed) */
++#define MAXFILENAMELENGTH 256
++#define GENERAL_FAILURE 0xffffffff /* SetFilePointer error */
++
++/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
++struct KFILE_FileObj {
++ u32 dwSignature;
++ __kernel_pid_t owner_pid; /* PID of process that opened this file */
++ char *fileName ;
++ bool isOpen ;
++ u32 size ;
++ u32 curPos ;
++ long hInternal; /* internal handle of file */
++ struct file *fileDesc;
++
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask KFILE_debugMask = { NULL, NULL }; /* Debug mask */
++#endif
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ */
++s32 KFILE_Close(struct KFILE_FileObj *hFile)
++{
++ s32 cRetVal = 0; /* 0 indicates success */
++ s32 fRetVal = 0;
++ __kernel_pid_t curr_pid;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
++ hFile);
++
++ /* Check for valid handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* Close file only if opened by the same process (id). Otherwise
++ * Linux closes all open file handles when process exits.*/
++ /* Return PID instead of process handle */
++ curr_pid = (__kernel_pid_t)current->pid;
++ fRetVal = filp_close(hFile->fileDesc, NULL) ;
++ if (fRetVal) {
++ cRetVal = E_KFILE_ERROR;
++ GT_1trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Close: sys_close "
++ "returned %d\n", fRetVal);
++ }
++ MEM_FreeObject(hFile);
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
++ "invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count
++ * is 0.
++ */
++void KFILE_Exit(void)
++{
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
++}
++
++/*
++ * ======== KFILE_Init ========
++ */
++bool KFILE_Init(void)
++{
++ GT_create(&KFILE_debugMask, "KF"); /* "KF" for KFile */
++
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Open a file for reading ONLY
++ */
++struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
++{
++ struct KFILE_FileObj *hFile; /* file handle */
++ DSP_STATUS status;
++ mm_segment_t fs;
++
++ struct file*fileDesc = NULL;
++ DBC_Require(pszMode != NULL);
++ DBC_Require(pszFileName != NULL);
++
++ GT_2trace(KFILE_debugMask, GT_ENTER,
++ "KFILE_Open: pszFileName %s, pszMode "
++ "%s\n", pszFileName, pszMode);
++
++ /* create a KFILE object */
++ MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
++
++ if (hFile) {
++ fs = get_fs();
++ set_fs(get_ds());
++ /* Third argument is mode (permissions). Ignored unless creating file */
++ fileDesc = filp_open(pszFileName, O_RDONLY, 0);
++ if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
++ (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
++ || (fileDesc->f_op->llseek == NULL)) {
++ status = DSP_EFILE;
++ } else {
++ hFile->fileDesc = fileDesc;
++ hFile->fileName = (char *)pszFileName;
++ hFile->isOpen = true;
++ hFile->curPos = 0;
++ hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
++ SEEK_END);
++ fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
++ /* Return PID instead of process handle */
++ hFile->owner_pid = current->pid;
++
++ status = DSP_SOK;
++ }
++ set_fs(fs);
++ if (DSP_FAILED(status)) {
++ /* free memory, and clear handle */
++ MEM_FreeObject(hFile);
++ hFile = NULL;
++ }
++ } else {
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Open: MEM_AllocObject failed\n");
++ status = DSP_EMEMORY;
++ }
++ return hFile;
++}
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * Reads a specified number of bytes into a buffer.
++ */
++s32
++KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount,
++ struct KFILE_FileObj *hFile)
++{
++ u32 dwBytesRead = 0;
++ s32 cRetVal = 0;
++ mm_segment_t fs;
++
++ DBC_Require(pBuffer != NULL);
++
++ GT_4trace(KFILE_debugMask, GT_4CLASS,
++ "KFILE_Read: buffer 0x%x, cSize 0x%x,"
++ "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ if ((cSize > 0) && (cCount > 0) && pBuffer) {
++ /* read from file */
++ fs = get_fs();
++ set_fs(get_ds());
++ dwBytesRead = hFile->fileDesc->f_op->read(hFile->
++ fileDesc, pBuffer, cSize *cCount,
++ &(hFile->fileDesc->f_pos));
++ set_fs(fs);
++ if (dwBytesRead) {
++ cRetVal = dwBytesRead / cSize;
++ hFile->curPos += dwBytesRead;
++ DBC_Assert((dwBytesRead / cSize) <= \
++ (u32)cCount);
++ } else {
++ cRetVal = E_KFILE_ERROR;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: sys_read() failed\n");
++ }
++ } else {
++ cRetVal = DSP_EINVALIDARG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: Invalid argument(s)\n");
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: invalid file handle\n");
++ }
++
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * Sets the file position indicator. NOTE: we don't support seeking
++ * beyond the boundaries of a file.
++ */
++s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
++{
++ s32 cRetVal = 0; /* 0 for success */
++ u32 dwCurPos = 0;
++
++ struct file *fileDesc = NULL;
++
++ GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
++ "lOffset 0x%x, cOrigin 0x%x\n",
++ hFile, lOffset, cOrigin);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* based on the origin flag, move the internal pointer */
++
++ fileDesc = hFile->fileDesc;
++ switch (cOrigin) {
++ case KFILE_SEEK_SET:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_SET);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++
++ case KFILE_SEEK_CUR:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_CUR);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ case KFILE_SEEK_END:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_END);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ default:
++ cRetVal = E_KFILE_BADORIGINFLAG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:bad origin flag\n");
++ break;
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * Reports the current value of the position indicator. We did not
++ * consider 64 bit long file size, which implies a 4GB file limit
++ * (2 to 32 power).
++ */
++s32 KFILE_Tell(struct KFILE_FileObj *hFile)
++{
++ u32 dwCurPos = 0;
++ s32 lRetVal = E_KFILE_ERROR;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
++
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++
++ /* Get current position. */
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
++ SEEK_CUR);
++ if (dwCurPos >= 0)
++ lRetVal = dwCurPos;
++
++ } else {
++ lRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return lRetVal;
++}
++
+diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
+new file mode 100644
+index 0000000..7fa3e76
+--- /dev/null
++++ b/drivers/dsp/bridge/services/list.c
+@@ -0,0 +1,285 @@
++/*
++ * list.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== listce.c ========
++ * Purpose
++ * Provides standard circular list handling functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_Init
++ * LST_InitElem
++ * LST_InsertBefore
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ *! Revision History
++ *! ================
++ *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
++ *! list manipulation code.
++ *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ */
++struct LST_LIST *LST_Create(void)
++{
++ struct LST_LIST *pList;
++
++ GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
++
++ pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
++ MEM_NONPAGED);
++ if (pList != NULL) {
++ pList->head.next = &pList->head;
++ pList->head.prev = &pList->head;
++ pList->head.self = NULL;
++ }
++
++ return pList;
++}
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ */
++void LST_Delete(struct LST_LIST *pList)
++{
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
++
++ MEM_Free(pList);
++}
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of the LST module.
++ */
++void LST_Exit(void)
++{
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
++}
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the
++ * list is empty.
++ */
++struct LST_ELEM *LST_First(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem = NULL;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
++
++ if (!LST_IsEmpty(pList))
++ pElem = pList->head.next;
++
++ return pElem;
++}
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * "Pops" the head off the list and returns a pointer to it.
++ */
++struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
++
++ if (LST_IsEmpty(pList))
++ return NULL;
++
++ /* pElem is always valid because the list cannot be empty
++ * at this point */
++ pElem = pList->head.next;
++ pList->head.next = pElem->next;
++ pElem->next->prev = &pList->head;
++
++ return pElem->self;
++}
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initialize LST module private state.
++ */
++bool LST_Init(void)
++{
++ GT_create(&LST_debugMask, "LS"); /* LS for LSt module */
++
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ */
++void LST_InitElem(struct LST_ELEM *pElem)
++{
++ DBC_Require(pElem != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
++
++ if (pElem) {
++ pElem->next = NULL;
++ pElem->prev = NULL;
++ pElem->self = pElem;
++ }
++}
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ */
++void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
++ struct LST_ELEM *pElemExisting)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++ DBC_Require(pElemExisting != NULL);
++
++ GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
++ "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
++ pElemExisting);
++
++ pElemExisting->prev->next = pElem;
++ pElem->prev = pElemExisting->prev;
++ pElem->next = pElemExisting;
++ pElemExisting->prev = pElem;
++}
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the
++ * next element is the head of the list or the list is empty.
++ */
++struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ struct LST_ELEM *pNextElem = NULL;
++
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_Next: pList 0x%x, pCurElem 0x%x\n",
++ pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ if (pCurElem->next != &pList->head)
++ pNextElem = pCurElem->next;
++ }
++
++ return pNextElem;
++}
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ */
++void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_PutTail: pList 0x%x, pElem 0x%x\n",
++ pList, pElem);
++
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++
++ DBC_Ensure(!LST_IsEmpty(pList));
++}
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ */
++void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_RemoveElem: pList 0x%x, pCurElem "
++ "0x%x\n", pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++
++ /* set elem fields to NULL to prevent illegal references */
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
+new file mode 100644
+index 0000000..0a10304
+--- /dev/null
++++ b/drivers/dsp/bridge/services/mem.c
+@@ -0,0 +1,599 @@
++/*
++ * mem.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.c ========
++ * Purpose:
++ * Implementation of platform specific memory services.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreePhysMem
++ * MEM_Init
++ * MEM_ExtPhysPoolInit
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Jan-2004 hp: Added support for External physical memory pool
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Code cleanup.
++ *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
++ *! Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
++ *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
++ *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 16-Aug-1999 kc: modified for WinCE.
++ *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
++ *! Mdl offset now ORed not added to userBuf.
++ *! 23-Dec-1997 cr: Code review changes.
++ *! 08-Dec-1997 cr: Prepared for code review.
++ *! 24-Jun-1997 cr: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mem.h>
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Defines */
++#define MEM_512MB 0x1fffffff
++#define memInfoSign 0x464E494D /* "MINF" (in reverse). */
++
++#ifdef DEBUG
++#define MEM_CHECK /* Use to detect source of memory leaks */
++#endif
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool extPhysMemPoolEnabled;
++
++struct extPhysMemPool {
++ u32 physMemBase;
++ u32 physMemSize;
++ u32 virtMemBase;
++ u32 nextPhysAllocPtr;
++};
++
++static struct extPhysMemPool extMemPool;
++
++/* Information about each element allocated on heap */
++struct memInfo {
++ struct LST_ELEM link; /* Must be first */
++ size_t size;
++ void *caller;
++ u32 dwSignature; /* Should be last */
++};
++
++#ifdef MEM_CHECK
++
++/*
++ * This structure holds a linked list to all memory elements allocated on
++ * heap by DSP/BIOS Bridge. This is used to report memory leaks and free
++ * such elements while removing the DSP/BIOS Bridge driver
++ */
++struct memMan {
++ struct LST_LIST lst;
++ spinlock_t lock;
++};
++
++static struct memMan mMan;
++
++/*
++ * These functions are similar to LST_PutTail and LST_RemoveElem and are
++ * duplicated here to make MEM independent of LST
++ */
++static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++ pElem->self = pElem;
++}
++
++static inline void MLST_RemoveElem(struct LST_LIST *pList,
++ struct LST_ELEM *pCurElem)
++{
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++}
++
++static void MEM_Check(void)
++{
++ struct memInfo *pMem;
++ struct LST_ELEM *last = &mMan.lst.head;
++ struct LST_ELEM *curr = mMan.lst.head.next;
++
++ if (!LST_IsEmpty(&mMan.lst)) {
++ GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "Addr Size Caller\n");
++ while (curr != last) {
++ pMem = (struct memInfo *)curr;
++ curr = curr->next;
++ if ((u32)pMem > PAGE_OFFSET &&
++ MEM_IsValidHandle(pMem, memInfoSign)) {
++ GT_3trace(MEM_debugMask, GT_7CLASS,
++ "%lx %d\t [<%p>]\n",
++ (u32) pMem + sizeof(struct memInfo),
++ pMem->size, pMem->caller);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32)pMem + sizeof(struct memInfo));
++ break;
++ }
++ }
++ }
++ DBC_Ensure(LST_IsEmpty(&mMan.lst));
++}
++
++#endif
++
++void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
++{
++ u32 poolVirtBase;
++
++ /* get the virtual address for the physical memory pool passed */
++ poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
++
++ if ((void **)poolVirtBase == NULL) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "[PHYS_POOL]Mapping External "
++ "physical memory to virt failed \n");
++ extPhysMemPoolEnabled = false;
++ } else {
++ extMemPool.physMemBase = poolPhysBase;
++ extMemPool.physMemSize = poolSize;
++ extMemPool.virtMemBase = poolVirtBase;
++ extMemPool.nextPhysAllocPtr = poolPhysBase;
++ extPhysMemPoolEnabled = true;
++ GT_3trace(MEM_debugMask, GT_1CLASS,
++ "ExtMemory Pool details " "Pool"
++ "Physical mem base = %0x " "Pool Physical mem size "
++ "= %0x" "Pool Virtual mem base = %0x \n",
++ poolPhysBase, poolSize, poolVirtBase);
++ }
++}
++
++static void MEM_ExtPhysPoolRelease(void)
++{
++ GT_0trace(MEM_debugMask, GT_1CLASS,
++ "Releasing External memory pool \n");
++ if (extPhysMemPoolEnabled) {
++ iounmap((void *)(extMemPool.virtMemBase));
++ extPhysMemPoolEnabled = false;
++ }
++}
++
++/*
++ * ======== MEM_ExtPhysMemAlloc ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory from external memory pool
++ */
++
++static void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
++{
++ u32 newAllocPtr;
++ u32 offset;
++ u32 virtAddr;
++
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation" "bytes=0x%x , "
++ "align=0x%x \n", bytes, align);
++ if (align == 0) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "No alignment request in allocation call !! \n");
++ align = 1;
++ }
++ if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
++ - extMemPool.nextPhysAllocPtr)) {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "unable to allocate memory for bytes = 0x%x \n",
++ bytes);
++ pPhysAddr = NULL;
++ return NULL;
++ } else {
++ offset = (extMemPool.nextPhysAllocPtr & (align - 1));
++ if (offset == 0)
++ newAllocPtr = extMemPool.nextPhysAllocPtr;
++ else
++ newAllocPtr = (extMemPool.nextPhysAllocPtr) +
++ (align - offset);
++ if ((newAllocPtr + bytes) <=
++ (extMemPool.physMemBase + extMemPool.physMemSize)) {
++ /* we can allocate */
++ *pPhysAddr = newAllocPtr;
++ extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
++ virtAddr = extMemPool.virtMemBase + (newAllocPtr -
++ extMemPool.physMemBase);
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation succedded "
++ "phys address=0x%x , virtaddress=0x%x \n",
++ newAllocPtr, virtAddr);
++ return (void *)virtAddr;
++ } else {
++ *pPhysAddr = 0;
++ return NULL;
++ }
++ }
++}
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ */
++void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *)pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++
++ default:
++ GT_0trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Alloc: unexpected "
++ "MEM_POOLATTRS value\n");
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ */
++void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
++{
++ void *pVaMem = NULL;
++ dma_addr_t paMem;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
++ "0x%x\n", cBytes, ulAlign);
++
++ if (cBytes > 0) {
++ if (extPhysMemPoolEnabled) {
++ pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
++ (u32 *)&paMem);
++ } else
++ pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pVaMem == NULL) {
++ *pPhysicalAddress = 0;
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_AllocPhysMem failed: "
++ "0x%x\n", pVaMem);
++ } else {
++ *pPhysicalAddress = paMem;
++ }
++ }
++ return pVaMem;
++}
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ */
++void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
++ cBytes, type);
++
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
++ pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Calloc: unexpected "
++ "MEM_POOLATTRS value 0x%x\n", type);
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of the MEM module.
++ */
++void MEM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++#ifdef MEM_CHECK
++ if (cRefs == 0)
++ MEM_Check();
++
++#endif
++ MEM_ExtPhysPoolRelease();
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Flush cache
++ */
++void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
++{
++ DBC_Require(cRefs > 0);
++
++ switch (FlushType) {
++ /* invalidate only */
++ case PROC_INVALIDATE_MEM:
++ dmac_inv_range(pMemBuf, pMemBuf + cBytes);
++ outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback only */
++ case PROC_WRITEBACK_MEM:
++ dmac_clean_range(pMemBuf, pMemBuf + cBytes);
++ outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback and invalidate */
++ case PROC_WRITEBACK_INVALIDATE_MEM:
++ dmac_flush_range(pMemBuf, pMemBuf + cBytes);
++ outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
++ "FlushMemType 0x%x\n", FlushType);
++ break;
++ }
++
++}
++
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ */
++void MEM_Free(IN void *pMemBuf)
++{
++#ifdef MEM_CHECK
++ struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
++#endif
++
++ DBC_Require(pMemBuf != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
++ pMemBuf);
++
++ if (pMemBuf) {
++#ifndef MEM_CHECK
++ kfree(pMemBuf);
++#else
++ if (pMem) {
++ if (pMem->dwSignature == memInfoSign) {
++ spin_lock(&mMan.lock);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem->dwSignature = 0;
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32) pMem + sizeof(struct memInfo));
++ }
++ }
++#endif
++ }
++}
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ */
++void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
++ u32 cBytes)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(pVirtualAddress != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
++ "0x%x\n", pVirtualAddress);
++
++ if (!extPhysMemPoolEnabled)
++ dma_free_coherent(NULL, cBytes, pVirtualAddress,
++ pPhysicalAddress);
++}
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initialize MEM module private state.
++ */
++bool MEM_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ GT_create(&MEM_debugMask, "MM"); /* MM for MeM module */
++
++#ifdef MEM_CHECK
++ mMan.lst.head.next = &mMan.lst.head;
++ mMan.lst.head.prev = &mMan.lst.head;
++ mMan.lst.head.self = NULL;
++ spin_lock_init(&mMan.lock);
++#endif
++
++ }
++
++ cRefs++;
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs > 0);
++
++ return true;
++}
+diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
+new file mode 100644
+index 0000000..2eff3eb
+--- /dev/null
++++ b/drivers/dsp/bridge/services/ntfy.c
+@@ -0,0 +1,329 @@
++/*
++ * ntfy.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfyce.c ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE related code.
++ *! 05-Nov-2001 kc Updated DSP_HNOTIFICATION structure.
++ *! 10-May-2001 jeh Removed SERVICES module init/exit from NTFY_Init/Exit.
++ *! NTFY_Register() returns DSP_ENOTIMPL for all but
++ *! DSP_SIGNALEVENT.
++ *! 12-Oct-2000 jeh Use MEM_IsValidHandle().
++ *! 07-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define NTFY_SIGNATURE 0x5946544e /* "YFTN" */
++
++/*
++ * ======== NTFY_OBJECT ========
++ */
++struct NTFY_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct LST_LIST *notifyList; /* List of NOTIFICATION objects */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++};
++
++/*
++ * ======== NOTIFICATION ========
++ * This object will be created when a client registers for events.
++ */
++struct NOTIFICATION {
++ struct LST_ELEM listElem;
++ u32 uEventMask; /* Events to be notified about */
++ u32 uNotifyType; /* Type of notification to be sent */
++
++ /*
++ * We keep a copy of the event name to check if the event has
++ * already been registered. (SYNC also keeps a copy of the name).
++ */
++ char *pstrName; /* Name of event */
++ HANDLE hEvent; /* Handle for notification */
++ struct SYNC_OBJECT *hSync;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask NTFY_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DeleteNotify(struct NOTIFICATION *pNotify);
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ */
++DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
++{
++ struct NTFY_OBJECT *pNtfy;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phNtfy != NULL);
++
++ *phNtfy = NULL;
++ MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
++
++ if (pNtfy) {
++
++ status = SYNC_InitializeDPCCS(&pNtfy->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pNtfy->notifyList = LST_Create();
++ if (pNtfy->notifyList == NULL) {
++ (void) SYNC_DeleteCS(pNtfy->hSync);
++ MEM_FreeObject(pNtfy);
++ status = DSP_EMEMORY;
++ } else {
++ *phNtfy = pNtfy;
++ }
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
++ (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
++ NTFY_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ */
++void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /* Remove any elements remaining in list */
++ if (hNtfy->notifyList) {
++ while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
++ notifyList))) {
++ DeleteNotify(pNotify);
++ }
++ DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
++ LST_Delete(hNtfy->notifyList);
++ }
++ if (hNtfy->hSync)
++ (void)SYNC_DeleteCS(hNtfy->hSync);
++
++ MEM_FreeObject(hNtfy);
++}
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ */
++void NTFY_Exit(void)
++{
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
++}
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ */
++bool NTFY_Init(void)
++{
++ GT_create(&NTFY_debugMask, "NY"); /* "NY" for NtfY */
++
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
++
++ return true;
++}
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ */
++void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /*
++ * Go through notifyList and notify all clients registered for
++ * uEventMask events.
++ */
++
++ (void) SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ if (pNotify->uEventMask & uEventMask) {
++ /* Notify */
++ if (pNotify->uNotifyType == DSP_SIGNALEVENT)
++ (void)SYNC_SetEvent(pNotify->hSync);
++
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++
++ (void) SYNC_LeaveCS(hNtfy->hSync);
++}
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ */
++DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
++ struct DSP_NOTIFICATION *hNotification,
++ u32 uEventMask, u32 uNotifyType)
++{
++ struct NOTIFICATION *pNotify;
++ struct SYNC_ATTRS syncAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ if (hNotification == NULL)
++ status = DSP_EHANDLE;
++
++ /* Return DSP_ENOTIMPL if uNotifyType is not supported */
++ if (DSP_SUCCEEDED(status)) {
++ if (!IsValidNotifyMask(uNotifyType))
++ status = DSP_ENOTIMPL;
++
++ }
++
++ if (DSP_FAILED(status))
++ return status;
++
++ (void)SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++
++ if (hNotification->handle == pNotify->hSync) {
++ /* found */
++ break;
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++ if (pNotify == NULL) {
++ /* Not registered */
++ if (uEventMask == 0) {
++ status = DSP_EVALUE;
++ } else {
++ /* Allocate NOTIFICATION object, add to list */
++ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
++ MEM_PAGED);
++ if (pNotify == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem((struct LST_ELEM *) pNotify);
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
++ hNotification->handle = pNotify->hSync;
++
++ if (DSP_SUCCEEDED(status)) {
++ pNotify->uEventMask = uEventMask;
++ pNotify->uNotifyType = uNotifyType;
++ LST_PutTail(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ } else {
++ DeleteNotify(pNotify);
++ }
++ }
++ } else {
++ /* Found in list */
++ if (uEventMask == 0) {
++ /* Remove from list and free */
++ LST_RemoveElem(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ DeleteNotify(pNotify);
++ } else {
++ /* Update notification mask (type shouldn't change) */
++ pNotify->uEventMask = uEventMask;
++ }
++ }
++ (void)SYNC_LeaveCS(hNtfy->hSync);
++ return status;
++}
++
++/*
++ * ======== DeleteNotify ========
++ * Purpose:
++ * Free the notification object.
++ */
++static void DeleteNotify(struct NOTIFICATION *pNotify)
++{
++ if (pNotify->hSync)
++ (void) SYNC_CloseEvent(pNotify->hSync);
++
++ if (pNotify->pstrName)
++ MEM_Free(pNotify->pstrName);
++
++ MEM_Free(pNotify);
++}
++
+diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
+new file mode 100644
+index 0000000..0d85f41
+--- /dev/null
++++ b/drivers/dsp/bridge/services/reg.c
+@@ -0,0 +1,196 @@
++/*
++ * reg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regce.c ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! ================
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/reg.h>
++#include <regsup.h>
++
++#if GT_TRACE
++struct GT_Mask REG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== REG_DeleteValue ========
++ * Deletes a registry entry value. NOTE: A registry entry value is not the
++ * same as * a registry key.
++ */
++DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS status;
++ DBC_Require(pstrSubkey && pstrValue);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
++
++ /* Note that we don't use phKey */
++ if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_EnumValue ========
++ * Enumerates a registry key and retrieve values stored under the key.
++ * We will assume the input pdwValueSize is smaller than
++ * REG_MAXREGPATHLENGTH for implementation purposes.
++ */
++DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
++ IN CONST char *pstrKey, IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
++ pdwDataSize);
++ DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrKey) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
++
++ status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
++ pstrData, pdwDataSize);
++
++ return status;
++}
++
++/*
++ * ======== REG_Exit ========
++ * Discontinue usage of the REG module.
++ */
++void REG_Exit(void)
++{
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
++
++ regsupExit();
++}
++
++/*
++ * ======== REG_GetValue ========
++ * Retrieve a value from the registry.
++ */
++DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, OUT u8 *pbData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrSubkey && pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_Init ========
++ * Initialize the REG module's private state.
++ */
++bool REG_Init(void)
++{
++ bool fInit;
++
++ GT_create(&REG_debugMask, "RG"); /* RG for ReG */
++
++ fInit = regsupInit();
++
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
++
++ return fInit;
++}
++
++/*
++ * ======== REG_SetValue ========
++ * Set a value in the registry.
++ */
++DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, IN CONST u32 dwType,
++ IN u8 *pbData, IN u32 dwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(dwDataSize > 0);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
+new file mode 100644
+index 0000000..5251b68
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.c
+@@ -0,0 +1,368 @@
++/*
++ * regsup.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.c ========
++ * Purpose:
++ * Provide registry support functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-May-2002 map: Integrated PSI's dspimage update mechanism
++ *! 11-May-2002 gp: Turned PERF "on".
++ *! 21-May-2002 map: Fixed bug in SetValue - if resizing datasize, set
++ *! new size too
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- This */
++#include <regsup.h>
++
++struct RegValueStruct {
++ char name[BRIDGE_MAX_NAME_SIZE]; /* Name of a given value entry */
++ u32 dataSize; /* Size of the data */
++ void *pData; /* Pointer to the actual data */
++};
++
++struct RegKeyStruct {
++ /*The current number of value entries this key has*/
++ u32 numValueEntries;
++ /* Array of value entries */
++ struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
++};
++
++
++/* Pointer to the registry support key */
++static struct RegKeyStruct *pRegKey;
++
++#if GT_TRACE
++extern struct GT_Mask REG_debugMask; /* GT trace var. */
++/*
++ * ======== printS ========
++ * Purpose:
++ * Displays printable characters in pBuf, if any.
++ */
++static inline void printS(void *pBuf)
++{
++ int pos = 0;
++ if (*(REG_debugMask).flags & (GT_2CLASS)) {
++ while (*(u8 *)((pBuf)+pos) >= ' ' &&
++ *(u8 *)((pBuf)+pos) <= '~') {
++ GT_1trace(REG_debugMask, GT_2CLASS, "%c",
++ *(u8 *)((pBuf) + pos++));
++ }
++
++ GT_0trace(REG_debugMask, GT_2CLASS, "\n");
++ }
++}
++#else
++#define printS(pBuf)
++#endif
++
++/*
++ * ======== regsupInit ========
++ * Purpose:
++ * Initialize the Registry Support module's private state.
++ */
++bool regsupInit(void)
++{
++ if (pRegKey != NULL)
++ return true;
++
++ /* Need to allocate and setup our registry. */
++ pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
++ if (pRegKey == NULL)
++ return false;
++
++ return true;
++}
++
++/*
++ * ======== regsupExit ========
++ * Purpose:
++ * Release all registry support allocations.
++ */
++void regsupExit(void)
++{
++ u32 i;
++
++ /* Make sure data has actually been allocated. */
++ if (pRegKey == NULL) {
++ /* Nothing initialized.return! */
++ return;
++ }
++
++ GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
++ pRegKey->numValueEntries);
++
++ /* Now go through each entry and free all resources. */
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ if (pRegKey->values[i].name[0] != '\0') {
++ /* We have a valid entry.free it up! */
++ if (pRegKey->values[i].pData != NULL) {
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E %d\t %s DATA %x ", i,
++ pRegKey->values[i].name,
++ *(u32 *)pRegKey->values[i].pData);
++ printS((u8 *)(pRegKey->values[i].pData));
++ MEM_Free(pRegKey->values[i].pData);
++ }
++ pRegKey->values[i].pData = NULL;
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].name[0] = '\0';
++ }
++ }
++
++ /* Now that all of the resources are freed up, free the main one! */
++ MEM_Free(pRegKey);
++
++ /* Don't forget to NULL out the global entry! */
++ pRegKey = NULL;
++}
++
++/*
++ * ======== regsupGetValue ========
++ * Purpose:
++ * Get the value of the entry having the given name.
++ */
++DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++
++ /* We have a match! Copy out the data. */
++ memcpy(pBuf, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++
++ /* Get the size for the caller. */
++ *dataSize = pRegKey->values[i].dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (DSP_SUCCEEDED(retVal)) {
++ GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++ } else {
++ GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupSetValue ========
++ * Purpose:
++ * Sets the value of the entry having the given name.
++ */
++DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* Make sure the new data size is the same. */
++ if (dataSize != pRegKey->values[i].dataSize) {
++ /* The caller needs a different data size! */
++ MEM_Free(pRegKey->values[i].pData);
++ pRegKey->values[i].pData = MEM_Alloc(dataSize,
++ MEM_NONPAGED);
++ if (pRegKey->values[i].pData == NULL)
++ break;
++
++ }
++
++ /* We have a match! Copy out the data. */
++ memcpy(pRegKey->values[i].pData, pBuf, dataSize);
++
++ /* Reset datasize - overwrite if new or same */
++ pRegKey->values[i].dataSize = dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ /* See if we found a match or if this is a new entry */
++ if (i == pRegKey->numValueEntries) {
++ /* No match, need to make a new entry */
++ /* First check to see if we can make any more entries. */
++ if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
++ strncpy(pRegKey->values[pRegKey->numValueEntries].name,
++ valName, BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[pRegKey->numValueEntries].pData =
++ MEM_Alloc(dataSize, MEM_NONPAGED);
++ if (pRegKey->values[pRegKey->numValueEntries].pData !=
++ NULL) {
++ memcpy(pRegKey->
++ values[pRegKey->numValueEntries].pData,
++ pBuf, dataSize);
++ pRegKey->
++ values[pRegKey->numValueEntries].dataSize =
++ dataSize;
++ pRegKey->numValueEntries++;
++ retVal = DSP_SOK;
++ }
++ } else {
++ GT_0trace(REG_debugMask, GT_7CLASS,
++ "MAX NUM REG ENTRIES REACHED\n");
++ }
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupEnumValue ========
++ * Purpose:
++ * Returns registry "values" and their "data" under a (sub)key.
++ */
++DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
++ u32 i;
++ u32 dwKeyLen;
++ u32 count = 0;
++
++ DBC_Require(pstrKey);
++ dwKeyLen = strlen(pstrKey);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if ((strncmp(pRegKey->values[i].name, pstrKey,
++ dwKeyLen) == 0) && count++ == dwIndex) {
++ /* We have a match! Copy out the data. */
++ memcpy(pstrData, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++ /* Get the size for the caller. */
++ *pdwDataSize = pRegKey->values[i].dataSize;
++ *pdwValueSize = strlen(&(pRegKey->
++ values[i].name[dwKeyLen]));
++ strncpy(pstrValue,
++ &(pRegKey->values[i].name[dwKeyLen]),
++ *pdwValueSize + 1);
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E Key %s, Value %s, Data %x ",
++ pstrKey, pstrValue, *(u32 *)pstrData);
++ printS((u8 *)pstrData);
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (count && DSP_FAILED(retVal))
++ retVal = REG_E_NOMOREITEMS;
++
++ return retVal;
++}
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ /* See if the name matches... */
++ if (strncmp(pRegKey->values[i].name, pstrValue,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* We have a match! Delete this key. To delete a
++ * key, we free all resources associated with this
++ * key and, if we're not already the last entry in
++ * the array, we copy that entry into this deleted
++ * key.
++ */
++ MEM_Free(pRegKey->values[i].pData);
++ if ((pRegKey->numValueEntries - 1) == i) {
++ /* we're deleting the last one */
++ pRegKey->values[i].name[0] = '\0';
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].pData = NULL;
++ } else {
++ /* move the last one here */
++ strncpy(pRegKey->values[i].name, pRegKey->
++ values[pRegKey->numValueEntries - 1].name,
++ BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[i].dataSize =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].dataSize;
++ pRegKey->values[i].pData =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].pData;
++ /* don't have to do this, but for
++ * the paranoid... */
++ pRegKey->
++ values[pRegKey->numValueEntries-1].name[0] =
++ '\0';
++ }
++
++ /* another one bites the dust. */
++ pRegKey->numValueEntries--;
++
++ /* Set our status to good and exit... */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++ return retVal;
++
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
+new file mode 100644
+index 0000000..011be52
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.h
+@@ -0,0 +1,58 @@
++/*
++ * regsup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef _REGSUP_H_
++#define _REGSUP_H_
++
++#define BRIDGE_MAX_NAME_SIZE MAXREGPATHLENGTH
++#define BRIDGE_MAX_NUM_REG_ENTRIES 52
++
++/* Init function. MUST be called BEFORE any calls are */
++/* made into this psuedo-registry!!! Returns TRUE/FALSE for SUCCESS/ERROR */
++extern bool regsupInit(void);
++
++/* Release all registry support allocations. */
++extern void regsupExit(void);
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++/* Get the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value retrieved. Returns DSP_EFAIL
++ * otherwise.*/
++extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
++
++/* Sets the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value set. Returns DSP_EFAIL otherwise. */
++extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
++
++/* Returns registry "values" and their "data" under a (sub)key. */
++extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
++
++#endif
++
+diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
+new file mode 100644
+index 0000000..346007e
+--- /dev/null
++++ b/drivers/dsp/bridge/services/services.c
+@@ -0,0 +1,193 @@
++/*
++ * services.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.c ========
++ * Purpose:
++ * Provide SERVICES loading.
++ *
++ * Public Functions:
++ * SERVICES_Exit
++ * SERVICES_Init
++ *
++ *
++ *! Revision History
++ *! ================
++ *! 20-Nov-2000 rr: NTFY_Init/Exit added.
++ *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/services.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SERVICES_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++static u32 cRefs; /* SERVICES module reference count */
++
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void SERVICES_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
++ cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ /* Uninitialize all SERVICES modules here */
++ NTFY_Exit();
++ UTIL_Exit();
++ SYNC_Exit();
++ CLK_Exit();
++ REG_Exit();
++ LST_Exit();
++ KFILE_Exit();
++ DPC_Exit();
++ DBG_Exit();
++ CSL_Exit();
++ CFG_Exit();
++ MEM_Exit();
++
++ GT_exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ */
++bool SERVICES_Init(void)
++{
++ bool fInit = true;
++ bool fCFG, fCSL, fDBG, fDPC, fKFILE, fLST, fMEM;
++ bool fREG, fSYNC, fCLK, fUTIL, fNTFY;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ GT_init();
++ GT_create(&SERVICES_debugMask, "OS"); /* OS for OSal */
++
++ GT_0trace(SERVICES_debugMask, GT_ENTER,
++ "SERVICES_Init: entered\n");
++
++ /* Perform required initialization of SERVICES modules. */
++ fMEM = MEM_Init();
++ fREG = REG_Init();
++ fCFG = CFG_Init();
++ fCSL = CSL_Init();
++ fDBG = DBG_Init();
++ fDPC = DPC_Init();
++ fKFILE = KFILE_Init();
++ fLST = LST_Init();
++ /* fREG = REG_Init(); */
++ fSYNC = SYNC_Init();
++ fCLK = CLK_Init();
++ fUTIL = UTIL_Init();
++ fNTFY = NTFY_Init();
++
++ fInit = fCFG && fCSL && fDBG && fDPC && fKFILE &&
++ fLST && fMEM && fREG && fSYNC && fCLK && fUTIL;
++
++ if (!fInit) {
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fUTIL)
++ UTIL_Exit();
++
++ if (fSYNC)
++ SYNC_Exit();
++
++ if (fCLK)
++ CLK_Exit();
++
++ if (fREG)
++ REG_Exit();
++
++ if (fLST)
++ LST_Exit();
++
++ if (fKFILE)
++ KFILE_Exit();
++
++ if (fDPC)
++ DPC_Exit();
++
++ if (fDBG)
++ DBG_Exit();
++
++ if (fCSL)
++ CSL_Exit();
++
++ if (fCFG)
++ CFG_Exit();
++
++ if (fMEM)
++ MEM_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
++
++ return fInit;
++}
++
+diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
+new file mode 100644
+index 0000000..7ab9347
+--- /dev/null
++++ b/drivers/dsp/bridge/services/sync.c
+@@ -0,0 +1,602 @@
++/*
++ * sync.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.c ========
++ * Purpose:
++ * Synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Nov-2001 kc: Minor cosmetic changes.
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 10-Aug-2000 rr: SYNC_PostMessage added.
++ *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 22-Sep-1999 kc: Modified from sync95.c.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x434e5953 /* "SYNC" (in reverse) */
++
++enum wait_state {
++ wo_waiting,
++ wo_signalled
++} ;
++
++enum sync_state {
++ so_reset,
++ so_signalled
++} ;
++
++struct WAIT_OBJECT {
++ enum wait_state state;
++ struct SYNC_OBJECT *signalling_event;
++ struct semaphore sem;
++};
++
++/* Generic SYNC object: */
++struct SYNC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ enum sync_state state;
++ spinlock_t sync_lock;
++ struct WAIT_OBJECT *pWaitObj;
++};
++
++struct SYNC_DPCCSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ spinlock_t sync_dpccs_lock;
++ s32 count;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SYNC_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static int test_and_set(volatile void *ptr, int val)
++{
++ int ret = val;
++ asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
++ return ret;
++}
++
++static void timeout_callback(unsigned long hWaitObj);
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close an existing SYNC event object.
++ */
++DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ if (pEvent->pWaitObj) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: Wait object not NULL\n");
++ }
++ MEM_FreeObject(pEvent);
++
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: invalid "
++ "hEvent handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Cleanup SYNC module.
++ */
++void SYNC_Exit(void)
++{
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
++}
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initialize SYNC module.
++ */
++bool SYNC_Init(void)
++{
++ GT_create(&SYNC_debugMask, "SY"); /* SY for SYnc */
++
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Open a new synchronization event object.
++ */
++DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS *pAttrs)
++{
++ struct SYNC_OBJECT *pEvent = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phEvent != NULL);
++
++ GT_2trace(SYNC_debugMask, GT_ENTER,
++ "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
++ "0x%x\n", phEvent, pAttrs);
++
++ /* Allocate memory for sync object */
++ MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
++ if (pEvent != NULL) {
++ pEvent->state = so_reset;
++ pEvent->pWaitObj = NULL;
++ spin_lock_init(&pEvent->sync_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_OpenEvent: MEM_AllocObject failed\n");
++ }
++
++ *phEvent = pEvent;
++
++ return status;
++}
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset an event to non-signalled.
++ */
++DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ pEvent->state = so_reset;
++ status = DSP_SOK;
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_ResetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Set an event to signaled and unblock one waiting thread.
++ *
++ * This function is called from ISR, DPC and user context. Hence interrupts
++ * are disabled to ensure atomicity.
++ */
++
++DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ unsigned long flags;
++
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ spin_lock_irqsave(&hEvent->sync_lock, flags);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: pEvent->pWaitObj "
++ "= 0x%x \n", pEvent->pWaitObj);
++ if (pEvent->pWaitObj)
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
++ "pEvent->pWaitObj->state = 0x%x \n",
++ pEvent->pWaitObj->state);
++ if (pEvent->pWaitObj != NULL &&
++ test_and_set(&pEvent->pWaitObj->state,
++ wo_signalled) == wo_waiting) {
++
++ pEvent->state = so_reset;
++ pEvent->pWaitObj->signalling_event = pEvent;
++ up(&pEvent->pWaitObj->sem);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: Unlock "
++ "Semaphore for hEvent 0x%x\n", hEvent);
++ } else {
++ pEvent->state = so_signalled;
++ }
++ spin_unlock_irqrestore(&hEvent->sync_lock, flags);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Note: dwTimeOut must be 0xffffffff to signal infinite wait.
++ */
++DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ u32 temp;
++
++ GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
++ "dwTimeOut 0x%x", hEvent, dwTimeout);
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
++ &temp);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnEvent: invalid hEvent"
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ */
++DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
++ u32 uCount, u32 dwTimeout,
++ OUT u32 *puIndex)
++{
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 curr;
++ struct WAIT_OBJECT *Wp;
++
++ DBC_Require(uCount > 0);
++ DBC_Require(hSyncEvents != NULL);
++ DBC_Require(puIndex != NULL);
++
++ for (i = 0; i < uCount; i++)
++ DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
++
++ GT_4trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnMultipleEvents: hSyncEvents:"
++ "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
++ hSyncEvents, uCount, dwTimeout, puIndex);
++
++ Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
++ if (Wp == NULL)
++ return DSP_EMEMORY;
++
++ Wp->state = wo_waiting;
++ Wp->signalling_event = NULL;
++ init_MUTEX_LOCKED(&(Wp->sem));
++
++ for (curr = 0; curr < uCount; curr++) {
++ hSyncEvents[curr]->pWaitObj = Wp;
++ if (hSyncEvents[curr]->state == so_signalled) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Detected signaled Event !!!\n");
++ if (test_and_set(&(Wp->state), wo_signalled) ==
++ wo_waiting) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Setting Signal Event!!!\n");
++ hSyncEvents[curr]->state = so_reset;
++ Wp->signalling_event = hSyncEvents[curr];
++ }
++ curr++; /* Will try optimizing later */
++ break;
++ }
++ }
++
++ curr--; /* Will try optimizing later */
++ if (Wp->state != wo_signalled && dwTimeout > 0) {
++ struct timer_list timeout;
++ if (dwTimeout != SYNC_INFINITE) {
++ init_timer(&timeout);
++ timeout.function = timeout_callback;
++ timeout.data = (unsigned long)Wp;
++ timeout.expires = jiffies + dwTimeout * HZ / 1000;
++ add_timer(&timeout);
++ }
++ if (down_interruptible(&(Wp->sem))) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
++ "WaitOnMultipleEvents Interrupted by signal\n");
++ status = DSP_EFAIL;
++ }
++ if (dwTimeout != SYNC_INFINITE) {
++ if (in_interrupt()) {
++ if (!del_timer(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ } else {
++ if (!del_timer_sync(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ }
++ }
++ }
++ for (i = 0; i <= curr; i++) {
++ if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
++ /* Memory corruption here if hSyncEvents[i] is
++ * freed before following statememt. */
++ hSyncEvents[i]->pWaitObj = NULL;
++ }
++ if (hSyncEvents[i] == Wp->signalling_event)
++ *puIndex = i;
++
++ }
++ if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC:Signaling Event NULL!!!(:-\n");
++ status = DSP_ETIMEOUT;
++ }
++ if (Wp)
++ MEM_Free(Wp);
++ return status;
++}
++
++static void timeout_callback(unsigned long hWaitObj)
++{
++ struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
++ if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
++ up(&pWaitObj->sem);
++
++}
++
++/*
++ * ======== SYNC_DeleteCS ========
++ */
++DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (down_trylock(&pCSObj->sem) != 0) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(hCSObj);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ if (pDPCCSObj->count != 1) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "DPC CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(pDPCCSObj);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_DeleteCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_EnterCS ========
++ */
++DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
++ hCSObj);
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (in_interrupt()) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS called from "
++ "ISR/DPC or with ISR/DPC disabled!");
++ DBC_Assert(0);
++ } else if (down_interruptible(&pCSObj->sem)) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS interrupted by signal! "
++ "pCSObj=0x%X", pCSObj);
++ status = DSP_EFAIL;
++ }
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ pDPCCSObj->count--;
++ if (pDPCCSObj->count != 0) {
++ /* FATAL ERROR : Failed to acquire DPC CS */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS DPCCS %x locked,"
++ "count %d", pDPCCSObj, pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_EnterCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_InitializeCS ========
++ */
++DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = NULL;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
++
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
++ if (pCSObj != NULL) {
++ init_MUTEX(&pCSObj->sem);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeCS: MEM_AllocObject"
++ "failed\n");
++ }
++ /* return CS object */
++ *phCSObj = pCSObj;
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++ return status;
++}
++
++DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_DPCCSOBJECT *pCSObj = NULL;
++
++ DBC_Require(phCSObj);
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
++
++ if (phCSObj) {
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
++ SIGNATUREDPCCS);
++ if (pCSObj != NULL) {
++ pCSObj->count = 1;
++ spin_lock_init(&pCSObj->sync_dpccs_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeDPCCS: "
++ "MEM_AllocObject failed\n");
++ }
++
++ /* return CS object */
++ *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
++ "pCSObj %p\n", pCSObj);
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++
++ return status;
++}
++
++/*
++ * ======== SYNC_LeaveCS ========
++ */
++DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
++ hCSObj);
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ up(&pCSObj->sem);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ pDPCCSObj->count++;
++ if (pDPCCSObj->count != 1) {
++ /* FATAL ERROR : Invalid DPC CS count */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_LeaveCS DPCCS %x, "
++ "Invalid count %d", pDPCCSObj,
++ pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ }
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_LeaveCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
+new file mode 100644
+index 0000000..801b000
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_cmm.h
+@@ -0,0 +1,59 @@
++/*
++ * _cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _cmm.h ========
++ * Description:
++ * Private header file defining CMM manager objects and defines needed
++ * by IO manager to register shared memory regions when DSP base image
++ * is loaded(WMD_IO_OnLoaded).
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Aug-2001 ag Created.
++ */
++
++#ifndef _CMM_
++#define _CMM_
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for shared memory manager CMM.
++ * They are defined in the *cfg.cmd file by cdb code.
++ */
++#define SHM0_SHARED_BASE_SYM "_SHM0_BEG"
++#define SHM0_SHARED_END_SYM "_SHM0_END"
++#define SHM0_SHARED_RESERVED_BASE_SYM "_SHM0_RSVDSTRT"
++
++/*
++ * Shared Memory Region #0(SHMSEG0) is used in the following way:
++ *
++ * |(_SHM0_BEG) | (_SHM0_RSVDSTRT) | (_SHM0_END)
++ * V V V
++ * ------------------------------------------------------------
++ * | DSP-side allocations | GPP-side allocations |
++ * ------------------------------------------------------------
++ *
++ *
++ */
++
++#endif /* _CMM_ */
+diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
+new file mode 100644
+index 0000000..df281ad
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_deh.h
+@@ -0,0 +1,46 @@
++/*
++ * _deh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _deh.h ========
++ * Description:
++ * Private header for DEH module.
++ *
++ *! Revision History:
++ *! ================
++ *! 21-Sep-2001 kc: created.
++ */
++
++#ifndef _DEH_
++#define _DEH_
++
++#include <dspbridge/dpc.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/wmd.h>
++
++#define SIGNATURE 0x5f484544 /* "DEH_" backwards */
++
++/* DEH Manager: only one created per board: */
++struct DEH_MGR {
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct NTFY_OBJECT *hNtfy; /* NTFY object */
++ struct DPC_OBJECT *hMmuFaultDpc; /* DPC object handle. */
++ struct DSP_ERRORINFO errInfo; /* DSP exception info. */
++} ;
++
++#endif /* _DEH_ */
+diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
+new file mode 100644
+index 0000000..fa5e9ee
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_msg_sm.h
+@@ -0,0 +1,158 @@
++/*
++ * _msg_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _msg_sm.h ========
++ * Description:
++ * Private header file defining MSG manager objects and defines needed
++ * by IO manager.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 09-May-2001 jeh Code Review cleanup.
++ *! 08-Nov-2000 jeh Created.
++ */
++
++#ifndef _MSG_SM_
++#define _MSG_SM_
++
++#include <dspbridge/list.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for messages. They are
++ * defined in the *cfg.cmd file by cdb code.
++ */
++#define MSG_SHARED_BUFFER_BASE_SYM "_MSG_BEG"
++#define MSG_SHARED_BUFFER_LIMIT_SYM "_MSG_END"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++/*
++ * ======== MSG ========
++ * There is a control structure for messages to the DSP, and a control
++ * structure for messages from the DSP. The shared memory region for
++ * transferring messages is partitioned as follows:
++ *
++ * ----------------------------------------------------------
++ * |Control | Messages from DSP | Control | Messages to DSP |
++ * ----------------------------------------------------------
++ *
++ * MSG control structure for messages to the DSP is used in the following
++ * way:
++ *
++ * bufEmpty - This flag is set to FALSE by the GPP after it has output
++ * messages for the DSP. The DSP host driver sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 by the GPP after it has written the messages,
++ * set the size, and set bufEmpty to FALSE.
++ * The DSP Host driver uses SWI_andn of the postSWI field
++ * when a host interrupt occurs. The host driver clears
++ * this after posting the SWI.
++ * size - Number of messages to be read by the DSP.
++ *
++ * For messages from the DSP:
++ * bufEmpty - This flag is set to FALSE by the DSP after it has output
++ * messages for the GPP. The DPC on the GPP sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 the DPC on the GPP after copying the messages.
++ * size - Number of messages to be read by the GPP.
++ */
++struct MSG {
++ u32 bufEmpty; /* to/from DSP buffer is empty */
++ u32 postSWI; /* Set to "1" to post MSG SWI */
++ u32 size; /* Number of messages to/from the DSP */
++ u32 resvd;
++} ;
++
++/*
++ * ======== MSG_MGR ========
++ * The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
++ * have MSG_QUEUE to hold all messages that come up from the corresponding
++ * node on the DSP. The MSG_MGR also has a shared queue of messages
++ * ready to go to the DSP.
++ */
++struct MSG_MGR {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++
++ struct IO_MGR *hIOMgr; /* IO manager */
++ struct LST_LIST *queueList; /* List of MSG_QUEUEs */
++ struct SYNC_CSOBJECT *hSyncCS; /* For critical sections */
++ /* Signalled when MsgFrame is available */
++ struct SYNC_OBJECT *hSyncEvent;
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ struct LST_LIST *msgUsedList; /* MsgFrames ready to go to DSP */
++ u32 uMsgsPending; /* # of queued messages to go to DSP */
++ u32 uMaxMsgs; /* Max # of msgs that fit in buffer */
++ MSG_ONEXIT onExit; /* called when RMS_EXIT is received */
++} ;
++
++/*
++ * ======== MSG_QUEUE ========
++ * Each NODE has a MSG_QUEUE for receiving messages from the
++ * corresponding node on the DSP. The MSG_QUEUE object maintains a list
++ * of messages that have been sent to the host, but not yet read (MSG_Get),
++ * and a list of free frames that can be filled when new messages arrive
++ * from the DSP.
++ * The MSG_QUEUE's hSynEvent gets posted when a message is ready.
++ */
++struct MSG_QUEUE {
++ struct LST_ELEM listElem;
++ u32 dwSignature;
++ struct MSG_MGR *hMsgMgr;
++ u32 uMaxMsgs; /* Node message depth */
++ u32 dwId; /* Node environment pointer */
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ /* Filled MsgFramess waiting to be read */
++ struct LST_LIST *msgUsedList;
++ HANDLE hArg; /* Handle passed to mgr onExit callback */
++ struct SYNC_OBJECT *hSyncEvent; /* Signalled when message is ready */
++ struct SYNC_OBJECT *hSyncDone; /* For synchronizing cleanup */
++ struct SYNC_OBJECT *hSyncDoneAck; /* For synchronizing cleanup */
++ struct NTFY_OBJECT *hNtfy; /* For notification of message ready */
++ bool fDone; /* TRUE <==> deleting the object */
++ u32 refCount; /* Number of pending MSG_get/put calls */
++};
++
++/*
++ * ======== MSG_DSPMSG ========
++ */
++struct MSG_DSPMSG {
++ struct DSP_MSG msg;
++ u32 dwId; /* Identifies the node the message goes to */
++} ;
++
++/*
++ * ======== MSG_FRAME ========
++ */
++struct MSG_FRAME {
++ struct LST_ELEM listElem;
++ struct MSG_DSPMSG msgData;
++} ;
++
++#endif /* _MSG_SM_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
+new file mode 100644
+index 0000000..815f695
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap.h
+@@ -0,0 +1,384 @@
++/*
++ * _tiomap.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap.h ========
++ * Description:
++ * Definitions and types private to this WMD.
++ *
++ */
++
++#ifndef _TIOMAP_
++#define _TIOMAP_
++
++#include <dspbridge/devdefs.h>
++#include <hw_defs.h>
++#include <hw_mbox.h>
++#include <dspbridge/wmdioctl.h> /* for WMDIOCTL_EXTPROC defn */
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++
++struct MAP_L4PERIPHERAL {
++ u32 physAddr;
++ u32 dspVirtAddr;
++} ;
++
++#define ARM_MAILBOX_START 0xfffcf000
++#define ARM_MAILBOX_LENGTH 0x800
++
++/* New Registers in OMAP3.1 */
++
++#define TESTBLOCK_ID_START 0xfffed400
++#define TESTBLOCK_ID_LENGTH 0xff
++
++/* ID Returned by OMAP1510 */
++#define TBC_ID_VALUE 0xB47002F
++
++#define SPACE_LENGTH 0x2000
++#define API_CLKM_DPLL_DMA 0xfffec000
++#define ARM_INTERRUPT_OFFSET 0xb00
++
++#define BIOS_24XX
++
++#define L4_PERIPHERAL_NULL 0x0
++#define DSPVA_PERIPHERAL_NULL 0x0
++
++#define MAX_LOCK_TLB_ENTRIES 15
++
++#define L4_PERIPHERAL_PRM 0x48306000 /*PRM L4 Peripheral */
++#define DSPVA_PERIPHERAL_PRM 0x1181e000
++#define L4_PERIPHERAL_SCM 0x48002000 /*SCM L4 Peripheral */
++#define DSPVA_PERIPHERAL_SCM 0x1181f000
++#define L4_PERIPHERAL_MMU 0x5D000000 /*MMU L4 Peripheral */
++#define DSPVA_PERIPHERAL_MMU 0x11820000
++#define L4_PERIPHERAL_CM 0x48004000 /* Core L4, Clock Management */
++#define DSPVA_PERIPHERAL_CM 0x1181c000
++#define L4_PERIPHERAL_PER 0x48005000 /* PER */
++#define DSPVA_PERIPHERAL_PER 0x1181d000
++
++#define L4_PERIPHERAL_GPIO1 0x48310000
++#define DSPVA_PERIPHERAL_GPIO1 0x11809000
++#define L4_PERIPHERAL_GPIO2 0x49050000
++#define DSPVA_PERIPHERAL_GPIO2 0x1180a000
++#define L4_PERIPHERAL_GPIO3 0x49052000
++#define DSPVA_PERIPHERAL_GPIO3 0x1180b000
++#define L4_PERIPHERAL_GPIO4 0x49054000
++#define DSPVA_PERIPHERAL_GPIO4 0x1180c000
++#define L4_PERIPHERAL_GPIO5 0x49056000
++#define DSPVA_PERIPHERAL_GPIO5 0x1180d000
++
++#define L4_PERIPHERAL_IVA2WDT 0x49030000
++#define DSPVA_PERIPHERAL_IVA2WDT 0x1180e000
++
++#define L4_PERIPHERAL_DISPLAY 0x48050000
++#define DSPVA_PERIPHERAL_DISPLAY 0x1180f000
++
++#define L4_PERIPHERAL_SSI 0x48058000
++#define DSPVA_PERIPHERAL_SSI 0x11804000
++#define L4_PERIPHERAL_GDD 0x48059000
++#define DSPVA_PERIPHERAL_GDD 0x11805000
++#define L4_PERIPHERAL_SS1 0x4805a000
++#define DSPVA_PERIPHERAL_SS1 0x11806000
++#define L4_PERIPHERAL_SS2 0x4805b000
++#define DSPVA_PERIPHERAL_SS2 0x11807000
++
++#define L4_PERIPHERAL_CAMERA 0x480BC000
++#define DSPVA_PERIPHERAL_CAMERA 0x11819000
++
++#define L4_PERIPHERAL_SDMA 0x48056000
++#define DSPVA_PERIPHERAL_SDMA 0x11810000 /*0x1181d000 conflicts with PER */
++
++#define L4_PERIPHERAL_UART1 0x4806a000
++#define DSPVA_PERIPHERAL_UART1 0x11811000
++#define L4_PERIPHERAL_UART2 0x4806c000
++#define DSPVA_PERIPHERAL_UART2 0x11812000
++#define L4_PERIPHERAL_UART3 0x49020000
++#define DSPVA_PERIPHERAL_UART3 0x11813000
++
++#define L4_PERIPHERAL_MCBSP1 0x48074000
++#define DSPVA_PERIPHERAL_MCBSP1 0x11814000
++#define L4_PERIPHERAL_MCBSP2 0x49022000
++#define DSPVA_PERIPHERAL_MCBSP2 0x11815000
++#define L4_PERIPHERAL_MCBSP3 0x49024000
++#define DSPVA_PERIPHERAL_MCBSP3 0x11816000
++#define L4_PERIPHERAL_MCBSP4 0x49026000
++#define DSPVA_PERIPHERAL_MCBSP4 0x11817000
++#define L4_PERIPHERAL_MCBSP5 0x48096000
++#define DSPVA_PERIPHERAL_MCBSP5 0x11818000
++
++#define L4_PERIPHERAL_GPTIMER5 0x49038000
++#define DSPVA_PERIPHERAL_GPTIMER5 0x11800000
++#define L4_PERIPHERAL_GPTIMER6 0x4903a000
++#define DSPVA_PERIPHERAL_GPTIMER6 0x11801000
++#define L4_PERIPHERAL_GPTIMER7 0x4903c000
++#define DSPVA_PERIPHERAL_GPTIMER7 0x11802000
++#define L4_PERIPHERAL_GPTIMER8 0x4903e000
++#define DSPVA_PERIPHERAL_GPTIMER8 0x11803000
++
++#define L4_PERIPHERAL_SPI1 0x48098000
++#define DSPVA_PERIPHERAL_SPI1 0x1181a000
++#define L4_PERIPHERAL_SPI2 0x4809a000
++#define DSPVA_PERIPHERAL_SPI2 0x1181b000
++
++#define L4_PERIPHERAL_MBOX 0x48094000
++#define DSPVA_PERIPHERAL_MBOX 0x11808000
++
++#define PM_GRPSEL_BASE 0x48307000
++#define DSPVA_GRPSEL_BASE 0x11821000
++
++#define L4_PERIPHERAL_SIDETONE_MCBSP2 0x49028000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP2 0x11824000
++#define L4_PERIPHERAL_SIDETONE_MCBSP3 0x4902a000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP3 0x11825000
++
++/* define a static array with L4 mappings */
++static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
++ {L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX},
++ {L4_PERIPHERAL_SCM, DSPVA_PERIPHERAL_SCM},
++ {L4_PERIPHERAL_MMU, DSPVA_PERIPHERAL_MMU},
++ {L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5},
++ {L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6},
++ {L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7},
++ {L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8},
++ {L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1},
++ {L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2},
++ {L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3},
++ {L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4},
++ {L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5},
++ {L4_PERIPHERAL_IVA2WDT, DSPVA_PERIPHERAL_IVA2WDT},
++ {L4_PERIPHERAL_DISPLAY, DSPVA_PERIPHERAL_DISPLAY},
++ {L4_PERIPHERAL_SSI, DSPVA_PERIPHERAL_SSI},
++ {L4_PERIPHERAL_GDD, DSPVA_PERIPHERAL_GDD},
++ {L4_PERIPHERAL_SS1, DSPVA_PERIPHERAL_SS1},
++ {L4_PERIPHERAL_SS2, DSPVA_PERIPHERAL_SS2},
++ {L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1},
++ {L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2},
++ {L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3},
++ {L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1},
++ {L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2},
++ {L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3},
++ {L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4},
++ {L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5},
++ {L4_PERIPHERAL_CAMERA, DSPVA_PERIPHERAL_CAMERA},
++ {L4_PERIPHERAL_SPI1, DSPVA_PERIPHERAL_SPI1},
++ {L4_PERIPHERAL_SPI2, DSPVA_PERIPHERAL_SPI2},
++ {L4_PERIPHERAL_PRM, DSPVA_PERIPHERAL_PRM},
++ {L4_PERIPHERAL_CM, DSPVA_PERIPHERAL_CM},
++ {L4_PERIPHERAL_PER, DSPVA_PERIPHERAL_PER},
++ {PM_GRPSEL_BASE, DSPVA_GRPSEL_BASE},
++ {L4_PERIPHERAL_SIDETONE_MCBSP2, DSPVA_PERIPHERAL_SIDETONE_MCBSP2},
++ {L4_PERIPHERAL_SIDETONE_MCBSP3, DSPVA_PERIPHERAL_SIDETONE_MCBSP3},
++ {L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
++};
++
++/*
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where c -> Externel Clock Command: Clk & Autoidle Disable/Enable
++ * i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
++ */
++
++/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
++#define MBX_PM_CLK_IDMASK 0x7F
++
++/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
++#define MBX_PM_CLK_CMDSHIFT 7
++
++/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
++#define MBX_PM_CLK_CMDMASK 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
++#define MBX_CORE1_RESOURCES 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
++#define MBX_CORE2_RESOURCES 1
++
++/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
++#define MBX_PM_MAX_RESOURCES 11
++
++/* Power Management Commands */
++enum BPWR_ExtClockCmd {
++ BPWR_DisableClock = 0,
++ BPWR_EnableClock,
++ BPWR_DisableAutoIdle,
++ BPWR_EnableAutoIdle
++} ;
++
++/* OMAP242x specific resources */
++enum BPWR_ExtClockId {
++ BPWR_GPTimer5 = 0x10,
++ BPWR_GPTimer6,
++ BPWR_GPTimer7,
++ BPWR_GPTimer8,
++ BPWR_WDTimer3,
++ BPWR_MCBSP1,
++ BPWR_MCBSP2,
++ BPWR_MCBSP3,
++ BPWR_MCBSP4,
++ BPWR_MCBSP5,
++ BPWR_SSI = 0x20
++} ;
++
++static const u32 BPWR_CLKID[] = {
++ (u32) BPWR_GPTimer5,
++ (u32) BPWR_GPTimer6,
++ (u32) BPWR_GPTimer7,
++ (u32) BPWR_GPTimer8,
++ (u32) BPWR_WDTimer3,
++ (u32) BPWR_MCBSP1,
++ (u32) BPWR_MCBSP2,
++ (u32) BPWR_MCBSP3,
++ (u32) BPWR_MCBSP4,
++ (u32) BPWR_MCBSP5,
++ (u32) BPWR_SSI
++};
++
++struct BPWR_Clk_t {
++ u32 clkId;
++ enum SERVICES_ClkId funClk;
++ enum SERVICES_ClkId intClk;
++} ;
++
++static const struct BPWR_Clk_t BPWR_Clks[] = {
++ {(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
++ {(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
++ {(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
++ {(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
++ {(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
++ {(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
++ {(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
++ {(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
++ {(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
++ {(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
++ {(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
++};
++
++/* Interrupt Register Offsets */
++#define INTH_IT_REG_OFFSET 0x00 /* Interrupt register offset */
++#define INTH_MASK_IT_REG_OFFSET 0x04 /* Mask Interrupt reg offset */
++
++#define DSP_MAILBOX1_INT 10
++
++/*
++ * INTH_InterruptKind_t
++ * Identify the kind of interrupt: either FIQ/IRQ
++ */
++enum INTH_InterruptKind_t {
++ INTH_IRQ = 0,
++ INTH_FIQ = 1
++} ;
++
++enum INTH_SensitiveEdge_t {
++ FALLING_EDGE_SENSITIVE = 0,
++ LOW_LEVEL_SENSITIVE = 1
++} ;
++
++/*
++ * Bit definition of Interrupt Level Registers
++ */
++
++/* Mail Box defines */
++#define MB_ARM2DSP1_REG_OFFSET 0x00
++
++#define MB_ARM2DSP1B_REG_OFFSET 0x04
++
++#define MB_DSP2ARM1B_REG_OFFSET 0x0C
++
++#define MB_ARM2DSP1_FLAG_REG_OFFSET 0x18
++
++#define MB_ARM2DSP_FLAG 0x0001
++
++#define MBOX_ARM2DSP HW_MBOX_ID_0
++#define MBOX_DSP2ARM HW_MBOX_ID_1
++#define MBOX_ARM HW_MBOX_U0_ARM
++#define MBOX_DSP HW_MBOX_U1_DSP1
++
++#define ENABLE true
++#define DISABLE false
++
++#define HIGH_LEVEL true
++#define LOW_LEVEL false
++
++/* Macro's */
++#define REG16(A) (*(REG_UWORD16 *)(A))
++
++#define ClearBit(reg, mask) (reg &= ~mask)
++#define SetBit(reg, mask) (reg |= mask)
++
++#define SetGroupBits16(reg, position, width, value) \
++ do {\
++ reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
++ reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
++ } while (0);
++
++#define ClearBitIndex(reg, index) (reg &= ~(1 << (index)))
++
++/* This mini driver's device context: */
++struct WMD_DEV_CONTEXT {
++ struct DEV_OBJECT *hDevObject; /* Handle to WCD device object. */
++ u32 dwDspBaseAddr; /* Arm's API to DSP virtual base addr */
++ /*
++ * DSP External memory prog address as seen virtually by the OS on
++ * the host side.
++ */
++ u32 dwDspExtBaseAddr; /* See the comment above */
++ u32 dwAPIRegBase; /* API memory mapped registers */
++ u32 dwDSPMmuBase; /* DSP MMU Mapped registers */
++ u32 dwMailBoxBase; /* Mail box mapped registers */
++ u32 dwAPIClkBase; /* CLK Registers */
++ u32 dwDSPClkM2Base; /* DSP Clock Module m2 */
++ u32 dwPublicRhea; /* Pub Rhea */
++ u32 dwIntAddr; /* MB INTR reg */
++ u32 dwTCEndianism; /* TC Endianism register */
++ u32 dwTestBase; /* DSP MMU Mapped registers */
++ u32 dwSelfLoop; /* Pointer to the selfloop */
++ u32 dwDSPStartAdd; /* API Boot vector */
++ u32 dwInternalSize; /* Internal memory size */
++
++ /*
++ * Processor specific info is set when prog loaded and read from DCD.
++ * [See WMD_BRD_Ctrl()] PROC info contains DSP-MMU TLB entries.
++ */
++ /* DMMU TLB entries */
++ struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
++ u32 dwBrdState; /* Last known board state. */
++ u32 ulIntMask; /* int mask */
++ u16 ioBase; /* Board I/O base */
++ u32 numTLBEntries; /* DSP MMU TLB entry counter */
++ u32 fixedTLBEntries; /* Fixed DSPMMU TLB entry count */
++
++ /* TC Settings */
++ bool tcWordSwapOn; /* Traffic Controller Word Swap */
++ struct PgTableAttrs *pPtAttrs;
++ u32 uDspPerClks;
++} ;
++
++ /*
++ * ======== WMD_TLB_DspVAToMpuPA ========
++ * Given a DSP virtual address, traverse the page table and return
++ * a corresponding MPU physical address and size.
++ */
++extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 ulVirtAddr,
++ OUT u32 *ulPhysAddr,
++ OUT u32 *sizeTlb);
++
++#endif /* _TIOMAP_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+new file mode 100644
+index 0000000..6b21047
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+@@ -0,0 +1,53 @@
++/*
++ * _tiomap_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_mmu.h ========
++ * Description:
++ * Definitions and types for the DSP MMU modules
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb: Renamed HW types. Removed dspMmuTlbEntry
++ *! 05-Jan-2004 vp: Moved the file to a platform specific folder from common.
++ *! 21-Mar-2003 sb: Added macro definition TIHEL_LARGEPAGESIZE
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_MMU_
++#define _TIOMAP_MMU_
++
++#include "_tiomap.h"
++
++/*
++ * ======== configureDspMmu ========
++ *
++ * Make DSP MMu page table entries.
++ * Note: Not utilizing Coarse / Fine page tables.
++ * SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
++ * DSP Byte address 0x40_0000 is word addr 0x20_0000.
++ */
++extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dataBasePhys,
++ u32 dspBaseVirt,
++ u32 sizeInBytes,
++ s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++#endif /* _TIOMAP_MMU_ */
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+new file mode 100644
+index 0000000..7ebd7b5
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+@@ -0,0 +1,102 @@
++/*
++ * _tiomap_pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_pwr.h ========
++ * Description:
++ * Definitions and types for the DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_PWR_
++#define _TIOMAP_PWR_
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++
++/*
++ * ======== SleepDSP =========
++ * Places the DSP in DeepSleep.
++ */
++extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 dwCmd, IN void *pArgs);
++/*
++ * ========InterruptDSP========
++ * Sends an interrupt to DSP unconditionally.
++ */
++extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
++/*
++ * ======== PostScale_DSP ========
++ * Handle Post Scale notification to DSP
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== PreScale_DSP ========
++ * Handle Pre Scale notification to DSP
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== handle_constraints_set ========
++ * Handle constraints request from DSP
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== DSP_PeripheralClocks_Disable ========
++ * This function disables all the peripheral clocks that
++ * were enabled by DSP. Call this function only when
++ * DSP is entering Hibernation or when DSP is in
++ * Error state
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSP_PeripheralClocks_Enable ========
++ * This function enables all the peripheral clocks that
++ * were requested by DSP.
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSPClkWakeupEventCtrl ========
++ * This function sets the group selction bits for while
++ * enabling/disabling.
++ */
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable);
++
++#endif /* _TIOMAP_PWR_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
+new file mode 100644
+index 0000000..47e1e5d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
+@@ -0,0 +1,46 @@
++/*
++ * _tiomap_util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_util.h ========
++ * Description:
++ * Definitions and types for the utility routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_UTIL_
++#define _TIOMAP_UTIL_
++
++/* Time out Values in uSeconds*/
++#define TIHELEN_ACKTIMEOUT 10000
++
++/* Time delay for HOM->SAM transition. */
++#define WAIT_SAM 1000000 /* in usec (1000 millisec) */
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ * The argument dwSyncAddr is set to 1 before releasing the DSP.
++ * If the DSP starts running, it will clear this location.
++ */
++extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
++
++#endif /* _TIOMAP_UTIL_ */
++
+diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
+new file mode 100644
+index 0000000..e8ffb2f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/chnl_sm.c
+@@ -0,0 +1,1100 @@
++/*
++ * chnl_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD channel module.
++ *
++ * Public Functions:
++ * WMD_CHNL_AddIOReq
++ * WMD_CHNL_CancelIO
++ * WMD_CHNL_Close
++ * WMD_CHNL_Create
++ * WMD_CHNL_Destroy
++ * WMD_CHNL_FlushIO
++ * WMD_CHNL_GetInfo
++ * WMD_CHNL_GetIOC
++ * WMD_CHNL_GetMgrInfo
++ * WMD_CHNL_Idle
++ * WMD_CHNL_Open
++ *
++ * Notes:
++ * The lower edge functions must be implemented by the WMD writer, and
++ * are declared in chnl_sm.h.
++ *
++ * Care is taken in this code to prevent simulataneous access to channel
++ * queues from
++ * 1. Threads.
++ * 2. IO_DPC(), scheduled from the IO_ISR() as an event.
++ *
++ * This is done primarily by:
++ * - Semaphores.
++ * - state flags in the channel object; and
++ * - ensuring the IO_Dispatch() routine, which is called from both
++ * CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
++ * This invariant condition is:
++ *
++ * LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
++ * and
++ * !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
++ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 29-Aug-2002 rr Changed the SYNC error code return to DSP error code return
++ * in WMD_CHNL_GetIOC.
++ *! 22-Jan-2002 ag Zero-copy support added.
++ *! CMM_CallocBuf() used for SM allocations.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
++ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
++ *! Remove #ifdef DEBUG from around channel cIOCs field.
++ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
++ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
++ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
++ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
++ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
++ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
++ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
++ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
++ *! SM addrs taken from COFF(IO) or host resource(SM).
++ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
++ *! address and length from symbols defined in the currently
++ *! loaded COFF file. See _chn_sm.h.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
++ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
++ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
++ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
++ *! of the SHM window length reported by Windows CM.
++ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
++ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
++ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
++ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
++ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
++ *! 13-Sep-1996 gp: Added performance statistics for channel.
++ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
++ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
++ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
++ *! 17-Jul-1996 gp: Started pseudo coding.
++ *! 11-Jul-1996 gp: Stubbed out.
++ */
++
++/* ----------------------------------- OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini-Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Define for This */
++#define USERMODE_ADDR PAGE_OFFSET
++
++#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
++
++/* ----------------------------------- Function Prototypes */
++static struct LST_LIST *CreateChirpList(u32 uChirps);
++
++static void FreeChirpList(struct LST_LIST *pList);
++
++static struct CHNL_IRP *MakeNewChirp(void);
++
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ */
++DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr, u32 dwArg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwState;
++ bool fIsEOS;
++ struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
++ u8 *pHostSysBuf = NULL;
++ bool fSchedDPC = false;
++ u16 wMbVal = 0;
++
++ DBG_Trace(DBG_ENTER,
++ "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
++ "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType, pChnl->uId);
++
++ fIsEOS = (cBytes == 0) ? true : false;
++
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
++ if (!(pHostBuf < (void *)USERMODE_ADDR)) {
++ pHostSysBuf = pHostBuf;
++ goto func_cont;
++ }
++ /* if addr in user mode, then copy to kernel space */
++ pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
++ if (pHostSysBuf == NULL) {
++ status = DSP_EMEMORY;
++ DBG_Trace(DBG_LEVEL7,
++ "No memory to allocate kernel buffer\n");
++ goto func_cont;
++ }
++ if (CHNL_IsOutput(pChnl->uMode)) {
++ status = copy_from_user(pHostSysBuf, pHostBuf,
++ cBufSize);
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying user buffer to "
++ "kernel, %d bytes remaining.\n",
++ status);
++ MEM_Free(pHostSysBuf);
++ pHostSysBuf = NULL;
++ status = DSP_EPOINTER;
++ }
++ }
++ }
++func_cont:
++ /* Validate args: */
++ if (pHostBuf == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
++ status = CHNL_E_NOEOS;
++ } else {
++ /* Check the channel state: only queue chirp if channel state
++ * allows */
++ dwState = pChnl->dwState;
++ if (dwState != CHNL_STATEREADY) {
++ if (dwState & CHNL_STATECANCEL) {
++ status = CHNL_E_CANCELLED;
++ } else if ((dwState & CHNL_STATEEOS)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = CHNL_E_EOS;
++ } else {
++ /* No other possible states left: */
++ DBC_Assert(0);
++ }
++ }
++ }
++ /* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
++ * channels. DPCCS is held to avoid race conditions with PCPY channels.
++ * If DPC is scheduled in process context (IO_Schedule) and any
++ * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
++ * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* This is a processor-copy channel. */
++ if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
++ /* Check buffer size on output channels for fit. */
++ if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
++ status = CHNL_E_BUFSIZE;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a free chirp: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
++ if (pChirp == NULL)
++ status = CHNL_E_NOIORPS;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Enqueue the chirp on the chnl's IORequest queue: */
++ pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
++ pChirp->pHostSysBuf = pHostSysBuf;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: for dma chans dwDspAddr contains dsp address
++ * of SM buffer.*/
++ DBC_Assert(pChnlMgr->uWordSize != 0);
++ /* DSP address */
++ pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
++ pChirp->cBytes = cBytes;
++ pChirp->cBufSize = cBufSize;
++ /* Only valid for output channel */
++ pChirp->dwArg = dwArg;
++ pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
++ CHNL_IOCSTATCOMPLETE);
++ LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
++ pChirp);
++ pChnl->cIOReqs++;
++ DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
++ /* If end of stream, update the channel state to prevent
++ * more IOR's: */
++ if (fIsEOS)
++ pChnl->dwState |= CHNL_STATEEOS;
++
++ {
++ /* Legacy DSM Processor-Copy */
++ DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
++ /* Request IO from the DSP */
++ IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
++ (CHNL_IsInput(pChnl->uMode) ?
++ IO_INPUT : IO_OUTPUT), &wMbVal);
++ fSchedDPC = true;
++ }
++ }
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ if (wMbVal != 0)
++ IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
++
++ if (fSchedDPC == true) {
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(pChnlMgr->hIOMgr);
++ }
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ */
++DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ u32 iChnl = -1;
++ CHNL_MODE uMode;
++ struct CHNL_IRP *pChirp;
++ struct CHNL_MGR *pChnlMgr = NULL;
++
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ iChnl = pChnl->uId;
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Mark this channel as cancelled, to prevent further IORequests or
++ * IORequests or dispatching. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnl->dwState |= CHNL_STATECANCEL;
++ if (LST_IsEmpty(pChnl->pIORequests))
++ goto func_cont;
++
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* Indicate we have no more buffers available for transfer: */
++ if (CHNL_IsInput(pChnl->uMode)) {
++ IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
++ } else {
++ /* Record that we no longer have output buffers
++ * available: */
++ pChnlMgr->dwOutputMask &= ~(1 << iChnl);
++ }
++ }
++ /* Move all IOR's to IOC queue: */
++ while (!LST_IsEmpty(pChnl->pIORequests)) {
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (pChirp) {
++ pChirp->cBytes = 0;
++ pChirp->status |= CHNL_IOCSTATCANCEL;
++ LST_PutTail(pChnl->pIOCompletions,
++ (struct LST_ELEM *)pChirp);
++ pChnl->cIOCs++;
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ }
++ }
++func_cont:
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ */
++DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++
++ /* Check args: */
++ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_cont;
++ }
++ {
++ /* Cancel IO: this ensures no further IO requests or
++ * notifications.*/
++ status = WMD_CHNL_CancelIO(hChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Assert I/O on this channel is now cancelled: Protects
++ * from IO_DPC. */
++ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
++ /* Invalidate channel object: Protects from
++ * CHNL_GetIOCompletion(). */
++ pChnl->dwSignature = 0x0000;
++ /* Free the slot in the channel manager: */
++ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
++ pChnl->pChnlMgr->cOpenChannels -= 1;
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ /* Reset channel event: (NOTE: hUserEvent freed in user
++ * context.). */
++ if (pChnl->hSyncEvent) {
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ SYNC_CloseEvent(pChnl->hSyncEvent);
++ pChnl->hSyncEvent = NULL;
++ }
++ /* Free I/O request and I/O completion queues: */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ pChnl->cIOReqs = 0;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ /* Release channel object. */
++ MEM_FreeObject(pChnl);
++ pChnl = NULL;
++ }
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ */
++DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = NULL;
++ s32 cChannels;
++#ifdef DEBUG
++ struct CHNL_MGR *hChnlMgr;
++#endif
++ /* Check DBC requirements: */
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->cChannels > 0);
++ DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++#ifdef DEBUG
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr == NULL);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate channel manager object: */
++ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
++ if (pChnlMgr) {
++ /* The cChannels attr must equal the # of supported
++ * chnls for each transport(# chnls for PCPY = DDMA =
++ * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
++ * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */
++ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
++ cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
++ CHNL_PCPY));
++ /* Create array of channels: */
++ pChnlMgr->apChannel = MEM_Calloc(
++ sizeof(struct CHNL_OBJECT *) *
++ cChannels, MEM_NONPAGED);
++ if (pChnlMgr->apChannel) {
++ /* Initialize CHNL_MGR object: */
++ /* Shared memory driver. */
++ pChnlMgr->dwType = CHNL_TYPESM;
++ pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
++ /* total # chnls supported */
++ pChnlMgr->cChannels = cChannels;
++ pChnlMgr->cOpenChannels = 0;
++ pChnlMgr->dwOutputMask = 0;
++ pChnlMgr->dwLastOutput = 0;
++ pChnlMgr->hDevObject = hDevObject;
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_InitializeDPCCS
++ (&pChnlMgr->hCSObj);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ WMD_CHNL_Destroy(pChnlMgr);
++ *phChnlMgr = NULL;
++ } else {
++ /* Return channel manager object to caller... */
++ *phChnlMgr = pChnlMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ u32 iChnl;
++
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Close all open channels: */
++ for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
++ if (DSP_SUCCEEDED
++ (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
++ DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
++ }
++ }
++ /* release critical section */
++ if (pChnlMgr->hCSObj)
++ SYNC_DeleteCS(pChnlMgr->hCSObj);
++
++ /* Free channel manager object: */
++ if (pChnlMgr->apChannel)
++ MEM_Free(pChnlMgr->apChannel);
++
++ /* Set hChnlMgr to NULL in device object. */
++ DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
++ /* Free this Chnl Mgr object: */
++ MEM_FreeObject(hChnlMgr);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * purpose:
++ * Flushes all the outstanding data requests on a channel.
++ */
++DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ CHNL_MODE uMode = -1;
++ struct CHNL_MGR *pChnlMgr;
++ struct CHNL_IOC chnlIOC;
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ if ((dwTimeOut == CHNL_IOCNOWAIT)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = DSP_EINVALIDARG;
++ } else {
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: Currently, if another thread continues to add IO
++ * requests to this channel, this function will continue to
++ * flush all such queued IO requests. */
++ if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
++ /* Wait for IO completions, up to the specified
++ * timeout: */
++ while (!LST_IsEmpty(pChnl->pIORequests) &&
++ DSP_SUCCEEDED(status)) {
++ status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
++ &chnlIOC);
++ if (DSP_FAILED(status))
++ continue;
++
++ if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
++ status = CHNL_E_WAITTIMEOUT;
++
++ }
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++ /* Now, leave the channel in the ready state: */
++ pChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++ }
++ DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ */
++DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ if (pInfo != NULL) {
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ /* Return the requested information: */
++ pInfo->hChnlMgr = pChnl->pChnlMgr;
++ pInfo->hEvent = pChnl->hUserEvent;
++ pInfo->dwID = pChnl->uId;
++ pInfo->dwMode = pChnl->uMode;
++ pInfo->cPosition = pChnl->cBytesMoved;
++ pInfo->hProcess = pChnl->hProcess;
++ pInfo->hSyncEvent = pChnl->hSyncEvent;
++ pInfo->cIOCs = pChnl->cIOCs;
++ pInfo->cIOReqs = pChnl->cIOReqs;
++ pInfo->dwState = pChnl->dwState;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Optionally wait for I/O completion on a channel. Dequeue an I/O
++ * completion record, which contains information about the completed
++ * I/O request.
++ * Note: Ensures Channel Invariant (see notes above).
++ */
++DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp;
++ DSP_STATUS statSync;
++ bool fDequeueIOC = true;
++ struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
++ u8 *pHostSysBuf = NULL;
++
++ DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
++ "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType);
++ /* Check args: */
++ if (pIOC == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (dwTimeOut == CHNL_IOCNOWAIT) {
++ if (LST_IsEmpty(pChnl->pIOCompletions))
++ status = CHNL_E_NOIOC;
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ ioc.status = CHNL_IOCSTATCOMPLETE;
++ if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
++ if (dwTimeOut == CHNL_IOCINFINITE)
++ dwTimeOut = SYNC_INFINITE;
++
++ statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
++ if (statSync == DSP_ETIMEOUT) {
++ /* No response from DSP */
++ ioc.status |= CHNL_IOCSTATTIMEOUT;
++ fDequeueIOC = false;
++ } else if (statSync == DSP_EFAIL) {
++ /* This can occur when the user mode thread is
++ * aborted (^C), or when _VWIN32_WaitSingleObject()
++ * fails due to unkown causes. */
++ /* Even though Wait failed, there may be something in
++ * the Q: */
++ if (LST_IsEmpty(pChnl->pIOCompletions)) {
++ ioc.status |= CHNL_IOCSTATCANCEL;
++ fDequeueIOC = false;
++ }
++ }
++ }
++ /* See comment in AddIOReq */
++ SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (fDequeueIOC) {
++ /* Dequeue IOC and set pIOC; */
++ DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
++ /* Update pIOC from channel state and chirp: */
++ if (pChirp) {
++ pChnl->cIOCs--;
++ /* If this is a zero-copy channel, then set IOC's pBuf
++ * to the DSP's address. This DSP address will get
++ * translated to user's virtual addr later. */
++ {
++ pHostSysBuf = pChirp->pHostSysBuf;
++ ioc.pBuf = pChirp->pHostUserBuf;
++ }
++ ioc.cBytes = pChirp->cBytes;
++ ioc.cBufSize = pChirp->cBufSize;
++ ioc.dwArg = pChirp->dwArg;
++ ioc.status |= pChirp->status;
++ /* Place the used chirp on the free list: */
++ LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
++ pChirp);
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ }
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ ioc.dwArg = 0;
++ ioc.cBufSize = 0;
++ }
++ /* Ensure invariant: If any IOC's are queued for this channel... */
++ if (!LST_IsEmpty(pChnl->pIOCompletions)) {
++ /* Since DSPStream_Reclaim() does not take a timeout
++ * parameter, we pass the stream's timeout value to
++ * WMD_CHNL_GetIOC. We cannot determine whether or not
++ * we have waited in User mode. Since the stream's timeout
++ * value may be non-zero, we still have to set the event.
++ * Therefore, this optimization is taken out.
++ *
++ * if (dwTimeOut == CHNL_IOCNOWAIT) {
++ * ... ensure event is set..
++ * SYNC_SetEvent(pChnl->hSyncEvent);
++ * } */
++ SYNC_SetEvent(pChnl->hSyncEvent);
++ } else {
++ /* else, if list is empty, ensure event is reset. */
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
++ if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
++ if (!(ioc.pBuf < (void *) USERMODE_ADDR))
++ goto func_cont;
++
++ /* If the addr is in user mode, then copy it */
++ if (!pHostSysBuf || !ioc.pBuf) {
++ status = DSP_EPOINTER;
++ DBG_Trace(DBG_LEVEL7,
++ "System buffer NULL in IO completion.\n");
++ goto func_cont;
++ }
++ if (!CHNL_IsInput(pChnl->uMode))
++ goto func_cont1;
++
++ /*pHostUserBuf */
++ status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
++#ifndef RES_CLEANUP_DISABLE
++ if (status) {
++ if (current->flags & PF_EXITING) {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags == PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ status = 0;
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags != PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ }
++ }
++#endif
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying kernel buffer to user, %d"
++ " bytes remaining. in_interupt %d\n",
++ status, in_interrupt());
++ status = DSP_EPOINTER;
++ }
++func_cont1:
++ MEM_Free(pHostSysBuf);
++ }
++func_cont:
++ /* Update User's IOC block: */
++ *pIOC = ioc;
++func_end:
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Retrieve information related to the channel manager.
++ */
++DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
++ OUT struct CHNL_MGRINFO *pMgrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
++
++ if (pMgrInfo != NULL) {
++ if (uChnlID <= CHNL_MAXCHANNELS) {
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Return the requested information: */
++ pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
++ pMgrInfo->cOpenChannels = pChnlMgr->
++ cOpenChannels;
++ pMgrInfo->dwType = pChnlMgr->dwType;
++ /* total # of chnls */
++ pMgrInfo->cChannels = pChnlMgr->cChannels;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = CHNL_E_BADCHANID;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Idles a particular channel.
++ */
++DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ bool fFlush)
++{
++ CHNL_MODE uMode;
++ struct CHNL_MGR *pChnlMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
++
++ uMode = hChnl->uMode;
++ pChnlMgr = hChnl->pChnlMgr;
++
++ if (CHNL_IsOutput(uMode) && !fFlush) {
++ /* Wait for IO completions, up to the specified timeout: */
++ status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++
++ /* Reset the byte count and put channel back in ready state. */
++ hChnl->cBytesMoved = 0;
++ hChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Open a new half-duplex channel to the DSP board.
++ */
++DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
++ u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ struct CHNL_OBJECT *pChnl = NULL;
++ struct SYNC_ATTRS *pSyncAttrs = NULL;
++ struct SYNC_OBJECT *hSyncEvent = NULL;
++ /* Ensure DBC requirements: */
++ DBC_Require(phChnl != NULL);
++ DBC_Require(pAttrs != NULL);
++ *phChnl = NULL;
++ /* Validate Args: */
++ if (pAttrs->uIOReqs == 0) {
++ status = DSP_EINVALIDARG;
++ } else {
++ if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uChnlId != CHNL_PICKFREE) {
++ if (uChnlId >= pChnlMgr->cChannels) {
++ status = CHNL_E_BADCHANID;
++ } else if (pChnlMgr->apChannel[uChnlId] !=
++ NULL) {
++ status = CHNL_E_CHANBUSY;
++ }
++ } else {
++ /* Check for free channel */
++ status = SearchFreeChannel(pChnlMgr, &uChnlId);
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ DBC_Assert(uChnlId < pChnlMgr->cChannels);
++ /* Create channel object: */
++ MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
++ if (!pChnl) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /* Protect queues from IO_DPC: */
++ pChnl->dwState = CHNL_STATECANCEL;
++ /* Allocate initial IOR and IOC queues: */
++ pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
++ pChnl->pIORequests = CreateChirpList(0);
++ pChnl->pIOCompletions = CreateChirpList(0);
++ pChnl->cChirps = pAttrs->uIOReqs;
++ pChnl->cIOCs = 0;
++ pChnl->cIOReqs = 0;
++ status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ status = NTFY_Create(&pChnl->hNtfy);
++ if (DSP_FAILED(status)) {
++ /* The only failure that could have occurred */
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pChnl->pIOCompletions && pChnl->pIORequests &&
++ pChnl->pFreeList) {
++ /* Initialize CHNL object fields: */
++ pChnl->pChnlMgr = pChnlMgr;
++ pChnl->uId = uChnlId;
++ pChnl->uMode = uMode;
++ pChnl->hUserEvent = hSyncEvent; /* for Linux */
++ pChnl->hSyncEvent = hSyncEvent;
++ /* get the process handle */
++ pChnl->hProcess = current->pid;
++ pChnl->pCBArg = 0;
++ pChnl->cBytesMoved = 0;
++ /* Default to proc-copy */
++ pChnl->uChnlType = CHNL_PCPY;
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EINVALIDARG;
++ }
++ if (DSP_FAILED(status)) {
++ /* Free memory */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ if (hSyncEvent) {
++ SYNC_CloseEvent(hSyncEvent);
++ hSyncEvent = NULL;
++ }
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ MEM_FreeObject(pChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert channel object in channel manager: */
++ pChnlMgr->apChannel[pChnl->uId] = pChnl;
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnlMgr->cOpenChannels++;
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ /* Return result... */
++ pChnl->dwSignature = CHNL_SIGNATURE;
++ pChnl->dwState = CHNL_STATEREADY;
++ *phChnl = pChnl;
++ }
++func_end:
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
++ (*phChnl == NULL));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Registers for events on a particular channel.
++ */
++DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
++
++ status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ return status;
++}
++
++/*
++ * ======== CreateChirpList ========
++ * Purpose:
++ * Initialize a queue of channel I/O Request/Completion packets.
++ * Parameters:
++ * uChirps: Number of Chirps to allocate.
++ * Returns:
++ * Pointer to queue of IRPs, or NULL.
++ * Requires:
++ * Ensures:
++ */
++static struct LST_LIST *CreateChirpList(u32 uChirps)
++{
++ struct LST_LIST *pChirpList;
++ struct CHNL_IRP *pChirp;
++ u32 i;
++
++ pChirpList = LST_Create();
++
++ if (pChirpList) {
++ /* Make N chirps and place on queue. */
++ for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
++ NULL); i++) {
++ LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
++ }
++
++ /* If we couldn't allocate all chirps, free those allocated: */
++ if (i != uChirps) {
++ FreeChirpList(pChirpList);
++ pChirpList = NULL;
++ }
++ }
++
++ return pChirpList;
++}
++
++/*
++ * ======== FreeChirpList ========
++ * Purpose:
++ * Free the queue of Chirps.
++ */
++static void FreeChirpList(struct LST_LIST *pChirpList)
++{
++ DBC_Require(pChirpList != NULL);
++
++ while (!LST_IsEmpty(pChirpList))
++ MEM_Free(LST_GetHead(pChirpList));
++
++ LST_Delete(pChirpList);
++}
++
++/*
++ * ======== MakeNewChirp ========
++ * Allocate the memory for a new channel IRP.
++ */
++static struct CHNL_IRP *MakeNewChirp(void)
++{
++ struct CHNL_IRP *pChirp;
++
++ pChirp = (struct CHNL_IRP *)MEM_Calloc(
++ sizeof(struct CHNL_IRP), MEM_NONPAGED);
++ if (pChirp != NULL) {
++ /* LST_InitElem only resets the list's member values. */
++ LST_InitElem(&pChirp->link);
++ }
++
++ return pChirp;
++}
++
++/*
++ * ======== SearchFreeChannel ========
++ * Search for a free channel slot in the array of channel pointers.
++ */
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl)
++{
++ DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++
++ for (i = 0; i < pChnlMgr->cChannels; i++) {
++ if (pChnlMgr->apChannel[i] == NULL) {
++ status = DSP_SOK;
++ *pdwChnl = i;
++ break;
++ }
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
+new file mode 100644
+index 0000000..325f1f1
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/io_sm.c
+@@ -0,0 +1,2011 @@
++/*
++ * io_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== io_sm.c ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ *
++ * Public Functions:
++ * WMD_IO_Create
++ * WMD_IO_Destroy
++ * WMD_IO_OnLoaded
++ * IO_AndSetValue
++ * IO_BufSize
++ * IO_CancelChnl
++ * IO_DPC
++ * IO_ISR
++ * IO_IVAISR
++ * IO_OrSetValue
++ * IO_ReadValue
++ * IO_ReadValueLong
++ * IO_RequestChnl
++ * IO_Schedule
++ * IO_WriteValue
++ * IO_WriteValueLong
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure of the WIN32_WaitSingleObject
++ * function (SYNC_WaitOnEvent).
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/workqueue.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdioctl.h>
++#include <_tiomap.h>
++#include <tiomap_io.h>
++#include <_tiomap_pwr.h>
++#include <tiomap_io.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/rms_sh.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/drv.h>
++#include "_cmm.h"
++
++/* ----------------------------------- This */
++#include <dspbridge/io_sm.h>
++#include "_msg_sm.h"
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define OUTPUTNOTREADY 0xffff
++#define NOTENABLED 0xffff /* channel(s) not enabled */
++
++#define EXTEND "_EXT_END"
++
++#define SwapWord(x) (x)
++#define ulPageAlignSize 0x10000 /* Page Align Size */
++
++#define MAX_PM_REQS 32
++
++/* IO Manager: only one created per board: */
++struct IO_MGR {
++ /* These four fields must be the first fields in a IO_MGR_ struct: */
++ u32 dwSignature; /* Used for object validation */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents */
++
++ /* These fields initialized in WMD_IO_Create(): */
++ struct CHNL_MGR *hChnlMgr;
++ struct SHM *pSharedMem; /* Shared Memory control */
++ u8 *pInput; /* Address of input channel */
++ u8 *pOutput; /* Address of output channel */
++ struct MSG_MGR *hMsgMgr; /* Message manager */
++ struct MSG *pMsgInputCtrl; /* Msg control for from DSP messages */
++ struct MSG *pMsgOutputCtrl; /* Msg control for to DSP messages */
++ u8 *pMsgInput; /* Address of input messages */
++ u8 *pMsgOutput; /* Address of output messages */
++ u32 uSMBufSize; /* Size of a shared memory I/O channel */
++ bool fSharedIRQ; /* Is this IRQ shared? */
++ struct DPC_OBJECT *hDPC; /* DPC object handle */
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u16 wIntrVal; /* interrupt value */
++ /* private extnd proc info; mmu setup */
++ struct MGR_PROCESSOREXTINFO extProcInfo;
++ struct CMM_OBJECT *hCmmMgr; /* Shared Mem Mngr */
++ struct work_struct io_workq; /*workqueue */
++ u32 dQuePowerMbxVal[MAX_PM_REQS];
++ u32 iQuePowerHead;
++ u32 iQuePowerTail;
++#ifndef DSP_TRACEBUF_DISABLED
++ u32 ulTraceBufferBegin; /* Trace message start address */
++ u32 ulTraceBufferEnd; /* Trace message end address */
++ u32 ulTraceBufferCurrent; /* Trace message current address */
++ u32 ulGPPReadPointer; /* GPP Read pointer to Trace buffer */
++ u8 *pMsg;
++ u32 ulGppVa;
++ u32 ulDspVa;
++#endif
++} ;
++
++/* ----------------------------------- Function Prototypes */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void IO_DispatchPM(struct work_struct *work);
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp);
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask);
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static struct workqueue_struct *bridge_workqueue;
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
++#endif
++
++/* Bus Addr (cached kernel)*/
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA);
++
++#ifdef CONFIG_BRIDGE_DVFS
++/* The maximum number of OPPs that are supported */
++extern s32 dsp_max_opps;
++/* The Vdd1 opp table information */
++extern u32 vdd1_dsp_freq[6][4] ;
++#endif
++
++#if GT_TRACE
++static struct GT_Mask dsp_trace_mask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== WMD_IO_Create ========
++ * Create an IO manager object.
++ */
++DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct IO_MGR *pIOMgr = NULL;
++ struct SHM *pSharedMem = NULL;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++ struct CFG_HOSTRES hostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct CHNL_MGR *hChnlMgr;
++ static int ref_count;
++ u32 devType;
++ /* Check DBC requirements: */
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr != NULL);
++ DBC_Require(hChnlMgr->hIOMgr == NULL);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ DEV_GetDevType(hDevObject, &devType);
++ /* DSP shared memory area will get set properly when
++ * a program is loaded. They are unknown until a COFF file is
++ * loaded. I chose the value -1 because it was less likely to be
++ * a valid address than 0. */
++ pSharedMem = (struct SHM *) -1;
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /*
++ * Create a Single Threaded Work Queue
++ */
++
++ if (ref_count == 0)
++ bridge_workqueue = create_workqueue("bridge_work-queue");
++
++ if (bridge_workqueue <= 0)
++ DBG_Trace(DBG_LEVEL1, "Workque Create"
++ " failed 0x%d \n", bridge_workqueue);
++
++
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
++ if (pIOMgr == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /*Intializing Work Element*/
++ if (ref_count == 0) {
++ INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++ ref_count = 1;
++ } else
++ PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++
++ /* Initialize CHNL_MGR object: */
++#ifndef DSP_TRACEBUF_DISABLED
++ pIOMgr->pMsg = NULL;
++#endif
++ pIOMgr->hChnlMgr = hChnlMgr;
++ pIOMgr->uWordSize = pMgrAttrs->uWordSize;
++ pIOMgr->pSharedMem = pSharedMem;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pIOMgr->hCSObj);
++
++ if (devType == DSP_UNIT) {
++ /* Create a DPC object: */
++ status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ pIOMgr->iQuePowerHead = 0;
++ pIOMgr->iQuePowerTail = 0;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension() , &hostRes);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr->hWmdContext = hWmdContext;
++ pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
++ IO_DisableInterrupt(hWmdContext);
++ if (devType == DSP_UNIT) {
++ /* Plug the channel ISR:. */
++ if ((request_irq(INT_MAIL_MPU_IRQ, IO_ISR, 0,
++ "DspBridge\tmailbox", (void *)pIOMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status))
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pIOMgr);
++ else
++ status = CHNL_E_ISR;
++ } else
++ status = CHNL_E_ISR;
++func_cont:
++ if (DSP_FAILED(status)) {
++ /* Cleanup: */
++ WMD_IO_Destroy(pIOMgr);
++ *phIOMgr = NULL;
++ } else {
++ /* Return IO manager object to caller... */
++ hChnlMgr->hIOMgr = pIOMgr;
++ *phIOMgr = pIOMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Disable interrupts, destroy the IO manager.
++ */
++DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
++ /* Unplug IRQ: */
++ /* Disable interrupts from the board: */
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject,
++ &hWmdContext)))
++ DBC_Assert(hWmdContext);
++ (void)CHNLSM_DisableInterrupt(hWmdContext);
++ destroy_workqueue(bridge_workqueue);
++ /* Linux function to uninstall ISR */
++ free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr);
++ (void)DPC_Destroy(hIOMgr->hDPC);
++#ifndef DSP_TRACEBUF_DISABLED
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++#endif
++ SYNC_DeleteCS(hIOMgr->hCSObj); /* Leak Fix. */
++ /* Free this IO manager object: */
++ MEM_FreeObject(hIOMgr);
++ } else
++ status = DSP_EHANDLE;
++
++ return status;
++}
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called when a new program is loaded to get shared memory buffer
++ * parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
++ * are in DSP address units.
++ */
++DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
++{
++ struct COD_MANAGER *hCodMan;
++ struct CHNL_MGR *hChnlMgr;
++ struct MSG_MGR *hMsgMgr;
++ u32 ulShmBase;
++ u32 ulShmBaseOffset;
++ u32 ulShmLimit;
++ u32 ulShmLength = -1;
++ u32 ulMemLength = -1;
++ u32 ulMsgBase;
++ u32 ulMsgLimit;
++ u32 ulMsgLength = -1;
++ u32 ulExtEnd;
++ u32 ulGppPa = 0;
++ u32 ulGppVa = 0;
++ u32 ulDspVa = 0;
++ u32 ulSegSize = 0;
++ u32 ulPadSize = 0;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 uNumProcs = 0;
++ s32 ndx = 0;
++ /* DSP MMU setup table */
++ struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
++ struct CFG_HOSTRES hostRes;
++ u32 mapAttrs;
++ u32 ulShm0End;
++ u32 ulDynExtBase;
++ u32 ulSeg1Size = 0;
++ u32 paCurr = 0;
++ u32 vaCurr = 0;
++ u32 gppVaCurr = 0;
++ u32 numBytes = 0;
++ u32 allBits = 0;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++
++ status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ hChnlMgr = hIOMgr->hChnlMgr;
++ /* The message manager is destroyed when the board is stopped. */
++ DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
++ hMsgMgr = hIOMgr->hMsgMgr;
++ DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
++ DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ if (hIOMgr->pSharedMem)
++ hIOMgr->pSharedMem = NULL;
++
++ /* Get start and length of channel part of shared memory */
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
++ &ulShmBase);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
++ &ulShmLimit);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ if (ulShmLimit <= ulShmBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* get total length in bytes */
++ ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
++ /* Calculate size of a PROCCOPY shared memory region */
++ DBG_Trace(DBG_LEVEL7,
++ "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
++ (ulShmLength - sizeof(struct SHM)));
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
++ &ulMsgBase);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
++ &ulMsgLimit);
++ if (DSP_SUCCEEDED(status)) {
++ if (ulMsgLimit <= ulMsgBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* Length (bytes) of messaging part of shared
++ * memory */
++ ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
++ hIOMgr->uWordSize;
++ /* Total length (bytes) of shared memory:
++ * chnl + msg */
++ ulMemLength = ulShmLength + ulMsgLength;
++ }
++ } else {
++ status = CHNL_E_NOMEMMAP;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++#ifndef DSP_TRACEBUF_DISABLED
++ status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
++ ulShm0End);
++#else
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
++#endif
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get memory reserved in host resources */
++ (void)MGR_EnumProcessorInfo(0,
++ (struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
++ sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
++ CFG_GetHostResources((
++ struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &hostRes);
++ /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
++ ndx = 0;
++ ulGppPa = hostRes.dwMemPhys[1];
++ ulGppVa = hostRes.dwMemBase[1];
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
++ /* Why can't we directly take the DSPVA from the symbols? */
++ ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
++ ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
++ ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
++ ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
++ ulPageAlignSize);
++ if (ulPadSize == ulPageAlignSize)
++ ulPadSize = 0x0;
++
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
++ "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
++ "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
++ ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
++ ulSeg1Size);
++
++ if ((ulSegSize + ulSeg1Size + ulPadSize) >
++ hostRes.dwMemLength[1]) {
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
++ "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
++ "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
++ ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
++ ulExtEnd, ulSegSize, ulSeg1Size);
++ DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
++ "Required 0x%x\n", hostRes.dwMemLength[1],
++ ulSegSize + ulSeg1Size + ulPadSize);
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ paCurr = ulGppPa;
++ vaCurr = ulDynExtBase * hIOMgr->uWordSize;
++ gppVaCurr = ulGppVa;
++ numBytes = ulSeg1Size;
++
++ /*
++ * Try to fit into TLB entries. If not possible, push them to page
++ * tables. It is quite possible that if sections are not on
++ * bigger page boundary, we may end up making several small pages.
++ * So, push them onto page tables, if that is the case.
++ */
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, paCurr, vaCurr,
++ pgSize[i], mapAttrs);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size*/
++ break;
++ }
++ }
++ }
++ paCurr += ulPadSize;
++ vaCurr += ulPadSize;
++ gppVaCurr += ulPadSize;
++
++ /* configure the TLB entries for the next cacheable segment */
++ numBytes = ulSegSize;
++ vaCurr = ulDspVa * hIOMgr->uWordSize;
++ allBits = 0x0;
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned*/
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
++ "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
++ numBytes);
++ for (i = 0; i < 4; i++) {
++ if (!(numBytes >= pgSize[i]) ||
++ !((allBits & (pgSize[i]-1)) == 0))
++ continue;
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ /* This is the physical address written to
++ * DSP MMU */
++ aEProc[ndx].ulGppPa = paCurr;
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
++ * ADDRESS!!! */
++ aEProc[ndx].ulGppVa = gppVaCurr;
++ aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
++ uWordSize;
++ aEProc[ndx].ulSize = pgSize[i];
++ aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
++ aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
++ aEProc[ndx].mixedMode = HW_MMU_CPUES;
++ DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap(
++ hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
++ mapAttrs);
++ DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ }
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have reached
++ an address aligned to a bigger page size*/
++ break;
++ }
++ }
++
++ /* Copy remaining entries from CDB. All entries are 1 MB and should not
++ * conflict with SHM entries on MPU or DSP side */
++ for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
++ DSP_SUCCEEDED(status); i++) {
++ if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
++ continue;
++
++ if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
++ && hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
++ ulGppPa + ulSegSize)
++ || (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
++ 0x100000 / hIOMgr->uWordSize && hIOMgr->
++ extProcInfo.tyTlb[i].ulDspVirt
++ <= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
++ DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
++ "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
++ "GppPa %x, DspVa %x, Bytes %x.\n", i,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ ulGppPa, ulDspVa, ulSegSize);
++ status = DSP_EFAIL;
++ } else {
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
++ tyTlb[i].ulDspVirt;
++ aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
++ tyTlb[i].ulGppPhys;
++ aEProc[ndx].ulGppVa = 0;
++ /* Can't convert, so set to zero*/
++ aEProc[ndx].ulSize = 0x100000; /* 1 MB*/
++ DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
++ "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulDspVa);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ 0x100000, mapAttrs);
++ }
++ }
++ }
++ if (i < 7 && DSP_SUCCEEDED(status)) {
++ /* All CDB entries could not be made*/
++ status = DSP_EFAIL;
++ }
++func_cont:
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ /* Map the L4 peripherals */
++ i = 0;
++ while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, L4PeripheralTable[i].physAddr,
++ L4PeripheralTable[i].dspVirtAddr, HW_PAGE_SIZE_4KB,
++ mapAttrs);
++ if (DSP_FAILED(status))
++ break;
++ i++;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
++ aEProc[i].ulDspVa = 0;
++ aEProc[i].ulGppPa = 0;
++ aEProc[i].ulGppVa = 0;
++ aEProc[i].ulSize = 0;
++ }
++ /* Set the SHM physical address entry (grayed out in CDB file)
++ * to the virtual uncached ioremapped address of SHM reserved
++ * on MPU */
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
++ ulPadSize);
++ DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
++ /* Need SHM Phys addr. IO supports only one DSP for now:
++ * uNumProcs=1 */
++ if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
++ (uNumProcs != 1)) {
++ status = CHNL_E_NOMEMMAP;
++ DBC_Assert(false);
++ } else {
++ DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
++ /* ulShmBase may not be at ulDspVa address */
++ ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
++ hIOMgr->uWordSize;
++ /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
++ * _BRD_Start() the MMU will be re-programed with MMU
++ * DSPVa-GPPPa pair info while DSP is in a known
++ * (reset) state. */
++ DBC_Assert(hIOMgr->pIntfFxns != NULL);
++ DBC_Assert(hIOMgr->hWmdContext != NULL);
++ status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
++ hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
++ ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
++ "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
++ ulGppPhys);
++ ulShmBase += ulShmBaseOffset;
++ ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
++ ulMemLength);
++ DBC_Assert(ulShmBase != 0);
++ if (DSP_SUCCEEDED(status)) {
++ status = registerSHMSegs(hIOMgr, hCodMan,
++ aEProc[0].ulGppPa);
++ /* Register SM */
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
++ hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
++ sizeof(struct SHM);
++ hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
++ sizeof(struct SHM))/2;
++ hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
++ DBG_Trace(DBG_LEVEL3,
++ "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
++ hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
++ DBG_Trace(DBG_LEVEL3,
++ "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
++ hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
++ sizeof(struct SHM));
++ /* Set up Shared memory addresses for messaging. */
++ hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
++ hIOMgr->pSharedMem +
++ ulShmLength);
++ hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
++ sizeof(struct MSG);
++ hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
++ pMsgInputCtrl + ulMsgLength / 2);
++ hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
++ sizeof(struct MSG);
++ hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
++ hIOMgr->pMsgInput) /
++ sizeof(struct MSG_DSPMSG);
++ DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
++ "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
++ "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
++ "0x%x \n", (u8 *)hIOMgr->pSharedMem,
++ (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
++ (u8 *)hIOMgr->pMsgInputCtrl,
++ (u8 *)hIOMgr->pMsgInput,
++ (u8 *)hIOMgr->pMsgOutputCtrl,
++ (u8 *)hIOMgr->pMsgOutput);
++ DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
++ "0x%x\n", hMsgMgr->uMaxMsgs);
++ memset((void *) hIOMgr->pSharedMem, 0, sizeof(struct SHM));
++ }
++#ifndef DSP_TRACEBUF_DISABLED
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the start address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
++ &hIOMgr->ulTraceBufferBegin);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
++ (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferBegin - ulDspVa);
++ /* Get the end address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
++ &hIOMgr->ulTraceBufferEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferEnd - ulDspVa);
++ /* Get the current address of DSP write pointer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan,
++ BRIDGE_SYS_PUTC_current,
++ &hIOMgr->ulTraceBufferCurrent);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
++ ulPadSize) + (hIOMgr->
++ ulTraceBufferCurrent - ulDspVa);
++ /* Calculate the size of trace buffer */
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++ hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulTraceBufferBegin) *
++ hIOMgr->uWordSize) + 2, MEM_NONPAGED);
++ if (!hIOMgr->pMsg)
++ status = DSP_EMEMORY;
++
++ DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
++ hIOMgr->ulDspVa = ulDspVa;
++ hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
++ }
++#endif
++ IO_EnableInterrupt(hIOMgr->hWmdContext);
++ return status;
++}
++
++/*
++ * ======== IO_BufSize ========
++ * Size of shared memory I/O channel.
++ */
++u32 IO_BufSize(struct IO_MGR *hIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++
++ return hIOMgr->uSMBufSize;
++}
++
++/*
++ * ======== IO_CancelChnl ========
++ * Cancel IO on a given PCPY channel.
++ */
++void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
++ struct SHM *sm;
++
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ sm = hIOMgr->pSharedMem;
++
++ /* Inform DSP that we have no more buffers on this channel: */
++ IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (~(1 << ulChnl)));
++
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++}
++
++/*
++ * ======== IO_DispatchChnl ========
++ * Proc-copy chanl dispatch.
++ */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
++
++ /* See if there is any data available for transfer: */
++ DBC_Assert(iMode == IO_SERVICE);
++
++ /* Any channel will do for this mode: */
++ InputChnl(pIOMgr, pChnl, iMode);
++ OutputChnl(pIOMgr, pChnl, iMode);
++}
++
++/*
++ * ======== IO_DispatchMsg ========
++ * Performs I/O dispatch on message queues.
++ */
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
++
++ /* We are performing both input and output processing. */
++ InputMsg(pIOMgr, hMsgMgr);
++ OutputMsg(pIOMgr, hMsgMgr);
++}
++
++/*
++ * ======== IO_DispatchPM ========
++ * Performs I/O dispatch on PM related messages from DSP
++ */
++static void IO_DispatchPM(struct work_struct *work)
++{
++ struct IO_MGR *pIOMgr =
++ container_of(work, struct IO_MGR, io_workq);
++ DSP_STATUS status;
++ u32 pArg[2];
++
++ /*DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));*/
++
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
++
++ /* Perform Power message processing here */
++ while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
++ pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
++ iQuePowerTail]);
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
++ pArg[0]);
++ /* Send the command to the WMD clk/pwr manager to handle */
++ if (pArg[0] == MBX_PM_HIBERNATE_EN) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
++ "command\n");
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
++ "Hibernation command failed\n");
++ }
++ } else if (pArg[0] == MBX_PM_OPP_REQ) {
++ pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
++ "value =0x%x \n", pArg[1]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
++ pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to set constraint = 0x%x \n",
++ pArg[1]);
++ }
++
++ } else {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
++ "value of msg = 0x%x: \n", pArg[0]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to control the DSP clk = 0x%x \n",
++ *pArg);
++ }
++ }
++ /* increment the tail count here */
++ pIOMgr->iQuePowerTail++;
++ if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
++ pIOMgr->iQuePowerTail = 0;
++
++ }
++
++}
++
++/*
++ * ======== IO_DPC ========
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O as a non-preemptible event.It can only be
++ * pre-empted by an ISR.
++ */
++void IO_DPC(IN OUT void *pRefData)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
++ struct CHNL_MGR *pChnlMgr;
++ struct MSG_MGR *pMsgMgr;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++ pChnlMgr = pIOMgr->hChnlMgr;
++ DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
++ DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
++ /* Check value of interrupt register to ensure it is a valid error */
++ if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
++ /* notify DSP/BIOS exception */
++ if (hDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
++
++ }
++ IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
++#ifdef CHNL_MESSAGES
++ if (pMsgMgr) {
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++ IO_DispatchMsg(pIOMgr, pMsgMgr);
++ }
++#endif
++#ifndef DSP_TRACEBUF_DISABLED
++ if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
++ /* notify DSP Trace message */
++ if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
++ PrintDSPDebugTrace(pIOMgr);
++ }
++#endif
++
++#ifndef DSP_TRACEBUF_DISABLED
++ PrintDSPDebugTrace(pIOMgr);
++#endif
++}
++
++
++/*
++ * ======== IO_ISR ========
++ * Main interrupt handler for the shared memory IO manager.
++ * Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O.
++ */
++irqreturn_t IO_ISR(int irq, IN void *pRefData)
++{
++ struct IO_MGR *hIOMgr = (struct IO_MGR *)pRefData;
++ bool fSchedDPC;
++ DBC_Require(irq == INT_MAIL_MPU_IRQ);
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
++
++ /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
++ if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
++ {
++ DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
++ if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
++ hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
++ hIOMgr->wIntrVal;
++ hIOMgr->iQuePowerHead++;
++ if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
++ hIOMgr->iQuePowerHead = 0;
++
++ queue_work(bridge_workqueue, &hIOMgr->io_workq);
++ }
++ if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
++ DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
++ hIOMgr->wIntrVal = 0;
++ } else if (fSchedDPC) {
++ /* PROC-COPY defer i/o */
++ DPC_Schedule(hIOMgr->hDPC);
++ }
++ }
++ } else
++ /* Ensure that, if WMD didn't claim it, the IRQ is shared. */
++ DBC_Ensure(hIOMgr->fSharedIRQ);
++ return IRQ_HANDLED;
++}
++
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request chanenel I/O from the DSP. Sets flags in shared memory, then
++ * interrupts the DSP.
++ */
++void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ DBC_Require(pChnl != NULL);
++ DBC_Require(pwMbVal != NULL);
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ if (iMode == IO_INPUT) {
++ /* Assertion fires if CHNL_AddIOReq() called on a stream
++ * which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
++ (pChnl->dwState == CHNL_STATEEOS));
++ /* Indicate to the DSP we have a buffer available for input: */
++ IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (1 << pChnl->uId));
++ *pwMbVal = MBX_PCPY_CLASS;
++ } else if (iMode == IO_OUTPUT) {
++ /* This assertion fails if CHNL_AddIOReq() was called on a
++ * stream which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
++ CHNL_STATEREADY);
++ /* Record the fact that we have a buffer available for
++ * output: */
++ pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
++ } else {
++ DBC_Assert(iMode); /* Shouldn't get here. */
++ }
++}
++
++/*
++ * ======== IO_Schedule ========
++ * Schedule DPC for IO.
++ */
++void IO_Schedule(struct IO_MGR *pIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DPC_Schedule(pIOMgr->hDPC);
++}
++
++/*
++ * ======== FindReadyOutput ========
++ * Search for a host output channel which is ready to send. If this is
++ * called as a result of servicing the DPC, then implement a round
++ * robin search; otherwise, this was called by a client thread (via
++ * IO_Dispatch()), so just start searching from the current channel id.
++ */
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask)
++{
++ u32 uRetval = OUTPUTNOTREADY;
++ u32 id, startId;
++ u32 shift;
++
++ id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ DBC_Assert(id < CHNL_MAXCHANNELS);
++ if (dwMask) {
++ shift = (1 << id);
++ startId = id;
++ do {
++ if (dwMask & shift) {
++ uRetval = id;
++ if (pChnl == NULL)
++ pChnlMgr->dwLastOutput = id;
++
++ break;
++ }
++ id = id + 1;
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ shift = (1 << id);
++ } while (id != startId);
++ }
++ DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
++ return uRetval;
++}
++
++/*
++ * ======== InputChnl ========
++ * Dispatch a buffer on an input channel.
++ */
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ u32 uBytes;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwArg;
++ bool fClearChnl = false;
++ bool fNotifyClient = false;
++
++ sm = pIOMgr->pSharedMem;
++ pChnlMgr = pIOMgr->hChnlMgr;
++
++ DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
++
++ /* Attempt to perform input.... */
++ if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
++ goto func_end;
++
++ uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
++ pChnlMgr->uWordSize;
++ chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
++ dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
++ if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
++ /* Shouldn't be here: would indicate corrupted SHM. */
++ DBC_Assert(chnlId);
++ goto func_end;
++ }
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
++ if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
++ if (!pChnl->pIORequests)
++ goto func_end;
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
++ pIORequests);
++ if (pChirp) {
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ /* Ensure we don't overflow the client's
++ * buffer: */
++ uBytes = min(uBytes, pChirp->cBytes);
++ /* Transfer buffer from DSP side: */
++ uBytes = ReadData(pIOMgr->hWmdContext,
++ pChirp->pHostSysBuf,
++ pIOMgr->pInput, uBytes);
++ pChnl->cBytesMoved += uBytes;
++ pChirp->cBytes = uBytes;
++ pChirp->dwArg = dwArg;
++ pChirp->status = CHNL_IOCSTATCOMPLETE;
++ DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
++ "\n", *((RMS_WORD *)(pChirp->
++ pHostSysBuf)));
++ if (uBytes == 0) {
++ /* This assertion fails if the DSP
++ * sends EOS more than once on this
++ * channel: */
++ DBC_Assert(!(pChnl->dwState &
++ CHNL_STATEEOS));
++ /* Zero bytes indicates EOS. Update
++ * IOC status for this chirp, and also
++ * the channel state: */
++ pChirp->status |= CHNL_IOCSTATEOS;
++ pChnl->dwState |= CHNL_STATEEOS;
++ /* Notify that end of stream has
++ * occurred */
++ NTFY_Notify(pChnl->hNtfy,
++ DSP_STREAMDONE);
++ DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
++ "chnl = 0x%x\n", pChnl);
++ }
++ /* Tell DSP if no more I/O buffers available: */
++ if (!pChnl->pIORequests)
++ goto func_end;
++ if (LST_IsEmpty(pChnl->pIORequests)) {
++ IO_AndValue(pIOMgr->hWmdContext,
++ struct SHM, sm, hostFreeMask,
++ ~(1 << pChnl->uId));
++ }
++ fClearChnl = true;
++ fNotifyClient = true;
++ } else {
++ /* Input full for this channel, but we have no
++ * buffers available. The channel must be
++ * "idling". Clear out the physical input
++ * channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* Input channel cancelled: clear input channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* DPC fired after host closed channel: clear input channel. */
++ fClearChnl = true;
++ }
++ if (fClearChnl) {
++ /* Indicate to the DSP we have read the input: */
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ if (fNotifyClient) {
++ /* Notify client with IO completion record: */
++ NotifyChnlComplete(pChnl, pChirp);
++ }
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
++}
++
++/*
++ * ======== InputMsg ========
++ * Copies messages from shared memory to the message queues.
++ */
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs;
++ u32 i;
++ u8 *pMsgInput;
++ struct MSG_QUEUE *hMsgQueue;
++ struct MSG_FRAME *pMsg;
++ struct MSG_DSPMSG msg;
++ struct MSG *pCtrl;
++ u32 fInputEmpty;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgInputCtrl;
++ /* Get the number of input messages to be read. */
++ fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
++ if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
++ return;
++
++ pMsgInput = pIOMgr->pMsgInput;
++ for (i = 0; i < uMsgs; i++) {
++ /* Read the next message */
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
++ msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
++ msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
++ msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
++ msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ pMsgInput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->queueList)
++ goto func_end;
++
++ /* Determine which queue to put the message in */
++ hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
++ DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
++ "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
++ msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
++ /* Interrupt may occur before shared memory and message
++ * input locations have been set up. If all nodes were
++ * cleaned up, hMsgMgr->uMaxMsgs should be 0. */
++ if (hMsgQueue && uMsgs > hMsgMgr->uMaxMsgs)
++ goto func_end;
++
++ while (hMsgQueue != NULL) {
++ if (msg.dwId == hMsgQueue->dwId) {
++ /* Found it */
++ if (msg.msg.dwCmd == RMS_EXITACK) {
++ /* The exit message does not get
++ * queued */
++ /* Call the node exit notification */
++ /* Node handle */ /* status */
++ (*hMsgMgr->onExit)((HANDLE)hMsgQueue->
++ hArg, msg.msg.dwArg1);
++ } else {
++ /* Not an exit acknowledgement, queue
++ * the message */
++ if (!hMsgQueue->msgFreeList)
++ goto func_end;
++ pMsg = (struct MSG_FRAME *)LST_GetHead
++ (hMsgQueue->msgFreeList);
++ if (hMsgQueue->msgUsedList && pMsg) {
++ pMsg->msgData = msg;
++ LST_PutTail(hMsgQueue->
++ msgUsedList,
++ (struct LST_ELEM *)pMsg);
++ NTFY_Notify(hMsgQueue->hNtfy,
++ DSP_NODEMESSAGEREADY);
++ SYNC_SetEvent(hMsgQueue->
++ hSyncEvent);
++ } else {
++ /* No free frame to copy the
++ * message into */
++ DBG_Trace(DBG_LEVEL7, "NO FREE "
++ "MSG FRAMES, DISCARDING"
++ " MESSAGE\n");
++ }
++ }
++ break;
++ }
++
++ if (!hMsgMgr->queueList || !hMsgQueue)
++ goto func_end;
++ hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
++ queueList, (struct LST_ELEM *)hMsgQueue);
++ }
++ }
++ /* Set the post SWI flag */
++ if (uMsgs > 0) {
++ /* Tell the DSP we've read the messages */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
++ true);
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
++ true);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== NotifyChnlComplete ========
++ * Purpose:
++ * Signal the channel event, notifying the client that I/O has completed.
++ */
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp)
++{
++ bool fSignalEvent;
++
++ DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ DBC_Require(pChnl->hSyncEvent != NULL);
++ /* Note: we signal the channel event only if the queue of IO
++ * completions is empty. If it is not empty, the event is sure to be
++ * signalled by the only IO completion list consumer:
++ * WMD_CHNL_GetIOC(). */
++ fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
++ /* Enqueue the IO completion info for the client: */
++ LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
++ pChnl->cIOCs++;
++ DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
++ /* Signal the channel event (if not already set) that IO is complete: */
++ if (fSignalEvent)
++ SYNC_SetEvent(pChnl->hSyncEvent);
++
++ /* Notify that IO is complete */
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
++}
++
++/*
++ * ======== OutputChnl ========
++ * Purpose:
++ * Dispatch a buffer on an output channel.
++ */
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ struct CHNL_IRP *pChirp;
++ u32 dwDspFMask;
++
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
++ /* Attempt to perform output: */
++ if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
++ goto func_end;
++
++ if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
++ goto func_end;
++
++ /* Look to see if both a PC and DSP output channel are ready: */
++ dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
++ dspFreeMask);
++ chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
++ dwDspFMask));
++ if (chnlId == OUTPUTNOTREADY)
++ goto func_end;
++
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if (!pChnl || !pChnl->pIORequests) {
++ /* Shouldn't get here: */
++ goto func_end;
++ }
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (!pChirp)
++ goto func_end;
++
++ pChnl->cIOReqs--;
++ if (pChnl->cIOReqs < 0 || !pChnl->pIORequests)
++ goto func_end;
++
++ /* Record fact that no more I/O buffers available: */
++ if (LST_IsEmpty(pChnl->pIORequests))
++ pChnlMgr->dwOutputMask &= ~(1 << chnlId);
++
++ /* Transfer buffer to DSP side: */
++ pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
++ pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
++ cBytes));
++ pChnl->cBytesMoved += pChirp->cBytes;
++ /* Write all 32 bits of arg */
++ IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
++ (u16)chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
++ (u16)pChnlMgr->uWordSize);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
++ uWordSize);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
++ /* Indicate to the DSP we have written the output: */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ /* Notify client with IO completion record (keep EOS) */
++ pChirp->status &= CHNL_IOCSTATEOS;
++ NotifyChnlComplete(pChnl, pChirp);
++ /* Notify if stream is done. */
++ if (pChirp->status & CHNL_IOCSTATEOS)
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
++
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
++}
++/*
++ * ======== OutputMsg ========
++ * Copies messages from the message queues to the shared memory.
++ */
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs = 0;
++ u32 i;
++ u8 *pMsgOutput;
++ struct MSG_FRAME *pMsg;
++ struct MSG *pCtrl;
++ u32 fOutputEmpty;
++ u32 val;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgOutputCtrl;
++
++ /* Check if output has been cleared */
++ fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ if (fOutputEmpty) {
++ uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
++ hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
++ pMsgOutput = pIOMgr->pMsgOutput;
++ /* Copy uMsgs messages into shared memory */
++ for (i = 0; i < uMsgs; i++) {
++ if (!hMsgMgr->msgUsedList) {
++ DBG_Trace(DBG_LEVEL3, "msgUsedList is NULL\n");
++ pMsg = NULL;
++ goto func_end;
++ } else
++ pMsg = (struct MSG_FRAME *)LST_GetHead(
++ hMsgMgr->msgUsedList);
++ if (pMsg != NULL) {
++ val = (pMsg->msgData).dwId;
++ addr = (u32)&(((struct MSG_DSPMSG *)
++ pMsgOutput)->dwId);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwCmd;
++ addr = (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwCmd);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg1;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg1);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg2;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg2);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ pMsgOutput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->msgFreeList)
++ goto func_end;
++ LST_PutTail(hMsgMgr->msgFreeList,
++ (struct LST_ELEM *) pMsg);
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++ } else {
++ DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
++ }
++ }
++
++ if (uMsgs > 0) {
++ hMsgMgr->uMsgsPending -= uMsgs;
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, (u16)uMsgs);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, uMsgs);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty, false);
++ /* Set the post SWI flag */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ postSWI, true);
++ /* Tell the DSP we have written the output. */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== registerSHMSegs ========
++ * purpose:
++ * Registers GPP SM segment with CMM.
++ */
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 ulShm0_Base = 0;
++ u32 ulShm0_End = 0;
++ u32 ulShm0_RsrvdStart = 0;
++ u32 ulRsrvdSize = 0;
++ u32 ulGppPhys;
++ u32 ulDspVirt;
++ u32 ulShmSegId0 = 0;
++ u32 dwOffset, dwGPPBaseVA, ulDSPSize;
++
++ /* Read address and size info for first SM region.*/
++ /* Get start of 1st SM Heap region */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
++ DBC_Assert(ulShm0_Base != 0);
++ /* Get end of 1st SM Heap region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0_End);
++ DBC_Assert(ulShm0_End != 0);
++ }
++ /* start of Gpp reserved region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
++ &ulShm0_RsrvdStart);
++ DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart 0x%x \n",
++ ulShm0_RsrvdStart);
++ DBC_Assert(ulShm0_RsrvdStart != 0);
++ }
++ /* Register with CMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
++ CMM_ALLSEGMENTS);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
++ "Un-Register SM segments \n");
++ }
++ } else {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
++ "Handle \n");
++ }
++ }
++ /* Register new SM region(s) */
++ if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
++ /* calc size (bytes) of SM the GPP can alloc from */
++ ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulRsrvdSize > 0);
++ /* calc size of SM DSP can alloc from */
++ ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulDSPSize > 0);
++ /* First TLB entry reserved for Bridge SM use.*/
++ ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ /* get size in bytes */
++ ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
++ uWordSize;
++ /* Calc byte offset used to convert GPP phys <-> DSP byte
++ * address.*/
++ if (dwGPPBasePA > ulDspVirt)
++ dwOffset = dwGPPBasePA - ulDspVirt;
++ else
++ dwOffset = ulDspVirt - dwGPPBasePA;
++
++ DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is actually uncached kernel virtual address*/
++ dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
++ - ulDspVirt;
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is the physical address*/
++ dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
++ uWordSize - ulDspVirt;
++ /* Register SM Segment 0.*/
++ status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
++ ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
++ CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
++ (u32)(ulShm0_Base * hIOMgr->uWordSize),
++ ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
++ "Seg 0 \n");
++ }
++ /* first SM region is segId = 1 */
++ DBC_Assert(ulShmSegId0 == 1);
++ }
++ return status;
++}
++
++/*
++ * ======== ReadData ========
++ * Copies buffers from the shared memory to the host buffer.
++ */
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/*
++ * ======== WriteData ========
++ * Copies buffers from the host side buffer to the shared memory.
++ */
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/* ZCPY IO routines. */
++void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
++{
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
++}
++
++/*
++ * ======== IO_SHMcontrol ========
++ * Sets the requested SHM setting.
++ */
++DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 i;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++
++ switch (desc) {
++ case SHM_CURROPP:
++ /* Update the shared memory with requested OPP information */
++ if (pArgs != NULL)
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt =
++ *(u32 *)pArgs;
++ else
++ return DSP_EFAIL;
++ break;
++ case SHM_OPPINFO:
++ /* Update the shared memory with the voltage, frequency,
++ min and max frequency values for an OPP */
++ for (i = 0; i <= dsp_max_opps; i++) {
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
++ vdd1_dsp_freq[i][0];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].voltage);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
++ frequency = vdd1_dsp_freq[i][1];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].frequency);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
++ vdd1_dsp_freq[i][2];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].minFreq);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
++ vdd1_dsp_freq[i][3];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].maxFreq);
++ }
++ hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
++ /* Update the current OPP number */
++ if (pdata->dsp_get_opp)
++ i = (*pdata->dsp_get_opp)();
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
++ DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
++ "%d\n", i);
++ break;
++ case SHM_GETOPP:
++ /* Get the OPP that DSP has requested */
++ *(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ break;
++ default:
++ break;
++
++ queue_work(bridge_workqueue,
++ &(hIOMgr->io_workq));
++ }
++#endif
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_IO_GetProcLoad ========
++ * Gets the Processor's Load information
++ */
++DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat)
++{
++ pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
++ pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
++ pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
++ pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
++
++ DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
++ "Pred Freq = %d\n", pProcStat->uCurrLoad,
++ pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
++ pProcStat->uPredictedFreq);
++ return DSP_SOK;
++}
++
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
++{
++ u32 ulNewMessageLength = 0, ulGPPCurPointer;
++
++ GT_0trace(dsp_trace_mask, GT_ENTER, "Entering PrintDSPDebugTrace\n");
++
++ while (true) {
++ /* Get the DSP current pointer */
++ ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
++ ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
++ hIOMgr->ulDspVa);
++
++ /* No new debug messages available yet */
++ if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
++ break;
++
++ /* Continuous data */
++ else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
++ ulNewMessageLength = ulGPPCurPointer - hIOMgr->
++ ulGPPReadPointer;
++
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ ulNewMessageLength);
++ hIOMgr->pMsg[ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer += ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ /* Handle trace buffer wraparound */
++ else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer);
++ ulNewMessageLength = ulGPPCurPointer -
++ hIOMgr->ulTraceBufferBegin;
++ memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer],
++ (char *)hIOMgr->ulTraceBufferBegin,
++ ulNewMessageLength);
++ hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer +
++ ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
++ ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ }
++}
++#endif
++
++/*
++ * ======== PackTraceBuffer ========
++ * Removes extra nulls from the trace buffer returned from the DSP.
++ * Works even on buffers that already are packed (null removed); but has
++ * one bug in that case -- loses the last character (replaces with '\0').
++ * Continues through conversion for full set of nBytes input characters.
++ * Parameters:
++ * lpBuf: Pointer to input/output buffer
++ * nBytes: Number of characters in the buffer
++ * ulNumWords: Number of DSP words in the buffer. Indicates potential
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * lpBuf must be a fully allocated writable block of at least nBytes.
++ * There are no more than ulNumWords extra characters needed (the number of
++ * linefeeds minus the number of NULLS in the input buffer).
++ */
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *lpTmpBuf;
++ char *lpBufStart;
++ char *lpTmpStart;
++ u32 nCnt;
++ char thisChar;
++
++ /* tmp workspace, 1 KB longer than input buf */
++ lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
++ if (lpTmpBuf == NULL) {
++ DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lpBufStart = lpBuf;
++ lpTmpStart = lpTmpBuf;
++ for (nCnt = nBytes; nCnt > 0; nCnt--) {
++ thisChar = *lpBuf++;
++ switch (thisChar) {
++ case '\0': /* Skip null bytes */
++ break;
++ case '\n': /* Convert \n to \r\n */
++ /* NOTE: do not reverse order; Some OS */
++ /* editors control doesn't understand "\n\r" */
++ *lpTmpBuf++ = '\r';
++ *lpTmpBuf++ = '\n';
++ break;
++ default: /* Copy in the actual ascii byte */
++ *lpTmpBuf++ = thisChar;
++ break;
++ }
++ }
++ *lpTmpBuf = '\0'; /* Make sure tmp buf is null terminated */
++ /* Cut output down to input buf size */
++ strncpy(lpBufStart, lpTmpStart, nBytes);
++ /*Make sure output is null terminated */
++ lpBufStart[nBytes - 1] = '\0';
++ MEM_Free(lpTmpStart);
++ }
++
++ return status;
++}
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++/*
++ * ======== PrintDspTraceBuffer ========
++ * Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * hDehMgr muse be valid. Checked in WMD_DEH_Notify.
++ */
++DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT *hWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++ struct COD_MANAGER *hCodMgr;
++ u32 ulTraceEnd;
++ u32 ulTraceBegin;
++ u32 ulNumBytes = 0;
++ u32 ulNumWords = 0;
++ u32 ulWordSize = 2;
++ CONST u32 uMaxSize = 512;
++ char *pszBuf;
++ u16 *lpszBuf;
++
++ struct WMD_DEV_CONTEXT *pWmdContext = (struct WMD_DEV_CONTEXT *)
++ hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)
++ pWmdContext->hDevObject;
++
++ status = DEV_GetCodMgr(pDevObject, &hCodMgr);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
++ status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
++ ulTraceBegin);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
++ ulTraceEnd);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
++ /* If the chip type is 55 then the addresses will be
++ * byte addresses; convert them to word addresses. */
++ if (ulNumBytes > uMaxSize)
++ ulNumBytes = uMaxSize;
++
++ /* make sure the data we request fits evenly */
++ ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumBytes 0x%x\n", ulNumBytes);
++ ulNumWords = ulNumBytes * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumWords 0x%x\n", ulNumWords);
++ status = DEV_GetIntfFxns(pDevObject, &pIntfFxns);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
++ lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
++ if (pszBuf != NULL) {
++ /* Read bytes from the DSP trace buffer... */
++ status = (*pIntfFxns->pfnBrdRead)(hWmdContext,
++ (u8 *)pszBuf, (u32)ulTraceBegin,
++ ulNumBytes, 0);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "Failed to Read Trace Buffer.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Pack and do newline conversion */
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "before pack and unpack.\n");
++ PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
++ GT_1trace(dsp_trace_mask, GT_1CLASS,
++ "DSP Trace Buffer:\n%s\n", pszBuf);
++ }
++ MEM_Free(pszBuf);
++ MEM_Free(lpszBuf);
++ } else {
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed to "
++ "allocate trace buffer.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++#endif
++ return status;
++}
++
++void IO_SM_init(void)
++{
++
++ GT_create(&dsp_trace_mask, "DT"); /* DSP Trace Mask */
++
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
+new file mode 100644
+index 0000000..5585cdb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.c
+@@ -0,0 +1,172 @@
++/*
++ * mmu_fault.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== mmu_fault.c ========
++ * Description:
++ * Implements DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: Support for IVA MMU exception.
++ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
++ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
++ *! 05-Jan-2004 vp: Updated support for 24xx silicon
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/host_os.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "_deh.h"
++#include <dspbridge/cfg.h>
++#include "_tiomap_mmu.h"
++#include "_tiomap.h"
++#include "mmu_fault.h"
++
++static u32 dmmuEventMask;
++u32 faultAddr;
++
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++void MMU_FaultDpc(IN void *pRefData)
++{
++ struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
++
++ if (pDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
++}
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
++ DBC_Require(irq == INT_DSP_MMU_IRQ);
++ DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources "
++ "in MMU ISR **\n");
++ if (MMU_CheckIfFault(pDevContext)) {
++ printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
++ "0x%x\n", dmmuEventMask);
++ printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
++ "0x%x\n", faultAddr);
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ /*
++ * Schedule a DPC directly. In the future, it may be
++ * necessary to check if DSP MMU fault is intended for
++ * Bridge.
++ */
++ DPC_Schedule(pDehMgr->hMmuFaultDpc);
++ /* Reset errInfo structure before use. */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
++ pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "***** MMU FAULT ***** faultcode 0x%x\n",
++ dmmuEventMask);
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * ======== MMU_CheckIfFault ========
++ * Check to see if MMU Fault is valid TLB miss from DSP
++ * Note: This function is called from an ISR
++ */
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
++{
++
++
++ bool retVal = false;
++ DSP_STATUS status = DSP_SOK;
++ HW_STATUS hwStatus;
++ struct CFG_HOSTRES resources;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
++ "MMU_CheckIfFault **\n");
++
++ hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
++ if (dmmuEventMask == HW_MMU_TRANSLATION_FAULT) {
++ HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
++ DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", faultAddr);
++ retVal = true;
++ }
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
+new file mode 100644
+index 0000000..be59333
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.h
+@@ -0,0 +1,45 @@
++/*
++ * mmu_fault.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mmu_fault.h ========
++ * Description:
++ * Defines DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: IVA MMU handlers.
++ *! 10-Sep-2001 kc: created.
++ */
++
++#ifndef MMU_FAULT_
++#define MMU_FAULT_
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++ void MMU_FaultDpc(IN void *pRefData);
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData);
++
++#endif /* MMU_FAULT_ */
++
+diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
+new file mode 100644
+index 0000000..b9b2bec
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/msg_sm.c
+@@ -0,0 +1,643 @@
++/*
++ * msg_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD message module.
++ *
++ * Public Functions:
++ * WMD_MSG_Create
++ * WMD_MSG_CreateQueue
++ * WMD_MSG_Delete
++ * WMD_MSG_DeleteQueue
++ * WMD_MSG_Get
++ * WMD_MSG_Put
++ * WMD_MSG_RegisterNotify
++ * WMD_MSG_SetQueueId
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Jul-2002 jeh Release critical section in WMD_MSG_Put() before
++ *! scheduling DPC.
++ *! 09-May-2001 jeh Free MSG queue NTFY object, remove unnecessary set/
++ *! reset of events.
++ *! 10-Jan-2001 jeh Set/Reset message manager and message queue events
++ *! correctly.
++ *! 04-Dec-2000 jeh Bug fixes.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- This */
++#include <_msg_sm.h>
++#include <dspbridge/wmdmsg.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MSGQ_SIGNATURE 0x5147534d /* "QGSM" */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
++static void FreeMsgList(struct LST_LIST *msgList);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct MSG_MGR *pMsgMgr;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++ DEV_GetIOMgr(hDevObject, &hIOMgr);
++ DBC_Assert(hIOMgr != NULL);
++ *phMsgMgr = NULL;
++ /* Allocate MSG manager object */
++ MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
++
++ if (pMsgMgr) {
++ pMsgMgr->onExit = msgCallback;
++ pMsgMgr->hIOMgr = hIOMgr;
++ /* List of MSG_QUEUEs */
++ pMsgMgr->queueList = LST_Create();
++ /* Queues of message frames for messages to the DSP. Message
++ * frames will only be added to the free queue when a
++ * MSG_QUEUE object is created. */
++ pMsgMgr->msgFreeList = LST_Create();
++ pMsgMgr->msgUsedList = LST_Create();
++ if (pMsgMgr->queueList == NULL ||
++ pMsgMgr->msgFreeList == NULL ||
++ pMsgMgr->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
++
++ /* Create an event to be used by WMD_MSG_Put() in waiting
++ * for an available free frame from the message manager. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ *phMsgMgr = pMsgMgr;
++ else
++ DeleteMsgMgr(pMsgMgr);
++
++ } else {
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Create a MSG_QUEUE for sending/receiving messages to/from a node
++ * on the DSP.
++ */
++DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE hArg)
++{
++ u32 i;
++ u32 uNumAllocated = 0;
++ struct MSG_QUEUE *pMsgQ;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ DBC_Require(phMsgQueue != NULL);
++
++ *phMsgQueue = NULL;
++ /* Allocate MSG_QUEUE object */
++ MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
++ if (!pMsgQ) {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ LST_InitElem((struct LST_ELEM *) pMsgQ);
++ pMsgQ->uMaxMsgs = uMaxMsgs;
++ pMsgQ->hMsgMgr = hMsgMgr;
++ pMsgQ->hArg = hArg; /* Node handle */
++ pMsgQ->dwId = dwId; /* Node env (not valid yet) */
++ /* Queues of Message frames for messages from the DSP */
++ pMsgQ->msgFreeList = LST_Create();
++ pMsgQ->msgUsedList = LST_Create();
++ if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++
++ /* Create event that will be signalled when a message from
++ * the DSP is available. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
++
++ /* Create a notification list for message ready notification. */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pMsgQ->hNtfy);
++
++ /* Create events that will be used to synchronize cleanup
++ * when the object is deleted. hSyncDone will be set to
++ * unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
++ * will be set by the unblocked thread to signal that it
++ * is unblocked and will no longer reference the object. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* Initialize message frames and put in appropriate queues */
++ for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
++ status = AddNewMsg(hMsgMgr->msgFreeList);
++ if (DSP_SUCCEEDED(status)) {
++ uNumAllocated++;
++ status = AddNewMsg(pMsgQ->msgFreeList);
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Stay inside CS to prevent others from taking any
++ * of the newly allocated message frames. */
++ DeleteMsgQueue(pMsgQ, uNumAllocated);
++ } else {
++ LST_PutTail(hMsgMgr->queueList,
++ (struct LST_ELEM *)pMsgQ);
++ *phMsgQueue = pMsgQ;
++ /* Signal that free frames are now available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ } else {
++ DeleteMsgQueue(pMsgQ, 0);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ */
++void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ DeleteMsgMgr(hMsgMgr);
++}
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ */
++void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
++{
++ struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
++ u32 refCount;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ hMsgQueue->fDone = true;
++ /* Unblock all threads blocked in MSG_Get() or MSG_Put(). */
++ refCount = hMsgQueue->refCount;
++ while (refCount) {
++ /* Unblock thread */
++ SYNC_SetEvent(hMsgQueue->hSyncDone);
++ /* Wait for acknowledgement */
++ SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
++ refCount = hMsgQueue->refCount;
++ }
++ /* Remove message queue from hMsgMgr->queueList */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
++ /* Free the message queue object */
++ DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
++ if (!hMsgMgr->msgFreeList)
++ goto func_cont;
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++}
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Get a message from a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fGotMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++ if (!hMsgQueue->msgUsedList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* If a message is already there, get it */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
++ msgUsedList);
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ if (LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_ResetEvent(hMsgQueue->hSyncEvent);
++
++ fGotMsg = true;
++ }
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ if (DSP_SUCCEEDED(status) && !fGotMsg) {
++ /* Wait til message is available, timeout, or done. We don't
++ * have to schedule the DPC, since the DSP will send messages
++ * when they are available. */
++ hSyncs[0] = hMsgQueue->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(!LST_IsEmpty(hMsgQueue->
++ msgUsedList));
++ /* Get msg from used list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgQueue->msgUsedList);
++ /* Copy message into pMsg and put frame on the
++ * free list */
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset the event if there are still queued messages */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_SetEvent(hMsgQueue->hSyncEvent);
++
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Put a message onto a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fPutMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++
++ (void) SYNC_EnterCS(hMsgMgr->hSyncCS);
++
++ /* If a message frame is available, use it */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId = hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ fPutMsg = true;
++ }
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++
++ /* Release critical section before scheduling DPC */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ if (DSP_SUCCEEDED(status) && !fPutMsg) {
++ /* Wait til a free message frame is available, timeout,
++ * or done */
++ hSyncs[0] = hMsgMgr->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ status = DSP_EPOINTER;
++ goto func_cont;
++ }
++ /* Get msg from free list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgMgr->msgFreeList);
++ /* Copy message into pMsg and put frame on the
++ * used list */
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId =
++ hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList,
++ (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ /* Schedule a DPC, to do the actual
++ * data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset event if there are still frames available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ */
++DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(hNotification != NULL);
++ DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
++ DBC_Require(uNotifyType == DSP_SIGNALEVENT);
++
++ status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ if (status == DSP_EVALUE) {
++ /* Not registered. Ok, since we couldn't have known. Node
++ * notifications are split between node state change handled
++ * by NODE, and message ready handled by MSG. */
++ status = DSP_SOK;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ */
++void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ /* DBC_Require(dwId != 0); */
++
++ /*
++ * A message queue must be created when a node is allocated,
++ * so that NODE_RegisterNotify() can be called before the node
++ * is created. Since we don't know the node environment until the
++ * node is created, we need this function to set hMsgQueue->dwId
++ * to the node environment, after the node is created.
++ */
++ hMsgQueue->dwId = dwId;
++}
++
++/*
++ * ======== AddNewMsg ========
++ * Must be called in message manager critical section.
++ */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++ DSP_STATUS status = DSP_SOK;
++
++ pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
++ MEM_PAGED);
++ if (pMsg != NULL) {
++ LST_InitElem((struct LST_ELEM *) pMsg);
++ LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteMsgMgr ========
++ */
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ if (hMsgMgr->queueList) {
++ if (LST_IsEmpty(hMsgMgr->queueList)) {
++ LST_Delete(hMsgMgr->queueList);
++ hMsgMgr->queueList = NULL;
++ }
++ }
++
++ if (hMsgMgr->msgFreeList) {
++ FreeMsgList(hMsgMgr->msgFreeList);
++ hMsgMgr->msgFreeList = NULL;
++ }
++
++ if (hMsgMgr->msgUsedList) {
++ FreeMsgList(hMsgMgr->msgUsedList);
++ hMsgMgr->msgUsedList = NULL;
++ }
++
++ if (hMsgMgr->hSyncEvent)
++ SYNC_CloseEvent(hMsgMgr->hSyncEvent);
++
++ if (hMsgMgr->hSyncCS)
++ SYNC_DeleteCS(hMsgMgr->hSyncCS);
++
++ MEM_FreeObject(hMsgMgr);
++}
++
++/*
++ * ======== DeleteMsgQueue ========
++ */
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
++{
++ struct MSG_MGR *hMsgMgr;
++ struct MSG_FRAME *pMsg;
++ u32 i;
++
++ if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE)
++ || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList)
++ goto func_end;
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++
++ /* Pull off uNumToDSP message frames from Msg manager and free */
++ for (i = 0; i < uNumToDSP; i++) {
++
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ MEM_Free(pMsg);
++ } else {
++ /* Cannot free all of the message frames */
++ break;
++ }
++ }
++
++ if (hMsgQueue->msgFreeList) {
++ FreeMsgList(hMsgQueue->msgFreeList);
++ hMsgQueue->msgFreeList = NULL;
++ }
++
++ if (hMsgQueue->msgUsedList) {
++ FreeMsgList(hMsgQueue->msgUsedList);
++ hMsgQueue->msgUsedList = NULL;
++ }
++
++
++ if (hMsgQueue->hNtfy)
++ NTFY_Delete(hMsgQueue->hNtfy);
++
++ if (hMsgQueue->hSyncEvent)
++ SYNC_CloseEvent(hMsgQueue->hSyncEvent);
++
++ if (hMsgQueue->hSyncDone)
++ SYNC_CloseEvent(hMsgQueue->hSyncDone);
++
++ if (hMsgQueue->hSyncDoneAck)
++ SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
++
++ MEM_FreeObject(hMsgQueue);
++func_end:
++ return;
++
++}
++
++/*
++ * ======== FreeMsgList ========
++ */
++static void FreeMsgList(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++
++ if (!msgList)
++ goto func_end;
++
++ while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
++ MEM_Free(pMsg);
++
++ DBC_Assert(LST_IsEmpty(msgList));
++
++ LST_Delete(msgList);
++func_end:
++ return;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
+new file mode 100644
+index 0000000..2ab585d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430.c
+@@ -0,0 +1,2149 @@
++/*
++ * tiomap.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== tiomap.c ========
++ * Processor Manager Driver for TI OMAP3430 EVM.
++ *
++ * Public Function:
++ * WMD_DRV_Entry
++ *
++ *! Revision History:
++ *! ================
++ * 26-March-2008 HK and AL: Added WMD_DEV_WalkTbl funciton.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <mach-omap2/prm.h>
++#include <mach-omap2/cm.h>
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++#include <mach/control.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++#include <hw_mbox.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdmsg.h>
++#include <dspbridge/pwr.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Local */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_util.h"
++#include "tiomap_io.h"
++
++
++/* Offset in shared mem to write to in order to synchronize start with DSP */
++#define SHMSYNCOFFSET 4 /* GPP byte offset */
++
++#define BUFFERSIZE 1024
++
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++#define PAGES_II_LVL_TABLE 512
++#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
++
++#define MMU_GFLUSH 0x60
++
++/* Forward Declarations: */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dwDSPAddr);
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT BRD_STATUS *pdwState);
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState);
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttr);
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes);
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig);
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs);
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
++static u32 user_va2pa(struct mm_struct *mm, u32 address);
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs);
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);
++static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,
++ u32 sysctrl_base);
++void GetHWRegs(u32 prcm_base, u32 cm_base);
++
++/* ----------------------------------- Globals */
++
++/* Attributes of L2 page tables for DSP MMU */
++struct PageInfo {
++ u32 numEntries; /* Number of valid PTEs in the L2 PT */
++} ;
++
++/* Attributes used to manage the DSP MMU page tables */
++struct PgTableAttrs {
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++
++ u32 L1BasePa; /* Physical address of the L1 PT */
++ u32 L1BaseVa; /* Virtual address of the L1 PT */
++ u32 L1size; /* Size of the L1 PT */
++ u32 L1TblAllocPa;
++ /* Physical address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocVa;
++ /* Virtual address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocSz;
++ /* Size of consistent memory allocated for L1 table.
++ * May not be aligned */
++
++ u32 L2BasePa; /* Physical address of the L2 PT */
++ u32 L2BaseVa; /* Virtual address of the L2 PT */
++ u32 L2size; /* Size of the L2 PT */
++ u32 L2TblAllocPa;
++ /* Physical address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocVa;
++ /* Virtual address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocSz;
++ /* Size of consistent memory allocated for L2 table.
++ * May not be aligned */
++
++ u32 L2NumPages; /* Number of allocated L2 PT */
++ struct PageInfo *pgInfo; /* Array [L2NumPages] of L2 PT info structs */
++} ;
++
++/*
++ * If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
++ * to boot
++ */
++extern s32 dsp_debug;
++
++
++/*
++ * This mini driver's function interface table.
++ */
++static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
++ WCD_MAJOR_VERSION, /* WCD ver. for which this mini driver is built. */
++ WCD_MINOR_VERSION,
++ WMD_DEV_Create,
++ WMD_DEV_Destroy,
++ WMD_DEV_Ctrl,
++ WMD_BRD_Monitor,
++ WMD_BRD_Start,
++ WMD_BRD_Stop,
++ WMD_BRD_Status,
++ WMD_BRD_Read,
++ WMD_BRD_Write,
++ WMD_BRD_SetState,
++ WMD_BRD_MemCopy,
++ WMD_BRD_MemWrite,
++ WMD_BRD_MemMap,
++ WMD_BRD_MemUnMap,
++ /* The following CHNL functions are provided by chnl_io.lib: */
++ WMD_CHNL_Create,
++ WMD_CHNL_Destroy,
++ WMD_CHNL_Open,
++ WMD_CHNL_Close,
++ WMD_CHNL_AddIOReq,
++ WMD_CHNL_GetIOC,
++ WMD_CHNL_CancelIO,
++ WMD_CHNL_FlushIO,
++ WMD_CHNL_GetInfo,
++ WMD_CHNL_GetMgrInfo,
++ WMD_CHNL_Idle,
++ WMD_CHNL_RegisterNotify,
++ /* The following DEH functions are provided by tihelen_ue_deh.c */
++ WMD_DEH_Create,
++ WMD_DEH_Destroy,
++ WMD_DEH_Notify,
++ WMD_DEH_RegisterNotify,
++ WMD_DEH_GetInfo,
++ /* The following IO functions are provided by chnl_io.lib: */
++ WMD_IO_Create,
++ WMD_IO_Destroy,
++ WMD_IO_OnLoaded,
++ WMD_IO_GetProcLoad,
++ /* The following MSG functions are provided by chnl_io.lib: */
++ WMD_MSG_Create,
++ WMD_MSG_CreateQueue,
++ WMD_MSG_Delete,
++ WMD_MSG_DeleteQueue,
++ WMD_MSG_Get,
++ WMD_MSG_Put,
++ WMD_MSG_RegisterNotify,
++ WMD_MSG_SetQueueId,
++};
++
++static inline void tlb_flush_all(const u32 base)
++{
++ __raw_writeb(__raw_readb(base + MMU_GFLUSH) | 1, base + MMU_GFLUSH);
++}
++
++static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++ u32 temp = 0;
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++
++ if ((temp & HW_PWR_STATE_ON) == HW_PWR_STATE_OFF ||
++ (temp & HW_PWR_STATE_ON) == HW_PWR_STATE_RET) {
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ WakeDSP(pDevContext, NULL);
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ } else
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++}
++
++static void bad_page_dump(u32 pa, struct page *pg)
++{
++ pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
++ pr_emerg("Bad page state in process '%s'\n"
++ "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
++ "Backtrace:\n",
++ current->comm, pg, (int)(2*sizeof(unsigned long)),
++ (unsigned long)pg->flags, pg->mapping,
++ page_mapcount(pg), page_count(pg));
++ BUG();
++}
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * purpose:
++ * Mini Driver entry point.
++ */
++void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName)
++{
++
++ DBC_Require(pstrWMDFileName != NULL);
++ DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
++
++ IO_SM_init(); /* Initialization of io_sm module */
++
++ if (strcmp(pstrWMDFileName, "UMA") == 0)
++ *ppDrvInterface = &drvInterfaceFxns;
++ else
++ DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
++
++}
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * purpose:
++ * This WMD_BRD_Monitor puts DSP into a Loadable state.
++ * i.e Application can load and start the device.
++ *
++ * Preconditions:
++ * Device in 'OFF' state.
++ */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ enum HW_PwrState_t pwrState;
++
++ DBG_Trace(DBG_ENTER, "Board in the monitor state \n");
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ goto error_return;
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Read and set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Disable Automatic transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ status = run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the device state to IDLE */
++ pDevContext->dwBrdState = BRD_IDLE;
++
++ }
++error_return:
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Read ========
++ * purpose:
++ * Reads buffers for DSP memory.
++ */
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
++ " 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Read: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ /* change here to account for the 3 bands of the DSP internal memory */
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
++ } else {
++ DBG_Trace(DBG_LEVEL1,
++ "**** Reading From external memory **** \n ");
++ status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ return status;
++ }
++ /* copy the data from DSP memory, */
++ memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_SetState ========
++ * purpose:
++ * This routine updates the Board status.
++ */
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
++ ulBrdState);
++ pDevContext->dwBrdState = ulBrdState;
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Start ========
++ * purpose:
++ * Initializes DSP MMU and Starts DSP.
++ *
++ * Preconditions:
++ * a) DSP domain is 'ACTIVE'.
++ * b) DSP_RST1 is asserted.
++ * b) DSP_RST2 is released.
++ */
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 dwSyncAddr = 0;
++ u32 ulShmBase; /* Gpp Phys SM base addr(byte) */
++ u32 ulShmBaseVirt; /* Dsp Virt SM base addr */
++ u32 ulTLBBaseVirt; /* Base of MMU TLB entry */
++ u32 ulShmOffsetVirt; /* offset of ulShmBaseVirt from ulTLBBaseVirt */
++ s32 iEntryNdx;
++ s32 itmpEntryNdx = 0; /* DSP-MMU TLB entry base address */
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ u32 ulDspClkRate;
++ u32 ulDspClkAddr;
++ u32 ulBiosGpTimer;
++ u32 uClkCmd;
++ struct IO_MGR *hIOMgr;
++ u32 ulLoadMonitorTimer;
++ u32 extClkId = 0;
++ u32 tmpIndex;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
++ "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
++
++ /* The device context contains all the mmu setup info from when the
++ * last dsp base image was loaded. The first entry is always
++ * SHMMEM base. */
++ /* Get SHM_BEG - convert to byte address */
++ (void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
++ &ulShmBaseVirt);
++ ulShmBaseVirt *= DSPWORDSIZE;
++ DBC_Assert(ulShmBaseVirt != 0);
++ /* DSP Virtual address */
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
++ /* Kernel logical address */
++ ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
++
++ DBC_Assert(ulShmBase != 0);
++ /* 2nd wd is used as sync field */
++ dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
++ /* Write a signature into the SHM base + offset; this will
++ * get cleared when the DSP program starts. */
++ if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
++ status = DSP_EFAIL;
++ } else
++ *((volatile u32 *)dwSyncAddr) = 0xffffffff;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ /* Assert RST1 i.e only the RST only for DSP megacell */
++ /* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
++ if (dsp_debug) {
++ /* Set the bootmode to self loop */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to self loop"
++ " for IVA2 Device\n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
++ } else {
++ /* Set the bootmode to '0' - direct boot */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to direct"
++ " boot for IVA2 Device \n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Reset and Unreset the RST2, so that BOOTADDR is copied to
++ * IVA2 SYSC register */
++ HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ /* Disbale the DSP MMU */
++ HW_MMU_Disable(resources.dwDmmuBase);
++ /* Disable TWL */
++ HW_MMU_TWLDisable(resources.dwDmmuBase);
++
++ /* Only make TLB entry if both addresses are non-zero */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
++ iEntryNdx++) {
++ if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
++ (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
++ DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
++ " 0x%x DspVa 0x%x Size 0x%x\n",
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize);
++ configureDspMmu(pDevContext,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
++ DSPWORDSIZE,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize,
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].endianism,
++ pDevContext->aTLBEntry[iEntryNdx].elemSize,
++ pDevContext->aTLBEntry[iEntryNdx].
++ mixedMode);
++ itmpEntryNdx++;
++ }
++ } /* end for */
++ }
++
++ /* Lock the above TLB entries and get the BIOS and load monitor timer
++ * information*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_TTBSet(resources.dwDmmuBase,
++ pDevContext->pPtAttrs->L1BasePa);
++ HW_MMU_TWLEnable(resources.dwDmmuBase);
++ /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
++
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwDmmuBase) + 0x10));
++ temp = (temp & 0xFFFFFFEF) | 0x11;
++ *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)) =
++ (u32) temp;
++
++ /* Let the DSP MMU run */
++ HW_MMU_Enable(resources.dwDmmuBase);
++
++ /* Enable the BIOS clock */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_BIOSGPTIMER,
++ &ulBiosGpTimer);
++ DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_LOADMON_GPTIMER,
++ &ulLoadMonitorTimer);
++ DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
++ ulLoadMonitorTimer);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulLoadMonitorTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Disable: 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, " Error while setting"
++ "LM Timer to 32KHz\n");
++ }
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Enable : 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for Load "
++ "Monitor Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulBiosGpTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
++ "Disable: 0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ " Error while setting BIOS Timer to 32KHz\n");
++ }
++
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
++ "0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for BIOS Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the DSP clock rate */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ "_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
++ /*Set Autoidle Mode for IVA2 PLL */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
++ "0x%x \n", ulDspClkAddr);
++ if ((unsigned int *)ulDspClkAddr != NULL) {
++ /* Get the clock rate */
++ status = CLK_GetRate(SERVICESCLK_iva2_ck,
++ &ulDspClkRate);
++ DBG_Trace(DBG_LEVEL5,
++ "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
++ ulDspClkRate);
++ (void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
++ ulDspClkAddr, sizeof(u32), 0);
++ }
++/*PM_IVA2GRPSEL_PER = 0xC0;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ temp = (temp & 0xFFFFFF30) | 0xC0;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8)) =
++ (u32) temp;
++
++/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ temp = (temp & 0xFFFFFF3F);
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4)) =
++ (u32) temp;
++/*CM_SLEEPDEP_PER |= 0x04;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerBase) + 0x44));
++ temp = (temp & 0xFFFFFFFB) | 0x04;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerBase) + 0x44)) =
++ (u32) temp;
++
++/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x48));
++ temp = (temp & 0xFFFFFFFC) | 0x03;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x48)) =
++ (u32) temp;
++
++
++ /* Enable Mailbox events and also drain any pending
++ * stale messages */
++ (void)CHNLSM_EnableInterrupt(pDevContext);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
++ temp);
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
++ temp);
++
++ /* Let DSP go */
++ DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
++ /* Enable DSP MMU Interrupts */
++ HW_MMU_EventEnable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ /* release the RST1, DSP starts executing now .. */
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
++
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
++ temp);
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
++ temp);
++ DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
++ dwSyncAddr);
++ DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address = 0x%x \n",
++ dwDSPAddr);
++ if (dsp_debug)
++ while (*((volatile u16 *)dwSyncAddr))
++ ;;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait for DSP to clear word in shared memory */
++ /* Read the Location */
++ if (!WaitForStart(pDevContext, dwSyncAddr)) {
++ status = WMD_E_TIMEOUT;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start Failed to Synchronize\n");
++ }
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_SUCCEEDED(status)) {
++ IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start: OPP information initialzed\n");
++ /* Write the synchronization bit to indicate the
++ * completion of OPP table update to DSP
++ */
++ *((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* update board state */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ /* (void)CHNLSM_EnableInterrupt(pDevContext);*/
++ DBG_Trace(DBG_LEVEL7, "Device Started \n ");
++ } else {
++ pDevContext->dwBrdState = BRD_UNKNOWN;
++ DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * purpose:
++ * Puts DSP in self loop.
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 dspPwrState;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void)CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
++ * before turning off the clocks.. This is to ensure that there are no
++ * pending L3 or other transactons from IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
++ return DSP_EFAIL;
++ }
++
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
++ if (dspPwrState != HW_PWR_STATE_OFF) {
++
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
++
++ mdelay(10);
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++
++ run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++
++ udelay(50);
++
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: CLK_Disable failed "
++ "for iva2_fck\n");
++ }
++ /* IVA2 is not in OFF state */
++ /* Set PM_PWSTCTRL_IVA2 to OFF */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_OFF);
++ /* Set the SW supervised state transition for Sleep */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_SLEEP);
++ } else {
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
++ " for iva2_fck\n");
++ }
++ }
++ udelay(10);
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *) pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Delete ========
++ * purpose:
++ * Puts DSP in Low power mode
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void) CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive
++ * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
++ * to ensure that there are no pending L3 or other transactons from
++ * IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
++ return DSP_EFAIL;
++ }
++ status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
++ " iva2_fck\n");
++ }
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *)pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Returns the board status.
++ */
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS *pdwState)
++{
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ *pdwState = pDevContext->dwBrdState;
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Copies the buffers to DSP internal or external memory.
++ */
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
++ "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
++ "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Write: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType, false);
++ }
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy : DspLogicAddr=0x%x \n",
++ pDevContext->dwDspBaseAddr);
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Creates a driver object. Puts DSP in self loop.
++ */
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = NULL;
++ s32 iEntryNdx;
++ s32 tcWordSwap;
++ u32 tcWordSwapSize = sizeof(tcWordSwap);
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 pg_tbl_pa;
++ u32 pg_tbl_va;
++ u32 align_size;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
++ "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
++ ppDevContext, hDevObject, pConfig, pDspConfig);
++ /* Allocate and initialize a data structure to contain the mini driver
++ * state, which becomes the context for later calls into this WMD. */
++ pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
++ if (!pDevContext) {
++ DBG_Trace(DBG_ENTER, "Failed to allocate mem \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_ENTER, "Failed to get host resources \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++
++ pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
++ pDevContext->dwSelfLoop = (u32)NULL;
++ pDevContext->uDspPerClks = 0;
++ pDevContext->dwInternalSize = OMAP_DSP_SIZE;
++ /* Clear dev context MMU table entries.
++ * These get set on WMD_BRD_IOCTL() call after program loaded. */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
++ }
++ pDevContext->numTLBEntries = 0;
++ pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
++ (pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
++ if (!pDevContext->dwDspBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create: failed to Map the API memory\n");
++ }
++ pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
++ if (pPtAttrs != NULL) {
++ /* Assuming that we use only DSP's memory map
++ * until 0x4000:0000 , we would need only 1024
++ * L1 enties i.e L1 size = 4K */
++ pPtAttrs->L1size = 0x1000;
++ align_size = pPtAttrs->L1size;
++ /* Align sizes are expected to be power of 2 */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
++ align_size, &pg_tbl_pa);
++ /* Check if the PA is aligned for us */
++ if ((pg_tbl_pa) & (align_size-1)) {
++ /* PA not aligned to page table size ,
++ * try with more allocation and align */
++ MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa, pPtAttrs->L1size);
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
++ align_size, &pg_tbl_pa);
++ /* We should be able to get aligned table now */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
++ /* Align the PA to the next 'align' boundary */
++ pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
++ (~(align_size-1));
++ pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
++ pg_tbl_pa);
++ } else {
++ /* We got aligned PA, cool */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
++ pPtAttrs->L1BasePa = pg_tbl_pa;
++ pPtAttrs->L1BaseVa = pg_tbl_va;
++ }
++ if (pPtAttrs->L1BaseVa)
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++
++ /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
++ * L4 pages */
++ pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
++ pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
++ pPtAttrs->L2NumPages;
++ align_size = 4; /* Make it u32 aligned */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
++ align_size, &pg_tbl_pa);
++ pPtAttrs->L2TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L2TblAllocVa = pg_tbl_va;
++ pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
++ pPtAttrs->L2BasePa = pg_tbl_pa;
++ pPtAttrs->L2BaseVa = pg_tbl_va;
++
++ if (pPtAttrs->L2BaseVa)
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++
++ pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
++ sizeof(struct PageInfo), MEM_NONPAGED);
++ DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
++ "%x, size %x\n", pPtAttrs->L1BasePa,
++ pPtAttrs->L1BaseVa, pPtAttrs->L1size,
++ pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
++ pPtAttrs->L2size);
++ DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
++ pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
++ }
++ if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
++ (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
++ pDevContext->pPtAttrs = pPtAttrs;
++ else
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Endianism Register */ /* Need to set this */
++ /* Retrieve the TC u16 SWAP Option */
++ status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
++ (u8 *)&tcWordSwap, &tcWordSwapSize);
++ /* Save the value */
++ pDevContext->tcWordSwapOn = tcWordSwap;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Clock Divisor for the DSP module */
++ DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
++ "enable the clock \n");
++ status = CLK_Enable(SERVICESCLK_mailbox_ick);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_create:Reset mail box and "
++ "enable the clock Fail\n");
++ }
++ udelay(5);
++ /* 24xx-Linux MMU address is obtained from the host
++ * resources struct */
++ pDevContext->dwDSPMmuBase = resources.dwDmmuBase;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDevContext->hDevObject = hDevObject;
++ pDevContext->ulIntMask = 0;
++ /* Store current board state. */
++ pDevContext->dwBrdState = BRD_STOPPED;
++ /* Return this ptr to our device state to the WCD for storage:*/
++ *ppDevContext = pDevContext;
++ DBG_Trace(DBG_ENTER, "Device Created \n");
++ } else {
++ if (pPtAttrs != NULL) {
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa,
++ pPtAttrs->L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa,
++ pPtAttrs->L1TblAllocSz);
++ }
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ if (pDevContext)
++ MEM_Free(pDevContext);
++
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create Error Device not created\n");
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Receives device specific commands.
++ */
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
++ s32 ndx;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext: 0x%x\n\t\t dwCmd: "
++ "0x%x\n\t\tpArgs: 0x%x\n", pDevContext, dwCmd, pArgs);
++ switch (dwCmd) {
++ case WMDIOCTL_CHNLREAD:
++ break;
++ case WMDIOCTL_CHNLWRITE:
++ break;
++ case WMDIOCTL_SETMMUCONFIG:
++ /* store away dsp-mmu setup values for later use */
++ for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
++ pDevContext->aTLBEntry[ndx] = *paExtProc;
++
++ break;
++ case WMDIOCTL_DEEPSLEEP:
++ case WMDIOCTL_EMERGENCYSLEEP:
++ /* Currently only DSP Idle is supported Need to update for
++ * later releases */
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
++ status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
++ break;
++ case WMDIOCTL_WAKEUP:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
++ status = WakeDSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CLK_CTRL:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
++ status = DSP_SOK;
++ /* Looking For Baseport Fix for Clocks */
++ status = DSPPeripheralClkCtrl(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_PWR_HIBERNATE:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
++ status = handle_hibernation_fromDSP(pDevContext);
++ break;
++ case WMDIOCTL_PRESCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
++ status = PreScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_POSTSCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
++ status = PostScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CONSTRAINT_REQUEST:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
++ status = handle_constraints_set(pDevContext, pArgs);
++ break;
++ default:
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
++ break;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Destroys the driver object.
++ */
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
++ hDevContext;
++ DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
++ hDevContext);
++ /* first put the device to stop state */
++ WMD_BRD_Delete(pDevContext);
++ if (pDevContext && pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa, pPtAttrs->
++ L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa, pPtAttrs->
++ L1TblAllocSz);
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ }
++ /* Free the driver's device context: */
++ MEM_Free((void *) hDevContext);
++ return status;
++}
++
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 srcAddr = ulDspSrcAddr;
++ u32 destAddr = ulDspDestAddr;
++ u32 copyBytes = 0;
++ u32 totalBytes = ulNumBytes;
++ u8 hostBuf[BUFFERSIZE];
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
++ copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
++ /* Read from External memory */
++ status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
++ copyBytes, ulMemType);
++ if (DSP_SUCCEEDED(status)) {
++ if (destAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ /* Write to Internal memory */
++ status = WriteDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType);
++ } else {
++ /* Write to External memory */
++ status = WriteExtDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType, false);
++ }
++ }
++ totalBytes -= copyBytes;
++ srcAddr += copyBytes;
++ destAddr += copyBytes;
++ }
++ return status;
++}
++
++/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 ulRemainBytes = 0;
++ u32 ulBytes = 0;
++ ulRemainBytes = ulNumBytes;
++ while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
++ ulBytes =
++ ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
++ if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(hDevContext, pbHostBuf,
++ dwDSPAddr, ulBytes, ulMemType, true);
++ }
++ ulRemainBytes -= ulBytes;
++ dwDSPAddr += ulBytes;
++ pbHostBuf = pbHostBuf + ulBytes;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * This function maps MPU buffer to the DSP address space. It performs
++ * linear to physical address translation if required. It translates each
++ * page since linear addresses can be physically non-contiguous
++ * All address & size arguments are assumed to be page aligned (in proc.c)
++ *
++ * TODO: Disable MMU while updating the page tables (but that'll stall DSP)
++ */
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, u32 ulMapAttr)
++{
++ u32 attrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct HW_MMUMapAttrs_t hwAttrs;
++ struct vm_area_struct *vma;
++ struct mm_struct *mm = current->mm;
++ u32 write = 0;
++ u32 numUsrPgs = 0;
++ struct page *mappedPage, *pg;
++ s32 pgNum;
++ u32 va = ulVirtAddr;
++ struct task_struct *curr_task = current;
++ u32 pgI = 0;
++ u32 mpuAddr, pa;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
++ "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, ulMapAttr);
++ if (ulNumBytes == 0)
++ return DSP_EINVALIDARG;
++
++ if (ulMapAttr != 0) {
++ attrs = ulMapAttr;
++ } else {
++ /* Assign default attributes */
++ attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
++ }
++ /* Take mapping properties */
++ if (attrs & DSP_MAPBIGENDIAN)
++ hwAttrs.endianism = HW_BIG_ENDIAN;
++ else
++ hwAttrs.endianism = HW_LITTLE_ENDIAN;
++
++ hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
++ ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
++ /* Ignore elementSize if mixedSize is enabled */
++ if (hwAttrs.mixedSize == 0) {
++ if (attrs & DSP_MAPELEMSIZE8) {
++ /* Size is 8 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
++ } else if (attrs & DSP_MAPELEMSIZE16) {
++ /* Size is 16 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
++ } else if (attrs & DSP_MAPELEMSIZE32) {
++ /* Size is 32 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
++ } else if (attrs & DSP_MAPELEMSIZE64) {
++ /* Size is 64 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
++ } else {
++ /*
++ * Mixedsize isn't enabled, so size can't be
++ * zero here
++ */
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: MMU element size is zero\n");
++ return DSP_EINVALIDARG;
++ }
++ }
++ if (attrs & DSP_MAPDONOTLOCK)
++ hwAttrs.donotlockmpupage = 1;
++ else
++ hwAttrs.donotlockmpupage = 0;
++
++ if (attrs & DSP_MAPVMALLOCADDR) {
++ return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ }
++ /*
++ * Do OS-specific user-va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ if ((attrs & DSP_MAPPHYSICALADDR)) {
++ status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ goto func_cont;
++ }
++
++ /*
++ * Important Note: ulMpuAddr is mapped from user application process
++ * to current process - it must lie completely within the current
++ * virtual memory address space in order to be of use to us here!
++ */
++ down_read(&mm->mmap_sem);
++ vma = find_vma(mm, ulMpuAddr);
++ if (vma)
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++
++ /*
++ * It is observed that under some circumstances, the user buffer is
++ * spread across several VMAs. So loop through and check if the entire
++ * user buffer is covered
++ */
++ while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
++ /* jump to the next VMA region */
++ vma = find_vma(mm, vma->vm_end + 1);
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++ }
++ if (!vma) {
++ DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
++ "MPU Buffer !!! \n");
++ status = DSP_EINVALIDARG;
++ up_read(&mm->mmap_sem);
++ goto func_cont;
++ }
++
++ if (vma->vm_flags & VM_IO) {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ mpuAddr = ulMpuAddr;
++ DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"
++ "ulNumBytes= %d\n", numUsrPgs, ulNumBytes);
++ /* Get the physical addresses for user buffer */
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pa = user_va2pa(mm, mpuAddr);
++ if (!pa) {
++ status = DSP_EFAIL;
++ pr_err("DSPBRIDGE: VM_IO mapping physical"
++ "address is invalid\n");
++ break;
++ }
++ if (pfn_valid(__phys_to_pfn(pa))) {
++ pg = phys_to_page(pa);
++ get_page(pg);
++ if (page_count(pg) < 1) {
++ pr_err("Bad page in VM_IO buffer\n");
++ bad_page_dump(pa, pg);
++ }
++ }
++ status = PteSet(pDevContext->pPtAttrs, pa,
++ va, HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN VM_IO"
++ "PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ mpuAddr += HW_PAGE_SIZE_4KB;
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ } else {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
++ write = 1;
++
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,
++ write, 1, &mappedPage, NULL);
++ if (pgNum > 0) {
++ if (page_count(mappedPage) < 1) {
++ pr_err("Bad page count after doing"
++ "get_user_pages on"
++ "user buffer\n");
++ bad_page_dump(page_to_phys(mappedPage),
++ mappedPage);
++ }
++ status = PteSet(pDevContext->pPtAttrs,
++ page_to_phys(mappedPage), va,
++ HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ ulMpuAddr += HW_PAGE_SIZE_4KB;
++ } else {
++ pr_err("DSPBRIDGE: get_user_pages FAILED,"
++ "MPU addr = 0x%x,"
++ "vma->vm_flags = 0x%lx,"
++ "get_user_pages Err"
++ "Value = %d, Buffer"
++ "size=0x%x\n", ulMpuAddr,
++ vma->vm_flags, pgNum,
++ ulNumBytes);
++ status = DSP_EFAIL;
++ break;
++ }
++ }
++ }
++ up_read(&mm->mmap_sem);
++func_cont:
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ /*
++ * Roll out the mapped pages incase it failed in middle of
++ * mapping
++ */
++ if (pgI) {
++ WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,
++ (pgI * PG_SIZE_4K));
++ }
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Invalidate the PTEs for the DSP VA block to be unmapped.
++ *
++ * PTEs of a mapped memory block are contiguous in any page table
++ * So, instead of looking up the PTE address for every 4K block,
++ * we clear consecutive PTEs until we unmap all the bytes
++ */
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes)
++{
++ u32 L1BaseVa;
++ u32 L2BaseVa;
++ u32 L2BasePa;
++ u32 L2PageNum;
++ u32 pteVal;
++ u32 pteSize;
++ u32 pteCount;
++ u32 pteAddrL1;
++ u32 pteAddrL2 = 0;
++ u32 remBytes;
++ u32 remBytesL2;
++ u32 vaCurr;
++ struct page *pg = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct PgTableAttrs *pt = pDevContext->pPtAttrs;
++ u32 pacount = 0;
++ u32 *pPhysAddrPageTbl = NULL;
++ u32 temp;
++ u32 patemp = 0;
++ u32 pAddr;
++ u32 numof4KPages = 0;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
++ "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
++ pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
++ vaCurr = ulVirtAddr;
++ remBytes = ulNumBytes;
++ remBytesL2 = 0;
++ L1BaseVa = pt->L1BaseVa;
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
++ "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
++ vaCurr, remBytes);
++ while (remBytes && (DSP_SUCCEEDED(status))) {
++ u32 vaCurrOrig = vaCurr;
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /*
++ * Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA
++ */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ /*
++ * Find the L2 PTE address from which we will start
++ * clearing, the number of PTEs to be cleared on this
++ * page, and the size of VA space that needs to be
++ * cleared on this L2 page
++ */
++ pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
++ pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
++ pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
++ sizeof(u32);
++ if (remBytes < (pteCount * PG_SIZE_4K))
++ pteCount = remBytes / PG_SIZE_4K;
++
++ remBytesL2 = pteCount * PG_SIZE_4K;
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
++ "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
++ L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
++ /*
++ * Unmap the VA space on this L2 PT. A quicker way
++ * would be to clear pteCount entries starting from
++ * pteAddrL2. However, below code checks that we don't
++ * clear invalid entries or less than 64KB for a 64KB
++ * entry. Similar checking is done for L1 PTEs too
++ * below
++ */
++ while (remBytesL2 && (DSP_SUCCEEDED(status))) {
++ pteVal = *(u32 *)pteAddrL2;
++ pteSize = HW_MMU_PteSizeL2(pteVal);
++ /* vaCurr aligned to pteSize? */
++ if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ if (pteSize == HW_PAGE_SIZE_64KB)
++ numof4KPages = 16;
++ else
++ numof4KPages = 1;
++ temp = 0;
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] =
++ pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(pteAddrL2,
++ vaCurr, pteSize) == RET_OK) {
++ status = DSP_SOK;
++ remBytesL2 -= pteSize;
++ vaCurr += pteSize;
++ pteAddrL2 += (pteSize >> 12) *
++ sizeof(u32);
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (remBytesL2 == 0) {
++ pt->pgInfo[L2PageNum].numEntries -= pteCount;
++ if (pt->pgInfo[L2PageNum].numEntries == 0) {
++ /*
++ * Clear the L1 PTE pointing to the
++ * L2 PT
++ */
++ if (RET_OK == HW_MMU_PteClear(L1BaseVa,
++ vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))
++ status = DSP_SOK;
++ else {
++ status = DSP_EFAIL;
++ SYNC_LeaveCS(pt->hCSObj);
++ goto EXIT_LOOP;
++ }
++ }
++ remBytes -= pteCount * PG_SIZE_4K;
++ } else {
++ status = DSP_EFAIL;
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
++ "numEntries %x, pteCount %x, status: 0x%x\n",
++ L2PageNum, pt->pgInfo[L2PageNum].numEntries,
++ pteCount, status);
++ SYNC_LeaveCS(pt->hCSObj);
++ } else
++ /* vaCurr aligned to pteSize? */
++ /* pteSize = 1 MB or 16 MB */
++ if ((pteSize != 0) && (remBytes >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ if (pteSize == HW_PAGE_SIZE_1MB)
++ numof4KPages = 256;
++ else
++ numof4KPages = 4096;
++ temp = 0;
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] = pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)
++ == RET_OK) {
++ status = DSP_SOK;
++ remBytes -= pteSize;
++ vaCurr += pteSize;
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ /*
++ * It is better to flush the TLB here, so that any stale old entries
++ * get flushed
++ */
++EXIT_LOOP:
++ flush_all(pDevContext);
++ for (temp = 0; temp < pacount; temp++) {
++ patemp = pPhysAddrPageTbl[temp];
++ if (pfn_valid(__phys_to_pfn(patemp))) {
++ pg = phys_to_page(patemp);
++ if (page_count(pg) < 1) {
++ pr_info("DSPBRIDGE:UNMAP function: COUNT 0"
++ "FOR PA 0x%x, size = 0x%x\n",
++ patemp, ulNumBytes);
++ bad_page_dump(patemp, pg);
++ }
++ SetPageDirty(pg);
++ page_cache_release(pg);
++ }
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
++ "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
++ "remBytesL2 %x\n", status, remBytes, remBytesL2);
++ return status;
++}
++
++/*
++ * ======== user_va2pa ========
++ * Purpose:
++ * This function walks through the Linux page tables to convert a userland
++ * virtual address to physical address
++ */
++static u32 user_va2pa(struct mm_struct *mm, u32 address)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++
++ pgd = pgd_offset(mm, address);
++ if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
++ pmd = pmd_offset(pgd, address);
++ if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
++ ptep = pte_offset_map(pmd, address);
++ if (ptep) {
++ pte = *ptep;
++ if (pte_present(pte))
++ return pte & PAGE_MASK;
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++/*
++ * ======== PteUpdate ========
++ * This function calculates the optimum page-aligned addresses and sizes
++ * Caller must pass page-aligned values
++ */
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ u32 i;
++ u32 allBits;
++ u32 paCurr = pa;
++ u32 vaCurr = va;
++ u32 numBytes = size;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++ DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
++ "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
++ status = PteSet(pDevContext->pPtAttrs, paCurr,
++ vaCurr, pgSize[i], mapAttrs);
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size */
++ break;
++ }
++ }
++ }
++ DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
++ numBytes);
++ return status;
++}
++
++/*
++ * ======== PteSet ========
++ * This function calculates PTE address (MPU virtual) to be updated
++ * It also manages the L2 page tables
++ */
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs)
++{
++ u32 i;
++ u32 pteVal;
++ u32 pteAddrL1;
++ u32 pteSize;
++ u32 pgTblVa; /* Base address of the PT that will be updated */
++ u32 L1BaseVa;
++ /* Compiler warns that the next three variables might be used
++ * uninitialized in this function. Doesn't seem so. Working around,
++ * anyways. */
++ u32 L2BaseVa = 0;
++ u32 L2BasePa = 0;
++ u32 L2PageNum = 0;
++ DSP_STATUS status = DSP_SOK;
++ DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
++ "size %x, attrs %x\n", pt, pa, va, size, attrs);
++ L1BaseVa = pt->L1BaseVa;
++ pgTblVa = L1BaseVa;
++ if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
++ if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ } else {
++ return DSP_EFAIL;
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /* Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ } else if (pteSize == 0) {
++ /* L1 PTE is invalid. Allocate a L2 PT and
++ * point the L1 PTE to it */
++ /* Find a free L2 PT. */
++ for (i = 0; (i < pt->L2NumPages) &&
++ (pt->pgInfo[i].numEntries != 0); i++)
++ ;;
++ if (i < pt->L2NumPages) {
++ L2PageNum = i;
++ L2BasePa = pt->L2BasePa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ L2BaseVa = pt->L2BaseVa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ /* Endianness attributes are ignored for
++ * HW_MMU_COARSE_PAGE_SIZE */
++ status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
++ HW_MMU_COARSE_PAGE_SIZE, attrs);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Found valid L1 PTE of another size.
++ * Should not overwrite it. */
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pgTblVa = L2BaseVa;
++ if (size == HW_PAGE_SIZE_64KB)
++ pt->pgInfo[L2PageNum].numEntries += 16;
++ else
++ pt->pgInfo[L2PageNum].numEntries++;
++ DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
++ "PageNum %x numEntries %x\n", L2BaseVa,
++ L2BasePa, L2PageNum,
++ pt->pgInfo[L2PageNum].numEntries);
++ }
++ SYNC_LeaveCS(pt->hCSObj);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
++ pgTblVa, pa, va, size);
++ DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
++ "mixedSize %x\n", attrs->endianism,
++ attrs->elementSize, attrs->mixedSize);
++ status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
++ }
++ DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
++ return status;
++}
++
++/* Memory map kernel VA -- memory allocated with vmalloc */
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ struct HW_MMUMapAttrs_t *hwAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct page *pPage[1];
++ u32 i;
++ u32 paCurr;
++ u32 paNext;
++ u32 vaCurr;
++ u32 sizeCurr;
++ u32 numPages;
++ u32 pa;
++ u32 numOf4KPages;
++ u32 temp = 0;
++
++ DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
++ "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);
++
++ /*
++ * Do Kernel va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
++ i = 0;
++ vaCurr = ulMpuAddr;
++ pPage[0] = vmalloc_to_page((void *)vaCurr);
++ paNext = page_to_phys(pPage[0]);
++ while (DSP_SUCCEEDED(status) && (i < numPages)) {
++ /*
++ * Reuse paNext from the previous iteraion to avoid
++ * an extra va2pa call
++ */
++ paCurr = paNext;
++ sizeCurr = PAGE_SIZE;
++ /*
++ * If the next page is physically contiguous,
++ * map it with the current one by increasing
++ * the size of the region to be mapped
++ */
++ while (++i < numPages) {
++ pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
++ paNext = page_to_phys(pPage[0]);
++ DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
++ "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
++ if (paNext == (paCurr + sizeCurr))
++ sizeCurr += PAGE_SIZE;
++ else
++ break;
++
++ }
++ if (paNext == 0) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ pa = paCurr;
++ numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;
++ while (temp++ < numOf4KPages) {
++ get_page(phys_to_page(pa));
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
++ (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);
++ vaCurr += sizeCurr;
++ }
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
++ status);
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);
++ return status;
++}
++
++static DSP_STATUS run_IdleBoot(u32 prm_base, u32 cm_base,
++ u32 sysctrl_base)
++{
++ u32 temp;
++ DSP_STATUS status = DSP_SOK;
++ enum HW_PwrState_t pwrState;
++
++ /* Read PM_PWSTST_IVA2 */
++ HW_PWRST_IVA2RegGet(prm_base, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(prm_base, HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(cm_base, HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
++ }
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ udelay(10);
++ /* Assert IVA2-RST1 and IVA2-RST2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x07;
++ udelay(30);
++ /* set the SYSC for Idle Boot */
++ *((REG_UWORD32 *)((u32)(sysctrl_base) + 0x404)) = (u32)0x01;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x4)) =
++ (u32) temp;
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ udelay(20);
++ GetHWRegs(prm_base, cm_base);
++ /* Release Reset1 and Reset2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x05;
++ udelay(20);
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x04;
++ udelay(30);
++ return status;
++}
++
++
++void GetHWRegs(u32 prm_base, u32 cm_base)
++{
++ u32 temp;
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x00));
++ DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x20));
++ DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x48));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x4c));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x50));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x58));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE0));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE4));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0xA10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
++}
++
++/*
++ * ======== configureDspMmu ========
++ * Make DSP MMU page table entries.
++ */
++void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
++ u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ struct CFG_HOSTRES resources;
++ struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(sizeInBytes > 0);
++ DBG_Trace(DBG_LEVEL1,
++ "configureDspMmu entry %x pa %x, va %x, bytes %x ",
++ nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
++
++ DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
++ endianism, elemSize, mixedSize);
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ status = HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, dataBasePhys,
++ dspBaseVirt, sizeInBytes, nEntryStart,
++ &mapAttrs, HW_SET, HW_SET);
++}
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ */
++bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
++{
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++
++ /* Wait for response from board */
++ while (*((volatile u16 *)dwSyncAddr) && --usCount)
++ udelay(10);
++
++ /* If timed out: return FALSE */
++ if (!usCount) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
++ return FALSE;
++ }
++ return TRUE;
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+new file mode 100644
+index 0000000..cbf6925
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+@@ -0,0 +1,731 @@
++/*
++ * tiomap_pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap_pwr.c ========
++ * Description:
++ * Implementation of DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
++ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
++ *! code.
++ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
++ *! 06-Dec-2002 cring: Added Palm support.
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/io_sm.h>
++#include <dspbridge/chnl_sm.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/brddefs.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/iodefs.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++
++#include <dspbridge/pwr_sh.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_util.h"
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++
++#ifdef CONFIG_PM
++#include <mach/board-3430sdp.h>
++#endif
++extern struct MAILBOX_CONTEXT mboxsetting;
++static unsigned short enable_off_mode = 0;
++/*
++ * ======== handle_constraints_set ========
++ * Sets new DSP constraint
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 *pConstraintVal;
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES resources;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ pConstraintVal = (u32 *)(pArgs);
++ /* Read the target value requested by DSP */
++ DBG_Trace(DBG_LEVEL7, "handle_constraints_set:"
++ "opp requested = 0x%x\n", (u32)*(pConstraintVal+1));
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++
++ /* Set the new opp value */
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)((u32)*(pConstraintVal+1));
++ return DSP_SOK;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 opplevel;
++ struct IO_MGR *hIOMgr;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Off state, how much time should
++ * we wait? */
++ while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
++ status = WMD_E_TIMEOUT;
++ return status;
++ } else {
++
++ /* Save mailbox settings */
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
++ mboxsetting.sysconfig);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
++ mboxsetting.irqEnable0);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
++ mboxsetting.irqEnable1);
++ /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Bridger Driver state */
++ pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
++#ifdef CONFIG_BRIDGE_DVFS
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_FAILED(status))
++ return status;
++ IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
++ /* Set the OPP to low level before moving to OFF mode */
++ if (opplevel != VDD1_OPP1) {
++ DBG_Trace(DBG_LEVEL5,
++ "Tiomap_pwr.c - DSP requested"
++ " OPP = %d, MPU requesting low"
++ " OPP %d instead\n", opplevel,
++ VDD1_OPP1);
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(VDD1_OPP1);
++ status = DSP_SOK;
++ }
++#endif /* CONFIG_BRIDGE_DVFS */
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "handle_hibernation_fromDSP- FAILED\n");
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== SleepDSP ========
++ * Put DSP in low power consuming state.
++ */
++DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
++ IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ enum HW_PwrState_t pwrState;
++ enum HW_PwrState_t targetPwrState;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
++
++ /* next, check if sleep code is valid... */
++ if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
++ return DSP_EINVALIDARG;
++ }
++ switch (pDevContext->dwBrdState) {
++ case BRD_RUNNING:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP - Sent hibernate "
++ "command to DSP\n");
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPRETENTION);
++ targetPwrState = HW_PWR_STATE_RET;
++ }
++ break;
++ case BRD_RETENTION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else
++ return DSP_SOK;
++ break;
++ case BRD_HIBERNATION:
++ case BRD_DSP_HIBERNATION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ /* Already in Hibernation, so just return */
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
++ "hibernation\n");
++ return DSP_SOK;
++ case BRD_STOPPED:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Board in STOP state \n");
++ return DSP_SALREADYASLEEP;
++ default:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Bridge in Illegal state\n");
++ return DSP_EFAIL;
++ }
++ /* Get the PRCM DSP power domain status */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Standby state, how much time
++ * should we wait?*/
++ while ((pwrState != targetPwrState) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
++ " STANDBY %x \n", pwrState);
++ return WMD_E_TIMEOUT;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
++ pwrState);
++ /* Update the Bridger Driver state */
++ if (enable_off_mode)
++ pDevContext->dwBrdState = BRD_HIBERNATION;
++ else
++ pDevContext->dwBrdState = BRD_RETENTION;
++ /* Turn off DSP Peripheral clocks */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
++ }
++#endif
++ return status;
++}
++
++
++/*
++ * ======== WakeDSP ========
++ * Wake up DSP from sleep.
++ */
++DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++ u32 temp;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ /* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
++ if (pDevContext->dwBrdState == BRD_RUNNING ||
++ pDevContext->dwBrdState == BRD_STOPPED ||
++ pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ /* The Device is in 'RET' or 'OFF' state and WMD state is not
++ * 'SLEEP', this means state inconsistency, so return */
++ status = DSP_SOK;
++ return status;
++ }
++ /* Enable the DSP peripheral clocks and load monitor timer
++ * before waking the DSP */
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
++ pDevContext->uDspPerClks);
++ status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
++
++ /* Enabling Dppll in lock mode */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++
++ udelay(10);
++ if (DSP_SUCCEEDED(status)) {
++ /* Send a message to DSP to wake up */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ DBG_Trace(DBG_LEVEL7,
++ "\nWakeDSP: Power State After sending Interrupt "
++ "to DSP %x\n", pwrState);
++ /* set the device state to RUNNIG */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ } else {
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== DSPPeripheralClkCtrl ========
++ * Enable/Disable the DSP peripheral clocks as needed..
++ */
++DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 extClk = 0;
++ u32 extClkId = 0;
++ u32 extClkCmd = 0;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++ u32 tmpIndex;
++ u32 dspPerClksBefore;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++
++ DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
++ dspPerClksBefore = pDevContext->uDspPerClks;
++ DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
++ dspPerClksBefore);
++
++ extClk = (u32)*((u32 *)pArgs);
++
++ DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
++ extClk);
++
++ extClkId = extClk & MBX_PM_CLK_IDMASK;
++
++ /* process the power message -- TODO, keep it in a separate function */
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++ /* TODO -- Assert may be a too hard restriction here.. May be we should
++ * just return with failure when the CLK ID does not match */
++ /* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
++ if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl : Could n't get clock Id for"
++ "clkid 0x%x \n", clkIdIndex);
++ /* return with a more meaningfull error code */
++ return DSP_EFAIL;
++ }
++ extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
++ switch (extClkCmd) {
++ case BPWR_DisableClock:
++ /* Call BP to disable the needed clock */
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Disable CLK for \n");
++ status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, false);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) &=
++ (~((u32) (1 << clkIdIndex)));
++ } else {
++ DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
++ "to disable clk\n");
++ }
++ break;
++ case BPWR_EnableClock:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Enable CLK for \n");
++ status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, true);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) |= (1 << clkIdIndex);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl:Failed to Enable clk\n");
++ }
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Unsupported CMD \n");
++ /* unsupported cmd */
++ /* TODO -- provide support for AUTOIDLE Enable/Disable
++ * commands */
++ }
++ return status;
++}
++
++/*
++ * ========PreScale_DSP========
++ * Sends prescale notification to DSP
++ *
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
++ "0x%x\n", voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
++ "No notification to DSP\n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Send a prenotificatio to DSP */
++ DBG_Trace(DBG_LEVEL7,
++ "PreScale_DSP: Sent notification to DSP\n");
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
++ " state in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========PostScale_DSP========
++ * Sends postscale notification to DSP
++ *
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
++ voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: IVA in sleep. Wrote to shared "
++ "memory \n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ /* Send a post notification to DSP */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: Wrote to shared memory Sent post"
++ " notification to DSP\n");
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
++ "in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Disable========
++ * Disables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++
++ u32 clkIdx;
++ DSP_STATUS status = DSP_SOK;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Disables the interface clock of the peripheral */
++ status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ /* Disables the functional clock of the periphearl */
++ status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Enable========
++ * Enables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 clkIdx;
++ DSP_STATUS int_clk_status = DSP_EFAIL, fun_clk_status = DSP_EFAIL;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Enable the interface clock of the peripheral */
++ int_clk_status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
++ /* Enable the functional clock of the periphearl */
++ fun_clk_status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
++ }
++ }
++ if ((int_clk_status | fun_clk_status) != DSP_SOK)
++ return DSP_EFAIL;
++ return DSP_SOK;
++}
++
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable)
++{
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ u32 iva2_grpsel;
++ u32 mpu_grpsel;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return;
++
++ switch (ClkId) {
++ case BPWR_GPTimer5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer6:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT6;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT6;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer7:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT7;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT7;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer8:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT8;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT8;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP1:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP2:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP3:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP4:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ }
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
+new file mode 100644
+index 0000000..6121e8f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.c
+@@ -0,0 +1,427 @@
++/*
++ * tiomap_io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.c ========
++ * Description:
++ * Implementation for the io read/write routines.
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp: Fixed warning in WriteDspData function.
++ *! 16-Apr-2003 vp: Added support for TC word swap
++ *! 26-Feb-2003 vp: Fixed issue with EXT_BEG and EXT_END address.
++ *! 24-Feb-2003 vp: Ported to Linux platform
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/cfg.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "tiomap_io.h"
++
++static u32 ulExtBase;
++static u32 ulExtEnd;
++
++static u32 ulShm0End;
++static u32 ulDynExtBase;
++static u32 ulTraceSecBeg;
++static u32 ulTraceSecEnd;
++static u32 ulShmBaseVirt;
++
++bool bSymbolsReloaded = true;
++
++/*
++ * ======== ReadExtDspData ========
++ * Copies DSP external memory buffers to the host side buffers.
++ */
++DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ u32 dwExtProgVirtMem;
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ bool bTraceRead = false;
++
++ DBG_Trace(DBG_ENTER, "ReadExtDspData,"
++ "hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
++ "\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++
++ if (!ulShmBaseVirt) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ }
++ DBC_Assert(ulShmBaseVirt != 0);
++
++ /* Check if it is a read of Trace section */
++ if (!ulTraceSecBeg) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ }
++ DBC_Assert(ulTraceSecBeg != 0);
++
++ if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ DBC_Assert(ulTraceSecEnd != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
++ "section 0x%x \n", dwDSPAddr);
++ bTraceRead = true;
++ }
++ }
++
++ /* If reading from TRACE, force remap/unmap */
++ if ((bTraceRead) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ pDevContext->dwDspExtBaseAddr = 0;
++ }
++
++ if (!dwBaseAddr) {
++ /* Initialize ulExtBase and ulExtEnd */
++ ulExtBase = 0;
++ ulExtEnd = 0;
++
++ /* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
++ if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DYNEXTBASE, &ulDynExtBase);
++ }
++ DBC_Assert(ulDynExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTBASE, &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTEND, &ulExtEnd);
++ }
++ DBC_Assert(ulExtEnd != 0);
++
++ /* Trace buffer is right after the SHM SEG0,
++ * so set the base address to SHMBASE */
++ if (bTraceRead) {
++ ulExtBase = ulShmBaseVirt;
++ ulExtEnd = ulTraceSecEnd;
++ }
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++
++ if (ulExtEnd < ulExtBase)
++ status = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(status)) {
++ ulTLBBaseVirt =
++ pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
++
++ if (bTraceRead) {
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to SHMMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ } else {
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
++ ulDynExtBase + 1,
++ HW_PAGE_SIZE_64KB);
++ dwExtProgVirtMem -= ulShmOffsetVirt;
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ pDevContext->dwDspExtBaseAddr =
++ dwExtProgVirtMem;
++
++ /* This dwDspExtBaseAddr will get cleared only when the board is
++ * stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "failed to Map the program memory\n");
++ }
++ }
++
++ dwBaseAddr = dwExtProgVirtMem;
++ }
++ }
++
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7,
++ "Symbols missing for Ext Prog reading \n");
++ status = DSP_EFAIL;
++ }
++
++ offset = dwDSPAddr - ulExtBase;
++
++ if (DSP_SUCCEEDED(status))
++ memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
++
++ return status;
++}
++/*
++ * ======== WriteDspData ========
++ * purpose:
++ * Copies buffers to the DSP internal/external memory.
++ */
++DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
++{
++ u32 offset;
++ u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status;
++ u32 base1, base2, base3;
++ base1 = OMAP_DSP_MEM1_SIZE;
++ base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
++ base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
++ DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
++ if (offset < base1) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
++ resources.dwMemLength[2]);
++ } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
++ resources.dwMemLength[3]);
++ offset = offset - base2;
++ } else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
++ offset < base3 + OMAP_DSP_MEM3_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
++ resources.dwMemLength[4]);
++ offset = offset - base3;
++ } else{
++ status = DSP_EFAIL;
++ return status;
++ }
++ if (ulNumBytes)
++ memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+offset;
++
++ return status;
++}
++
++/*
++ * ======== WriteExtDspData ========
++ * purpose:
++ * Copies buffers to the external memory.
++ *
++ */
++DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType, bool bDynamicLoad)
++{
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ u32 dwOffset = 0;
++ u8 bTempByte1, bTempByte2;
++ u8 remainByte[4];
++ s32 i;
++ DSP_STATUS retVal = DSP_SOK;
++ u32 dwExtProgVirtMem;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ struct CFG_HOSTRES hostRes;
++ bool bTraceLoad = false;
++ bTempByte1 = 0x0;
++ bTempByte2 = 0x0;
++
++ DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
++ "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
++ if (bSymbolsReloaded) {
++ /* Check if it is a load to Trace section */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
++ "section 0x%x \n", dwDSPAddr);
++ bTraceLoad = true;
++ }
++ }
++
++ /* If dynamic, force remap/unmap */
++ if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ if (!dwBaseAddr) {
++ if (bSymbolsReloaded)
++ /* Get SHM_BEG EXT_BEG and EXT_END. */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ DBC_Assert(ulShmBaseVirt != 0);
++ if (bDynamicLoad) {
++ if (DSP_SUCCEEDED(retVal)) {
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal)) {
++ /* DR OMAPS00013235 : DLModules array may be
++ * in EXTMEM. It is expected that DYNEXTMEM and
++ * EXTMEM are contiguous, so checking for the
++ * upper bound at EXTEND should be Ok. */
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ } else {
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTBASE,
++ &ulExtBase);
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ }
++ /* Trace buffer it right after the SHM SEG0, so set the
++ * base address to SHMBASE */
++ if (bTraceLoad)
++ ulExtBase = ulShmBaseVirt;
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++ if (ulExtEnd < ulExtBase)
++ retVal = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(retVal)) {
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
++ DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DSP_TRACESEC_END,
++ &ulShm0End);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulDynExtBase);
++ }
++ }
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ if (bTraceLoad) {
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].
++ ulGppVa;
++ } else {
++ CFG_GetHostResources(
++ (struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++ dwExtProgVirtMem = hostRes.dwMemBase[1];
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ }
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
++ "pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++
++ pDevContext->dwDspExtBaseAddr =
++ (u32)MEM_LinearAddress((void *)
++ TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
++ - ulExtBase);
++ dwBaseAddr += pDevContext->dwDspExtBaseAddr;
++ /* This dwDspExtBaseAddr will get cleared only when
++ * the board is stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ retVal = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
++ "to Map the program memory\n");
++ }
++ }
++ }
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
++ retVal = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ for (i = 0; i < 4; i++)
++ remainByte[i] = 0x0;
++
++ dwOffset = dwDSPAddr - ulExtBase;
++ /* Also make sure the dwDSPAddr is < ulExtEnd */
++ if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
++ DBG_Trace(DBG_LEVEL7, "We can not load at this address "
++ "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
++ "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
++ ulExtEnd);
++ retVal = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if (ulNumBytes)
++ memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
++ ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
++ }
++ /* Unmap here to force remap for other Ext loads */
++ if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
++ MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ bSymbolsReloaded = false;
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
+new file mode 100644
+index 0000000..84a7553
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.h
+@@ -0,0 +1,112 @@
++/*
++ * tiomap_io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.h ========
++ * Description:
++ * Definitions, types and function prototypes for the io
++ * (r/w external mem).
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_IO_
++#define _TIOMAP_IO_
++
++/*
++ * Symbol that defines beginning of shared memory.
++ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
++ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
++ * (see dspMmuTlbEntry()).
++ */
++#define SHMBASENAME "SHM_BEG"
++#define EXTBASE "EXT_BEG"
++#define EXTEND "_EXT_END"
++#define DYNEXTBASE "_DYNEXT_BEG"
++#define DYNEXTEND "_DYNEXT_END"
++#define IVAEXTMEMBASE "_IVAEXTMEM_BEG"
++#define IVAEXTMEMEND "_IVAEXTMEM_END"
++
++
++#define DSP_TRACESEC_BEG "_BRIDGE_TRACE_BEG"
++#define DSP_TRACESEC_END "_BRIDGE_TRACE_END"
++
++#define SYS_PUTCBEG "_SYS_PUTCBEG"
++#define SYS_PUTCEND "_SYS_PUTCEND"
++#define BRIDGE_SYS_PUTC_current "_BRIDGE_SYS_PUTC_current"
++
++
++#define WORDSWAP_ENABLE 0x3 /* Enable word swap */
++
++/*
++ * ======== ReadExtDspData ========
++ * Reads it from DSP External memory. The external memory for the DSP
++ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
++ */
++extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteDspData ========
++ */
++extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteExtDspData ========
++ * Writes to the DSP External memory for external program.
++ * The ext mem for progra is configured by the combination of DSP MMU and
++ * SHM Memory manager in the CDB
++ */
++extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType,
++ bool bDynamicLoad);
++
++/*
++ * ======== WriteExt32BitDspData ========
++ * Writes 32 bit data to the external memory
++ */
++extern inline void WriteExt32BitDspData(IN const
++ struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
++ IN u32 val)
++{
++ *(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
++ 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
++}
++
++/*
++ * ======== ReadExt32BitDspData ========
++ * Reads 32 bit data from the external memory
++ */
++extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
++ *pDevContext, IN u32 dwDSPAddr)
++{
++ u32 retVal;
++ retVal = *(u32 *)dwDSPAddr;
++
++ retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
++ & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
++ return retVal;
++}
++
++#endif /* _TIOMAP_IO_ */
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
+new file mode 100644
+index 0000000..a6d5d62
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
+@@ -0,0 +1,195 @@
++/*
++ * tiomap_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#include <dspbridge/dbg.h>
++
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++
++#define MAILBOX_FIFOSTATUS(m) (0x80 + 4 * (m))
++
++static inline unsigned int fifo_full(void __iomem *mbox_base, int mbox_id)
++{
++ return __raw_readl(mbox_base + MAILBOX_FIFOSTATUS(mbox_id)) & 0x1;
++}
++
++DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 numMbxMsg;
++ u32 mbxValue;
++ struct CFG_HOSTRES resources;
++ u32 devType;
++ struct IO_MGR *hIOMgr;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
++
++ /* Read the messages in the mailbox until the message queue is empty */
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ DEV_GetDevType(pDevContext->hDevObject, &devType);
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (devType == DSP_UNIT) {
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_DSP2ARM, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ &mbxValue);
++ numMbxMsg--;
++ }
++ /* clear the DSP mailbox as well...*/
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_ARM2DSP, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_ARM2DSP, &mbxValue);
++ numMbxMsg--;
++ udelay(10);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_INT_NEW_MSG);
++ }
++ /* Enable the new message events on this IRQ line */
++ HW_MBOX_EventEnable(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ MBOX_ARM,
++ HW_MBOX_INT_NEW_MSG);
++ }
++
++ return status;
++}
++
++DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
++ MBOX_ARM, HW_MBOX_INT_NEW_MSG);
++ return DSP_SOK;
++}
++
++DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext,
++ u16 wMbVal)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ u32 opplevel = 0;
++#endif
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ unsigned long timeout;
++ u32 temp;
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ return DSP_EFAIL;
++#ifdef CONFIG_BRIDGE_DVFS
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ if (pdata->dsp_get_opp)
++ opplevel = (*pdata->dsp_get_opp)();
++ if (opplevel == 1) {
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(opplevel+1);
++ }
++ }
++#endif
++
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ /* Restore mailbox settings */
++ /* Restart the peripheral clocks that were disabled only
++ * in DSP initiated Hibernation case.*/
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ DSP_PeripheralClocks_Enable(pDevContext, NULL);
++ /* Enabling Dpll in lock mode*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++ }
++ HW_MBOX_restoreSettings(resources.dwMboxBase);
++
++ /* Access MMU SYS CONFIG register to generate a short wakeup */
++ temp = (u32) *((REG_UWORD32 *) ((u32)
++ (resources.dwDmmuBase) + 0x10));
++
++ pDevContext->dwBrdState = BRD_RUNNING;
++ }
++ timeout = jiffies + msecs_to_jiffies(1);
++ while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) {
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n");
++ return WMD_E_TIMEOUT;
++ }
++ }
++ DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
++ wMbVal);
++
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ wMbVal);
++ return DSP_SOK;
++}
++
++bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC,
++ u16 *pwIntrVal)
++{
++ struct CFG_HOSTRES resources;
++ u32 numMbxMsg;
++ u32 mbxValue;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
++
++ if (numMbxMsg > 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
++ HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
++
++ DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
++ *pwIntrVal = (u16) mbxValue;
++ }
++ /* Set *pfSchedDPC to true; */
++ *pfSchedDPC = true;
++ return true;
++}
+diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
+new file mode 100644
+index 0000000..d5551cb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/ue_deh.c
+@@ -0,0 +1,329 @@
++/*
++ * ue_deh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ue_deh.c ========
++ * Description:
++ * Implements upper edge DSP exception handling (DEH) functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn: Support for IVA DEH.
++ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "mmu_fault.h"
++#include "_tiomap.h"
++#include "_deh.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_pwr.h"
++#include <dspbridge/io_sm.h>
++
++static struct HW_MMUMapAttrs_t mapAttrs = { HW_LITTLE_ENDIAN,
++ HW_ELEM_SIZE_16BIT,
++ HW_MMU_CPUES} ;
++#define VirtToPhys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
++/*
++ * ======== WMD_DEH_Create ========
++ * Creates DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = NULL;
++ struct CFG_HOSTRES cfgHostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ /* Get WMD context info. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
++ if (pDehMgr == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Create an NTFY object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pDehMgr->hNtfy);
++
++ /* Create a DPC object. */
++ status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
++ (void *)pDehMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &cfgHostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in context structure */
++ pDehMgr->hWmdContext = hWmdContext;
++ pDehMgr->errInfo.dwErrMask = 0L;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Install ISR function for DSP MMU fault */
++ if ((request_irq(INT_DSP_MMU_IRQ, MMU_FaultIsr, 0,
++ "DspBridge\tiommu fault", (void *)pDehMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* If create failed, cleanup */
++ WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
++ *phDehMgr = NULL;
++ } else {
++ *phDehMgr = (struct DEH_MGR *)pDehMgr;
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Destroys DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* If notification object exists, delete it */
++ if (pDehMgr->hNtfy)
++ (void)NTFY_Delete(pDehMgr->hNtfy);
++ /* Disable DSP MMU fault */
++ free_irq(INT_DSP_MMU_IRQ, pDehMgr);
++ (void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
++ /* Deallocate the DEH manager object */
++ MEM_FreeObject(pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Registers for DEH notifications.
++ */
++DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
++ pDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ status = NTFY_Register(pDehMgr->hNtfy, hNotification,
++ uEventMask, uNotifyType);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_DEH_Notify ========
++ * DEH error notification function. Informs user about the error.
++ */
++void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
++ u32 dwErrInfo)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 memPhysical = 0;
++ u32 HW_MMU_MAX_TLB_COUNT = 31;
++ u32 extern faultAddr;
++ struct CFG_HOSTRES resources;
++ u32 dummyVaAddr;
++ HW_STATUS hwStatus;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources in MMU ISR **\n");
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
++ ulEventMask);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
++ "**********\n");
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++
++ switch (ulEventMask) {
++ case DSP_SYSERROR:
++ /* reset errInfo structure before use */
++ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ pDehMgr->errInfo.dwVal1 = dwErrInfo;
++ printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
++ "= 0x%x\n", dwErrInfo);
++ break;
++ case DSP_MMUFAULT:
++ /* MMU fault routine should have set err info
++ * structure */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
++ "errInfo = 0x%x\n", dwErrInfo);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal1);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal2);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", (unsigned int)faultAddr);
++ dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ memPhysical = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ dummyVaAddr = PG_ALIGN_LOW((u32)dummyVaAddr,
++ PG_SIZE_4K);
++ memPhysical = VirtToPhys(dummyVaAddr);
++ DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
++ "mem Physical= 0x%x\n", memPhysical);
++ pDevContext = (struct WMD_DEV_CONTEXT *)
++ pDehMgr->hWmdContext;
++ /* Reset the dynamic mmu index to fixed count if it
++ * exceeds 31. So that the dynmmuindex is always
++ * between the range of standard/fixed entries
++ * and 31. */
++ if (pDevContext->numTLBEntries >
++ HW_MMU_MAX_TLB_COUNT) {
++ pDevContext->numTLBEntries = pDevContext->
++ fixedTLBEntries;
++ }
++ DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
++ "PA: 0x%x\n", pDevContext->
++ numTLBEntries, faultAddr, memPhysical);
++ if (DSP_SUCCEEDED(status)) {
++ hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
++ memPhysical, faultAddr,
++ HW_PAGE_SIZE_4KB, 1, &mapAttrs,
++ HW_SET, HW_SET);
++ }
++ /* send an interrupt to DSP */
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ MBX_DEH_CLASS | MBX_DEH_EMMU);
++ /* Clear MMU interrupt */
++ HW_MMU_EventAck(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL6,
++ "WMD_DEH_Notify: Unknown Error, errInfo = "
++ "0x%x\n", dwErrInfo);
++ break;
++ }
++ /* Set the Board state as ERROR */
++ pDevContext->dwBrdState = BRD_ERROR;
++ /* Disable all the clocks that were enabled by DSP */
++ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ /* Call DSP Trace Buffer */
++ PrintDspTraceBuffer(hDehMgr->hWmdContext);
++
++ /* Signal DSP error/exception event. */
++ NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
++
++}
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Retrieves error information.
++ */
++DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBC_Require(pDehMgr);
++ DBC_Require(pErrInfo);
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* Copy DEH error info structure to PROC error info
++ * structure. */
++ pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
++ pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
++ pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
++ pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
++ }
++
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
++
++ return status;
++}
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch
new file mode 100644
index 0000000000..d75f15d00a
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch
@@ -0,0 +1,20 @@
+--- a/drivers/video/fbsysfs.c 2009-07-17 12:23:16.000000000 -0700
++++ b/drivers/video/fbsysfs.c 2009-07-17 12:24:32.000000000 -0700
+@@ -489,7 +489,7 @@
+ * fbdev to use configfs instead of sysfs */
+ static struct device_attribute device_attrs[] = {
+ __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+- __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
++ __ATTR(blank, S_IRUGO|S_IWUGO, show_blank, store_blank),
+ __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+ __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+ __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+@@ -498,7 +498,7 @@
+ __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+ __ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(stride, S_IRUGO, show_stride, NULL),
+- __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
++ __ATTR(rotate, S_IRUGO|S_IWUGO, show_rotate, store_rotate),
+ __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+ #ifdef CONFIG_FB_BACKLIGHT
+ __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-export-status.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-export-status.patch
new file mode 100644
index 0000000000..eaa78e28c7
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-export-status.patch
@@ -0,0 +1,44 @@
+From c78da49092fd206943f77aa9ebc3fa2c1301ac5a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Thu, 23 Apr 2009 18:19:32 -0700
+Subject: [PATCH] DSS2: Export display status to sysfs
+
+It is useful to know from userspace if the display has been turned off,
+e.g. to toggle display power from userspace.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 2c88718..28438fb 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -326,6 +326,15 @@ static ssize_t show_virt(struct device *dev,
+ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
+ }
+
++static ssize_t show_display_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omap_display *display = fb2display(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", display->state);
++}
++
+ static struct device_attribute omapfb_attrs[] = {
+ __ATTR(rotate_type, S_IRUGO, show_rotate_type, NULL),
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+@@ -333,6 +342,7 @@ static struct device_attribute omapfb_attrs[] = {
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
++ __ATTR(display_state, S_IRUGO, show_display_state, NULL),
+ };
+
+ int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch
new file mode 100644
index 0000000000..98a82c8a35
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch
@@ -0,0 +1,177 @@
+From a9cc890ffea21fa492678b1755a263120cbddf0e Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Mon, 20 Apr 2009 20:29:11 -0700
+Subject: [PATCH] DSS2: OMAPFB: Translate X/Y coordinates for the video planes when rotating.
+
+When rotating the video planes, translate the X/Y coordinates such that
+a [0,0] from userspace always maps to the correct upper left corner of
+the display. This patch assumes that you rotate plane 0 before rotating
+plane 1. Patch also corrects the scaling parameters so that the video is
+displayed in the correct orientation (vertically, instead of horizontally)
+when rotating by 90 / 270 degrees.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/dss/dispc.c | 16 ++++++++++++----
+ drivers/video/omap2/dss/overlay.c | 6 ++++++
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 28 ++++++++++++++++++++++++++++
+ 3 files changed, 46 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 7e551c2..bece91d 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1580,10 +1580,18 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ _dispc_set_pic_size(plane, width, height);
+
+ if (plane != OMAP_DSS_GFX) {
+- _dispc_set_scaling(plane, width, height,
+- out_width, out_height,
+- ilace, five_taps, fieldmode);
+- _dispc_set_vid_size(plane, out_width, out_height);
++ if (rotation == 1 || rotation == 3) {
++ _dispc_set_scaling(plane, width, height,
++ out_height, out_width,
++ ilace, five_taps, fieldmode);
++ _dispc_set_vid_size(plane, out_height, out_width);
++ } else {
++ _dispc_set_scaling(plane, width, height,
++ out_width, out_height,
++ ilace, five_taps, fieldmode);
++ _dispc_set_vid_size(plane, out_width, out_height);
++ }
++
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index c047206..a1a02b5 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -344,6 +344,20 @@
+ outh = info->out_height;
+ }
+
++ if ((ovl->supported_modes & info->color_mode) == 0) {
++ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
++ return -EINVAL;
++ }
++
++ if (ovl->id != OMAP_DSS_GFX && (info->rotation == 1 ||
++ info->rotation == 3)) {
++ if(outw > dh || outh > dw)
++ return -EINVAL;
++
++ /* If coordinates are invalid, they will be clipped later... */
++ return 0;
++ }
++
+ if (dw < info->pos_x + outw) {
+ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
+ dw, info->pos_x, outw);
+@@ -356,11 +370,6 @@
+ return -EINVAL;
+ }
+
+- if ((ovl->supported_modes & info->color_mode) == 0) {
+- DSSERR("overlay doesn't support mode %d\n", info->color_mode);
+- return -EINVAL;
+- }
+-
+ return 0;
+ }
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -400,7 +400,7 @@
+ struct omap_overlay *ovl;
+ bool ilace = 0;
+ int outw, outh;
+- int r;
++ int r, pos_x = 0, pos_y = 0;
+ int num_planes_enabled = 0;
+
+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+@@ -451,11 +451,51 @@
+ else
+ outh = ovl->info.out_height;
+
++ if (ovl->id != OMAP_DSS_GFX && ovl->info.rotation != 0) {
++ /* We need to rotate pos_x and pos_y with respect
++ to OMAP_DSS_GFX */
++
++ u16 dw, dh;
++ display->get_resolution(display, &dw, &dh);
++
++ DSSDBG("plane pos was: (%d, %d), %dx%d, scr: %dx%d \n", ovl->info.pos_x,
++ ovl->info.pos_y, outw, outh, dw, dh);
++
++ switch (ovl->info.rotation) {
++ case 1:
++ pos_y = ovl->info.pos_x;
++ pos_x = dw - ovl->info.pos_y - outh;
++ break;
++ case 2:
++ pos_x = dw - ovl->info.pos_x - outw;
++ pos_y = dh - ovl->info.pos_y - outh;
++ break;
++ case 3:
++ pos_x = ovl->info.pos_y;
++ pos_y = dh - ovl->info.pos_x - outw;
++ break;
++ }
++
++ /* Check sanity */
++ if (ovl->info.rotation != 2) {
++ if (dw < pos_x + outh)
++ pos_x = pos_y = 0;
++ else if (dh < pos_y + outw)
++ pos_x = pos_y = 0;
++ } else if ( (dw < ovl->info.pos_x + outw) || (dh < ovl->info.pos_y + outh) )
++ pos_x = pos_y = 0;
++
++ DSSDBG("pos_x is %d, pos_y is %d\n", pos_x, pos_y);
++ } else {
++ pos_x = ovl->info.pos_x;
++ pos_y = ovl->info.pos_y;
++ }
++
+ r = dispc_setup_plane(ovl->id, ovl->manager->id,
+ ovl->info.paddr,
+ ovl->info.screen_width,
+- ovl->info.pos_x,
+- ovl->info.pos_y,
++ pos_x,
++ pos_y,
+ ovl->info.width,
+ ovl->info.height,
+ outw,
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -484,22 +484,7 @@
+
+ if (var->rotate != fbi->var.rotate) {
+ DBG("rotation changing\n");
+-
+ ofbi->rotation = var->rotate;
+-
+- if (abs(var->rotate - fbi->var.rotate) != 2) {
+- int tmp;
+- DBG("rotate changing 90/270 degrees. "
+- "swapping x/y res\n");
+-
+- tmp = var->yres;
+- var->yres = var->xres;
+- var->xres = tmp;
+-
+- tmp = var->yres_virtual;
+- var->yres_virtual = var->xres_virtual;
+- var->xres_virtual = tmp;
+- }
+ }
+
+ xres_min = OMAPFB_PLANE_XRES_MIN;
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch
new file mode 100644
index 0000000000..7cb8a7d9bf
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch
@@ -0,0 +1,52 @@
+From 19a31ba4e8408ce80a4dbb96af489304c5e8128f Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Fri, 22 May 2009 18:58:33 -0700
+Subject: [PATCH] Fix scaling checks when rotation is 90 or 270 degrees.
+
+---
+ drivers/video/omap2/dss/dispc.c | 25 +++++++++++++++++++------
+ 1 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 088d353..77ca81b 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1508,16 +1508,29 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ }
+ } else {
+ /* video plane */
+-
++ u8 error = 0;
+ unsigned long fclk = 0;
+
+- if (out_width < width / maxdownscale ||
+- out_width > width * 8)
+- return -EINVAL;
++ if(rotation == 1 || rotation == 3)
++ {
++ if (out_width < height / maxdownscale || out_width > height * 8)
++ error = 1;
++
++ if (out_height < width / maxdownscale || out_height > width * 8)
++ error = 1;
++ } else {
++ if (out_width < width / maxdownscale || out_width > width * 8)
++ error = 1;
+
+- if (out_height < height / maxdownscale ||
+- out_height > height * 8)
++ if (out_height < height / maxdownscale || out_height > height * 8)
++ error = 1;
++ }
++
++ if(error != 0)
++ {
++ printk("DSS: Unable to down/up scale video plane\n");
+ return -EINVAL;
++ }
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/ehci.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/ehci.patch
new file mode 100644
index 0000000000..5a8c84471b
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/ehci.patch
@@ -0,0 +1,131 @@
+Index: git/arch/arm/mach-omap2/board-omap3beagle.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
++++ git/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -154,6 +154,7 @@ static int beagle_twl_gpio_setup(struct
+ * power switch and overcurrent detect
+ */
+
++#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+ gpio_request(gpio + 1, "EHCI_nOC");
+ gpio_direction_input(gpio + 1);
+
+@@ -163,7 +164,7 @@ static int beagle_twl_gpio_setup(struct
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+-
++#endif
+ return 0;
+ }
+
+Index: git/arch/arm/mach-omap2/usb-ehci.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/usb-ehci.c
++++ git/arch/arm/mach-omap2/usb-ehci.c
+@@ -147,9 +147,11 @@ static void setup_ehci_io_mux(void)
+
+ void __init usb_ehci_init(void)
+ {
++#if 0 /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+ /* Setup Pin IO MUX for EHCI */
+ if (cpu_is_omap34xx())
+ setup_ehci_io_mux();
++#endif
+
+ if (platform_device_register(&ehci_device) < 0) {
+ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+Index: git/drivers/usb/host/ehci-omap.c
+===================================================================
+--- git.orig/drivers/usb/host/ehci-omap.c
++++ git/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,25 @@
+ * to get the PHY state machine in working state
+ */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OMAP3_BEAGLE
++#define EXT_PHY_RESET_GPIO_PORT2 (147)
++#else
+ #define EXT_PHY_RESET_GPIO_PORT1 (57)
+ #define EXT_PHY_RESET_GPIO_PORT2 (61)
++#endif
+ #define EXT_PHY_RESET_DELAY (10)
+
++#define PHY_STP_PULLUP_ENABLE (0x10)
++#define PHY_STP_PULLUP_DISABLE (0x90)
++
+ /* ISSUE2:
+ * USBHOST supports External charge pump PHYs only
+ * Use the VBUS from Port1 to power VBUS of Port2 externally
+ * So use Port2 as the working ULPI port
+ */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+
+@@ -225,14 +234,43 @@ static int omap_start_ehc(struct platfor
+
+ #ifdef EXTERNAL_PHY_RESET
+ /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+ gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(EXT_PHY_RESET_DELAY);
+ #endif
+
++ /*
++ * The PHY register 0x7 - Interface Control register is
++ * configured to disable the integrated STP pull-up resistor
++ * used for interface protection.
++ *
++ * May not need to be here.
++ */
++ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (PHY_STP_PULLUP_DISABLE),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++ /* Force PHY to HS */
++ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (0x40),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+ /* Configure TLL for 60Mhz clk for ULPI */
+ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +345,9 @@ static int omap_start_ehc(struct platfor
+ * Hold the PHY in RESET for enough time till PHY is settled and ready
+ */
+ udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+
+@@ -393,7 +433,9 @@ static void omap_stop_ehc(struct platfor
+
+
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/logo_linux_clut224.ppm b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/logo_linux_clut224.ppm
new file mode 100644
index 0000000000..76b746bf91
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/logo_linux_clut224.ppm
@@ -0,0 +1,773 @@
+P3
+171 35
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 170 170 170 204 204 204 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 0 0 0
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 34 34 34 221 221 221 255 255 255 68 68 68 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 136 136 136 255 255 255 119 119 119 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 136 136 136 238 238 238 255 255 255 255 255 255
+187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 187 187 187
+255 255 255 255 255 255 255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0
+0 0 0 17 17 17 153 153 153 255 255 255 255 255 255 255 255 255 238 238 238 255 255 255
+85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 187 187 187 255 255 255 255 255 255
+238 238 238 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255
+255 255 255 255 255 255 68 68 68 0 0 0 119 119 119 187 187 187 255 255 255 255 255 255
+255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 85 85 85 238 238 238 255 255 255 51 51 51 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 17 17 17 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0
+0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+119 119 119 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255
+255 255 255 255 255 255 68 68 68 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0 0 0 0 204 204 204
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 153 153 153 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 153 153 153 255 255 255 170 170 170 17 17 17 0 0 0 0 0 0
+102 102 102 221 221 221 238 238 238 17 17 17 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0
+34 34 34 255 255 255 238 238 238 17 17 17 0 0 0 0 0 0 136 136 136 255 255 255
+85 85 85 0 0 0 34 34 34 255 255 255 221 221 221 102 102 102 0 0 0 0 0 0
+17 17 17 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+119 119 119 255 255 255 119 119 119 68 68 68 255 255 255 221 221 221 0 0 0 187 187 187
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 119 119 119 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 51 51 51 170 170 170
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0
+0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 187 187 187 136 136 136 51 51 51
+0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+68 68 68 255 255 255 187 187 187 153 153 153 255 255 255 255 255 255 85 85 85 238 238 238
+255 255 255 34 34 34 0 0 0 0 0 0 51 51 51 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 68 68 68 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0
+0 0 0 0 0 0 51 51 51 136 136 136 136 136 136 136 136 136 255 255 255 255 255 255
+102 102 102 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 238 238 238 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 238 238 238 221 221 221 238 238 238 255 255 255 255 255 255 204 204 204 255 255 255
+221 221 221 0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 170 170 170 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136
+0 0 0 0 0 0 51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0
+102 102 102 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 102 102 102 255 255 255
+204 204 204 0 0 0 51 51 51 255 255 255 204 204 204 85 85 85 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 255 255 255 170 170 170 221 221 221 255 255 255 255 255 255
+153 153 153 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0
+51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 51 51 51 0 0 0 0 0 0
+119 119 119 238 238 238 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+85 85 85 0 0 0 17 17 17 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 136 136 136 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+136 136 136 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 85 85 85 119 119 119 255 255 255 255 255 255
+102 102 102 0 0 0 0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+85 85 85 0 0 0 0 0 0 17 17 17 136 136 136 255 255 255 255 255 255 255 255 255
+255 255 255 187 187 187 136 136 136 17 17 17 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0
+102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 119 119 119
+0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 187 187 187 255 255 255 255 255 255
+255 255 255 255 255 255 136 136 136 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 102 102 102 255 255 255 221 221 221 0 0 0 17 17 17 238 238 238 255 255 255
+34 34 34 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255
+136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+0 0 0 0 0 0 0 0 0 17 17 17 170 170 170 255 255 255 255 255 255 255 255 255
+153 153 153 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/memory-move-malloc-end.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/memory-move-malloc-end.patch
new file mode 100644
index 0000000000..9000642104
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/memory-move-malloc-end.patch
@@ -0,0 +1,9 @@
+--- git/arch/arm/plat-omap/include/mach/vmalloc.h 2009-06-09 15:14:54.000000000 -0700
++++ git/arch/arm/plat-omap/include/mach/vmalloc.h 2009-06-09 15:06:35.000000000 -0700
+@@ -17,5 +17,5 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+-#define VMALLOC_END (PAGE_OFFSET + 0x18000000)
++#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch
new file mode 100644
index 0000000000..14e0934468
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch
@@ -0,0 +1,11 @@
+--- a/drivers/video/backlight/backlight.c 2009-07-17 12:20:05.000000000 -0700
++++ b/drivers/video/backlight/backlight.c 2009-07-17 12:20:46.000000000 -0700
+@@ -205,7 +205,7 @@
+
+ static struct device_attribute bl_device_attributes[] = {
+ __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
+- __ATTR(brightness, 0644, backlight_show_brightness,
++ __ATTR(brightness, 0666, backlight_show_brightness,
+ backlight_store_brightness),
+ __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
+ NULL),
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight.patch
new file mode 100644
index 0000000000..65b551f1de
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/screen-backlight.patch
@@ -0,0 +1,10 @@
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -128,6 +128,7 @@ config MACH_OMAP3EVM
+ config MACH_OMAP3_BEAGLE
+ bool "OMAP3 BEAGLE board"
+ depends on ARCH_OMAP3 && ARCH_OMAP34XX
++ select BACKLIGHT_CLASS_DEVICE
+
+ config MACH_OVERO
+ bool "Gumstix Overo board"
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/sound-headphone-detection.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/sound-headphone-detection.patch
new file mode 100644
index 0000000000..ef8b3626bc
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/sound-headphone-detection.patch
@@ -0,0 +1,93 @@
+From db8f1eba9154789c45c6a92413bbbd94f5d9c7f5 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Wed, 29 Apr 2009 17:30:25 -0700
+Subject: [PATCH] Touch Book: turn on/off the class D amplifier depending on whether the
+ headphones are plugged into the jack or not.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ sound/soc/omap/omap3beagle.c | 33 +++++++++++++++++++++++++++++++++
+ 1 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
+index fd24a4a..1236638 100644
+--- a/sound/soc/omap/omap3beagle.c
++++ b/sound/soc/omap/omap3beagle.c
+@@ -20,7 +20,10 @@
+ */
+
+ #include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/soc.h>
+@@ -35,6 +38,9 @@
+ #include "omap-pcm.h"
+ #include "../codecs/twl4030.h"
+
++#define TB_HEADPHONE_GPIO 56
++#define TB_HEADPHONE_IRQ OMAP_GPIO_IRQ(TB_HEADPHONE_GPIO)
++
+ static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -103,6 +109,33 @@ static struct snd_soc_device omap3beagle_snd_devdata = {
+
+ static struct platform_device *omap3beagle_snd_device;
+
++static void jack_work_func(struct work_struct *wq)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++ struct snd_soc_codec *codec = socdev->codec;
++
++ snd_soc_dapm_sync(codec);
++}
++DECLARE_WORK(jack_work, jack_work_func);
++
++static irqreturn_t touchbook_headphone_event(int irq, void *snd)
++{
++ int status = gpio_get_value(TB_HEADPHONE_GPIO);
++ struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++ struct snd_soc_codec *codec = socdev->codec;
++
++ if(status) {
++ snd_soc_dapm_disable_pin(codec, "HFL");
++ snd_soc_dapm_disable_pin(codec, "HFR");
++ } else {
++ snd_soc_dapm_enable_pin(codec, "HFL");
++ snd_soc_dapm_enable_pin(codec, "HFR");
++ }
++
++ schedule_work(&jack_work);
++ return IRQ_HANDLED;
++}
++
+ static int __init omap3beagle_soc_init(void)
+ {
+ int ret;
+@@ -123,10 +156,22 @@ static int __init omap3beagle_soc_init(void)
+ omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
+ *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
++ /* Touch Book -- headphone jack sensor */
++ omap_set_gpio_debounce(TB_HEADPHONE_GPIO, 1);
++ omap_set_gpio_debounce_time(TB_HEADPHONE_GPIO, 0xff);
++
++ ret = request_irq(TB_HEADPHONE_IRQ, touchbook_headphone_event, IRQF_TRIGGER_RISING |
++ IRQF_TRIGGER_FALLING, "touchbook_headphone", omap3beagle_snd_device);
++ if (ret < 0)
++ goto err1;
++
+ ret = platform_device_add(omap3beagle_snd_device);
+ if (ret)
+ goto err1;
+
++ /* Detect headphone status */
++ touchbook_headphone_event(0, omap3beagle_snd_device);
++
+ return 0;
+
+ err1:
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/tincantools-puppy.diff b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/tincantools-puppy.diff
new file mode 100644
index 0000000000..c7856731e5
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/tincantools-puppy.diff
@@ -0,0 +1,66 @@
+--- /tmp/board-omap3beagle.c 2009-07-01 01:06:44.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-01 01:06:50.000000000 +0200
+@@ -125,6 +125,13 @@
+ .wires = 8,
+ .gpio_wp = 29,
+ },
++ {
++ .mmc = 2,
++ .wires = 4,
++ .gpio_wp = 141,
++ .gpio_cd = 162,
++ .transceiver = true,
++ },
+ {} /* Terminator */
+ };
+
+@@ -132,6 +139,11 @@
+ .supply = "vmmc",
+ };
+
++static struct regulator_consumer_supply beagle_vmmc2_supply = {
++ .supply = "vmmc",
++};
++
++
+ static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+ };
+@@ -148,6 +160,7 @@
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
++ beagle_vmmc2_supply.dev = mmc[1].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+@@ -209,6 +222,21 @@
+ .consumer_supplies = &beagle_vmmc1_supply,
+ };
+
++/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .min_uV = 2700000,
++ .max_uV = 3150000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
++ | REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
+ /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+ static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+@@ -284,6 +312,7 @@
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
++ .vmmc2 = &beagle_vmmc2,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch
new file mode 100644
index 0000000000..f8353afee5
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch
@@ -0,0 +1,87 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 7c3897f..0c62ace 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -491,9 +491,82 @@ static ssize_t ads7846_disable_store(struct device *dev,
+
+ static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+
++static ssize_t show_debounce_max(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_max);
++}
++
++static ssize_t show_debounce_tol(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_tol);
++}
++
++static ssize_t show_debounce_rep(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_rep);
++}
++
++static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->x_plate_ohms);
++}
++
++static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_max = i;
++ return count;
++}
++
++static ssize_t write_debounce_tol(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_tol = i;
++ return count;
++}
++
++static ssize_t write_debounce_rep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_rep = i;
++ return count;
++}
++
++static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->x_plate_ohms = i;
++ return count;
++}
++
++static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
++static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
++static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
++static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++
+ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_pen_down.attr,
+ &dev_attr_disable.attr,
++ &dev_attr_debounce_max.attr,
++ &dev_attr_debounce_tol.attr,
++ &dev_attr_debounce_rep.attr,
++ &dev_attr_x_plate_ohms.attr,
+ NULL,
+ };
+
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch
new file mode 100644
index 0000000000..6196716f23
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch
@@ -0,0 +1,108 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 0c62ace..8f6e83c 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -127,6 +127,7 @@ struct ads7846 {
+ void (*filter_cleanup)(void *data);
+ int (*get_pendown_state)(void);
+ int gpio_pendown;
++ int rotate;
+ };
+
+ /* leave chip selected when we're done, for quicker re-select? */
+@@ -511,6 +512,11 @@ static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *at
+ return sprintf(buf, "%u\n", ts->x_plate_ohms);
+ }
+
++static ssize_t show_rotate(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->rotate);
++}
++
+ static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ unsigned long i;
+@@ -555,10 +561,22 @@ static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *a
+ return count;
+ }
+
++static ssize_t write_rotate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i = 0;
++
++ if (strict_strtoul(buf, 10, &i) || i > 3)
++ return -EINVAL;
++
++ ts->rotate = i;
++ return count;
++}
++
+ static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
+ static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
+ static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
+ static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++static DEVICE_ATTR(rotate, S_IRUGO | S_IWUGO, show_rotate, write_rotate);
+
+ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_pen_down.attr,
+@@ -567,6 +585,7 @@ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_debounce_tol.attr,
+ &dev_attr_debounce_rep.attr,
+ &dev_attr_x_plate_ohms.attr,
++ &dev_attr_rotate.attr,
+ NULL,
+ };
+
+@@ -596,6 +615,8 @@ static void ads7846_rx(void *ads)
+ {
+ struct ads7846 *ts = ads;
+ struct ads7846_packet *packet = ts->packet;
++ struct ads7846_platform_data *pdata = ts->spi->dev.platform_data;
++
+ unsigned Rt;
+ u16 x, y, z1, z2;
+
+@@ -657,6 +678,7 @@ static void ads7846_rx(void *ads)
+ * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
+ */
+ if (Rt) {
++ int t;
+ struct input_dev *input = ts->input;
+
+ if (!ts->pendown) {
+@@ -666,6 +688,27 @@ static void ads7846_rx(void *ads)
+ dev_dbg(&ts->spi->dev, "DOWN\n");
+ #endif
+ }
++
++ switch(ts->rotate)
++ {
++ case 0:
++ x = pdata->x_max - x + pdata->x_min;
++ y = pdata->y_max - y + pdata->y_min;
++ break;
++ case 1:
++ t = x;
++ x = pdata->x_max - (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++ y = pdata->y_min + (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++ break;
++ case 2:
++ break;
++ case 3:
++ t = x;
++ x = pdata->x_min + (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++ y = pdata->y_max - (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++ break;
++ }
++
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+ input_report_abs(input, ABS_PRESSURE, Rt);
+@@ -980,6 +1023,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+
+ dev_set_drvdata(&spi->dev, ts);
+
++ ts->rotate = 0;
+ ts->packet = packet;
+ ts->spi = spi;
+ ts->input = input_dev;
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch
new file mode 100644
index 0000000000..e2df6cf83d
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch
@@ -0,0 +1,30 @@
+--- a/drivers/usb/core/hub.c 2009-07-28 08:47:00.000000000 -0700
++++ b/drivers/usb/core/hub.c 2009-07-28 08:32:20.000000000 -0700
+@@ -22,6 +22,7 @@
+ #include <linux/kthread.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/gpio.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+@@ -3129,9 +3130,18 @@
+ USB_PORT_FEAT_C_RESET);
+ }
+
+- if (connect_change)
++ if (connect_change) {
++ if(portstatus & USB_PORT_STAT_CONNECTION) {
++ gpio_set_value(176,0);
++ mdelay(25);
++ }
+ hub_port_connect_change(hub, i,
+ portstatus, portchange);
++ if(portstatus & USB_PORT_STAT_CONNECTION) {
++ mdelay(75);
++ gpio_set_value(176,1);
++ }
++ }
+ } /* end for i */
+
+ /* deal with hub status changes */
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch
new file mode 100644
index 0000000000..2bcfbdcc2f
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch
@@ -0,0 +1,36 @@
+--- git/drivers/usb/gadget/file_storage.c 2009-06-07 12:18:05.000000000 -0700
++++ git/drivers/usb/gadget/file_storage.c 2009-06-07 12:08:36.000000000 -0700
+@@ -283,8 +283,8 @@
+ *
+ * DO NOT REUSE THESE IDs with any other driver!! Ever!!
+ * Instead: allocate your own, using normal USB-IF procedures. */
+-#define DRIVER_VENDOR_ID 0x0525 // NetChip
+-#define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget
++#define DRIVER_VENDOR_ID 0xa110 // Always Innovating, Inc.
++#define DRIVER_PRODUCT_ID 0x0001 // Tablet product
+
+
+ /*
+@@ -2025,9 +2025,9 @@
+ {
+ u8 *buf = (u8 *) bh->buf;
+
+- static char vendor_id[] = "Linux ";
++ static char vendor_id[] = "AI, Inc.";
+ static char product_disk_id[] = "File-Stor Gadget";
+- static char product_cdrom_id[] = "File-CD Gadget ";
++ static char product_cdrom_id[] = "Touch Book ";
+
+ if (!fsg->curlun) { // Unsupported LUNs are okay
+ fsg->bad_lun_okay = 1;
+@@ -3671,8 +3671,8 @@
+ }
+ if (num_sectors < min_sectors) {
+ LINFO(curlun, "file too small: %s\n", filename);
+- rc = -ETOOSMALL;
+- goto out;
++// rc = -ETOOSMALL;
++// goto out;
+ }
+
+ get_file(filp);
diff --git a/recipes/linux/linux-omap-2.6.29/omap3evm/defconfig b/recipes/linux/linux-omap-2.6.29/omap3evm/defconfig
index da726718c4..05f1dddaad 100644
--- a/recipes/linux/linux-omap-2.6.29/omap3evm/defconfig
+++ b/recipes/linux/linux-omap-2.6.29/omap3evm/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-omap1
-# Thu Jan 8 16:06:45 2009
+# Linux kernel version: 2.6.29-omap1
+# Thu Jul 16 16:20:40 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -35,7 +35,7 @@ CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
@@ -44,23 +44,32 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
@@ -71,10 +80,8 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -82,6 +89,7 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
@@ -97,7 +105,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
@@ -105,11 +112,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -125,7 +130,6 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
CONFIG_FREEZER=y
#
@@ -136,7 +140,6 @@ CONFIG_FREEZER=y
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
@@ -163,11 +166,13 @@ CONFIG_FREEZER=y
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_DAVINCI is not set
CONFIG_ARCH_OMAP=y
# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# TI OMAP Implementations
@@ -191,45 +196,29 @@ CONFIG_OMAP_BOOT_REASON=y
# CONFIG_OMAP_GPIO_SWITCH is not set
# CONFIG_OMAP_MUX is not set
CONFIG_OMAP_MCBSP=y
-# CONFIG_OMAP_MMU_FWK is not set
# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
CONFIG_OMAP_DM_TIMER=y
CONFIG_OMAP_LL_DEBUG_UART1=y
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
-CONFIG_OMAP2_DSS=y
-CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
-# CONFIG_OMAP2_DSS_RFBI is not set
-CONFIG_OMAP2_DSS_VENC=y
-# CONFIG_OMAP2_DSS_SDI is not set
-CONFIG_OMAP2_DSS_DSI=y
-CONFIG_OMAP2_DSS_USE_DSI_PLL=y
-# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
-CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
CONFIG_ARCH_OMAP34XX=y
CONFIG_ARCH_OMAP3430=y
#
# OMAP Board Type
#
+# CONFIG_MACH_NOKIA_RX51 is not set
# CONFIG_MACH_OMAP_LDP is not set
# CONFIG_MACH_OMAP_3430SDP is not set
CONFIG_MACH_OMAP3EVM=y
# CONFIG_MACH_OMAP3_BEAGLE is not set
# CONFIG_MACH_OVERO is not set
# CONFIG_MACH_OMAP3_PANDORA is not set
-CONFIG_OMAP_TICK_GPTIMER=12
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
#
# Processor Type
@@ -292,13 +281,12 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
CONFIG_LEDS=y
-CONFIG_ALIGNMENT_TRAP=n
+# CONFIG_ALIGNMENT_TRAP is not set
#
# Boot options
@@ -346,7 +334,6 @@ CONFIG_ARM_ERRATUM_451034=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=y
@@ -366,6 +353,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -440,6 +428,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -461,8 +450,6 @@ CONFIG_BT_HIDP=y
#
# Bluetooth device drivers
#
-CONFIG_BT_HCIUSB=y
-CONFIG_BT_HCIUSB_SCO=y
# CONFIG_BT_HCIBTUSB is not set
CONFIG_BT_HCIBTSDIO=y
# CONFIG_BT_HCIUART is not set
@@ -476,10 +463,16 @@ CONFIG_BT_HCIBPA10X=y
# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
CONFIG_NL80211=y
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
CONFIG_MAC80211=y
#
@@ -494,11 +487,7 @@ CONFIG_MAC80211_RC_DEFAULT="pid"
CONFIG_MAC80211_LEDS=y
# CONFIG_MAC80211_DEBUGFS is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -519,101 +508,6 @@ CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-CONFIG_MTD_OMAP_NOR=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-CONFIG_MTD_NAND=y
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_NAND_ECC_SMC is not set
-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
-# CONFIG_MTD_NAND_GPIO is not set
-CONFIG_MTD_NAND_OMAP2=y
-CONFIG_MTD_NAND_IDS=y
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-CONFIG_MTD_NAND_PLATFORM=y
-# CONFIG_MTD_ALAUDA is not set
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_VERIFY_WRITE=y
-# CONFIG_MTD_ONENAND_GENERIC is not set
-CONFIG_MTD_ONENAND_OMAP2=y
-# CONFIG_MTD_ONENAND_OTP is not set
-# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
-# CONFIG_MTD_ONENAND_SIM is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -630,11 +524,18 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_93CX6=m
# CONFIG_ICS932S401 is not set
# CONFIG_OMAP_STI is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=m
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -677,6 +578,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -721,8 +623,12 @@ CONFIG_SMSC_PHY=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
CONFIG_REALTEK_PHY=y
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
CONFIG_MDIO_BITBANG=y
+# CONFIG_MDIO_GPIO is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
@@ -730,6 +636,8 @@ CONFIG_SMC91X=y
# CONFIG_DM9000 is not set
# CONFIG_ENC28J60 is not set
CONFIG_SMC911X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -766,6 +674,10 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y
# CONFIG_RT2X00 is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -844,7 +756,6 @@ CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -860,6 +771,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
@@ -870,6 +782,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
# CONFIG_TOUCHSCREEN_TSC210X is not set
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_INPUT_MISC is not set
#
@@ -911,10 +824,10 @@ CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
@@ -952,20 +865,15 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
CONFIG_TWL4030_MADC=m
-CONFIG_TWL4030_PWRBUTTON=y
CONFIG_TWL4030_POWEROFF=y
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_SENSORS_TSL2563 is not set
-# CONFIG_LP5521 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -978,12 +886,12 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
# CONFIG_SPI_TSC210X is not set
# CONFIG_SPI_TSC2301 is not set
# CONFIG_SPI_SPIDEV is not set
@@ -1035,6 +943,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -1055,6 +964,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
@@ -1108,6 +1018,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
CONFIG_TWL4030_CORE=y
CONFIG_TWL4030_POWER=y
# CONFIG_MFD_TMIO is not set
@@ -1117,6 +1028,7 @@ CONFIG_TWL4030_POWER=y
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -1172,6 +1084,8 @@ CONFIG_VIDEO_CX2341X=m
# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_VIDEO_OMAP34XX_ISP_RESIZER is not set
# CONFIG_SOC_CAMERA is not set
CONFIG_V4L_USB_DRIVERS=y
CONFIG_USB_VIDEO_CLASS=m
@@ -1205,6 +1119,8 @@ CONFIG_RADIO_ADAPTERS=y
# CONFIG_USB_DSBR is not set
# CONFIG_USB_SI470X is not set
# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_TTPCI_EEPROM is not set
@@ -1238,8 +1154,6 @@ CONFIG_DVB_USB_AF9005_REMOTE=m
# CONFIG_DVB_USB_ANYSEE is not set
# CONFIG_DVB_USB_DTV5100 is not set
# CONFIG_DVB_USB_AF9015 is not set
-CONFIG_DVB_TTUSB_BUDGET=m
-CONFIG_DVB_TTUSB_DEC=m
# CONFIG_DVB_SIANO_SMS1XXX is not set
#
@@ -1257,6 +1171,12 @@ CONFIG_DVB_TTUSB_DEC=m
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
CONFIG_DVB_CX24110=m
@@ -1268,8 +1188,10 @@ CONFIG_DVB_S5H1420=m
CONFIG_DVB_STV0299=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
+# CONFIG_DVB_TDA8261 is not set
CONFIG_DVB_VES1X93=m
CONFIG_DVB_TUNER_ITD1000=m
+# CONFIG_DVB_TUNER_CX24113 is not set
CONFIG_DVB_TDA826X=m
CONFIG_DVB_TUA6100=m
# CONFIG_DVB_CX24116 is not set
@@ -1310,11 +1232,17 @@ CONFIG_DVB_NXT200X=m
# CONFIG_DVB_OR51132 is not set
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LGDT330X=m
+# CONFIG_DVB_LGDT3304 is not set
CONFIG_DVB_S5H1409=m
CONFIG_DVB_AU8522=m
CONFIG_DVB_S5H1411=m
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
CONFIG_DVB_PLL=m
@@ -1366,19 +1294,30 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
-CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=14
-CONFIG_FB_OMAP2=y
-CONFIG_FB_OMAP2_DEBUG=y
-# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
-CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=4
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
#
# OMAP2/3 Display Device Drivers
#
CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
CONFIG_PANEL_SHARP_LS037V7DW01=y
# CONFIG_PANEL_N800 is not set
# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_LTV350QV=y
@@ -1387,7 +1326,7 @@ CONFIG_LCD_ILI9320=y
CONFIG_LCD_VGG2432A4=y
CONFIG_LCD_PLATFORM=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CORGI=y
+CONFIG_BACKLIGHT_GENERIC=y
#
# Display device support
@@ -1424,6 +1363,7 @@ CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1443,10 +1383,8 @@ CONFIG_SND_USB_CAIAQ=m
CONFIG_SND_USB_CAIAQ_INPUT=y
CONFIG_SND_SOC=y
CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_MCBSP=y
-CONFIG_SND_OMAP_SOC_OMAP3EVM=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
-CONFIG_SND_SOC_TWL4030=y
# CONFIG_SOUND_PRIME is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
@@ -1467,11 +1405,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1479,12 +1415,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
# CONFIG_THRUSTMASTER_FF is not set
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
@@ -1514,6 +1453,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1555,7 +1495,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1624,12 +1563,14 @@ CONFIG_USB_SERIAL_SPCP8X5=m
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_OPTICON is not set
CONFIG_USB_SERIAL_DEBUG=m
#
@@ -1670,10 +1611,12 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
CONFIG_USB_GADGET_M66592=y
CONFIG_USB_M66592=y
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
@@ -1694,7 +1637,7 @@ CONFIG_USB_ETH_RNDIS=y
CONFIG_USB_OTG_UTILS=y
CONFIG_USB_GPIO_VBUS=y
# CONFIG_ISP1301_OMAP is not set
-CONFIG_TWL4030_USB=y
+CONFIG_NOP_USB_XCEIV=y
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_UNSAFE_RESUME=y
@@ -1726,6 +1669,7 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_OMAP_PWM is not set
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
#
@@ -1801,6 +1745,7 @@ CONFIG_RTC_DRV_TWL4030=y
# CONFIG_DMADEVICES is not set
# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# CBUS support
@@ -1820,7 +1765,7 @@ CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
+# CONFIG_FS_POSIX_ACL is not set
CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
# CONFIG_XFS_QUOTA is not set
@@ -1829,12 +1774,14 @@ CONFIG_XFS_FS=m
# CONFIG_XFS_DEBUG is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
# CONFIG_QUOTA_NETLINK_INTERFACE is not set
CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
@@ -1874,10 +1821,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1885,24 +1829,8 @@ CONFIG_HFSPLUS_FS=m
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_FS_POSIX_ACL=y
-CONFIG_JFFS2_FS_SECURITY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_RTIME=y
-CONFIG_JFFS2_RUBIN=y
-# CONFIG_JFFS2_CMODE_NONE is not set
-CONFIG_JFFS2_CMODE_PRIORITY=y
-# CONFIG_JFFS2_CMODE_SIZE is not set
-# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1920,6 +1848,7 @@ CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
@@ -2029,12 +1958,13 @@ CONFIG_DEBUG_MUTEXES=y
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
@@ -2058,6 +1988,7 @@ CONFIG_PREEMPT_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
@@ -2067,8 +1998,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_ERRORS is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_LL is not set
#
# Security options
@@ -2092,7 +2022,7 @@ CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
@@ -2130,7 +2060,7 @@ CONFIG_CRYPTO_XCBC=m
#
# Digest
#
-CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
@@ -2180,6 +2110,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
@@ -2187,10 +2118,8 @@ CONFIG_CRC_ITU_T=y
CONFIG_CRC32=y
CONFIG_CRC7=y
CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/01-vfp-pm.patch b/recipes/linux/linux-omap-2.6.29/vfp/01-vfp-pm.patch
new file mode 100644
index 0000000000..70d4d1efc5
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/vfp/01-vfp-pm.patch
@@ -0,0 +1,128 @@
+From: Ben Dooks <ben-linux@fluff.org>
+Date: Thu, 18 Dec 2008 10:26:54 +0000 (+0100)
+Subject: 5349/1: VFP: Add PM code to save and restore current VFP state
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=d504d72ad38e54b5feda67e956834348d6a500e1
+
+5349/1: VFP: Add PM code to save and restore current VFP state
+
+[ARM] 5349/1: VFP: Add PM code to save and restore current VFP state
+
+When CONFIG_PM is selected, the VFP code does not have any handler
+installed to deal with either saving the VFP state of the current
+task, nor does it do anything to try and restore the VFP after a
+resume.
+
+On resume, the VFP will have been reset and the co-processor access
+control registers are in an indeterminate state (very probably the
+CP10 and CP11 the VFP uses will have been disabled by the ARM core
+reset). When this happens, resume will break as soon as it tries to
+unfreeze the tasks and restart scheduling.
+
+Add a sys device to allow us to hook the suspend call to save the
+current thread state if the thread is using VFP and a resume hook
+which restores the CP10/CP11 access and ensures the VFP is disabled
+so that the lazy swapping will take place on next access.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
+index c85860b..8de86e4 100644
+--- a/arch/arm/vfp/vfp.h
++++ b/arch/arm/vfp/vfp.h
+@@ -377,6 +377,6 @@ struct op {
+ u32 flags;
+ };
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ extern void vfp_save_state(void *location, u32 fpexc);
+ #endif
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index a62dcf7..b21f43f 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -166,7 +166,7 @@ process_exception:
+ @ retry the faulted instruction
+ ENDPROC(vfp_support_entry)
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ ENTRY(vfp_save_state)
+ @ Save the current VFP state
+ @ r0 - save location
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 67ca340..9f476a1 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -322,6 +322,61 @@ static void vfp_enable(void *unused)
+ set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
+ }
+
++#ifdef CONFIG_PM
++#include <linux/sysdev.h>
++
++static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
++{
++ struct thread_info *ti = current_thread_info();
++ u32 fpexc = fmrx(FPEXC);
++
++ /* if vfp is on, then save state for resumption */
++ if (fpexc & FPEXC_EN) {
++ printk(KERN_DEBUG "%s: saving vfp state\n", __func__);
++ vfp_save_state(&ti->vfpstate, fpexc);
++
++ /* disable, just in case */
++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
++ }
++
++ /* clear any information we had about last context state */
++ memset(last_VFP_context, 0, sizeof(last_VFP_context));
++
++ return 0;
++}
++
++static int vfp_pm_resume(struct sys_device *dev)
++{
++ /* ensure we have access to the vfp */
++ vfp_enable(NULL);
++
++ /* and disable it to ensure the next usage restores the state */
++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
++
++ return 0;
++}
++
++static struct sysdev_class vfp_pm_sysclass = {
++ .name = "vfp",
++ .suspend = vfp_pm_suspend,
++ .resume = vfp_pm_resume,
++};
++
++static struct sys_device vfp_pm_sysdev = {
++ .cls = &vfp_pm_sysclass,
++};
++
++static void vfp_pm_init(void)
++{
++ sysdev_class_register(&vfp_pm_sysclass);
++ sysdev_register(&vfp_pm_sysdev);
++}
++
++
++#else
++static inline void vfp_pm_init(void) { }
++#endif /* CONFIG_PM */
++
+ #include <linux/smp.h>
+
+ /*
+@@ -365,6 +420,7 @@ static int __init vfp_init(void)
+ vfp_vector = vfp_support_entry;
+
+ thread_register_notifier(&vfp_notifier_block);
++ vfp_pm_init();
+
+ /*
+ * We detected VFP, and the support code is
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/02-vfp-ptrace.patch b/recipes/linux/linux-omap-2.6.29/vfp/02-vfp-ptrace.patch
new file mode 100644
index 0000000000..feba206f95
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/vfp/02-vfp-ptrace.patch
@@ -0,0 +1,231 @@
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Wed, 11 Feb 2009 11:12:56 +0000 (+0100)
+Subject: 5387/1: Add ptrace VFP support on ARM
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4dd5beb2244f15c895aba46474bd89545327d1a6
+
+5387/1: Add ptrace VFP support on ARM
+
+[ARM] 5387/1: Add ptrace VFP support on ARM
+
+This patch adds ptrace support for setting and getting the VFP registers
+using PTRACE_SETVFPREGS and PTRACE_GETVFPREGS. The user_vfp structure
+defined in asm/user.h contains 32 double registers (to cover VFPv3 and
+Neon hardware) and the FPSCR register.
+
+Cc: Paul Brook <paul@codesourcery.com>
+Cc: Daniel Jacobowitz <dan@codesourcery.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
+index 7319261..236a06b 100644
+--- a/arch/arm/include/asm/ptrace.h
++++ b/arch/arm/include/asm/ptrace.h
+@@ -27,6 +27,8 @@
+ /* PTRACE_SYSCALL is 24 */
+ #define PTRACE_GETCRUNCHREGS 25
+ #define PTRACE_SETCRUNCHREGS 26
++#define PTRACE_GETVFPREGS 27
++#define PTRACE_SETVFPREGS 28
+
+ /*
+ * PSR bits
+diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
+index 68b9ec8..b9dc8a8 100644
+--- a/arch/arm/include/asm/thread_info.h
++++ b/arch/arm/include/asm/thread_info.h
+@@ -113,6 +113,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
+ extern void iwmmxt_task_release(struct thread_info *);
+ extern void iwmmxt_task_switch(struct thread_info *);
+
++extern void vfp_sync_state(struct thread_info *thread);
++
+ #endif
+
+ /*
+diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h
+index 825c1e7..df95e05 100644
+--- a/arch/arm/include/asm/user.h
++++ b/arch/arm/include/asm/user.h
+@@ -81,4 +81,13 @@ struct user{
+ #define HOST_TEXT_START_ADDR (u.start_code)
+ #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+
++/*
++ * User specific VFP registers. If only VFPv2 is present, registers 16 to 31
++ * are ignored by the ptrace system call.
++ */
++struct user_vfp {
++ unsigned long long fpregs[32];
++ unsigned long fpscr;
++};
++
+ #endif /* _ARM_USER_H */
+diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
+index df653ea..89882a1 100644
+--- a/arch/arm/kernel/ptrace.c
++++ b/arch/arm/kernel/ptrace.c
+@@ -653,6 +653,54 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp)
+ }
+ #endif
+
++#ifdef CONFIG_VFP
++/*
++ * Get the child VFP state.
++ */
++static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
++{
++ struct thread_info *thread = task_thread_info(tsk);
++ union vfp_state *vfp = &thread->vfpstate;
++ struct user_vfp __user *ufp = data;
++
++ vfp_sync_state(thread);
++
++ /* copy the floating point registers */
++ if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
++ sizeof(vfp->hard.fpregs)))
++ return -EFAULT;
++
++ /* copy the status and control register */
++ if (put_user(vfp->hard.fpscr, &ufp->fpscr))
++ return -EFAULT;
++
++ return 0;
++}
++
++/*
++ * Set the child VFP state.
++ */
++static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
++{
++ struct thread_info *thread = task_thread_info(tsk);
++ union vfp_state *vfp = &thread->vfpstate;
++ struct user_vfp __user *ufp = data;
++
++ vfp_sync_state(thread);
++
++ /* copy the floating point registers */
++ if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
++ sizeof(vfp->hard.fpregs)))
++ return -EFAULT;
++
++ /* copy the status and control register */
++ if (get_user(vfp->hard.fpscr, &ufp->fpscr))
++ return -EFAULT;
++
++ return 0;
++}
++#endif
++
+ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+ int ret;
+@@ -775,6 +823,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ break;
+ #endif
+
++#ifdef CONFIG_VFP
++ case PTRACE_GETVFPREGS:
++ ret = ptrace_getvfpregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_SETVFPREGS:
++ ret = ptrace_setvfpregs(child, (void __user *)data);
++ break;
++#endif
++
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
+index 8de86e4..c8c98dd 100644
+--- a/arch/arm/vfp/vfp.h
++++ b/arch/arm/vfp/vfp.h
+@@ -377,6 +377,4 @@ struct op {
+ u32 flags;
+ };
+
+-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ extern void vfp_save_state(void *location, u32 fpexc);
+-#endif
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index b21f43f..902d396 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -166,7 +166,6 @@ process_exception:
+ @ retry the faulted instruction
+ ENDPROC(vfp_support_entry)
+
+-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ ENTRY(vfp_save_state)
+ @ Save the current VFP state
+ @ r0 - save location
+@@ -181,7 +180,6 @@ ENTRY(vfp_save_state)
+ stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
+ mov pc, lr
+ ENDPROC(vfp_save_state)
+-#endif
+
+ last_VFP_context_address:
+ .word last_VFP_context
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 9f476a1..7e12390 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -377,6 +377,55 @@ static void vfp_pm_init(void)
+ static inline void vfp_pm_init(void) { }
+ #endif /* CONFIG_PM */
+
++/*
++ * Synchronise the hardware VFP state of a thread other than current with the
++ * saved one. This function is used by the ptrace mechanism.
++ */
++#ifdef CONFIG_SMP
++void vfp_sync_state(struct thread_info *thread)
++{
++ /*
++ * On SMP systems, the VFP state is automatically saved at every
++ * context switch. We mark the thread VFP state as belonging to a
++ * non-existent CPU so that the saved one will be reloaded when
++ * needed.
++ */
++ thread->vfpstate.hard.cpu = NR_CPUS;
++}
++#else
++void vfp_sync_state(struct thread_info *thread)
++{
++ unsigned int cpu = get_cpu();
++ u32 fpexc = fmrx(FPEXC);
++
++ /*
++ * If VFP is enabled, the previous state was already saved and
++ * last_VFP_context updated.
++ */
++ if (fpexc & FPEXC_EN)
++ goto out;
++
++ if (!last_VFP_context[cpu])
++ goto out;
++
++ /*
++ * Save the last VFP state on this CPU.
++ */
++ fmxr(FPEXC, fpexc | FPEXC_EN);
++ vfp_save_state(last_VFP_context[cpu], fpexc);
++ fmxr(FPEXC, fpexc);
++
++ /*
++ * Set the context to NULL to force a reload the next time the thread
++ * uses the VFP.
++ */
++ last_VFP_context[cpu] = NULL;
++
++out:
++ put_cpu();
++}
++#endif
++
+ #include <linux/smp.h>
+
+ /*
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch b/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch
new file mode 100644
index 0000000000..216d4f5eaa
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch
@@ -0,0 +1,136 @@
+From: George G. Davis <gdavis@mvista.com>
+Date: Wed, 1 Apr 2009 18:27:18 +0000 (+0100)
+Subject: 5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4f7720780dc4a298a6d59c0ec39f7687022cc36f
+
+5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+
+[ARM] 5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+
+We've observed that ARM VFP state can be corrupted during VFP exception
+handling when PREEMPT is enabled. The exact conditions are difficult
+to reproduce but appear to occur during VFP exception handling when a
+task causes a VFP exception which is handled via VFP_bounce and is then
+preempted by yet another task which in turn causes yet another VFP
+exception. Since the VFP_bounce code is not preempt safe, VFP state then
+becomes corrupt. In order to prevent preemption from occuring while
+handling a VFP exception, this patch disables preemption while handling
+VFP exceptions.
+
+Signed-off-by: George G. Davis <gdavis@mvista.com>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
+index ba592a9..a2bed62 100644
+--- a/arch/arm/vfp/entry.S
++++ b/arch/arm/vfp/entry.S
+@@ -15,13 +15,16 @@
+ * r10 = thread_info structure
+ * lr = failure return
+ */
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/assembler.h>
++#include <asm/thread_info.h>
+ #include <asm/vfpmacros.h>
++#include "../kernel/entry-header.S"
+
+ ENTRY(do_vfp)
++#ifdef CONFIG_PREEMPT
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ add r11, r4, #1 @ increment it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ enable_irq
+ ldr r4, .LCvfp
+ ldr r11, [r10, #TI_CPU] @ CPU number
+@@ -30,6 +33,12 @@ ENTRY(do_vfp)
+ ENDPROC(do_vfp)
+
+ ENTRY(vfp_null_entry)
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, lr
+ ENDPROC(vfp_null_entry)
+
+@@ -41,6 +50,12 @@ ENDPROC(vfp_null_entry)
+
+ __INIT
+ ENTRY(vfp_testing_entry)
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ ldr r0, VFP_arch_address
+ str r5, [r0] @ known non-zero value
+ mov pc, r9 @ we have handled the fault
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index 902d396..ea0a156 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -131,6 +131,12 @@ check_for_exception:
+ VFPFMXR FPEXC, r1 @ restore FPEXC last
+ sub r2, r2, #4
+ str r2, [sp, #S_PC] @ retry the instruction
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, r9 @ we think we have handled things
+
+
+@@ -149,6 +155,12 @@ look_for_VFP_exceptions:
+ @ not recognised by VFP
+
+ DBGSTR "not VFP"
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, lr
+
+ process_exception:
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 75457b3..01599c4 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -266,7 +266,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ * on VFP subarch 1.
+ */
+ vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
+- return;
++ goto exit;
+ }
+
+ /*
+@@ -297,7 +297,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
+ */
+ if (fpexc ^ (FPEXC_EX | FPEXC_FP2V))
+- return;
++ goto exit;
+
+ /*
+ * The barrier() here prevents fpinst2 being read
+@@ -310,6 +310,8 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
+ if (exceptions)
+ vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
++ exit:
++ preempt_enable();
+ }
+
+ static void vfp_enable(void *unused)
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/04-vfp-threads.patch b/recipes/linux/linux-omap-2.6.29/vfp/04-vfp-threads.patch
new file mode 100644
index 0000000000..221b2774a1
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/vfp/04-vfp-threads.patch
@@ -0,0 +1,98 @@
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Jul 2009 21:20:59 +0000 (+0300)
+Subject: So far vfp_sync_state worked only for threads other than the current one. This worked...
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=23671113997664ae55c8132fc4a56e676d5b46c7
+
+So far vfp_sync_state worked only for threads other than the current one. This worked for tracing other threads, but not for PTRACE_TRACEME. Syncing for the current thread will also be needed by an upcoming patch adding support for VFP context save / restore around signal handlers.
+
+For SMP we need get_cpu now, since we have to protect the FPEXC
+register, other than this things remained the same for threads other
+than the current.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 01599c4..969b77a 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -380,12 +380,19 @@ static inline void vfp_pm_init(void) { }
+ #endif /* CONFIG_PM */
+
+ /*
+- * Synchronise the hardware VFP state of a thread other than current with the
+- * saved one. This function is used by the ptrace mechanism.
++ * Synchronise the hardware VFP state of a thread with the saved one.
++ * This function is used by the ptrace mechanism and the signal handler path.
+ */
+-#ifdef CONFIG_SMP
+ void vfp_sync_state(struct thread_info *thread)
+ {
++ unsigned int cpu = get_cpu();
++ u32 fpexc = fmrx(FPEXC);
++ int vfp_enabled;
++ int self;
++
++ vfp_enabled = fpexc & FPEXC_EN;
++ self = thread == current_thread_info();
++#ifdef CONFIG_SMP
+ /*
+ * On SMP systems, the VFP state is automatically saved at every
+ * context switch. We mark the thread VFP state as belonging to a
+@@ -393,18 +400,22 @@ void vfp_sync_state(struct thread_info *thread)
+ * needed.
+ */
+ thread->vfpstate.hard.cpu = NR_CPUS;
+-}
+-#else
+-void vfp_sync_state(struct thread_info *thread)
+-{
+- unsigned int cpu = get_cpu();
+- u32 fpexc = fmrx(FPEXC);
+-
+ /*
+- * If VFP is enabled, the previous state was already saved and
+- * last_VFP_context updated.
++ * Only the current thread's saved VFP context can be out-of-date.
++ * For others there is nothing else to do, since we already ensured
++ * force loading above.
+ */
+- if (fpexc & FPEXC_EN)
++ if (!self)
++ goto out;
++#endif
++ /*
++ * If the VFP is enabled only the current thread's saved VFP
++ * context can get out-of-date. For other threads the context
++ * was updated when the current thread started to use the VFP.
++ * This also means that the context will be reloaded next time
++ * the thread uses the VFP, so no need to enforce it.
++ */
++ if (vfp_enabled && !self)
+ goto out;
+
+ if (!last_VFP_context[cpu])
+@@ -413,8 +424,14 @@ void vfp_sync_state(struct thread_info *thread)
+ /*
+ * Save the last VFP state on this CPU.
+ */
+- fmxr(FPEXC, fpexc | FPEXC_EN);
++ if (!vfp_enabled)
++ fmxr(FPEXC, fpexc | FPEXC_EN);
+ vfp_save_state(last_VFP_context[cpu], fpexc);
++ /*
++ * Disable VFP in case it was enabled so that the force reload
++ * can happen.
++ */
++ fpexc &= ~FPEXC_EN;
+ fmxr(FPEXC, fpexc);
+
+ /*
+@@ -426,7 +443,6 @@ void vfp_sync_state(struct thread_info *thread)
+ out:
+ put_cpu();
+ }
+-#endif
+
+ #include <linux/smp.h>
+
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/05-vfp-signal-handlers.patch b/recipes/linux/linux-omap-2.6.29/vfp/05-vfp-signal-handlers.patch
new file mode 100644
index 0000000000..f648188584
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/vfp/05-vfp-signal-handlers.patch
@@ -0,0 +1,148 @@
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Jul 2009 21:21:06 +0000 (+0300)
+Subject: Signal handlers can use floating point, so prevent them to corrupt the main thread...
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4daa6b5d833c401a9de6f136ea23daa971fc4fdc
+
+Signal handlers can use floating point, so prevent them to corrupt the main thread's VFP context. So far there were two signal stack frame formats defined based on the VFP implementation, but recently a new user struct was added for ptrace that covers all possibilities, so use it for the signal stack too.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+
+diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
+index bf65e9f..5534653 100644
+--- a/arch/arm/include/asm/ucontext.h
++++ b/arch/arm/include/asm/ucontext.h
+@@ -59,23 +59,19 @@ struct iwmmxt_sigframe {
+ #endif /* CONFIG_IWMMXT */
+
+ #ifdef CONFIG_VFP
+-#if __LINUX_ARM_ARCH__ < 6
+-/* For ARM pre-v6, we use fstmiax and fldmiax. This adds one extra
+- * word after the registers, and a word of padding at the end for
+- * alignment. */
+ #define VFP_MAGIC 0x56465001
+-#define VFP_STORAGE_SIZE 152
+-#else
+-#define VFP_MAGIC 0x56465002
+-#define VFP_STORAGE_SIZE 144
+-#endif
+
+ struct vfp_sigframe
+ {
+ unsigned long magic;
+ unsigned long size;
+- union vfp_state storage;
+-};
++ struct user_vfp ufp;
++ unsigned long reserved;
++} __attribute__((__aligned__(8)));
++
++/* 8 byte for magic and size, 260 byte for ufp and 4 byte padding */
++#define VFP_STORAGE_SIZE sizeof(struct vfp_sigframe)
++
+ #endif /* CONFIG_VFP */
+
+ /*
+@@ -91,7 +87,7 @@ struct aux_sigframe {
+ #ifdef CONFIG_IWMMXT
+ struct iwmmxt_sigframe iwmmxt;
+ #endif
+-#if 0 && defined CONFIG_VFP /* Not yet saved. */
++#ifdef CONFIG_VFP
+ struct vfp_sigframe vfp;
+ #endif
+ /* Something that isn't a valid magic number for any coprocessor. */
+diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
+index 80b8b5c..a5ef7f5 100644
+--- a/arch/arm/kernel/signal.c
++++ b/arch/arm/kernel/signal.c
+@@ -196,6 +196,67 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
+
+ #endif
+
++#ifdef CONFIG_VFP
++
++static int preserve_vfp_context(struct vfp_sigframe __user *frame)
++{
++ struct thread_info *thread = current_thread_info();
++ struct vfp_hard_struct *h = &thread->vfpstate.hard;
++ const unsigned long magic = VFP_MAGIC;
++ const unsigned long size = VFP_STORAGE_SIZE;
++ int err = 0;
++
++ vfp_sync_state(thread);
++ __put_user_error(magic, &frame->magic, err);
++ __put_user_error(size, &frame->size, err);
++
++ /*
++ * Copy the floating point registers. There can be unused
++ * registers see asm/hwcap.h for details.
++ */
++ err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
++ sizeof(h->fpregs));
++ /*
++ * Copy the status and control register.
++ */
++ __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
++
++ return err ? -EFAULT : 0;
++}
++
++static int restore_vfp_context(struct vfp_sigframe __user *frame)
++{
++ struct thread_info *thread = current_thread_info();
++ struct vfp_hard_struct *h = &thread->vfpstate.hard;
++ unsigned long magic;
++ unsigned long size;
++ int err = 0;
++
++ vfp_sync_state(thread);
++ __get_user_error(magic, &frame->magic, err);
++ __get_user_error(size, &frame->size, err);
++
++ if (err)
++ return -EFAULT;
++ if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
++ return -EINVAL;
++
++ /*
++ * Copy the floating point registers. There can be unused
++ * registers see asm/hwcap.h for details.
++ */
++ err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
++ sizeof(h->fpregs));
++ /*
++ * Copy the status and control register.
++ */
++ __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
++
++ return err ? -EFAULT : 0;
++}
++
++#endif
++
+ /*
+ * Do a signal return; undo the signal stack. These are aligned to 64-bit.
+ */
+@@ -254,8 +315,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
+ err |= restore_iwmmxt_context(&aux->iwmmxt);
+ #endif
+ #ifdef CONFIG_VFP
+-// if (err == 0)
+-// err |= vfp_restore_state(&sf->aux.vfp);
++ if (err == 0)
++ err |= restore_vfp_context(&aux->vfp);
+ #endif
+
+ return err;
+@@ -369,8 +430,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
+ err |= preserve_iwmmxt_context(&aux->iwmmxt);
+ #endif
+ #ifdef CONFIG_VFP
+-// if (err == 0)
+-// err |= vfp_save_state(&sf->aux.vfp);
++ if (err == 0)
++ err |= preserve_vfp_context(&aux->vfp);
+ #endif
+ __put_user_error(0, &aux->end_magic, err);
+
diff --git a/recipes/linux/linux-omap-2.6.31/arch-has-holes.diff b/recipes/linux/linux-omap-2.6.31/arch-has-holes.diff
new file mode 100755
index 0000000000..d6fccc9696
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/arch-has-holes.diff
@@ -0,0 +1,145 @@
+From: Russell King - ARM Linux <linux@arm.linux.org.uk>
+To: Rabin Vincent <rabin@rab.in>
+Cc: "Aguirre Rodriguez, Sergio Alberto" <saaguirre@ti.com>,
+ "Syed Mohammed, Khasim" <khasim@ti.com>,
+ "linux-arm-kernel@lists.arm.linux.org.uk"
+ <linux-arm-kernel@lists.arm.linux.org.uk>,
+ "linux-omap@vger.kernel.org" <linux-omap@vger.kernel.org>
+Subject: Re: Exception while handling MEM Hole on OMAP3 / ARM Cortex A8
+Message-ID: <20090907142210.GB23361@n2100.arm.linux.org.uk>
+List-ID: <linux-omap.vger.kernel.org>
+X-Mailing-List: linux-omap@vger.kernel.org
+
+On Tue, Aug 18, 2009 at 08:31:49AM +0530, Rabin Vincent wrote:
+> Here's a fixed version:
+
+And here's my revised version with these fixes in. I changed the
+while loop to a do..while loop instead (since we will always have
+at least one memory bank, it's pointless doing that test for the
+first iteration.)
+
+Acks and tested-bys would be useful please.
+
+diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
+index 376be1a..cefedf0 100644
+--- a/arch/arm/include/asm/memory.h
++++ b/arch/arm/include/asm/memory.h
+@@ -218,7 +218,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
+ *
+ * page_to_pfn(page) convert a struct page * to a PFN number
+ * pfn_to_page(pfn) convert a _valid_ PFN number to struct page *
+- * pfn_valid(pfn) indicates whether a PFN number is valid
+ *
+ * virt_to_page(k) convert a _valid_ virtual address to struct page *
+ * virt_addr_valid(k) indicates whether a virtual address is valid
+@@ -227,10 +226,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
+
+ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
+
+-#ifndef CONFIG_SPARSEMEM
+-#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
+-#endif
+-
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+
+@@ -247,18 +242,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
+ #define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
+ #define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
+
+-#define pfn_valid(pfn) \
+- ({ \
+- unsigned int nid = PFN_TO_NID(pfn); \
+- int valid = nid < MAX_NUMNODES; \
+- if (valid) { \
+- pg_data_t *node = NODE_DATA(nid); \
+- valid = (pfn - node->node_start_pfn) < \
+- node->node_spanned_pages; \
+- } \
+- valid; \
+- })
+-
+ #define virt_to_page(kaddr) \
+ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
+diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
+index 9c746af..3a32af4 100644
+--- a/arch/arm/include/asm/page.h
++++ b/arch/arm/include/asm/page.h
+@@ -194,6 +194,10 @@ typedef unsigned long pgprot_t;
+
+ typedef struct page *pgtable_t;
+
++#ifndef CONFIG_SPARSEMEM
++extern int pfn_valid(unsigned long);
++#endif
++
+ #include <asm/memory.h>
+
+ #endif /* !__ASSEMBLY__ */
+
+--- /tmp/init.c 2009-09-15 10:17:10.000000000 +0200
++++ git/arch/arm/mm/init.c 2009-09-15 10:17:01.000000000 +0200
+@@ -15,6 +15,7 @@
+ #include <linux/mman.h>
+ #include <linux/nodemask.h>
+ #include <linux/initrd.h>
++#include <linux/sort.h>
+ #include <linux/highmem.h>
+
+ #include <asm/mach-types.h>
+@@ -349,12 +350,43 @@
+ free_area_init_node(node, zone_size, min, zhole_size);
+ }
+
++#ifndef CONFIG_SPARSEMEM
++int pfn_valid(unsigned long pfn)
++{
++ struct meminfo *mi = &meminfo;
++ unsigned int left = 0, right = mi->nr_banks;
++
++ do {
++ unsigned int mid = (right + left) / 2;
++ struct membank *bank = &mi->bank[mid];
++
++ if (pfn < bank_pfn_start(bank))
++ right = mid;
++ else if (pfn >= bank_pfn_end(bank))
++ left = mid + 1;
++ else
++ return 1;
++ } while (left < right);
++ return 0;
++}
++EXPORT_SYMBOL(pfn_valid);
++#endif
++
++static int __init meminfo_cmp(const void *_a, const void *_b)
++{
++ const struct membank *a = _a, *b = _b;
++ long cmp = bank_pfn_start(a) - bank_pfn_start(b);
++ return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
++}
++
+ void __init bootmem_init(void)
+ {
+ struct meminfo *mi = &meminfo;
+ unsigned long min, max_low, max_high;
+ int node, initrd_node;
+
++ sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL);
++
+ /*
+ * Locate which node contains the ramdisk image, if any.
+ */
+diff -purN git2/arch/arm/Kconfig git/arch/arm/Kconfig
+--- git2/arch/arm/Kconfig 2009-07-20 05:07:12.000000000 +0530
++++ git/arch/arm/Kconfig 2009-08-17 12:08:37.000000000 +0530
+@@ -569,6 +570,7 @@ config ARCH_OMAP
+ select ARCH_REQUIRE_GPIOLIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
++ select ARCH_HAS_HOLES_MEMORYMODEL
+ help
+ Support for TI's OMAP platform (OMAP1 and OMAP2).
+
diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig b/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig
new file mode 100644
index 0000000000..efe8e6d8dd
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig
@@ -0,0 +1,2806 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-omap1
+# Thu Sep 17 17:27:43 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OVERO is not set
+CONFIG_MACH_OMAP3EVM=y
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEV is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID6_PQ=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_QL is not set
+# CONFIG_DM_MULTIPATH_ST is not set
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_ENC28J60=y
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_SPI is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+CONFIG_RTL8187_LEDS=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_P54_SPI is not set
+CONFIG_P54_LEDS=y
+# CONFIG_AR9170_USB is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+# CONFIG_RT2800USB is not set
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_RFKILL=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+# CONFIG_WL12XX is not set
+# CONFIG_IWM is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+# CONFIG_TWL4030_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_MADC=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP_VIDEOOUT=m
+# CONFIG_NTSC_M is not set
+CONFIG_PAL_BDGHI=y
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+# CONFIG_USB_GSPCA_MR97310A is not set
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+# CONFIG_USB_GSPCA_SN9C20X is not set
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_CX231XX=m
+# CONFIG_VIDEO_CX231XX_ALSA is not set
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+# CONFIG_DVB_USB_CE6230 is not set
+# CONFIG_SMS_SIANO_MDTV is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=y
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+# CONFIG_PANEL_TAAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+# CONFIG_SND_OMAP_SOC_OMAP3EVM is not set
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP210X is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+# CONFIG_USB_SERIAL_SYMBOL is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=m
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+# CONFIG_PRISM2_USB is not set
+CONFIG_ECHO=m
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_OUTPUT=y
+CONFIG_ANDROID_TIMED_GPIO=m
+# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set
+# CONFIG_DST is not set
+# CONFIG_POHMELFS is not set
+# CONFIG_STLC45XX is not set
+# CONFIG_PLAN9AUTH is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_CPC is not set
+# CONFIG_FB_UDL is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+# CONFIG_GFS2_FS_LOCKING_DLM is not set
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch b/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch
new file mode 100644
index 0000000000..d8dcd522dc
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch
@@ -0,0 +1,22 @@
+From 870bb728d41c231941791bffe8783cd88cb7580a Mon Sep 17 00:00:00 2001
+From: Steve Sakoman <steve@sakoman.com>
+Date: Sat, 29 Aug 2009 15:46:30 -0700
+Subject: [PATCH] ARM: OMAP3: Fix EHCI initialization for Beagle
+
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 07aee90..65934ea 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -161,7 +161,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+
+ /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+ gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
++ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm b/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm
new file mode 100644
index 0000000000..d29fc1c544
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm
@@ -0,0 +1,73147 @@
+P3
+# CREATOR: GIMP PNM Filter Version 1.1
+387 63
+255
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+248
+138
+64
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+247
+143
+74
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+248
+138
+64
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+130
+53
+247
+130
+60
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+152
+92
+249
+146
+83
+250
+139
+73
+247
+130
+60
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+247
+150
+84
+246
+156
+93
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+152
+92
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+250
+139
+73
+247
+150
+84
+249
+159
+103
+247
+165
+111
+249
+174
+124
+248
+180
+134
+252
+185
+144
+240
+181
+138
+219
+170
+138
+219
+170
+138
+230
+173
+136
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+159
+103
+214
+151
+109
+121
+100
+85
+65
+67
+64
+74
+68
+68
+129
+102
+78
+214
+151
+109
+246
+156
+93
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+204
+141
+99
+102
+91
+75
+65
+67
+64
+81
+77
+76
+146
+111
+88
+238
+159
+107
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+247
+150
+84
+245
+162
+103
+162
+125
+96
+81
+77
+76
+55
+66
+67
+99
+90
+79
+187
+140
+108
+249
+159
+103
+247
+150
+84
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+187
+140
+108
+102
+91
+75
+58
+69
+70
+76
+78
+76
+146
+111
+88
+238
+159
+107
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+159
+103
+251
+168
+115
+248
+180
+134
+239
+182
+144
+186
+157
+134
+124
+111
+99
+82
+69
+65
+65
+58
+56
+55
+48
+48
+65
+58
+56
+65
+58
+56
+65
+58
+56
+99
+90
+79
+158
+130
+108
+230
+173
+136
+250
+176
+132
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+214
+151
+109
+74
+68
+68
+56
+64
+60
+95
+87
+59
+88
+82
+59
+56
+64
+60
+81
+77
+76
+238
+159
+107
+249
+152
+92
+248
+138
+64
+247
+130
+53
+246
+116
+28
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+187
+140
+108
+51
+62
+63
+69
+69
+61
+95
+87
+59
+83
+78
+61
+48
+58
+59
+121
+100
+85
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+123
+41
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+247
+165
+111
+139
+115
+96
+48
+58
+59
+95
+78
+64
+118
+86
+65
+81
+73
+62
+48
+58
+59
+162
+125
+96
+249
+159
+103
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+187
+140
+108
+48
+58
+59
+76
+70
+64
+118
+86
+65
+95
+78
+64
+51
+62
+63
+121
+100
+85
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+152
+92
+247
+165
+111
+250
+176
+132
+251
+192
+154
+167
+142
+123
+65
+58
+56
+35
+31
+30
+71
+60
+43
+108
+87
+46
+129
+106
+52
+137
+110
+49
+156
+125
+62
+187
+166
+150
+129
+106
+52
+101
+83
+47
+59
+50
+39
+55
+48
+48
+139
+115
+96
+240
+181
+138
+249
+174
+124
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+247
+165
+111
+124
+111
+99
+56
+64
+60
+137
+110
+49
+171
+129
+45
+171
+129
+45
+129
+106
+52
+51
+62
+63
+162
+125
+96
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+245
+169
+119
+81
+77
+76
+69
+69
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+105
+93
+60
+48
+58
+59
+187
+140
+108
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+250
+139
+73
+249
+159
+103
+210
+156
+119
+51
+62
+63
+112
+85
+63
+234
+126
+45
+234
+126
+45
+225
+124
+48
+95
+78
+64
+63
+74
+74
+234
+168
+124
+246
+156
+93
+250
+139
+73
+247
+123
+41
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+245
+169
+119
+81
+77
+76
+81
+73
+62
+212
+120
+56
+234
+126
+45
+234
+126
+45
+135
+94
+64
+41
+58
+57
+187
+140
+108
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+249
+174
+124
+249
+189
+146
+236
+186
+153
+99
+90
+79
+47
+40
+38
+85
+71
+43
+145
+114
+49
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+160
+120
+43
+195
+167
+113
+216
+194
+154
+168
+127
+42
+168
+127
+42
+123
+102
+54
+59
+50
+39
+82
+69
+65
+230
+173
+136
+249
+174
+124
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+246
+156
+93
+245
+169
+119
+84
+85
+82
+83
+78
+61
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+101
+100
+92
+249
+174
+124
+246
+156
+93
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+210
+156
+119
+48
+58
+59
+105
+93
+60
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+62
+63
+61
+139
+115
+96
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+247
+165
+111
+158
+130
+108
+51
+62
+63
+188
+112
+56
+234
+125
+52
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+210
+156
+119
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+247
+165
+111
+210
+156
+119
+55
+66
+67
+146
+97
+64
+234
+126
+45
+224
+123
+55
+234
+125
+52
+199
+115
+54
+62
+63
+61
+139
+115
+96
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+250
+176
+132
+219
+170
+138
+150
+125
+114
+65
+58
+56
+24
+22
+23
+59
+50
+39
+152
+119
+47
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+158
+125
+46
+227
+196
+175
+192
+155
+91
+160
+120
+43
+171
+129
+45
+158
+125
+46
+85
+71
+43
+65
+58
+56
+219
+170
+138
+249
+174
+124
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+230
+173
+136
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+252
+185
+144
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+203
+161
+131
+43
+57
+62
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+133
+120
+107
+250
+176
+132
+246
+156
+93
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+154
+133
+118
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+186
+157
+134
+250
+176
+132
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+249
+174
+124
+209
+171
+139
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+133
+120
+107
+249
+174
+124
+246
+156
+93
+248
+138
+64
+247
+123
+41
+247
+111
+26
+246
+109
+10
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+158
+130
+108
+47
+40
+38
+59
+50
+39
+85
+71
+43
+85
+71
+43
+59
+50
+39
+35
+31
+30
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+192
+155
+91
+224
+207
+180
+158
+125
+46
+160
+120
+43
+168
+127
+42
+171
+129
+45
+71
+60
+43
+82
+69
+65
+239
+182
+144
+249
+174
+124
+249
+152
+92
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+247
+165
+111
+239
+182
+144
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+250
+197
+158
+250
+176
+132
+249
+159
+103
+247
+143
+74
+247
+130
+60
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+248
+180
+134
+212
+173
+150
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+248
+180
+134
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+249
+159
+103
+250
+176
+132
+167
+142
+123
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+249
+189
+146
+251
+168
+115
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+150
+84
+247
+165
+111
+252
+185
+144
+212
+173
+150
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+133
+120
+107
+248
+180
+134
+249
+159
+103
+250
+139
+73
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+249
+159
+103
+250
+176
+132
+167
+142
+123
+24
+22
+23
+85
+71
+43
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+85
+71
+43
+35
+31
+30
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+216
+194
+154
+195
+167
+113
+152
+119
+47
+158
+125
+46
+168
+127
+42
+158
+125
+46
+59
+50
+39
+139
+115
+96
+252
+185
+144
+247
+165
+111
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+251
+168
+115
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+251
+209
+178
+249
+189
+146
+249
+174
+124
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+248
+138
+64
+247
+143
+74
+246
+156
+93
+249
+174
+124
+251
+192
+154
+207
+178
+158
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+159
+103
+252
+185
+144
+167
+142
+123
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+51
+62
+63
+187
+166
+150
+250
+200
+166
+248
+180
+134
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+249
+152
+92
+247
+165
+111
+248
+180
+134
+250
+197
+158
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+252
+185
+144
+249
+159
+103
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+247
+150
+84
+251
+168
+115
+230
+173
+136
+47
+40
+38
+59
+50
+39
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+171
+129
+45
+59
+50
+39
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+170
+137
+67
+239
+227
+208
+170
+137
+67
+160
+120
+43
+158
+125
+46
+171
+129
+45
+123
+102
+54
+47
+40
+38
+209
+171
+139
+248
+180
+134
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+249
+174
+124
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+253
+204
+176
+249
+189
+146
+249
+174
+124
+247
+165
+111
+246
+156
+93
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+249
+146
+83
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+174
+124
+252
+185
+144
+250
+200
+166
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+251
+192
+154
+249
+174
+124
+246
+156
+93
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+249
+146
+83
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+150
+84
+251
+168
+115
+249
+189
+146
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+253
+212
+188
+250
+197
+158
+248
+180
+134
+251
+168
+115
+249
+159
+103
+247
+150
+84
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+247
+150
+84
+249
+146
+83
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+60
+248
+138
+64
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+250
+139
+73
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+250
+139
+73
+250
+139
+73
+250
+139
+73
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+150
+84
+249
+159
+103
+251
+168
+115
+248
+180
+134
+250
+197
+158
+253
+212
+188
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+247
+150
+84
+249
+146
+83
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+248
+138
+64
+248
+138
+64
+250
+139
+73
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+139
+115
+96
+35
+31
+30
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+35
+31
+30
+152
+119
+47
+168
+127
+42
+168
+127
+42
+160
+120
+43
+168
+127
+42
+171
+129
+45
+152
+119
+47
+216
+194
+154
+224
+207
+180
+160
+120
+43
+160
+120
+43
+137
+110
+49
+102
+91
+75
+35
+31
+30
+115
+102
+92
+250
+200
+166
+250
+176
+132
+249
+159
+103
+249
+146
+83
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+253
+204
+176
+250
+197
+158
+252
+185
+144
+249
+174
+124
+251
+168
+115
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+60
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+247
+165
+111
+251
+168
+115
+250
+176
+132
+252
+185
+144
+250
+200
+166
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+250
+200
+166
+250
+176
+132
+247
+165
+111
+249
+152
+92
+247
+150
+84
+249
+146
+83
+247
+150
+84
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+246
+156
+93
+247
+150
+84
+247
+143
+74
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+159
+103
+249
+174
+124
+251
+192
+154
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+187
+166
+150
+255
+215
+190
+253
+212
+188
+250
+200
+166
+249
+189
+146
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+246
+156
+93
+246
+156
+93
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+152
+92
+249
+152
+92
+247
+150
+84
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+150
+84
+249
+152
+92
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+250
+176
+132
+249
+189
+146
+250
+200
+166
+253
+212
+188
+255
+215
+190
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+249
+152
+92
+249
+146
+83
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+248
+138
+64
+247
+143
+74
+249
+146
+83
+249
+152
+92
+246
+156
+93
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+249
+152
+92
+247
+150
+84
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+249
+146
+83
+247
+150
+84
+246
+156
+93
+249
+159
+103
+247
+165
+111
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+236
+186
+153
+47
+40
+38
+59
+50
+39
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+47
+40
+38
+108
+87
+46
+168
+127
+42
+111
+94
+57
+76
+70
+64
+59
+50
+39
+101
+83
+47
+160
+120
+43
+170
+137
+67
+253
+255
+252
+195
+167
+113
+145
+114
+49
+69
+69
+61
+120
+114
+108
+35
+31
+30
+47
+40
+38
+217
+187
+166
+250
+197
+158
+250
+176
+132
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+250
+139
+73
+246
+156
+93
+250
+176
+132
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+245
+212
+186
+227
+196
+175
+212
+173
+150
+209
+171
+139
+219
+170
+138
+240
+181
+138
+250
+176
+132
+251
+168
+115
+249
+159
+103
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+248
+138
+64
+249
+146
+83
+246
+156
+93
+247
+165
+111
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+250
+176
+132
+249
+174
+124
+249
+159
+103
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+248
+138
+64
+249
+146
+83
+246
+156
+93
+247
+165
+111
+249
+174
+124
+245
+179
+138
+230
+173
+136
+203
+161
+131
+203
+161
+131
+219
+170
+138
+239
+182
+144
+251
+192
+154
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+245
+169
+119
+234
+168
+124
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+150
+84
+247
+150
+84
+247
+150
+84
+249
+152
+92
+249
+159
+103
+247
+165
+111
+249
+174
+124
+248
+180
+134
+230
+173
+136
+219
+170
+138
+203
+161
+131
+209
+171
+139
+239
+182
+144
+251
+192
+154
+249
+189
+146
+249
+189
+146
+252
+185
+144
+252
+185
+144
+249
+189
+146
+236
+186
+153
+250
+200
+166
+255
+215
+190
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+253
+204
+176
+252
+185
+144
+249
+174
+124
+247
+165
+111
+247
+165
+111
+247
+165
+111
+251
+168
+115
+249
+174
+124
+248
+180
+134
+230
+173
+136
+219
+170
+138
+203
+161
+131
+209
+171
+139
+230
+173
+136
+245
+179
+138
+250
+176
+132
+251
+168
+115
+249
+159
+103
+249
+159
+103
+246
+156
+93
+249
+159
+103
+251
+168
+115
+248
+180
+134
+250
+197
+158
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+187
+166
+150
+255
+215
+190
+255
+215
+190
+234
+204
+183
+207
+178
+158
+209
+171
+139
+209
+171
+139
+230
+173
+136
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+247
+165
+111
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+174
+124
+250
+176
+132
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+230
+173
+136
+251
+192
+154
+249
+189
+146
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+250
+176
+132
+248
+180
+134
+250
+176
+132
+250
+176
+132
+250
+176
+132
+248
+180
+134
+248
+180
+134
+230
+173
+136
+240
+181
+138
+252
+185
+144
+252
+185
+144
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+234
+168
+124
+249
+174
+124
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+251
+168
+115
+249
+174
+124
+250
+176
+132
+248
+180
+134
+230
+173
+136
+219
+170
+138
+209
+171
+139
+207
+178
+158
+227
+196
+175
+253
+212
+188
+255
+215
+190
+217
+187
+166
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+247
+150
+84
+249
+146
+83
+247
+143
+74
+247
+143
+74
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+234
+168
+124
+234
+168
+124
+248
+180
+134
+252
+185
+144
+252
+185
+144
+252
+185
+144
+248
+180
+134
+250
+176
+132
+234
+168
+124
+249
+174
+124
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+247
+165
+111
+251
+168
+115
+249
+174
+124
+250
+176
+132
+248
+180
+134
+230
+173
+136
+203
+161
+131
+203
+161
+131
+219
+170
+138
+239
+182
+144
+251
+192
+154
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+238
+159
+107
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+247
+143
+74
+247
+165
+111
+252
+185
+144
+154
+133
+118
+24
+22
+23
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+85
+71
+43
+101
+83
+47
+89
+84
+82
+152
+147
+147
+24
+22
+23
+24
+22
+23
+108
+87
+46
+168
+127
+42
+224
+207
+180
+253
+255
+252
+209
+171
+139
+101
+83
+47
+24
+22
+23
+35
+31
+30
+35
+31
+30
+167
+142
+123
+253
+212
+188
+250
+197
+158
+248
+180
+134
+247
+165
+111
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+60
+248
+138
+64
+249
+146
+83
+249
+159
+103
+250
+176
+132
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+217
+187
+166
+137
+127
+115
+91
+92
+89
+55
+66
+67
+48
+58
+59
+48
+58
+59
+55
+66
+67
+84
+85
+82
+133
+120
+107
+209
+171
+139
+248
+180
+134
+251
+168
+115
+249
+159
+103
+247
+150
+84
+247
+143
+74
+250
+139
+73
+250
+139
+73
+249
+146
+83
+249
+152
+92
+247
+165
+111
+249
+174
+124
+245
+179
+138
+178
+146
+122
+124
+111
+99
+76
+78
+76
+51
+62
+63
+48
+58
+59
+48
+58
+59
+58
+69
+70
+91
+92
+89
+144
+125
+110
+203
+161
+131
+248
+180
+134
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+248
+138
+64
+250
+139
+73
+249
+146
+83
+246
+156
+93
+247
+165
+111
+250
+176
+132
+230
+173
+136
+154
+133
+118
+101
+100
+92
+58
+69
+70
+48
+58
+59
+48
+58
+59
+51
+62
+63
+84
+85
+82
+137
+127
+115
+217
+187
+166
+253
+212
+188
+227
+196
+175
+144
+125
+110
+89
+84
+82
+81
+77
+76
+115
+102
+92
+210
+156
+119
+249
+174
+124
+251
+168
+115
+251
+168
+115
+251
+168
+115
+249
+174
+124
+250
+176
+132
+252
+185
+144
+195
+157
+134
+124
+111
+99
+76
+78
+76
+51
+62
+63
+48
+58
+59
+48
+58
+59
+70
+79
+77
+120
+114
+108
+187
+166
+150
+253
+212
+188
+253
+212
+188
+172
+150
+134
+101
+100
+92
+77
+85
+81
+101
+100
+92
+176
+156
+141
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+253
+212
+188
+250
+197
+158
+252
+185
+144
+248
+180
+134
+248
+180
+134
+252
+185
+144
+239
+182
+144
+167
+142
+123
+109
+106
+99
+70
+79
+77
+48
+58
+59
+48
+58
+59
+48
+58
+59
+58
+69
+70
+91
+92
+89
+150
+125
+114
+219
+170
+138
+248
+180
+134
+249
+174
+124
+249
+174
+124
+249
+174
+124
+250
+176
+132
+249
+189
+146
+253
+204
+176
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+176
+156
+141
+187
+166
+150
+109
+106
+99
+63
+74
+74
+43
+57
+62
+43
+57
+62
+43
+57
+62
+63
+74
+74
+109
+106
+99
+178
+146
+122
+245
+179
+138
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+248
+138
+64
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+174
+124
+252
+185
+144
+195
+157
+134
+124
+111
+99
+77
+85
+81
+51
+62
+63
+41
+58
+57
+43
+57
+62
+51
+62
+63
+77
+85
+81
+124
+111
+99
+195
+157
+134
+252
+185
+144
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+150
+84
+249
+159
+103
+251
+168
+115
+248
+180
+134
+203
+161
+131
+124
+111
+99
+77
+85
+81
+48
+58
+59
+43
+57
+62
+43
+57
+62
+63
+74
+74
+109
+106
+99
+187
+166
+150
+253
+212
+188
+253
+212
+188
+187
+166
+150
+109
+106
+99
+77
+85
+81
+84
+85
+82
+150
+125
+114
+232
+190
+161
+253
+204
+176
+253
+204
+176
+172
+150
+134
+101
+100
+92
+77
+85
+81
+91
+92
+89
+137
+127
+115
+227
+196
+175
+253
+212
+188
+186
+157
+134
+109
+106
+99
+77
+85
+81
+84
+85
+82
+124
+111
+99
+219
+170
+138
+249
+189
+146
+249
+189
+146
+249
+189
+146
+251
+192
+154
+250
+197
+158
+186
+157
+134
+109
+106
+99
+70
+79
+77
+43
+57
+62
+43
+57
+62
+41
+58
+57
+63
+74
+74
+101
+100
+92
+176
+156
+141
+194
+173
+157
+55
+66
+67
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+249
+174
+124
+252
+185
+144
+203
+161
+131
+133
+120
+107
+84
+85
+82
+55
+66
+67
+43
+57
+62
+41
+58
+57
+51
+62
+63
+77
+85
+81
+124
+111
+99
+178
+146
+122
+239
+182
+144
+250
+176
+132
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+210
+156
+119
+124
+111
+99
+77
+85
+81
+77
+85
+81
+109
+106
+99
+194
+173
+157
+253
+212
+188
+217
+187
+166
+133
+120
+107
+89
+84
+82
+76
+78
+76
+101
+100
+92
+178
+146
+122
+249
+189
+146
+252
+185
+144
+252
+185
+144
+252
+185
+144
+251
+192
+154
+236
+186
+153
+167
+142
+123
+101
+100
+92
+63
+74
+74
+41
+58
+57
+43
+57
+62
+51
+62
+63
+77
+85
+81
+137
+127
+115
+217
+187
+166
+253
+212
+188
+227
+196
+175
+144
+125
+110
+84
+85
+82
+76
+78
+76
+115
+102
+92
+204
+141
+99
+249
+159
+103
+247
+143
+74
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+250
+197
+158
+82
+69
+65
+47
+40
+38
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+101
+83
+47
+59
+50
+39
+101
+83
+47
+24
+22
+23
+35
+31
+30
+24
+22
+23
+24
+22
+23
+108
+87
+46
+168
+127
+42
+195
+167
+113
+253
+255
+252
+253
+255
+252
+239
+227
+208
+186
+157
+134
+162
+125
+96
+105
+93
+60
+47
+40
+38
+150
+125
+114
+217
+187
+166
+250
+200
+166
+252
+185
+144
+251
+168
+115
+246
+156
+93
+249
+146
+83
+247
+143
+74
+249
+146
+83
+249
+152
+92
+247
+165
+111
+252
+185
+144
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+58
+69
+70
+56
+64
+60
+83
+78
+61
+105
+93
+60
+117
+98
+55
+117
+98
+55
+105
+93
+60
+83
+78
+61
+56
+64
+60
+55
+66
+67
+144
+125
+110
+239
+182
+144
+250
+176
+132
+247
+165
+111
+249
+159
+103
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+252
+185
+144
+195
+157
+134
+89
+84
+82
+48
+58
+59
+63
+69
+60
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+105
+93
+60
+83
+78
+61
+56
+64
+60
+51
+62
+63
+124
+111
+99
+219
+170
+138
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+249
+152
+92
+246
+156
+93
+247
+165
+111
+249
+174
+124
+252
+185
+144
+167
+142
+123
+70
+79
+77
+51
+62
+63
+75
+74
+61
+100
+89
+56
+117
+98
+55
+123
+102
+54
+105
+93
+60
+83
+78
+61
+51
+62
+63
+63
+74
+74
+172
+150
+134
+109
+106
+99
+51
+62
+63
+83
+78
+61
+95
+87
+59
+65
+67
+64
+65
+67
+64
+209
+171
+139
+249
+189
+146
+249
+189
+146
+249
+189
+146
+250
+197
+158
+212
+173
+150
+109
+106
+99
+48
+58
+59
+63
+69
+60
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+95
+87
+59
+62
+63
+61
+48
+58
+59
+137
+127
+115
+146
+135
+124
+48
+58
+59
+75
+74
+61
+95
+87
+59
+75
+74
+61
+48
+58
+59
+161
+144
+134
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+250
+200
+166
+172
+150
+134
+77
+85
+81
+48
+58
+59
+69
+69
+61
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+100
+89
+56
+75
+74
+61
+56
+64
+60
+55
+66
+67
+133
+120
+107
+236
+186
+153
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+253
+212
+188
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+63
+74
+74
+48
+58
+59
+76
+70
+64
+118
+86
+65
+146
+97
+64
+155
+100
+63
+146
+97
+64
+118
+86
+65
+76
+70
+64
+43
+57
+62
+91
+92
+89
+203
+161
+131
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+247
+150
+84
+249
+152
+92
+249
+159
+103
+251
+168
+115
+248
+180
+134
+209
+171
+139
+101
+100
+92
+43
+57
+62
+69
+69
+61
+106
+82
+65
+135
+94
+64
+155
+100
+63
+155
+100
+63
+135
+94
+64
+106
+82
+65
+65
+67
+64
+43
+57
+62
+101
+100
+92
+209
+171
+139
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+247
+150
+84
+247
+150
+84
+246
+156
+93
+247
+165
+111
+250
+176
+132
+219
+170
+138
+124
+111
+99
+48
+58
+59
+62
+63
+61
+106
+82
+65
+139
+96
+61
+155
+100
+63
+146
+97
+64
+125
+90
+64
+76
+70
+64
+41
+58
+57
+120
+114
+108
+172
+150
+134
+51
+62
+63
+69
+69
+61
+112
+85
+63
+95
+78
+64
+51
+62
+63
+120
+114
+108
+245
+212
+186
+146
+135
+124
+43
+57
+62
+81
+73
+62
+118
+86
+65
+95
+78
+64
+56
+64
+60
+101
+100
+92
+133
+120
+107
+43
+57
+62
+76
+70
+64
+112
+85
+63
+106
+82
+65
+62
+63
+61
+77
+85
+81
+227
+196
+175
+253
+212
+188
+253
+212
+188
+217
+187
+166
+109
+106
+99
+41
+58
+57
+69
+69
+61
+112
+85
+63
+139
+96
+61
+155
+100
+63
+146
+97
+64
+118
+86
+65
+81
+73
+62
+48
+58
+59
+58
+69
+70
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+250
+176
+132
+219
+170
+138
+124
+111
+99
+43
+57
+62
+62
+63
+61
+106
+82
+65
+135
+94
+64
+155
+100
+63
+155
+100
+63
+139
+96
+61
+106
+82
+65
+69
+69
+61
+43
+57
+62
+91
+92
+89
+195
+157
+134
+251
+192
+154
+252
+185
+144
+248
+180
+134
+248
+180
+134
+252
+185
+144
+203
+161
+131
+63
+74
+74
+62
+63
+61
+106
+82
+65
+112
+85
+63
+69
+69
+61
+55
+66
+67
+146
+135
+124
+63
+74
+74
+56
+64
+60
+95
+78
+64
+112
+85
+63
+76
+70
+64
+48
+58
+59
+172
+150
+134
+253
+204
+176
+251
+209
+178
+251
+209
+178
+187
+166
+150
+77
+85
+81
+48
+58
+59
+81
+73
+62
+125
+90
+64
+146
+97
+64
+155
+100
+63
+139
+96
+61
+95
+78
+64
+56
+64
+60
+58
+69
+70
+161
+144
+134
+109
+106
+99
+51
+62
+63
+95
+78
+64
+112
+85
+63
+65
+67
+64
+65
+67
+64
+204
+141
+99
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+209
+171
+139
+24
+22
+23
+85
+71
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+47
+40
+38
+137
+110
+49
+101
+83
+47
+59
+50
+39
+59
+50
+39
+101
+83
+47
+158
+125
+46
+160
+120
+43
+192
+155
+91
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+152
+147
+147
+81
+77
+76
+55
+48
+48
+115
+102
+92
+212
+173
+150
+251
+192
+154
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+249
+189
+146
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+43
+57
+62
+95
+87
+59
+145
+114
+49
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+145
+114
+49
+95
+87
+59
+48
+58
+59
+109
+106
+99
+236
+186
+153
+252
+185
+144
+248
+180
+134
+250
+176
+132
+250
+176
+132
+252
+185
+144
+251
+192
+154
+150
+125
+114
+48
+58
+59
+69
+69
+61
+117
+98
+55
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+152
+119
+47
+100
+89
+56
+56
+64
+60
+63
+74
+74
+186
+157
+134
+249
+189
+146
+248
+180
+134
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+251
+192
+154
+133
+120
+107
+48
+58
+59
+75
+74
+61
+137
+110
+49
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+145
+114
+49
+75
+74
+61
+43
+57
+62
+51
+62
+63
+123
+102
+54
+171
+129
+45
+171
+129
+45
+145
+114
+49
+56
+64
+60
+133
+120
+107
+253
+212
+188
+251
+209
+178
+253
+212
+188
+194
+173
+157
+63
+74
+74
+56
+64
+60
+111
+94
+57
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+158
+125
+46
+105
+93
+60
+51
+62
+63
+43
+57
+62
+88
+82
+59
+168
+127
+42
+171
+129
+45
+168
+127
+42
+88
+82
+59
+63
+74
+74
+187
+166
+150
+55
+66
+67
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+133
+120
+107
+48
+58
+59
+75
+74
+61
+129
+106
+52
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+171
+129
+45
+168
+127
+42
+145
+114
+49
+95
+87
+59
+51
+62
+63
+77
+85
+81
+212
+173
+150
+253
+204
+176
+253
+204
+176
+251
+209
+178
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+41
+58
+57
+69
+69
+61
+155
+100
+63
+214
+121
+50
+234
+126
+45
+234
+126
+45
+234
+126
+45
+234
+126
+45
+234
+126
+45
+224
+123
+55
+155
+100
+63
+69
+69
+61
+51
+62
+63
+178
+146
+122
+249
+189
+146
+250
+176
+132
+251
+168
+115
+251
+168
+115
+249
+174
+124
+250
+176
+132
+249
+189
+146
+167
+142
+123
+55
+66
+67
+65
+67
+64
+146
+97
+64
+212
+120
+56
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+125
+52
+209
+117
+53
+146
+97
+64
+65
+67
+64
+55
+66
+67
+178
+146
+122
+249
+189
+146
+250
+176
+132
+251
+168
+115
+247
+165
+111
+251
+168
+115
+249
+174
+124
+252
+185
+144
+203
+161
+131
+63
+74
+74
+56
+64
+60
+125
+90
+64
+209
+117
+53
+234
+126
+45
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+126
+45
+214
+121
+50
+146
+97
+64
+56
+64
+60
+41
+58
+57
+81
+73
+62
+209
+117
+53
+234
+126
+45
+234
+126
+45
+125
+90
+64
+51
+62
+63
+176
+156
+141
+55
+66
+67
+106
+82
+65
+225
+124
+48
+234
+126
+45
+234
+126
+45
+146
+97
+64
+41
+58
+57
+43
+57
+62
+125
+90
+64
+214
+121
+50
+234
+126
+45
+234
+126
+45
+183
+110
+59
+56
+64
+60
+137
+127
+115
+255
+215
+190
+194
+173
+157
+63
+74
+74
+62
+63
+61
+146
+97
+64
+214
+121
+50
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+125
+52
+234
+126
+45
+225
+124
+48
+173
+106
+60
+81
+73
+62
+35
+56
+60
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+247
+165
+111
+248
+180
+134
+186
+157
+134
+58
+69
+70
+56
+64
+60
+135
+94
+64
+199
+115
+54
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+125
+52
+234
+126
+45
+234
+125
+52
+212
+120
+56
+155
+100
+63
+76
+70
+64
+51
+62
+63
+146
+135
+124
+251
+209
+178
+253
+204
+176
+250
+200
+166
+253
+204
+176
+101
+100
+92
+69
+69
+61
+194
+112
+58
+234
+126
+45
+234
+126
+45
+199
+115
+54
+65
+67
+64
+35
+56
+60
+81
+73
+62
+194
+112
+58
+234
+125
+52
+234
+126
+45
+214
+121
+50
+95
+78
+64
+63
+74
+74
+238
+205
+179
+255
+215
+190
+161
+144
+134
+43
+57
+62
+81
+73
+62
+173
+106
+60
+225
+124
+48
+234
+126
+45
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+126
+45
+194
+112
+58
+95
+78
+64
+41
+58
+57
+48
+58
+59
+155
+100
+63
+234
+126
+45
+234
+126
+45
+199
+115
+54
+69
+69
+61
+99
+90
+79
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+249
+174
+124
+251
+192
+154
+124
+111
+99
+35
+31
+30
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+47
+40
+38
+108
+87
+46
+175
+132
+40
+161
+127
+40
+168
+127
+42
+171
+129
+45
+158
+125
+46
+152
+119
+47
+203
+161
+131
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+89
+84
+82
+47
+40
+38
+139
+115
+96
+236
+186
+153
+252
+185
+144
+250
+176
+132
+249
+174
+124
+250
+176
+132
+252
+185
+144
+250
+197
+158
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+111
+94
+57
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+111
+94
+57
+48
+58
+59
+109
+106
+99
+253
+204
+176
+250
+200
+166
+250
+200
+166
+250
+200
+166
+253
+204
+176
+137
+127
+115
+43
+57
+62
+88
+82
+59
+158
+125
+46
+171
+129
+45
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+145
+114
+49
+69
+69
+61
+51
+62
+63
+187
+166
+150
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+253
+204
+176
+133
+120
+107
+48
+58
+59
+95
+87
+59
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+158
+125
+46
+75
+74
+61
+62
+63
+61
+168
+127
+42
+161
+127
+40
+158
+125
+46
+171
+129
+45
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+207
+178
+158
+58
+69
+70
+63
+69
+60
+145
+114
+49
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+105
+93
+60
+43
+57
+62
+137
+110
+49
+171
+129
+45
+158
+125
+46
+171
+129
+45
+137
+110
+49
+51
+62
+63
+146
+135
+124
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+65
+67
+64
+137
+127
+115
+255
+215
+190
+255
+215
+190
+245
+212
+186
+120
+114
+108
+48
+58
+59
+100
+89
+56
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+129
+106
+52
+61
+67
+58
+63
+74
+74
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+95
+78
+64
+209
+117
+53
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+209
+117
+53
+89
+75
+66
+51
+62
+63
+187
+166
+150
+250
+197
+158
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+161
+144
+134
+41
+58
+57
+95
+78
+64
+199
+115
+54
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+199
+115
+54
+89
+75
+66
+41
+58
+57
+167
+142
+123
+250
+200
+166
+251
+192
+154
+252
+185
+144
+249
+189
+146
+250
+197
+158
+212
+173
+150
+63
+74
+74
+69
+69
+61
+183
+110
+59
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+163
+104
+61
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+234
+125
+52
+188
+112
+56
+51
+62
+63
+109
+106
+99
+51
+62
+63
+188
+112
+56
+234
+126
+45
+224
+123
+55
+234
+125
+52
+188
+112
+56
+43
+57
+62
+112
+85
+63
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+95
+78
+64
+109
+106
+99
+217
+187
+166
+58
+69
+70
+69
+69
+61
+188
+112
+56
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+214
+121
+50
+95
+78
+64
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+186
+157
+134
+51
+62
+63
+81
+73
+62
+188
+112
+56
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+212
+120
+56
+106
+82
+65
+41
+58
+57
+146
+135
+124
+255
+215
+190
+255
+215
+190
+234
+204
+183
+63
+74
+74
+125
+90
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+234
+125
+52
+89
+75
+66
+62
+63
+61
+199
+115
+54
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+217
+187
+166
+172
+150
+134
+41
+58
+57
+106
+82
+65
+214
+121
+50
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+69
+69
+61
+227
+126
+50
+227
+126
+50
+224
+123
+55
+238
+123
+45
+125
+90
+64
+55
+66
+67
+250
+176
+132
+246
+156
+93
+250
+139
+73
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+248
+180
+134
+232
+190
+161
+47
+40
+38
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+170
+137
+67
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+74
+68
+68
+89
+75
+66
+212
+173
+150
+250
+197
+158
+251
+192
+154
+249
+189
+146
+251
+192
+154
+253
+204
+176
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+111
+94
+57
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+48
+58
+59
+95
+87
+59
+168
+127
+42
+168
+127
+42
+158
+125
+46
+161
+127
+40
+171
+129
+45
+158
+125
+46
+152
+119
+47
+152
+119
+47
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+69
+69
+61
+58
+69
+70
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+43
+57
+62
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+158
+125
+46
+168
+127
+42
+137
+110
+49
+83
+78
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+238
+205
+179
+84
+85
+82
+62
+63
+61
+145
+114
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+161
+127
+40
+158
+125
+46
+88
+82
+59
+152
+119
+47
+161
+127
+40
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+63
+69
+60
+137
+127
+115
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+105
+93
+60
+171
+129
+45
+161
+127
+40
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+152
+119
+47
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+145
+114
+49
+62
+63
+61
+70
+79
+77
+227
+196
+175
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+234
+126
+45
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+76
+70
+64
+70
+79
+77
+234
+204
+183
+253
+212
+188
+251
+209
+178
+253
+212
+188
+187
+166
+150
+43
+57
+62
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+95
+78
+64
+48
+58
+59
+194
+173
+157
+253
+212
+188
+251
+209
+178
+251
+209
+178
+245
+212
+186
+91
+92
+89
+62
+63
+61
+188
+112
+56
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+126
+45
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+212
+120
+56
+183
+110
+59
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+95
+78
+64
+84
+85
+82
+91
+92
+89
+62
+63
+61
+188
+112
+56
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+152
+92
+249
+174
+124
+209
+171
+139
+58
+69
+70
+81
+73
+62
+209
+117
+53
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+112
+85
+63
+41
+58
+57
+172
+150
+134
+255
+215
+190
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+194
+112
+58
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+238
+128
+40
+163
+104
+61
+55
+66
+67
+161
+144
+134
+58
+69
+70
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+126
+45
+234
+125
+52
+227
+126
+50
+234
+125
+52
+173
+106
+60
+118
+86
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+146
+97
+64
+51
+62
+63
+252
+185
+144
+249
+159
+103
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+251
+168
+115
+251
+192
+154
+154
+133
+118
+24
+22
+23
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+108
+87
+46
+47
+40
+38
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+156
+125
+62
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+152
+147
+147
+35
+31
+30
+55
+48
+48
+154
+133
+118
+217
+187
+166
+253
+204
+176
+253
+204
+176
+253
+212
+188
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+168
+127
+42
+158
+125
+46
+123
+102
+54
+105
+93
+60
+111
+94
+57
+129
+106
+52
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+83
+78
+61
+58
+69
+70
+227
+196
+175
+255
+215
+190
+217
+187
+166
+58
+69
+70
+75
+74
+61
+168
+127
+42
+161
+127
+40
+158
+125
+46
+168
+127
+42
+152
+119
+47
+105
+93
+60
+69
+69
+61
+62
+63
+61
+62
+63
+61
+75
+74
+61
+117
+98
+55
+161
+127
+40
+161
+127
+40
+158
+125
+46
+171
+129
+45
+145
+114
+49
+56
+64
+60
+97
+98
+96
+245
+212
+186
+255
+215
+190
+227
+196
+175
+63
+74
+74
+75
+74
+61
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+129
+106
+52
+111
+94
+57
+105
+93
+60
+129
+106
+52
+158
+125
+46
+168
+127
+42
+161
+127
+40
+152
+119
+47
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+84
+85
+82
+255
+215
+190
+161
+144
+134
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+117
+98
+55
+105
+93
+60
+117
+98
+55
+145
+114
+49
+171
+129
+45
+168
+127
+42
+152
+119
+47
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+194
+173
+157
+48
+58
+59
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+95
+87
+59
+69
+69
+61
+62
+63
+61
+62
+63
+61
+83
+78
+61
+123
+102
+54
+168
+127
+42
+161
+127
+40
+158
+125
+46
+171
+129
+45
+129
+106
+52
+51
+62
+63
+120
+114
+108
+255
+215
+190
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+188
+112
+56
+146
+97
+64
+135
+94
+64
+146
+97
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+173
+106
+60
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+76
+70
+64
+214
+121
+50
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+163
+104
+61
+135
+94
+64
+135
+94
+64
+163
+104
+61
+224
+123
+55
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+212
+120
+56
+76
+70
+64
+77
+85
+81
+238
+205
+179
+255
+215
+190
+255
+215
+190
+161
+144
+134
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+199
+115
+54
+155
+100
+63
+135
+94
+64
+146
+97
+64
+188
+112
+56
+227
+126
+50
+227
+126
+50
+214
+121
+50
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+199
+115
+54
+125
+90
+64
+51
+62
+63
+55
+66
+67
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+209
+117
+53
+155
+100
+63
+135
+94
+64
+139
+96
+61
+183
+110
+59
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+60
+249
+146
+83
+247
+165
+111
+252
+185
+144
+101
+100
+92
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+173
+106
+60
+135
+94
+64
+135
+94
+64
+163
+104
+61
+214
+121
+50
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+81
+73
+62
+58
+69
+70
+227
+196
+175
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+125
+52
+212
+120
+56
+155
+100
+63
+69
+69
+61
+76
+78
+76
+84
+85
+82
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+183
+110
+59
+139
+96
+61
+135
+94
+64
+155
+100
+63
+209
+117
+53
+234
+125
+52
+224
+123
+55
+212
+120
+56
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+251
+192
+154
+251
+168
+115
+249
+146
+83
+247
+130
+53
+247
+118
+39
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+250
+176
+132
+232
+190
+161
+65
+58
+56
+59
+50
+39
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+47
+40
+38
+129
+106
+52
+168
+127
+42
+160
+120
+43
+158
+125
+46
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+62
+63
+61
+35
+31
+30
+91
+92
+89
+164
+158
+157
+186
+181
+179
+82
+69
+65
+176
+156
+141
+255
+215
+190
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+65
+67
+64
+48
+58
+59
+55
+66
+67
+55
+66
+67
+48
+58
+59
+83
+78
+61
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+146
+135
+124
+255
+215
+190
+120
+114
+108
+56
+64
+60
+145
+114
+49
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+69
+69
+61
+43
+57
+62
+109
+106
+99
+146
+135
+124
+137
+127
+115
+91
+92
+89
+43
+57
+62
+88
+82
+59
+158
+125
+46
+161
+127
+40
+158
+125
+46
+171
+129
+45
+117
+98
+55
+48
+58
+59
+172
+150
+134
+255
+215
+190
+146
+135
+124
+51
+62
+63
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+75
+74
+61
+48
+58
+59
+55
+66
+67
+55
+66
+67
+48
+58
+59
+69
+69
+61
+137
+110
+49
+168
+127
+42
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+234
+204
+183
+70
+79
+77
+83
+78
+61
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+111
+94
+57
+56
+64
+60
+43
+57
+62
+58
+69
+70
+48
+58
+59
+56
+64
+60
+100
+89
+56
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+255
+215
+190
+97
+98
+96
+62
+63
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+137
+110
+49
+62
+63
+61
+51
+62
+63
+120
+114
+108
+146
+135
+124
+137
+127
+115
+84
+85
+82
+43
+57
+62
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+100
+89
+56
+43
+57
+62
+194
+173
+157
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+118
+86
+65
+51
+62
+63
+43
+57
+62
+58
+69
+70
+41
+58
+57
+56
+64
+60
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+106
+82
+65
+63
+74
+74
+234
+204
+183
+255
+215
+190
+161
+144
+134
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+183
+110
+59
+76
+70
+64
+43
+57
+62
+55
+66
+67
+55
+66
+67
+48
+58
+59
+81
+73
+62
+183
+110
+59
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+161
+144
+134
+255
+215
+190
+234
+204
+183
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+62
+63
+61
+43
+57
+62
+58
+69
+70
+43
+57
+62
+51
+62
+63
+125
+90
+64
+225
+124
+48
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+227
+126
+50
+173
+106
+60
+95
+78
+64
+56
+64
+60
+51
+62
+63
+120
+114
+108
+70
+79
+77
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+65
+67
+64
+41
+58
+57
+55
+66
+67
+51
+62
+63
+48
+58
+59
+106
+82
+65
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+130
+60
+250
+139
+73
+246
+156
+93
+250
+176
+132
+186
+157
+134
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+199
+115
+54
+89
+75
+66
+48
+58
+59
+51
+62
+63
+55
+66
+67
+43
+57
+62
+76
+70
+64
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+137
+127
+115
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+199
+115
+54
+125
+90
+64
+69
+69
+61
+41
+58
+57
+97
+98
+96
+146
+135
+124
+51
+62
+63
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+106
+82
+65
+48
+58
+59
+51
+62
+63
+55
+66
+67
+41
+58
+57
+65
+67
+64
+163
+104
+61
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+197
+158
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+154
+133
+118
+24
+22
+23
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+85
+71
+43
+171
+129
+45
+160
+120
+43
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+65
+58
+56
+62
+63
+61
+219
+212
+208
+253
+255
+252
+237
+233
+225
+120
+114
+108
+35
+31
+30
+55
+48
+48
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+84
+85
+82
+187
+166
+150
+227
+196
+175
+227
+196
+175
+161
+144
+134
+51
+62
+63
+69
+69
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+217
+187
+166
+55
+66
+67
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+58
+69
+70
+187
+166
+150
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+161
+144
+134
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+84
+85
+82
+234
+204
+183
+76
+78
+76
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+62
+63
+61
+63
+74
+74
+176
+156
+141
+227
+196
+175
+227
+196
+175
+176
+156
+141
+70
+79
+77
+62
+63
+61
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+172
+150
+134
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+43
+57
+62
+120
+114
+108
+207
+178
+158
+227
+196
+175
+217
+187
+166
+120
+114
+108
+41
+58
+57
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+146
+135
+124
+207
+178
+158
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+62
+63
+61
+70
+79
+77
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+238
+205
+179
+137
+127
+115
+43
+57
+62
+117
+98
+55
+168
+127
+42
+158
+125
+46
+168
+127
+42
+152
+119
+47
+62
+63
+61
+109
+106
+99
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+41
+58
+57
+137
+127
+115
+217
+187
+166
+227
+196
+175
+207
+178
+158
+109
+106
+99
+41
+58
+57
+146
+97
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+176
+156
+141
+245
+212
+186
+70
+79
+77
+95
+78
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+188
+112
+56
+56
+64
+60
+70
+79
+77
+176
+156
+141
+227
+196
+175
+227
+196
+175
+176
+156
+141
+63
+74
+74
+62
+63
+61
+194
+112
+58
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+77
+85
+81
+245
+212
+186
+172
+150
+134
+48
+58
+59
+173
+106
+60
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+135
+94
+64
+35
+56
+60
+120
+114
+108
+207
+178
+158
+227
+196
+175
+217
+187
+166
+133
+120
+107
+35
+56
+60
+118
+86
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+95
+78
+64
+48
+58
+59
+70
+79
+77
+146
+135
+124
+217
+187
+166
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+91
+92
+89
+194
+173
+157
+227
+196
+175
+217
+187
+166
+146
+135
+124
+43
+57
+62
+89
+75
+66
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+130
+60
+248
+138
+64
+249
+146
+83
+247
+165
+111
+239
+182
+144
+91
+92
+89
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+76
+70
+64
+55
+66
+67
+172
+150
+134
+227
+196
+175
+227
+196
+175
+187
+166
+150
+77
+85
+81
+51
+62
+63
+173
+106
+60
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+118
+86
+65
+58
+69
+70
+217
+187
+166
+70
+79
+77
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+125
+90
+64
+56
+64
+60
+55
+66
+67
+120
+114
+108
+187
+166
+150
+245
+212
+186
+120
+114
+108
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+225
+124
+48
+95
+78
+64
+43
+57
+62
+146
+135
+124
+217
+187
+166
+227
+196
+175
+194
+173
+157
+91
+92
+89
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+197
+158
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+251
+168
+115
+239
+182
+144
+65
+58
+56
+59
+50
+39
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+108
+87
+46
+47
+40
+38
+152
+119
+47
+170
+137
+67
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+174
+168
+167
+24
+22
+23
+109
+106
+99
+152
+147
+147
+97
+98
+96
+47
+40
+38
+24
+22
+23
+35
+31
+30
+35
+31
+30
+176
+156
+141
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+76
+78
+76
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+187
+166
+150
+51
+62
+63
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+55
+66
+67
+109
+106
+99
+48
+58
+59
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+117
+98
+55
+48
+58
+59
+187
+166
+150
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+171
+129
+45
+117
+98
+55
+55
+66
+67
+137
+127
+115
+55
+66
+67
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+58
+69
+70
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+91
+92
+89
+109
+106
+99
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+120
+114
+108
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+146
+135
+124
+146
+135
+124
+62
+63
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+100
+89
+56
+51
+62
+63
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+109
+106
+99
+63
+69
+60
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+100
+89
+56
+51
+62
+63
+227
+196
+175
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+41
+58
+57
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+109
+106
+99
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+76
+70
+64
+109
+106
+99
+194
+173
+157
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+225
+124
+48
+89
+75
+66
+63
+74
+74
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+58
+69
+70
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+43
+57
+62
+207
+178
+158
+109
+106
+99
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+120
+114
+108
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+188
+112
+56
+62
+63
+61
+58
+69
+70
+161
+144
+134
+234
+204
+183
+255
+215
+190
+255
+215
+190
+137
+127
+115
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+69
+69
+61
+77
+85
+81
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+176
+156
+141
+35
+56
+60
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+247
+150
+84
+250
+139
+73
+248
+138
+64
+250
+139
+73
+249
+152
+92
+249
+174
+124
+209
+171
+139
+43
+57
+62
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+112
+85
+63
+51
+62
+63
+194
+173
+157
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+227
+196
+175
+70
+79
+77
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+146
+135
+124
+77
+85
+81
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+95
+78
+64
+35
+56
+60
+120
+114
+108
+217
+187
+166
+255
+215
+190
+255
+215
+190
+227
+196
+175
+58
+69
+70
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+41
+58
+57
+172
+150
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+51
+62
+63
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+178
+146
+122
+24
+22
+23
+101
+83
+47
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+47
+40
+38
+123
+102
+54
+209
+171
+139
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+164
+158
+157
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+47
+40
+38
+194
+173
+157
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+176
+156
+141
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+120
+114
+108
+56
+64
+60
+152
+119
+47
+161
+127
+40
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+48
+58
+59
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+63
+74
+74
+194
+173
+157
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+172
+150
+134
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+51
+62
+63
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+70
+79
+77
+63
+74
+74
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+55
+66
+67
+227
+196
+175
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+234
+204
+183
+70
+79
+77
+88
+82
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+97
+98
+96
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+84
+85
+82
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+217
+187
+166
+146
+135
+124
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+187
+166
+150
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+70
+79
+77
+245
+212
+186
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+217
+187
+166
+43
+57
+62
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+106
+82
+65
+77
+85
+81
+133
+120
+107
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+48
+58
+59
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+77
+85
+81
+118
+86
+65
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+55
+66
+67
+227
+196
+175
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+234
+204
+183
+63
+74
+74
+106
+82
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+89
+75
+66
+63
+74
+74
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+91
+92
+89
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+146
+97
+64
+43
+57
+62
+187
+166
+150
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+101
+100
+92
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+247
+150
+84
+250
+139
+73
+250
+139
+73
+247
+143
+74
+249
+159
+103
+250
+176
+132
+154
+133
+118
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+176
+156
+141
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+91
+92
+89
+70
+79
+77
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+146
+97
+64
+35
+56
+60
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+97
+98
+96
+255
+215
+190
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+187
+166
+150
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+159
+103
+248
+180
+134
+124
+111
+99
+35
+31
+30
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+59
+50
+39
+85
+71
+43
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+207
+202
+200
+47
+40
+38
+24
+22
+23
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+65
+58
+56
+238
+205
+179
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+100
+89
+56
+63
+74
+74
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+194
+173
+157
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+43
+57
+62
+95
+87
+59
+168
+127
+42
+158
+125
+46
+161
+127
+40
+158
+125
+46
+63
+69
+60
+43
+57
+62
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+43
+57
+62
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+43
+57
+62
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+51
+62
+63
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+109
+106
+99
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+120
+114
+108
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+120
+114
+108
+70
+79
+77
+105
+93
+60
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+43
+57
+62
+111
+94
+57
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+62
+63
+61
+146
+135
+124
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+212
+188
+250
+200
+166
+250
+200
+166
+253
+204
+176
+253
+212
+188
+253
+212
+188
+97
+98
+96
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+63
+74
+74
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+135
+94
+64
+55
+66
+67
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+217
+187
+166
+51
+62
+63
+139
+96
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+58
+69
+70
+51
+62
+63
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+224
+123
+55
+81
+73
+62
+109
+106
+99
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+120
+114
+108
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+70
+79
+77
+118
+86
+65
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+77
+85
+81
+245
+212
+186
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+176
+156
+141
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+249
+152
+92
+247
+143
+74
+247
+143
+74
+247
+150
+84
+249
+159
+103
+248
+180
+134
+120
+114
+108
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+43
+57
+62
+194
+173
+157
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+234
+204
+183
+63
+74
+74
+112
+85
+63
+234
+125
+52
+227
+126
+50
+224
+123
+55
+234
+125
+52
+106
+82
+65
+58
+69
+70
+55
+66
+67
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+77
+85
+81
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+172
+150
+134
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+245
+212
+186
+63
+74
+74
+112
+85
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+252
+185
+144
+82
+69
+65
+47
+40
+38
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+85
+71
+43
+59
+50
+39
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+164
+158
+157
+47
+40
+38
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+65
+67
+64
+65
+58
+56
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+227
+196
+175
+58
+69
+70
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+41
+58
+57
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+137
+110
+49
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+41
+58
+57
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+70
+79
+77
+245
+212
+186
+253
+212
+188
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+238
+205
+179
+70
+79
+77
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+146
+135
+124
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+253
+204
+176
+255
+215
+190
+172
+150
+134
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+97
+98
+96
+55
+66
+67
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+117
+98
+55
+145
+114
+49
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+137
+127
+115
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+187
+166
+150
+255
+215
+190
+253
+204
+176
+251
+192
+154
+251
+192
+154
+250
+197
+158
+253
+204
+176
+255
+215
+190
+137
+127
+115
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+43
+57
+62
+41
+58
+57
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+77
+85
+81
+245
+212
+186
+251
+209
+178
+250
+197
+158
+249
+189
+146
+251
+192
+154
+250
+197
+158
+251
+209
+178
+238
+205
+179
+77
+85
+81
+112
+85
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+106
+82
+65
+41
+58
+57
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+253
+204
+176
+255
+215
+190
+176
+156
+141
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+176
+156
+141
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+227
+196
+175
+58
+69
+70
+139
+96
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+255
+215
+190
+207
+178
+158
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+249
+174
+124
+246
+156
+93
+247
+150
+84
+249
+146
+83
+249
+152
+92
+251
+168
+115
+249
+189
+146
+97
+98
+96
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+58
+69
+70
+227
+196
+175
+253
+212
+188
+250
+200
+166
+251
+192
+154
+249
+189
+146
+250
+197
+158
+251
+209
+178
+255
+215
+190
+97
+98
+96
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+43
+57
+62
+43
+57
+62
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+126
+45
+155
+100
+63
+43
+57
+62
+207
+178
+158
+255
+215
+190
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+197
+158
+251
+209
+178
+255
+215
+190
+109
+106
+99
+89
+75
+66
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+143
+74
+249
+159
+103
+252
+185
+144
+55
+48
+48
+59
+50
+39
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+101
+83
+47
+59
+50
+39
+209
+171
+139
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+137
+127
+115
+101
+100
+92
+120
+114
+108
+186
+181
+179
+152
+147
+147
+55
+48
+48
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+234
+204
+183
+70
+79
+77
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+41
+58
+57
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+75
+74
+61
+41
+58
+57
+88
+82
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+77
+85
+81
+245
+212
+186
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+245
+212
+186
+84
+85
+82
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+161
+144
+134
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+187
+166
+150
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+91
+92
+89
+55
+66
+67
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+63
+69
+60
+137
+127
+115
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+48
+58
+59
+187
+166
+150
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+41
+58
+57
+118
+86
+65
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+95
+78
+64
+91
+92
+89
+255
+215
+190
+253
+204
+176
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+253
+204
+176
+245
+212
+186
+91
+92
+89
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+41
+58
+57
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+227
+126
+50
+199
+115
+54
+56
+64
+60
+161
+144
+134
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+187
+166
+150
+48
+58
+59
+183
+110
+59
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+217
+187
+166
+55
+66
+67
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+69
+69
+61
+137
+127
+115
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+249
+189
+146
+250
+200
+166
+253
+212
+188
+217
+187
+166
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+250
+197
+158
+249
+174
+124
+249
+159
+103
+249
+152
+92
+249
+152
+92
+249
+159
+103
+249
+174
+124
+250
+197
+158
+91
+92
+89
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+125
+90
+64
+70
+79
+77
+234
+204
+183
+251
+209
+178
+250
+197
+158
+249
+189
+146
+252
+185
+144
+251
+192
+154
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+126
+45
+135
+94
+64
+41
+58
+57
+41
+58
+57
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+212
+188
+253
+212
+188
+251
+209
+178
+251
+209
+178
+255
+215
+190
+137
+127
+115
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+146
+97
+64
+51
+62
+63
+227
+196
+175
+253
+212
+188
+250
+197
+158
+249
+189
+146
+249
+189
+146
+251
+192
+154
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+252
+185
+144
+55
+48
+48
+59
+50
+39
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+154
+125
+71
+170
+137
+67
+108
+87
+46
+59
+50
+39
+192
+155
+91
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+47
+40
+38
+65
+58
+56
+245
+212
+186
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+253
+212
+188
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+234
+204
+183
+63
+74
+74
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+41
+58
+57
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+111
+94
+57
+56
+64
+60
+43
+57
+62
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+70
+79
+77
+245
+212
+186
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+197
+158
+251
+209
+178
+245
+212
+186
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+152
+119
+47
+56
+64
+60
+161
+144
+134
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+176
+156
+141
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+91
+92
+89
+55
+66
+67
+123
+102
+54
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+100
+89
+56
+48
+58
+59
+187
+166
+150
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+255
+215
+190
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+197
+158
+253
+204
+176
+255
+215
+190
+146
+135
+124
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+41
+58
+57
+112
+85
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+84
+85
+82
+255
+215
+190
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+238
+205
+179
+84
+85
+82
+106
+82
+65
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+41
+58
+57
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+176
+156
+141
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+253
+212
+188
+253
+204
+176
+250
+200
+166
+253
+204
+176
+217
+187
+166
+55
+66
+67
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+207
+178
+158
+48
+58
+59
+163
+104
+61
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+250
+200
+166
+248
+180
+134
+251
+168
+115
+247
+165
+111
+247
+165
+111
+251
+168
+115
+248
+180
+134
+250
+200
+166
+91
+92
+89
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+63
+74
+74
+227
+196
+175
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+253
+204
+176
+255
+215
+190
+109
+106
+99
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+125
+52
+125
+90
+64
+43
+57
+62
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+137
+127
+115
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+43
+57
+62
+217
+187
+166
+253
+212
+188
+250
+200
+166
+251
+192
+154
+249
+189
+146
+250
+197
+158
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+248
+180
+134
+76
+70
+64
+47
+40
+38
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+170
+137
+67
+101
+83
+47
+59
+50
+39
+170
+137
+67
+255
+238
+227
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+152
+147
+147
+35
+31
+30
+24
+22
+23
+115
+102
+92
+255
+215
+190
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+58
+69
+70
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+207
+178
+158
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+161
+127
+40
+158
+125
+46
+75
+74
+61
+48
+58
+59
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+48
+58
+59
+101
+100
+92
+91
+92
+89
+75
+74
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+111
+94
+57
+55
+66
+67
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+227
+196
+175
+51
+62
+63
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+48
+58
+59
+48
+58
+59
+123
+102
+54
+168
+127
+42
+158
+125
+46
+161
+127
+40
+158
+125
+46
+69
+69
+61
+120
+114
+108
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+251
+209
+178
+255
+215
+190
+146
+135
+124
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+109
+106
+99
+63
+74
+74
+111
+94
+57
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+69
+69
+61
+51
+62
+63
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+51
+62
+63
+48
+58
+59
+120
+114
+108
+245
+212
+186
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+137
+127
+115
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+109
+106
+99
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+48
+58
+59
+43
+57
+62
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+125
+90
+64
+63
+74
+74
+227
+196
+175
+253
+212
+188
+250
+200
+166
+250
+197
+158
+250
+197
+158
+253
+204
+176
+255
+215
+190
+227
+196
+175
+55
+66
+67
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+48
+58
+59
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+251
+209
+178
+255
+215
+190
+137
+127
+115
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+176
+156
+141
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+91
+92
+89
+253
+212
+188
+253
+212
+188
+250
+200
+166
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+172
+150
+134
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+209
+178
+251
+192
+154
+250
+176
+132
+249
+174
+124
+249
+174
+124
+248
+180
+134
+251
+192
+154
+251
+209
+178
+109
+106
+99
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+146
+97
+64
+43
+57
+62
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+197
+158
+250
+197
+158
+250
+200
+166
+253
+212
+188
+245
+212
+186
+70
+79
+77
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+51
+62
+63
+51
+62
+63
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+245
+212
+186
+250
+200
+166
+251
+192
+154
+250
+197
+158
+253
+204
+176
+146
+135
+124
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+197
+158
+250
+200
+166
+253
+212
+188
+255
+215
+190
+84
+85
+82
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+121
+100
+85
+35
+31
+30
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+171
+129
+45
+85
+71
+43
+71
+60
+43
+171
+129
+45
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+174
+168
+167
+81
+77
+76
+24
+22
+23
+35
+31
+30
+35
+31
+30
+187
+166
+150
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+176
+156
+141
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+152
+119
+47
+56
+64
+60
+43
+57
+62
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+146
+135
+124
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+172
+150
+134
+172
+150
+134
+146
+135
+124
+146
+135
+124
+194
+173
+157
+245
+212
+186
+137
+127
+115
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+161
+144
+134
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+161
+144
+134
+48
+58
+59
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+51
+62
+63
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+70
+79
+77
+245
+212
+186
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+255
+215
+190
+255
+215
+190
+91
+92
+89
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+133
+120
+107
+84
+85
+82
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+55
+66
+67
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+172
+150
+134
+172
+150
+134
+137
+127
+115
+146
+135
+124
+207
+178
+158
+245
+212
+186
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+76
+78
+76
+245
+212
+186
+255
+215
+190
+253
+212
+188
+253
+212
+188
+253
+212
+188
+255
+215
+190
+227
+196
+175
+58
+69
+70
+118
+86
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+125
+90
+64
+63
+74
+74
+97
+98
+96
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+187
+166
+150
+255
+215
+190
+255
+215
+190
+251
+209
+178
+251
+209
+178
+255
+215
+190
+255
+215
+190
+176
+156
+141
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+69
+69
+61
+101
+100
+92
+63
+74
+74
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+63
+74
+74
+234
+204
+183
+255
+215
+190
+253
+212
+188
+253
+212
+188
+253
+212
+188
+255
+215
+190
+245
+212
+186
+70
+79
+77
+89
+75
+66
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+176
+156
+141
+253
+204
+176
+251
+192
+154
+251
+192
+154
+251
+192
+154
+250
+200
+166
+77
+85
+81
+106
+82
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+135
+94
+64
+51
+62
+63
+217
+187
+166
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+109
+106
+99
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+250
+200
+166
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+250
+200
+166
+255
+215
+190
+146
+135
+124
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+251
+209
+178
+251
+209
+178
+253
+212
+188
+255
+215
+190
+194
+173
+157
+43
+57
+62
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+77
+85
+81
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+200
+166
+172
+150
+134
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+120
+114
+108
+255
+215
+190
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+255
+215
+190
+217
+187
+166
+51
+62
+63
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+251
+168
+115
+187
+140
+108
+24
+22
+23
+59
+50
+39
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+154
+125
+71
+156
+125
+62
+158
+125
+46
+47
+40
+38
+108
+87
+46
+158
+125
+46
+195
+167
+113
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+164
+158
+157
+109
+106
+99
+65
+58
+56
+24
+22
+23
+24
+22
+23
+94
+60
+47
+178
+86
+46
+59
+50
+39
+150
+125
+114
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+84
+85
+82
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+55
+66
+67
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+123
+102
+54
+51
+62
+63
+76
+78
+76
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+133
+120
+107
+77
+85
+81
+77
+85
+81
+146
+135
+124
+245
+212
+186
+176
+156
+141
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+63
+74
+74
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+77
+85
+81
+77
+85
+81
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+48
+58
+59
+117
+98
+55
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+120
+114
+108
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+111
+94
+57
+51
+62
+63
+176
+156
+141
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+120
+114
+108
+70
+79
+77
+84
+85
+82
+161
+144
+134
+255
+215
+190
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+41
+58
+57
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+183
+110
+59
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+97
+98
+96
+172
+150
+134
+48
+58
+59
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+84
+85
+82
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+176
+156
+141
+97
+98
+96
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+41
+58
+57
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+250
+200
+166
+249
+189
+146
+252
+185
+144
+249
+189
+146
+250
+200
+166
+120
+114
+108
+69
+69
+61
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+101
+100
+92
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+187
+166
+150
+43
+57
+62
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+253
+212
+188
+255
+215
+190
+187
+166
+150
+41
+58
+57
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+58
+69
+70
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+91
+92
+89
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+77
+85
+81
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+204
+176
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+212
+173
+150
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+118
+86
+65
+51
+62
+63
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+109
+106
+99
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+248
+180
+134
+89
+75
+66
+24
+22
+23
+85
+71
+43
+171
+129
+45
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+154
+125
+71
+156
+125
+62
+175
+132
+40
+85
+71
+43
+47
+40
+38
+158
+125
+46
+158
+125
+46
+170
+137
+67
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+207
+202
+200
+164
+158
+157
+146
+135
+124
+120
+114
+108
+89
+84
+82
+65
+58
+56
+47
+40
+38
+24
+22
+23
+24
+22
+23
+35
+31
+30
+94
+60
+47
+178
+86
+46
+226
+110
+35
+241
+100
+24
+144
+77
+47
+65
+58
+56
+253
+212
+188
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+129
+106
+52
+48
+58
+59
+101
+100
+92
+217
+187
+166
+245
+212
+186
+245
+212
+186
+194
+173
+157
+76
+78
+76
+56
+64
+60
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+77
+85
+81
+176
+156
+141
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+95
+87
+59
+41
+58
+57
+137
+127
+115
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+207
+178
+158
+120
+114
+108
+48
+58
+59
+62
+63
+61
+100
+89
+56
+95
+87
+59
+51
+62
+63
+120
+114
+108
+227
+196
+175
+55
+66
+67
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+84
+85
+82
+207
+178
+158
+245
+212
+186
+245
+212
+186
+207
+178
+158
+97
+98
+96
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+91
+92
+89
+120
+114
+108
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+161
+144
+134
+227
+196
+175
+253
+212
+188
+234
+204
+183
+161
+144
+134
+51
+62
+63
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+176
+156
+141
+48
+58
+59
+137
+110
+49
+171
+129
+45
+158
+125
+46
+161
+127
+40
+158
+125
+46
+75
+74
+61
+43
+57
+62
+161
+144
+134
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+194
+173
+157
+109
+106
+99
+43
+57
+62
+69
+69
+61
+105
+93
+60
+88
+82
+59
+48
+58
+59
+146
+135
+124
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+95
+78
+64
+43
+57
+62
+161
+144
+134
+234
+204
+183
+245
+212
+186
+227
+196
+175
+146
+135
+124
+35
+56
+60
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+188
+112
+56
+51
+62
+63
+161
+144
+134
+234
+204
+183
+51
+62
+63
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+163
+104
+61
+43
+57
+62
+97
+98
+96
+207
+178
+158
+245
+212
+186
+245
+212
+186
+207
+178
+158
+91
+92
+89
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+118
+86
+65
+55
+66
+67
+234
+204
+183
+146
+135
+124
+56
+64
+60
+194
+112
+58
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+35
+56
+60
+146
+135
+124
+227
+196
+175
+253
+212
+188
+234
+204
+183
+161
+144
+134
+43
+57
+62
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+250
+197
+158
+252
+185
+144
+248
+180
+134
+248
+180
+134
+251
+192
+154
+172
+150
+134
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+41
+58
+57
+120
+114
+108
+217
+187
+166
+245
+212
+186
+234
+204
+183
+176
+156
+141
+58
+69
+70
+81
+73
+62
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+255
+215
+190
+217
+187
+166
+133
+120
+107
+84
+85
+82
+91
+92
+89
+146
+135
+124
+234
+204
+183
+238
+205
+179
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+84
+85
+82
+194
+173
+157
+245
+212
+186
+245
+212
+186
+217
+187
+166
+109
+106
+99
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+146
+97
+64
+51
+62
+63
+187
+166
+150
+76
+78
+76
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+97
+98
+96
+250
+200
+166
+249
+189
+146
+248
+180
+134
+248
+180
+134
+252
+185
+144
+232
+190
+161
+70
+79
+77
+112
+85
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+199
+115
+54
+65
+67
+64
+70
+79
+77
+187
+166
+150
+238
+205
+179
+245
+212
+186
+217
+187
+166
+133
+120
+107
+35
+56
+60
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+251
+168
+115
+203
+161
+131
+55
+48
+48
+24
+22
+23
+71
+60
+43
+145
+114
+49
+171
+129
+45
+171
+129
+45
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+156
+125
+62
+156
+125
+62
+171
+129
+45
+171
+129
+45
+101
+83
+47
+35
+31
+30
+123
+102
+54
+171
+129
+45
+158
+125
+46
+160
+120
+43
+224
+207
+180
+253
+255
+252
+253
+255
+252
+219
+212
+208
+47
+40
+38
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+24
+22
+23
+47
+40
+38
+226
+110
+35
+241
+100
+24
+226
+110
+35
+226
+110
+35
+144
+77
+47
+55
+48
+48
+238
+205
+179
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+123
+102
+54
+56
+64
+60
+51
+62
+63
+84
+85
+82
+84
+85
+82
+48
+58
+59
+63
+69
+60
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+245
+212
+186
+84
+85
+82
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+95
+87
+59
+48
+58
+59
+63
+74
+74
+109
+106
+99
+133
+120
+107
+133
+120
+107
+91
+92
+89
+51
+62
+63
+56
+64
+60
+100
+89
+56
+152
+119
+47
+171
+129
+45
+175
+132
+40
+100
+89
+56
+48
+58
+59
+217
+187
+166
+120
+114
+108
+63
+69
+60
+152
+119
+47
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+61
+67
+58
+51
+62
+63
+84
+85
+82
+84
+85
+82
+51
+62
+63
+56
+64
+60
+123
+102
+54
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+187
+166
+150
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+83
+78
+61
+48
+58
+59
+63
+74
+74
+91
+92
+89
+70
+79
+77
+48
+58
+59
+75
+74
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+234
+204
+183
+63
+74
+74
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+83
+78
+61
+48
+58
+59
+70
+79
+77
+109
+106
+99
+133
+120
+107
+120
+114
+108
+84
+85
+82
+48
+58
+59
+61
+67
+58
+111
+94
+57
+158
+125
+46
+171
+129
+45
+171
+129
+45
+88
+82
+59
+58
+69
+70
+238
+205
+179
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+212
+120
+56
+95
+78
+64
+43
+57
+62
+70
+79
+77
+84
+85
+82
+63
+74
+74
+48
+58
+59
+118
+86
+65
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+112
+85
+63
+55
+66
+67
+227
+196
+175
+255
+215
+190
+120
+114
+108
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+155
+100
+63
+62
+63
+61
+51
+62
+63
+77
+85
+81
+77
+85
+81
+51
+62
+63
+62
+63
+61
+155
+100
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+199
+115
+54
+56
+64
+60
+120
+114
+108
+255
+215
+190
+217
+187
+166
+43
+57
+62
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+106
+82
+65
+48
+58
+59
+63
+74
+74
+84
+85
+82
+70
+79
+77
+43
+57
+62
+95
+78
+64
+212
+120
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+172
+150
+134
+251
+192
+154
+248
+180
+134
+249
+174
+124
+249
+174
+124
+248
+180
+134
+236
+186
+153
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+51
+62
+63
+55
+66
+67
+84
+85
+82
+70
+79
+77
+41
+58
+57
+81
+73
+62
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+194
+173
+157
+58
+69
+70
+62
+63
+61
+106
+82
+65
+95
+78
+64
+51
+62
+63
+91
+92
+89
+238
+205
+179
+161
+144
+134
+48
+58
+59
+183
+110
+59
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+173
+106
+60
+65
+67
+64
+48
+58
+59
+77
+85
+81
+84
+85
+82
+55
+66
+67
+56
+64
+60
+146
+97
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+69
+69
+61
+101
+100
+92
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+250
+197
+158
+252
+185
+144
+249
+174
+124
+249
+174
+124
+250
+176
+132
+251
+192
+154
+120
+114
+108
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+188
+112
+56
+76
+70
+64
+41
+58
+57
+77
+85
+81
+84
+85
+82
+58
+69
+70
+48
+58
+59
+125
+90
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+243
+101
+2
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+249
+174
+124
+203
+161
+131
+55
+48
+48
+24
+22
+23
+35
+31
+30
+85
+71
+43
+137
+110
+49
+152
+119
+47
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+152
+119
+47
+117
+98
+55
+59
+50
+39
+35
+31
+30
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+146
+135
+124
+65
+58
+56
+35
+31
+30
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+83
+53
+42
+236
+108
+29
+236
+108
+29
+226
+110
+35
+94
+60
+47
+65
+58
+56
+253
+212
+188
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+145
+114
+49
+105
+93
+60
+83
+78
+61
+83
+78
+61
+111
+94
+57
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+51
+62
+63
+217
+187
+166
+255
+215
+190
+176
+156
+141
+43
+57
+62
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+137
+110
+49
+88
+82
+59
+69
+69
+61
+62
+63
+61
+63
+69
+60
+75
+74
+61
+105
+93
+60
+152
+119
+47
+171
+129
+45
+168
+127
+42
+158
+125
+46
+171
+129
+45
+129
+106
+52
+48
+58
+59
+194
+173
+157
+207
+178
+158
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+111
+94
+57
+83
+78
+61
+83
+78
+61
+105
+93
+60
+145
+114
+49
+168
+127
+42
+161
+127
+40
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+245
+212
+186
+77
+85
+81
+75
+74
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+129
+106
+52
+95
+87
+59
+81
+73
+62
+95
+87
+59
+123
+102
+54
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+161
+144
+134
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+129
+106
+52
+88
+82
+59
+69
+69
+61
+62
+63
+61
+63
+69
+60
+75
+74
+61
+117
+98
+55
+152
+119
+47
+171
+129
+45
+161
+127
+40
+158
+125
+46
+171
+129
+45
+111
+94
+57
+48
+58
+59
+227
+196
+175
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+163
+104
+61
+112
+85
+63
+95
+78
+64
+118
+86
+65
+173
+106
+60
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+133
+120
+107
+255
+215
+190
+255
+215
+190
+217
+187
+166
+51
+62
+63
+106
+82
+65
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+199
+115
+54
+135
+94
+64
+95
+78
+64
+95
+78
+64
+135
+94
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+106
+82
+65
+51
+62
+63
+217
+187
+166
+255
+215
+190
+255
+215
+190
+120
+114
+108
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+173
+106
+60
+118
+86
+65
+95
+78
+64
+112
+85
+63
+163
+104
+61
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+172
+150
+134
+252
+185
+144
+249
+174
+124
+247
+165
+111
+247
+165
+111
+249
+174
+124
+252
+185
+144
+154
+133
+118
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+188
+112
+56
+125
+90
+64
+95
+78
+64
+106
+82
+65
+155
+100
+63
+224
+123
+55
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+253
+212
+188
+91
+92
+89
+69
+69
+61
+194
+112
+58
+234
+126
+45
+234
+126
+45
+163
+104
+61
+51
+62
+63
+137
+127
+115
+238
+205
+179
+63
+74
+74
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+146
+97
+64
+106
+82
+65
+95
+78
+64
+125
+90
+64
+194
+112
+58
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+125
+90
+64
+41
+58
+57
+194
+173
+157
+238
+205
+179
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+251
+192
+154
+250
+176
+132
+251
+168
+115
+247
+165
+111
+249
+174
+124
+245
+179
+138
+195
+157
+134
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+146
+97
+64
+106
+82
+65
+95
+78
+64
+125
+90
+64
+183
+110
+59
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+219
+170
+138
+115
+102
+92
+47
+40
+38
+24
+22
+23
+35
+31
+30
+47
+40
+38
+59
+50
+39
+59
+50
+39
+59
+50
+39
+59
+50
+39
+47
+40
+38
+47
+40
+38
+71
+60
+43
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+170
+137
+67
+219
+212
+208
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+152
+147
+147
+109
+106
+99
+65
+67
+64
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+94
+60
+47
+178
+86
+46
+109
+63
+45
+35
+31
+30
+124
+111
+99
+251
+209
+178
+251
+209
+178
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+117
+98
+55
+129
+106
+52
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+171
+129
+45
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+120
+114
+108
+51
+62
+63
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+152
+119
+47
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+81
+73
+62
+58
+69
+70
+227
+196
+175
+255
+215
+190
+120
+114
+108
+48
+58
+59
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+152
+119
+47
+117
+98
+55
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+176
+156
+141
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+145
+114
+49
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+238
+205
+179
+91
+92
+89
+56
+64
+60
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+158
+125
+46
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+152
+119
+47
+69
+69
+61
+84
+85
+82
+245
+212
+186
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+125
+90
+64
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+125
+52
+227
+126
+50
+234
+125
+52
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+81
+73
+62
+63
+74
+74
+227
+196
+175
+255
+215
+190
+253
+212
+188
+255
+215
+190
+146
+135
+124
+48
+58
+59
+146
+97
+64
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+139
+96
+61
+48
+58
+59
+146
+135
+124
+255
+215
+190
+253
+212
+188
+255
+215
+190
+217
+187
+166
+55
+66
+67
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+163
+104
+61
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+167
+142
+123
+248
+180
+134
+247
+165
+111
+249
+159
+103
+246
+156
+93
+249
+159
+103
+249
+174
+124
+239
+182
+144
+77
+85
+81
+65
+67
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+135
+94
+64
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+146
+135
+124
+227
+196
+175
+43
+57
+62
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+106
+82
+65
+70
+79
+77
+253
+212
+188
+176
+156
+141
+41
+58
+57
+125
+90
+64
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+227
+126
+50
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+155
+100
+63
+48
+58
+59
+120
+114
+108
+253
+212
+188
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+252
+185
+144
+245
+169
+119
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+251
+192
+154
+109
+106
+99
+62
+63
+61
+188
+112
+56
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+212
+120
+56
+199
+115
+54
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+243
+101
+2
+243
+101
+2
+247
+103
+7
+247
+111
+26
+247
+111
+26
+247
+123
+41
+247
+130
+60
+243
+141
+78
+249
+159
+103
+250
+176
+132
+251
+192
+154
+207
+178
+158
+154
+133
+118
+82
+69
+65
+24
+22
+23
+71
+60
+43
+101
+83
+47
+101
+83
+47
+101
+83
+47
+117
+98
+55
+145
+114
+49
+171
+129
+45
+168
+127
+42
+160
+120
+43
+160
+120
+43
+158
+125
+46
+192
+155
+91
+237
+233
+225
+81
+77
+76
+55
+48
+48
+74
+68
+68
+81
+77
+76
+89
+84
+82
+91
+92
+89
+89
+84
+82
+81
+77
+76
+65
+58
+56
+47
+40
+38
+35
+31
+30
+55
+48
+48
+115
+102
+92
+172
+150
+134
+55
+48
+48
+24
+22
+23
+24
+22
+23
+24
+22
+23
+65
+58
+56
+230
+173
+136
+251
+192
+154
+250
+197
+158
+250
+200
+166
+84
+85
+82
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+83
+78
+61
+69
+69
+61
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+117
+98
+55
+48
+58
+59
+101
+100
+92
+238
+205
+179
+253
+204
+176
+250
+200
+166
+253
+204
+176
+238
+205
+179
+91
+92
+89
+51
+62
+63
+117
+98
+55
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+145
+114
+49
+75
+74
+61
+48
+58
+59
+172
+150
+134
+253
+212
+188
+255
+215
+190
+234
+204
+183
+84
+85
+82
+56
+64
+60
+129
+106
+52
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+81
+73
+62
+63
+69
+60
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+84
+85
+82
+255
+215
+190
+245
+212
+186
+109
+106
+99
+51
+62
+63
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+171
+129
+45
+105
+93
+60
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+62
+63
+61
+137
+127
+115
+255
+215
+190
+255
+215
+190
+227
+196
+175
+77
+85
+81
+56
+64
+60
+129
+106
+52
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+137
+110
+49
+69
+69
+61
+51
+62
+63
+187
+166
+150
+255
+215
+190
+172
+150
+134
+51
+62
+63
+194
+112
+58
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+209
+117
+53
+89
+75
+66
+48
+58
+59
+187
+166
+150
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+109
+106
+99
+48
+58
+59
+135
+94
+64
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+43
+57
+62
+120
+114
+108
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+172
+150
+134
+41
+58
+57
+106
+82
+65
+214
+121
+50
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+183
+110
+59
+48
+58
+59
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+188
+112
+56
+51
+62
+63
+109
+106
+99
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+178
+146
+122
+245
+169
+119
+246
+156
+93
+247
+150
+84
+249
+146
+83
+247
+150
+84
+249
+159
+103
+249
+174
+124
+203
+161
+131
+58
+69
+70
+76
+70
+64
+194
+112
+58
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+183
+110
+59
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+146
+135
+124
+217
+187
+166
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+58
+69
+70
+234
+204
+183
+255
+215
+190
+137
+127
+115
+41
+58
+57
+118
+86
+65
+225
+124
+48
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+146
+97
+64
+51
+62
+63
+97
+98
+96
+238
+205
+179
+255
+215
+190
+234
+204
+183
+63
+74
+74
+118
+86
+65
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+81
+73
+62
+101
+100
+92
+250
+176
+132
+247
+165
+111
+246
+156
+93
+249
+152
+92
+249
+159
+103
+251
+168
+115
+252
+185
+144
+217
+187
+166
+58
+69
+70
+69
+69
+61
+199
+115
+54
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+197
+158
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+243
+101
+2
+247
+103
+7
+236
+102
+14
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+243
+141
+78
+249
+159
+103
+249
+174
+124
+249
+189
+146
+253
+204
+176
+124
+111
+99
+35
+31
+30
+145
+114
+49
+175
+132
+40
+171
+129
+45
+168
+127
+42
+192
+155
+91
+216
+194
+154
+224
+207
+180
+224
+207
+180
+216
+194
+154
+216
+194
+154
+239
+227
+208
+253
+255
+252
+253
+255
+252
+186
+181
+179
+146
+135
+124
+120
+114
+108
+109
+106
+99
+95
+78
+64
+71
+60
+43
+85
+71
+43
+101
+83
+47
+108
+87
+46
+35
+31
+30
+150
+125
+114
+227
+196
+175
+255
+215
+190
+253
+212
+188
+212
+173
+150
+121
+100
+85
+95
+78
+64
+129
+102
+78
+234
+168
+124
+250
+176
+132
+250
+176
+132
+248
+180
+134
+249
+189
+146
+124
+111
+99
+62
+63
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+145
+114
+49
+56
+64
+60
+43
+57
+62
+83
+78
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+152
+119
+47
+95
+87
+59
+48
+58
+59
+101
+100
+92
+236
+186
+153
+251
+192
+154
+252
+185
+144
+248
+180
+134
+245
+179
+138
+249
+189
+146
+236
+186
+153
+101
+100
+92
+48
+58
+59
+88
+82
+59
+137
+110
+49
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+145
+114
+49
+100
+89
+56
+56
+64
+60
+58
+69
+70
+172
+150
+134
+250
+200
+166
+251
+192
+154
+250
+197
+158
+250
+200
+166
+217
+187
+166
+84
+85
+82
+51
+62
+63
+105
+93
+60
+158
+125
+46
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+152
+119
+47
+83
+78
+61
+43
+57
+62
+48
+58
+59
+129
+106
+52
+175
+132
+40
+171
+129
+45
+158
+125
+46
+63
+69
+60
+120
+114
+108
+255
+215
+190
+255
+215
+190
+227
+196
+175
+84
+85
+82
+51
+62
+63
+105
+93
+60
+158
+125
+46
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+158
+125
+46
+105
+93
+60
+48
+58
+59
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+172
+150
+134
+91
+92
+89
+75
+74
+61
+168
+127
+42
+171
+129
+45
+175
+132
+40
+117
+98
+55
+48
+58
+59
+176
+156
+141
+253
+204
+176
+253
+204
+176
+253
+204
+176
+217
+187
+166
+84
+85
+82
+48
+58
+59
+95
+87
+59
+145
+114
+49
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+158
+125
+46
+137
+110
+49
+95
+87
+59
+51
+62
+63
+70
+79
+77
+187
+166
+150
+251
+209
+178
+251
+209
+178
+207
+178
+158
+43
+57
+62
+135
+94
+64
+238
+123
+45
+234
+126
+45
+234
+126
+45
+118
+86
+65
+35
+56
+60
+56
+64
+60
+155
+100
+63
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+126
+45
+227
+126
+50
+163
+104
+61
+76
+70
+64
+51
+62
+63
+167
+142
+123
+251
+192
+154
+248
+180
+134
+249
+174
+124
+249
+174
+124
+250
+176
+132
+245
+179
+138
+236
+186
+153
+109
+106
+99
+41
+58
+57
+95
+78
+64
+183
+110
+59
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+227
+126
+50
+183
+110
+59
+95
+78
+64
+43
+57
+62
+124
+111
+99
+236
+186
+153
+252
+185
+144
+250
+176
+132
+249
+174
+124
+249
+174
+124
+248
+180
+134
+251
+192
+154
+154
+133
+118
+43
+57
+62
+81
+73
+62
+173
+106
+60
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+125
+52
+155
+100
+63
+56
+64
+60
+35
+56
+60
+89
+75
+66
+227
+126
+50
+234
+126
+45
+238
+128
+40
+146
+97
+64
+43
+57
+62
+176
+156
+141
+58
+69
+70
+118
+86
+65
+234
+126
+45
+234
+126
+45
+234
+126
+45
+112
+85
+63
+43
+57
+62
+210
+156
+119
+245
+162
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+241
+138
+68
+249
+146
+83
+249
+159
+103
+250
+176
+132
+195
+157
+134
+58
+69
+70
+65
+67
+64
+155
+100
+63
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+173
+106
+60
+65
+67
+64
+35
+56
+60
+106
+82
+65
+234
+126
+45
+234
+126
+45
+238
+128
+40
+146
+97
+64
+43
+57
+62
+187
+166
+150
+234
+204
+183
+55
+66
+67
+106
+82
+65
+234
+126
+45
+234
+125
+52
+234
+125
+52
+224
+123
+55
+81
+73
+62
+91
+92
+89
+245
+212
+186
+253
+212
+188
+253
+212
+188
+137
+127
+115
+41
+58
+57
+89
+75
+66
+173
+106
+60
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+125
+52
+194
+112
+58
+106
+82
+65
+43
+57
+62
+101
+100
+92
+227
+196
+175
+251
+209
+178
+251
+209
+178
+253
+212
+188
+97
+98
+96
+69
+69
+61
+209
+117
+53
+234
+126
+45
+238
+128
+40
+173
+106
+60
+51
+62
+63
+139
+115
+96
+251
+168
+115
+246
+156
+93
+247
+150
+84
+249
+146
+83
+249
+152
+92
+247
+165
+111
+248
+180
+134
+250
+200
+166
+187
+166
+150
+55
+66
+67
+69
+69
+61
+163
+104
+61
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+126
+45
+199
+115
+54
+95
+78
+64
+35
+56
+60
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+250
+197
+158
+245
+169
+119
+247
+150
+84
+247
+130
+60
+247
+118
+39
+235
+107
+16
+243
+101
+2
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+246
+97
+3
+237
+95
+0
+243
+101
+2
+247
+103
+7
+236
+102
+14
+247
+111
+26
+246
+116
+28
+238
+123
+45
+241
+132
+59
+247
+143
+74
+246
+156
+93
+245
+169
+119
+230
+173
+136
+47
+40
+38
+59
+50
+39
+168
+127
+42
+161
+127
+40
+160
+120
+43
+192
+155
+91
+255
+238
+227
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+239
+227
+208
+170
+137
+67
+171
+129
+45
+171
+129
+45
+171
+129
+45
+59
+50
+39
+154
+133
+118
+250
+200
+166
+250
+197
+158
+249
+189
+146
+248
+180
+134
+249
+174
+124
+247
+165
+111
+247
+165
+111
+245
+162
+103
+249
+159
+103
+245
+162
+103
+247
+165
+111
+249
+174
+124
+203
+161
+131
+55
+66
+67
+69
+69
+61
+111
+94
+57
+105
+93
+60
+69
+69
+61
+63
+74
+74
+137
+127
+115
+51
+62
+63
+62
+63
+61
+95
+87
+59
+129
+106
+52
+137
+110
+49
+137
+110
+49
+123
+102
+54
+95
+87
+59
+62
+63
+61
+51
+62
+63
+133
+120
+107
+239
+182
+144
+248
+180
+134
+245
+169
+119
+247
+165
+111
+249
+159
+103
+245
+162
+103
+251
+168
+115
+250
+176
+132
+239
+182
+144
+154
+133
+118
+63
+74
+74
+51
+62
+63
+75
+74
+61
+105
+93
+60
+123
+102
+54
+137
+110
+49
+137
+110
+49
+137
+110
+49
+123
+102
+54
+100
+89
+56
+75
+74
+61
+56
+64
+60
+55
+66
+67
+124
+111
+99
+219
+170
+138
+252
+185
+144
+250
+176
+132
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+236
+186
+153
+124
+111
+99
+48
+58
+59
+63
+69
+60
+95
+87
+59
+123
+102
+54
+137
+110
+49
+137
+110
+49
+129
+106
+52
+95
+87
+59
+62
+63
+61
+55
+66
+67
+146
+135
+124
+77
+85
+81
+61
+67
+58
+105
+93
+60
+111
+94
+57
+75
+74
+61
+48
+58
+59
+194
+173
+157
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+120
+114
+108
+43
+57
+62
+69
+69
+61
+100
+89
+56
+129
+106
+52
+137
+110
+49
+137
+110
+49
+129
+106
+52
+105
+93
+60
+69
+69
+61
+48
+58
+59
+77
+85
+81
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+187
+166
+150
+187
+166
+150
+48
+58
+59
+75
+74
+61
+111
+94
+57
+95
+87
+59
+56
+64
+60
+99
+90
+79
+239
+182
+144
+252
+185
+144
+245
+179
+138
+252
+185
+144
+249
+189
+146
+236
+186
+153
+137
+127
+115
+55
+66
+67
+56
+64
+60
+83
+78
+61
+111
+94
+57
+129
+106
+52
+137
+110
+49
+137
+110
+49
+129
+106
+52
+117
+98
+55
+95
+87
+59
+69
+69
+61
+51
+62
+63
+63
+74
+74
+133
+120
+107
+236
+186
+153
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+197
+158
+124
+111
+99
+51
+62
+63
+112
+85
+63
+146
+97
+64
+106
+82
+65
+48
+58
+59
+120
+114
+108
+101
+100
+92
+48
+58
+59
+95
+78
+64
+146
+97
+64
+183
+110
+59
+188
+112
+56
+173
+106
+60
+139
+96
+61
+89
+75
+66
+48
+58
+59
+77
+85
+81
+186
+157
+134
+245
+179
+138
+245
+169
+119
+245
+162
+103
+246
+156
+93
+246
+156
+93
+246
+156
+93
+247
+165
+111
+249
+174
+124
+249
+189
+146
+154
+133
+118
+58
+69
+70
+51
+62
+63
+95
+78
+64
+139
+96
+61
+173
+106
+60
+183
+110
+59
+183
+110
+59
+173
+106
+60
+139
+96
+61
+95
+78
+64
+51
+62
+63
+63
+74
+74
+167
+142
+123
+249
+189
+146
+249
+174
+124
+247
+165
+111
+246
+156
+93
+246
+156
+93
+246
+156
+93
+245
+162
+103
+245
+169
+119
+245
+179
+138
+178
+146
+122
+70
+79
+77
+48
+58
+59
+89
+75
+66
+139
+96
+61
+173
+106
+60
+188
+112
+56
+183
+110
+59
+155
+100
+63
+95
+78
+64
+48
+58
+59
+101
+100
+92
+146
+135
+124
+48
+58
+59
+95
+78
+64
+146
+97
+64
+125
+90
+64
+62
+63
+61
+101
+100
+92
+245
+212
+186
+137
+127
+115
+48
+58
+59
+106
+82
+65
+146
+97
+64
+106
+82
+65
+48
+58
+59
+124
+111
+99
+247
+165
+111
+247
+150
+84
+241
+138
+68
+241
+132
+59
+247
+130
+53
+247
+130
+53
+242
+133
+67
+241
+145
+79
+245
+162
+103
+250
+176
+132
+203
+161
+131
+91
+92
+89
+43
+57
+62
+81
+73
+62
+135
+94
+64
+173
+106
+60
+188
+112
+56
+183
+110
+59
+155
+100
+63
+106
+82
+65
+51
+62
+63
+91
+92
+89
+133
+120
+107
+48
+58
+59
+95
+78
+64
+146
+97
+64
+118
+86
+65
+56
+64
+60
+101
+100
+92
+245
+212
+186
+253
+212
+188
+146
+135
+124
+48
+58
+59
+118
+86
+65
+183
+110
+59
+173
+106
+60
+95
+78
+64
+43
+57
+62
+186
+157
+134
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+172
+150
+134
+70
+79
+77
+48
+58
+59
+89
+75
+66
+135
+94
+64
+163
+104
+61
+183
+110
+59
+183
+110
+59
+173
+106
+60
+146
+97
+64
+95
+78
+64
+56
+64
+60
+55
+66
+67
+150
+125
+114
+236
+186
+153
+251
+192
+154
+249
+189
+146
+249
+189
+146
+251
+192
+154
+195
+157
+134
+51
+62
+63
+76
+70
+64
+139
+96
+61
+125
+90
+64
+65
+67
+64
+76
+78
+76
+234
+168
+124
+249
+159
+103
+247
+150
+84
+243
+141
+78
+247
+143
+74
+247
+150
+84
+249
+159
+103
+250
+176
+132
+250
+197
+158
+255
+215
+190
+207
+178
+158
+84
+85
+82
+48
+58
+59
+89
+75
+66
+146
+97
+64
+173
+106
+60
+183
+110
+59
+183
+110
+59
+163
+104
+61
+118
+86
+65
+62
+63
+61
+58
+69
+70
+63
+74
+74
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+135
+94
+64
+58
+69
+70
+251
+192
+154
+245
+169
+119
+249
+146
+83
+247
+130
+53
+238
+116
+34
+235
+107
+16
+243
+101
+2
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+243
+101
+2
+236
+102
+14
+236
+102
+14
+235
+107
+16
+246
+116
+28
+239
+117
+44
+241
+132
+59
+247
+143
+74
+249
+152
+92
+214
+151
+109
+118
+86
+65
+146
+111
+88
+192
+155
+91
+192
+155
+91
+195
+167
+113
+239
+227
+208
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+216
+194
+154
+192
+155
+91
+192
+155
+91
+192
+155
+91
+146
+111
+88
+162
+125
+96
+250
+176
+132
+245
+169
+119
+247
+165
+111
+249
+159
+103
+246
+156
+93
+247
+150
+84
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+145
+79
+247
+150
+84
+249
+159
+103
+245
+169
+119
+187
+140
+108
+89
+84
+82
+48
+58
+59
+48
+58
+59
+91
+92
+89
+194
+173
+157
+255
+215
+190
+207
+178
+158
+109
+106
+99
+51
+62
+63
+48
+58
+59
+51
+62
+63
+48
+58
+59
+48
+58
+59
+55
+66
+67
+124
+111
+99
+203
+161
+131
+248
+180
+134
+245
+169
+119
+249
+159
+103
+247
+150
+84
+243
+141
+78
+243
+141
+78
+243
+141
+78
+247
+150
+84
+249
+159
+103
+245
+169
+119
+248
+180
+134
+219
+170
+138
+154
+133
+118
+84
+85
+82
+51
+62
+63
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+48
+58
+59
+55
+66
+67
+91
+92
+89
+154
+133
+118
+209
+171
+139
+245
+179
+138
+249
+174
+124
+247
+165
+111
+249
+159
+103
+246
+156
+93
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+252
+185
+144
+195
+157
+134
+109
+106
+99
+55
+66
+67
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+51
+62
+63
+109
+106
+99
+207
+178
+158
+255
+215
+190
+217
+187
+166
+91
+92
+89
+51
+62
+63
+48
+58
+59
+76
+78
+76
+172
+150
+134
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+101
+100
+92
+51
+62
+63
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+48
+58
+59
+97
+98
+96
+194
+173
+157
+146
+135
+124
+56
+64
+60
+145
+114
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+194
+173
+157
+255
+215
+190
+176
+156
+141
+76
+78
+76
+48
+58
+59
+55
+66
+67
+115
+102
+92
+234
+168
+124
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+245
+179
+138
+209
+171
+139
+144
+125
+110
+76
+78
+76
+48
+58
+59
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+48
+58
+59
+58
+69
+70
+101
+100
+92
+154
+133
+118
+219
+170
+138
+252
+185
+144
+248
+180
+134
+249
+174
+124
+245
+169
+119
+249
+174
+124
+250
+176
+132
+230
+173
+136
+124
+111
+99
+55
+66
+67
+43
+57
+62
+58
+69
+70
+137
+127
+115
+245
+212
+186
+245
+212
+186
+161
+144
+134
+70
+79
+77
+43
+57
+62
+51
+62
+63
+51
+62
+63
+48
+58
+59
+43
+57
+62
+84
+85
+82
+154
+133
+118
+240
+181
+138
+249
+174
+124
+247
+165
+111
+249
+152
+92
+243
+141
+78
+241
+138
+68
+242
+133
+67
+241
+138
+68
+241
+145
+79
+246
+156
+93
+247
+165
+111
+250
+176
+132
+219
+170
+138
+144
+125
+110
+77
+85
+81
+43
+57
+62
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+77
+85
+81
+150
+125
+114
+219
+170
+138
+250
+176
+132
+247
+165
+111
+246
+156
+93
+241
+145
+79
+241
+138
+68
+241
+138
+68
+241
+138
+68
+243
+141
+78
+249
+152
+92
+247
+165
+111
+250
+176
+132
+230
+173
+136
+154
+133
+118
+77
+85
+81
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+70
+79
+77
+161
+144
+134
+245
+212
+186
+255
+215
+190
+161
+144
+134
+63
+74
+74
+43
+57
+62
+51
+62
+63
+109
+106
+99
+217
+187
+166
+251
+209
+178
+238
+205
+179
+137
+127
+115
+58
+69
+70
+43
+57
+62
+58
+69
+70
+139
+115
+96
+238
+159
+107
+249
+152
+92
+241
+138
+68
+247
+130
+53
+238
+123
+45
+239
+117
+44
+247
+118
+39
+238
+123
+45
+241
+132
+59
+241
+145
+79
+249
+159
+103
+249
+174
+124
+240
+181
+138
+167
+142
+123
+91
+92
+89
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+63
+74
+74
+137
+127
+115
+234
+204
+183
+255
+215
+190
+146
+135
+124
+63
+74
+74
+43
+57
+62
+51
+62
+63
+115
+102
+92
+236
+186
+153
+251
+192
+154
+251
+192
+154
+236
+186
+153
+133
+120
+107
+43
+57
+62
+48
+58
+59
+48
+58
+59
+55
+66
+67
+158
+130
+108
+248
+180
+134
+250
+176
+132
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+239
+182
+144
+154
+133
+118
+84
+85
+82
+43
+57
+62
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+70
+79
+77
+133
+120
+107
+219
+170
+138
+245
+179
+138
+250
+176
+132
+245
+169
+119
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+187
+140
+108
+81
+77
+76
+43
+57
+62
+43
+57
+62
+99
+90
+79
+214
+151
+109
+249
+159
+103
+247
+150
+84
+247
+143
+74
+241
+138
+68
+241
+138
+68
+249
+146
+83
+249
+159
+103
+250
+176
+132
+250
+197
+158
+255
+215
+190
+255
+215
+190
+245
+212
+186
+161
+144
+134
+77
+85
+81
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+41
+58
+57
+55
+66
+67
+120
+114
+108
+217
+187
+166
+97
+98
+96
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+70
+79
+77
+249
+189
+146
+247
+165
+111
+243
+141
+78
+247
+130
+53
+238
+116
+34
+236
+102
+14
+243
+101
+2
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+247
+165
+111
+249
+174
+124
+250
+176
+132
+245
+179
+138
+252
+185
+144
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+252
+185
+144
+245
+179
+138
+250
+176
+132
+249
+174
+124
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+242
+133
+67
+243
+141
+78
+241
+145
+86
+249
+159
+103
+238
+159
+107
+210
+156
+119
+210
+156
+119
+240
+181
+138
+249
+189
+146
+251
+192
+154
+251
+192
+154
+250
+197
+158
+212
+173
+150
+186
+157
+134
+167
+142
+123
+167
+142
+123
+195
+157
+134
+219
+170
+138
+248
+180
+134
+245
+169
+119
+245
+162
+103
+247
+150
+84
+243
+141
+78
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+138
+68
+247
+150
+84
+245
+162
+103
+245
+169
+119
+250
+176
+132
+239
+182
+144
+219
+170
+138
+186
+157
+134
+167
+142
+123
+167
+142
+123
+172
+150
+134
+195
+157
+134
+219
+170
+138
+239
+182
+144
+248
+180
+134
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+79
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+145
+79
+241
+153
+96
+247
+165
+111
+249
+174
+124
+245
+179
+138
+219
+170
+138
+186
+157
+134
+167
+142
+123
+167
+142
+123
+186
+157
+134
+212
+173
+150
+250
+197
+158
+251
+192
+154
+251
+192
+154
+249
+189
+146
+239
+182
+144
+219
+170
+138
+219
+170
+138
+239
+182
+144
+250
+197
+158
+250
+200
+166
+251
+209
+178
+238
+205
+179
+172
+150
+134
+137
+127
+115
+161
+144
+134
+217
+187
+166
+253
+212
+188
+227
+196
+175
+194
+173
+157
+176
+156
+141
+172
+150
+134
+187
+166
+150
+217
+187
+166
+255
+215
+190
+245
+212
+186
+76
+78
+76
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+58
+69
+70
+217
+187
+166
+255
+215
+190
+253
+204
+176
+236
+186
+153
+210
+156
+119
+210
+156
+119
+247
+165
+111
+249
+159
+103
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+145
+79
+247
+150
+84
+241
+153
+96
+245
+162
+103
+245
+169
+119
+248
+180
+134
+239
+182
+144
+209
+171
+139
+186
+157
+134
+167
+142
+123
+167
+142
+123
+178
+146
+122
+195
+157
+134
+230
+173
+136
+239
+182
+144
+250
+176
+132
+245
+169
+119
+247
+165
+111
+249
+159
+103
+241
+153
+96
+249
+152
+92
+249
+152
+92
+241
+153
+96
+245
+162
+103
+247
+165
+111
+210
+156
+119
+210
+156
+119
+230
+173
+136
+249
+189
+146
+249
+189
+146
+251
+192
+154
+250
+197
+158
+236
+186
+153
+203
+161
+131
+167
+142
+123
+167
+142
+123
+178
+146
+122
+203
+161
+131
+240
+181
+138
+249
+174
+124
+247
+165
+111
+241
+153
+96
+243
+141
+78
+242
+133
+67
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+249
+159
+103
+245
+169
+119
+250
+176
+132
+240
+181
+138
+209
+171
+139
+178
+146
+122
+167
+142
+123
+167
+142
+123
+186
+157
+134
+209
+171
+139
+240
+181
+138
+250
+176
+132
+245
+169
+119
+249
+159
+103
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+238
+123
+45
+238
+123
+45
+247
+130
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+247
+165
+111
+250
+176
+132
+240
+181
+138
+203
+161
+131
+178
+146
+122
+167
+142
+123
+167
+142
+123
+195
+157
+134
+236
+186
+153
+251
+192
+154
+251
+192
+154
+249
+189
+146
+249
+189
+146
+230
+173
+136
+203
+161
+131
+219
+170
+138
+245
+179
+138
+245
+179
+138
+245
+179
+138
+245
+179
+138
+248
+180
+134
+234
+168
+124
+214
+151
+109
+214
+151
+109
+245
+162
+103
+241
+145
+86
+241
+138
+68
+238
+123
+53
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+238
+116
+34
+238
+123
+45
+241
+132
+59
+243
+141
+78
+241
+153
+96
+247
+165
+111
+249
+174
+124
+240
+181
+138
+209
+171
+139
+178
+146
+122
+167
+142
+123
+167
+142
+123
+195
+157
+134
+236
+186
+153
+250
+197
+158
+251
+192
+154
+249
+189
+146
+249
+189
+146
+230
+173
+136
+210
+156
+119
+210
+156
+119
+250
+176
+132
+249
+174
+124
+249
+174
+124
+249
+174
+124
+249
+174
+124
+250
+176
+132
+210
+156
+119
+162
+125
+96
+162
+125
+96
+214
+151
+109
+247
+165
+111
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+159
+103
+247
+165
+111
+245
+169
+119
+250
+176
+132
+240
+181
+138
+209
+171
+139
+186
+157
+134
+167
+142
+123
+167
+142
+123
+178
+146
+122
+203
+161
+131
+239
+182
+144
+248
+180
+134
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+145
+86
+241
+145
+86
+247
+150
+84
+241
+153
+96
+245
+162
+103
+238
+159
+107
+204
+141
+99
+214
+151
+109
+241
+153
+96
+249
+152
+92
+243
+141
+78
+242
+133
+67
+241
+132
+59
+241
+132
+59
+241
+138
+68
+241
+145
+79
+245
+162
+103
+248
+180
+134
+212
+173
+150
+146
+135
+124
+137
+127
+115
+176
+156
+141
+234
+204
+183
+253
+212
+188
+217
+187
+166
+187
+166
+150
+172
+150
+134
+176
+156
+141
+194
+173
+157
+234
+204
+183
+255
+215
+190
+194
+173
+157
+43
+57
+62
+139
+96
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+245
+179
+138
+245
+162
+103
+241
+138
+68
+238
+123
+45
+236
+108
+29
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+79
+249
+152
+92
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+243
+141
+78
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+132
+59
+238
+123
+53
+239
+117
+44
+238
+116
+34
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+249
+174
+124
+250
+176
+132
+250
+176
+132
+250
+176
+132
+249
+174
+124
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+242
+133
+67
+241
+132
+59
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+241
+132
+59
+242
+133
+67
+243
+141
+78
+249
+152
+92
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+245
+179
+138
+251
+192
+154
+232
+190
+161
+101
+100
+92
+51
+62
+63
+63
+69
+60
+51
+62
+63
+55
+66
+67
+109
+106
+99
+176
+156
+141
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+207
+178
+158
+91
+92
+89
+51
+62
+63
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+91
+92
+89
+245
+212
+186
+250
+200
+166
+252
+185
+144
+249
+174
+124
+247
+165
+111
+241
+153
+96
+241
+145
+79
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+247
+165
+111
+245
+169
+119
+249
+174
+124
+250
+176
+132
+250
+176
+132
+249
+174
+124
+249
+174
+124
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+145
+79
+241
+138
+68
+242
+133
+67
+242
+133
+67
+242
+133
+67
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+245
+162
+103
+241
+153
+96
+241
+145
+79
+241
+138
+68
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+169
+119
+249
+174
+124
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+132
+59
+238
+123
+53
+239
+117
+44
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+169
+119
+249
+174
+124
+249
+174
+124
+249
+174
+124
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+79
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+242
+133
+67
+241
+145
+86
+247
+165
+111
+210
+156
+119
+63
+74
+74
+62
+63
+61
+69
+69
+61
+48
+58
+59
+63
+74
+74
+133
+120
+107
+194
+173
+157
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+176
+156
+141
+55
+66
+67
+76
+70
+64
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+194
+112
+58
+56
+64
+60
+154
+133
+118
+250
+176
+132
+241
+153
+96
+242
+133
+67
+239
+117
+44
+236
+108
+29
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+138
+68
+243
+141
+78
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+132
+59
+242
+133
+67
+241
+138
+68
+243
+141
+78
+243
+141
+78
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+249
+152
+92
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+179
+138
+144
+125
+110
+51
+62
+63
+117
+98
+55
+158
+125
+46
+145
+114
+49
+105
+93
+60
+69
+69
+61
+48
+58
+59
+58
+69
+70
+91
+92
+89
+120
+114
+108
+120
+114
+108
+91
+92
+89
+48
+58
+59
+56
+64
+60
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+48
+58
+59
+161
+144
+134
+250
+197
+158
+248
+180
+134
+247
+165
+111
+241
+153
+96
+241
+145
+79
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+249
+152
+92
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+123
+45
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+138
+68
+241
+138
+68
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+243
+141
+78
+242
+133
+67
+241
+132
+59
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+145
+86
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+45
+239
+117
+44
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+241
+132
+59
+242
+133
+67
+243
+141
+78
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+241
+145
+79
+243
+141
+78
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+238
+123
+45
+238
+123
+53
+242
+133
+67
+241
+138
+68
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+242
+133
+67
+242
+133
+67
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+145
+86
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+86
+238
+159
+107
+84
+85
+82
+69
+69
+61
+188
+112
+56
+214
+121
+50
+173
+106
+60
+112
+85
+63
+62
+63
+61
+41
+58
+57
+63
+74
+74
+97
+98
+96
+120
+114
+108
+109
+106
+99
+77
+85
+81
+41
+58
+57
+81
+73
+62
+194
+112
+58
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+51
+62
+63
+209
+171
+139
+245
+169
+119
+241
+145
+86
+241
+132
+59
+238
+116
+34
+235
+107
+16
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+145
+86
+238
+159
+107
+234
+168
+124
+84
+85
+82
+83
+78
+61
+171
+129
+45
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+129
+106
+52
+100
+89
+56
+83
+78
+61
+75
+74
+61
+69
+69
+61
+83
+78
+61
+105
+93
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+75
+74
+61
+63
+74
+74
+236
+186
+153
+245
+179
+138
+238
+159
+107
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+145
+86
+204
+141
+99
+41
+58
+57
+155
+100
+63
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+125
+52
+209
+117
+53
+155
+100
+63
+118
+86
+65
+89
+75
+66
+81
+73
+62
+81
+73
+62
+106
+82
+65
+155
+100
+63
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+109
+106
+99
+245
+179
+138
+245
+162
+103
+241
+138
+68
+238
+123
+45
+235
+113
+30
+236
+102
+14
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+138
+68
+241
+145
+86
+238
+159
+107
+89
+84
+82
+75
+74
+61
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+95
+87
+59
+48
+58
+59
+167
+142
+123
+245
+179
+138
+238
+159
+107
+241
+145
+86
+242
+133
+67
+238
+123
+45
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+241
+132
+59
+241
+145
+79
+204
+141
+99
+48
+58
+59
+139
+96
+61
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+81
+73
+62
+58
+69
+70
+219
+170
+138
+245
+169
+119
+241
+145
+86
+241
+132
+59
+239
+117
+44
+236
+108
+29
+236
+102
+14
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+229
+102
+7
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+224
+98
+18
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+229
+102
+7
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+236
+108
+29
+239
+117
+44
+234
+125
+52
+231
+136
+72
+241
+153
+96
+162
+125
+96
+48
+58
+59
+95
+87
+59
+158
+125
+46
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+158
+125
+46
+95
+87
+59
+48
+58
+59
+124
+111
+99
+245
+179
+138
+247
+165
+111
+241
+145
+86
+241
+132
+59
+238
+123
+45
+238
+116
+34
+236
+108
+29
+224
+98
+18
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+230
+97
+5
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+235
+94
+9
+235
+94
+9
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+235
+107
+16
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+236
+102
+14
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+235
+94
+9
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+224
+98
+18
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+230
+97
+5
+229
+102
+7
+224
+98
+18
+236
+108
+29
+238
+116
+34
+238
+123
+53
+243
+141
+78
+241
+153
+96
+99
+90
+79
+56
+64
+60
+155
+100
+63
+234
+126
+45
+234
+126
+45
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+194
+112
+58
+81
+73
+62
+48
+58
+59
+178
+146
+122
+249
+174
+124
+241
+153
+96
+231
+136
+72
+234
+125
+52
+238
+116
+34
+235
+107
+16
+229
+102
+7
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+235
+113
+30
+239
+117
+44
+230
+128
+60
+236
+147
+85
+238
+159
+107
+139
+115
+96
+48
+58
+59
+69
+69
+61
+111
+94
+57
+145
+114
+49
+158
+125
+46
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+152
+119
+47
+117
+98
+55
+69
+69
+61
+48
+58
+59
+144
+125
+110
+240
+181
+138
+247
+165
+111
+236
+147
+85
+242
+133
+67
+238
+123
+45
+235
+113
+30
+235
+107
+16
+236
+102
+14
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+235
+107
+16
+235
+113
+30
+238
+123
+45
+242
+133
+67
+241
+153
+96
+214
+151
+109
+99
+90
+79
+48
+58
+59
+95
+78
+64
+155
+100
+63
+209
+117
+53
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+194
+112
+58
+125
+90
+64
+56
+64
+60
+58
+69
+70
+178
+146
+122
+250
+176
+132
+238
+159
+107
+241
+145
+79
+234
+125
+52
+239
+117
+44
+236
+108
+29
+224
+98
+18
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+230
+97
+5
+229
+102
+7
+223
+103
+18
+226
+110
+35
+234
+125
+52
+231
+136
+72
+241
+153
+96
+245
+169
+119
+178
+146
+122
+101
+100
+92
+48
+58
+59
+56
+64
+60
+69
+69
+61
+95
+87
+59
+111
+94
+57
+123
+102
+54
+129
+106
+52
+129
+106
+52
+123
+102
+54
+105
+93
+60
+88
+82
+59
+62
+63
+61
+48
+58
+59
+91
+92
+89
+186
+157
+134
+245
+179
+138
+238
+159
+107
+236
+147
+85
+230
+128
+60
+234
+125
+52
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+224
+98
+18
+236
+108
+29
+239
+117
+44
+230
+123
+57
+243
+141
+78
+238
+159
+107
+234
+168
+124
+158
+130
+108
+76
+78
+76
+41
+58
+57
+62
+63
+61
+95
+78
+64
+125
+90
+64
+146
+97
+64
+163
+104
+61
+173
+106
+60
+163
+104
+61
+155
+100
+63
+125
+90
+64
+95
+78
+64
+56
+64
+60
+43
+57
+62
+124
+111
+99
+209
+171
+139
+234
+168
+124
+238
+159
+107
+241
+145
+79
+230
+128
+60
+239
+117
+44
+236
+108
+29
+236
+102
+14
+229
+102
+7
+230
+97
+5
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+230
+97
+5
+224
+98
+18
+236
+108
+29
+226
+110
+35
+230
+123
+57
+231
+136
+72
+241
+153
+96
+238
+159
+107
+240
+181
+138
+203
+161
+131
+150
+125
+114
+101
+100
+92
+76
+78
+76
+55
+66
+67
+48
+58
+59
+48
+58
+59
+48
+58
+59
+48
+58
+59
+58
+69
+70
+84
+85
+82
+124
+111
+99
+178
+146
+122
+240
+181
+138
+234
+168
+124
+238
+159
+107
+236
+147
+85
+230
+128
+60
+234
+125
+52
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+128
+60
+236
+147
+85
+241
+153
+96
+234
+168
+124
+230
+173
+136
+186
+157
+134
+133
+120
+107
+91
+92
+89
+63
+74
+74
+51
+62
+63
+48
+58
+59
+48
+58
+59
+48
+58
+59
+51
+62
+63
+63
+74
+74
+91
+92
+89
+144
+125
+110
+203
+161
+131
+240
+181
+138
+245
+169
+119
+241
+153
+96
+241
+145
+79
+230
+128
+60
+225
+124
+48
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+239
+117
+44
+230
+123
+57
+231
+136
+72
+236
+147
+85
+238
+159
+107
+245
+169
+119
+234
+168
+124
+240
+181
+138
+239
+182
+144
+236
+186
+153
+250
+197
+158
+250
+197
+158
+250
+197
+158
+251
+192
+154
+236
+186
+153
+239
+182
+144
+245
+179
+138
+234
+168
+124
+238
+159
+107
+241
+153
+96
+231
+136
+72
+230
+128
+60
+225
+124
+48
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+128
+60
+231
+136
+72
+241
+153
+96
+238
+159
+107
+234
+168
+124
+240
+181
+138
+239
+182
+144
+236
+186
+153
+251
+192
+154
+250
+197
+158
+250
+197
+158
+250
+197
+158
+236
+186
+153
+239
+182
+144
+240
+181
+138
+234
+168
+124
+245
+169
+119
+238
+159
+107
+236
+147
+85
+231
+136
+72
+230
+123
+57
+239
+117
+44
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+128
+60
+231
+136
+72
+236
+147
+85
+241
+153
+96
+238
+159
+107
+238
+159
+107
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+238
+159
+107
+238
+159
+107
+241
+153
+96
+236
+147
+85
+231
+136
+72
+230
+128
+60
+230
+123
+57
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+123
+57
+230
+128
+60
+231
+136
+72
+236
+147
+85
+241
+153
+96
+238
+159
+107
+238
+159
+107
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+238
+159
+107
+238
+159
+107
+241
+153
+96
+236
+147
+85
+231
+136
+72
+230
+128
+60
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+128
+60
+230
+128
+60
+231
+136
+72
+231
+136
+72
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+231
+136
+72
+231
+136
+72
+231
+136
+72
+230
+128
+60
+227
+126
+50
+225
+124
+48
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+123
+57
+230
+128
+60
+231
+136
+72
+231
+136
+72
+231
+136
+72
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+231
+136
+72
+231
+136
+72
+230
+128
+60
+230
+123
+57
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+225
+124
+48
+225
+124
+48
+224
+123
+55
+224
+123
+55
+224
+123
+55
+230
+123
+57
+224
+123
+55
+224
+123
+55
+225
+124
+48
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+225
+124
+48
+225
+124
+48
+224
+123
+55
+230
+123
+57
+230
+123
+57
+230
+123
+57
+230
+123
+57
+230
+123
+57
+225
+124
+48
+225
+124
+48
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+223
+103
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
diff --git a/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch
new file mode 100644
index 0000000000..9da374041c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch
@@ -0,0 +1,169 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line
+Date: Wed, 2 Sep 2009 20:19:58 +0300
+Lines: 92
+Approved: news@gmane.org
+Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name>
+References: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1MiqiI-0003K3-An
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 14:20:23 +0000
+Original-Received: by bwz22 with SMTP id 22so788877bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT)
+X-Mailer: git-send-email 1.6.4.2
+In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04
+X-CRM114-Status: UNSURE ( 9.59 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.2 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -1.6 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025>
+
+Optimized version of copy_page() was written with assumption that cache
+line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes.
+
+This patch tries to generalize copy_page() to work with any cache line
+size if cache line size is multiple of 16 and page size is multiple of
+two cache line size.
+
+After this optimization we've got ~25% speedup on OMAP3(tested in
+userspace).
+
+There is test for kernelspace which trigger copy-on-write after fork():
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+ #define BUF_SIZE (10000*4096)
+ #define NFORK 200
+
+ int main(int argc, char **argv)
+ {
+ char *buf = malloc(BUF_SIZE);
+ int i;
+
+ memset(buf, 0, BUF_SIZE);
+
+ for(i = 0; i < NFORK; i++) {
+ if (fork()) {
+ wait(NULL);
+ } else {
+ int j;
+
+ for(j = 0; j < BUF_SIZE; j+= 4096)
+ buf[j] = (j & 0xFF) + 1;
+ break;
+ }
+ }
+
+ free(buf);
+ return 0;
+ }
+
+Before optimization this test takes ~66 seconds, after optimization
+takes ~56 seconds.
+
+Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com>
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/lib/copy_page.S | 16 ++++++++--------
+ 1 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
+index 6ae04db..6ee2f67 100644
+--- a/arch/arm/lib/copy_page.S
++++ b/arch/arm/lib/copy_page.S
+@@ -12,8 +12,9 @@
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+ #include <asm/asm-offsets.h>
++#include <asm/cache.h>
+
+-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 ))
+
+ .text
+ .align 5
+@@ -26,17 +27,16 @@
+ ENTRY(copy_page)
+ stmfd sp!, {r4, lr} @ 2
+ PLD( pld [r1, #0] )
+- PLD( pld [r1, #32] )
++ PLD( pld [r1, #L1_CACHE_BYTES] )
+ mov r2, #COPY_COUNT @ 1
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+-1: PLD( pld [r1, #64] )
+- PLD( pld [r1, #96] )
+-2: stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
+- stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
++1: PLD( pld [r1, #2 * L1_CACHE_BYTES])
++ PLD( pld [r1, #3 * L1_CACHE_BYTES])
++2:
++ .rept (2 * L1_CACHE_BYTES / 16 - 1)
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
++ .endr
+ subs r2, r2, #1 @ 1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmgtia r1!, {r3, r4, ip, lr} @ 4
+--
+1.6.4.2
diff --git a/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch b/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch
new file mode 100644
index 0000000000..e58d49c7a3
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch
@@ -0,0 +1,115 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line
+ size
+Date: Wed, 2 Sep 2009 19:11:52 +0300
+Lines: 39
+Approved: news@gmane.org
+Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1Mipeu-0000ZH-G2
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 13:12:04 +0000
+Original-Received: by bwz22 with SMTP id 22so735896bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT)
+X-Mailer: git-send-email 1.6.3.4
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2
+X-CRM114-Status: UNSURE ( 8.83 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.6 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.6 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -2.0 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017>
+
+Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5.
+It's not true at least for CPUs based on Cortex-A8.
+
+List of CPUs with cache line size != 32 should be expanded later.
+
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/include/asm/cache.h | 2 +-
+ arch/arm/mm/Kconfig | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
+index feaa75f..2ee7743 100644
+--- a/arch/arm/include/asm/cache.h
++++ b/arch/arm/include/asm/cache.h
+@@ -4,7 +4,7 @@
+ #ifndef __ASMARM_CACHE_H
+ #define __ASMARM_CACHE_H
+
+-#define L1_CACHE_SHIFT 5
++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT)
+ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+ /*
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index 83c025e..3c37d4c 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -771,3 +771,8 @@ config CACHE_XSC3L2
+ select OUTER_CACHE
+ help
+ This option enables the L2 cache on XScale3.
++
++config ARM_L1_CACHE_SHIFT
++ int
++ default 6 if ARCH_OMAP3
++ default 5
+--
+1.6.3.4
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch
new file mode 100644
index 0000000000..8880c8b37d
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch
@@ -0,0 +1,69 @@
+From 17091382ab8f92a366e7e1267c30f83711ccd9f8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 11:26:12 +0300
+Subject: [PATCH 01/18] OMAP2: Add funcs for writing SMS_ROT_* registers
+
+SMS_ROT_* registers are used by VRFB rotation engine.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Acked-by: Paul Walmsley <paul@pwsan.com>
+---
+ arch/arm/mach-omap2/sdrc.c | 16 ++++++++++++++++
+ arch/arm/plat-omap/include/mach/sdrc.h | 9 ++++++++-
+ 2 files changed, 24 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
+index 9e3bd4f..6a5a2c5 100644
+--- a/arch/arm/mach-omap2/sdrc.c
++++ b/arch/arm/mach-omap2/sdrc.c
+@@ -133,3 +133,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+ (1 << SDRC_POWER_PAGEPOLICY_SHIFT);
+ sdrc_write_reg(l, SDRC_POWER);
+ }
++
++void omap2_sms_write_rot_control(u32 val, unsigned ctx)
++{
++ sms_write_reg(val, SMS_ROT_CONTROL(ctx));
++}
++
++void omap2_sms_write_rot_size(u32 val, unsigned ctx)
++{
++ sms_write_reg(val, SMS_ROT_SIZE(ctx));
++}
++
++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
++{
++ sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
++}
++
+diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
+index 0be18e4..6438f0f 100644
+--- a/arch/arm/plat-omap/include/mach/sdrc.h
++++ b/arch/arm/plat-omap/include/mach/sdrc.h
+@@ -79,7 +79,10 @@
+
+ /* SMS register offsets - read/write with sms_{read,write}_reg() */
+
+-#define SMS_SYSCONFIG 0x010
++#define SMS_SYSCONFIG 0x010
++#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context)
++#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context)
++#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context)
+ /* REVISIT: fill in other SMS registers here */
+
+
+@@ -112,6 +115,10 @@ int omap2_sdrc_get_params(unsigned long r,
+ struct omap_sdrc_params **sdrc_cs0,
+ struct omap_sdrc_params **sdrc_cs1);
+
++void omap2_sms_write_rot_control(u32 val, unsigned ctx);
++void omap2_sms_write_rot_size(u32 val, unsigned ctx);
++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
++
+ #ifdef CONFIG_ARCH_OMAP2
+
+ struct memory_timings {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch
new file mode 100644
index 0000000000..0167fe2a55
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch
@@ -0,0 +1,385 @@
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Thu, 10 Sep 2009 15:11:34 +0000 (+0530)
+Subject: OMAP3: Enable DSS2 for OMAP3EVM board
+X-Git-Url: http://arago-project.org/git/people/?p=vaibhav%2Fti-psp-omap-video.git;a=commitdiff_plain;h=1022536cf655419eac21299eac837f57f8f72eef
+
+OMAP3: Enable DSS2 for OMAP3EVM board
+
+Tested -
+ - Validated all three outut interfaces (LCD, DVI and TV)
+
+TODO:
+ - Enable selection for both S-Video and Composite TV out
+ - DVI color (VPLL2_DEV_GRP should be equal to 0x7)
+---
+
+diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig
+index d5ff477..ba395a2 100644
+--- a/arch/arm/configs/omap3_evm_defconfig
++++ b/arch/arm/configs/omap3_evm_defconfig
+@@ -903,7 +903,56 @@ CONFIG_DAB=y
+ #
+ # CONFIG_VGASTATE is not set
+ CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
++CONFIG_OMAP2_DSS=y
++CONFIG_OMAP2_VRAM_SIZE=4
++# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set
++# CONFIG_OMAP2_DSS_RFBI is not set
++CONFIG_OMAP2_DSS_VENC=y
++# CONFIG_OMAP2_DSS_SDI is not set
++# CONFIG_OMAP2_DSS_DSI is not set
++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++CONFIG_FB_OMAP2=y
++# CONFIG_FB_OMAP2_DEBUG_SUPPORT is not set
++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
++CONFIG_FB_OMAP2_NUM_FBS=3
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC=y
++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
++CONFIG_PANEL_SHARP_LS037V7DW01=y
+ # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index 35f6075..5bc4bfe 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -22,6 +22,7 @@
+ #include <linux/input.h>
+ #include <linux/leds.h>
+
++#include <linux/regulator/machine.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
+ #include <linux/i2c/twl4030.h>
+@@ -38,6 +39,7 @@
+ #include <mach/common.h>
+ #include <mach/mcspi.h>
+ #include <mach/keypad.h>
++#include <mach/display.h>
+
+ #include "sdram-micron-mt46h32m32lf-6.h"
+ #include "mmc-twl4030.h"
+@@ -91,6 +93,174 @@ static inline void __init omap3evm_init_smc911x(void)
+
+ gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ);
+ }
++/*
++ * OMAP3EVM LCD Panel control signals
++ */
++#define OMAP3EVM_LCD_PANEL_LR 2
++#define OMAP3EVM_LCD_PANEL_UD 3
++#define OMAP3EVM_LCD_PANEL_INI 152
++#define OMAP3EVM_LCD_PANEL_ENVDD 153
++#define OMAP3EVM_LCD_PANEL_QVGA 154
++#define OMAP3EVM_LCD_PANEL_RESB 155
++#define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210
++#define OMAP3EVM_DVI_PANEL_EN_GPIO 199
++
++static int lcd_enabled;
++static int dvi_enabled;
++
++static void __init omap3_evm_display_init(void)
++{
++ int r;
++ r = gpio_request(OMAP3EVM_LCD_PANEL_RESB, "lcd_panel_resb");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_resb\n");
++ return;
++ }
++ gpio_direction_output(OMAP3EVM_LCD_PANEL_RESB, 1);
++
++ r = gpio_request(OMAP3EVM_LCD_PANEL_INI, "lcd_panel_ini");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_ini\n");
++ goto err_1;
++ }
++ gpio_direction_output(OMAP3EVM_LCD_PANEL_INI, 1);
++
++ r = gpio_request(OMAP3EVM_LCD_PANEL_QVGA, "lcd_panel_qvga");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_qvga\n");
++ goto err_2;
++ }
++ gpio_direction_output(OMAP3EVM_LCD_PANEL_QVGA, 0);
++
++ r = gpio_request(OMAP3EVM_LCD_PANEL_LR, "lcd_panel_lr");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_lr\n");
++ goto err_3;
++ }
++ gpio_direction_output(OMAP3EVM_LCD_PANEL_LR, 1);
++
++ r = gpio_request(OMAP3EVM_LCD_PANEL_UD, "lcd_panel_ud");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_ud\n");
++ goto err_4;
++ }
++ gpio_direction_output(OMAP3EVM_LCD_PANEL_UD, 1);
++
++ r = gpio_request(OMAP3EVM_LCD_PANEL_ENVDD, "lcd_panel_envdd");
++ if (r) {
++ printk(KERN_ERR "failed to get lcd_panel_envdd\n");
++ goto err_5;
++ }
++
++ return;
++
++err_5:
++ gpio_free(OMAP3EVM_LCD_PANEL_UD);
++err_4:
++ gpio_free(OMAP3EVM_LCD_PANEL_LR);
++err_3:
++ gpio_free(OMAP3EVM_LCD_PANEL_QVGA);
++err_2:
++ gpio_free(OMAP3EVM_LCD_PANEL_INI);
++err_1:
++ gpio_free(OMAP3EVM_LCD_PANEL_RESB);
++
++}
++
++static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++
++ gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0);
++ gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
++ lcd_enabled = 1;
++ return 0;
++}
++
++static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev)
++{
++ gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1);
++ gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
++ lcd_enabled = 0;
++}
++
++static struct omap_dss_device omap3_evm_lcd_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .driver_name = "sharp_ls_panel",
++ .phy.dpi.data_lines = 18,
++ .platform_enable = omap3_evm_enable_lcd,
++ .platform_disable = omap3_evm_disable_lcd,
++};
++
++static int omap3_evm_enable_tv(struct omap_dss_device *dssdev)
++{
++ return 0;
++}
++
++static void omap3_evm_disable_tv(struct omap_dss_device *dssdev)
++{
++}
++
++static struct omap_dss_device omap3_evm_tv_device = {
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .name = "tv",
++ .driver_name = "venc",
++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .platform_enable = omap3_evm_enable_tv,
++ .platform_disable = omap3_evm_disable_tv,
++};
++
++static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++
++ gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
++ dvi_enabled = 1;
++
++ return 0;
++}
++
++static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
++{
++ gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
++ dvi_enabled = 0;
++}
++
++static struct omap_dss_device omap3_evm_dvi_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = omap3_evm_enable_dvi,
++ .platform_disable = omap3_evm_disable_dvi,
++};
++
++static struct omap_dss_device *omap3_evm_dss_devices[] = {
++ &omap3_evm_lcd_device,
++ &omap3_evm_tv_device,
++ &omap3_evm_dvi_device,
++};
++
++static struct omap_dss_board_info omap3_evm_dss_data = {
++ .num_devices = ARRAY_SIZE(omap3_evm_dss_devices),
++ .devices = omap3_evm_dss_devices,
++ .default_device = &omap3_evm_lcd_device,
++};
++
++static struct platform_device omap3_evm_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &omap3_evm_dss_data,
++ },
++};
+
+ static struct twl4030_hsmmc_info mmc[] = {
+ {
+@@ -139,6 +309,14 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
+ * the P2 connector; notably LEDA for the LCD backlight.
+ */
+
++ /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */
++ gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL");
++ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
++
++ /* gpio + 7 == DVI Enable */
++ gpio_request(gpio + 7, "EN_DVI");
++ gpio_direction_output(gpio + 7, 0);
++
+ /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+
+@@ -190,6 +368,47 @@ static struct twl4030_madc_platform_data omap3evm_madc_data = {
+ .irq_line = 1,
+ };
+
++static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = {
++ .supply = "vdda_dac",
++ .dev = &omap3_evm_dss_device.dev,
++};
++
++/* VDAC for DSS driving S-Video */
++static struct regulator_init_data omap3_evm_vdac = {
++ .constraints = {
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .apply_uV = true,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &omap3_evm_vdda_dac_supply,
++};
++
++/* VPLL2 for digital video outputs */
++static struct regulator_consumer_supply omap3_evm_vpll2_supply = {
++ .supply = "vdvi",
++ .dev = &omap3_evm_lcd_device.dev,
++};
++
++static struct regulator_init_data omap3_evm_vpll2 = {
++ .constraints = {
++ .name = "VDVI",
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .apply_uV = true,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &omap3_evm_vpll2_supply,
++};
++
+ static struct twl4030_platform_data omap3evm_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+@@ -199,6 +418,8 @@ static struct twl4030_platform_data omap3evm_twldata = {
+ .madc = &omap3evm_madc_data,
+ .usb = &omap3evm_usb_data,
+ .gpio = &omap3evm_gpio_data,
++ .vdac = &omap3_evm_vdac,
++ .vpll2 = &omap3_evm_vpll2,
+ };
+
+ static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
+@@ -219,15 +440,6 @@ static int __init omap3_evm_i2c_init(void)
+ return 0;
+ }
+
+-static struct platform_device omap3_evm_lcd_device = {
+- .name = "omap3evm_lcd",
+- .id = -1,
+-};
+-
+-static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
+- .ctrl_name = "internal",
+-};
+-
+ static void ads7846_dev_init(void)
+ {
+ if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0)
+@@ -275,7 +487,6 @@ struct spi_board_info omap3evm_spi_board_info[] = {
+ };
+
+ static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
+- { OMAP_TAG_LCD, &omap3_evm_lcd_config },
+ };
+
+ static void __init omap3_evm_init_irq(void)
+@@ -289,7 +500,7 @@ static void __init omap3_evm_init_irq(void)
+ }
+
+ static struct platform_device *omap3_evm_devices[] __initdata = {
+- &omap3_evm_lcd_device,
++ &omap3_evm_dss_device,
+ &omap3evm_smc911x_device,
+ };
+
+@@ -310,6 +521,7 @@ static void __init omap3_evm_init(void)
+ usb_musb_init();
+ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
+ ads7846_dev_init();
++ omap3_evm_display_init();
+ }
+
+ static void __init omap3_evm_map_io(void)
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch b/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch
new file mode 100644
index 0000000000..405ea72fec
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch
@@ -0,0 +1,1151 @@
+From c87b390673167a65a52c0e8da22e2842862227f1 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 3 Aug 2009 15:06:36 +0300
+Subject: [PATCH 02/18] OMAP: OMAPFB: split omapfb.h
+
+Split arch/arm/plat-omap/include/mach/omapfb.h into two files:
+
+include/linux/omapfb.h - ioctls etc for userspace and some kernel
+ stuff for board files
+drivers/video/omap/omapfb.h - for omapfb internal use
+
+This cleans up omapfb.h and also makes it easier for the upcoming new
+DSS driver to co-exist with the old driver.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap1/board-nokia770.c | 2 +-
+ arch/arm/mach-omap2/io.c | 2 +-
+ arch/arm/plat-omap/fb.c | 2 +-
+ arch/arm/plat-omap/include/mach/omapfb.h | 398 ------------------------------
+ drivers/video/omap/blizzard.c | 2 +-
+ drivers/video/omap/dispc.c | 2 +-
+ drivers/video/omap/hwa742.c | 2 +-
+ drivers/video/omap/lcd_h3.c | 2 +-
+ drivers/video/omap/lcd_h4.c | 2 +-
+ drivers/video/omap/lcd_inn1510.c | 2 +-
+ drivers/video/omap/lcd_inn1610.c | 2 +-
+ drivers/video/omap/lcd_osk.c | 2 +-
+ drivers/video/omap/lcd_palmte.c | 2 +-
+ drivers/video/omap/lcd_palmtt.c | 2 +-
+ drivers/video/omap/lcd_palmz71.c | 2 +-
+ drivers/video/omap/lcdc.c | 3 +-
+ drivers/video/omap/omapfb.h | 227 +++++++++++++++++
+ drivers/video/omap/omapfb_main.c | 2 +-
+ drivers/video/omap/rfbi.c | 3 +-
+ drivers/video/omap/sossi.c | 2 +-
+ include/linux/omapfb.h | 197 +++++++++++++++
+ 21 files changed, 443 insertions(+), 417 deletions(-)
+ delete mode 100644 arch/arm/plat-omap/include/mach/omapfb.h
+ create mode 100644 drivers/video/omap/omapfb.h
+ create mode 100644 include/linux/omapfb.h
+
+diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
+index ed2a48a..6fbde33 100644
+--- a/arch/arm/mach-omap1/board-nokia770.c
++++ b/arch/arm/mach-omap1/board-nokia770.c
+@@ -14,6 +14,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/input.h>
+ #include <linux/clk.h>
++#include <linux/omapfb.h>
+
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
+@@ -32,7 +33,6 @@
+ #include <mach/keypad.h>
+ #include <mach/common.h>
+ #include <mach/dsp_common.h>
+-#include <mach/omapfb.h>
+ #include <mach/hwa742.h>
+ #include <mach/lcd_mipid.h>
+ #include <mach/mmc.h>
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index e9b9bcb..49199a3 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -22,13 +22,13 @@
+ #include <linux/init.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
++#include <linux/omapfb.h>
+
+ #include <asm/tlb.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <mach/sram.h>
+ #include <mach/sdrc.h>
+ #include <mach/gpmc.h>
+diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
+index 3746222..40615a6 100644
+--- a/arch/arm/plat-omap/fb.c
++++ b/arch/arm/plat-omap/fb.c
+@@ -28,13 +28,13 @@
+ #include <linux/platform_device.h>
+ #include <linux/bootmem.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach/map.h>
+
+ #include <mach/board.h>
+ #include <mach/sram.h>
+-#include <mach/omapfb.h>
+
+ #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
+deleted file mode 100644
+index 7b74d12..0000000
+--- a/arch/arm/plat-omap/include/mach/omapfb.h
++++ /dev/null
+@@ -1,398 +0,0 @@
+-/*
+- * File: arch/arm/plat-omap/include/mach/omapfb.h
+- *
+- * Framebuffer driver for TI OMAP boards
+- *
+- * Copyright (C) 2004 Nokia Corporation
+- * Author: Imre Deak <imre.deak@nokia.com>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#ifndef __OMAPFB_H
+-#define __OMAPFB_H
+-
+-#include <asm/ioctl.h>
+-#include <asm/types.h>
+-
+-/* IOCTL commands. */
+-
+-#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
+-#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
+-#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
+-#define OMAP_IO(num) _IO('O', num)
+-
+-#define OMAPFB_MIRROR OMAP_IOW(31, int)
+-#define OMAPFB_SYNC_GFX OMAP_IO(37)
+-#define OMAPFB_VSYNC OMAP_IO(38)
+-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
+-#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
+-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
+-#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
+-#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
+-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
+-#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
+-#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
+-#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
+-#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
+-#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
+-#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
+-#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
+-
+-#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+-#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+-#define OMAPFB_CAPS_PANEL_MASK 0xff000000
+-
+-#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
+-#define OMAPFB_CAPS_TEARSYNC 0x00002000
+-#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
+-#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
+-#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
+-#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
+-#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
+-#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
+-#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
+-
+-/* Values from DSP must map to lower 16-bits */
+-#define OMAPFB_FORMAT_MASK 0x00ff
+-#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
+-#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
+-#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
+-#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
+-#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
+-
+-#define OMAPFB_EVENT_READY 1
+-#define OMAPFB_EVENT_DISABLED 2
+-
+-#define OMAPFB_MEMTYPE_SDRAM 0
+-#define OMAPFB_MEMTYPE_SRAM 1
+-#define OMAPFB_MEMTYPE_MAX 1
+-
+-enum omapfb_color_format {
+- OMAPFB_COLOR_RGB565 = 0,
+- OMAPFB_COLOR_YUV422,
+- OMAPFB_COLOR_YUV420,
+- OMAPFB_COLOR_CLUT_8BPP,
+- OMAPFB_COLOR_CLUT_4BPP,
+- OMAPFB_COLOR_CLUT_2BPP,
+- OMAPFB_COLOR_CLUT_1BPP,
+- OMAPFB_COLOR_RGB444,
+- OMAPFB_COLOR_YUY422,
+-};
+-
+-struct omapfb_update_window {
+- __u32 x, y;
+- __u32 width, height;
+- __u32 format;
+- __u32 out_x, out_y;
+- __u32 out_width, out_height;
+- __u32 reserved[8];
+-};
+-
+-struct omapfb_update_window_old {
+- __u32 x, y;
+- __u32 width, height;
+- __u32 format;
+-};
+-
+-enum omapfb_plane {
+- OMAPFB_PLANE_GFX = 0,
+- OMAPFB_PLANE_VID1,
+- OMAPFB_PLANE_VID2,
+-};
+-
+-enum omapfb_channel_out {
+- OMAPFB_CHANNEL_OUT_LCD = 0,
+- OMAPFB_CHANNEL_OUT_DIGIT,
+-};
+-
+-struct omapfb_plane_info {
+- __u32 pos_x;
+- __u32 pos_y;
+- __u8 enabled;
+- __u8 channel_out;
+- __u8 mirror;
+- __u8 reserved1;
+- __u32 out_width;
+- __u32 out_height;
+- __u32 reserved2[12];
+-};
+-
+-struct omapfb_mem_info {
+- __u32 size;
+- __u8 type;
+- __u8 reserved[3];
+-};
+-
+-struct omapfb_caps {
+- __u32 ctrl;
+- __u32 plane_color;
+- __u32 wnd_color;
+-};
+-
+-enum omapfb_color_key_type {
+- OMAPFB_COLOR_KEY_DISABLED = 0,
+- OMAPFB_COLOR_KEY_GFX_DST,
+- OMAPFB_COLOR_KEY_VID_SRC,
+-};
+-
+-struct omapfb_color_key {
+- __u8 channel_out;
+- __u32 background;
+- __u32 trans_key;
+- __u8 key_type;
+-};
+-
+-enum omapfb_update_mode {
+- OMAPFB_UPDATE_DISABLED = 0,
+- OMAPFB_AUTO_UPDATE,
+- OMAPFB_MANUAL_UPDATE
+-};
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/completion.h>
+-#include <linux/interrupt.h>
+-#include <linux/fb.h>
+-#include <linux/mutex.h>
+-
+-#include <mach/board.h>
+-
+-#define OMAP_LCDC_INV_VSYNC 0x0001
+-#define OMAP_LCDC_INV_HSYNC 0x0002
+-#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
+-#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
+-#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
+-#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
+-
+-#define OMAP_LCDC_SIGNAL_MASK 0x003f
+-
+-#define OMAP_LCDC_PANEL_TFT 0x0100
+-
+-#define OMAPFB_PLANE_XRES_MIN 8
+-#define OMAPFB_PLANE_YRES_MIN 8
+-
+-#ifdef CONFIG_ARCH_OMAP1
+-#define OMAPFB_PLANE_NUM 1
+-#else
+-#define OMAPFB_PLANE_NUM 3
+-#endif
+-
+-struct omapfb_device;
+-
+-struct lcd_panel {
+- const char *name;
+- int config; /* TFT/STN, signal inversion */
+- int bpp; /* Pixel format in fb mem */
+- int data_lines; /* Lines on LCD HW interface */
+-
+- int x_res, y_res;
+- int pixel_clock; /* In kHz */
+- int hsw; /* Horizontal synchronization
+- pulse width */
+- int hfp; /* Horizontal front porch */
+- int hbp; /* Horizontal back porch */
+- int vsw; /* Vertical synchronization
+- pulse width */
+- int vfp; /* Vertical front porch */
+- int vbp; /* Vertical back porch */
+- int acb; /* ac-bias pin frequency */
+- int pcd; /* pixel clock divider.
+- Obsolete use pixel_clock instead */
+-
+- int (*init) (struct lcd_panel *panel,
+- struct omapfb_device *fbdev);
+- void (*cleanup) (struct lcd_panel *panel);
+- int (*enable) (struct lcd_panel *panel);
+- void (*disable) (struct lcd_panel *panel);
+- unsigned long (*get_caps) (struct lcd_panel *panel);
+- int (*set_bklight_level)(struct lcd_panel *panel,
+- unsigned int level);
+- unsigned int (*get_bklight_level)(struct lcd_panel *panel);
+- unsigned int (*get_bklight_max) (struct lcd_panel *panel);
+- int (*run_test) (struct lcd_panel *panel, int test_num);
+-};
+-
+-struct extif_timings {
+- int cs_on_time;
+- int cs_off_time;
+- int we_on_time;
+- int we_off_time;
+- int re_on_time;
+- int re_off_time;
+- int we_cycle_time;
+- int re_cycle_time;
+- int cs_pulse_width;
+- int access_time;
+-
+- int clk_div;
+-
+- u32 tim[5]; /* set by extif->convert_timings */
+-
+- int converted;
+-};
+-
+-struct lcd_ctrl_extif {
+- int (*init) (struct omapfb_device *fbdev);
+- void (*cleanup) (void);
+- void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
+- unsigned long (*get_max_tx_rate)(void);
+- int (*convert_timings) (struct extif_timings *timings);
+- void (*set_timings) (const struct extif_timings *timings);
+- void (*set_bits_per_cycle)(int bpc);
+- void (*write_command) (const void *buf, unsigned int len);
+- void (*read_data) (void *buf, unsigned int len);
+- void (*write_data) (const void *buf, unsigned int len);
+- void (*transfer_area) (int width, int height,
+- void (callback)(void * data), void *data);
+- int (*setup_tearsync) (unsigned pin_cnt,
+- unsigned hs_pulse_time, unsigned vs_pulse_time,
+- int hs_pol_inv, int vs_pol_inv, int div);
+- int (*enable_tearsync) (int enable, unsigned line);
+-
+- unsigned long max_transmit_size;
+-};
+-
+-struct omapfb_notifier_block {
+- struct notifier_block nb;
+- void *data;
+- int plane_idx;
+-};
+-
+-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+- unsigned long event,
+- void *fbi);
+-
+-struct omapfb_mem_region {
+- dma_addr_t paddr;
+- void *vaddr;
+- unsigned long size;
+- u8 type; /* OMAPFB_PLANE_MEM_* */
+- unsigned alloc:1; /* allocated by the driver */
+- unsigned map:1; /* kernel mapped by the driver */
+-};
+-
+-struct omapfb_mem_desc {
+- int region_cnt;
+- struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
+-};
+-
+-struct lcd_ctrl {
+- const char *name;
+- void *data;
+-
+- int (*init) (struct omapfb_device *fbdev,
+- int ext_mode,
+- struct omapfb_mem_desc *req_md);
+- void (*cleanup) (void);
+- void (*bind_client) (struct omapfb_notifier_block *nb);
+- void (*get_caps) (int plane, struct omapfb_caps *caps);
+- int (*set_update_mode)(enum omapfb_update_mode mode);
+- enum omapfb_update_mode (*get_update_mode)(void);
+- int (*setup_plane) (int plane, int channel_out,
+- unsigned long offset,
+- int screen_width,
+- int pos_x, int pos_y, int width,
+- int height, int color_mode);
+- int (*set_rotate) (int angle);
+- int (*setup_mem) (int plane, size_t size,
+- int mem_type, unsigned long *paddr);
+- int (*mmap) (struct fb_info *info,
+- struct vm_area_struct *vma);
+- int (*set_scale) (int plane,
+- int orig_width, int orig_height,
+- int out_width, int out_height);
+- int (*enable_plane) (int plane, int enable);
+- int (*update_window) (struct fb_info *fbi,
+- struct omapfb_update_window *win,
+- void (*callback)(void *),
+- void *callback_data);
+- void (*sync) (void);
+- void (*suspend) (void);
+- void (*resume) (void);
+- int (*run_test) (int test_num);
+- int (*setcolreg) (u_int regno, u16 red, u16 green,
+- u16 blue, u16 transp,
+- int update_hw_mem);
+- int (*set_color_key) (struct omapfb_color_key *ck);
+- int (*get_color_key) (struct omapfb_color_key *ck);
+-};
+-
+-enum omapfb_state {
+- OMAPFB_DISABLED = 0,
+- OMAPFB_SUSPENDED= 99,
+- OMAPFB_ACTIVE = 100
+-};
+-
+-struct omapfb_plane_struct {
+- int idx;
+- struct omapfb_plane_info info;
+- enum omapfb_color_format color_mode;
+- struct omapfb_device *fbdev;
+-};
+-
+-struct omapfb_device {
+- int state;
+- int ext_lcdc; /* Using external
+- LCD controller */
+- struct mutex rqueue_mutex;
+-
+- int palette_size;
+- u32 pseudo_palette[17];
+-
+- struct lcd_panel *panel; /* LCD panel */
+- const struct lcd_ctrl *ctrl; /* LCD controller */
+- const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
+- struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
+- interface */
+- struct device *dev;
+- struct fb_var_screeninfo new_var; /* for mode changes */
+-
+- struct omapfb_mem_desc mem_desc;
+- struct fb_info *fb_info[OMAPFB_PLANE_NUM];
+-};
+-
+-struct omapfb_platform_data {
+- struct omap_lcd_config lcd;
+- struct omapfb_mem_desc mem_desc;
+- void *ctrl_platform_data;
+-};
+-
+-#ifdef CONFIG_ARCH_OMAP1
+-extern struct lcd_ctrl omap1_lcd_ctrl;
+-#else
+-extern struct lcd_ctrl omap2_disp_ctrl;
+-#endif
+-
+-extern void omapfb_reserve_sdram(void);
+-extern void omapfb_register_panel(struct lcd_panel *panel);
+-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+-extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+- unsigned long event);
+-extern int omapfb_register_client(struct omapfb_notifier_block *nb,
+- omapfb_notifier_callback_t callback,
+- void *callback_data);
+-extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
+-extern int omapfb_update_window_async(struct fb_info *fbi,
+- struct omapfb_update_window *win,
+- void (*callback)(void *),
+- void *callback_data);
+-
+-/* in arch/arm/plat-omap/fb.c */
+-extern void omapfb_set_ctrl_platform_data(void *pdata);
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __OMAPFB_H */
+diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
+index 9dfcf39..38de019 100644
+--- a/drivers/video/omap/blizzard.c
++++ b/drivers/video/omap/blizzard.c
+@@ -27,9 +27,9 @@
+ #include <linux/clk.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+ #include <mach/blizzard.h>
+
++#include "omapfb.h"
+ #include "dispc.h"
+
+ #define MODULE_NAME "blizzard"
+diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
+index 148cbcc..f021770 100644
+--- a/drivers/video/omap/dispc.c
++++ b/drivers/video/omap/dispc.c
+@@ -26,9 +26,9 @@
+ #include <linux/io.h>
+
+ #include <mach/sram.h>
+-#include <mach/omapfb.h>
+ #include <mach/board.h>
+
++#include "omapfb.h"
+ #include "dispc.h"
+
+ #define MODULE_NAME "dispc"
+diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
+index 5d4f348..f5c5bfb 100644
+--- a/drivers/video/omap/hwa742.c
++++ b/drivers/video/omap/hwa742.c
+@@ -27,8 +27,8 @@
+ #include <linux/clk.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+ #include <mach/hwa742.h>
++#include "omapfb.h"
+
+ #define HWA742_REV_CODE_REG 0x0
+ #define HWA742_CONFIG_REG 0x2
+diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
+index 2486237..fb4cc4b 100644
+--- a/drivers/video/omap/lcd_h3.c
++++ b/drivers/video/omap/lcd_h3.c
+@@ -24,7 +24,7 @@
+ #include <linux/i2c/tps65010.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ #define MODULE_NAME "omapfb-lcd_h3"
+
+diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
+index 6ff5643..d7e9b36 100644
+--- a/drivers/video/omap/lcd_h4.c
++++ b/drivers/video/omap/lcd_h4.c
+@@ -22,7 +22,7 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+ {
+diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
+index 6953ed4..bc34607 100644
+--- a/drivers/video/omap/lcd_inn1510.c
++++ b/drivers/video/omap/lcd_inn1510.c
+@@ -24,7 +24,7 @@
+ #include <linux/io.h>
+
+ #include <mach/fpga.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int innovator1510_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
+index 4c4f7ee..3e0abda 100644
+--- a/drivers/video/omap/lcd_inn1610.c
++++ b/drivers/video/omap/lcd_inn1610.c
+@@ -23,7 +23,7 @@
+ #include <linux/platform_device.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ #define MODULE_NAME "omapfb-lcd_h3"
+
+diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
+index 379c96d..68b8668 100644
+--- a/drivers/video/omap/lcd_osk.c
++++ b/drivers/video/omap/lcd_osk.c
+@@ -25,7 +25,7 @@
+
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+ {
+diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
+index 2183173..f993457 100644
+--- a/drivers/video/omap/lcd_palmte.c
++++ b/drivers/video/omap/lcd_palmte.c
+@@ -24,7 +24,7 @@
+ #include <linux/io.h>
+
+ #include <mach/fpga.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int palmte_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
+index 57b0f6c..d4cf822 100644
+--- a/drivers/video/omap/lcd_palmtt.c
++++ b/drivers/video/omap/lcd_palmtt.c
+@@ -30,7 +30,7 @@ GPIO13 - screen blanking
+ #include <linux/io.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int palmtt_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
+index d33d78b..1382891 100644
+--- a/drivers/video/omap/lcd_palmz71.c
++++ b/drivers/video/omap/lcd_palmz71.c
+@@ -24,7 +24,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+
+-#include <mach/omapfb.h>
++#include "omapfb.h"
+
+ static int palmz71_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
+index ab39492..520ed97 100644
+--- a/drivers/video/omap/lcdc.c
++++ b/drivers/video/omap/lcdc.c
+@@ -30,10 +30,11 @@
+ #include <linux/clk.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
+ #include <asm/mach-types.h>
+
++#include "omapfb.h"
++
+ #include "lcdc.h"
+
+ #define MODULE_NAME "lcdc"
+diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
+new file mode 100644
+index 0000000..46e4714
+--- /dev/null
++++ b/drivers/video/omap/omapfb.h
+@@ -0,0 +1,227 @@
++/*
++ * File: drivers/video/omap/omapfb.h
++ *
++ * Framebuffer driver for TI OMAP boards
++ *
++ * Copyright (C) 2004 Nokia Corporation
++ * Author: Imre Deak <imre.deak@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __OMAPFB_H
++#define __OMAPFB_H
++
++#include <linux/fb.h>
++#include <linux/mutex.h>
++#include <linux/omapfb.h>
++
++#define OMAPFB_EVENT_READY 1
++#define OMAPFB_EVENT_DISABLED 2
++
++#define OMAP_LCDC_INV_VSYNC 0x0001
++#define OMAP_LCDC_INV_HSYNC 0x0002
++#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
++#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
++#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
++#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
++
++#define OMAP_LCDC_SIGNAL_MASK 0x003f
++
++#define OMAP_LCDC_PANEL_TFT 0x0100
++
++#define OMAPFB_PLANE_XRES_MIN 8
++#define OMAPFB_PLANE_YRES_MIN 8
++
++struct omapfb_device;
++
++struct lcd_panel {
++ const char *name;
++ int config; /* TFT/STN, signal inversion */
++ int bpp; /* Pixel format in fb mem */
++ int data_lines; /* Lines on LCD HW interface */
++
++ int x_res, y_res;
++ int pixel_clock; /* In kHz */
++ int hsw; /* Horizontal synchronization
++ pulse width */
++ int hfp; /* Horizontal front porch */
++ int hbp; /* Horizontal back porch */
++ int vsw; /* Vertical synchronization
++ pulse width */
++ int vfp; /* Vertical front porch */
++ int vbp; /* Vertical back porch */
++ int acb; /* ac-bias pin frequency */
++ int pcd; /* pixel clock divider.
++ Obsolete use pixel_clock instead */
++
++ int (*init) (struct lcd_panel *panel,
++ struct omapfb_device *fbdev);
++ void (*cleanup) (struct lcd_panel *panel);
++ int (*enable) (struct lcd_panel *panel);
++ void (*disable) (struct lcd_panel *panel);
++ unsigned long (*get_caps) (struct lcd_panel *panel);
++ int (*set_bklight_level)(struct lcd_panel *panel,
++ unsigned int level);
++ unsigned int (*get_bklight_level)(struct lcd_panel *panel);
++ unsigned int (*get_bklight_max) (struct lcd_panel *panel);
++ int (*run_test) (struct lcd_panel *panel, int test_num);
++};
++
++struct extif_timings {
++ int cs_on_time;
++ int cs_off_time;
++ int we_on_time;
++ int we_off_time;
++ int re_on_time;
++ int re_off_time;
++ int we_cycle_time;
++ int re_cycle_time;
++ int cs_pulse_width;
++ int access_time;
++
++ int clk_div;
++
++ u32 tim[5]; /* set by extif->convert_timings */
++
++ int converted;
++};
++
++struct lcd_ctrl_extif {
++ int (*init) (struct omapfb_device *fbdev);
++ void (*cleanup) (void);
++ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
++ unsigned long (*get_max_tx_rate)(void);
++ int (*convert_timings) (struct extif_timings *timings);
++ void (*set_timings) (const struct extif_timings *timings);
++ void (*set_bits_per_cycle)(int bpc);
++ void (*write_command) (const void *buf, unsigned int len);
++ void (*read_data) (void *buf, unsigned int len);
++ void (*write_data) (const void *buf, unsigned int len);
++ void (*transfer_area) (int width, int height,
++ void (callback)(void *data), void *data);
++ int (*setup_tearsync) (unsigned pin_cnt,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int div);
++ int (*enable_tearsync) (int enable, unsigned line);
++
++ unsigned long max_transmit_size;
++};
++
++struct omapfb_notifier_block {
++ struct notifier_block nb;
++ void *data;
++ int plane_idx;
++};
++
++typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
++ unsigned long event,
++ void *fbi);
++
++struct lcd_ctrl {
++ const char *name;
++ void *data;
++
++ int (*init) (struct omapfb_device *fbdev,
++ int ext_mode,
++ struct omapfb_mem_desc *req_md);
++ void (*cleanup) (void);
++ void (*bind_client) (struct omapfb_notifier_block *nb);
++ void (*get_caps) (int plane, struct omapfb_caps *caps);
++ int (*set_update_mode)(enum omapfb_update_mode mode);
++ enum omapfb_update_mode (*get_update_mode)(void);
++ int (*setup_plane) (int plane, int channel_out,
++ unsigned long offset,
++ int screen_width,
++ int pos_x, int pos_y, int width,
++ int height, int color_mode);
++ int (*set_rotate) (int angle);
++ int (*setup_mem) (int plane, size_t size,
++ int mem_type, unsigned long *paddr);
++ int (*mmap) (struct fb_info *info,
++ struct vm_area_struct *vma);
++ int (*set_scale) (int plane,
++ int orig_width, int orig_height,
++ int out_width, int out_height);
++ int (*enable_plane) (int plane, int enable);
++ int (*update_window) (struct fb_info *fbi,
++ struct omapfb_update_window *win,
++ void (*callback)(void *),
++ void *callback_data);
++ void (*sync) (void);
++ void (*suspend) (void);
++ void (*resume) (void);
++ int (*run_test) (int test_num);
++ int (*setcolreg) (u_int regno, u16 red, u16 green,
++ u16 blue, u16 transp,
++ int update_hw_mem);
++ int (*set_color_key) (struct omapfb_color_key *ck);
++ int (*get_color_key) (struct omapfb_color_key *ck);
++};
++
++enum omapfb_state {
++ OMAPFB_DISABLED = 0,
++ OMAPFB_SUSPENDED = 99,
++ OMAPFB_ACTIVE = 100
++};
++
++struct omapfb_plane_struct {
++ int idx;
++ struct omapfb_plane_info info;
++ enum omapfb_color_format color_mode;
++ struct omapfb_device *fbdev;
++};
++
++struct omapfb_device {
++ int state;
++ int ext_lcdc; /* Using external
++ LCD controller */
++ struct mutex rqueue_mutex;
++
++ int palette_size;
++ u32 pseudo_palette[17];
++
++ struct lcd_panel *panel; /* LCD panel */
++ const struct lcd_ctrl *ctrl; /* LCD controller */
++ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
++ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
++ interface */
++ struct device *dev;
++ struct fb_var_screeninfo new_var; /* for mode changes */
++
++ struct omapfb_mem_desc mem_desc;
++ struct fb_info *fb_info[OMAPFB_PLANE_NUM];
++};
++
++#ifdef CONFIG_ARCH_OMAP1
++extern struct lcd_ctrl omap1_lcd_ctrl;
++#else
++extern struct lcd_ctrl omap2_disp_ctrl;
++#endif
++
++extern void omapfb_register_panel(struct lcd_panel *panel);
++extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
++extern void omapfb_notify_clients(struct omapfb_device *fbdev,
++ unsigned long event);
++extern int omapfb_register_client(struct omapfb_notifier_block *nb,
++ omapfb_notifier_callback_t callback,
++ void *callback_data);
++extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
++extern int omapfb_update_window_async(struct fb_info *fbi,
++ struct omapfb_update_window *win,
++ void (*callback)(void *),
++ void *callback_data);
++
++#endif /* __OMAPFB_H */
+diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
+index 8862233..a6c4abe 100644
+--- a/drivers/video/omap/omapfb_main.c
++++ b/drivers/video/omap/omapfb_main.c
+@@ -29,8 +29,8 @@
+ #include <linux/uaccess.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
++#include "omapfb.h"
+ #include "lcdc.h"
+ #include "dispc.h"
+
+diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
+index 9332d6c..2e71446 100644
+--- a/drivers/video/omap/rfbi.c
++++ b/drivers/video/omap/rfbi.c
+@@ -27,8 +27,7 @@
+ #include <linux/clk.h>
+ #include <linux/io.h>
+
+-#include <mach/omapfb.h>
+-
++#include "omapfb.h"
+ #include "dispc.h"
+
+ /* To work around an RFBI transfer rate limitation */
+diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
+index a769462..6853627 100644
+--- a/drivers/video/omap/sossi.c
++++ b/drivers/video/omap/sossi.c
+@@ -25,8 +25,8 @@
+ #include <linux/io.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
++#include "omapfb.h"
+ #include "lcdc.h"
+
+ #define MODULE_NAME "omapfb-sossi"
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+new file mode 100644
+index 0000000..a3611d3
+--- /dev/null
++++ b/include/linux/omapfb.h
+@@ -0,0 +1,197 @@
++/*
++ * File: include/linux/omapfb.h
++ *
++ * Framebuffer driver for TI OMAP boards
++ *
++ * Copyright (C) 2004 Nokia Corporation
++ * Author: Imre Deak <imre.deak@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __LINUX_OMAPFB_H__
++#define __LINUX_OMAPFB_H__
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++/* IOCTL commands. */
++
++#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
++#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
++#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
++#define OMAP_IO(num) _IO('O', num)
++
++#define OMAPFB_MIRROR OMAP_IOW(31, int)
++#define OMAPFB_SYNC_GFX OMAP_IO(37)
++#define OMAPFB_VSYNC OMAP_IO(38)
++#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
++#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
++#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
++#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
++#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
++#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
++#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
++#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
++#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
++#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
++#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
++#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
++#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
++
++#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
++#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
++#define OMAPFB_CAPS_PANEL_MASK 0xff000000
++
++#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
++#define OMAPFB_CAPS_TEARSYNC 0x00002000
++#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
++#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
++#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
++#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
++#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
++#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
++#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
++
++/* Values from DSP must map to lower 16-bits */
++#define OMAPFB_FORMAT_MASK 0x00ff
++#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
++#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
++#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
++#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
++#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
++
++#define OMAPFB_MEMTYPE_SDRAM 0
++#define OMAPFB_MEMTYPE_SRAM 1
++#define OMAPFB_MEMTYPE_MAX 1
++
++enum omapfb_color_format {
++ OMAPFB_COLOR_RGB565 = 0,
++ OMAPFB_COLOR_YUV422,
++ OMAPFB_COLOR_YUV420,
++ OMAPFB_COLOR_CLUT_8BPP,
++ OMAPFB_COLOR_CLUT_4BPP,
++ OMAPFB_COLOR_CLUT_2BPP,
++ OMAPFB_COLOR_CLUT_1BPP,
++ OMAPFB_COLOR_RGB444,
++ OMAPFB_COLOR_YUY422,
++};
++
++struct omapfb_update_window {
++ __u32 x, y;
++ __u32 width, height;
++ __u32 format;
++ __u32 out_x, out_y;
++ __u32 out_width, out_height;
++ __u32 reserved[8];
++};
++
++struct omapfb_update_window_old {
++ __u32 x, y;
++ __u32 width, height;
++ __u32 format;
++};
++
++enum omapfb_plane {
++ OMAPFB_PLANE_GFX = 0,
++ OMAPFB_PLANE_VID1,
++ OMAPFB_PLANE_VID2,
++};
++
++enum omapfb_channel_out {
++ OMAPFB_CHANNEL_OUT_LCD = 0,
++ OMAPFB_CHANNEL_OUT_DIGIT,
++};
++
++struct omapfb_plane_info {
++ __u32 pos_x;
++ __u32 pos_y;
++ __u8 enabled;
++ __u8 channel_out;
++ __u8 mirror;
++ __u8 reserved1;
++ __u32 out_width;
++ __u32 out_height;
++ __u32 reserved2[12];
++};
++
++struct omapfb_mem_info {
++ __u32 size;
++ __u8 type;
++ __u8 reserved[3];
++};
++
++struct omapfb_caps {
++ __u32 ctrl;
++ __u32 plane_color;
++ __u32 wnd_color;
++};
++
++enum omapfb_color_key_type {
++ OMAPFB_COLOR_KEY_DISABLED = 0,
++ OMAPFB_COLOR_KEY_GFX_DST,
++ OMAPFB_COLOR_KEY_VID_SRC,
++};
++
++struct omapfb_color_key {
++ __u8 channel_out;
++ __u32 background;
++ __u32 trans_key;
++ __u8 key_type;
++};
++
++enum omapfb_update_mode {
++ OMAPFB_UPDATE_DISABLED = 0,
++ OMAPFB_AUTO_UPDATE,
++ OMAPFB_MANUAL_UPDATE
++};
++
++#ifdef __KERNEL__
++
++#include <mach/board.h>
++
++#ifdef CONFIG_ARCH_OMAP1
++#define OMAPFB_PLANE_NUM 1
++#else
++#define OMAPFB_PLANE_NUM 3
++#endif
++
++struct omapfb_mem_region {
++ u32 paddr;
++ void __iomem *vaddr;
++ unsigned long size;
++ u8 type; /* OMAPFB_PLANE_MEM_* */
++ unsigned alloc:1; /* allocated by the driver */
++ unsigned map:1; /* kernel mapped by the driver */
++};
++
++struct omapfb_mem_desc {
++ int region_cnt;
++ struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
++};
++
++struct omapfb_platform_data {
++ struct omap_lcd_config lcd;
++ struct omapfb_mem_desc mem_desc;
++ void *ctrl_platform_data;
++};
++
++/* in arch/arm/plat-omap/fb.c */
++extern void omapfb_set_ctrl_platform_data(void *pdata);
++extern void omapfb_reserve_sdram(void);
++
++#endif
++
++#endif /* __OMAPFB_H */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch b/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch
new file mode 100644
index 0000000000..f05929088f
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch
@@ -0,0 +1,152 @@
+From bcb3cd3f6dd8d80a4f7cc524b769d711addfc48d Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Wed, 22 Jul 2009 23:49:29 +0530
+Subject: [PATCH 2/5] V4L2: Added New V4L2 CIDs for omap devices V4L2 IOCTL
+
+Changes -
+ - Renamed V4L2_CID_ROTATION to V4L2_CID_ROTATE
+ - Implementationadded for VIDIOC_S/G_COLOR_SPACE_CONV
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/media/video/v4l2-ioctl.c | 19 +++++++++++++++++++
+ include/linux/videodev2.h | 21 ++++++++++++++++++---
+ include/media/v4l2-ioctl.h | 4 ++++
+ 3 files changed, 41 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
+index f2afc4e..74d2ed9 100644
+--- a/drivers/media/video/v4l2-ioctl.c
++++ b/drivers/media/video/v4l2-ioctl.c
+@@ -278,6 +278,8 @@ static const char *v4l2_ioctls[] = {
+ [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
+ [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
+ #endif
++ [_IOC_NR(VIDIOC_S_COLOR_SPACE_CONV)] = "VIDIOC_S_COLOR_SPACE_CONV",
++ [_IOC_NR(VIDIOC_G_COLOR_SPACE_CONV)] = "VIDIOC_G_COLOR_SPACE_CONV",
+ };
+ #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
+
+@@ -1784,6 +1786,23 @@ static long __video_do_ioctl(struct file *file,
+ break;
+ }
+
++ /*---------------Color space conversion------------------------------*/
++ case VIDIOC_S_COLOR_SPACE_CONV:
++ {
++ struct v4l2_color_space_conversion *p = arg;
++ if (!ops->vidioc_s_color_space_conv)
++ break;
++ ret = ops->vidioc_s_color_space_conv(file, fh, p);
++ break;
++ }
++ case VIDIOC_G_COLOR_SPACE_CONV:
++ {
++ struct v4l2_color_space_conversion *p = arg;
++ if (!ops->vidioc_g_color_space_conv)
++ break;
++ ret = ops->vidioc_g_color_space_conv(file, fh, p);
++ break;
++ }
+ default:
+ {
+ if (!ops->vidioc_default)
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 74f1687..78e8158 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -554,6 +554,7 @@ struct v4l2_framebuffer {
+ #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
+ #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
+ #define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
++#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080
+ /* Flags for the 'flags' field. */
+ #define V4L2_FBUF_FLAG_PRIMARY 0x0001
+ #define V4L2_FBUF_FLAG_OVERLAY 0x0002
+@@ -561,6 +562,7 @@ struct v4l2_framebuffer {
+ #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
+ #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
+ #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
++#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040
+
+ struct v4l2_clip {
+ struct v4l2_rect c;
+@@ -902,6 +904,8 @@ enum v4l2_colorfx {
+
+ /* last CID + 1 */
+ #define V4L2_CID_LASTP1 (V4L2_CID_BASE+33)
++#define V4L2_CID_ROTATE (V4L2_CID_BASE+34)
++#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35)
+
+ /* MPEG-class control IDs defined by V4L2 */
+ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
+@@ -1213,6 +1217,18 @@ struct v4l2_hw_freq_seek {
+ };
+
+ /*
++ * Color conversion
++ * User needs to pass pointer to color conversion matrix
++ * defined by hardware
++ */
++struct v4l2_color_space_conversion {
++ __s32 coefficients[3][3];
++ __s32 const_factor;
++ __s32 input_offs[3];
++ __s32 output_offs[3];
++};
++
++/*
+ * A U D I O
+ */
+ struct v4l2_audio {
+@@ -1265,7 +1281,6 @@ struct v4l2_enc_idx {
+ struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES];
+ };
+
+-
+ #define V4L2_ENC_CMD_START (0)
+ #define V4L2_ENC_CMD_STOP (1)
+ #define V4L2_ENC_CMD_PAUSE (2)
+@@ -1286,7 +1301,6 @@ struct v4l2_encoder_cmd {
+
+ #endif
+
+-
+ /*
+ * D A T A S E R V I C E S ( V B I )
+ *
+@@ -1423,7 +1437,6 @@ struct v4l2_format {
+ } fmt;
+ };
+
+-
+ /* Stream type-dependent parameters
+ */
+ struct v4l2_streamparm {
+@@ -1551,6 +1564,8 @@ struct v4l2_dbg_chip_ident {
+ #endif
+
+ #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
++#define VIDIOC_S_COLOR_SPACE_CONV _IOW('V', 83, struct v4l2_color_space_conversion)
++#define VIDIOC_G_COLOR_SPACE_CONV _IOR('V', 84, struct v4l2_color_space_conversion)
+ /* Reminder: when adding new ioctls please add support for them to
+ drivers/media/video/v4l2-compat-ioctl32.c as well! */
+
+diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
+index 7a4529d..6f46d09 100644
+--- a/include/media/v4l2-ioctl.h
++++ b/include/media/v4l2-ioctl.h
+@@ -242,6 +242,10 @@ struct v4l2_ioctl_ops {
+ /* For other private ioctls */
+ long (*vidioc_default) (struct file *file, void *fh,
+ int cmd, void *arg);
++ int (*vidioc_s_color_space_conv) (struct file *file, void *fh,
++ struct v4l2_color_space_conversion *a);
++ int (*vidioc_g_color_space_conv) (struct file *file, void *fh,
++ struct v4l2_color_space_conversion *a);
+ };
+
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch b/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch
new file mode 100644
index 0000000000..fb9928cfce
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch
@@ -0,0 +1,136 @@
+From 40b33143283fda49f0be9113b952c1d77e1c709a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 18 Jun 2009 13:02:39 +0300
+Subject: [PATCH 03/18] OMAP: OMAPFB: add omapdss device
+
+The upcoming new display subsystem driver is divided to two devices,
+omapdss and omapfb, of which omapdss handles the actual hardware.
+
+This patch adds a dummy omapdss platform device for the current omapfb
+driver, which is then used to get the clocks. This will make it possible
+for the current and the new display drivers to co-exist.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/clock24xx.c | 8 ++++----
+ arch/arm/mach-omap2/clock34xx.c | 14 +++++++-------
+ drivers/video/omap/dispc.c | 19 ++++++++++++++++---
+ 3 files changed, 27 insertions(+), 14 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
+index bc5d3ac..8cb8368 100644
+--- a/arch/arm/mach-omap2/clock24xx.c
++++ b/arch/arm/mach-omap2/clock24xx.c
+@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = {
+ CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
+ CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
+ /* DSS domain clocks */
+- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X),
+- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
+- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
+- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
++ CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X),
++ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
++ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
++ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
+ /* L3 domain clocks */
+ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X),
+ CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X),
+diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
+index cd7819c..aff72ea 100644
+--- a/arch/arm/mach-omap2/clock34xx.c
++++ b/arch/arm/mach-omap2/clock34xx.c
+@@ -235,13 +235,13 @@ static struct omap_clk omap34xx_clks[] = {
+ CLK("omap_rng", "ick", &rng_ick, CK_343X),
+ CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
+ CLK(NULL, "des1_ick", &des1_ick, CK_343X),
+- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
+- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
+- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X),
+- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X),
+- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X),
+- CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1),
+- CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2),
++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
++ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
++ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
++ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
++ CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
++ CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2),
+ CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
+ CLK(NULL, "cam_ick", &cam_ick, CK_343X),
+ CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
+diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
+index f021770..d383888 100644
+--- a/drivers/video/omap/dispc.c
++++ b/drivers/video/omap/dispc.c
+@@ -24,6 +24,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/clk.h>
+ #include <linux/io.h>
++#include <linux/platform_device.h>
+
+ #include <mach/sram.h>
+ #include <mach/board.h>
+@@ -184,6 +185,11 @@ static struct {
+ struct omapfb_color_key color_key;
+ } dispc;
+
++static struct platform_device omapdss_device = {
++ .name = "omapdss",
++ .id = -1,
++};
++
+ static void enable_lcd_clocks(int enable);
+
+ static void inline dispc_write_reg(int idx, u32 val)
+@@ -880,20 +886,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
+
+ static int get_dss_clocks(void)
+ {
+- dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick");
++ dispc.dss_ick = clk_get(&omapdss_device.dev, "ick");
+ if (IS_ERR(dispc.dss_ick)) {
+ dev_err(dispc.fbdev->dev, "can't get ick\n");
+ return PTR_ERR(dispc.dss_ick);
+ }
+
+- dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck");
++ dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck");
+ if (IS_ERR(dispc.dss1_fck)) {
+ dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
+ clk_put(dispc.dss_ick);
+ return PTR_ERR(dispc.dss1_fck);
+ }
+
+- dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck");
++ dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck");
+ if (IS_ERR(dispc.dss_54m_fck)) {
+ dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
+ clk_put(dispc.dss_ick);
+@@ -1349,6 +1355,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
+ int skip_init = 0;
+ int i;
+
++ r = platform_device_register(&omapdss_device);
++ if (r) {
++ dev_err(fbdev->dev, "can't register omapdss device\n");
++ return r;
++ }
++
+ memset(&dispc, 0, sizeof(dispc));
+
+ dispc.base = ioremap(DISPC_BASE, SZ_1K);
+@@ -1490,6 +1502,7 @@ static void omap_dispc_cleanup(void)
+ enable_interface_clocks(0);
+ put_dss_clocks();
+ iounmap(dispc.base);
++ platform_device_unregister(&omapdss_device);
+ }
+
+ const struct lcd_ctrl omap2_int_ctrl = {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch b/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch
new file mode 100644
index 0000000000..0fd8135bb1
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch
@@ -0,0 +1,40 @@
+From 691a4534df820b6c90a37de1941197efbe86984a Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Fri, 21 Aug 2009 11:19:46 +0530
+Subject: [PATCH 3/5] V4L2: Updated v4l2_common for new V4L2 CIDs.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/media/video/v4l2-common.c | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
+index b91d66a..5dae426 100644
+--- a/drivers/media/video/v4l2-common.c
++++ b/drivers/media/video/v4l2-common.c
+@@ -421,6 +421,8 @@ const char *v4l2_ctrl_get_name(u32 id)
+ case V4L2_CID_CHROMA_AGC: return "Chroma AGC";
+ case V4L2_CID_COLOR_KILLER: return "Color Killer";
+ case V4L2_CID_COLORFX: return "Color Effects";
++ case V4L2_CID_ROTATE: return "Rotate";
++ case V4L2_CID_BG_COLOR: return "Background color";
+
+ /* MPEG controls */
+ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
+@@ -546,6 +548,13 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
+ qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ min = max = step = def = 0;
+ break;
++ case V4L2_CID_BG_COLOR:
++ qctrl->type = V4L2_CTRL_TYPE_INTEGER;
++ step = 1;
++ min = 0;
++ /* Max is calculated as RGB888 that is 2^12*/
++ max = 0xFFFFFF;
++ break;
+ default:
+ qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+ break;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch
new file mode 100644
index 0000000000..47eab0fa7d
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch
@@ -0,0 +1,840 @@
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 09:01:55 +0000 (+0300)
+Subject: OMAP: Add VRAM manager
+X-Git-Url: http://arago-project.org/git/people/?p=vaibhav%2Fti-psp-omap-video.git;a=commitdiff_plain;h=9e5a02f69fe2261ac928aa956add6f1c9f48386d
+
+OMAP: Add VRAM manager
+
+Add a Video RAM manager for OMAP 2 and 3 platforms. VRAM manager is used
+to allocate large continuous blocks of SDRAM or SRAM. The features VRAM
+manager has that are missing from dma_alloc_* functions are:
+
+- Support for OMAP2's SRAM
+- Allocate without ioremapping
+- Allocate at defined physical addresses
+- Allows larger VRAM area and larger allocations
+
+The upcoming DSS2 uses VRAM manager.
+
+VRAM area size can be defined in kernel config, board file or with
+kernel boot parameters. Board file definition overrides kernel config,
+and boot parameter overrides kernel config and board file.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index 4a08ad3..e5dd736 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -33,6 +33,7 @@
+ #include <mach/sdrc.h>
+ #include <mach/gpmc.h>
+ #include <mach/serial.h>
++#include <mach/vram.h>
+
+ #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */
+ #include "clock.h"
+@@ -246,6 +247,7 @@ void __init omap2_map_common_io(void)
+ omap2_check_revision();
+ omap_sram_init();
+ omapfb_reserve_sdram();
++ omap_vram_reserve_sdram();
+ }
+
+ /*
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+new file mode 100644
+index 0000000..fe72f81
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -0,0 +1,63 @@
++/*
++ * VRAM manager for OMAP
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __OMAP_VRAM_H__
++#define __OMAP_VRAM_H__
++
++#include <linux/autoconf.h>
++#include <linux/types.h>
++
++#define OMAP_VRAM_MEMTYPE_SDRAM 0
++#define OMAP_VRAM_MEMTYPE_SRAM 1
++#define OMAP_VRAM_MEMTYPE_MAX 1
++
++extern int omap_vram_add_region(unsigned long paddr, size_t size);
++extern int omap_vram_free(unsigned long paddr, size_t size);
++extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
++extern int omap_vram_reserve(unsigned long paddr, size_t size);
++extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
++ unsigned long *largest_free_block);
++
++#ifdef CONFIG_OMAP2_VRAM
++extern void omap_vram_set_sdram_vram(u32 size, u32 start);
++extern void omap_vram_set_sram_vram(u32 size, u32 start);
++
++extern void omap_vram_reserve_sdram(void);
++extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail);
++#else
++static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
++static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
++
++static inline void omap_vram_reserve_sdram(void) { }
++static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail)
++{
++ return 0;
++}
++#endif
++
++#endif
+diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
+index 925f647..cda311b 100644
+--- a/arch/arm/plat-omap/sram.c
++++ b/arch/arm/plat-omap/sram.c
+@@ -28,6 +28,7 @@
+ #include <mach/sram.h>
+ #include <mach/board.h>
+ #include <mach/cpu.h>
++#include <mach/vram.h>
+
+ #include <mach/control.h>
+
+@@ -185,6 +186,13 @@ void __init omap_detect_sram(void)
+ omap_sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ);
+ omap_sram_size -= reserved;
++
++ reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
++ omap_sram_size,
++ omap_sram_start + SRAM_BOOTLOADER_SZ,
++ omap_sram_size - SRAM_BOOTLOADER_SZ);
++ omap_sram_size -= reserved;
++
+ omap_sram_ceil = omap_sram_base + omap_sram_size;
+ }
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 3b54b39..e09367a 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2149,6 +2149,7 @@ config FB_BROADSHEET
+ a bridge adapter.
+
+ source "drivers/video/omap/Kconfig"
++source "drivers/video/omap2/Kconfig"
+
+ source "drivers/video/backlight/Kconfig"
+ source "drivers/video/display/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 01a819f..cc7f5c8 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -123,6 +123,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
+ obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+ obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
+ obj-$(CONFIG_FB_OMAP) += omap/
++obj-y += omap2/
+ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+ obj-$(CONFIG_FB_CARMINE) += carminefb.o
+ obj-$(CONFIG_FB_MB862XX) += mb862xx/
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+new file mode 100644
+index 0000000..7a6c4c9
+--- /dev/null
++++ b/drivers/video/omap2/Kconfig
+@@ -0,0 +1,2 @@
++config OMAP2_VRAM
++ bool
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+new file mode 100644
+index 0000000..7fdf7bd
+--- /dev/null
++++ b/drivers/video/omap2/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_OMAP2_VRAM) += vram.o
+diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
+new file mode 100644
+index 0000000..634ce23
+--- /dev/null
++++ b/drivers/video/omap2/vram.c
+@@ -0,0 +1,655 @@
++/*
++ * VRAM manager for OMAP
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*#define DEBUG*/
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/list.h>
++#include <linux/seq_file.h>
++#include <linux/bootmem.h>
++#include <linux/completion.h>
++#include <linux/debugfs.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++
++#include <asm/setup.h>
++
++#include <mach/sram.h>
++#include <mach/vram.h>
++#include <mach/dma.h>
++
++#ifdef DEBUG
++#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define OMAP2_SRAM_START 0x40200000
++/* Maximum size, in reality this is smaller if SRAM is partially locked. */
++#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
++
++/* postponed regions are used to temporarily store region information at boot
++ * time when we cannot yet allocate the region list */
++#define MAX_POSTPONED_REGIONS 10
++
++static bool vram_initialized;
++static int postponed_cnt;
++static struct {
++ unsigned long paddr;
++ size_t size;
++} postponed_regions[MAX_POSTPONED_REGIONS];
++
++struct vram_alloc {
++ struct list_head list;
++ unsigned long paddr;
++ unsigned pages;
++};
++
++struct vram_region {
++ struct list_head list;
++ struct list_head alloc_list;
++ unsigned long paddr;
++ unsigned pages;
++};
++
++static DEFINE_MUTEX(region_mutex);
++static LIST_HEAD(region_list);
++
++static inline int region_mem_type(unsigned long paddr)
++{
++ if (paddr >= OMAP2_SRAM_START &&
++ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
++ return OMAP_VRAM_MEMTYPE_SRAM;
++ else
++ return OMAP_VRAM_MEMTYPE_SDRAM;
++}
++
++static struct vram_region *omap_vram_create_region(unsigned long paddr,
++ unsigned pages)
++{
++ struct vram_region *rm;
++
++ rm = kzalloc(sizeof(*rm), GFP_KERNEL);
++
++ if (rm) {
++ INIT_LIST_HEAD(&rm->alloc_list);
++ rm->paddr = paddr;
++ rm->pages = pages;
++ }
++
++ return rm;
++}
++
++#if 0
++static void omap_vram_free_region(struct vram_region *vr)
++{
++ list_del(&vr->list);
++ kfree(vr);
++}
++#endif
++
++static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
++ unsigned long paddr, unsigned pages)
++{
++ struct vram_alloc *va;
++ struct vram_alloc *new;
++
++ new = kzalloc(sizeof(*va), GFP_KERNEL);
++
++ if (!new)
++ return NULL;
++
++ new->paddr = paddr;
++ new->pages = pages;
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ if (va->paddr > new->paddr)
++ break;
++ }
++
++ list_add_tail(&new->list, &va->list);
++
++ return new;
++}
++
++static void omap_vram_free_allocation(struct vram_alloc *va)
++{
++ list_del(&va->list);
++ kfree(va);
++}
++
++int omap_vram_add_region(unsigned long paddr, size_t size)
++{
++ struct vram_region *rm;
++ unsigned pages;
++
++ if (vram_initialized) {
++ DBG("adding region paddr %08lx size %d\n",
++ paddr, size);
++
++ size &= PAGE_MASK;
++ pages = size >> PAGE_SHIFT;
++
++ rm = omap_vram_create_region(paddr, pages);
++ if (rm == NULL)
++ return -ENOMEM;
++
++ list_add(&rm->list, &region_list);
++ } else {
++ if (postponed_cnt == MAX_POSTPONED_REGIONS)
++ return -ENOMEM;
++
++ postponed_regions[postponed_cnt].paddr = paddr;
++ postponed_regions[postponed_cnt].size = size;
++
++ ++postponed_cnt;
++ }
++ return 0;
++}
++
++int omap_vram_free(unsigned long paddr, size_t size)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++ unsigned start, end;
++
++ DBG("free mem paddr %08lx size %d\n", paddr, size);
++
++ size = PAGE_ALIGN(size);
++
++ mutex_lock(&region_mutex);
++
++ list_for_each_entry(rm, &region_list, list) {
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ start = alloc->paddr;
++ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
++
++ if (start >= paddr && end < paddr + size)
++ goto found;
++ }
++ }
++
++ mutex_unlock(&region_mutex);
++ return -EINVAL;
++
++found:
++ omap_vram_free_allocation(alloc);
++
++ mutex_unlock(&region_mutex);
++ return 0;
++}
++EXPORT_SYMBOL(omap_vram_free);
++
++static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++ size_t size;
++
++ size = pages << PAGE_SHIFT;
++
++ list_for_each_entry(rm, &region_list, list) {
++ unsigned long start, end;
++
++ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
++
++ if (region_mem_type(rm->paddr) != region_mem_type(paddr))
++ continue;
++
++ start = rm->paddr;
++ end = start + (rm->pages << PAGE_SHIFT) - 1;
++ if (start > paddr || end < paddr + size - 1)
++ continue;
++
++ DBG("block ok, checking allocs\n");
++
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ end = alloc->paddr - 1;
++
++ if (start <= paddr && end >= paddr + size - 1)
++ goto found;
++
++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
++ }
++
++ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
++
++ if (!(start <= paddr && end >= paddr + size - 1))
++ continue;
++found:
++ DBG("found area start %lx, end %lx\n", start, end);
++
++ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
++ return -ENOMEM;
++
++ return 0;
++ }
++
++ return -ENOMEM;
++}
++
++int omap_vram_reserve(unsigned long paddr, size_t size)
++{
++ unsigned pages;
++ int r;
++
++ DBG("reserve mem paddr %08lx size %d\n", paddr, size);
++
++ size = PAGE_ALIGN(size);
++ pages = size >> PAGE_SHIFT;
++
++ mutex_lock(&region_mutex);
++
++ r = _omap_vram_reserve(paddr, pages);
++
++ mutex_unlock(&region_mutex);
++
++ return r;
++}
++EXPORT_SYMBOL(omap_vram_reserve);
++
++static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
++{
++ struct completion *compl = data;
++ complete(compl);
++}
++
++static int _omap_vram_clear(u32 paddr, unsigned pages)
++{
++ struct completion compl;
++ unsigned elem_count;
++ unsigned frame_count;
++ int r;
++ int lch;
++
++ init_completion(&compl);
++
++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
++ _omap_vram_dma_cb,
++ &compl, &lch);
++ if (r) {
++ pr_err("VRAM: request_dma failed for memory clear\n");
++ return -EBUSY;
++ }
++
++ elem_count = pages * PAGE_SIZE / 4;
++ frame_count = 1;
++
++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
++ elem_count, frame_count,
++ OMAP_DMA_SYNC_ELEMENT,
++ 0, 0);
++
++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
++ paddr, 0, 0);
++
++ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
++
++ omap_start_dma(lch);
++
++ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
++ omap_stop_dma(lch);
++ pr_err("VRAM: dma timeout while clearing memory\n");
++ r = -EIO;
++ goto err;
++ }
++
++ r = 0;
++err:
++ omap_free_dma(lch);
++
++ return r;
++}
++
++static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++
++ list_for_each_entry(rm, &region_list, list) {
++ unsigned long start, end;
++
++ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
++
++ if (region_mem_type(rm->paddr) != mtype)
++ continue;
++
++ start = rm->paddr;
++
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ end = alloc->paddr;
++
++ if (end - start >= pages << PAGE_SHIFT)
++ goto found;
++
++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
++ }
++
++ end = rm->paddr + (rm->pages << PAGE_SHIFT);
++found:
++ if (end - start < pages << PAGE_SHIFT)
++ continue;
++
++ DBG("found %lx, end %lx\n", start, end);
++
++ alloc = omap_vram_create_allocation(rm, start, pages);
++ if (alloc == NULL)
++ return -ENOMEM;
++
++ *paddr = start;
++
++ _omap_vram_clear(start, pages);
++
++ return 0;
++ }
++
++ return -ENOMEM;
++}
++
++int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
++{
++ unsigned pages;
++ int r;
++
++ BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size);
++
++ DBG("alloc mem type %d size %d\n", mtype, size);
++
++ size = PAGE_ALIGN(size);
++ pages = size >> PAGE_SHIFT;
++
++ mutex_lock(&region_mutex);
++
++ r = _omap_vram_alloc(mtype, pages, paddr);
++
++ mutex_unlock(&region_mutex);
++
++ return r;
++}
++EXPORT_SYMBOL(omap_vram_alloc);
++
++void omap_vram_get_info(unsigned long *vram,
++ unsigned long *free_vram,
++ unsigned long *largest_free_block)
++{
++ struct vram_region *vr;
++ struct vram_alloc *va;
++
++ *vram = 0;
++ *free_vram = 0;
++ *largest_free_block = 0;
++
++ mutex_lock(&region_mutex);
++
++ list_for_each_entry(vr, &region_list, list) {
++ unsigned free;
++ unsigned long pa;
++
++ pa = vr->paddr;
++ *vram += vr->pages << PAGE_SHIFT;
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ free = va->paddr - pa;
++ *free_vram += free;
++ if (free > *largest_free_block)
++ *largest_free_block = free;
++ pa = va->paddr + (va->pages << PAGE_SHIFT);
++ }
++
++ free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
++ *free_vram += free;
++ if (free > *largest_free_block)
++ *largest_free_block = free;
++ }
++
++ mutex_unlock(&region_mutex);
++}
++EXPORT_SYMBOL(omap_vram_get_info);
++
++#if defined(CONFIG_DEBUG_FS)
++static int vram_debug_show(struct seq_file *s, void *unused)
++{
++ struct vram_region *vr;
++ struct vram_alloc *va;
++ unsigned size;
++
++ mutex_lock(&region_mutex);
++
++ list_for_each_entry(vr, &region_list, list) {
++ size = vr->pages << PAGE_SHIFT;
++ seq_printf(s, "%08lx-%08lx (%d bytes)\n",
++ vr->paddr, vr->paddr + size - 1,
++ size);
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ size = va->pages << PAGE_SHIFT;
++ seq_printf(s, " %08lx-%08lx (%d bytes)\n",
++ va->paddr, va->paddr + size - 1,
++ size);
++ }
++ }
++
++ mutex_unlock(&region_mutex);
++
++ return 0;
++}
++
++static int vram_debug_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, vram_debug_show, inode->i_private);
++}
++
++static const struct file_operations vram_debug_fops = {
++ .open = vram_debug_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init omap_vram_create_debugfs(void)
++{
++ struct dentry *d;
++
++ d = debugfs_create_file("vram", S_IRUGO, NULL,
++ NULL, &vram_debug_fops);
++ if (IS_ERR(d))
++ return PTR_ERR(d);
++
++ return 0;
++}
++#endif
++
++static __init int omap_vram_init(void)
++{
++ int i;
++
++ vram_initialized = 1;
++
++ for (i = 0; i < postponed_cnt; i++)
++ omap_vram_add_region(postponed_regions[i].paddr,
++ postponed_regions[i].size);
++
++#ifdef CONFIG_DEBUG_FS
++ if (omap_vram_create_debugfs())
++ pr_err("VRAM: Failed to create debugfs file\n");
++#endif
++
++ return 0;
++}
++
++arch_initcall(omap_vram_init);
++
++/* boottime vram alloc stuff */
++
++/* set from board file */
++static u32 omap_vram_sram_start __initdata;
++static u32 omap_vram_sram_size __initdata;
++
++/* set from board file */
++static u32 omap_vram_sdram_start __initdata;
++static u32 omap_vram_sdram_size __initdata;
++
++/* set from kernel cmdline */
++static u32 omap_vram_def_sdram_size __initdata;
++static u32 omap_vram_def_sdram_start __initdata;
++
++static void __init omap_vram_early_vram(char **p)
++{
++ omap_vram_def_sdram_size = memparse(*p, p);
++ if (**p == ',')
++ omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16);
++}
++__early_param("vram=", omap_vram_early_vram);
++
++/*
++ * Called from map_io. We need to call to this early enough so that we
++ * can reserve the fixed SDRAM regions before VM could get hold of them.
++ */
++void __init omap_vram_reserve_sdram(void)
++{
++ struct bootmem_data *bdata;
++ unsigned long sdram_start, sdram_size;
++ u32 paddr;
++ u32 size = 0;
++
++ /* cmdline arg overrides the board file definition */
++ if (omap_vram_def_sdram_size) {
++ size = omap_vram_def_sdram_size;
++ paddr = omap_vram_def_sdram_start;
++ }
++
++ if (!size) {
++ size = omap_vram_sdram_size;
++ paddr = omap_vram_sdram_start;
++ }
++
++#ifdef CONFIG_OMAP2_VRAM_SIZE
++ if (!size) {
++ size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
++ paddr = 0;
++ }
++#endif
++
++ if (!size)
++ return;
++
++ size = PAGE_ALIGN(size);
++
++ bdata = NODE_DATA(0)->bdata;
++ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
++ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
++
++ if (paddr) {
++ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
++ paddr + size > sdram_start + sdram_size) {
++ pr_err("Illegal SDRAM region for VRAM\n");
++ return;
++ }
++
++ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
++ pr_err("FB: failed to reserve VRAM\n");
++ return;
++ }
++ } else {
++ if (size > sdram_size) {
++ pr_err("Illegal SDRAM size for VRAM\n");
++ return;
++ }
++
++ paddr = virt_to_phys(alloc_bootmem_pages(size));
++ BUG_ON(paddr & ~PAGE_MASK);
++ }
++
++ omap_vram_add_region(paddr, size);
++
++ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
++}
++
++/*
++ * Called at sram init time, before anything is pushed to the SRAM stack.
++ * Because of the stack scheme, we will allocate everything from the
++ * start of the lowest address region to the end of SRAM. This will also
++ * include padding for page alignment and possible holes between regions.
++ *
++ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
++ * this point, since the driver built as a module would have problem with
++ * freeing / reallocating the regions.
++ */
++unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail)
++{
++ unsigned long pend_avail;
++ unsigned long reserved;
++ u32 paddr;
++ u32 size;
++
++ paddr = omap_vram_sram_start;
++ size = omap_vram_sram_size;
++
++ if (!size)
++ return 0;
++
++ reserved = 0;
++ pend_avail = pstart_avail + size_avail;
++
++ if (!paddr) {
++ /* Dynamic allocation */
++ if ((size_avail & PAGE_MASK) < size) {
++ pr_err("Not enough SRAM for VRAM\n");
++ return 0;
++ }
++ size_avail = (size_avail - size) & PAGE_MASK;
++ paddr = pstart_avail + size_avail;
++ }
++
++ if (paddr < sram_pstart ||
++ paddr + size > sram_pstart + sram_size) {
++ pr_err("Illegal SRAM region for VRAM\n");
++ return 0;
++ }
++
++ /* Reserve everything above the start of the region. */
++ if (pend_avail - paddr > reserved)
++ reserved = pend_avail - paddr;
++ size_avail = pend_avail - reserved - pstart_avail;
++
++ omap_vram_add_region(paddr, size);
++
++ if (reserved)
++ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
++
++ return reserved;
++}
++
++void __init omap_vram_set_sdram_vram(u32 size, u32 start)
++{
++ omap_vram_sdram_start = start;
++ omap_vram_sdram_size = size;
++}
++
++void __init omap_vram_set_sram_vram(u32 size, u32 start)
++{
++ omap_vram_sram_start = start;
++ omap_vram_sram_size = size;
++}
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch
new file mode 100644
index 0000000000..5db9c65d41
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch
@@ -0,0 +1,3248 @@
+From 2ae2dbacb82c5f0cb0fbcde7b49510d5cf2d45b5 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Wed, 12 Aug 2009 19:38:30 +0530
+Subject: [PATCH 4/5] OMAP2/3 V4L2: Add support for OMAP2/3 V4L2 driver on top of DSS2
+
+Features Supported -
+ 1. Provides V4L2 user interface for the video pipelines of DSS
+ 2. Basic streaming working on LCD, DVI and TV.
+ 3. Works on latest DSS2 library from Tomi
+ 4. Support for various pixel formats like YUV, UYVY, RGB32, RGB24,
+ RGB565
+ 5. Supports Alpha blending.
+ 6. Supports Color keying both source and destination.
+ 7. Supports rotation.
+ 8. Supports cropping.
+ 9. Supports Background color setting.
+
+TODO:
+ 1. Complete Testing is pending, only basic test passed.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/plat-omap/devices.c | 29 +
+ drivers/media/video/Kconfig | 12 +
+ drivers/media/video/Makefile | 2 +
+ drivers/media/video/omap/Kconfig | 22 +
+ drivers/media/video/omap/Makefile | 2 +
+ drivers/media/video/omap/omap_vout.c | 2623 +++++++++++++++++++++++++++++++
+ drivers/media/video/omap/omap_voutdef.h | 148 ++
+ drivers/media/video/omap/omap_voutlib.c | 258 +++
+ drivers/media/video/omap/omap_voutlib.h | 34 +
+ 9 files changed, 3130 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/omap/Kconfig
+ create mode 100644 drivers/media/video/omap/Makefile
+ create mode 100644 drivers/media/video/omap/omap_vout.c
+ create mode 100644 drivers/media/video/omap/omap_voutdef.h
+ create mode 100644 drivers/media/video/omap/omap_voutlib.c
+ create mode 100644 drivers/media/video/omap/omap_voutlib.h
+
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
+index a64b692..8b6a9a0 100644
+--- a/arch/arm/plat-omap/devices.c
++++ b/arch/arm/plat-omap/devices.c
+@@ -357,6 +357,34 @@ static void omap_init_rng(void)
+ static inline void omap_init_rng(void) {}
+ #endif
+
++/*---------------------------------------------------------------------------*/
++
++#if defined(CONFIG_VIDEO_OMAP_VIDEOOUT) || \
++ defined(CONFIG_VIDEO_OMAP_VIDEOOUT_MODULE)
++#ifdef CONFIG_FB_OMAP2
++static struct resource omap3evm_vout_resource[3 - CONFIG_FB_OMAP2_NUM_FBS] = {
++};
++#else
++static struct resource omap3evm_vout_resource[2] = {
++};
++#endif
++
++static struct platform_device omap3evm_vout_device = {
++ .name = "omap_vout",
++ .num_resources = ARRAY_SIZE(omap3evm_vout_resource),
++ .resource = &omap3evm_vout_resource[0],
++ .id = -1,
++};
++static void omap_init_vout(void)
++{
++ (void) platform_device_register(&omap3evm_vout_device);
++}
++#else
++static inline void omap_init_vout(void) {}
++#endif
++
++/*---------------------------------------------------------------------------*/
++
+ /*
+ * This gets called after board-specific INIT_MACHINE, and initializes most
+ * on-chip peripherals accessible on this board (except for few like USB):
+@@ -387,6 +415,7 @@ static int __init omap_init_devices(void)
+ omap_init_uwire();
+ omap_init_wdt();
+ omap_init_rng();
++ omap_init_vout();
+ return 0;
+ }
+ arch_initcall(omap_init_devices);
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index dcf9fa9..afb4478 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -718,6 +718,18 @@ config VIDEO_CAFE_CCIC
+ CMOS camera controller. This is the controller found on first-
+ generation OLPC systems.
+
++config VIDEO_OMAP3
++ bool "OMAP2/OMAP3 Camera and V4L2-DSS drivers"
++ select VIDEOBUF_GEN
++ select VIDEOBUF_DMA_SG
++ select OMAP2_DSS
++ depends on VIDEO_DEV && (ARCH_OMAP24XX || ARCH_OMAP34XX)
++ default y
++ ---help---
++ V4L2 DSS and Camera driver support for OMAP2/3 based boards.
++
++source "drivers/media/video/omap/Kconfig"
++
+ config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA && I2C
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index 9f2e321..36040b9 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -117,6 +117,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
+
+ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+
++obj-$(CONFIG_VIDEO_OMAP3) += omap/
++
+ obj-$(CONFIG_USB_DABUSB) += dabusb.o
+ obj-$(CONFIG_USB_OV511) += ov511.o
+ obj-$(CONFIG_USB_SE401) += se401.o
+diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig
+new file mode 100644
+index 0000000..5b86db3
+--- /dev/null
++++ b/drivers/media/video/omap/Kconfig
+@@ -0,0 +1,22 @@
++config VIDEO_OMAP_VIDEOOUT
++ tristate "OMAP Video out driver"
++ select VIDEOBUF_DMA_SG
++ select VIDEOBUF_GEN
++ depends on VIDEO_OMAP3
++ default VIDEO_OMAP3
++
++choice
++ prompt "TV Mode"
++ default NTSC_M
++
++config NTSC_M
++ bool "Use NTSC_M mode"
++ help
++ Select this option if you want NTSC_M mode on TV
++
++config PAL_BDGHI
++ bool "Use PAL_BDGHI mode"
++ help
++ Select this option if you want PAL_BDGHI mode on TV
++
++endchoice
+diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
+new file mode 100644
+index 0000000..18854c7
+--- /dev/null
++++ b/drivers/media/video/omap/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_VIDEO_OMAP_VIDEOOUT) += omap_vout.o omap_voutlib.o
++
+diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
+new file mode 100644
+index 0000000..7e15db2
+--- /dev/null
++++ b/drivers/media/video/omap/omap_vout.c
+@@ -0,0 +1,2623 @@
++/*
++ * drivers/media/video/omap/omap_vout.c
++ *
++ * Copyright (C) 2005-2009 Texas Instruments.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ *
++ * Leveraged code from the OMAP2 camera driver
++ * Video-for-Linux (Version 2) camera capture driver for
++ * the OMAP24xx camera controller.
++ *
++ * Author: Andy Lowe (source@mvista.com)
++ *
++ * Copyright (C) 2004 MontaVista Software, Inc.
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ * History:
++ * 20-APR-2006 Khasim Modified VRFB based Rotation,
++ * The image data is always read from 0 degree
++ * view and written
++ * to the virtual space of desired rotation angle
++ * 4-DEC-2006 Jian Changed to support better memory management
++ *
++ * 17-Nov-2008 Hardik Changed to used the new DSS paches by Tomi
++ * Changed driver to use video_ioctl2
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/vmalloc.h>
++#include <linux/interrupt.h>
++#include <linux/kdev_t.h>
++#include <linux/types.h>
++#include <linux/wait.h>
++#include <linux/videodev2.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/irq.h>
++
++#include <media/videobuf-dma-sg.h>
++#include <media/v4l2-dev.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-device.h>
++
++#include <asm/processor.h>
++#include <mach/dma.h>
++#include <mach/vram.h>
++#include <mach/vrfb.h>
++#include <mach/display.h>
++
++#include "omap_voutlib.h"
++#include "omap_voutdef.h"
++
++MODULE_AUTHOR("Texas Instruments.");
++MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
++MODULE_LICENSE("GPL");
++
++#define OMAP_VIDEO1 0
++#define OMAP_VIDEO2 1
++
++/* configuration macros */
++#define VOUT_NAME "omap_vout"
++
++#define QQVGA_WIDTH 160
++#define QQVGA_HEIGHT 120
++
++#define NUM_OF_VIDEO_CHANNELS 2
++
++#define VID_MAX_WIDTH 1280 /* Largest width */
++#define VID_MAX_HEIGHT 720/* Largest height */
++
++/* Mimimum requirement is 2x2 for DSS */
++#define VID_MIN_WIDTH 2
++#define VID_MIN_HEIGHT 2
++
++/* 2048 x 2048 is max res supported by OMAP display controller */
++#define DMA_CHAN_ALLOTED 1
++#define DMA_CHAN_NOT_ALLOTED 0
++#define MAX_PIXELS_PER_LINE 2048
++#define VRFB_TX_TIMEOUT 1000
++
++/* IRQ Bits mask of DSS */
++#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
++
++static struct videobuf_queue_ops video_vbq_ops;
++
++static u32 video1_numbuffers = 3;
++static u32 video2_numbuffers = 3;
++static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
++static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
++static u32 vid1_static_vrfb_alloc;
++static u32 vid2_static_vrfb_alloc;
++static int debug;
++
++/* Module parameters */
++module_param(video1_numbuffers, uint, S_IRUGO);
++MODULE_PARM_DESC(video1_numbuffers,
++ "Number of buffers to be allocated at init time for Video1 device.");
++
++module_param(video2_numbuffers, uint, S_IRUGO);
++MODULE_PARM_DESC(video2_numbuffers,
++ "Number of buffers to be allocated at init time for Video2 device.");
++
++module_param(video1_bufsize, uint, S_IRUGO);
++MODULE_PARM_DESC(video1_bufsize,
++ "Size of the buffer to be allocated for video1 device");
++
++module_param(video2_bufsize, uint, S_IRUGO);
++MODULE_PARM_DESC(video2_bufsize,
++ "Size of the buffer to be allocated for video2 device");
++
++module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
++MODULE_PARM_DESC(vid1_static_vrfb_alloc,
++ "Static allocation of the VRFB buffer for video1 device");
++
++module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
++MODULE_PARM_DESC(vid2_static_vrfb_alloc,
++ "Static allocation of the VRFB buffer for video2 device");
++
++module_param(debug, bool, S_IRUGO);
++MODULE_PARM_DESC(debug, "Debug level (0-1)");
++
++/* Local Helper functions */
++static void omap_vout_isr(void *arg, unsigned int irqstatus);
++static void omap_vout_cleanup_device(struct omap_vout_device *vout);
++/*
++ * Maximum amount of memory to use for rendering buffers.
++ * Default is enough to four (RGB24) DVI 720P buffers.
++ */
++#define MAX_ALLOWED_VIDBUFFERS 4
++
++/* list of image formats supported by OMAP2 video pipelines */
++const static struct v4l2_fmtdesc omap_formats[] = {
++ {
++ /* Note: V4L2 defines RGB565 as:
++ *
++ * Byte 0 Byte 1
++ * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3
++ *
++ * We interpret RGB565 as:
++ *
++ * Byte 0 Byte 1
++ * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3
++ */
++ .description = "RGB565, le",
++ .pixelformat = V4L2_PIX_FMT_RGB565,
++ },
++ {
++ /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use
++ * this for RGB24 unpack mode, the last 8 bits are ignored
++ * */
++ .description = "RGB32, le",
++ .pixelformat = V4L2_PIX_FMT_RGB32,
++ },
++ {
++ /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use
++ * this for RGB24 packed mode
++ *
++ */
++ .description = "RGB24, le",
++ .pixelformat = V4L2_PIX_FMT_RGB24,
++ },
++ {
++ .description = "YUYV (YUV 4:2:2), packed",
++ .pixelformat = V4L2_PIX_FMT_YUYV,
++ },
++ {
++ .description = "UYVY, packed",
++ .pixelformat = V4L2_PIX_FMT_UYVY,
++ },
++};
++
++#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
++
++/* Allocate buffers */
++static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
++{
++ unsigned long virt_addr, addr;
++ u32 order, size;
++
++ size = PAGE_ALIGN(buf_size);
++ order = get_order(size);
++ virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
++ addr = virt_addr;
++
++ if (virt_addr) {
++ while (size > 0) {
++ SetPageReserved(virt_to_page(addr));
++ addr += PAGE_SIZE;
++ size -= PAGE_SIZE;
++ }
++ }
++ *phys_addr = (u32) virt_to_phys((void *) virt_addr);
++ return virt_addr;
++}
++
++/* Free buffers */
++static void omap_vout_free_buffer(unsigned long virtaddr, u32 phys_addr,
++ u32 buf_size)
++{
++ unsigned long addr = virtaddr;
++ u32 order, size;
++
++ size = PAGE_ALIGN(buf_size);
++ order = get_order(size);
++
++ while (size > 0) {
++ ClearPageReserved(virt_to_page(addr));
++ addr += PAGE_SIZE;
++ size -= PAGE_SIZE;
++ }
++ free_pages((unsigned long) virtaddr, order);
++}
++
++/* Function for allocating video buffers */
++static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout,
++ unsigned int *count, int startindex)
++{
++ int i, j;
++
++ for (i = 0; i < *count; i++) {
++ if (!vout->smsshado_virt_addr[i]) {
++ vout->smsshado_virt_addr[i] =
++ omap_vout_alloc_buffer(vout->smsshado_size,
++ &vout->smsshado_phy_addr[i]);
++ }
++ if (!vout->smsshado_virt_addr[i] && startindex != -1) {
++ if (V4L2_MEMORY_MMAP == vout->memory
++ && i >= startindex)
++ break;
++ }
++ if (!vout->smsshado_virt_addr[i]) {
++ for (j = 0; j < i; j++) {
++ omap_vout_free_buffer(
++ vout->smsshado_virt_addr[j],
++ vout->smsshado_phy_addr[j],
++ vout->smsshado_size);
++ vout->smsshado_virt_addr[j] = 0;
++ vout->smsshado_phy_addr[j] = 0;
++ }
++ *count = 0;
++ return -ENOMEM;
++ }
++ memset((void *) vout->smsshado_virt_addr[i], 0,
++ vout->smsshado_size);
++ }
++ return 0;
++}
++
++/* Try format */
++static int omap_vout_try_format(struct v4l2_pix_format *pix)
++{
++ int ifmt, bpp = 0;
++
++ pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
++ (u32)VID_MAX_HEIGHT);
++ pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
++
++ for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
++ if (pix->pixelformat == omap_formats[ifmt].pixelformat)
++ break;
++ }
++
++ if (ifmt == NUM_OUTPUT_FORMATS)
++ ifmt = 0;
++
++ pix->pixelformat = omap_formats[ifmt].pixelformat;
++ pix->field = V4L2_FIELD_ANY;
++ pix->priv = 0;
++
++ switch (pix->pixelformat) {
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_UYVY:
++ default:
++ pix->colorspace = V4L2_COLORSPACE_JPEG;
++ bpp = YUYV_BPP;
++ break;
++ case V4L2_PIX_FMT_RGB565:
++ case V4L2_PIX_FMT_RGB565X:
++ pix->colorspace = V4L2_COLORSPACE_SRGB;
++ bpp = RGB565_BPP;
++ break;
++ case V4L2_PIX_FMT_RGB24:
++ pix->colorspace = V4L2_COLORSPACE_SRGB;
++ bpp = RGB24_BPP;
++ break;
++ case V4L2_PIX_FMT_RGB32:
++ case V4L2_PIX_FMT_BGR32:
++ pix->colorspace = V4L2_COLORSPACE_SRGB;
++ bpp = RGB32_BPP;
++ break;
++ }
++ pix->bytesperline = pix->width * bpp;
++ pix->sizeimage = pix->bytesperline * pix->height;
++ return bpp;
++}
++
++/*
++ * omap_vout_uservirt_to_phys: This inline function is used to convert user
++ * space virtual address to physical address.
++ */
++static inline u32 omap_vout_uservirt_to_phys(u32 virtp)
++{
++ unsigned long physp = 0;
++ struct mm_struct *mm = current->mm;
++ struct vm_area_struct *vma;
++
++ vma = find_vma(mm, virtp);
++ /* For kernel direct-mapped memory, take the easy way */
++ if (virtp >= PAGE_OFFSET) {
++ physp = virt_to_phys((void *) virtp);
++ } else if (vma && (vma->vm_flags & VM_IO)
++ && vma->vm_pgoff) {
++ /* this will catch, kernel-allocated,
++ mmaped-to-usermode addresses */
++ physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
++ } else {
++ /* otherwise, use get_user_pages() for general userland pages */
++ int res, nr_pages = 1;
++ struct page *pages;
++ down_read(&current->mm->mmap_sem);
++
++ res = get_user_pages(current, current->mm, virtp, nr_pages,
++ 1, 0, &pages, NULL);
++ up_read(&current->mm->mmap_sem);
++
++ if (res == nr_pages) {
++ physp = __pa(page_address(&pages[0]) +
++ (virtp & ~PAGE_MASK));
++ } else {
++ printk(KERN_WARNING VOUT_NAME
++ "get_user_pages failed\n");
++ return 0;
++ }
++ }
++
++ return physp;
++}
++
++/* This functions wakes up the application once
++ * the DMA transfer to VRFB space is completed. */
++static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data)
++{
++ struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data;
++
++ t->tx_status = 1;
++ wake_up_interruptible(&t->wait);
++}
++
++/* Release the VRFB context once the module exits */
++static void omap_vout_release_vrfb(struct omap_vout_device *vout)
++{
++ int i;
++
++ for (i = 0; i < 4; i++)
++ omap_vrfb_release_ctx(&vout->vrfb_context[i]);
++
++ if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
++ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
++ omap_free_dma(vout->vrfb_dma_tx.dma_ch);
++ }
++
++}
++
++/* Return true if rotation is 90 or 270 */
++static inline int rotate_90_or_270(const struct omap_vout_device *vout)
++{
++ return (vout->rotation == dss_rotation_90_degree ||
++ vout->rotation == dss_rotation_270_degree);
++}
++
++/* Return true if rotation is enabled */
++static inline int rotation_enabled(const struct omap_vout_device *vout)
++{
++ return vout->rotation || vout->mirror;
++}
++
++/* Reverse the rotation degree if mirroring is enabled */
++static inline int calc_rotation(const struct omap_vout_device *vout)
++{
++ if (!vout->mirror)
++ return vout->rotation;
++
++ switch (vout->rotation) {
++ case dss_rotation_90_degree:
++ return dss_rotation_270_degree;
++ case dss_rotation_270_degree:
++ return dss_rotation_90_degree;
++ case dss_rotation_180_degree:
++ return dss_rotation_0_degree;
++ default:
++ return dss_rotation_180_degree;
++ }
++}
++
++/* Free the V4L2 buffers */
++static void omap_vout_free_buffers(struct omap_vout_device *vout)
++{
++ int i, numbuffers;
++
++ /* Allocate memory for the buffers */
++ numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers;
++ vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize;
++
++ for (i = 0; i < numbuffers; i++) {
++ omap_vout_free_buffer(vout->buf_virt_addr[i],
++ vout->buf_phy_addr[i], vout->buffer_size);
++ vout->buf_phy_addr[i] = 0;
++ vout->buf_virt_addr[i] = 0;
++ }
++}
++
++/* Free VRFB buffers */
++static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
++{
++ int j;
++
++ for (j = 0; j < 4; j++) {
++ omap_vout_free_buffer(vout->smsshado_virt_addr[j],
++ vout->smsshado_phy_addr[j],
++ vout->smsshado_size);
++ vout->smsshado_virt_addr[j] = 0;
++ vout->smsshado_phy_addr[j] = 0;
++ }
++}
++
++/* Allocate the buffers for the VRFB space. Data is copied from V4L2
++ * buffers to the VRFB buffers using the DMA engine.*/
++static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
++ unsigned int *count, unsigned int startindex)
++{
++ int i;
++ bool yuv_mode;
++
++ /* Allocate the VRFB buffers only if the buffers are not
++ * allocated during init time.
++ */
++ if ((rotation_enabled(vout)) &&
++ !vout->vrfb_static_allocation)
++ if (omap_vout_allocate_vrfb_buffers(vout, count, startindex))
++ return -ENOMEM;
++
++ if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 ||
++ vout->dss_mode == OMAP_DSS_COLOR_UYVY)
++ yuv_mode = true;
++ else
++ yuv_mode = false;
++
++ for (i = 0; i < *count; i++) {
++ omap_vrfb_setup(&vout->vrfb_context[i],
++ vout->smsshado_phy_addr[i],
++ vout->pix.width, vout->pix.height,
++ vout->bpp, yuv_mode);
++ }
++ return 0;
++}
++
++/* Convert V4L2 rotation to DSS rotation
++ * V4L2 understand 0, 90, 180, 270.
++ * convert to 0, 1, 2 and 3 repsectively for DSS */
++static int v4l2_rot_to_dss_rot(int v4l2_rotation, enum dss_rotation *rotation,
++ bool mirror)
++{
++ switch (v4l2_rotation) {
++ case 90:
++ *rotation = dss_rotation_90_degree;
++ return 0;
++ case 180:
++ *rotation = dss_rotation_180_degree;
++ return 0;
++ case 270:
++ *rotation = dss_rotation_270_degree;
++ return 0;
++ case 0:
++ *rotation = dss_rotation_0_degree;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++
++}
++
++/* Calculate the buffer offsets from which the streaming should
++ * start. This offset calculation is mainly required because of
++ * the VRFB 32 pixels alignment with rotation
++ */
++static int omap_vout_calculate_offset(struct omap_vout_device *vout)
++{
++ struct v4l2_pix_format *pix = &vout->pix;
++ struct v4l2_rect *crop = &vout->crop;
++ enum dss_rotation rotation;
++ bool mirroring = vout->mirror;
++ int vr_ps = 1, ps = 2, temp_ps = 2;
++ int offset = 0, ctop = 0, cleft = 0, line_length = 0;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ struct omap_dss_device *cur_display;
++ int *cropped_offset = &vout->cropped_offset;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++ /* get the display device attached to the overlay */
++ if (!ovl->manager || !ovl->manager->device)
++ return -1;
++ cur_display = ovl->manager->device;
++
++ rotation = calc_rotation(vout);
++
++ if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
++ V4L2_PIX_FMT_UYVY == pix->pixelformat) {
++ if (rotation_enabled(vout)) {
++ /*
++ * ps - Actual pixel size for YUYV/UYVY for
++ * VRFB/Mirroring is 4 bytes
++ * vr_ps - Virtually pixel size for YUYV/UYVY is
++ * 2 bytes
++ */
++ ps = 4;
++ vr_ps = 2;
++ } else {
++ ps = 2; /* otherwise the pixel size is 2 byte */
++ }
++ } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) {
++ ps = 4;
++ } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) {
++ ps = 3;
++ }
++ vout->ps = ps;
++ vout->vr_ps = vr_ps;
++ if (rotation_enabled(vout)) {
++ line_length = MAX_PIXELS_PER_LINE;
++ ctop = (pix->height - crop->height) - crop->top;
++ cleft = (pix->width - crop->width) - crop->left;
++ } else {
++ line_length = pix->width;
++ }
++ vout->line_length = line_length;
++ switch (rotation) {
++ case dss_rotation_90_degree:
++ offset = vout->vrfb_context[0].yoffset *
++ vout->vrfb_context[0].bytespp;
++ temp_ps = ps / vr_ps;
++ if (mirroring == 0) {
++ *cropped_offset = offset + line_length *
++ temp_ps * cleft + crop->top * temp_ps;
++ } else {
++ *cropped_offset = offset + line_length * temp_ps *
++ cleft + crop->top * temp_ps + (line_length *
++ ((crop->width / (vr_ps)) - 1) * ps);
++ }
++ break;
++ case dss_rotation_180_degree:
++ offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset *
++ vout->vrfb_context[0].bytespp) +
++ (vout->vrfb_context[0].xoffset *
++ vout->vrfb_context[0].bytespp));
++ if (mirroring == 0) {
++ *cropped_offset = offset + (line_length * ps * ctop) +
++ (cleft / vr_ps) * ps;
++
++ } else {
++ *cropped_offset = offset + (line_length * ps * ctop) +
++ (cleft / vr_ps) * ps + (line_length *
++ (crop->height - 1) * ps);
++ }
++ break;
++ case dss_rotation_270_degree:
++ offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset *
++ vout->vrfb_context[0].bytespp;
++ temp_ps = ps / vr_ps;
++ if (mirroring == 0) {
++ *cropped_offset = offset + line_length *
++ temp_ps * crop->left + ctop * ps;
++ } else {
++ *cropped_offset = offset + line_length *
++ temp_ps * crop->left + ctop * ps +
++ (line_length * ((crop->width / vr_ps) - 1) *
++ ps);
++ }
++ break;
++ case dss_rotation_0_degree:
++ if (mirroring == 0) {
++ *cropped_offset = (line_length * ps) *
++ crop->top + (crop->left / vr_ps) * ps;
++ } else {
++ *cropped_offset = (line_length * ps) *
++ crop->top + (crop->left / vr_ps) * ps +
++ (line_length * (crop->height - 1) * ps);
++ }
++ break;
++ default:
++ *cropped_offset = (line_length * ps * crop->top) /
++ vr_ps + (crop->left * ps) / vr_ps +
++ ((crop->width / vr_ps) - 1) * ps;
++ break;
++ }
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ "%s Offset:%x\n", __func__, *cropped_offset);
++ return 0;
++}
++
++/* convert V4L2 pixel format to DSS pixel format */
++static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device
++ *vout)
++{
++ struct omap_overlay *ovl;
++ struct omapvideo_info *ovid;
++ struct v4l2_pix_format *pix = &vout->pix;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ switch (pix->pixelformat) {
++ case 0:
++ break;
++ case V4L2_PIX_FMT_YUYV:
++ return OMAP_DSS_COLOR_YUV2;
++
++ case V4L2_PIX_FMT_UYVY:
++ return OMAP_DSS_COLOR_UYVY;
++
++ case V4L2_PIX_FMT_RGB565:
++ return OMAP_DSS_COLOR_RGB16;
++
++ case V4L2_PIX_FMT_RGB24:
++ return OMAP_DSS_COLOR_RGB24P;
++
++ case V4L2_PIX_FMT_RGB32:
++ return (ovl->id == OMAP_DSS_VIDEO1) ?
++ OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
++ case V4L2_PIX_FMT_BGR32:
++ return OMAP_DSS_COLOR_RGBX32;
++
++ default:
++ return -EINVAL;
++ }
++ return -EINVAL;
++}
++
++/* Setup the overlay */
++int omapvid_setup_overlay(struct omap_vout_device *vout,
++ struct omap_overlay *ovl, int posx, int posy, int outw,
++ int outh, u32 addr)
++{
++ int r = 0;
++ enum omap_color_mode mode = 0;
++ enum dss_rotation rotation;
++ bool mirror;
++ int cropheight, cropwidth, pixheight, pixwidth;
++ struct omap_overlay_info info;
++
++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
++ (outw != vout->pix.width || outh != vout->pix.height)) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ vout->dss_mode = video_mode_to_dss_mode(vout);
++
++ if (mode == -EINVAL) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ rotation = vout->rotation;
++ mirror = vout->mirror;
++
++ /* Setup the input plane parameters according to
++ * rotation value selected.
++ */
++ if (rotate_90_or_270(vout)) {
++ cropheight = vout->crop.width;
++ cropwidth = vout->crop.height;
++ pixheight = vout->pix.width;
++ pixwidth = vout->pix.height;
++ } else {
++ cropheight = vout->crop.height;
++ cropwidth = vout->crop.width;
++ pixheight = vout->pix.height;
++ pixwidth = vout->pix.width;
++ }
++
++ ovl->get_overlay_info(ovl, &info);
++ info.paddr = addr;
++ info.vaddr = NULL;
++ info.width = cropwidth;
++ info.height = cropheight;
++ info.color_mode = vout->dss_mode;
++ info.mirror = mirror;
++ info.pos_x = posx;
++ info.pos_y = posy;
++ info.out_width = outw;
++ info.out_height = outh;
++ info.global_alpha = vout->win.global_alpha;
++ if (!rotation_enabled(vout)) {
++ info.rotation = 0;
++ info.rotation_type = OMAP_DSS_ROT_DMA;
++ info.screen_width = pixwidth;
++ } else {
++ info.rotation = vout->rotation;
++ info.rotation_type = OMAP_DSS_ROT_VRFB;
++ info.screen_width = 2048;
++ }
++
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ "%s info.enable=%d info.addr=%x info.width=%d\n info.height=%d "
++ "info.color_mode=%d info.rotation=%d info.mirror=%d\n "
++ "info.posx=%d info.posy=%d info.out_width = %d info.out_height=%d\n "
++ "info.rotation_type=%d info.screen_width=%d\n", __func__, info.enabled,
++ info.paddr, info.width, info.height, info.color_mode, info.rotation,
++ info.mirror, info.pos_x, info.pos_y, info.out_width, info.out_height,
++ info.rotation_type, info.screen_width);
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ goto err;
++
++ return 0;
++err:
++ printk(KERN_WARNING VOUT_NAME "setup_overlay failed\n");
++ return r;
++}
++
++/* Initialize the overlay structure */
++int omapvid_init(struct omap_vout_device *vout, u32 addr)
++{
++ int r = 0;
++ struct omapvideo_info *ovid = &vout->vid_info;
++ struct omap_overlay *ovl;
++ int posx, posy;
++ int outw, outh, temp, rotation;
++ int i;
++ struct v4l2_window *win;
++ struct omap_video_timings *timing;
++
++ win = &vout->win;
++ rotation = vout->rotation;
++ for (i = 0; i < ovid->num_overlays; i++) {
++ ovl = ovid->overlays[i];
++ if (!ovl->manager || !ovl->manager->device)
++ return -EINVAL;
++
++ timing = &ovl->manager->device->panel.timings;
++
++ outw = win->w.width;
++ outh = win->w.height;
++ switch (rotation) {
++ case dss_rotation_90_degree:
++ /* Invert the height and width for 90
++ * and 270 degree rotation
++ */
++ temp = outw;
++ outw = outh;
++ outh = temp;
++ posy = (timing->y_res - win->w.width)-
++ win->w.left;
++ posx = win->w.top;
++ break;
++
++ case dss_rotation_180_degree:
++ posx = (timing->x_res - win->w.width) -
++ win->w.left;
++ posy = (timing->y_res - win->w.height) -
++ win->w.top;
++ break;
++
++ case dss_rotation_270_degree:
++ temp = outw;
++ outw = outh;
++ outh = temp;
++ posy = win->w.left;
++ posx = (timing->x_res - win->w.height)
++ - win->w.top;
++ break;
++
++ default:
++ posx = win->w.left;
++ posy = win->w.top;
++ break;
++ }
++
++ r = omapvid_setup_overlay(vout, ovl, posx, posy, outw,
++ outh, addr);
++ if (r)
++ goto err;
++ }
++ return 0;
++err:
++ printk(KERN_WARNING VOUT_NAME "apply_changes failed\n");
++ return r;
++}
++
++/* Apply the changes set the go bit of DSS */
++int omapvid_apply_changes(struct omap_vout_device *vout)
++{
++ struct omapvideo_info *ovid = &vout->vid_info;
++ struct omap_overlay *ovl;
++ int i;
++
++ for (i = 0; i < ovid->num_overlays; i++) {
++ ovl = ovid->overlays[i];
++ if (!ovl->manager || !ovl->manager->device)
++ return -EINVAL;
++ ovl->manager->apply(ovl->manager);
++ }
++ return 0;
++
++}
++
++/* Video buffer call backs */
++
++/* Buffer setup function is called by videobuf layer when REQBUF ioctl is
++ * called. This is used to setup buffers and return size and count of
++ * buffers allocated. After the call to this buffer, videobuf layer will
++ * setup buffer queue depending on the size and count of buffers
++ */
++static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
++ unsigned int *size)
++{
++ struct omap_vout_device *vout = q->priv_data;
++ int startindex = 0, i, j;
++ u32 phy_addr = 0, virt_addr = 0;
++
++ if (!vout)
++ return -EINVAL;
++
++ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
++ return -EINVAL;
++
++ startindex = (vout->vid == OMAP_VIDEO1) ?
++ video1_numbuffers : video2_numbuffers;
++ if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex)
++ *count = startindex;
++
++ if ((rotation_enabled(vout))
++ && *count > 4)
++ *count = 4;
++
++ /* If rotation is enabled, allocate memory for VRFB space also */
++ if (rotation_enabled(vout)) {
++ if (omap_vout_vrfb_buffer_setup(vout, count, startindex))
++ return -ENOMEM;
++ }
++
++ if (V4L2_MEMORY_MMAP != vout->memory)
++ return 0;
++
++ /* Now allocated the V4L2 buffers */
++ *size = vout->buffer_size;
++ startindex = (vout->vid == OMAP_VIDEO1) ?
++ video1_numbuffers : video2_numbuffers;
++ for (i = startindex; i < *count; i++) {
++ vout->buffer_size = *size;
++
++ virt_addr = omap_vout_alloc_buffer(vout->buffer_size,
++ &phy_addr);
++ if (!virt_addr) {
++ if (!rotation_enabled(vout))
++ break;
++ /* Free the VRFB buffers if no space for V4L2 buffers */
++ for (j = i; j < *count; j++) {
++ omap_vout_free_buffer(
++ vout->smsshado_virt_addr[j],
++ vout->smsshado_phy_addr[j],
++ vout->smsshado_size);
++ vout->smsshado_virt_addr[j] = 0;
++ vout->smsshado_phy_addr[j] = 0;
++ }
++ }
++ vout->buf_virt_addr[i] = virt_addr;
++ vout->buf_phy_addr[i] = phy_addr;
++ }
++ *count = vout->buffer_allocated = i;
++ return 0;
++}
++
++/* Free the V4L2 buffers additionally allocated than default
++ * number of buffers and free all the VRFB buffers */
++static void omap_vout_free_allbuffers(struct omap_vout_device *vout)
++{
++ int num_buffers = 0, i;
++
++ num_buffers = (vout->vid == OMAP_VIDEO1) ?
++ video1_numbuffers : video2_numbuffers;
++ for (i = num_buffers; i < vout->buffer_allocated; i++) {
++ if (vout->buf_virt_addr[i]) {
++ omap_vout_free_buffer(vout->buf_virt_addr[i],
++ vout->buf_phy_addr[i], vout->buffer_size);
++ }
++ vout->buf_virt_addr[i] = 0;
++ vout->buf_phy_addr[i] = 0;
++ }
++ /* Free the VRFB buffers only if they are allocated
++ * during reqbufs. Don't free if init time allocated
++ */
++ if (!vout->vrfb_static_allocation) {
++ for (i = 0; i < 4; i++) {
++ if (vout->smsshado_virt_addr[i]) {
++ omap_vout_free_buffer(
++ vout->smsshado_virt_addr[i],
++ vout->smsshado_phy_addr[i],
++ vout->smsshado_size);
++ vout->smsshado_virt_addr[i] = 0;
++ vout->smsshado_phy_addr[i] = 0;
++ }
++ }
++ }
++ vout->buffer_allocated = num_buffers;
++}
++
++/* This function will be called when VIDIOC_QBUF ioctl is called.
++ * It prepare buffers before give out for the display. This function
++ * user space virtual address into physical address if userptr memory
++ * exchange mechanism is used. If rotation is enabled, it copies entire
++ * buffer into VRFB memory space before giving it to the DSS.
++ */
++static int omap_vout_buffer_prepare(struct videobuf_queue *q,
++ struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ struct omap_vout_device *vout = q->priv_data;
++ u32 dest_frame_index = 0, src_element_index = 0;
++ u32 dest_element_index = 0, src_frame_index = 0;
++ u32 elem_count = 0, frame_count = 0, pixsize = 2;
++ struct videobuf_dmabuf *dmabuf = NULL;
++ enum dss_rotation rotation;
++ struct vid_vrfb_dma *tx;
++
++ if (VIDEOBUF_NEEDS_INIT == vb->state) {
++ vb->width = vout->pix.width;
++ vb->height = vout->pix.height;
++ vb->size = vb->width * vb->height * vout->bpp;
++ vb->field = field;
++ }
++ vb->state = VIDEOBUF_PREPARED;
++ /* if user pointer memory mechanism is used, get the physical
++ * address of the buffer
++ */
++ if (V4L2_MEMORY_USERPTR == vb->memory) {
++ if (0 == vb->baddr)
++ return -EINVAL;
++ /* Virtual address */
++ /* priv points to struct videobuf_pci_sg_memory. But we went
++ * pointer to videobuf_dmabuf, which is member of
++ * videobuf_pci_sg_memory */
++ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
++ dmabuf->vmalloc = (void *) vb->baddr;
++
++ /* Physical address */
++ dmabuf->bus_addr =
++ (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr);
++ }
++
++ if (!rotation_enabled(vout)) {
++ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
++
++ vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr;
++ return 0;
++ }
++ dmabuf = videobuf_to_dma(q->bufs[vb->i]);
++ /* If rotation is enabled, copy input buffer into VRFB
++ * memory space using DMA. We are copying input buffer
++ * into VRFB memory space of desired angle and DSS will
++ * read image VRFB memory for 0 degree angle
++ */
++ pixsize = vout->bpp * vout->vrfb_bpp;
++ /*
++ * DMA transfer in double index mode
++ */
++
++ /* Frame index */
++ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) -
++ (vout->pix.width * vout->bpp)) + 1;
++
++ /* Source and destination parameters */
++ src_element_index = 0;
++ src_frame_index = 0;
++ dest_element_index = 1;
++ /* Number of elements per frame */
++ elem_count = vout->pix.width * vout->bpp;
++ frame_count = vout->pix.height;
++ tx = &vout->vrfb_dma_tx;
++ tx->tx_status = 0;
++ omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32,
++ (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,
++ tx->dev_id, 0x0);
++ /* src_port required only for OMAP1 */
++ omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
++ dmabuf->bus_addr, src_element_index, src_frame_index);
++ /*set dma source burst mode for VRFB */
++ omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
++ rotation = calc_rotation(vout);
++
++ /* dest_port required only for OMAP1 */
++ omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX,
++ vout->vrfb_context[vb->i].paddr[0], dest_element_index,
++ dest_frame_index);
++ /*set dma dest burst mode for VRFB */
++ omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);
++ omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0);
++
++ omap_start_dma(tx->dma_ch);
++ interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT);
++
++ if (tx->tx_status == 0) {
++ omap_stop_dma(tx->dma_ch);
++ return -EINVAL;
++ }
++ /* Store buffers physical address into an array. Addresses
++ * from this array will be used to configure DSS */
++ vout->queued_buf_addr[vb->i] = (u8 *)
++ vout->vrfb_context[vb->i].paddr[rotation];
++ return 0;
++}
++
++/* Buffer queue funtion will be called from the videobuf layer when _QBUF
++ * ioctl is called. It is used to enqueue buffer, which is ready to be
++ * displayed. */
++static void omap_vout_buffer_queue(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ struct omap_vout_device *vout = q->priv_data;
++
++ /* Driver is also maintainig a queue. So enqueue buffer in the driver
++ * queue */
++ list_add_tail(&vb->queue, &vout->dma_queue);
++
++ vb->state = VIDEOBUF_PREPARED;
++}
++
++/* Buffer release function is called from videobuf layer to release buffer
++ * which are already allocated */
++static void omap_vout_buffer_release(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ struct omap_vout_device *vout = q->priv_data;
++
++ vb->state = VIDEOBUF_NEEDS_INIT;
++
++ if (V4L2_MEMORY_MMAP != vout->memory)
++ return;
++}
++
++/*
++ * File operations
++ */
++static void omap_vout_vm_open(struct vm_area_struct *vma)
++{
++ struct omap_vout_device *vout = vma->vm_private_data;
++
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
++ vout->mmap_count++;
++}
++
++static void omap_vout_vm_close(struct vm_area_struct *vma)
++{
++ struct omap_vout_device *vout = vma->vm_private_data;
++
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end);
++ vout->mmap_count--;
++}
++
++static struct vm_operations_struct omap_vout_vm_ops = {
++ .open = omap_vout_vm_open,
++ .close = omap_vout_vm_close,
++};
++
++static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct omap_vout_device *vout = file->private_data;
++ struct videobuf_queue *q = &vout->vbq;
++ unsigned long size = (vma->vm_end - vma->vm_start);
++ unsigned long start = vma->vm_start;
++ int i;
++ void *pos;
++ struct videobuf_dmabuf *dmabuf = NULL;
++
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__,
++ vma->vm_pgoff, vma->vm_start, vma->vm_end);
++
++ /* look for the buffer to map */
++ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
++ if (NULL == q->bufs[i])
++ continue;
++ if (V4L2_MEMORY_MMAP != q->bufs[i]->memory)
++ continue;
++ if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT))
++ break;
++ }
++
++ if (VIDEO_MAX_FRAME == i) {
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
++ "offset invalid [offset=0x%lx]\n",
++ (vma->vm_pgoff << PAGE_SHIFT));
++ return -EINVAL;
++ }
++ q->bufs[i]->baddr = vma->vm_start;
++
++ vma->vm_flags |= VM_RESERVED;
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ vma->vm_ops = &omap_vout_vm_ops;
++ vma->vm_private_data = (void *) vout;
++ dmabuf = videobuf_to_dma(q->bufs[i]);
++ pos = dmabuf->vmalloc;
++ vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;
++ while (size > 0) {
++ unsigned long pfn;
++ pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT;
++ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
++ return -EAGAIN;
++ start += PAGE_SIZE;
++ pos += PAGE_SIZE;
++ size -= PAGE_SIZE;
++ }
++ vout->mmap_count++;
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
++ return 0;
++}
++
++static int omap_vout_release(struct file *file)
++{
++
++ struct omap_vout_device *vout = file->private_data;
++ struct videobuf_queue *q;
++ unsigned int t;
++ struct omapvideo_info *ovid;
++ unsigned int r;
++
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
++ ovid = &vout->vid_info;
++
++ if (!vout)
++ return 0;
++ q = &vout->vbq;
++
++ /* Disable all the overlay managers connected with this interface */
++ for (t = 0; t < ovid->num_overlays; t++) {
++ struct omap_overlay *ovl = ovid->overlays[t];
++ if (ovl->manager && ovl->manager->device) {
++ struct omap_overlay_info info;
++ ovl->get_overlay_info(ovl, &info);
++ info.enabled = 0;
++ ovl->set_overlay_info(ovl, &info);
++ }
++
++ }
++ /* Turn off the pipeline */
++ r = omapvid_apply_changes(vout);
++ if (r)
++ printk(KERN_WARNING VOUT_NAME "Unable to apply changes\n");
++
++ /* Free all buffers */
++ omap_vout_free_allbuffers(vout);
++ videobuf_mmap_free(q);
++
++ /* Even if apply changes fails we should continue
++ freeing allocated memeory */
++ if (vout->streaming) {
++ u32 mask = 0;
++
++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
++ DISPC_IRQ_EVSYNC_ODD;
++ omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
++ vout->streaming = 0;
++
++ videobuf_streamoff(q);
++ videobuf_queue_cancel(q);
++
++ }
++
++ if (vout->mmap_count != 0)
++ vout->mmap_count = 0;
++
++ vout->opened -= 1;
++ file->private_data = NULL;
++
++ if (vout->buffer_allocated)
++ videobuf_mmap_free(q);
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
++ return r;
++}
++
++static int omap_vout_open(struct file *file)
++{
++ struct omap_vout_device *vout = NULL;
++ struct videobuf_queue *q;
++
++ vout = video_drvdata(file);
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
++
++ if (vout == NULL)
++ return -ENODEV;
++
++ /* for now, we only support single open */
++ if (vout->opened)
++ return -EBUSY;
++
++ vout->opened += 1;
++
++ file->private_data = vout;
++ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++
++ q = &vout->vbq;
++ video_vbq_ops.buf_setup = omap_vout_buffer_setup;
++ video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
++ video_vbq_ops.buf_release = omap_vout_buffer_release;
++ video_vbq_ops.buf_queue = omap_vout_buffer_queue;
++ spin_lock_init(&vout->vbq_lock);
++
++ videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock,
++ vout->type, V4L2_FIELD_NONE, sizeof
++ (struct videobuf_buffer), vout);
++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
++ return 0;
++}
++
++/* V4L2 ioctls */
++static int vidioc_querycap(struct file *file, void *fh,
++ struct v4l2_capability *cap)
++{
++ struct omap_vout_device *vout = fh;
++
++ strlcpy(cap->driver, VOUT_NAME,
++ sizeof(cap->driver));
++ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
++ cap->bus_info[0] = '\0';
++ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
++ return 0;
++}
++
++static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
++ struct v4l2_fmtdesc *fmt)
++{
++ int index = fmt->index;
++ enum v4l2_buf_type type = fmt->type;
++
++ fmt->index = index;
++ fmt->type = type;
++ if (index >= NUM_OUTPUT_FORMATS)
++ return -EINVAL;
++
++ fmt->flags = omap_formats[index].flags;
++ strlcpy(fmt->description, omap_formats[index].description,
++ sizeof(fmt->description));
++ fmt->pixelformat = omap_formats[index].pixelformat;
++ return 0;
++}
++
++static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap_vout_device *vout = fh;
++
++ f->fmt.pix = vout->pix;
++ return 0;
++
++}
++
++static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap_vout_device *vout = fh;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ struct omap_video_timings *timing;
++
++ if (vout->streaming)
++ return -EBUSY;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ if (!ovl->manager || !ovl->manager->device)
++ return -EINVAL;
++ /* get the display device attached to the overlay */
++ timing = &ovl->manager->device->panel.timings;
++
++ vout->fbuf.fmt.height = timing->y_res;
++ vout->fbuf.fmt.width = timing->x_res;
++
++ omap_vout_try_format(&f->fmt.pix);
++ return 0;
++}
++
++static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap_vout_device *vout = fh;
++ int bpp;
++ int r;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ struct omap_video_timings *timing;
++
++ if (vout->streaming)
++ return -EBUSY;
++
++ mutex_lock(&vout->lock);
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ /* get the display device attached to the overlay */
++ if (!ovl->manager || !ovl->manager->device) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++ timing = &ovl->manager->device->panel.timings;
++
++ /* We dont support RGB24-packed mode if vrfb rotation
++ * is enabled*/
++ if ((rotation_enabled(vout)) &&
++ f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++
++ /* get the framebuffer parameters */
++
++ if (rotate_90_or_270(vout)) {
++ vout->fbuf.fmt.height = timing->x_res;
++ vout->fbuf.fmt.width = timing->y_res;
++ } else {
++ vout->fbuf.fmt.height = timing->y_res;
++ vout->fbuf.fmt.width = timing->x_res;
++ }
++
++ /* change to samller size is OK */
++
++ bpp = omap_vout_try_format(&f->fmt.pix);
++ f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
++
++ /* try & set the new output format */
++ vout->bpp = bpp;
++ vout->pix = f->fmt.pix;
++ vout->vrfb_bpp = 1;
++
++ /* If YUYV then vrfb bpp is 2, for others its 1 */
++ if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
++ V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
++ vout->vrfb_bpp = 2;
++
++ /* set default crop and win */
++ omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
++
++ /* Save the changes in the overlay strcuture */
++ r = omapvid_init(vout, 0);
++ if (r) {
++ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++ mutex_unlock(&vout->lock);
++ return 0;
++}
++
++static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ int err = -EINVAL;
++ struct omap_vout_device *vout = fh;
++ struct v4l2_window *win = &f->fmt.win;
++
++ err = omap_vout_try_window(&vout->fbuf, win);
++
++ if (err)
++ return err;
++
++ if (vout->vid == OMAP_VIDEO1)
++ win->global_alpha = 255;
++ else
++ win->global_alpha = f->fmt.win.global_alpha;
++
++ return 0;
++}
++
++static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap_vout_device *vout = fh;
++ int err = -EINVAL;
++ struct omap_overlay *ovl;
++ struct omapvideo_info *ovid;
++ struct v4l2_window *win = &f->fmt.win;
++
++ mutex_lock(&vout->lock);
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ err = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
++ if (err) {
++ mutex_unlock(&vout->lock);
++ return err;
++ }
++ /* Video1 plane does not support global alpha */
++ if (ovl->id == OMAP_DSS_VIDEO1)
++ vout->win.global_alpha = 255;
++ else
++ vout->win.global_alpha = f->fmt.win.global_alpha;
++
++ vout->win.chromakey = f->fmt.win.chromakey;
++ mutex_unlock(&vout->lock);
++ return 0;
++}
++
++static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh,
++ struct v4l2_fmtdesc *fmt)
++{
++ int index = fmt->index;
++ enum v4l2_buf_type type = fmt->type;
++
++ fmt->index = index;
++ fmt->type = type;
++ if (index >= NUM_OUTPUT_FORMATS)
++ return -EINVAL;
++
++ fmt->flags = omap_formats[index].flags;
++ strlcpy(fmt->description, omap_formats[index].description,
++ sizeof(fmt->description));
++ fmt->pixelformat = omap_formats[index].pixelformat;
++ return 0;
++}
++
++static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap_vout_device *vout = fh;
++ struct omap_overlay *ovl;
++ struct omapvideo_info *ovid;
++ struct omap_overlay_manager_info info;
++ struct v4l2_window *win = &f->fmt.win;
++ u32 key_value = 0;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ win->w = vout->win.w;
++ win->field = vout->win.field;
++ win->global_alpha = vout->win.global_alpha;
++
++ if (ovl->manager && ovl->manager->get_manager_info) {
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ key_value = info.trans_key;
++ }
++ win->chromakey = key_value;
++ return 0;
++}
++
++static int vidioc_cropcap(struct file *file, void *fh,
++ struct v4l2_cropcap *cropcap)
++{
++ struct omap_vout_device *vout = fh;
++ enum v4l2_buf_type type = cropcap->type;
++ struct v4l2_pix_format *pix = &vout->pix;
++
++ cropcap->type = type;
++ if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ return -EINVAL;
++
++ /* Width and height are always even */
++ cropcap->bounds.width = pix->width & ~1;
++ cropcap->bounds.height = pix->height & ~1;
++
++ omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect);
++ cropcap->pixelaspect.numerator = 1;
++ cropcap->pixelaspect.denominator = 1;
++ return 0;
++}
++
++static int vidioc_g_crop(struct file *file, void *fh,
++ struct v4l2_crop *crop)
++{
++ struct omap_vout_device *vout = fh;
++
++ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ return -EINVAL;
++ crop->c = vout->crop;
++ return 0;
++}
++
++static int vidioc_s_crop(struct file *file, void *fh,
++ struct v4l2_crop *crop)
++{
++ struct omap_vout_device *vout = fh;
++ int err = -EINVAL;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ struct omap_video_timings *timing;
++
++ if (vout->streaming)
++ return -EBUSY;
++
++ mutex_lock(&vout->lock);
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ if (!ovl->manager || !ovl->manager->device) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++ /* get the display device attached to the overlay */
++ timing = &ovl->manager->device->panel.timings;
++
++ if (rotate_90_or_270(vout)) {
++ vout->fbuf.fmt.height = timing->x_res;
++ vout->fbuf.fmt.width = timing->y_res;
++ } else {
++ vout->fbuf.fmt.height = timing->y_res;
++ vout->fbuf.fmt.width = timing->x_res;
++ }
++
++ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
++ err = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
++ &vout->fbuf, &crop->c);
++ mutex_unlock(&vout->lock);
++ return err;
++ } else {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++}
++
++static int vidioc_queryctrl(struct file *file, void *fh,
++ struct v4l2_queryctrl *ctrl)
++{
++ switch (ctrl->id) {
++ case V4L2_CID_ROTATE:
++ v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0);
++ break;
++ case V4L2_CID_BG_COLOR:
++ v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0);
++ break;
++ case V4L2_CID_VFLIP:
++ v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
++ default:
++ ctrl->name[0] = '\0';
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
++{
++ struct omap_vout_device *vout = fh;
++
++ switch (ctrl->id) {
++ case V4L2_CID_ROTATE:
++ ctrl->value = vout->control[0].value;
++ return 0;
++ case V4L2_CID_BG_COLOR:
++ {
++ struct omap_overlay_manager_info info;
++ struct omap_overlay *ovl;
++ ovl = vout->vid_info.overlays[0];
++
++ if (!ovl->manager || !ovl->manager->get_manager_info)
++ return -EINVAL;
++
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ ctrl->value = info.default_color;
++ return 0;
++ }
++
++ case V4L2_CID_VFLIP:
++ ctrl->value = vout->control[2].value;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
++{
++ struct omap_vout_device *vout = fh;
++
++ switch (a->id) {
++ case V4L2_CID_ROTATE:
++ {
++ int rotation = a->value;
++
++ mutex_lock(&vout->lock);
++
++ if (rotation &&
++ vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++
++ if ((v4l2_rot_to_dss_rot(rotation, &vout->rotation,
++ vout->mirror))) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++
++ vout->control[0].value = rotation;
++ mutex_unlock(&vout->lock);
++ return 0;
++ }
++ case V4L2_CID_BG_COLOR:
++ {
++ unsigned int color = a->value;
++ struct omap_overlay_manager_info info;
++ struct omap_overlay *ovl;
++ ovl = vout->vid_info.overlays[0];
++
++ mutex_lock(&vout->lock);
++ if (!ovl->manager || !ovl->manager->get_manager_info) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ info.default_color = color;
++ if (ovl->manager->set_manager_info(ovl->manager, &info)) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++
++ vout->control[1].value = color;
++ mutex_unlock(&vout->lock);
++ return 0;
++ }
++ case V4L2_CID_VFLIP:
++ {
++ unsigned int mirror = a->value;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ mutex_lock(&vout->lock);
++
++ if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++ vout->mirror = mirror;
++ vout->control[2].value = mirror;
++ mutex_unlock(&vout->lock);
++ return 0;
++ }
++
++ default:
++ return -EINVAL;
++ }
++
++}
++
++static int vidioc_reqbufs(struct file *file, void *fh,
++ struct v4l2_requestbuffers *req)
++{
++ struct omap_vout_device *vout = fh;
++ struct videobuf_queue *q = &vout->vbq;
++ unsigned int i, num_buffers = 0;
++ int ret = 0;
++ struct videobuf_dmabuf *dmabuf = NULL;
++
++ if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0))
++ return -EINVAL;
++ /* if memory is not mmp or userptr
++ return error */
++ if ((V4L2_MEMORY_MMAP != req->memory) &&
++ (V4L2_MEMORY_USERPTR != req->memory))
++ return -EINVAL;
++
++ mutex_lock(&vout->lock);
++ /* Cannot be requested when streaming is on */
++ if (vout->streaming) {
++ mutex_unlock(&vout->lock);
++ return -EBUSY;
++ }
++
++ /* If buffers are already allocated free them */
++ if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) {
++ if (vout->mmap_count) {
++ mutex_unlock(&vout->lock);
++ return -EBUSY;
++ }
++ num_buffers = (vout->vid == OMAP_VIDEO1) ?
++ video1_numbuffers : video2_numbuffers;
++ for (i = num_buffers; i < vout->buffer_allocated; i++) {
++ dmabuf = videobuf_to_dma(q->bufs[i]);
++ omap_vout_free_buffer((u32)dmabuf->vmalloc,
++ dmabuf->bus_addr, vout->buffer_size);
++ vout->buf_virt_addr[i] = 0;
++ vout->buf_phy_addr[i] = 0;
++ }
++ vout->buffer_allocated = num_buffers;
++ videobuf_mmap_free(q);
++ } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) {
++ if (vout->buffer_allocated) {
++ videobuf_mmap_free(q);
++ for (i = 0; i < vout->buffer_allocated; i++) {
++ kfree(q->bufs[i]);
++ q->bufs[i] = NULL;
++ }
++ vout->buffer_allocated = 0;
++ }
++ }
++
++ /*store the memory type in data structure */
++ vout->memory = req->memory;
++
++ INIT_LIST_HEAD(&vout->dma_queue);
++
++ /* call videobuf_reqbufs api */
++ ret = videobuf_reqbufs(q, req);
++ if (ret < 0) {
++ mutex_unlock(&vout->lock);
++ return ret;
++ }
++
++ vout->buffer_allocated = req->count;
++ for (i = 0; i < req->count; i++) {
++ dmabuf = videobuf_to_dma(q->bufs[i]);
++ dmabuf->vmalloc = (void *) vout->buf_virt_addr[i];
++ dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i];
++ dmabuf->sglen = 1;
++ }
++ mutex_unlock(&vout->lock);
++ return 0;
++}
++
++static int vidioc_querybuf(struct file *file, void *fh,
++ struct v4l2_buffer *b)
++{
++ struct omap_vout_device *vout = fh;
++
++ return videobuf_querybuf(&vout->vbq, b);
++}
++
++static int vidioc_qbuf(struct file *file, void *fh,
++ struct v4l2_buffer *buffer)
++{
++ struct omap_vout_device *vout = fh;
++ struct videobuf_queue *q = &vout->vbq;
++ int ret = 0;
++
++ if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) ||
++ (buffer->index >= vout->buffer_allocated) ||
++ (q->bufs[buffer->index]->memory != buffer->memory)) {
++ return -EINVAL;
++ }
++ if (V4L2_MEMORY_USERPTR == buffer->memory) {
++ if ((buffer->length < vout->pix.sizeimage) ||
++ (0 == buffer->m.userptr)) {
++ return -EINVAL;
++ }
++ }
++
++ if ((rotation_enabled(vout)) &&
++ vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) {
++ printk(KERN_WARNING VOUT_NAME
++ "DMA Channel not allocated for Rotation\n");
++ return -EINVAL;
++ }
++
++ ret = videobuf_qbuf(q, buffer);
++ return ret;
++}
++
++static int vidioc_dqbuf(struct file *file, void *fh,
++ struct v4l2_buffer *b)
++{
++ struct omap_vout_device *vout = fh;
++ struct videobuf_queue *q = &vout->vbq;
++ int ret = 0;
++
++ if (!vout->streaming)
++ return -EINVAL;
++
++ if (file->f_flags & O_NONBLOCK)
++ /* Call videobuf_dqbuf for non blocking mode */
++ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
++ else
++ /* Call videobuf_dqbuf for blocking mode */
++ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
++ return ret;
++}
++
++static int vidioc_streamon(struct file *file, void *fh,
++ enum v4l2_buf_type i)
++{
++ struct omap_vout_device *vout = fh;
++ struct videobuf_queue *q = &vout->vbq;
++ u32 addr = 0;
++ int r = 0;
++ int t;
++ struct omapvideo_info *ovid = &vout->vid_info;
++ u32 mask = 0;
++
++ mutex_lock(&vout->lock);
++
++ if (vout->streaming) {
++ mutex_unlock(&vout->lock);
++ return -EBUSY;
++ }
++
++ r = videobuf_streamon(q);
++ if (r < 0) {
++ mutex_unlock(&vout->lock);
++ return r;
++ }
++
++ if (list_empty(&vout->dma_queue)) {
++ mutex_unlock(&vout->lock);
++ return -EIO;
++ }
++ /* Get the next frame from the buffer queue */
++ vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
++ struct videobuf_buffer, queue);
++ /* Remove buffer from the buffer queue */
++ list_del(&vout->cur_frm->queue);
++ /* Mark state of the current frame to active */
++ vout->cur_frm->state = VIDEOBUF_ACTIVE;
++ /* Initialize field_id and started member */
++ vout->field_id = 0;
++
++ /* set flag here. Next QBUF will start DMA */
++ vout->streaming = 1;
++
++ vout->first_int = 1;
++
++ if (omap_vout_calculate_offset(vout)) {
++ mutex_unlock(&vout->lock);
++ return -EINVAL;
++ }
++ addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
++ + vout->cropped_offset;
++
++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
++ DISPC_IRQ_EVSYNC_ODD;
++
++ omap_dispc_register_isr(omap_vout_isr, vout, mask);
++
++ for (t = 0; t < ovid->num_overlays; t++) {
++ struct omap_overlay *ovl = ovid->overlays[t];
++ if (ovl->manager && ovl->manager->device) {
++ struct omap_overlay_info info;
++ ovl->get_overlay_info(ovl, &info);
++ info.enabled = 1;
++ info.paddr = addr;
++ if (ovl->set_overlay_info(ovl, &info))
++ return -EINVAL;
++ }
++ }
++
++ /* First save the configuration in ovelray structure */
++ r = omapvid_init(vout, addr);
++ if (r)
++ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n");
++ /* Enable the pipeline and set the Go bit */
++ r = omapvid_apply_changes(vout);
++ if (r)
++ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
++
++ mutex_unlock(&vout->lock);
++ return r;
++}
++
++static int vidioc_streamoff(struct file *file, void *fh,
++ enum v4l2_buf_type i)
++{
++ struct omap_vout_device *vout = fh;
++ int t, r = 0;
++ struct omapvideo_info *ovid = &vout->vid_info;
++ u32 mask = 0;
++
++ if (!vout->streaming)
++ return -EINVAL;
++
++ vout->streaming = 0;
++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
++ DISPC_IRQ_EVSYNC_ODD;
++
++ omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
++
++ for (t = 0; t < ovid->num_overlays; t++) {
++ struct omap_overlay *ovl = ovid->overlays[t];
++ if (ovl->manager && ovl->manager->device) {
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++ info.enabled = 0;
++ return ovl->set_overlay_info(ovl, &info);
++ }
++ }
++
++ /* Turn of the pipeline */
++ r = omapvid_apply_changes(vout);
++ if (r) {
++ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
++ return r;
++ }
++ videobuf_streamoff(&vout->vbq);
++ videobuf_queue_cancel(&vout->vbq);
++ return 0;
++}
++
++static int vidioc_s_fbuf(struct file *file, void *fh,
++ struct v4l2_framebuffer *a)
++{
++ struct omap_vout_device *vout = fh;
++ struct omap_overlay_manager_info info;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
++ int enable = 0;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ /* OMAP DSS doesn't support Source and Destination color
++ key together */
++ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
++ (a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
++ return -EINVAL;
++ /* OMAP DSS Doesn't support the Destination color key
++ and alpha blending together */
++ if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
++ (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
++ return -EINVAL;
++
++ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
++ vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
++ key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
++ } else
++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
++
++ if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
++ vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
++ key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
++ } else
++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
++
++ if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
++ V4L2_FBUF_FLAG_SRC_CHROMAKEY))
++ enable = 1;
++ else
++ enable = 0;
++ if (ovl->manager && ovl->manager->get_manager_info &&
++ ovl->manager->set_manager_info) {
++
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ info.trans_enabled = enable;
++ info.trans_key_type = key_type;
++ info.trans_key = vout->win.chromakey;
++
++ if (ovl->manager->set_manager_info(ovl->manager, &info))
++ return -EINVAL;
++ }
++ if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
++ vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
++ enable = 1;
++ } else {
++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
++ enable = 0;
++ }
++ if (ovl->manager && ovl->manager->get_manager_info &&
++ ovl->manager->set_manager_info) {
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ info.alpha_enabled = enable;
++ if (ovl->manager->set_manager_info(ovl->manager, &info))
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int vidioc_g_fbuf(struct file *file, void *fh,
++ struct v4l2_framebuffer *a)
++{
++ struct omap_vout_device *vout = fh;
++ struct omap_overlay_manager_info info;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++
++ a->flags = 0x0;
++
++ a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
++ | V4L2_FBUF_CAP_SRC_CHROMAKEY;
++
++ if (ovl->manager && ovl->manager->get_manager_info) {
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
++ a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
++ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
++ a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
++ }
++ if (ovl->manager && ovl->manager->get_manager_info) {
++ ovl->manager->get_manager_info(ovl->manager, &info);
++ if (info.alpha_enabled)
++ a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
++ }
++
++ return 0;
++}
++
++static const struct v4l2_ioctl_ops vout_ioctl_ops = {
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
++ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
++ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
++ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
++ .vidioc_queryctrl = vidioc_queryctrl,
++ .vidioc_g_ctrl = vidioc_g_ctrl,
++ .vidioc_s_fbuf = vidioc_s_fbuf,
++ .vidioc_g_fbuf = vidioc_g_fbuf,
++ .vidioc_s_ctrl = vidioc_s_ctrl,
++ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
++ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
++ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
++ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
++ .vidioc_cropcap = vidioc_cropcap,
++ .vidioc_g_crop = vidioc_g_crop,
++ .vidioc_s_crop = vidioc_s_crop,
++ .vidioc_reqbufs = vidioc_reqbufs,
++ .vidioc_querybuf = vidioc_querybuf,
++ .vidioc_qbuf = vidioc_qbuf,
++ .vidioc_dqbuf = vidioc_dqbuf,
++ .vidioc_streamon = vidioc_streamon,
++ .vidioc_streamoff = vidioc_streamoff,
++};
++
++static const struct v4l2_file_operations omap_vout_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = video_ioctl2,
++ .mmap = omap_vout_mmap,
++ .open = omap_vout_open,
++ .release = omap_vout_release,
++};
++
++/* Init functions used during driver intitalization */
++/* Initial setup of video_data */
++static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
++{
++ struct v4l2_pix_format *pix;
++ struct video_device *vfd;
++ struct v4l2_control *control;
++ struct omap_dss_device *display =
++ vout->vid_info.overlays[0]->manager->device;
++
++ /* set the default pix */
++ pix = &vout->pix;
++
++ /* Set the default picture of QVGA */
++ pix->width = QQVGA_WIDTH;
++ pix->height = QQVGA_HEIGHT;
++
++ /* Default pixel format is RGB 5-6-5 */
++ pix->pixelformat = V4L2_PIX_FMT_RGB565;
++ pix->field = V4L2_FIELD_ANY;
++ pix->bytesperline = pix->width * 2;
++ pix->sizeimage = pix->bytesperline * pix->height;
++ pix->priv = 0;
++ pix->colorspace = V4L2_COLORSPACE_JPEG;
++
++ vout->bpp = RGB565_BPP;
++ vout->fbuf.fmt.width = display->panel.timings.x_res;
++ vout->fbuf.fmt.height = display->panel.timings.y_res;
++
++ /* Set the data structures for the overlay parameters*/
++ vout->win.global_alpha = 255;
++ vout->fbuf.flags = 0;
++ vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
++ V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY;
++ vout->win.chromakey = 0;
++
++ omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
++
++ /*Initialize the control variables for
++ rotation, flipping and background color. */
++ control = vout->control;
++ control[0].id = V4L2_CID_ROTATE;
++ control[0].value = 0;
++ vout->rotation = 0;
++ vout->mirror = 0;
++ vout->control[2].id = V4L2_CID_HFLIP;
++ vout->control[2].value = 0;
++ vout->vrfb_bpp = 2;
++
++ control[1].id = V4L2_CID_BG_COLOR;
++ control[1].value = 0;
++
++ /* initialize the video_device struct */
++ vfd = vout->vfd = video_device_alloc();
++
++ if (!vfd) {
++ printk(KERN_ERR VOUT_NAME ": could not allocate"
++ " video device struct\n");
++ return -ENOMEM;
++ }
++ vfd->release = video_device_release;
++ vfd->ioctl_ops = &vout_ioctl_ops;
++
++ strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
++ vfd->vfl_type = VFL_TYPE_GRABBER;
++
++ /* need to register for a VID_HARDWARE_* ID in videodev.h */
++ vfd->fops = &omap_vout_fops;
++ mutex_init(&vout->lock);
++
++ vfd->minor = -1;
++ return 0;
++
++}
++
++/* Setup video buffers */
++static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
++ int vid_num)
++{
++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
++ omap2video_device, v4l2_dev);
++ struct omap_vout_device *vout;
++ int i, j, r = 0;
++ int image_width, image_height;
++ unsigned numbuffers;
++ struct video_device *vfd;
++ int static_vrfb_allocation = 0, vrfb_num_bufs = 4;
++
++ vout = vid_dev->vouts[vid_num];
++ vfd = vout->vfd;
++
++ numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
++ vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
++ printk(KERN_INFO VOUT_NAME "Buffer Size = %d\n", vout->buffer_size);
++ for (i = 0; i < numbuffers; i++) {
++ vout->buf_virt_addr[i] =
++ omap_vout_alloc_buffer(vout->buffer_size,
++ (u32 *) &vout->buf_phy_addr[i]);
++ if (!vout->buf_virt_addr[i]) {
++ numbuffers = i;
++ r = -ENOMEM;
++ goto free_buffers;
++ }
++ }
++
++ for (i = 0; i < 4; i++) {
++ if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
++ printk(KERN_INFO VOUT_NAME ": VRFB Region allocation "
++ "for rotation failed\n");
++ r = -ENOMEM;
++ break;
++ }
++ }
++ if (r == -ENOMEM) {
++ for (j = 0; j < i; j++)
++ omap_vrfb_release_ctx(&vout->vrfb_context[j]);
++
++ goto free_buffers;
++ }
++
++ vout->cropped_offset = 0;
++
++ /* Calculate VRFB memory size */
++ /* allocate for worst case size */
++ image_width = VID_MAX_WIDTH / TILE_SIZE;
++ if (VID_MAX_WIDTH % TILE_SIZE)
++ image_width++;
++
++ image_width = image_width * TILE_SIZE;
++ image_height = VID_MAX_HEIGHT / TILE_SIZE;
++
++ if (VID_MAX_HEIGHT % TILE_SIZE)
++ image_height++;
++
++ image_height = image_height * TILE_SIZE;
++ vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);
++
++ /*
++ * Request and Initialize DMA, for DMA based VRFB transfer
++ */
++ vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
++ vout->vrfb_dma_tx.dma_ch = -1;
++ vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
++ r = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
++ omap_vout_vrfb_dma_tx_callback,
++ (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
++ if (r < 0) {
++ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
++ printk(KERN_INFO VOUT_NAME ": DMA Channel not alloted "
++ "for video%d [v4l2]\n", vfd->minor);
++ }
++ init_waitqueue_head(&vout->vrfb_dma_tx.wait);
++
++ /* Allocate VRFB buffers if selected through bootargs */
++ static_vrfb_allocation = (vid_num == 0) ?
++ vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
++
++ /* statically allocated the VRFB buffer is done through
++ commands line aruments */
++ if (static_vrfb_allocation) {
++ if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
++ r = -ENOMEM;
++ goto free_buffers;
++ }
++ vout->vrfb_static_allocation = 1;
++ }
++ return 0;
++
++free_buffers:
++ for (i = 0; i < numbuffers; i++) {
++ omap_vout_free_buffer(vout->buf_virt_addr[i],
++ vout->buf_phy_addr[i], vout->buffer_size);
++ vout->buf_virt_addr[i] = 0;
++ vout->buf_phy_addr[i] = 0;
++ }
++ return r;
++
++}
++
++/* Create video out devices */
++static int __init omap_vout_create_video_devices(struct platform_device *pdev)
++{
++ int r = 0, k;
++ struct omap_vout_device *vout;
++ struct video_device *vfd = NULL;
++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
++
++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
++ omap2video_device, v4l2_dev);
++
++ for (k = 0; k < pdev->num_resources; k++) {
++
++ vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
++ if (!vout) {
++ printk(KERN_ERR VOUT_NAME
++ ": could not allocate memory\n");
++ return -ENOMEM;
++ }
++
++ memset(vout, 0, sizeof(struct omap_vout_device));
++
++ vout->vid = k;
++ vid_dev->vouts[k] = vout;
++ vout->vid_dev = vid_dev;
++ /* Select video2 if only 1 overlay is controlled by V4L2 */
++ if (pdev->num_resources == 1)
++ vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
++ else
++ /* Else select video1 and video2 one by one. */
++ vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
++ vout->vid_info.num_overlays = 1;
++ vout->vid_info.id = k + 1;
++ vid_dev->num_videos++;
++
++ /* Setup the default configuration for the video devices
++ */
++ if (omap_vout_setup_video_data(vout) != 0) {
++ r = -ENOMEM;
++ goto error;
++ }
++
++ /* Allocate default number of buffers for the video streaming
++ * and reserve the VRFB space for rotation
++ */
++ if (omap_vout_setup_video_bufs(pdev, k) != 0) {
++ r = -ENOMEM;
++ goto error1;
++ }
++
++ /* Register the Video device with V4L2
++ */
++ vfd = vout->vfd;
++ if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) {
++ printk(KERN_ERR VOUT_NAME ": could not register "
++ "Video for Linux device\n");
++ vfd->minor = -1;
++ r = -ENODEV;
++ goto error2;
++ }
++ video_set_drvdata(vfd, vout);
++
++ /* Configure the overlay structure */
++ r = omapvid_init(vid_dev->vouts[k], 0);
++
++ if (r)
++ goto error2;
++ else
++ goto success;
++error2:
++ omap_vout_release_vrfb(vout);
++ omap_vout_free_buffers(vout);
++error1:
++ video_device_release(vfd);
++error:
++ kfree(vout);
++ return r;
++
++success:
++ printk(KERN_INFO VOUT_NAME ": registered and initialized "
++ "video device %d [v4l2]\n", vfd->minor);
++ if (k == (pdev->num_resources - 1))
++ return 0;
++ }
++ return -ENODEV;
++
++}
++/* Driver functions */
++static int omap_vout_remove(struct platform_device *pdev)
++{
++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
++ omap2video_device, v4l2_dev);
++ int k;
++
++ v4l2_device_unregister(v4l2_dev);
++ for (k = 0; k < pdev->num_resources; k++)
++ omap_vout_cleanup_device(vid_dev->vouts[k]);
++
++ for (k = 0; k < vid_dev->num_displays; k++) {
++ if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
++ vid_dev->displays[k]->disable(vid_dev->displays[k]);
++
++ omap_dss_put_device(vid_dev->displays[k]);
++ }
++ kfree(vid_dev);
++ return 0;
++}
++
++static int __init omap_vout_probe(struct platform_device *pdev)
++{
++ int r = 0, i;
++ struct omap2video_device *vid_dev = NULL;
++ struct omap_overlay *ovl;
++ struct omap_dss_device *def_display;
++ struct omap_dss_device *dssdev;
++
++ if (pdev->num_resources == 0) {
++ dev_err(&pdev->dev, "probed for an unknown device\n");
++ r = -ENODEV;
++ return r;
++ }
++
++ vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
++ if (vid_dev == NULL) {
++ r = -ENOMEM;
++ return r;
++ }
++
++ vid_dev->num_displays = 0;
++ dssdev = NULL;
++ for_each_dss_dev(dssdev) {
++ omap_dss_get_device(dssdev);
++ vid_dev->displays[vid_dev->num_displays++] = dssdev;
++ }
++
++ if (vid_dev->num_displays == 0) {
++ dev_err(&pdev->dev, "no displays\n");
++ r = -EINVAL;
++ goto error0;
++ }
++
++ vid_dev->num_overlays = omap_dss_get_num_overlays();
++ for (i = 0; i < vid_dev->num_overlays; i++)
++ vid_dev->overlays[i] = omap_dss_get_overlay(i);
++
++ vid_dev->num_managers = omap_dss_get_num_overlay_managers();
++ for (i = 0; i < vid_dev->num_managers; i++)
++ vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
++
++ /* Get the Video1 overlay and video2 overlay.
++ * Setup the Display attached to that overlays
++ */
++ for (i = 1; i < 3; i++) {
++ ovl = omap_dss_get_overlay(i);
++ if (ovl->manager && ovl->manager->device) {
++ def_display = ovl->manager->device;
++ } else {
++ dev_warn(&pdev->dev, "cannot find display\n");
++ def_display = NULL;
++ }
++ if (def_display) {
++ r = def_display->enable(def_display);
++ if (r) {
++ /* Here we are not considering a error
++ * as display may be enabled by frame
++ * buffer driver
++ */
++ dev_warn(&pdev->dev,
++ "'%s' Display already enabled\n",
++ def_display->name);
++ }
++ /* set the update mode */
++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 1);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++#else /* MANUAL_UPDATE */
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 0);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_MANUAL);
++#endif
++ } else {
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++ }
++ }
++ }
++
++ if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
++ printk(KERN_ERR VOUT_NAME "v4l2_device_register failed\n");
++ return -ENODEV;
++ }
++
++ r = omap_vout_create_video_devices(pdev);
++ if (r)
++ goto error0;
++
++ for (i = 0; i < vid_dev->num_displays; i++) {
++ struct omap_dss_device *display = vid_dev->displays[i];
++
++ if (display->update)
++ display->update(display, 0, 0,
++ display->panel.timings.x_res,
++ display->panel.timings.y_res);
++ }
++ return 0;
++
++error0:
++ kfree(vid_dev);
++ return r;
++}
++
++static struct platform_driver omap_vout_driver = {
++ .driver = {
++ .name = VOUT_NAME,
++ },
++ .probe = omap_vout_probe,
++ .remove = omap_vout_remove,
++};
++
++void omap_vout_isr(void *arg, unsigned int irqstatus)
++{
++ int r;
++ struct timeval timevalue;
++ struct omap_vout_device *vout =
++ (struct omap_vout_device *) arg;
++ u32 addr, fid;
++ struct omapvideo_info *ovid;
++ struct omap_overlay *ovl;
++ struct omap_dss_device *cur_display;
++
++ if (!vout->streaming)
++ return;
++
++ ovid = &vout->vid_info;
++ ovl = ovid->overlays[0];
++ /* get the display device attached to the overlay */
++ if (!ovl->manager || !ovl->manager->device)
++ return;
++ cur_display = ovl->manager->device;
++
++ spin_lock(&vout->vbq_lock);
++ do_gettimeofday(&timevalue);
++ if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) {
++ if (!(irqstatus & DISPC_IRQ_VSYNC))
++ return;
++ if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
++ vout->cur_frm->ts = timevalue;
++ vout->cur_frm->state = VIDEOBUF_DONE;
++ wake_up_interruptible(&vout->cur_frm->done);
++ vout->cur_frm = vout->next_frm;
++ }
++ vout->first_int = 0;
++ if (list_empty(&vout->dma_queue)) {
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++
++ vout->next_frm = list_entry(vout->dma_queue.next,
++ struct videobuf_buffer, queue);
++ list_del(&vout->next_frm->queue);
++
++ vout->next_frm->state = VIDEOBUF_ACTIVE;
++
++ addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
++ + vout->cropped_offset;
++
++ /* First save the configuration in ovelray structure */
++ r = omapvid_init(vout, addr);
++ if (r)
++ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n");
++ /* Enable the pipeline and set the Go bit */
++ r = omapvid_apply_changes(vout);
++ if (r)
++ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
++ } else {
++
++ if (vout->first_int) {
++ vout->first_int = 0;
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++ if (irqstatus & DISPC_IRQ_EVSYNC_ODD) {
++ fid = 1;
++ } else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) {
++ fid = 0;
++ } else {
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++ vout->field_id ^= 1;
++ if (fid != vout->field_id) {
++ if (0 == fid)
++ vout->field_id = fid;
++
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++ if (0 == fid) {
++ if (vout->cur_frm == vout->next_frm) {
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++ vout->cur_frm->ts = timevalue;
++ vout->cur_frm->state = VIDEOBUF_DONE;
++ wake_up_interruptible(&vout->cur_frm->done);
++ vout->cur_frm = vout->next_frm;
++ } else if (1 == fid) {
++ if (list_empty(&vout->dma_queue) ||
++ (vout->cur_frm != vout->next_frm)) {
++ spin_unlock(&vout->vbq_lock);
++ return;
++ }
++ vout->next_frm = list_entry(vout->dma_queue.next,
++ struct videobuf_buffer, queue);
++ list_del(&vout->next_frm->queue);
++
++ vout->next_frm->state = VIDEOBUF_ACTIVE;
++ addr = (unsigned long)
++ vout->queued_buf_addr[vout->next_frm->i] +
++ vout->cropped_offset;
++ /* First save the configuration in ovelray structure */
++ r = omapvid_init(vout, addr);
++ if (r)
++ printk(KERN_ERR VOUT_NAME
++ "failed to set overlay info\n");
++ /* Enable the pipeline and set the Go bit */
++ r = omapvid_apply_changes(vout);
++ if (r)
++ printk(KERN_ERR VOUT_NAME
++ "failed to change mode\n");
++ }
++
++ }
++ spin_unlock(&vout->vbq_lock);
++}
++
++static void omap_vout_cleanup_device(struct omap_vout_device *vout)
++{
++ struct video_device *vfd;
++
++ if (!vout)
++ return;
++ vfd = vout->vfd;
++
++ if (vfd) {
++ if (vfd->minor == -1) {
++ /*
++ * The device was never registered, so release the
++ * video_device struct directly.
++ */
++ video_device_release(vfd);
++ } else {
++ /*
++ * The unregister function will release the video_device
++ * struct as well as unregistering it.
++ */
++ video_unregister_device(vfd);
++ }
++ }
++
++ omap_vout_release_vrfb(vout);
++
++ omap_vout_free_buffers(vout);
++ /* Free the VRFB buffer if allocated
++ * init time
++ */
++ if (vout->vrfb_static_allocation)
++ omap_vout_free_vrfb_buffers(vout);
++
++ kfree(vout);
++}
++
++static int __init omap_vout_init(void)
++{
++
++ if (platform_driver_register(&omap_vout_driver) != 0) {
++ printk(KERN_ERR VOUT_NAME ": could not register \
++ Video driver\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void omap_vout_cleanup(void)
++{
++ platform_driver_unregister(&omap_vout_driver);
++}
++
++late_initcall(omap_vout_init);
++module_exit(omap_vout_cleanup);
+diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
+new file mode 100644
+index 0000000..57743e5
+--- /dev/null
++++ b/drivers/media/video/omap/omap_voutdef.h
+@@ -0,0 +1,148 @@
++/*
++ * drivers/media/video/omap/omap_voutdef.h
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#ifndef OMAP_VOUTDEF_H
++#define OMAP_VOUTDEF_H
++
++#include <mach/display.h>
++
++#define YUYV_BPP 2
++#define RGB565_BPP 2
++#define RGB24_BPP 3
++#define RGB32_BPP 4
++#define TILE_SIZE 32
++#define YUYV_VRFB_BPP 2
++#define RGB_VRFB_BPP 1
++#define MAX_CID 3
++#define MAC_VRFB_CTXS 4
++#define MAX_VOUT_DEV 2
++#define MAX_OVLS 3
++#define MAX_DISPLAYS 3
++#define MAX_MANAGERS 3
++
++/* Enum for Rotation
++ * DSS understands rotation in 0, 1, 2, 3 context
++ * while V4L2 driver understands it as 0, 90, 180, 270
++ */
++enum dss_rotation {
++ dss_rotation_0_degree = 0,
++ dss_rotation_90_degree = 1,
++ dss_rotation_180_degree = 2,
++ dss_rotation_270_degree = 3,
++};
++/*
++ * This structure is used to store the DMA transfer parameters
++ * for VRFB hidden buffer
++ */
++struct vid_vrfb_dma {
++ int dev_id;
++ int dma_ch;
++ int req_status;
++ int tx_status;
++ wait_queue_head_t wait;
++};
++
++struct omapvideo_info {
++ int id;
++ int num_overlays;
++ struct omap_overlay *overlays[MAX_OVLS];
++};
++
++struct omap2video_device {
++ struct mutex mtx;
++
++ int state;
++
++ struct v4l2_device v4l2_dev;
++ int num_videos;
++ struct omap_vout_device *vouts[MAX_VOUT_DEV];
++
++ int num_displays;
++ struct omap_dss_device *displays[MAX_DISPLAYS];
++ int num_overlays;
++ struct omap_overlay *overlays[MAX_OVLS];
++ int num_managers;
++ struct omap_overlay_manager *managers[MAX_MANAGERS];
++};
++
++/* per-device data structure */
++struct omap_vout_device {
++
++ struct omapvideo_info vid_info;
++ struct video_device *vfd;
++ struct omap2video_device *vid_dev;
++ int vid;
++ int opened;
++
++ /* we don't allow to change image fmt/size once buffer has
++ * been allocated
++ */
++ int buffer_allocated;
++ /* allow to reuse previously allocated buffer which is big enough */
++ int buffer_size;
++ /* keep buffer info across opens */
++ unsigned long buf_virt_addr[VIDEO_MAX_FRAME];
++ unsigned long buf_phy_addr[VIDEO_MAX_FRAME];
++ enum omap_color_mode dss_mode;
++
++ /* we don't allow to request new buffer when old buffers are
++ * still mmaped
++ */
++ int mmap_count;
++
++ spinlock_t vbq_lock; /* spinlock for videobuf queues */
++ unsigned long field_count; /* field counter for videobuf_buffer */
++
++ /* non-NULL means streaming is in progress. */
++ bool streaming;
++
++ struct v4l2_pix_format pix;
++ struct v4l2_rect crop;
++ struct v4l2_window win;
++ struct v4l2_framebuffer fbuf;
++
++ /* Lock to protect the shared data structures in ioctl */
++ struct mutex lock;
++
++ /* V4L2 control structure for different control id */
++ struct v4l2_control control[MAX_CID];
++ enum dss_rotation rotation;
++ bool mirror;
++ int flicker_filter;
++ /* V4L2 control structure for different control id */
++
++ int bpp; /* bytes per pixel */
++ int vrfb_bpp; /* bytes per pixel with respect to VRFB */
++
++ struct vid_vrfb_dma vrfb_dma_tx;
++ unsigned int smsshado_phy_addr[MAC_VRFB_CTXS];
++ unsigned int smsshado_virt_addr[MAC_VRFB_CTXS];
++ struct vrfb vrfb_context[MAC_VRFB_CTXS];
++ bool vrfb_static_allocation;
++ unsigned int smsshado_size;
++ unsigned char pos;
++
++ int ps, vr_ps, line_length, first_int, field_id;
++ enum v4l2_memory memory;
++ struct videobuf_buffer *cur_frm, *next_frm;
++ struct list_head dma_queue;
++ u8 *queued_buf_addr[VIDEO_MAX_FRAME];
++ u32 cropped_offset;
++ s32 tv_field1_offset;
++ void *isr_handle;
++
++ /* Buffer queue variables */
++ struct omap_vout_device *vout;
++ enum v4l2_buf_type type;
++ struct videobuf_queue vbq;
++ int io_allowed;
++
++};
++#endif /* ifndef OMAP_VOUTDEF_H */
+diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c
+new file mode 100644
+index 0000000..bce5072
+--- /dev/null
++++ b/drivers/media/video/omap/omap_voutlib.c
+@@ -0,0 +1,258 @@
++/*
++ * drivers/media/video/omap/omap_voutlib.c
++ *
++ * Copyright (C) 2005-2009 Texas Instruments.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ *
++ * Based on the OMAP2 camera driver
++ * Video-for-Linux (Version 2) camera capture driver for
++ * the OMAP24xx camera controller.
++ *
++ * Author: Andy Lowe (source@mvista.com)
++ *
++ * Copyright (C) 2004 MontaVista Software, Inc.
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/videodev2.h>
++
++MODULE_AUTHOR("Texas Instruments.");
++MODULE_DESCRIPTION("OMAP Video library");
++MODULE_LICENSE("GPL");
++
++/* Return the default overlay cropping rectangle in crop given the image
++ * size in pix and the video display size in fbuf. The default
++ * cropping rectangle is the largest rectangle no larger than the capture size
++ * that will fit on the display. The default cropping rectangle is centered in
++ * the image. All dimensions and offsets are rounded down to even numbers.
++ */
++void omap_vout_default_crop(struct v4l2_pix_format *pix,
++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop)
++{
++ crop->width = (pix->width < fbuf->fmt.width) ?
++ pix->width : fbuf->fmt.width;
++ crop->height = (pix->height < fbuf->fmt.height) ?
++ pix->height : fbuf->fmt.height;
++ crop->width &= ~1;
++ crop->height &= ~1;
++ crop->left = ((pix->width - crop->width) >> 1) & ~1;
++ crop->top = ((pix->height - crop->height) >> 1) & ~1;
++}
++EXPORT_SYMBOL_GPL(omap_vout_default_crop);
++
++/* Given a new render window in new_win, adjust the window to the
++ * nearest supported configuration. The adjusted window parameters are
++ * returned in new_win.
++ * Returns zero if succesful, or -EINVAL if the requested window is
++ * impossible and cannot reasonably be adjusted.
++ */
++int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
++ struct v4l2_window *new_win)
++{
++ struct v4l2_rect try_win;
++
++ /* make a working copy of the new_win rectangle */
++ try_win = new_win->w;
++
++ /* adjust the preview window so it fits on the display by clipping any
++ * offscreen areas
++ */
++ if (try_win.left < 0) {
++ try_win.width += try_win.left;
++ try_win.left = 0;
++ }
++ if (try_win.top < 0) {
++ try_win.height += try_win.top;
++ try_win.top = 0;
++ }
++ try_win.width = (try_win.width < fbuf->fmt.width) ?
++ try_win.width : fbuf->fmt.width;
++ try_win.height = (try_win.height < fbuf->fmt.height) ?
++ try_win.height : fbuf->fmt.height;
++ if (try_win.left + try_win.width > fbuf->fmt.width)
++ try_win.width = fbuf->fmt.width - try_win.left;
++ if (try_win.top + try_win.height > fbuf->fmt.height)
++ try_win.height = fbuf->fmt.height - try_win.top;
++ try_win.width &= ~1;
++ try_win.height &= ~1;
++
++ if (try_win.width <= 0 || try_win.height <= 0)
++ return -EINVAL;
++
++ /* We now have a valid preview window, so go with it */
++ new_win->w = try_win;
++ new_win->field = V4L2_FIELD_ANY;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(omap_vout_try_window);
++
++/* Given a new render window in new_win, adjust the window to the
++ * nearest supported configuration. The image cropping window in crop
++ * will also be adjusted if necessary. Preference is given to keeping the
++ * the window as close to the requested configuration as possible. If
++ * successful, new_win, vout->win, and crop are updated.
++ * Returns zero if succesful, or -EINVAL if the requested preview window is
++ * impossible and cannot reasonably be adjusted.
++ */
++int omap_vout_new_window(struct v4l2_rect *crop,
++ struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
++ struct v4l2_window *new_win)
++{
++ int err;
++
++ err = omap_vout_try_window(fbuf, new_win);
++ if (err)
++ return err;
++
++ /* update our preview window */
++ win->w = new_win->w;
++ win->field = new_win->field;
++ win->chromakey = new_win->chromakey;
++
++ /* adjust the cropping window to allow for resizing limitations */
++ if ((crop->height/win->w.height) >= 4) {
++ /* The maximum vertical downsizing ratio is 4:1 */
++ crop->height = win->w.height * 4;
++ }
++ if ((crop->width/win->w.width) >= 4) {
++ /* The maximum horizontal downsizing ratio is 4:1 */
++ crop->width = win->w.width * 4;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(omap_vout_new_window);
++
++/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
++ * the nearest supported configuration. The image render window in win will
++ * also be adjusted if necessary. The preview window is adjusted such that the
++ * horizontal and vertical rescaling ratios stay constant. If the render
++ * window would fall outside the display boundaries, the cropping rectangle
++ * will also be adjusted to maintain the rescaling ratios. If successful, crop
++ * and win are updated.
++ * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is
++ * impossible and cannot reasonably be adjusted.
++ */
++int omap_vout_new_crop(struct v4l2_pix_format *pix,
++ struct v4l2_rect *crop, struct v4l2_window *win,
++ struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop)
++{
++ struct v4l2_rect try_crop;
++ unsigned long vresize, hresize;
++
++ /* make a working copy of the new_crop rectangle */
++ try_crop = *new_crop;
++
++ /* adjust the cropping rectangle so it fits in the image */
++ if (try_crop.left < 0) {
++ try_crop.width += try_crop.left;
++ try_crop.left = 0;
++ }
++ if (try_crop.top < 0) {
++ try_crop.height += try_crop.top;
++ try_crop.top = 0;
++ }
++ try_crop.width = (try_crop.width < pix->width) ?
++ try_crop.width : pix->width;
++ try_crop.height = (try_crop.height < pix->height) ?
++ try_crop.height : pix->height;
++ if (try_crop.left + try_crop.width > pix->width)
++ try_crop.width = pix->width - try_crop.left;
++ if (try_crop.top + try_crop.height > pix->height)
++ try_crop.height = pix->height - try_crop.top;
++ try_crop.width &= ~1;
++ try_crop.height &= ~1;
++ if (try_crop.width <= 0 || try_crop.height <= 0)
++ return -EINVAL;
++
++ if (crop->height != win->w.height) {
++ /* If we're resizing vertically, we can't support a crop width
++ * wider than 768 pixels.
++ */
++ if (try_crop.width > 768)
++ try_crop.width = 768;
++ }
++ /* vertical resizing */
++ vresize = (1024 * crop->height) / win->w.height;
++ if (vresize > 4096)
++ vresize = 4096;
++ else if (vresize == 0)
++ vresize = 1;
++ win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
++ if (win->w.height == 0)
++ win->w.height = 2;
++ if (win->w.height + win->w.top > fbuf->fmt.height) {
++ /* We made the preview window extend below the bottom of the
++ * display, so clip it to the display boundary and resize the
++ * cropping height to maintain the vertical resizing ratio.
++ */
++ win->w.height = (fbuf->fmt.height - win->w.top) & ~1;
++ if (try_crop.height == 0)
++ try_crop.height = 2;
++ }
++ /* horizontal resizing */
++ hresize = (1024 * crop->width) / win->w.width;
++ if (hresize > 4096)
++ hresize = 4096;
++ else if (hresize == 0)
++ hresize = 1;
++ win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
++ if (win->w.width == 0)
++ win->w.width = 2;
++ if (win->w.width + win->w.left > fbuf->fmt.width) {
++ /* We made the preview window extend past the right side of the
++ * display, so clip it to the display boundary and resize the
++ * cropping width to maintain the horizontal resizing ratio.
++ */
++ win->w.width = (fbuf->fmt.width - win->w.left) & ~1;
++ if (try_crop.width == 0)
++ try_crop.width = 2;
++ }
++
++ /* Check for resizing constraints */
++ if ((try_crop.height/win->w.height) >= 4) {
++ /* The maximum vertical downsizing ratio is 4:1 */
++ try_crop.height = win->w.height * 4;
++ }
++ if ((try_crop.width/win->w.width) >= 4) {
++ /* The maximum horizontal downsizing ratio is 4:1 */
++ try_crop.width = win->w.width * 4;
++ }
++
++ /* update our cropping rectangle and we're done */
++ *crop = try_crop;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(omap_vout_new_crop);
++
++/* Given a new format in pix and fbuf, crop and win
++ * structures are initialized to default values. crop
++ * is initialized to the largest window size that will fit on the display. The
++ * crop window is centered in the image. win is initialized to
++ * the same size as crop and is centered on the display.
++ * All sizes and offsets are constrained to be even numbers.
++ */
++void omap_vout_new_format(struct v4l2_pix_format *pix,
++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
++ struct v4l2_window *win)
++{
++ /* crop defines the preview source window in the image capture
++ * buffer
++ */
++ omap_vout_default_crop(pix, fbuf, crop);
++
++ /* win defines the preview target window on the display */
++ win->w.width = crop->width;
++ win->w.height = crop->height;
++ win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1;
++ win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1;
++}
++EXPORT_SYMBOL_GPL(omap_vout_new_format);
++
+diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h
+new file mode 100644
+index 0000000..8ef6e25
+--- /dev/null
++++ b/drivers/media/video/omap/omap_voutlib.h
+@@ -0,0 +1,34 @@
++/*
++ * drivers/media/video/omap/omap_voutlib.h
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ *
++ */
++
++#ifndef OMAP_VOUTLIB_H
++#define OMAP_VOUTLIB_H
++
++extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
++
++extern int omap_vout_new_crop(struct v4l2_pix_format *pix,
++ struct v4l2_rect *crop, struct v4l2_window *win,
++ struct v4l2_framebuffer *fbuf,
++ const struct v4l2_rect *new_crop);
++
++extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
++ struct v4l2_window *new_win);
++
++extern int omap_vout_new_window(struct v4l2_rect *crop,
++ struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
++ struct v4l2_window *new_win);
++
++extern void omap_vout_new_format(struct v4l2_pix_format *pix,
++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
++ struct v4l2_window *win);
++#endif /* #ifndef OMAP_LIB_H */
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch b/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch
new file mode 100644
index 0000000000..0a38a31d76
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch
@@ -0,0 +1,378 @@
+From 4df5684fb6c8cab641a843d890bd010cb32ccc97 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 12:04:26 +0300
+Subject: [PATCH 05/18] OMAP: Add support for VRFB rotation engine
+
+VRFB rotation engine is a block in OMAP2/3 that offers 12 independent
+contexts that can be used for framebuffer rotation.
+
+Each context has a backend area of real memory, where it stores the
+pixels in undisclosed format. This memory is offered to users via 4
+virtual memory areas, which see the same memory area in different
+rotation angles (0, 90, 180 and 270 degrees).
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 46 ++++++
+ drivers/video/omap2/Kconfig | 3 +
+ drivers/video/omap2/Makefile | 1 +
+ drivers/video/omap2/vrfb.c | 277 ++++++++++++++++++++++++++++++++
+ 4 files changed, 327 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/plat-omap/include/mach/vrfb.h
+ create mode 100644 drivers/video/omap2/vrfb.c
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+new file mode 100644
+index 0000000..8790612
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -0,0 +1,46 @@
++/*
++ * VRFB Rotation Engine
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __OMAP_VRFB_H__
++#define __OMAP_VRFB_H__
++
++#define OMAP_VRFB_LINE_LEN 2048
++
++struct vrfb {
++ u8 context;
++ void __iomem *vaddr[4];
++ unsigned long paddr[4];
++ u16 xoffset;
++ u16 yoffset;
++ u8 bytespp;
++};
++
++extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
++ u8 bytespp);
++extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
++ u16 width, u16 height,
++ unsigned bytespp, bool yuv_mode);
++extern void omap_vrfb_restore_context(void);
++
++#endif /* __VRFB_H */
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+index 7a6c4c9..ac8b650 100644
+--- a/drivers/video/omap2/Kconfig
++++ b/drivers/video/omap2/Kconfig
+@@ -1,2 +1,5 @@
+ config OMAP2_VRAM
+ bool
++
++config OMAP2_VRFB
++ bool
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+index 7fdf7bd..aa3751b 100644
+--- a/drivers/video/omap2/Makefile
++++ b/drivers/video/omap2/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_OMAP2_VRAM) += vram.o
++obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
+diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
+new file mode 100644
+index 0000000..8726689
+--- /dev/null
++++ b/drivers/video/omap2/vrfb.c
+@@ -0,0 +1,277 @@
++/*
++ * VRFB Rotation Engine
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/bitops.h>
++#include <linux/mutex.h>
++
++#include <mach/io.h>
++#include <mach/vrfb.h>
++#include <mach/sdrc.h>
++/*#define DEBUG*/
++
++#ifdef DEBUG
++#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define SMS_ROT_VIRT_BASE(context, rot) \
++ (((context >= 4) ? 0xD0000000 : 0x70000000) \
++ + (0x4000000 * (context)) \
++ + (0x1000000 * (rot)))
++
++#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
++
++#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
++#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
++#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
++#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
++#define SMS_IMAGEHEIGHT_OFFSET 16
++#define SMS_IMAGEWIDTH_OFFSET 0
++#define SMS_PH_OFFSET 8
++#define SMS_PW_OFFSET 4
++#define SMS_PS_OFFSET 0
++
++#define VRFB_NUM_CTXS 12
++/* bitmap of reserved contexts */
++static unsigned long ctx_map;
++/* bitmap of contexts for which we have to keep the HW context valid */
++static unsigned long ctx_map_active;
++
++static DEFINE_MUTEX(ctx_lock);
++
++/*
++ * Access to this happens from client drivers or the PM core after wake-up.
++ * For the first case we require locking at the driver level, for the second
++ * we don't need locking, since no drivers will run until after the wake-up
++ * has finished.
++ */
++static struct {
++ u32 physical_ba;
++ u32 control;
++ u32 size;
++} vrfb_hw_context[VRFB_NUM_CTXS];
++
++static inline void restore_hw_context(int ctx)
++{
++ omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
++ omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
++ omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
++}
++
++void omap_vrfb_restore_context(void)
++{
++ int i;
++ unsigned long map = ctx_map_active;
++
++ for (i = ffs(map); i; i = ffs(map)) {
++ /* i=1..32 */
++ i--;
++ map &= ~(1 << i);
++ restore_hw_context(i);
++ }
++}
++
++void omap_vrfb_adjust_size(u16 *width, u16 *height,
++ u8 bytespp)
++{
++ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
++ *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
++}
++EXPORT_SYMBOL(omap_vrfb_adjust_size);
++
++void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
++ u16 width, u16 height,
++ unsigned bytespp, bool yuv_mode)
++{
++ unsigned pixel_size_exp;
++ u16 vrfb_width;
++ u16 vrfb_height;
++ u8 ctx = vrfb->context;
++ u32 size;
++ u32 control;
++
++ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
++ width, height, color_mode);
++
++ /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
++ * differently. See TRM. */
++ if (yuv_mode) {
++ bytespp *= 2;
++ width /= 2;
++ }
++
++ if (bytespp == 4)
++ pixel_size_exp = 2;
++ else if (bytespp == 2)
++ pixel_size_exp = 1;
++ else
++ BUG();
++
++ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
++ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
++
++ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
++
++ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
++ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
++
++ control = pixel_size_exp << SMS_PS_OFFSET;
++ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
++ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
++
++ vrfb_hw_context[ctx].physical_ba = paddr;
++ vrfb_hw_context[ctx].size = size;
++ vrfb_hw_context[ctx].control = control;
++
++ omap2_sms_write_rot_physical_ba(paddr, ctx);
++ omap2_sms_write_rot_size(size, ctx);
++ omap2_sms_write_rot_control(control, ctx);
++
++ DBG("vrfb offset pixels %d, %d\n",
++ vrfb_width - width, vrfb_height - height);
++
++ vrfb->xoffset = vrfb_width - width;
++ vrfb->yoffset = vrfb_height - height;
++ vrfb->bytespp = bytespp;
++}
++EXPORT_SYMBOL(omap_vrfb_setup);
++
++void omap_vrfb_release_ctx(struct vrfb *vrfb)
++{
++ int rot;
++ int ctx = vrfb->context;
++
++ if (ctx == 0xff)
++ return;
++
++ DBG("release ctx %d\n", ctx);
++
++ mutex_lock(&ctx_lock);
++
++ BUG_ON(!(ctx_map & (1 << ctx)));
++
++ clear_bit(ctx, &ctx_map_active);
++ clear_bit(ctx, &ctx_map);
++
++ for (rot = 0; rot < 4; ++rot) {
++ if (vrfb->paddr[rot]) {
++ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
++ vrfb->paddr[rot] = 0;
++ }
++ }
++
++ vrfb->context = 0xff;
++
++ mutex_unlock(&ctx_lock);
++}
++EXPORT_SYMBOL(omap_vrfb_release_ctx);
++
++int omap_vrfb_request_ctx(struct vrfb *vrfb)
++{
++ int rot;
++ u32 paddr;
++ u8 ctx;
++ int r;
++
++ DBG("request ctx\n");
++
++ mutex_lock(&ctx_lock);
++
++ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
++ if ((ctx_map & (1 << ctx)) == 0)
++ break;
++
++ if (ctx == VRFB_NUM_CTXS) {
++ pr_err("vrfb: no free contexts\n");
++ r = -EBUSY;
++ goto out;
++ }
++
++ DBG("found free ctx %d\n", ctx);
++
++ set_bit(ctx, &ctx_map);
++ WARN_ON(ctx_map_active & (1 << ctx));
++ set_bit(ctx, &ctx_map_active);
++
++ memset(vrfb, 0, sizeof(*vrfb));
++
++ vrfb->context = ctx;
++
++ for (rot = 0; rot < 4; ++rot) {
++ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
++ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
++ pr_err("vrfb: failed to reserve VRFB "
++ "area for ctx %d, rotation %d\n",
++ ctx, rot * 90);
++ omap_vrfb_release_ctx(vrfb);
++ r = -ENOMEM;
++ goto out;
++ }
++
++ vrfb->paddr[rot] = paddr;
++
++ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
++ }
++
++ r = 0;
++out:
++ mutex_unlock(&ctx_lock);
++ return r;
++}
++EXPORT_SYMBOL(omap_vrfb_request_ctx);
++
++void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
++{
++ DBG("suspend ctx %d\n", vrfb->context);
++ mutex_lock(&ctx_lock);
++
++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
++ BUG_ON(!((1 << vrfb->context) & ctx_map_active));
++
++ clear_bit(vrfb->context, &ctx_map_active);
++ mutex_unlock(&ctx_lock);
++}
++EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
++
++void omap_vrfb_resume_ctx(struct vrfb *vrfb)
++{
++ DBG("resume ctx %d\n", vrfb->context);
++ mutex_lock(&ctx_lock);
++
++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
++ BUG_ON((1 << vrfb->context) & ctx_map_active);
++
++ /*
++ * omap_vrfb_restore_context is normally called by the core domain
++ * save / restore logic, but since this VRFB context was suspended
++ * those calls didn't actually restore the context and now we might
++ * have an invalid context. Do an explicit restore here.
++ */
++ restore_hw_context(vrfb->context);
++ set_bit(vrfb->context, &ctx_map_active);
++ mutex_unlock(&ctx_lock);
++}
++EXPORT_SYMBOL(omap_vrfb_resume_ctx);
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch b/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch
new file mode 100644
index 0000000000..ab159d5183
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch
@@ -0,0 +1,337 @@
+From f7ffb36c21956befc2b8b51cf4db0e99f954ae06 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 4 Aug 2009 15:47:11 +0300
+Subject: [PATCH 06/18] OMAP: DSS2: Documentation for DSS2
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ Documentation/arm/OMAP/DSS | 317 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 317 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/arm/OMAP/DSS
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+new file mode 100644
+index 0000000..0af0e9e
+--- /dev/null
++++ b/Documentation/arm/OMAP/DSS
+@@ -0,0 +1,317 @@
++OMAP2/3 Display Subsystem
++-------------------------
++
++This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
++(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
++TV-out and multiple display support, but there are lots of small improvements
++also.
++
++The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
++panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
++currently side by side, you can choose which one to use.
++
++Features
++--------
++
++Working and tested features include:
++
++- MIPI DPI (parallel) output
++- MIPI DSI output in command mode
++- MIPI DBI (RFBI) output
++- SDI output
++- TV output
++- All pieces can be compiled as a module or inside kernel
++- Use DISPC to update any of the outputs
++- Use CPU to update RFBI or DSI output
++- OMAP DISPC planes
++- RGB16, RGB24 packed, RGB24 unpacked
++- YUV2, UYVY
++- Scaling
++- Adjusting DSS FCK to find a good pixel clock
++- Use DSI DPLL to create DSS FCK
++
++Tested boards include:
++- OMAP3 SDP board
++- Beagle board
++- N810
++
++omapdss driver
++--------------
++
++The DSS driver does not itself have any support for Linux framebuffer, V4L or
++such like the current ones, but it has an internal kernel API that upper level
++drivers can use.
++
++The DSS driver models OMAP's overlays, overlay managers and displays in a
++flexible way to enable non-common multi-display configuration. In addition to
++modelling the hardware overlays, omapdss supports virtual overlays and overlay
++managers. These can be used when updating a display with CPU or system DMA.
++
++Panel and controller drivers
++----------------------------
++
++The drivers implement panel or controller specific functionality and are not
++usually visible to users except through omapfb driver. They register
++themselves to the DSS driver.
++
++omapfb driver
++-------------
++
++The omapfb driver implements arbitrary number of standard linux framebuffers.
++These framebuffers can be routed flexibly to any overlays, thus allowing very
++dynamic display architecture.
++
++The driver exports some omapfb specific ioctls, which are compatible with the
++ioctls in the old driver.
++
++The rest of the non standard features are exported via sysfs. Whether the final
++implementation will use sysfs, or ioctls, is still open.
++
++V4L2 drivers
++------------
++
++V4L2 is being implemented in TI.
++
++From omapdss point of view the V4L2 drivers should be similar to framebuffer
++driver.
++
++Architecture
++--------------------
++
++Some clarification what the different components do:
++
++ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
++ pixel data for the image. Framebuffer has width and height and color
++ depth.
++ - Overlay defines where the pixels are read from and where they go on the
++ screen. The overlay may be smaller than framebuffer, thus displaying only
++ part of the framebuffer. The position of the overlay may be changed if
++ the overlay is smaller than the display.
++ - Overlay manager combines the overlays in to one image and feeds them to
++ display.
++ - Display is the actual physical display device.
++
++A framebuffer can be connected to multiple overlays to show the same pixel data
++on all of the overlays. Note that in this case the overlay input sizes must be
++the same, but, in case of video overlays, the output size can be different. Any
++framebuffer can be connected to any overlay.
++
++An overlay can be connected to one overlay manager. Also DISPC overlays can be
++connected only to DISPC overlay managers, and virtual overlays can be only
++connected to virtual overlays.
++
++An overlay manager can be connected to one display. There are certain
++restrictions which kinds of displays an overlay manager can be connected:
++
++ - DISPC TV overlay manager can be only connected to TV display.
++ - Virtual overlay managers can only be connected to DBI or DSI displays.
++ - DISPC LCD overlay manager can be connected to all displays, except TV
++ display.
++
++Sysfs
++-----
++The sysfs interface is mainly used for testing. I don't think sysfs
++interface is the best for this in the final version, but I don't quite know
++what would be the best interfaces for these things.
++
++The sysfs interface is divided to two parts: DSS and FB.
++
++/sys/class/graphics/fb? directory:
++mirror 0=off, 1=on
++rotate Rotation 0-3 for 0, 90, 180, 270 degrees
++rotate_type 0 = DMA rotation, 1 = VRFB rotation
++overlays List of overlay numbers to which framebuffer pixels go
++phys_addr Physical address of the framebuffer
++virt_addr Virtual address of the framebuffer
++size Size of the framebuffer
++
++/sys/devices/platform/omapdss/overlay? directory:
++enabled 0=off, 1=on
++input_size width,height (ie. the framebuffer size)
++manager Destination overlay manager name
++name
++output_size width,height
++position x,y
++screen_width width
++global_alpha global alpha 0-255 0=transparent 255=opaque
++
++/sys/devices/platform/omapdss/manager? directory:
++display Destination display
++name
++alpha_blending_enabled 0=off, 1=on
++trans_key_enabled 0=off, 1=on
++trans_key_type gfx-destination, video-source
++trans_key_value transparency color key (RGB24)
++default_color default background color (RGB24)
++
++/sys/devices/platform/omapdss/display? directory:
++ctrl_name Controller name
++mirror 0=off, 1=on
++update_mode 0=off, 1=auto, 2=manual
++enabled 0=off, 1=on
++name
++rotate Rotation 0-3 for 0, 90, 180, 270 degrees
++timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
++ When writing, two special timings are accepted for tv-out:
++ "pal" and "ntsc"
++panel_name
++tear_elim Tearing elimination 0=off, 1=on
++
++There are also some debugfs files at <debugfs>/omapdss/ which show information
++about clocks and registers.
++
++Examples
++--------
++
++The following definitions have been made for the examples below:
++
++ovl0=/sys/devices/platform/omapdss/overlay0
++ovl1=/sys/devices/platform/omapdss/overlay1
++ovl2=/sys/devices/platform/omapdss/overlay2
++
++mgr0=/sys/devices/platform/omapdss/manager0
++mgr1=/sys/devices/platform/omapdss/manager1
++
++lcd=/sys/devices/platform/omapdss/display0
++dvi=/sys/devices/platform/omapdss/display1
++tv=/sys/devices/platform/omapdss/display2
++
++fb0=/sys/class/graphics/fb0
++fb1=/sys/class/graphics/fb1
++fb2=/sys/class/graphics/fb2
++
++Default setup on OMAP3 SDP
++--------------------------
++
++Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
++and TV-out are not in use. The columns from left to right are:
++framebuffers, overlays, overlay managers, displays. Framebuffers are
++handled by omapfb, and the rest by the DSS.
++
++FB0 --- GFX -\ DVI
++FB1 --- VID1 --+- LCD ---- LCD
++FB2 --- VID2 -/ TV ----- TV
++
++Example: Switch from LCD to DVI
++----------------------
++
++w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
++h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
++
++echo "0" > $lcd/enabled
++echo "" > $mgr0/display
++fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
++# at this point you have to switch the dvi/lcd dip-switch from the omap board
++echo "dvi" > $mgr0/display
++echo "1" > $dvi/enabled
++
++After this the configuration looks like:
++
++FB0 --- GFX -\ -- DVI
++FB1 --- VID1 --+- LCD -/ LCD
++FB2 --- VID2 -/ TV ----- TV
++
++Example: Clone GFX overlay to LCD and TV
++-------------------------------
++
++w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
++h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
++
++echo "0" > $ovl0/enabled
++echo "0" > $ovl1/enabled
++
++echo "" > $fb1/overlays
++echo "0,1" > $fb0/overlays
++
++echo "$w,$h" > $ovl1/output_size
++echo "tv" > $ovl1/manager
++
++echo "1" > $ovl0/enabled
++echo "1" > $ovl1/enabled
++
++echo "1" > $tv/enabled
++
++After this the configuration looks like (only relevant parts shown):
++
++FB0 +-- GFX ---- LCD ---- LCD
++ \- VID1 ---- TV ---- TV
++
++Misc notes
++----------
++
++OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
++
++Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
++of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
++
++Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
++does not support mirroring.
++
++VRFB rotation requires much more memory than non-rotated framebuffer, so you
++probably need to increase your vram setting before using VRFB rotation. Also,
++many applications may not work with VRFB if they do not pay attention to all
++framebuffer parameters.
++
++Kernel boot arguments
++---------------------
++
++vram=<size>
++ - Amount of total VRAM to preallocate. For example, "10M". omapfb
++ allocates memory for framebuffers from VRAM.
++
++omapfb.mode=<display>:<mode>[,...]
++ - Default video mode for specified displays. For example,
++ "dvi:800x400MR-24@60". See drivers/video/modedb.c.
++ There are also two special modes: "pal" and "ntsc" that
++ can be used to tv out.
++
++omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
++ - VRAM allocated for a framebuffer. Normally omapfb allocates vram
++ depending on the display size. With this you can manually allocate
++ more or define the physical address of each framebuffer. For example,
++ "1:4M" to allocate 4M for fb1.
++
++omapfb.debug=<y|n>
++ - Enable debug printing. You have to have OMAPFB debug support enabled
++ in kernel config.
++
++omapfb.test=<y|n>
++ - Draw test pattern to framebuffer whenever framebuffer settings change.
++ You need to have OMAPFB debug support enabled in kernel config.
++
++omapfb.vrfb=<y|n>
++ - Use VRFB rotation for all framebuffers.
++
++omapfb.rotate=<angle>
++ - Default rotation applied to all framebuffers.
++ 0 - 0 degree rotation
++ 1 - 90 degree rotation
++ 2 - 180 degree rotation
++ 3 - 270 degree rotation
++
++omapfb.mirror=<y|n>
++ - Default mirror for all framebuffers. Only works with DMA rotation.
++
++omapdss.def_disp=<display>
++ - Name of default display, to which all overlays will be connected.
++ Common examples are "lcd" or "tv".
++
++omapdss.debug=<y|n>
++ - Enable debug printing. You have to have DSS debug support enabled in
++ kernel config.
++
++TODO
++----
++
++DSS locking
++
++Error checking
++- Lots of checks are missing or implemented just as BUG()
++
++System DMA update for DSI
++- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
++ to skip the empty byte?)
++
++OMAP1 support
++- Not sure if needed
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch b/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch
new file mode 100644
index 0000000000..8692200e02
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch
@@ -0,0 +1,2341 @@
+From 17254fca49c4f3a8897a6afb10af3416a691cb8a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 13:42:34 +0300
+Subject: [PATCH 07/18] OMAP: DSS2: Display Subsystem Driver core
+
+The core files of DSS2. DSS2 commits are split a bit artificially to
+make the individual commits smaller, and DSS2 doesn't compile properly
+without the rest of the core commits. This shouldn't be a problem, as no
+configuration uses DSS2 yet.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 540 +++++++++++++++++
+ drivers/video/omap2/Kconfig | 2 +
+ drivers/video/omap2/Makefile | 2 +
+ drivers/video/omap2/dss/Kconfig | 89 +++
+ drivers/video/omap2/dss/Makefile | 6 +
+ drivers/video/omap2/dss/core.c | 917 +++++++++++++++++++++++++++++
+ drivers/video/omap2/dss/dss.c | 347 +++++++++++
+ drivers/video/omap2/dss/dss.h | 356 +++++++++++
+ 8 files changed, 2259 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/plat-omap/include/mach/display.h
+ create mode 100644 drivers/video/omap2/dss/Kconfig
+ create mode 100644 drivers/video/omap2/dss/Makefile
+ create mode 100644 drivers/video/omap2/dss/core.c
+ create mode 100644 drivers/video/omap2/dss/dss.c
+ create mode 100644 drivers/video/omap2/dss/dss.h
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+new file mode 100644
+index 0000000..4c7422e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -0,0 +1,540 @@
++/*
++ * linux/include/asm-arm/arch-omap/display.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ASM_ARCH_OMAP_DISPLAY_H
++#define __ASM_ARCH_OMAP_DISPLAY_H
++
++#include <linux/list.h>
++#include <linux/kobject.h>
++#include <linux/device.h>
++#include <asm/atomic.h>
++
++#define DISPC_IRQ_FRAMEDONE (1 << 0)
++#define DISPC_IRQ_VSYNC (1 << 1)
++#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
++#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
++#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
++#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
++#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
++#define DISPC_IRQ_GFX_END_WIN (1 << 7)
++#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
++#define DISPC_IRQ_OCP_ERR (1 << 9)
++#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
++#define DISPC_IRQ_VID1_END_WIN (1 << 11)
++#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
++#define DISPC_IRQ_VID2_END_WIN (1 << 13)
++#define DISPC_IRQ_SYNC_LOST (1 << 14)
++#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
++#define DISPC_IRQ_WAKEUP (1 << 16)
++
++struct omap_dss_device;
++struct omap_overlay_manager;
++
++enum omap_display_type {
++ OMAP_DISPLAY_TYPE_NONE = 0,
++ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
++ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
++ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
++ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
++ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
++};
++
++enum omap_plane {
++ OMAP_DSS_GFX = 0,
++ OMAP_DSS_VIDEO1 = 1,
++ OMAP_DSS_VIDEO2 = 2
++};
++
++enum omap_channel {
++ OMAP_DSS_CHANNEL_LCD = 0,
++ OMAP_DSS_CHANNEL_DIGIT = 1,
++};
++
++enum omap_color_mode {
++ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
++ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
++ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
++ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
++ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
++ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
++ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
++ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
++ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
++ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
++ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
++ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
++ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
++ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
++
++ OMAP_DSS_COLOR_GFX_OMAP3 =
++ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
++ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
++
++ OMAP_DSS_COLOR_VID_OMAP3 =
++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
++ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
++};
++
++enum omap_lcd_display_type {
++ OMAP_DSS_LCD_DISPLAY_STN,
++ OMAP_DSS_LCD_DISPLAY_TFT,
++};
++
++enum omap_dss_load_mode {
++ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
++ OMAP_DSS_LOAD_CLUT_ONLY = 1,
++ OMAP_DSS_LOAD_FRAME_ONLY = 2,
++ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
++};
++
++enum omap_dss_trans_key_type {
++ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
++ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
++};
++
++enum omap_rfbi_te_mode {
++ OMAP_DSS_RFBI_TE_MODE_1 = 1,
++ OMAP_DSS_RFBI_TE_MODE_2 = 2,
++};
++
++enum omap_panel_config {
++ OMAP_DSS_LCD_IVS = 1<<0,
++ OMAP_DSS_LCD_IHS = 1<<1,
++ OMAP_DSS_LCD_IPC = 1<<2,
++ OMAP_DSS_LCD_IEO = 1<<3,
++ OMAP_DSS_LCD_RF = 1<<4,
++ OMAP_DSS_LCD_ONOFF = 1<<5,
++
++ OMAP_DSS_LCD_TFT = 1<<20,
++};
++
++enum omap_dss_venc_type {
++ OMAP_DSS_VENC_TYPE_COMPOSITE,
++ OMAP_DSS_VENC_TYPE_SVIDEO,
++};
++
++enum omap_display_caps {
++ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
++};
++
++enum omap_dss_update_mode {
++ OMAP_DSS_UPDATE_DISABLED = 0,
++ OMAP_DSS_UPDATE_AUTO,
++ OMAP_DSS_UPDATE_MANUAL,
++};
++
++enum omap_dss_display_state {
++ OMAP_DSS_DISPLAY_DISABLED = 0,
++ OMAP_DSS_DISPLAY_ACTIVE,
++ OMAP_DSS_DISPLAY_SUSPENDED,
++};
++
++/* XXX perhaps this should be removed */
++enum omap_dss_overlay_managers {
++ OMAP_DSS_OVL_MGR_LCD,
++ OMAP_DSS_OVL_MGR_TV,
++};
++
++enum omap_dss_rotation_type {
++ OMAP_DSS_ROT_DMA = 0,
++ OMAP_DSS_ROT_VRFB = 1,
++};
++
++enum omap_overlay_caps {
++ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
++ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
++};
++
++enum omap_overlay_manager_caps {
++ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
++};
++
++/* RFBI */
++
++struct rfbi_timings {
++ int cs_on_time;
++ int cs_off_time;
++ int we_on_time;
++ int we_off_time;
++ int re_on_time;
++ int re_off_time;
++ int we_cycle_time;
++ int re_cycle_time;
++ int cs_pulse_width;
++ int access_time;
++
++ int clk_div;
++
++ u32 tim[5]; /* set by rfbi_convert_timings() */
++
++ int converted;
++};
++
++void omap_rfbi_write_command(const void *buf, u32 len);
++void omap_rfbi_read_data(void *buf, u32 len);
++void omap_rfbi_write_data(const void *buf, u32 len);
++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
++ u16 x, u16 y,
++ u16 w, u16 h);
++int omap_rfbi_enable_te(bool enable, unsigned line);
++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int extif_div);
++
++/* DSI */
++void dsi_bus_lock(void);
++void dsi_bus_unlock(void);
++int dsi_vc_dcs_write(int channel, u8 *data, int len);
++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
++int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
++int dsi_vc_send_null(int channel);
++int dsi_vc_send_bta_sync(int channel);
++
++/* Board specific data */
++struct omap_dss_board_info {
++ int (*get_last_off_on_transaction_id)(struct device *dev);
++ int num_devices;
++ struct omap_dss_device **devices;
++ struct omap_dss_device *default_device;
++};
++
++struct omap_video_timings {
++ /* Unit: pixels */
++ u16 x_res;
++ /* Unit: pixels */
++ u16 y_res;
++ /* Unit: KHz */
++ u32 pixel_clock;
++ /* Unit: pixel clocks */
++ u16 hsw; /* Horizontal synchronization pulse width */
++ /* Unit: pixel clocks */
++ u16 hfp; /* Horizontal front porch */
++ /* Unit: pixel clocks */
++ u16 hbp; /* Horizontal back porch */
++ /* Unit: line clocks */
++ u16 vsw; /* Vertical synchronization pulse width */
++ /* Unit: line clocks */
++ u16 vfp; /* Vertical front porch */
++ /* Unit: line clocks */
++ u16 vbp; /* Vertical back porch */
++};
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++/* Hardcoded timings for tv modes. Venc only uses these to
++ * identify the mode, and does not actually use the configs
++ * itself. However, the configs should be something that
++ * a normal monitor can also show */
++const extern struct omap_video_timings omap_dss_pal_timings;
++const extern struct omap_video_timings omap_dss_ntsc_timings;
++#endif
++
++struct omap_overlay_info {
++ bool enabled;
++
++ u32 paddr;
++ void __iomem *vaddr;
++ u16 screen_width;
++ u16 width;
++ u16 height;
++ enum omap_color_mode color_mode;
++ u8 rotation;
++ enum omap_dss_rotation_type rotation_type;
++ bool mirror;
++
++ u16 pos_x;
++ u16 pos_y;
++ u16 out_width; /* if 0, out_width == width */
++ u16 out_height; /* if 0, out_height == height */
++ u8 global_alpha;
++};
++
++struct omap_overlay {
++ struct kobject kobj;
++ struct list_head list;
++
++ /* static fields */
++ const char *name;
++ int id;
++ enum omap_color_mode supported_modes;
++ enum omap_overlay_caps caps;
++
++ /* dynamic fields */
++ struct omap_overlay_manager *manager;
++ struct omap_overlay_info info;
++
++ /* if true, info has been changed, but not applied() yet */
++ bool info_dirty;
++
++ int (*set_manager)(struct omap_overlay *ovl,
++ struct omap_overlay_manager *mgr);
++ int (*unset_manager)(struct omap_overlay *ovl);
++
++ int (*set_overlay_info)(struct omap_overlay *ovl,
++ struct omap_overlay_info *info);
++ void (*get_overlay_info)(struct omap_overlay *ovl,
++ struct omap_overlay_info *info);
++
++ int (*wait_for_go)(struct omap_overlay *ovl);
++};
++
++struct omap_overlay_manager_info {
++ u32 default_color;
++
++ enum omap_dss_trans_key_type trans_key_type;
++ u32 trans_key;
++ bool trans_enabled;
++
++ bool alpha_enabled;
++};
++
++struct omap_overlay_manager {
++ struct kobject kobj;
++ struct list_head list;
++
++ /* static fields */
++ const char *name;
++ int id;
++ enum omap_overlay_manager_caps caps;
++ int num_overlays;
++ struct omap_overlay **overlays;
++ enum omap_display_type supported_displays;
++
++ /* dynamic fields */
++ struct omap_dss_device *device;
++ struct omap_overlay_manager_info info;
++
++ bool device_changed;
++ /* if true, info has been changed but not applied() yet */
++ bool info_dirty;
++
++ int (*set_device)(struct omap_overlay_manager *mgr,
++ struct omap_dss_device *dssdev);
++ int (*unset_device)(struct omap_overlay_manager *mgr);
++
++ int (*set_manager_info)(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info);
++ void (*get_manager_info)(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info);
++
++ int (*apply)(struct omap_overlay_manager *mgr);
++ int (*wait_for_go)(struct omap_overlay_manager *mgr);
++};
++
++struct omap_dss_device {
++ struct device dev;
++
++ enum omap_display_type type;
++
++ union {
++ struct {
++ u8 data_lines;
++ } dpi;
++
++ struct {
++ u8 channel;
++ u8 data_lines;
++ } rfbi;
++
++ struct {
++ u8 datapairs;
++ } sdi;
++
++ struct {
++ u8 clk_lane;
++ u8 clk_pol;
++ u8 data1_lane;
++ u8 data1_pol;
++ u8 data2_lane;
++ u8 data2_pol;
++ unsigned long lp_clk_hz;
++ unsigned long ddr_clk_hz;
++
++ bool ext_te;
++ u8 ext_te_gpio;
++ } dsi;
++
++ struct {
++ enum omap_dss_venc_type type;
++ bool invert_polarity;
++ } venc;
++ } phy;
++
++ struct {
++ struct omap_video_timings timings;
++
++ int acbi; /* ac-bias pin transitions per interrupt */
++ /* Unit: line clocks */
++ int acb; /* ac-bias pin frequency */
++
++ enum omap_panel_config config;
++
++ u8 recommended_bpp;
++
++ struct omap_dss_device *ctrl;
++ } panel;
++
++ struct {
++ u8 pixel_size;
++ struct rfbi_timings rfbi_timings;
++ struct omap_dss_device *panel;
++ } ctrl;
++
++ int reset_gpio;
++
++ int max_backlight_level;
++
++ const char *name;
++
++ /* used to match device to driver */
++ const char *driver_name;
++
++ void *data;
++
++ struct omap_dss_driver *driver;
++
++ /* helper variable for driver suspend/resume */
++ bool activate_after_resume;
++
++ enum omap_display_caps caps;
++
++ struct omap_overlay_manager *manager;
++
++ enum omap_dss_display_state state;
++
++ int (*enable)(struct omap_dss_device *dssdev);
++ void (*disable)(struct omap_dss_device *dssdev);
++
++ int (*suspend)(struct omap_dss_device *dssdev);
++ int (*resume)(struct omap_dss_device *dssdev);
++
++ void (*get_resolution)(struct omap_dss_device *dssdev,
++ u16 *xres, u16 *yres);
++ int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
++
++ int (*check_timings)(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings);
++ void (*set_timings)(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings);
++ void (*get_timings)(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings);
++ int (*update)(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h);
++ int (*sync)(struct omap_dss_device *dssdev);
++ int (*wait_vsync)(struct omap_dss_device *dssdev);
++
++ int (*set_update_mode)(struct omap_dss_device *dssdev,
++ enum omap_dss_update_mode);
++ enum omap_dss_update_mode (*get_update_mode)
++ (struct omap_dss_device *dssdev);
++
++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
++ int (*get_te)(struct omap_dss_device *dssdev);
++
++ u8 (*get_rotate)(struct omap_dss_device *dssdev);
++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
++
++ bool (*get_mirror)(struct omap_dss_device *dssdev);
++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
++
++ int (*run_test)(struct omap_dss_device *dssdev, int test);
++ int (*memory_read)(struct omap_dss_device *dssdev,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h);
++
++ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
++ u32 (*get_wss)(struct omap_dss_device *dssdev);
++
++ /* platform specific */
++ int (*platform_enable)(struct omap_dss_device *dssdev);
++ void (*platform_disable)(struct omap_dss_device *dssdev);
++ int (*set_backlight)(struct omap_dss_device *dssdev, int level);
++ int (*get_backlight)(struct omap_dss_device *dssdev);
++};
++
++struct omap_dss_driver {
++ struct device_driver driver;
++
++ int (*probe)(struct omap_dss_device *);
++ void (*remove)(struct omap_dss_device *);
++
++ int (*enable)(struct omap_dss_device *display);
++ void (*disable)(struct omap_dss_device *display);
++ int (*suspend)(struct omap_dss_device *display);
++ int (*resume)(struct omap_dss_device *display);
++ int (*run_test)(struct omap_dss_device *display, int test);
++
++ void (*setup_update)(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h);
++
++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
++ int (*wait_for_te)(struct omap_dss_device *dssdev);
++
++ u8 (*get_rotate)(struct omap_dss_device *dssdev);
++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
++
++ bool (*get_mirror)(struct omap_dss_device *dssdev);
++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
++
++ int (*memory_read)(struct omap_dss_device *dssdev,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h);
++};
++
++int omap_dss_register_driver(struct omap_dss_driver *);
++void omap_dss_unregister_driver(struct omap_dss_driver *);
++
++int omap_dss_register_device(struct omap_dss_device *);
++void omap_dss_unregister_device(struct omap_dss_device *);
++
++void omap_dss_get_device(struct omap_dss_device *dssdev);
++void omap_dss_put_device(struct omap_dss_device *dssdev);
++#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
++struct omap_dss_device *omap_dss_find_device(void *data,
++ int (*match)(struct omap_dss_device *dssdev, void *data));
++
++int omap_dss_start_device(struct omap_dss_device *dssdev);
++void omap_dss_stop_device(struct omap_dss_device *dssdev);
++
++int omap_dss_get_num_overlay_managers(void);
++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
++
++int omap_dss_get_num_overlays(void);
++struct omap_overlay *omap_dss_get_overlay(int num);
++
++typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
++
++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
++ unsigned long timeout);
++
++#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
++#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
++
++#endif
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+index ac8b650..55b4c42 100644
+--- a/drivers/video/omap2/Kconfig
++++ b/drivers/video/omap2/Kconfig
+@@ -3,3 +3,5 @@ config OMAP2_VRAM
+
+ config OMAP2_VRFB
+ bool
++
++source "drivers/video/omap2/dss/Kconfig"
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+index aa3751b..ee0644f 100644
+--- a/drivers/video/omap2/Makefile
++++ b/drivers/video/omap2/Makefile
+@@ -1,2 +1,4 @@
+ obj-$(CONFIG_OMAP2_VRAM) += vram.o
+ obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
++
++obj-y += dss/
+diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
+new file mode 100644
+index 0000000..71d8dec
+--- /dev/null
++++ b/drivers/video/omap2/dss/Kconfig
+@@ -0,0 +1,89 @@
++menuconfig OMAP2_DSS
++ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
++ depends on ARCH_OMAP2 || ARCH_OMAP3
++ help
++ OMAP2/3 Display Subsystem support.
++
++if OMAP2_DSS
++
++config OMAP2_VRAM_SIZE
++ int "VRAM size (MB)"
++ range 0 32
++ default 0
++ help
++ The amount of SDRAM to reserve at boot time for video RAM use.
++ This VRAM will be used by omapfb and other drivers that need
++ large continuous RAM area for video use.
++
++ You can also set this with "vram=<bytes>" kernel argument, or
++ in the board file.
++
++config OMAP2_DSS_DEBUG_SUPPORT
++ bool "Debug support"
++ default y
++ help
++ This enables debug messages. You need to enable printing
++ with 'debug' module parameter.
++
++config OMAP2_DSS_RFBI
++ bool "RFBI support"
++ default n
++ help
++ MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
++
++config OMAP2_DSS_VENC
++ bool "VENC support"
++ default y
++ help
++ OMAP Video Encoder support.
++
++config OMAP2_DSS_SDI
++ bool "SDI support"
++ depends on ARCH_OMAP3
++ default n
++ help
++ SDI (Serial Display Interface) support.
++
++config OMAP2_DSS_DSI
++ bool "DSI support"
++ depends on ARCH_OMAP3
++ default n
++ help
++ MIPI DSI support.
++
++config OMAP2_DSS_USE_DSI_PLL
++ bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
++ default n
++ depends on OMAP2_DSS_DSI
++ help
++ Use DSI PLL to generate pixel clock. Currently only for DPI output.
++ DSI PLL can be used to generate higher and more precise pixel clocks.
++
++config OMAP2_DSS_FAKE_VSYNC
++ bool "Fake VSYNC irq from manual update displays"
++ default n
++ help
++ If this is selected, DSI will generate a fake DISPC VSYNC interrupt
++ when DSI has sent a frame. This is only needed with DSI or RFBI
++ displays using manual mode, and you want VSYNC to, for example,
++ time animation.
++
++config OMAP2_DSS_MIN_FCK_PER_PCK
++ int "Minimum FCK/PCK ratio (for scaling)"
++ range 0 32
++ default 0
++ help
++ This can be used to adjust the minimum FCK/PCK ratio.
++
++ With this you can make sure that DISPC FCK is at least
++ n x PCK. Video plane scaling requires higher FCK than
++ normally.
++
++ If this is set to 0, there's no extra constraint on the
++ DISPC FCK. However, the FCK will at minimum be
++ 2xPCK (if active matrix) or 3xPCK (if passive matrix).
++
++ Max FCK is 173MHz, so this doesn't work if your PCK
++ is very high.
++
++endif
+diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
+new file mode 100644
+index 0000000..980c72c
+--- /dev/null
++++ b/drivers/video/omap2/dss/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_OMAP2_DSS) += omapdss.o
++omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
++omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
++omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
++omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
++omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+new file mode 100644
+index 0000000..e8d430c
+--- /dev/null
++++ b/drivers/video/omap2/dss/core.c
+@@ -0,0 +1,917 @@
++/*
++ * linux/drivers/video/omap2/dss/core.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "CORE"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/platform_device.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
++#include <linux/io.h>
++#include <linux/device.h>
++
++#include <mach/display.h>
++#include <mach/clock.h>
++
++#include "dss.h"
++
++static struct {
++ struct platform_device *pdev;
++ int ctx_id;
++
++ struct clk *dss_ick;
++ struct clk *dss1_fck;
++ struct clk *dss2_fck;
++ struct clk *dss_54m_fck;
++ struct clk *dss_96m_fck;
++ unsigned num_clks_enabled;
++} core;
++
++static void dss_clk_enable_all_no_ctx(void);
++static void dss_clk_disable_all_no_ctx(void);
++static void dss_clk_enable_no_ctx(enum dss_clock clks);
++static void dss_clk_disable_no_ctx(enum dss_clock clks);
++
++static char *def_disp_name;
++module_param_named(def_disp, def_disp_name, charp, 0);
++MODULE_PARM_DESC(def_disp_name, "default display name");
++
++#ifdef DEBUG
++unsigned int dss_debug;
++module_param_named(debug, dss_debug, bool, 0644);
++#endif
++
++/* CONTEXT */
++static int dss_get_ctx_id(void)
++{
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++ int r;
++
++ if (!pdata->get_last_off_on_transaction_id)
++ return 0;
++ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++ if (r < 0) {
++ dev_err(&core.pdev->dev, "getting transaction ID failed, "
++ "will force context restore\n");
++ r = -1;
++ }
++ return r;
++}
++
++int dss_need_ctx_restore(void)
++{
++ int id = dss_get_ctx_id();
++
++ if (id < 0 || id != core.ctx_id) {
++ DSSDBG("ctx id %d -> id %d\n",
++ core.ctx_id, id);
++ core.ctx_id = id;
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++static void save_all_ctx(void)
++{
++ DSSDBG("save context\n");
++
++ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dss_save_context();
++ dispc_save_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_save_context();
++#endif
++
++ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++static void restore_all_ctx(void)
++{
++ DSSDBG("restore context\n");
++
++ dss_clk_enable_all_no_ctx();
++
++ dss_restore_context();
++ dispc_restore_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_restore_context();
++#endif
++
++ dss_clk_disable_all_no_ctx();
++}
++
++/* CLOCKS */
++void dss_dump_clocks(struct seq_file *s)
++{
++ int i;
++ struct clk *clocks[5] = {
++ core.dss_ick,
++ core.dss1_fck,
++ core.dss2_fck,
++ core.dss_54m_fck,
++ core.dss_96m_fck
++ };
++
++ seq_printf(s, "- dss -\n");
++
++ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
++
++ for (i = 0; i < 5; i++) {
++ if (!clocks[i])
++ continue;
++ seq_printf(s, "%-15s\t%lu\t%d\n",
++ clocks[i]->name,
++ clk_get_rate(clocks[i]),
++ clocks[i]->usecount);
++ }
++}
++
++static int dss_get_clock(struct clk **clock, const char *clk_name)
++{
++ struct clk *clk;
++
++ clk = clk_get(&core.pdev->dev, clk_name);
++
++ if (IS_ERR(clk)) {
++ DSSERR("can't get clock %s", clk_name);
++ return PTR_ERR(clk);
++ }
++
++ *clock = clk;
++
++ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
++
++ return 0;
++}
++
++static int dss_get_clocks(void)
++{
++ int r;
++
++ core.dss_ick = NULL;
++ core.dss1_fck = NULL;
++ core.dss2_fck = NULL;
++ core.dss_54m_fck = NULL;
++ core.dss_96m_fck = NULL;
++
++ r = dss_get_clock(&core.dss_ick, "ick");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss1_fck, "dss1_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss2_fck, "dss2_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss_96m_fck, "video_fck");
++ if (r)
++ goto err;
++
++ return 0;
++
++err:
++ if (core.dss_ick)
++ clk_put(core.dss_ick);
++ if (core.dss1_fck)
++ clk_put(core.dss1_fck);
++ if (core.dss2_fck)
++ clk_put(core.dss2_fck);
++ if (core.dss_54m_fck)
++ clk_put(core.dss_54m_fck);
++ if (core.dss_96m_fck)
++ clk_put(core.dss_96m_fck);
++
++ return r;
++}
++
++static void dss_put_clocks(void)
++{
++ if (core.dss_96m_fck)
++ clk_put(core.dss_96m_fck);
++ clk_put(core.dss_54m_fck);
++ clk_put(core.dss1_fck);
++ clk_put(core.dss2_fck);
++ clk_put(core.dss_ick);
++}
++
++unsigned long dss_clk_get_rate(enum dss_clock clk)
++{
++ switch (clk) {
++ case DSS_CLK_ICK:
++ return clk_get_rate(core.dss_ick);
++ case DSS_CLK_FCK1:
++ return clk_get_rate(core.dss1_fck);
++ case DSS_CLK_FCK2:
++ return clk_get_rate(core.dss2_fck);
++ case DSS_CLK_54M:
++ return clk_get_rate(core.dss_54m_fck);
++ case DSS_CLK_96M:
++ return clk_get_rate(core.dss_96m_fck);
++ }
++
++ BUG();
++ return 0;
++}
++
++static unsigned count_clk_bits(enum dss_clock clks)
++{
++ unsigned num_clks = 0;
++
++ if (clks & DSS_CLK_ICK)
++ ++num_clks;
++ if (clks & DSS_CLK_FCK1)
++ ++num_clks;
++ if (clks & DSS_CLK_FCK2)
++ ++num_clks;
++ if (clks & DSS_CLK_54M)
++ ++num_clks;
++ if (clks & DSS_CLK_96M)
++ ++num_clks;
++
++ return num_clks;
++}
++
++static void dss_clk_enable_no_ctx(enum dss_clock clks)
++{
++ unsigned num_clks = count_clk_bits(clks);
++
++ if (clks & DSS_CLK_ICK)
++ clk_enable(core.dss_ick);
++ if (clks & DSS_CLK_FCK1)
++ clk_enable(core.dss1_fck);
++ if (clks & DSS_CLK_FCK2)
++ clk_enable(core.dss2_fck);
++ if (clks & DSS_CLK_54M)
++ clk_enable(core.dss_54m_fck);
++ if (clks & DSS_CLK_96M)
++ clk_enable(core.dss_96m_fck);
++
++ core.num_clks_enabled += num_clks;
++}
++
++void dss_clk_enable(enum dss_clock clks)
++{
++ dss_clk_enable_no_ctx(clks);
++
++ if (cpu_is_omap34xx() && dss_need_ctx_restore())
++ restore_all_ctx();
++}
++
++static void dss_clk_disable_no_ctx(enum dss_clock clks)
++{
++ unsigned num_clks = count_clk_bits(clks);
++
++ if (clks & DSS_CLK_ICK)
++ clk_disable(core.dss_ick);
++ if (clks & DSS_CLK_FCK1)
++ clk_disable(core.dss1_fck);
++ if (clks & DSS_CLK_FCK2)
++ clk_disable(core.dss2_fck);
++ if (clks & DSS_CLK_54M)
++ clk_disable(core.dss_54m_fck);
++ if (clks & DSS_CLK_96M)
++ clk_disable(core.dss_96m_fck);
++
++ core.num_clks_enabled -= num_clks;
++}
++
++void dss_clk_disable(enum dss_clock clks)
++{
++ if (cpu_is_omap34xx()) {
++ unsigned num_clks = count_clk_bits(clks);
++
++ BUG_ON(core.num_clks_enabled < num_clks);
++
++ if (core.num_clks_enabled == num_clks)
++ save_all_ctx();
++ }
++
++ dss_clk_disable_no_ctx(clks);
++}
++
++static void dss_clk_enable_all_no_ctx(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_enable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all_no_ctx(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_disable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_disable(clks);
++}
++
++/* DEBUGFS */
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++static void dss_debug_dump_clocks(struct seq_file *s)
++{
++ dss_dump_clocks(s);
++ dispc_dump_clocks(s);
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_dump_clocks(s);
++#endif
++}
++
++static int dss_debug_show(struct seq_file *s, void *unused)
++{
++ void (*func)(struct seq_file *) = s->private;
++ func(s);
++ return 0;
++}
++
++static int dss_debug_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, dss_debug_show, inode->i_private);
++}
++
++static const struct file_operations dss_debug_fops = {
++ .open = dss_debug_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static struct dentry *dss_debugfs_dir;
++
++static int dss_initialize_debugfs(void)
++{
++ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
++ if (IS_ERR(dss_debugfs_dir)) {
++ int err = PTR_ERR(dss_debugfs_dir);
++ dss_debugfs_dir = NULL;
++ return err;
++ }
++
++ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
++ &dss_debug_dump_clocks, &dss_debug_fops);
++
++ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
++ &dss_dump_regs, &dss_debug_fops);
++ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
++ &dispc_dump_regs, &dss_debug_fops);
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
++ &rfbi_dump_regs, &dss_debug_fops);
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
++ &dsi_dump_regs, &dss_debug_fops);
++#endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
++ &venc_dump_regs, &dss_debug_fops);
++#endif
++ return 0;
++}
++
++static void dss_uninitialize_debugfs(void)
++{
++ if (dss_debugfs_dir)
++ debugfs_remove_recursive(dss_debugfs_dir);
++}
++#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
++
++/* PLATFORM DEVICE */
++static int omap_dss_probe(struct platform_device *pdev)
++{
++ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
++ int skip_init = 0;
++ int r;
++ int i;
++
++ core.pdev = pdev;
++
++ dss_init_overlay_managers(pdev);
++ dss_init_overlays(pdev);
++
++ r = dss_get_clocks();
++ if (r)
++ goto fail0;
++
++ dss_clk_enable_all_no_ctx();
++
++ core.ctx_id = dss_get_ctx_id();
++ DSSDBG("initial ctx id %u\n", core.ctx_id);
++
++#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
++ /* DISPC_CONTROL */
++ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
++ skip_init = 1;
++#endif
++
++ r = dss_init(skip_init);
++ if (r) {
++ DSSERR("Failed to initialize DSS\n");
++ goto fail0;
++ }
++
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ r = rfbi_init();
++ if (r) {
++ DSSERR("Failed to initialize rfbi\n");
++ goto fail0;
++ }
++#endif
++
++ r = dpi_init();
++ if (r) {
++ DSSERR("Failed to initialize dpi\n");
++ goto fail0;
++ }
++
++ r = dispc_init();
++ if (r) {
++ DSSERR("Failed to initialize dispc\n");
++ goto fail0;
++ }
++#ifdef CONFIG_OMAP2_DSS_VENC
++ r = venc_init(pdev);
++ if (r) {
++ DSSERR("Failed to initialize venc\n");
++ goto fail0;
++ }
++#endif
++ if (cpu_is_omap34xx()) {
++#ifdef CONFIG_OMAP2_DSS_SDI
++ r = sdi_init(skip_init);
++ if (r) {
++ DSSERR("Failed to initialize SDI\n");
++ goto fail0;
++ }
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ r = dsi_init(pdev);
++ if (r) {
++ DSSERR("Failed to initialize DSI\n");
++ goto fail0;
++ }
++#endif
++ }
++
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++ r = dss_initialize_debugfs();
++ if (r)
++ goto fail0;
++#endif
++
++ for (i = 0; i < pdata->num_devices; ++i) {
++ struct omap_dss_device *dssdev = pdata->devices[i];
++
++ r = omap_dss_register_device(dssdev);
++ if (r)
++ DSSERR("device reg failed %d\n", i);
++
++ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
++ pdata->default_device = dssdev;
++ }
++
++ dss_clk_disable_all();
++
++ return 0;
++
++ /* XXX fail correctly */
++fail0:
++ return r;
++}
++
++static int omap_dss_remove(struct platform_device *pdev)
++{
++ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
++ int i;
++ int c;
++
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++ dss_uninitialize_debugfs();
++#endif
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ venc_exit();
++#endif
++ dispc_exit();
++ dpi_exit();
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ rfbi_exit();
++#endif
++ if (cpu_is_omap34xx()) {
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_exit();
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ sdi_exit();
++#endif
++ }
++
++ dss_exit();
++
++ /* these should be removed at some point */
++ c = core.dss_ick->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_ick usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss_ick);
++ }
++
++ c = core.dss1_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss1_fck);
++ }
++
++ c = core.dss2_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss2_fck);
++ }
++
++ c = core.dss_54m_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss_54m_fck);
++ }
++
++ if (core.dss_96m_fck) {
++ c = core.dss_96m_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
++ c);
++ while (c-- > 0)
++ clk_disable(core.dss_96m_fck);
++ }
++ }
++
++ dss_put_clocks();
++
++ dss_uninit_overlays(pdev);
++ dss_uninit_overlay_managers(pdev);
++
++ for (i = 0; i < pdata->num_devices; ++i)
++ omap_dss_unregister_device(pdata->devices[i]);
++
++ return 0;
++}
++
++static void omap_dss_shutdown(struct platform_device *pdev)
++{
++ DSSDBG("shutdown\n");
++}
++
++static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ DSSDBG("suspend %d\n", state.event);
++
++ return dss_suspend_all_devices();
++}
++
++static int omap_dss_resume(struct platform_device *pdev)
++{
++ DSSDBG("resume\n");
++
++ return dss_resume_all_devices();
++}
++
++static struct platform_driver omap_dss_driver = {
++ .probe = omap_dss_probe,
++ .remove = omap_dss_remove,
++ .shutdown = omap_dss_shutdown,
++ .suspend = omap_dss_suspend,
++ .resume = omap_dss_resume,
++ .driver = {
++ .name = "omapdss",
++ .owner = THIS_MODULE,
++ },
++};
++
++/* BUS */
++static int dss_bus_match(struct device *dev, struct device_driver *driver)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ DSSDBG("bus_match. dev %s/%s, drv %s\n",
++ dev_name(dev), dssdev->driver_name, driver->name);
++
++ return strcmp(dssdev->driver_name, driver->name) == 0;
++}
++
++static ssize_t device_name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ dssdev->name ?
++ dssdev->name : "");
++}
++
++static struct device_attribute default_dev_attrs[] = {
++ __ATTR(name, S_IRUGO, device_name_show, NULL),
++ __ATTR_NULL,
++};
++
++static ssize_t driver_name_show(struct device_driver *drv, char *buf)
++{
++ struct omap_dss_driver *dssdrv = to_dss_driver(drv);
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ dssdrv->driver.name ?
++ dssdrv->driver.name : "");
++}
++static struct driver_attribute default_drv_attrs[] = {
++ __ATTR(name, S_IRUGO, driver_name_show, NULL),
++ __ATTR_NULL,
++};
++
++static struct bus_type dss_bus_type = {
++ .name = "omapdss",
++ .match = dss_bus_match,
++ .dev_attrs = default_dev_attrs,
++ .drv_attrs = default_drv_attrs,
++};
++
++static void dss_bus_release(struct device *dev)
++{
++ DSSDBG("bus_release\n");
++}
++
++static struct device dss_bus = {
++ .release = dss_bus_release,
++};
++
++struct bus_type *dss_get_bus(void)
++{
++ return &dss_bus_type;
++}
++
++/* DRIVER */
++static int dss_driver_probe(struct device *dev)
++{
++ int r;
++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++ bool force;
++
++ DSSDBG("driver_probe: dev %s/%s, drv %s\n",
++ dev_name(dev), dssdev->driver_name,
++ dssdrv->driver.name);
++
++ dss_init_device(core.pdev, dssdev);
++
++ /* skip this if the device is behind a ctrl */
++ if (!dssdev->panel.ctrl) {
++ force = pdata->default_device == dssdev;
++ dss_recheck_connections(dssdev, force);
++ }
++
++ r = dssdrv->probe(dssdev);
++
++ if (r) {
++ DSSERR("driver probe failed: %d\n", r);
++ return r;
++ }
++
++ DSSDBG("probe done for device %s\n", dev_name(dev));
++
++ dssdev->driver = dssdrv;
++
++ return 0;
++}
++
++static int dss_driver_remove(struct device *dev)
++{
++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
++ dssdev->driver_name);
++
++ dssdrv->remove(dssdev);
++
++ dss_uninit_device(core.pdev, dssdev);
++
++ dssdev->driver = NULL;
++
++ return 0;
++}
++
++int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
++{
++ dssdriver->driver.bus = &dss_bus_type;
++ dssdriver->driver.probe = dss_driver_probe;
++ dssdriver->driver.remove = dss_driver_remove;
++ return driver_register(&dssdriver->driver);
++}
++EXPORT_SYMBOL(omap_dss_register_driver);
++
++void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
++{
++ driver_unregister(&dssdriver->driver);
++}
++EXPORT_SYMBOL(omap_dss_unregister_driver);
++
++/* DEVICE */
++static void reset_device(struct device *dev, int check)
++{
++ u8 *dev_p = (u8 *)dev;
++ u8 *dev_end = dev_p + sizeof(*dev);
++ void *saved_pdata;
++
++ saved_pdata = dev->platform_data;
++ if (check) {
++ /*
++ * Check if there is any other setting than platform_data
++ * in struct device; warn that these will be reset by our
++ * init.
++ */
++ dev->platform_data = NULL;
++ while (dev_p < dev_end) {
++ if (*dev_p) {
++ WARN("%s: struct device fields will be "
++ "discarded\n",
++ __func__);
++ break;
++ }
++ dev_p++;
++ }
++ }
++ memset(dev, 0, sizeof(*dev));
++ dev->platform_data = saved_pdata;
++}
++
++
++static void omap_dss_dev_release(struct device *dev)
++{
++ reset_device(dev, 0);
++}
++
++int omap_dss_register_device(struct omap_dss_device *dssdev)
++{
++ static int dev_num;
++ static int panel_num;
++ int r;
++
++ WARN_ON(!dssdev->driver_name);
++
++ reset_device(&dssdev->dev, 1);
++ dssdev->dev.bus = &dss_bus_type;
++ dssdev->dev.parent = &dss_bus;
++ dssdev->dev.release = omap_dss_dev_release;
++ dev_set_name(&dssdev->dev, "display%d", dev_num++);
++ r = device_register(&dssdev->dev);
++ if (r)
++ return r;
++
++ if (dssdev->ctrl.panel) {
++ struct omap_dss_device *panel = dssdev->ctrl.panel;
++
++ panel->panel.ctrl = dssdev;
++
++ reset_device(&panel->dev, 1);
++ panel->dev.bus = &dss_bus_type;
++ panel->dev.parent = &dssdev->dev;
++ panel->dev.release = omap_dss_dev_release;
++ dev_set_name(&panel->dev, "panel%d", panel_num++);
++ r = device_register(&panel->dev);
++ if (r)
++ return r;
++ }
++
++ return 0;
++}
++
++void omap_dss_unregister_device(struct omap_dss_device *dssdev)
++{
++ device_unregister(&dssdev->dev);
++
++ if (dssdev->ctrl.panel) {
++ struct omap_dss_device *panel = dssdev->ctrl.panel;
++ device_unregister(&panel->dev);
++ }
++}
++
++/* BUS */
++static int omap_dss_bus_register(void)
++{
++ int r;
++
++ r = bus_register(&dss_bus_type);
++ if (r) {
++ DSSERR("bus register failed\n");
++ return r;
++ }
++
++ dev_set_name(&dss_bus, "omapdss");
++ r = device_register(&dss_bus);
++ if (r) {
++ DSSERR("bus driver register failed\n");
++ bus_unregister(&dss_bus_type);
++ return r;
++ }
++
++ return 0;
++}
++
++/* INIT */
++
++#ifdef CONFIG_OMAP2_DSS_MODULE
++static void omap_dss_bus_unregister(void)
++{
++ device_unregister(&dss_bus);
++
++ bus_unregister(&dss_bus_type);
++}
++
++static int __init omap_dss_init(void)
++{
++ int r;
++
++ r = omap_dss_bus_register();
++ if (r)
++ return r;
++
++ r = platform_driver_register(&omap_dss_driver);
++ if (r) {
++ omap_dss_bus_unregister();
++ return r;
++ }
++
++ return 0;
++}
++
++static void __exit omap_dss_exit(void)
++{
++ platform_driver_unregister(&omap_dss_driver);
++
++ omap_dss_bus_unregister();
++}
++
++module_init(omap_dss_init);
++module_exit(omap_dss_exit);
++#else
++static int __init omap_dss_init(void)
++{
++ return omap_dss_bus_register();
++}
++
++static int __init omap_dss_init2(void)
++{
++ return platform_driver_register(&omap_dss_driver);
++}
++
++core_initcall(omap_dss_init);
++device_initcall(omap_dss_init2);
++#endif
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
+new file mode 100644
+index 0000000..aab9758
+--- /dev/null
++++ b/drivers/video/omap2/dss/dss.c
+@@ -0,0 +1,347 @@
++/*
++ * linux/drivers/video/omap2/dss/dss.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DSS"
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/seq_file.h>
++
++#include <mach/display.h>
++#include "dss.h"
++
++#define DSS_BASE 0x48050000
++
++#define DSS_SZ_REGS SZ_512
++
++struct dss_reg {
++ u16 idx;
++};
++
++#define DSS_REG(idx) ((const struct dss_reg) { idx })
++
++#define DSS_REVISION DSS_REG(0x0000)
++#define DSS_SYSCONFIG DSS_REG(0x0010)
++#define DSS_SYSSTATUS DSS_REG(0x0014)
++#define DSS_IRQSTATUS DSS_REG(0x0018)
++#define DSS_CONTROL DSS_REG(0x0040)
++#define DSS_SDI_CONTROL DSS_REG(0x0044)
++#define DSS_PLL_CONTROL DSS_REG(0x0048)
++#define DSS_SDI_STATUS DSS_REG(0x005C)
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dss_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
++
++static struct {
++ void __iomem *base;
++
++ u32 ctx[DSS_SZ_REGS / sizeof(u32)];
++} dss;
++
++static int _omap_dss_wait_reset(void);
++
++static inline void dss_write_reg(const struct dss_reg idx, u32 val)
++{
++ __raw_writel(val, dss.base + idx.idx);
++}
++
++static inline u32 dss_read_reg(const struct dss_reg idx)
++{
++ return __raw_readl(dss.base + idx.idx);
++}
++
++#define SR(reg) \
++ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
++#define RR(reg) \
++ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
++
++void dss_save_context(void)
++{
++ if (cpu_is_omap24xx())
++ return;
++
++ SR(SYSCONFIG);
++ SR(CONTROL);
++
++#ifdef CONFIG_OMAP2_DSS_SDI
++ SR(SDI_CONTROL);
++ SR(PLL_CONTROL);
++#endif
++}
++
++void dss_restore_context(void)
++{
++ if (_omap_dss_wait_reset())
++ DSSERR("DSS not coming out of reset after sleep\n");
++
++ RR(SYSCONFIG);
++ RR(CONTROL);
++
++#ifdef CONFIG_OMAP2_DSS_SDI
++ RR(SDI_CONTROL);
++ RR(PLL_CONTROL);
++#endif
++}
++
++#undef SR
++#undef RR
++
++void dss_sdi_init(u8 datapairs)
++{
++ u32 l;
++
++ BUG_ON(datapairs > 3 || datapairs < 1);
++
++ l = dss_read_reg(DSS_SDI_CONTROL);
++ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
++ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
++ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
++ dss_write_reg(DSS_SDI_CONTROL, l);
++
++ l = dss_read_reg(DSS_PLL_CONTROL);
++ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
++ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
++ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
++ dss_write_reg(DSS_PLL_CONTROL, l);
++}
++
++void dss_sdi_enable(void)
++{
++ dispc_pck_free_enable(1);
++
++ /* Reset SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
++ udelay(1); /* wait 2x PCLK */
++
++ /* Lock SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
++
++ /* Waiting for PLL lock request to complete */
++ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
++ ;
++
++ /* Clearing PLL_GO bit */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
++
++ /* Waiting for PLL to lock */
++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
++ ;
++
++ dispc_lcd_enable_signal(1);
++
++ /* Waiting for SDI reset to complete */
++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
++ ;
++}
++
++void dss_sdi_disable(void)
++{
++ dispc_lcd_enable_signal(0);
++
++ dispc_pck_free_enable(0);
++
++ /* Reset SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
++}
++
++void dss_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DSS_REVISION);
++ DUMPREG(DSS_SYSCONFIG);
++ DUMPREG(DSS_SYSSTATUS);
++ DUMPREG(DSS_IRQSTATUS);
++ DUMPREG(DSS_CONTROL);
++ DUMPREG(DSS_SDI_CONTROL);
++ DUMPREG(DSS_PLL_CONTROL);
++ DUMPREG(DSS_SDI_STATUS);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++void dss_select_clk_source(bool dsi, bool dispc)
++{
++ u32 r;
++ r = dss_read_reg(DSS_CONTROL);
++ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
++ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
++ dss_write_reg(DSS_CONTROL, r);
++}
++
++int dss_get_dsi_clk_source(void)
++{
++ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
++}
++
++int dss_get_dispc_clk_source(void)
++{
++ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
++}
++
++static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
++{
++ dispc_irq_handler();
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
++{
++ u32 irqstatus;
++
++ irqstatus = dss_read_reg(DSS_IRQSTATUS);
++
++ if (irqstatus & (1<<0)) /* DISPC_IRQ */
++ dispc_irq_handler();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ if (irqstatus & (1<<1)) /* DSI_IRQ */
++ dsi_irq_handler();
++#endif
++
++ return IRQ_HANDLED;
++}
++
++static int _omap_dss_wait_reset(void)
++{
++ unsigned timeout = 1000;
++
++ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
++ udelay(1);
++ if (!--timeout) {
++ DSSERR("soft reset failed\n");
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++static int _omap_dss_reset(void)
++{
++ /* Soft reset */
++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
++ return _omap_dss_wait_reset();
++}
++
++void dss_set_venc_output(enum omap_dss_venc_type type)
++{
++ int l = 0;
++
++ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
++ l = 0;
++ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
++ l = 1;
++ else
++ BUG();
++
++ /* venc out selection. 0 = comp, 1 = svideo */
++ REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
++}
++
++void dss_set_dac_pwrdn_bgz(bool enable)
++{
++ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
++}
++
++int dss_init(bool skip_init)
++{
++ int r;
++ u32 rev;
++
++ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
++ if (!dss.base) {
++ DSSERR("can't ioremap DSS\n");
++ r = -ENOMEM;
++ goto fail0;
++ }
++
++ if (!skip_init) {
++ /* disable LCD and DIGIT output. This seems to fix the synclost
++ * problem that we get, if the bootloader starts the DSS and
++ * the kernel resets it */
++ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
++
++ /* We need to wait here a bit, otherwise we sometimes start to
++ * get synclost errors, and after that only power cycle will
++ * restore DSS functionality. I have no idea why this happens.
++ * And we have to wait _before_ resetting the DSS, but after
++ * enabling clocks.
++ */
++ msleep(50);
++
++ _omap_dss_reset();
++ }
++
++ /* autoidle */
++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
++
++ /* Select DPLL */
++ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
++ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
++ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
++#endif
++
++ r = request_irq(INT_24XX_DSS_IRQ,
++ cpu_is_omap24xx()
++ ? dss_irq_handler_omap2
++ : dss_irq_handler_omap3,
++ 0, "OMAP DSS", NULL);
++
++ if (r < 0) {
++ DSSERR("omap2 dss: request_irq failed\n");
++ goto fail1;
++ }
++
++ dss_save_context();
++
++ rev = dss_read_reg(DSS_REVISION);
++ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ return 0;
++
++fail1:
++ iounmap(dss.base);
++fail0:
++ return r;
++}
++
++void dss_exit(void)
++{
++ free_irq(INT_24XX_DSS_IRQ, NULL);
++
++ iounmap(dss.base);
++}
++
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+new file mode 100644
+index 0000000..50f7f5f
+--- /dev/null
++++ b/drivers/video/omap2/dss/dss.h
+@@ -0,0 +1,356 @@
++/*
++ * linux/drivers/video/omap2/dss/dss.h
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __OMAP2_DSS_H
++#define __OMAP2_DSS_H
++
++#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
++#define DEBUG
++#endif
++
++#ifdef DEBUG
++extern unsigned int dss_debug;
++#ifdef DSS_SUBSYS_NAME
++#define DSSDBG(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSDBG(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSDBGF(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
++ ": %s(" format ")\n", \
++ __func__, \
++ ## __VA_ARGS__)
++#else
++#define DSSDBGF(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss: " \
++ ": %s(" format ")\n", \
++ __func__, \
++ ## __VA_ARGS__)
++#endif
++
++#else /* DEBUG */
++#define DSSDBG(format, ...)
++#define DSSDBGF(format, ...)
++#endif
++
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSERR(format, ...) \
++ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSERR(format, ...) \
++ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSINFO(format, ...) \
++ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSINFO(format, ...) \
++ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSWARN(format, ...) \
++ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSWARN(format, ...) \
++ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++/* OMAP TRM gives bitfields as start:end, where start is the higher bit
++ number. For example 7:0 */
++#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
++#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
++#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
++#define FLD_MOD(orig, val, start, end) \
++ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
++
++#define DISPC_MAX_FCK 173000000
++
++enum omap_burst_size {
++ OMAP_DSS_BURST_4x32 = 0,
++ OMAP_DSS_BURST_8x32 = 1,
++ OMAP_DSS_BURST_16x32 = 2,
++};
++
++enum omap_parallel_interface_mode {
++ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
++ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
++ OMAP_DSS_PARALLELMODE_DSI,
++};
++
++enum dss_clock {
++ DSS_CLK_ICK = 1 << 0,
++ DSS_CLK_FCK1 = 1 << 1,
++ DSS_CLK_FCK2 = 1 << 2,
++ DSS_CLK_54M = 1 << 3,
++ DSS_CLK_96M = 1 << 4,
++};
++
++struct dispc_clock_info {
++ /* rates that we get with dividers below */
++ unsigned long fck;
++ unsigned long lck;
++ unsigned long pck;
++
++ /* dividers */
++ u16 fck_div;
++ u16 lck_div;
++ u16 pck_div;
++};
++
++struct dsi_clock_info {
++ /* rates that we get with dividers below */
++ unsigned long fint;
++ unsigned long dsiphy;
++ unsigned long clkin;
++ unsigned long dsi1_pll_fclk;
++ unsigned long dsi2_pll_fclk;
++ unsigned long lck;
++ unsigned long pck;
++
++ /* dividers */
++ u16 regn;
++ u16 regm;
++ u16 regm3;
++ u16 regm4;
++
++ u16 lck_div;
++ u16 pck_div;
++
++ u8 highfreq;
++ bool use_dss2_fck;
++};
++
++struct seq_file;
++struct platform_device;
++
++/* core */
++void dss_clk_enable(enum dss_clock clks);
++void dss_clk_disable(enum dss_clock clks);
++unsigned long dss_clk_get_rate(enum dss_clock clk);
++int dss_need_ctx_restore(void);
++void dss_dump_clocks(struct seq_file *s);
++struct bus_type *dss_get_bus(void);
++
++/* display */
++int dss_suspend_all_devices(void);
++int dss_resume_all_devices(void);
++
++void dss_init_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev);
++void dss_uninit_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev);
++bool dss_use_replication(struct omap_dss_device *dssdev,
++ enum omap_color_mode mode);
++void default_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high);
++
++/* manager */
++int dss_init_overlay_managers(struct platform_device *pdev);
++void dss_uninit_overlay_managers(struct platform_device *pdev);
++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
++void dss_setup_partial_planes(struct omap_dss_device *dssdev,
++ u16 *x, u16 *y, u16 *w, u16 *h);
++void dss_start_update(struct omap_dss_device *dssdev);
++
++/* overlay */
++void dss_init_overlays(struct platform_device *pdev);
++void dss_uninit_overlays(struct platform_device *pdev);
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
++#ifdef L4_EXAMPLE
++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
++#endif
++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
++
++/* DSS */
++int dss_init(bool skip_init);
++void dss_exit(void);
++
++void dss_save_context(void);
++void dss_restore_context(void);
++
++void dss_dump_regs(struct seq_file *s);
++
++void dss_sdi_init(u8 datapairs);
++void dss_sdi_enable(void);
++void dss_sdi_disable(void);
++
++void dss_select_clk_source(bool dsi, bool dispc);
++int dss_get_dsi_clk_source(void);
++int dss_get_dispc_clk_source(void);
++void dss_set_venc_output(enum omap_dss_venc_type type);
++void dss_set_dac_pwrdn_bgz(bool enable);
++
++/* SDI */
++int sdi_init(bool skip_init);
++void sdi_exit(void);
++int sdi_init_display(struct omap_dss_device *display);
++
++/* DSI */
++int dsi_init(struct platform_device *pdev);
++void dsi_exit(void);
++
++void dsi_dump_clocks(struct seq_file *s);
++void dsi_dump_regs(struct seq_file *s);
++
++void dsi_save_context(void);
++void dsi_restore_context(void);
++
++int dsi_init_display(struct omap_dss_device *display);
++void dsi_irq_handler(void);
++unsigned long dsi_get_dsi1_pll_rate(void);
++unsigned long dsi_get_dsi2_pll_rate(void);
++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
++ struct dsi_clock_info *cinfo);
++int dsi_pll_program(struct dsi_clock_info *cinfo);
++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
++void dsi_pll_uninit(void);
++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high);
++
++/* DPI */
++int dpi_init(void);
++void dpi_exit(void);
++int dpi_init_display(struct omap_dss_device *dssdev);
++
++/* DISPC */
++int dispc_init(void);
++void dispc_exit(void);
++void dispc_dump_clocks(struct seq_file *s);
++void dispc_dump_regs(struct seq_file *s);
++void dispc_irq_handler(void);
++void dispc_fake_vsync_irq(void);
++
++void dispc_save_context(void);
++void dispc_restore_context(void);
++
++void dispc_enable_sidle(void);
++void dispc_disable_sidle(void);
++
++void dispc_lcd_enable_signal_polarity(bool act_high);
++void dispc_lcd_enable_signal(bool enable);
++void dispc_pck_free_enable(bool enable);
++void dispc_enable_fifohandcheck(bool enable);
++
++void dispc_set_lcd_size(u16 width, u16 height);
++void dispc_set_digit_size(u16 width, u16 height);
++u32 dispc_get_plane_fifo_size(enum omap_plane plane);
++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
++void dispc_enable_fifomerge(bool enable);
++void dispc_set_burst_size(enum omap_plane plane,
++ enum omap_burst_size burst_size);
++
++void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
++void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
++void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
++void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
++void dispc_set_channel_out(enum omap_plane plane,
++ enum omap_channel channel_out);
++
++int dispc_setup_plane(enum omap_plane plane,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
++ u8 rotation, bool mirror,
++ u8 global_alpha);
++
++bool dispc_go_busy(enum omap_channel channel);
++void dispc_go(enum omap_channel channel);
++void dispc_enable_lcd_out(bool enable);
++void dispc_enable_digit_out(bool enable);
++int dispc_enable_plane(enum omap_plane plane, bool enable);
++void dispc_enable_replication(enum omap_plane plane, bool enable);
++
++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
++void dispc_set_tft_data_lines(u8 data_lines);
++void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
++void dispc_set_loadmode(enum omap_dss_load_mode mode);
++
++void dispc_set_default_color(enum omap_channel channel, u32 color);
++u32 dispc_get_default_color(enum omap_channel channel);
++void dispc_set_trans_key(enum omap_channel ch,
++ enum omap_dss_trans_key_type type,
++ u32 trans_key);
++void dispc_get_trans_key(enum omap_channel ch,
++ enum omap_dss_trans_key_type *type,
++ u32 *trans_key);
++void dispc_enable_trans_key(enum omap_channel ch, bool enable);
++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
++bool dispc_trans_key_enabled(enum omap_channel ch);
++bool dispc_alpha_blending_enabled(enum omap_channel ch);
++
++bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
++void dispc_set_lcd_timings(struct omap_video_timings *timings);
++unsigned long dispc_fclk_rate(void);
++unsigned long dispc_lclk_rate(void);
++unsigned long dispc_pclk_rate(void);
++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
++ u16 *lck_div, u16 *pck_div);
++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
++ struct dispc_clock_info *cinfo);
++int dispc_set_clock_div(struct dispc_clock_info *cinfo);
++int dispc_get_clock_div(struct dispc_clock_info *cinfo);
++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
++
++
++/* VENC */
++int venc_init(struct platform_device *pdev);
++void venc_exit(void);
++void venc_dump_regs(struct seq_file *s);
++int venc_init_display(struct omap_dss_device *display);
++
++/* RFBI */
++int rfbi_init(void);
++void rfbi_exit(void);
++void rfbi_dump_regs(struct seq_file *s);
++
++int rfbi_configure(int rfbi_module, int bpp, int lines);
++void rfbi_enable_rfbi(bool enable);
++void rfbi_transfer_area(u16 width, u16 height,
++ void (callback)(void *data), void *data);
++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
++unsigned long rfbi_get_max_tx_rate(void);
++int rfbi_init_display(struct omap_dss_device *display);
++
++#endif
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch b/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch
new file mode 100644
index 0000000000..3237d49eae
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch
@@ -0,0 +1,2856 @@
+From 9e37324c13a58b705b85e63b0779f7efbd94342a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 13:43:20 +0300
+Subject: [PATCH 08/18] OMAP: DSS2: Add more core files
+
+Add more core files to DSS2.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/display.c | 658 ++++++++++++++++
+ drivers/video/omap2/dss/manager.c | 1487 +++++++++++++++++++++++++++++++++++++
+ drivers/video/omap2/dss/overlay.c | 673 +++++++++++++++++
+ 3 files changed, 2818 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/display.c
+ create mode 100644 drivers/video/omap2/dss/manager.c
+ create mode 100644 drivers/video/omap2/dss/overlay.c
+
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+new file mode 100644
+index 0000000..6b5d0cf
+--- /dev/null
++++ b/drivers/video/omap2/dss/display.c
+@@ -0,0 +1,658 @@
++/*
++ * linux/drivers/video/omap2/dss/display.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DISPLAY"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/jiffies.h>
++#include <linux/list.h>
++#include <linux/platform_device.h>
++
++#include <mach/display.h>
++#include "dss.h"
++
++static LIST_HEAD(display_list);
++
++static ssize_t display_enabled_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
++}
++
++static ssize_t display_enabled_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ bool enabled, r;
++
++ enabled = simple_strtoul(buf, NULL, 10);
++
++ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
++ if (enabled) {
++ r = dssdev->enable(dssdev);
++ if (r)
++ return r;
++ } else {
++ dssdev->disable(dssdev);
++ }
++ }
++
++ return size;
++}
++
++static ssize_t display_upd_mode_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
++ if (dssdev->get_update_mode)
++ mode = dssdev->get_update_mode(dssdev);
++ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
++}
++
++static ssize_t display_upd_mode_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ int val, r;
++ enum omap_dss_update_mode mode;
++
++ val = simple_strtoul(buf, NULL, 10);
++
++ switch (val) {
++ case OMAP_DSS_UPDATE_DISABLED:
++ case OMAP_DSS_UPDATE_AUTO:
++ case OMAP_DSS_UPDATE_MANUAL:
++ mode = (enum omap_dss_update_mode)val;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ r = dssdev->set_update_mode(dssdev, mode);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t display_tear_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ dssdev->get_te ? dssdev->get_te(dssdev) : 0);
++}
++
++static ssize_t display_tear_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ unsigned long te;
++ int r;
++
++ if (!dssdev->enable_te || !dssdev->get_te)
++ return -ENOENT;
++
++ te = simple_strtoul(buf, NULL, 0);
++
++ r = dssdev->enable_te(dssdev, te);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t display_timings_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct omap_video_timings t;
++
++ if (!dssdev->get_timings)
++ return -ENOENT;
++
++ dssdev->get_timings(dssdev, &t);
++
++ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
++ t.pixel_clock,
++ t.x_res, t.hfp, t.hbp, t.hsw,
++ t.y_res, t.vfp, t.vbp, t.vsw);
++}
++
++static ssize_t display_timings_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct omap_video_timings t;
++ int r, found;
++
++ if (!dssdev->set_timings || !dssdev->check_timings)
++ return -ENOENT;
++
++ found = 0;
++#ifdef CONFIG_OMAP2_DSS_VENC
++ if (strncmp("pal", buf, 3) == 0) {
++ t = omap_dss_pal_timings;
++ found = 1;
++ } else if (strncmp("ntsc", buf, 4) == 0) {
++ t = omap_dss_ntsc_timings;
++ found = 1;
++ }
++#endif
++ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
++ &t.pixel_clock,
++ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
++ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
++ return -EINVAL;
++
++ r = dssdev->check_timings(dssdev, &t);
++ if (r)
++ return r;
++
++ dssdev->set_timings(dssdev, &t);
++
++ return size;
++}
++
++static ssize_t display_rotate_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ int rotate;
++ if (!dssdev->get_rotate)
++ return -ENOENT;
++ rotate = dssdev->get_rotate(dssdev);
++ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
++}
++
++static ssize_t display_rotate_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ unsigned long rot;
++ int r;
++
++ if (!dssdev->set_rotate || !dssdev->get_rotate)
++ return -ENOENT;
++
++ rot = simple_strtoul(buf, NULL, 0);
++
++ r = dssdev->set_rotate(dssdev, rot);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t display_mirror_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ int mirror;
++ if (!dssdev->get_mirror)
++ return -ENOENT;
++ mirror = dssdev->get_mirror(dssdev);
++ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
++}
++
++static ssize_t display_mirror_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ unsigned long mirror;
++ int r;
++
++ if (!dssdev->set_mirror || !dssdev->get_mirror)
++ return -ENOENT;
++
++ mirror = simple_strtoul(buf, NULL, 0);
++
++ r = dssdev->set_mirror(dssdev, mirror);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t display_wss_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ unsigned int wss;
++
++ if (!dssdev->get_wss)
++ return -ENOENT;
++
++ wss = dssdev->get_wss(dssdev);
++
++ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
++}
++
++static ssize_t display_wss_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ unsigned long wss;
++ int r;
++
++ if (!dssdev->get_wss || !dssdev->set_wss)
++ return -ENOENT;
++
++ if (strict_strtoul(buf, 0, &wss))
++ return -EINVAL;
++
++ if (wss > 0xfffff)
++ return -EINVAL;
++
++ r = dssdev->set_wss(dssdev, wss);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
++ display_enabled_show, display_enabled_store);
++static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
++ display_upd_mode_show, display_upd_mode_store);
++static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
++ display_tear_show, display_tear_store);
++static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
++ display_timings_show, display_timings_store);
++static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
++ display_rotate_show, display_rotate_store);
++static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
++ display_mirror_show, display_mirror_store);
++static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
++ display_wss_show, display_wss_store);
++
++static struct device_attribute *display_sysfs_attrs[] = {
++ &dev_attr_enabled,
++ &dev_attr_update_mode,
++ &dev_attr_tear_elim,
++ &dev_attr_timings,
++ &dev_attr_rotate,
++ &dev_attr_mirror,
++ &dev_attr_wss,
++ NULL
++};
++
++static void default_get_resolution(struct omap_dss_device *dssdev,
++ u16 *xres, u16 *yres)
++{
++ *xres = dssdev->panel.timings.x_res;
++ *yres = dssdev->panel.timings.y_res;
++}
++
++void default_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high)
++{
++ unsigned burst_size_bytes;
++
++ *burst_size = OMAP_DSS_BURST_16x32;
++ burst_size_bytes = 16 * 32 / 8;
++
++ *fifo_high = fifo_size - 1;
++ *fifo_low = fifo_size - burst_size_bytes;
++}
++
++static int default_wait_vsync(struct omap_dss_device *dssdev)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ u32 irq;
++
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
++ irq = DISPC_IRQ_EVSYNC_ODD;
++ else
++ irq = DISPC_IRQ_VSYNC;
++
++ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++}
++
++static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
++{
++ if (dssdev->panel.recommended_bpp)
++ return dssdev->panel.recommended_bpp;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ if (dssdev->phy.dpi.data_lines == 24)
++ return 24;
++ else
++ return 16;
++
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DSI:
++ if (dssdev->ctrl.pixel_size == 24)
++ return 24;
++ else
++ return 16;
++ case OMAP_DISPLAY_TYPE_VENC:
++ case OMAP_DISPLAY_TYPE_SDI:
++ return 24;
++ return 24;
++ default:
++ BUG();
++ }
++}
++
++/* Checks if replication logic should be used. Only use for active matrix,
++ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
++ * 18bpp or 24bpp */
++bool dss_use_replication(struct omap_dss_device *dssdev,
++ enum omap_color_mode mode)
++{
++ int bpp;
++
++ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
++ return false;
++
++ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
++ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
++ return false;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ bpp = dssdev->phy.dpi.data_lines;
++ break;
++ case OMAP_DISPLAY_TYPE_VENC:
++ case OMAP_DISPLAY_TYPE_SDI:
++ bpp = 24;
++ break;
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DSI:
++ bpp = dssdev->ctrl.pixel_size;
++ break;
++ default:
++ BUG();
++ }
++
++ return bpp > 16;
++}
++
++void dss_init_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev)
++{
++ struct device_attribute *attr;
++ int i;
++ int r;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ case OMAP_DISPLAY_TYPE_DBI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ case OMAP_DISPLAY_TYPE_SDI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ case OMAP_DISPLAY_TYPE_VENC:
++#endif
++ break;
++ default:
++ DSSERR("Support for display '%s' not compiled in.\n",
++ dssdev->name);
++ return;
++ }
++
++ dssdev->get_resolution = default_get_resolution;
++ dssdev->get_recommended_bpp = default_get_recommended_bpp;
++ dssdev->wait_vsync = default_wait_vsync;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ r = dpi_init_display(dssdev);
++ break;
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ case OMAP_DISPLAY_TYPE_DBI:
++ r = rfbi_init_display(dssdev);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ case OMAP_DISPLAY_TYPE_VENC:
++ r = venc_init_display(dssdev);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ case OMAP_DISPLAY_TYPE_SDI:
++ r = sdi_init_display(dssdev);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++ r = dsi_init_display(dssdev);
++ break;
++#endif
++ default:
++ BUG();
++ }
++
++ if (r) {
++ DSSERR("failed to init display %s\n", dssdev->name);
++ return;
++ }
++
++ /* create device sysfs files */
++ i = 0;
++ while ((attr = display_sysfs_attrs[i++]) != NULL) {
++ r = device_create_file(&dssdev->dev, attr);
++ if (r)
++ DSSERR("failed to create sysfs file\n");
++ }
++
++ /* create display? sysfs links */
++ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
++ dev_name(&dssdev->dev));
++ if (r)
++ DSSERR("failed to create sysfs display link\n");
++}
++
++void dss_uninit_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev)
++{
++ struct device_attribute *attr;
++ int i = 0;
++
++ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
++
++ while ((attr = display_sysfs_attrs[i++]) != NULL)
++ device_remove_file(&dssdev->dev, attr);
++
++ if (dssdev->manager)
++ dssdev->manager->unset_device(dssdev->manager);
++}
++
++static int dss_suspend_device(struct device *dev, void *data)
++{
++ int r;
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ dssdev->activate_after_resume = false;
++ return 0;
++ }
++
++ if (!dssdev->suspend) {
++ DSSERR("display '%s' doesn't implement suspend\n",
++ dssdev->name);
++ return -ENOSYS;
++ }
++
++ r = dssdev->suspend(dssdev);
++ if (r)
++ return r;
++
++ dssdev->activate_after_resume = true;
++
++ return 0;
++}
++
++int dss_suspend_all_devices(void)
++{
++ int r;
++ struct bus_type *bus = dss_get_bus();
++
++ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
++ if (r) {
++ /* resume all displays that were suspended */
++ dss_resume_all_devices();
++ return r;
++ }
++
++ return 0;
++}
++
++static int dss_resume_device(struct device *dev, void *data)
++{
++ int r;
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ if (dssdev->activate_after_resume && dssdev->resume) {
++ r = dssdev->resume(dssdev);
++ if (r)
++ return r;
++ }
++
++ dssdev->activate_after_resume = false;
++
++ return 0;
++}
++
++int dss_resume_all_devices(void)
++{
++ struct bus_type *bus = dss_get_bus();
++
++ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
++}
++
++
++void omap_dss_get_device(struct omap_dss_device *dssdev)
++{
++ get_device(&dssdev->dev);
++}
++EXPORT_SYMBOL(omap_dss_get_device);
++
++void omap_dss_put_device(struct omap_dss_device *dssdev)
++{
++ put_device(&dssdev->dev);
++}
++EXPORT_SYMBOL(omap_dss_put_device);
++
++/* ref count of the found device is incremented. ref count
++ * of from-device is decremented. */
++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
++{
++ struct device *dev;
++ struct device *dev_start = NULL;
++ struct omap_dss_device *dssdev = NULL;
++
++ int match(struct device *dev, void *data)
++ {
++ /* skip panels connected to controllers */
++ if (to_dss_device(dev)->panel.ctrl)
++ return 0;
++
++ return 1;
++ }
++
++ if (from)
++ dev_start = &from->dev;
++ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
++ if (dev)
++ dssdev = to_dss_device(dev);
++ if (from)
++ put_device(&from->dev);
++
++ return dssdev;
++}
++EXPORT_SYMBOL(omap_dss_get_next_device);
++
++struct omap_dss_device *omap_dss_find_device(void *data,
++ int (*match)(struct omap_dss_device *dssdev, void *data))
++{
++ struct omap_dss_device *dssdev = NULL;
++
++ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
++ if (match(dssdev, data))
++ return dssdev;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_find_device);
++
++int omap_dss_start_device(struct omap_dss_device *dssdev)
++{
++ int r;
++
++ if (!dssdev->driver) {
++ DSSDBG("no driver\n");
++ r = -ENODEV;
++ goto err0;
++ }
++
++ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
++ DSSDBG("no panel driver\n");
++ r = -ENODEV;
++ goto err0;
++ }
++
++ if (!try_module_get(dssdev->dev.driver->owner)) {
++ r = -ENODEV;
++ goto err0;
++ }
++
++ if (dssdev->ctrl.panel) {
++ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
++ r = -ENODEV;
++ goto err1;
++ }
++ }
++
++ return 0;
++err1:
++ module_put(dssdev->dev.driver->owner);
++err0:
++ return r;
++}
++EXPORT_SYMBOL(omap_dss_start_device);
++
++void omap_dss_stop_device(struct omap_dss_device *dssdev)
++{
++ if (dssdev->ctrl.panel)
++ module_put(dssdev->ctrl.panel->dev.driver->owner);
++
++ module_put(dssdev->dev.driver->owner);
++}
++EXPORT_SYMBOL(omap_dss_stop_device);
++
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+new file mode 100644
+index 0000000..7ee0b2b
+--- /dev/null
++++ b/drivers/video/omap2/dss/manager.c
+@@ -0,0 +1,1487 @@
++/*
++ * linux/drivers/video/omap2/dss/manager.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "MANAGER"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/jiffies.h>
++
++#include <mach/display.h>
++#include <mach/cpu.h>
++
++#include "dss.h"
++
++static int num_managers;
++static struct list_head manager_list;
++
++static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
++}
++
++static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ mgr->device ? mgr->device->name : "<none>");
++}
++
++static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ int r = 0;
++ size_t len = size;
++ struct omap_dss_device *dssdev = NULL;
++
++ int match(struct omap_dss_device *dssdev, void *data)
++ {
++ const char *str = data;
++ return sysfs_streq(dssdev->name, str);
++ }
++
++ if (buf[size-1] == '\n')
++ --len;
++
++ if (len > 0)
++ dssdev = omap_dss_find_device((void *)buf, match);
++
++ if (len > 0 && dssdev == NULL)
++ return -EINVAL;
++
++ if (dssdev)
++ DSSDBG("display %s found\n", dssdev->name);
++
++ if (mgr->device) {
++ r = mgr->unset_device(mgr);
++ if (r) {
++ DSSERR("failed to unset display\n");
++ goto put_device;
++ }
++ }
++
++ if (dssdev) {
++ r = mgr->set_device(mgr, dssdev);
++ if (r) {
++ DSSERR("failed to set manager\n");
++ goto put_device;
++ }
++
++ r = mgr->apply(mgr);
++ if (r) {
++ DSSERR("failed to apply dispc config\n");
++ goto put_device;
++ }
++ }
++
++put_device:
++ if (dssdev)
++ omap_dss_put_device(dssdev);
++
++ return r ? r : size;
++}
++
++static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
++}
++
++static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager_info info;
++ u32 color;
++ int r;
++
++ if (sscanf(buf, "%d", &color) != 1)
++ return -EINVAL;
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.default_color = color;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static const char *trans_key_type_str[] = {
++ "gfx-destination",
++ "video-source",
++};
++
++static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ enum omap_dss_trans_key_type key_type;
++
++ key_type = mgr->info.trans_key_type;
++ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
++
++ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
++}
++
++static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ enum omap_dss_trans_key_type key_type;
++ struct omap_overlay_manager_info info;
++ int r;
++
++ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
++ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
++ if (sysfs_streq(buf, trans_key_type_str[key_type]))
++ break;
++ }
++
++ if (key_type == ARRAY_SIZE(trans_key_type_str))
++ return -EINVAL;
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.trans_key_type = key_type;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
++}
++
++static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager_info info;
++ u32 key_value;
++ int r;
++
++ if (sscanf(buf, "%d", &key_value) != 1)
++ return -EINVAL;
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.trans_key = key_value;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
++}
++
++static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager_info info;
++ int enable;
++ int r;
++
++ if (sscanf(buf, "%d", &enable) != 1)
++ return -EINVAL;
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.trans_enabled = enable ? true : false;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++
++ return size;
++}
++
++static ssize_t manager_alpha_blending_enabled_show(
++ struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
++}
++
++static ssize_t manager_alpha_blending_enabled_store(
++ struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager_info info;
++ int enable;
++ int r;
++
++ if (sscanf(buf, "%d", &enable) != 1)
++ return -EINVAL;
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.alpha_enabled = enable ? true : false;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++
++ return size;
++}
++
++struct manager_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct omap_overlay_manager *, char *);
++ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
++};
++
++#define MANAGER_ATTR(_name, _mode, _show, _store) \
++ struct manager_attribute manager_attr_##_name = \
++ __ATTR(_name, _mode, _show, _store)
++
++static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
++static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
++ manager_display_show, manager_display_store);
++static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
++ manager_default_color_show, manager_default_color_store);
++static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
++ manager_trans_key_type_show, manager_trans_key_type_store);
++static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
++ manager_trans_key_value_show, manager_trans_key_value_store);
++static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
++ manager_trans_key_enabled_show,
++ manager_trans_key_enabled_store);
++static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
++ manager_alpha_blending_enabled_show,
++ manager_alpha_blending_enabled_store);
++
++
++static struct attribute *manager_sysfs_attrs[] = {
++ &manager_attr_name.attr,
++ &manager_attr_display.attr,
++ &manager_attr_default_color.attr,
++ &manager_attr_trans_key_type.attr,
++ &manager_attr_trans_key_value.attr,
++ &manager_attr_trans_key_enabled.attr,
++ &manager_attr_alpha_blending_enabled.attr,
++ NULL
++};
++
++static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ struct omap_overlay_manager *manager;
++ struct manager_attribute *manager_attr;
++
++ manager = container_of(kobj, struct omap_overlay_manager, kobj);
++ manager_attr = container_of(attr, struct manager_attribute, attr);
++
++ if (!manager_attr->show)
++ return -ENOENT;
++
++ return manager_attr->show(manager, buf);
++}
++
++static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager *manager;
++ struct manager_attribute *manager_attr;
++
++ manager = container_of(kobj, struct omap_overlay_manager, kobj);
++ manager_attr = container_of(attr, struct manager_attribute, attr);
++
++ if (!manager_attr->store)
++ return -ENOENT;
++
++ return manager_attr->store(manager, buf, size);
++}
++
++static struct sysfs_ops manager_sysfs_ops = {
++ .show = manager_attr_show,
++ .store = manager_attr_store,
++};
++
++static struct kobj_type manager_ktype = {
++ .sysfs_ops = &manager_sysfs_ops,
++ .default_attrs = manager_sysfs_attrs,
++};
++
++/*
++ * We have 4 levels of cache for the dispc settings. First two are in SW and
++ * the latter two in HW.
++ *
++ * +--------------------+
++ * |overlay/manager_info|
++ * +--------------------+
++ * v
++ * apply()
++ * v
++ * +--------------------+
++ * | dss_cache |
++ * +--------------------+
++ * v
++ * configure()
++ * v
++ * +--------------------+
++ * | shadow registers |
++ * +--------------------+
++ * v
++ * VFP or lcd/digit_enable
++ * v
++ * +--------------------+
++ * | registers |
++ * +--------------------+
++ */
++
++struct overlay_cache_data {
++ /* If true, cache changed, but not written to shadow registers. Set
++ * in apply(), cleared when registers written. */
++ bool dirty;
++ /* If true, shadow registers contain changed values not yet in real
++ * registers. Set when writing to shadow registers, cleared at
++ * VSYNC/EVSYNC */
++ bool shadow_dirty;
++
++ bool enabled;
++
++ u32 paddr;
++ void __iomem *vaddr;
++ u16 screen_width;
++ u16 width;
++ u16 height;
++ enum omap_color_mode color_mode;
++ u8 rotation;
++ enum omap_dss_rotation_type rotation_type;
++ bool mirror;
++
++ u16 pos_x;
++ u16 pos_y;
++ u16 out_width; /* if 0, out_width == width */
++ u16 out_height; /* if 0, out_height == height */
++ u8 global_alpha;
++
++ enum omap_channel channel;
++ bool replication;
++ bool ilace;
++
++ enum omap_burst_size burst_size;
++ u32 fifo_low;
++ u32 fifo_high;
++
++ bool manual_update;
++};
++
++struct manager_cache_data {
++ /* If true, cache changed, but not written to shadow registers. Set
++ * in apply(), cleared when registers written. */
++ bool dirty;
++ /* If true, shadow registers contain changed values not yet in real
++ * registers. Set when writing to shadow registers, cleared at
++ * VSYNC/EVSYNC */
++ bool shadow_dirty;
++
++ u32 default_color;
++
++ enum omap_dss_trans_key_type trans_key_type;
++ u32 trans_key;
++ bool trans_enabled;
++
++ bool alpha_enabled;
++
++ bool manual_upd_display;
++ bool manual_update;
++ bool do_manual_update;
++
++ /* manual update region */
++ u16 x, y, w, h;
++};
++
++static struct {
++ spinlock_t lock;
++ struct overlay_cache_data overlay_cache[3];
++ struct manager_cache_data manager_cache[2];
++
++ bool irq_enabled;
++} dss_cache;
++
++
++
++static int omap_dss_set_device(struct omap_overlay_manager *mgr,
++ struct omap_dss_device *dssdev)
++{
++ int i;
++ int r;
++
++ if (dssdev->manager) {
++ DSSERR("display '%s' already has a manager '%s'\n",
++ dssdev->name, dssdev->manager->name);
++ return -EINVAL;
++ }
++
++ if ((mgr->supported_displays & dssdev->type) == 0) {
++ DSSERR("display '%s' does not support manager '%s'\n",
++ dssdev->name, mgr->name);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < mgr->num_overlays; i++) {
++ struct omap_overlay *ovl = mgr->overlays[i];
++
++ if (ovl->manager != mgr || !ovl->info.enabled)
++ continue;
++
++ r = dss_check_overlay(ovl, dssdev);
++ if (r)
++ return r;
++ }
++
++ dssdev->manager = mgr;
++ mgr->device = dssdev;
++ mgr->device_changed = true;
++
++ return 0;
++}
++
++static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
++{
++ if (!mgr->device) {
++ DSSERR("failed to unset display, display not set.\n");
++ return -EINVAL;
++ }
++
++ mgr->device->manager = NULL;
++ mgr->device = NULL;
++ mgr->device_changed = true;
++
++ return 0;
++}
++
++static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ struct manager_cache_data *mc;
++ enum omap_channel channel;
++ u32 irq;
++ int r;
++ int i;
++
++ if (!mgr->device)
++ return 0;
++
++ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
++ channel = OMAP_DSS_CHANNEL_DIGIT;
++ } else {
++ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++ enum omap_dss_update_mode mode;
++ mode = mgr->device->get_update_mode(mgr->device);
++ if (mode != OMAP_DSS_UPDATE_AUTO)
++ return 0;
++
++ irq = DISPC_IRQ_FRAMEDONE;
++ } else {
++ irq = DISPC_IRQ_VSYNC;
++ }
++ channel = OMAP_DSS_CHANNEL_LCD;
++ }
++
++ mc = &dss_cache.manager_cache[mgr->id];
++ i = 0;
++ while (1) {
++ unsigned long flags;
++ bool shadow_dirty, dirty;
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++ dirty = mc->dirty;
++ shadow_dirty = mc->shadow_dirty;
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ if (!dirty && !shadow_dirty) {
++ r = 0;
++ break;
++ }
++
++ /* 4 iterations is the worst case:
++ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
++ * 2 - first VSYNC, dirty = true
++ * 3 - dirty = false, shadow_dirty = true
++ * 4 - shadow_dirty = false */
++ if (i++ == 3) {
++ DSSERR("mgr(%d)->wait_for_go() not finishing\n",
++ mgr->id);
++ r = 0;
++ break;
++ }
++
++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++ if (r == -ERESTARTSYS)
++ break;
++
++ if (r) {
++ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
++ break;
++ }
++ }
++
++ return r;
++}
++
++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ enum omap_channel channel;
++ struct overlay_cache_data *oc;
++ struct omap_dss_device *dssdev;
++ u32 irq;
++ int r;
++ int i;
++
++ if (!ovl->manager || !ovl->manager->device)
++ return 0;
++
++ dssdev = ovl->manager->device;
++
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
++ channel = OMAP_DSS_CHANNEL_DIGIT;
++ } else {
++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++ enum omap_dss_update_mode mode;
++ mode = dssdev->get_update_mode(dssdev);
++ if (mode != OMAP_DSS_UPDATE_AUTO)
++ return 0;
++
++ irq = DISPC_IRQ_FRAMEDONE;
++ } else {
++ irq = DISPC_IRQ_VSYNC;
++ }
++ channel = OMAP_DSS_CHANNEL_LCD;
++ }
++
++ oc = &dss_cache.overlay_cache[ovl->id];
++ i = 0;
++ while (1) {
++ unsigned long flags;
++ bool shadow_dirty, dirty;
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++ dirty = oc->dirty;
++ shadow_dirty = oc->shadow_dirty;
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ if (!dirty && !shadow_dirty) {
++ r = 0;
++ break;
++ }
++
++ /* 4 iterations is the worst case:
++ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
++ * 2 - first VSYNC, dirty = true
++ * 3 - dirty = false, shadow_dirty = true
++ * 4 - shadow_dirty = false */
++ if (i++ == 3) {
++ DSSERR("ovl(%d)->wait_for_go() not finishing\n",
++ ovl->id);
++ r = 0;
++ break;
++ }
++
++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++ if (r == -ERESTARTSYS)
++ break;
++
++ if (r) {
++ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
++ break;
++ }
++ }
++
++ return r;
++}
++
++static int overlay_enabled(struct omap_overlay *ovl)
++{
++ return ovl->info.enabled && ovl->manager && ovl->manager->device;
++}
++
++/* Is rect1 a subset of rect2? */
++static bool rectangle_subset(int x1, int y1, int w1, int h1,
++ int x2, int y2, int w2, int h2)
++{
++ if (x1 < x2 || y1 < y2)
++ return false;
++
++ if (x1 + w1 > x2 + w2)
++ return false;
++
++ if (y1 + h1 > y2 + h2)
++ return false;
++
++ return true;
++}
++
++/* Do rect1 and rect2 overlap? */
++static bool rectangle_intersects(int x1, int y1, int w1, int h1,
++ int x2, int y2, int w2, int h2)
++{
++ if (x1 >= x2 + w2)
++ return false;
++
++ if (x2 >= x1 + w1)
++ return false;
++
++ if (y1 >= y2 + h2)
++ return false;
++
++ if (y2 >= y1 + h1)
++ return false;
++
++ return true;
++}
++
++static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
++{
++ if (oc->out_width != 0 && oc->width != oc->out_width)
++ return true;
++
++ if (oc->out_height != 0 && oc->height != oc->out_height)
++ return true;
++
++ return false;
++}
++
++static int configure_overlay(enum omap_plane plane)
++{
++ struct overlay_cache_data *c;
++ struct manager_cache_data *mc;
++ u16 outw, outh;
++ u16 x, y, w, h;
++ u32 paddr;
++ int r;
++
++ DSSDBGF("%d", plane);
++
++ c = &dss_cache.overlay_cache[plane];
++
++ if (!c->enabled) {
++ dispc_enable_plane(plane, 0);
++ return 0;
++ }
++
++ mc = &dss_cache.manager_cache[c->channel];
++
++ x = c->pos_x;
++ y = c->pos_y;
++ w = c->width;
++ h = c->height;
++ outw = c->out_width == 0 ? c->width : c->out_width;
++ outh = c->out_height == 0 ? c->height : c->out_height;
++ paddr = c->paddr;
++
++ if (c->manual_update && mc->do_manual_update) {
++ unsigned bpp;
++ /* If the overlay is outside the update region, disable it */
++ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
++ x, y, outw, outh)) {
++ dispc_enable_plane(plane, 0);
++ return 0;
++ }
++
++ switch (c->color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ bpp = 16;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ bpp = 24;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ bpp = 32;
++ break;
++
++ default:
++ BUG();
++ }
++
++ if (dispc_is_overlay_scaled(c)) {
++ /* If the overlay is scaled, the update area has
++ * already been enlarged to cover the whole overlay. We
++ * only need to adjust x/y here */
++ x = c->pos_x - mc->x;
++ y = c->pos_y - mc->y;
++ } else {
++ if (mc->x > c->pos_x) {
++ x = 0;
++ w -= (mc->x - c->pos_x);
++ paddr += (mc->x - c->pos_x) * bpp / 8;
++ } else {
++ x = c->pos_x - mc->x;
++ }
++
++ if (mc->y > c->pos_y) {
++ y = 0;
++ h -= (mc->y - c->pos_y);
++ paddr += (mc->y - c->pos_y) * c->screen_width *
++ bpp / 8;
++ } else {
++ y = c->pos_y - mc->y;
++ }
++
++ if (mc->w < (x+w))
++ w -= (x+w) - (mc->w);
++
++ if (mc->h < (y+h))
++ h -= (y+h) - (mc->h);
++
++ outw = w;
++ outh = h;
++ }
++ }
++
++ r = dispc_setup_plane(plane,
++ paddr,
++ c->screen_width,
++ x, y,
++ w, h,
++ outw, outh,
++ c->color_mode,
++ c->ilace,
++ c->rotation_type,
++ c->rotation,
++ c->mirror,
++ c->global_alpha);
++
++ if (r) {
++ /* this shouldn't happen */
++ DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
++ dispc_enable_plane(plane, 0);
++ return r;
++ }
++
++ dispc_enable_replication(plane, c->replication);
++
++ dispc_set_burst_size(plane, c->burst_size);
++ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
++
++ dispc_enable_plane(plane, 1);
++
++ return 0;
++}
++
++static void configure_manager(enum omap_channel channel)
++{
++ struct manager_cache_data *c;
++
++ DSSDBGF("%d", channel);
++
++ c = &dss_cache.manager_cache[channel];
++
++ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
++ dispc_enable_trans_key(channel, c->trans_enabled);
++ dispc_enable_alpha_blending(channel, c->alpha_enabled);
++}
++
++/* configure_dispc() tries to write values from cache to shadow registers.
++ * It writes only to those managers/overlays that are not busy.
++ * returns 0 if everything could be written to shadow registers.
++ * returns 1 if not everything could be written to shadow registers. */
++static int configure_dispc(void)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
++ int i;
++ int r;
++ bool mgr_busy[2];
++ bool mgr_go[2];
++ bool busy;
++
++ r = 0;
++ busy = false;
++
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
++ mgr_go[0] = false;
++ mgr_go[1] = false;
++
++ /* Commit overlay settings */
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ mc = &dss_cache.manager_cache[oc->channel];
++
++ if (!oc->dirty)
++ continue;
++
++ if (oc->manual_update && !mc->do_manual_update)
++ continue;
++
++ if (mgr_busy[oc->channel]) {
++ busy = true;
++ continue;
++ }
++
++ r = configure_overlay(i);
++ if (r)
++ DSSERR("configure_overlay %d failed\n", i);
++
++ oc->dirty = false;
++ oc->shadow_dirty = true;
++ mgr_go[oc->channel] = true;
++ }
++
++ /* Commit manager settings */
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++
++ if (!mc->dirty)
++ continue;
++
++ if (mc->manual_update && !mc->do_manual_update)
++ continue;
++
++ if (mgr_busy[i]) {
++ busy = true;
++ continue;
++ }
++
++ configure_manager(i);
++ mc->dirty = false;
++ mc->shadow_dirty = true;
++ mgr_go[i] = true;
++ }
++
++ /* set GO */
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++
++ if (!mgr_go[i])
++ continue;
++
++ /* We don't need GO with manual update display. LCD iface will
++ * always be turned off after frame, and new settings will be
++ * taken in to use at next update */
++ if (!mc->manual_upd_display)
++ dispc_go(i);
++ }
++
++ if (busy)
++ r = 1;
++ else
++ r = 0;
++
++ return r;
++}
++
++/* Configure dispc for partial update. Return possibly modified update
++ * area */
++void dss_setup_partial_planes(struct omap_dss_device *dssdev,
++ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ struct omap_overlay_manager *mgr;
++ int i;
++ u16 x, y, w, h;
++ unsigned long flags;
++
++ x = *xi;
++ y = *yi;
++ w = *wi;
++ h = *hi;
++
++ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
++ *xi, *yi, *wi, *hi);
++
++ mgr = dssdev->manager;
++
++ if (!mgr) {
++ DSSDBG("no manager\n");
++ return;
++ }
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++
++ /* We need to show the whole overlay if it is scaled. So look for
++ * those, and make the update area larger if found.
++ * Also mark the overlay cache dirty */
++ for (i = 0; i < num_ovls; ++i) {
++ unsigned x1, y1, x2, y2;
++ unsigned outw, outh;
++
++ oc = &dss_cache.overlay_cache[i];
++
++ if (oc->channel != mgr->id)
++ continue;
++
++ oc->dirty = true;
++
++ if (!oc->enabled)
++ continue;
++
++ if (!dispc_is_overlay_scaled(oc))
++ continue;
++
++ outw = oc->out_width == 0 ? oc->width : oc->out_width;
++ outh = oc->out_height == 0 ? oc->height : oc->out_height;
++
++ /* is the overlay outside the update region? */
++ if (!rectangle_intersects(x, y, w, h,
++ oc->pos_x, oc->pos_y,
++ outw, outh))
++ continue;
++
++ /* if the overlay totally inside the update region? */
++ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
++ x, y, w, h))
++ continue;
++
++ if (x > oc->pos_x)
++ x1 = oc->pos_x;
++ else
++ x1 = x;
++
++ if (y > oc->pos_y)
++ y1 = oc->pos_y;
++ else
++ y1 = y;
++
++ if ((x + w) < (oc->pos_x + outw))
++ x2 = oc->pos_x + outw;
++ else
++ x2 = x + w;
++
++ if ((y + h) < (oc->pos_y + outh))
++ y2 = oc->pos_y + outh;
++ else
++ y2 = y + h;
++
++ x = x1;
++ y = y1;
++ w = x2 - x1;
++ h = y2 - y1;
++
++ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
++ i, x, y, w, h);
++ }
++
++ mc = &dss_cache.manager_cache[mgr->id];
++ mc->do_manual_update = true;
++ mc->x = x;
++ mc->y = y;
++ mc->w = w;
++ mc->h = h;
++
++ configure_dispc();
++
++ mc->do_manual_update = false;
++
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ *xi = x;
++ *yi = y;
++ *wi = w;
++ *hi = h;
++}
++
++void dss_start_update(struct omap_dss_device *dssdev)
++{
++ struct manager_cache_data *mc;
++ struct overlay_cache_data *oc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
++ struct omap_overlay_manager *mgr;
++ int i;
++
++ mgr = dssdev->manager;
++
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ if (oc->channel != mgr->id)
++ continue;
++
++ oc->shadow_dirty = false;
++ }
++
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++ if (mgr->id != i)
++ continue;
++
++ mc->shadow_dirty = false;
++ }
++
++ dispc_enable_lcd_out(1);
++}
++
++static void dss_apply_irq_handler(void *data, u32 mask)
++{
++ struct manager_cache_data *mc;
++ struct overlay_cache_data *oc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
++ int i, r;
++ bool mgr_busy[2];
++
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
++
++ spin_lock(&dss_cache.lock);
++
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ if (!mgr_busy[oc->channel])
++ oc->shadow_dirty = false;
++ }
++
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++ if (!mgr_busy[i])
++ mc->shadow_dirty = false;
++ }
++
++ r = configure_dispc();
++ if (r == 1)
++ goto end;
++
++ /* re-read busy flags */
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
++
++ /* keep running as long as there are busy managers, so that
++ * we can collect overlay-applied information */
++ for (i = 0; i < num_mgrs; ++i) {
++ if (mgr_busy[i])
++ goto end;
++ }
++
++ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
++ DISPC_IRQ_EVSYNC_EVEN);
++ dss_cache.irq_enabled = false;
++
++end:
++ spin_unlock(&dss_cache.lock);
++}
++
++static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ int i;
++ struct omap_overlay *ovl;
++ int num_planes_enabled = 0;
++ bool use_fifomerge;
++ unsigned long flags;
++ int r;
++
++ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++
++ /* Configure overlays */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_dss_device *dssdev;
++
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ oc = &dss_cache.overlay_cache[ovl->id];
++
++ if (!overlay_enabled(ovl)) {
++ if (oc->enabled) {
++ oc->enabled = false;
++ oc->dirty = true;
++ }
++ continue;
++ }
++
++ if (!ovl->info_dirty) {
++ if (oc->enabled)
++ ++num_planes_enabled;
++ continue;
++ }
++
++ dssdev = ovl->manager->device;
++
++ if (dss_check_overlay(ovl, dssdev)) {
++ if (oc->enabled) {
++ oc->enabled = false;
++ oc->dirty = true;
++ }
++ continue;
++ }
++
++ ovl->info_dirty = false;
++ oc->dirty = true;
++
++ oc->paddr = ovl->info.paddr;
++ oc->vaddr = ovl->info.vaddr;
++ oc->screen_width = ovl->info.screen_width;
++ oc->width = ovl->info.width;
++ oc->height = ovl->info.height;
++ oc->color_mode = ovl->info.color_mode;
++ oc->rotation = ovl->info.rotation;
++ oc->rotation_type = ovl->info.rotation_type;
++ oc->mirror = ovl->info.mirror;
++ oc->pos_x = ovl->info.pos_x;
++ oc->pos_y = ovl->info.pos_y;
++ oc->out_width = ovl->info.out_width;
++ oc->out_height = ovl->info.out_height;
++ oc->global_alpha = ovl->info.global_alpha;
++
++ oc->replication =
++ dss_use_replication(dssdev, ovl->info.color_mode);
++
++ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
++
++ oc->channel = ovl->manager->id;
++
++ oc->enabled = true;
++
++ oc->manual_update =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
++
++ ++num_planes_enabled;
++ }
++
++ /* Configure managers */
++ list_for_each_entry(mgr, &manager_list, list) {
++ struct omap_dss_device *dssdev;
++
++ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
++ continue;
++
++ mc = &dss_cache.manager_cache[mgr->id];
++
++ if (mgr->device_changed) {
++ mgr->device_changed = false;
++ mgr->info_dirty = true;
++ }
++
++ if (!mgr->info_dirty)
++ continue;
++
++ if (!mgr->device)
++ continue;
++
++ dssdev = mgr->device;
++
++ mgr->info_dirty = false;
++ mc->dirty = true;
++
++ mc->default_color = mgr->info.default_color;
++ mc->trans_key_type = mgr->info.trans_key_type;
++ mc->trans_key = mgr->info.trans_key;
++ mc->trans_enabled = mgr->info.trans_enabled;
++ mc->alpha_enabled = mgr->info.alpha_enabled;
++
++ mc->manual_upd_display =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ mc->manual_update =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
++ }
++
++ /* XXX TODO: Try to get fifomerge working. The problem is that it
++ * affects both managers, not individually but at the same time. This
++ * means the change has to be well synchronized. I guess the proper way
++ * is to have a two step process for fifo merge:
++ * fifomerge enable:
++ * 1. disable other planes, leaving one plane enabled
++ * 2. wait until the planes are disabled on HW
++ * 3. config merged fifo thresholds, enable fifomerge
++ * fifomerge disable:
++ * 1. config unmerged fifo thresholds, disable fifomerge
++ * 2. wait until fifo changes are in HW
++ * 3. enable planes
++ */
++ use_fifomerge = false;
++
++ /* Configure overlay fifos */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_dss_device *dssdev;
++ u32 size;
++
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ oc = &dss_cache.overlay_cache[ovl->id];
++
++ if (!oc->enabled)
++ continue;
++
++ dssdev = ovl->manager->device;
++
++ size = dispc_get_plane_fifo_size(ovl->id);
++ if (use_fifomerge)
++ size *= 3;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_SDI:
++ case OMAP_DISPLAY_TYPE_VENC:
++ default_get_overlay_fifo_thresholds(ovl->id, size,
++ &oc->burst_size, &oc->fifo_low,
++ &oc->fifo_high);
++ break;
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++ dsi_get_overlay_fifo_thresholds(ovl->id, size,
++ &oc->burst_size, &oc->fifo_low,
++ &oc->fifo_high);
++ break;
++#endif
++ default:
++ BUG();
++ }
++ }
++
++ r = 0;
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ if (!dss_cache.irq_enabled) {
++ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
++ DISPC_IRQ_EVSYNC_EVEN);
++ dss_cache.irq_enabled = true;
++ }
++ configure_dispc();
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ return r;
++}
++
++static int dss_check_manager(struct omap_overlay_manager *mgr)
++{
++ /* OMAP supports only graphics source transparency color key and alpha
++ * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
++
++ if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
++ mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info)
++{
++ int r;
++ struct omap_overlay_manager_info old_info;
++
++ old_info = mgr->info;
++ mgr->info = *info;
++
++ r = dss_check_manager(mgr);
++ if (r) {
++ mgr->info = old_info;
++ return r;
++ }
++
++ mgr->info_dirty = true;
++
++ return 0;
++}
++
++static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info)
++{
++ *info = mgr->info;
++}
++
++static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
++{
++ ++num_managers;
++ list_add_tail(&manager->list, &manager_list);
++}
++
++int dss_init_overlay_managers(struct platform_device *pdev)
++{
++ int i, r;
++
++ spin_lock_init(&dss_cache.lock);
++
++ INIT_LIST_HEAD(&manager_list);
++
++ num_managers = 0;
++
++ for (i = 0; i < 2; ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++ BUG_ON(mgr == NULL);
++
++ switch (i) {
++ case 0:
++ mgr->name = "lcd";
++ mgr->id = OMAP_DSS_CHANNEL_LCD;
++ mgr->supported_displays =
++ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
++ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
++ break;
++ case 1:
++ mgr->name = "tv";
++ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
++ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
++ break;
++ }
++
++ mgr->set_device = &omap_dss_set_device;
++ mgr->unset_device = &omap_dss_unset_device;
++ mgr->apply = &omap_dss_mgr_apply;
++ mgr->set_manager_info = &omap_dss_mgr_set_info;
++ mgr->get_manager_info = &omap_dss_mgr_get_info;
++ mgr->wait_for_go = &dss_mgr_wait_for_go;
++
++ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
++
++ dss_overlay_setup_dispc_manager(mgr);
++
++ omap_dss_add_overlay_manager(mgr);
++
++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
++ &pdev->dev.kobj, "manager%d", i);
++
++ if (r) {
++ DSSERR("failed to create sysfs file\n");
++ continue;
++ }
++ }
++
++#ifdef L4_EXAMPLE
++ {
++ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
++ {
++ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
++
++ return 0;
++ }
++
++ struct omap_overlay_manager *mgr;
++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++ BUG_ON(mgr == NULL);
++
++ mgr->name = "l4";
++ mgr->supported_displays =
++ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
++
++ mgr->set_device = &omap_dss_set_device;
++ mgr->unset_device = &omap_dss_unset_device;
++ mgr->apply = &omap_dss_mgr_apply_l4;
++ mgr->set_manager_info = &omap_dss_mgr_set_info;
++ mgr->get_manager_info = &omap_dss_mgr_get_info;
++
++ dss_overlay_setup_l4_manager(mgr);
++
++ omap_dss_add_overlay_manager(mgr);
++
++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
++ &pdev->dev.kobj, "managerl4");
++
++ if (r)
++ DSSERR("failed to create sysfs file\n");
++ }
++#endif
++
++ return 0;
++}
++
++void dss_uninit_overlay_managers(struct platform_device *pdev)
++{
++ struct omap_overlay_manager *mgr;
++
++ while (!list_empty(&manager_list)) {
++ mgr = list_first_entry(&manager_list,
++ struct omap_overlay_manager, list);
++ list_del(&mgr->list);
++ kobject_del(&mgr->kobj);
++ kobject_put(&mgr->kobj);
++ kfree(mgr);
++ }
++
++ num_managers = 0;
++}
++
++int omap_dss_get_num_overlay_managers(void)
++{
++ return num_managers;
++}
++EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
++
++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
++{
++ int i = 0;
++ struct omap_overlay_manager *mgr;
++
++ list_for_each_entry(mgr, &manager_list, list) {
++ if (i++ == num)
++ return mgr;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_get_overlay_manager);
++
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+new file mode 100644
+index 0000000..c7cb81b
+--- /dev/null
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -0,0 +1,673 @@
++/*
++ * linux/drivers/video/omap2/dss/overlay.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "OVERLAY"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/sysfs.h>
++#include <linux/kobject.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++#include "dss.h"
++
++static int num_overlays;
++static struct list_head overlay_list;
++
++static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
++}
++
++static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ ovl->manager ? ovl->manager->name : "<none>");
++}
++
++static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
++ size_t size)
++{
++ int i, r;
++ struct omap_overlay_manager *mgr = NULL;
++ struct omap_overlay_manager *old_mgr;
++ int len = size;
++
++ if (buf[size-1] == '\n')
++ --len;
++
++ if (len > 0) {
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (strncmp(buf, mgr->name, len) == 0)
++ break;
++
++ mgr = NULL;
++ }
++ }
++
++ if (len > 0 && mgr == NULL)
++ return -EINVAL;
++
++ if (mgr)
++ DSSDBG("manager %s found\n", mgr->name);
++
++ if (mgr == ovl->manager)
++ return size;
++
++ old_mgr = ovl->manager;
++
++ /* detach old manager */
++ if (old_mgr) {
++ r = ovl->unset_manager(ovl);
++ if (r) {
++ DSSERR("detach failed\n");
++ return r;
++ }
++
++ r = old_mgr->apply(old_mgr);
++ if (r)
++ return r;
++ }
++
++ if (mgr) {
++ r = ovl->set_manager(ovl, mgr);
++ if (r) {
++ DSSERR("Failed to attach overlay\n");
++ return r;
++ }
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
++ }
++
++ return size;
++}
++
++static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.width, ovl->info.height);
++}
++
++static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
++}
++
++static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.pos_x, ovl->info.pos_y);
++}
++
++static ssize_t overlay_position_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ char *last;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.pos_x = simple_strtoul(buf, &last, 10);
++ ++last;
++ if (last - buf >= size)
++ return -EINVAL;
++
++ info.pos_y = simple_strtoul(last, &last, 10);
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ return r;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
++
++ return size;
++}
++
++static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.out_width, ovl->info.out_height);
++}
++
++static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ char *last;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.out_width = simple_strtoul(buf, &last, 10);
++ ++last;
++ if (last - buf >= size)
++ return -EINVAL;
++
++ info.out_height = simple_strtoul(last, &last, 10);
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ return r;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
++
++ return size;
++}
++
++static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
++}
++
++static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
++ size_t size)
++{
++ int r;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.enabled = simple_strtoul(buf, NULL, 10);
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ return r;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
++
++ return size;
++}
++
++static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ ovl->info.global_alpha);
++}
++
++static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ /* Video1 plane does not support global alpha
++ * to always make it 255 completely opaque
++ */
++ if (ovl->id == OMAP_DSS_VIDEO1)
++ info.global_alpha = 255;
++ else
++ info.global_alpha = simple_strtoul(buf, NULL, 10);
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ return r;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
++
++ return size;
++}
++
++struct overlay_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct omap_overlay *, char *);
++ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
++};
++
++#define OVERLAY_ATTR(_name, _mode, _show, _store) \
++ struct overlay_attribute overlay_attr_##_name = \
++ __ATTR(_name, _mode, _show, _store)
++
++static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
++static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
++ overlay_manager_show, overlay_manager_store);
++static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
++static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
++static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
++ overlay_position_show, overlay_position_store);
++static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
++ overlay_output_size_show, overlay_output_size_store);
++static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
++ overlay_enabled_show, overlay_enabled_store);
++static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
++ overlay_global_alpha_show, overlay_global_alpha_store);
++
++static struct attribute *overlay_sysfs_attrs[] = {
++ &overlay_attr_name.attr,
++ &overlay_attr_manager.attr,
++ &overlay_attr_input_size.attr,
++ &overlay_attr_screen_width.attr,
++ &overlay_attr_position.attr,
++ &overlay_attr_output_size.attr,
++ &overlay_attr_enabled.attr,
++ &overlay_attr_global_alpha.attr,
++ NULL
++};
++
++static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ struct omap_overlay *overlay;
++ struct overlay_attribute *overlay_attr;
++
++ overlay = container_of(kobj, struct omap_overlay, kobj);
++ overlay_attr = container_of(attr, struct overlay_attribute, attr);
++
++ if (!overlay_attr->show)
++ return -ENOENT;
++
++ return overlay_attr->show(overlay, buf);
++}
++
++static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay *overlay;
++ struct overlay_attribute *overlay_attr;
++
++ overlay = container_of(kobj, struct omap_overlay, kobj);
++ overlay_attr = container_of(attr, struct overlay_attribute, attr);
++
++ if (!overlay_attr->store)
++ return -ENOENT;
++
++ return overlay_attr->store(overlay, buf, size);
++}
++
++static struct sysfs_ops overlay_sysfs_ops = {
++ .show = overlay_attr_show,
++ .store = overlay_attr_store,
++};
++
++static struct kobj_type overlay_ktype = {
++ .sysfs_ops = &overlay_sysfs_ops,
++ .default_attrs = overlay_sysfs_attrs,
++};
++
++/* Check if overlay parameters are compatible with display */
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
++{
++ struct omap_overlay_info *info;
++ u16 outw, outh;
++ u16 dw, dh;
++
++ if (!dssdev)
++ return 0;
++
++ if (!ovl->info.enabled)
++ return 0;
++
++ info = &ovl->info;
++
++ if (info->paddr == 0) {
++ DSSDBG("check_overlay failed: paddr 0\n");
++ return -EINVAL;
++ }
++
++ dssdev->get_resolution(dssdev, &dw, &dh);
++
++ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
++ ovl->id,
++ info->pos_x, info->pos_y,
++ info->width, info->height,
++ info->out_width, info->out_height,
++ dw, dh);
++
++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
++ outw = info->width;
++ outh = info->height;
++ } else {
++ if (info->out_width == 0)
++ outw = info->width;
++ else
++ outw = info->out_width;
++
++ if (info->out_height == 0)
++ outh = info->height;
++ else
++ outh = info->out_height;
++ }
++
++ if (dw < info->pos_x + outw) {
++ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
++ dw, info->pos_x, outw);
++ return -EINVAL;
++ }
++
++ if (dh < info->pos_y + outh) {
++ DSSDBG("check_overlay failed 2: %d < %d + %d\n",
++ dh, info->pos_y, outh);
++ return -EINVAL;
++ }
++
++ if ((ovl->supported_modes & info->color_mode) == 0) {
++ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
++ struct omap_overlay_info *info)
++{
++ int r;
++ struct omap_overlay_info old_info;
++
++ old_info = ovl->info;
++ ovl->info = *info;
++
++ if (ovl->manager) {
++ r = dss_check_overlay(ovl, ovl->manager->device);
++ if (r) {
++ ovl->info = old_info;
++ return r;
++ }
++ }
++
++ ovl->info_dirty = true;
++
++ return 0;
++}
++
++static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
++ struct omap_overlay_info *info)
++{
++ *info = ovl->info;
++}
++
++static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
++{
++ return dss_mgr_wait_for_go_ovl(ovl);
++}
++
++static int omap_dss_set_manager(struct omap_overlay *ovl,
++ struct omap_overlay_manager *mgr)
++{
++ if (!mgr)
++ return -EINVAL;
++
++ if (ovl->manager) {
++ DSSERR("overlay '%s' already has a manager '%s'\n",
++ ovl->name, ovl->manager->name);
++ return -EINVAL;
++ }
++
++ if (ovl->info.enabled) {
++ DSSERR("overlay has to be disabled to change the manager\n");
++ return -EINVAL;
++ }
++
++ ovl->manager = mgr;
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ /* XXX: on manual update display, in auto update mode, a bug happens
++ * here. When an overlay is first enabled on LCD, then it's disabled,
++ * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
++ * errors. Waiting before changing the channel_out fixes it. I'm
++ * guessing that the overlay is still somehow being used for the LCD,
++ * but I don't understand how or why. */
++ msleep(40);
++ dispc_set_channel_out(ovl->id, mgr->id);
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ return 0;
++}
++
++static int omap_dss_unset_manager(struct omap_overlay *ovl)
++{
++ int r;
++
++ if (!ovl->manager) {
++ DSSERR("failed to detach overlay: manager not set\n");
++ return -EINVAL;
++ }
++
++ if (ovl->info.enabled) {
++ DSSERR("overlay has to be disabled to unset the manager\n");
++ return -EINVAL;
++ }
++
++ r = ovl->wait_for_go(ovl);
++ if (r)
++ return r;
++
++ ovl->manager = NULL;
++
++ return 0;
++}
++
++int omap_dss_get_num_overlays(void)
++{
++ return num_overlays;
++}
++EXPORT_SYMBOL(omap_dss_get_num_overlays);
++
++struct omap_overlay *omap_dss_get_overlay(int num)
++{
++ int i = 0;
++ struct omap_overlay *ovl;
++
++ list_for_each_entry(ovl, &overlay_list, list) {
++ if (i++ == num)
++ return ovl;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_get_overlay);
++
++static void omap_dss_add_overlay(struct omap_overlay *overlay)
++{
++ ++num_overlays;
++ list_add_tail(&overlay->list, &overlay_list);
++}
++
++static struct omap_overlay *dispc_overlays[3];
++
++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
++{
++ mgr->num_overlays = 3;
++ mgr->overlays = dispc_overlays;
++}
++
++#ifdef L4_EXAMPLE
++static struct omap_overlay *l4_overlays[1];
++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
++{
++ mgr->num_overlays = 1;
++ mgr->overlays = l4_overlays;
++}
++#endif
++
++void dss_init_overlays(struct platform_device *pdev)
++{
++ int i, r;
++
++ INIT_LIST_HEAD(&overlay_list);
++
++ num_overlays = 0;
++
++ for (i = 0; i < 3; ++i) {
++ struct omap_overlay *ovl;
++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
++
++ BUG_ON(ovl == NULL);
++
++ switch (i) {
++ case 0:
++ ovl->name = "gfx";
++ ovl->id = OMAP_DSS_GFX;
++ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
++ break;
++ case 1:
++ ovl->name = "vid1";
++ ovl->id = OMAP_DSS_VIDEO1;
++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
++ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
++ break;
++ case 2:
++ ovl->name = "vid2";
++ ovl->id = OMAP_DSS_VIDEO2;
++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
++ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
++ break;
++ }
++
++ ovl->set_manager = &omap_dss_set_manager;
++ ovl->unset_manager = &omap_dss_unset_manager;
++ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
++ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
++ ovl->wait_for_go = &dss_ovl_wait_for_go;
++
++ omap_dss_add_overlay(ovl);
++
++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
++ &pdev->dev.kobj, "overlay%d", i);
++
++ if (r) {
++ DSSERR("failed to create sysfs file\n");
++ continue;
++ }
++
++ dispc_overlays[i] = ovl;
++ }
++
++#ifdef L4_EXAMPLE
++ {
++ struct omap_overlay *ovl;
++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
++
++ BUG_ON(ovl == NULL);
++
++ ovl->name = "l4";
++ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
++
++ ovl->set_manager = &omap_dss_set_manager;
++ ovl->unset_manager = &omap_dss_unset_manager;
++ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
++ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
++
++ omap_dss_add_overlay(ovl);
++
++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
++ &pdev->dev.kobj, "overlayl4");
++
++ if (r)
++ DSSERR("failed to create sysfs file\n");
++
++ l4_overlays[0] = ovl;
++ }
++#endif
++}
++
++/* connect overlays to the new device, if not already connected. if force
++ * selected, connect always. */
++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
++{
++ int i;
++ struct omap_overlay_manager *lcd_mgr;
++ struct omap_overlay_manager *tv_mgr;
++ struct omap_overlay_manager *mgr = NULL;
++
++ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
++ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
++
++ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
++ if (!lcd_mgr->device || force) {
++ if (lcd_mgr->device)
++ lcd_mgr->unset_device(lcd_mgr);
++ lcd_mgr->set_device(lcd_mgr, dssdev);
++ mgr = lcd_mgr;
++ }
++ }
++
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
++ if (!tv_mgr->device || force) {
++ if (tv_mgr->device)
++ tv_mgr->unset_device(tv_mgr);
++ tv_mgr->set_device(tv_mgr, dssdev);
++ mgr = tv_mgr;
++ }
++ }
++
++ if (mgr) {
++ for (i = 0; i < 3; i++) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++ if (!ovl->manager || force) {
++ if (ovl->manager)
++ omap_dss_unset_manager(ovl);
++ omap_dss_set_manager(ovl, mgr);
++ }
++ }
++ }
++}
++
++void dss_uninit_overlays(struct platform_device *pdev)
++{
++ struct omap_overlay *ovl;
++
++ while (!list_empty(&overlay_list)) {
++ ovl = list_first_entry(&overlay_list,
++ struct omap_overlay, list);
++ list_del(&ovl->list);
++ kobject_del(&ovl->kobj);
++ kobject_put(&ovl->kobj);
++ kfree(ovl);
++ }
++
++ num_overlays = 0;
++}
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch b/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch
new file mode 100644
index 0000000000..a558223c11
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch
@@ -0,0 +1,3204 @@
+From 8ec6585980444513ee55fbdf462dc36ca5fcbef4 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 13:15:32 +0300
+Subject: [PATCH 09/18] OMAP: DSS2: DISPC
+
+This file implements DISPC (display controller) block of the OMAP DSS.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 3182 +++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 3182 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/dispc.c
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+new file mode 100644
+index 0000000..d648475
+--- /dev/null
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -0,0 +1,3182 @@
++/*
++ * linux/drivers/video/omap2/dss/dispc.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DISPC"
++
++#include <linux/kernel.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
++#include <linux/seq_file.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++
++#include <mach/sram.h>
++#include <mach/board.h>
++#include <mach/clock.h>
++
++#include <mach/display.h>
++
++#include "dss.h"
++
++/* DISPC */
++#define DISPC_BASE 0x48050400
++
++#define DISPC_SZ_REGS SZ_1K
++
++struct dispc_reg { u16 idx; };
++
++#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
++
++/* DISPC common */
++#define DISPC_REVISION DISPC_REG(0x0000)
++#define DISPC_SYSCONFIG DISPC_REG(0x0010)
++#define DISPC_SYSSTATUS DISPC_REG(0x0014)
++#define DISPC_IRQSTATUS DISPC_REG(0x0018)
++#define DISPC_IRQENABLE DISPC_REG(0x001C)
++#define DISPC_CONTROL DISPC_REG(0x0040)
++#define DISPC_CONFIG DISPC_REG(0x0044)
++#define DISPC_CAPABLE DISPC_REG(0x0048)
++#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
++#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
++#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
++#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
++#define DISPC_LINE_STATUS DISPC_REG(0x005C)
++#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
++#define DISPC_TIMING_H DISPC_REG(0x0064)
++#define DISPC_TIMING_V DISPC_REG(0x0068)
++#define DISPC_POL_FREQ DISPC_REG(0x006C)
++#define DISPC_DIVISOR DISPC_REG(0x0070)
++#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
++#define DISPC_SIZE_DIG DISPC_REG(0x0078)
++#define DISPC_SIZE_LCD DISPC_REG(0x007C)
++
++/* DISPC GFX plane */
++#define DISPC_GFX_BA0 DISPC_REG(0x0080)
++#define DISPC_GFX_BA1 DISPC_REG(0x0084)
++#define DISPC_GFX_POSITION DISPC_REG(0x0088)
++#define DISPC_GFX_SIZE DISPC_REG(0x008C)
++#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
++#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
++#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
++#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
++#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
++#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
++#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
++
++#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
++#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
++#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
++
++#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
++#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
++#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
++
++#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
++
++/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
++#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
++
++#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
++#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
++#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
++#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
++#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
++#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
++#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
++#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
++#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
++#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
++#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
++#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
++#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
++
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
++/* coef index i = {0, 1, 2, 3, 4} */
++#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
++
++#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
++
++
++#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
++ DISPC_IRQ_OCP_ERR | \
++ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
++ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
++ DISPC_IRQ_SYNC_LOST | \
++ DISPC_IRQ_SYNC_LOST_DIGIT)
++
++#define DISPC_MAX_NR_ISRS 8
++
++struct omap_dispc_isr_data {
++ omap_dispc_isr_t isr;
++ void *arg;
++ u32 mask;
++};
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dispc_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
++
++static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
++ DISPC_VID_ATTRIBUTES(0),
++ DISPC_VID_ATTRIBUTES(1) };
++
++static struct {
++ void __iomem *base;
++
++ struct clk *dpll4_m4_ck;
++
++ unsigned long cache_req_pck;
++ unsigned long cache_prate;
++ struct dispc_clock_info cache_cinfo;
++
++ u32 fifo_size[3];
++
++ spinlock_t irq_lock;
++ u32 irq_error_mask;
++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
++ u32 error_irqs;
++ struct work_struct error_work;
++
++ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
++} dispc;
++
++static void _omap_dispc_set_irqs(void);
++
++static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
++{
++ __raw_writel(val, dispc.base + idx.idx);
++}
++
++static inline u32 dispc_read_reg(const struct dispc_reg idx)
++{
++ return __raw_readl(dispc.base + idx.idx);
++}
++
++#define SR(reg) \
++ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
++#define RR(reg) \
++ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
++
++void dispc_save_context(void)
++{
++ if (cpu_is_omap24xx())
++ return;
++
++ SR(SYSCONFIG);
++ SR(IRQENABLE);
++ SR(CONTROL);
++ SR(CONFIG);
++ SR(DEFAULT_COLOR0);
++ SR(DEFAULT_COLOR1);
++ SR(TRANS_COLOR0);
++ SR(TRANS_COLOR1);
++ SR(LINE_NUMBER);
++ SR(TIMING_H);
++ SR(TIMING_V);
++ SR(POL_FREQ);
++ SR(DIVISOR);
++ SR(GLOBAL_ALPHA);
++ SR(SIZE_DIG);
++ SR(SIZE_LCD);
++
++ SR(GFX_BA0);
++ SR(GFX_BA1);
++ SR(GFX_POSITION);
++ SR(GFX_SIZE);
++ SR(GFX_ATTRIBUTES);
++ SR(GFX_FIFO_THRESHOLD);
++ SR(GFX_ROW_INC);
++ SR(GFX_PIXEL_INC);
++ SR(GFX_WINDOW_SKIP);
++ SR(GFX_TABLE_BA);
++
++ SR(DATA_CYCLE1);
++ SR(DATA_CYCLE2);
++ SR(DATA_CYCLE3);
++
++ SR(CPR_COEF_R);
++ SR(CPR_COEF_G);
++ SR(CPR_COEF_B);
++
++ SR(GFX_PRELOAD);
++
++ /* VID1 */
++ SR(VID_BA0(0));
++ SR(VID_BA1(0));
++ SR(VID_POSITION(0));
++ SR(VID_SIZE(0));
++ SR(VID_ATTRIBUTES(0));
++ SR(VID_FIFO_THRESHOLD(0));
++ SR(VID_ROW_INC(0));
++ SR(VID_PIXEL_INC(0));
++ SR(VID_FIR(0));
++ SR(VID_PICTURE_SIZE(0));
++ SR(VID_ACCU0(0));
++ SR(VID_ACCU1(0));
++
++ SR(VID_FIR_COEF_H(0, 0));
++ SR(VID_FIR_COEF_H(0, 1));
++ SR(VID_FIR_COEF_H(0, 2));
++ SR(VID_FIR_COEF_H(0, 3));
++ SR(VID_FIR_COEF_H(0, 4));
++ SR(VID_FIR_COEF_H(0, 5));
++ SR(VID_FIR_COEF_H(0, 6));
++ SR(VID_FIR_COEF_H(0, 7));
++
++ SR(VID_FIR_COEF_HV(0, 0));
++ SR(VID_FIR_COEF_HV(0, 1));
++ SR(VID_FIR_COEF_HV(0, 2));
++ SR(VID_FIR_COEF_HV(0, 3));
++ SR(VID_FIR_COEF_HV(0, 4));
++ SR(VID_FIR_COEF_HV(0, 5));
++ SR(VID_FIR_COEF_HV(0, 6));
++ SR(VID_FIR_COEF_HV(0, 7));
++
++ SR(VID_CONV_COEF(0, 0));
++ SR(VID_CONV_COEF(0, 1));
++ SR(VID_CONV_COEF(0, 2));
++ SR(VID_CONV_COEF(0, 3));
++ SR(VID_CONV_COEF(0, 4));
++
++ SR(VID_FIR_COEF_V(0, 0));
++ SR(VID_FIR_COEF_V(0, 1));
++ SR(VID_FIR_COEF_V(0, 2));
++ SR(VID_FIR_COEF_V(0, 3));
++ SR(VID_FIR_COEF_V(0, 4));
++ SR(VID_FIR_COEF_V(0, 5));
++ SR(VID_FIR_COEF_V(0, 6));
++ SR(VID_FIR_COEF_V(0, 7));
++
++ SR(VID_PRELOAD(0));
++
++ /* VID2 */
++ SR(VID_BA0(1));
++ SR(VID_BA1(1));
++ SR(VID_POSITION(1));
++ SR(VID_SIZE(1));
++ SR(VID_ATTRIBUTES(1));
++ SR(VID_FIFO_THRESHOLD(1));
++ SR(VID_ROW_INC(1));
++ SR(VID_PIXEL_INC(1));
++ SR(VID_FIR(1));
++ SR(VID_PICTURE_SIZE(1));
++ SR(VID_ACCU0(1));
++ SR(VID_ACCU1(1));
++
++ SR(VID_FIR_COEF_H(1, 0));
++ SR(VID_FIR_COEF_H(1, 1));
++ SR(VID_FIR_COEF_H(1, 2));
++ SR(VID_FIR_COEF_H(1, 3));
++ SR(VID_FIR_COEF_H(1, 4));
++ SR(VID_FIR_COEF_H(1, 5));
++ SR(VID_FIR_COEF_H(1, 6));
++ SR(VID_FIR_COEF_H(1, 7));
++
++ SR(VID_FIR_COEF_HV(1, 0));
++ SR(VID_FIR_COEF_HV(1, 1));
++ SR(VID_FIR_COEF_HV(1, 2));
++ SR(VID_FIR_COEF_HV(1, 3));
++ SR(VID_FIR_COEF_HV(1, 4));
++ SR(VID_FIR_COEF_HV(1, 5));
++ SR(VID_FIR_COEF_HV(1, 6));
++ SR(VID_FIR_COEF_HV(1, 7));
++
++ SR(VID_CONV_COEF(1, 0));
++ SR(VID_CONV_COEF(1, 1));
++ SR(VID_CONV_COEF(1, 2));
++ SR(VID_CONV_COEF(1, 3));
++ SR(VID_CONV_COEF(1, 4));
++
++ SR(VID_FIR_COEF_V(1, 0));
++ SR(VID_FIR_COEF_V(1, 1));
++ SR(VID_FIR_COEF_V(1, 2));
++ SR(VID_FIR_COEF_V(1, 3));
++ SR(VID_FIR_COEF_V(1, 4));
++ SR(VID_FIR_COEF_V(1, 5));
++ SR(VID_FIR_COEF_V(1, 6));
++ SR(VID_FIR_COEF_V(1, 7));
++
++ SR(VID_PRELOAD(1));
++}
++
++void dispc_restore_context(void)
++{
++ RR(SYSCONFIG);
++ RR(IRQENABLE);
++ /*RR(CONTROL);*/
++ RR(CONFIG);
++ RR(DEFAULT_COLOR0);
++ RR(DEFAULT_COLOR1);
++ RR(TRANS_COLOR0);
++ RR(TRANS_COLOR1);
++ RR(LINE_NUMBER);
++ RR(TIMING_H);
++ RR(TIMING_V);
++ RR(POL_FREQ);
++ RR(DIVISOR);
++ RR(GLOBAL_ALPHA);
++ RR(SIZE_DIG);
++ RR(SIZE_LCD);
++
++ RR(GFX_BA0);
++ RR(GFX_BA1);
++ RR(GFX_POSITION);
++ RR(GFX_SIZE);
++ RR(GFX_ATTRIBUTES);
++ RR(GFX_FIFO_THRESHOLD);
++ RR(GFX_ROW_INC);
++ RR(GFX_PIXEL_INC);
++ RR(GFX_WINDOW_SKIP);
++ RR(GFX_TABLE_BA);
++
++ RR(DATA_CYCLE1);
++ RR(DATA_CYCLE2);
++ RR(DATA_CYCLE3);
++
++ RR(CPR_COEF_R);
++ RR(CPR_COEF_G);
++ RR(CPR_COEF_B);
++
++ RR(GFX_PRELOAD);
++
++ /* VID1 */
++ RR(VID_BA0(0));
++ RR(VID_BA1(0));
++ RR(VID_POSITION(0));
++ RR(VID_SIZE(0));
++ RR(VID_ATTRIBUTES(0));
++ RR(VID_FIFO_THRESHOLD(0));
++ RR(VID_ROW_INC(0));
++ RR(VID_PIXEL_INC(0));
++ RR(VID_FIR(0));
++ RR(VID_PICTURE_SIZE(0));
++ RR(VID_ACCU0(0));
++ RR(VID_ACCU1(0));
++
++ RR(VID_FIR_COEF_H(0, 0));
++ RR(VID_FIR_COEF_H(0, 1));
++ RR(VID_FIR_COEF_H(0, 2));
++ RR(VID_FIR_COEF_H(0, 3));
++ RR(VID_FIR_COEF_H(0, 4));
++ RR(VID_FIR_COEF_H(0, 5));
++ RR(VID_FIR_COEF_H(0, 6));
++ RR(VID_FIR_COEF_H(0, 7));
++
++ RR(VID_FIR_COEF_HV(0, 0));
++ RR(VID_FIR_COEF_HV(0, 1));
++ RR(VID_FIR_COEF_HV(0, 2));
++ RR(VID_FIR_COEF_HV(0, 3));
++ RR(VID_FIR_COEF_HV(0, 4));
++ RR(VID_FIR_COEF_HV(0, 5));
++ RR(VID_FIR_COEF_HV(0, 6));
++ RR(VID_FIR_COEF_HV(0, 7));
++
++ RR(VID_CONV_COEF(0, 0));
++ RR(VID_CONV_COEF(0, 1));
++ RR(VID_CONV_COEF(0, 2));
++ RR(VID_CONV_COEF(0, 3));
++ RR(VID_CONV_COEF(0, 4));
++
++ RR(VID_FIR_COEF_V(0, 0));
++ RR(VID_FIR_COEF_V(0, 1));
++ RR(VID_FIR_COEF_V(0, 2));
++ RR(VID_FIR_COEF_V(0, 3));
++ RR(VID_FIR_COEF_V(0, 4));
++ RR(VID_FIR_COEF_V(0, 5));
++ RR(VID_FIR_COEF_V(0, 6));
++ RR(VID_FIR_COEF_V(0, 7));
++
++ RR(VID_PRELOAD(0));
++
++ /* VID2 */
++ RR(VID_BA0(1));
++ RR(VID_BA1(1));
++ RR(VID_POSITION(1));
++ RR(VID_SIZE(1));
++ RR(VID_ATTRIBUTES(1));
++ RR(VID_FIFO_THRESHOLD(1));
++ RR(VID_ROW_INC(1));
++ RR(VID_PIXEL_INC(1));
++ RR(VID_FIR(1));
++ RR(VID_PICTURE_SIZE(1));
++ RR(VID_ACCU0(1));
++ RR(VID_ACCU1(1));
++
++ RR(VID_FIR_COEF_H(1, 0));
++ RR(VID_FIR_COEF_H(1, 1));
++ RR(VID_FIR_COEF_H(1, 2));
++ RR(VID_FIR_COEF_H(1, 3));
++ RR(VID_FIR_COEF_H(1, 4));
++ RR(VID_FIR_COEF_H(1, 5));
++ RR(VID_FIR_COEF_H(1, 6));
++ RR(VID_FIR_COEF_H(1, 7));
++
++ RR(VID_FIR_COEF_HV(1, 0));
++ RR(VID_FIR_COEF_HV(1, 1));
++ RR(VID_FIR_COEF_HV(1, 2));
++ RR(VID_FIR_COEF_HV(1, 3));
++ RR(VID_FIR_COEF_HV(1, 4));
++ RR(VID_FIR_COEF_HV(1, 5));
++ RR(VID_FIR_COEF_HV(1, 6));
++ RR(VID_FIR_COEF_HV(1, 7));
++
++ RR(VID_CONV_COEF(1, 0));
++ RR(VID_CONV_COEF(1, 1));
++ RR(VID_CONV_COEF(1, 2));
++ RR(VID_CONV_COEF(1, 3));
++ RR(VID_CONV_COEF(1, 4));
++
++ RR(VID_FIR_COEF_V(1, 0));
++ RR(VID_FIR_COEF_V(1, 1));
++ RR(VID_FIR_COEF_V(1, 2));
++ RR(VID_FIR_COEF_V(1, 3));
++ RR(VID_FIR_COEF_V(1, 4));
++ RR(VID_FIR_COEF_V(1, 5));
++ RR(VID_FIR_COEF_V(1, 6));
++ RR(VID_FIR_COEF_V(1, 7));
++
++ RR(VID_PRELOAD(1));
++
++ /* enable last, because LCD & DIGIT enable are here */
++ RR(CONTROL);
++}
++
++#undef SR
++#undef RR
++
++static inline void enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++bool dispc_go_busy(enum omap_channel channel)
++{
++ int bit;
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 5; /* GOLCD */
++ else
++ bit = 6; /* GODIGIT */
++
++ return REG_GET(DISPC_CONTROL, bit, bit) == 1;
++}
++
++void dispc_go(enum omap_channel channel)
++{
++ int bit;
++
++ enable_clocks(1);
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 0; /* LCDENABLE */
++ else
++ bit = 1; /* DIGITALENABLE */
++
++ /* if the channel is not enabled, we don't need GO */
++ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
++ goto end;
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 5; /* GOLCD */
++ else
++ bit = 6; /* GODIGIT */
++
++ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
++ DSSERR("GO bit not down for channel %d\n", channel);
++ goto end;
++ }
++
++ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
++
++ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
++end:
++ enable_clocks(0);
++}
++
++static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
++}
++
++static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
++}
++
++static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
++}
++
++static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
++ int vscaleup, int five_taps)
++{
++ /* Coefficients for horizontal up-sampling */
++ static const u32 coef_hup[8] = {
++ 0x00800000,
++ 0x0D7CF800,
++ 0x1E70F5FF,
++ 0x335FF5FE,
++ 0xF74949F7,
++ 0xF55F33FB,
++ 0xF5701EFE,
++ 0xF87C0DFF,
++ };
++
++ /* Coefficients for horizontal down-sampling */
++ static const u32 coef_hdown[8] = {
++ 0x24382400,
++ 0x28371FFE,
++ 0x2C361BFB,
++ 0x303516F9,
++ 0x11343311,
++ 0x1635300C,
++ 0x1B362C08,
++ 0x1F372804,
++ };
++
++ /* Coefficients for horizontal and vertical up-sampling */
++ static const u32 coef_hvup[2][8] = {
++ {
++ 0x00800000,
++ 0x037B02FF,
++ 0x0C6F05FE,
++ 0x205907FB,
++ 0x00404000,
++ 0x075920FE,
++ 0x056F0CFF,
++ 0x027B0300,
++ },
++ {
++ 0x00800000,
++ 0x0D7CF8FF,
++ 0x1E70F5FE,
++ 0x335FF5FB,
++ 0xF7404000,
++ 0xF55F33FE,
++ 0xF5701EFF,
++ 0xF87C0D00,
++ },
++ };
++
++ /* Coefficients for horizontal and vertical down-sampling */
++ static const u32 coef_hvdown[2][8] = {
++ {
++ 0x24382400,
++ 0x28391F04,
++ 0x2D381B08,
++ 0x3237170C,
++ 0x123737F7,
++ 0x173732F9,
++ 0x1B382DFB,
++ 0x1F3928FE,
++ },
++ {
++ 0x24382400,
++ 0x28371F04,
++ 0x2C361B08,
++ 0x3035160C,
++ 0x113433F7,
++ 0x163530F9,
++ 0x1B362CFB,
++ 0x1F3728FE,
++ },
++ };
++
++ /* Coefficients for vertical up-sampling */
++ static const u32 coef_vup[8] = {
++ 0x00000000,
++ 0x0000FF00,
++ 0x0000FEFF,
++ 0x0000FBFE,
++ 0x000000F7,
++ 0x0000FEFB,
++ 0x0000FFFE,
++ 0x000000FF,
++ };
++
++
++ /* Coefficients for vertical down-sampling */
++ static const u32 coef_vdown[8] = {
++ 0x00000000,
++ 0x000004FE,
++ 0x000008FB,
++ 0x00000CF9,
++ 0x0000F711,
++ 0x0000F90C,
++ 0x0000FB08,
++ 0x0000FE04,
++ };
++
++ const u32 *h_coef;
++ const u32 *hv_coef;
++ const u32 *hv_coef_mod;
++ const u32 *v_coef;
++ int i;
++
++ if (hscaleup)
++ h_coef = coef_hup;
++ else
++ h_coef = coef_hdown;
++
++ if (vscaleup) {
++ hv_coef = coef_hvup[five_taps];
++ v_coef = coef_vup;
++
++ if (hscaleup)
++ hv_coef_mod = NULL;
++ else
++ hv_coef_mod = coef_hvdown[five_taps];
++ } else {
++ hv_coef = coef_hvdown[five_taps];
++ v_coef = coef_vdown;
++
++ if (hscaleup)
++ hv_coef_mod = coef_hvup[five_taps];
++ else
++ hv_coef_mod = NULL;
++ }
++
++ for (i = 0; i < 8; i++) {
++ u32 h, hv;
++
++ h = h_coef[i];
++
++ hv = hv_coef[i];
++
++ if (hv_coef_mod) {
++ hv &= 0xffffff00;
++ hv |= (hv_coef_mod[i] & 0xff);
++ }
++
++ _dispc_write_firh_reg(plane, i, h);
++ _dispc_write_firhv_reg(plane, i, hv);
++ }
++
++ if (!five_taps)
++ return;
++
++ for (i = 0; i < 8; i++) {
++ u32 v;
++ v = v_coef[i];
++ _dispc_write_firv_reg(plane, i, v);
++ }
++}
++
++static void _dispc_setup_color_conv_coef(void)
++{
++ const struct color_conv_coef {
++ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
++ int full_range;
++ } ctbl_bt601_5 = {
++ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
++ };
++
++ const struct color_conv_coef *ct;
++
++#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
++
++ ct = &ctbl_bt601_5;
++
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
++
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
++
++#undef CVAL
++
++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
++}
++
++
++static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
++{
++ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
++ DISPC_VID_BA0(0),
++ DISPC_VID_BA0(1) };
++
++ dispc_write_reg(ba0_reg[plane], paddr);
++}
++
++static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
++{
++ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
++ DISPC_VID_BA1(0),
++ DISPC_VID_BA1(1) };
++
++ dispc_write_reg(ba1_reg[plane], paddr);
++}
++
++static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
++{
++ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
++ DISPC_VID_POSITION(0),
++ DISPC_VID_POSITION(1) };
++
++ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
++ dispc_write_reg(pos_reg[plane], val);
++}
++
++static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
++{
++ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
++ DISPC_VID_PICTURE_SIZE(0),
++ DISPC_VID_PICTURE_SIZE(1) };
++ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ dispc_write_reg(siz_reg[plane], val);
++}
++
++static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
++{
++ u32 val;
++ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
++ DISPC_VID_SIZE(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ dispc_write_reg(vsi_reg[plane-1], val);
++}
++
++static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
++{
++
++ BUG_ON(plane == OMAP_DSS_VIDEO1);
++
++ if (plane == OMAP_DSS_GFX)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
++ else if (plane == OMAP_DSS_VIDEO2)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
++}
++
++static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
++{
++ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
++ DISPC_VID_PIXEL_INC(0),
++ DISPC_VID_PIXEL_INC(1) };
++
++ dispc_write_reg(ri_reg[plane], inc);
++}
++
++static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
++{
++ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
++ DISPC_VID_ROW_INC(0),
++ DISPC_VID_ROW_INC(1) };
++
++ dispc_write_reg(ri_reg[plane], inc);
++}
++
++static void _dispc_set_color_mode(enum omap_plane plane,
++ enum omap_color_mode color_mode)
++{
++ u32 m = 0;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_CLUT1:
++ m = 0x0; break;
++ case OMAP_DSS_COLOR_CLUT2:
++ m = 0x1; break;
++ case OMAP_DSS_COLOR_CLUT4:
++ m = 0x2; break;
++ case OMAP_DSS_COLOR_CLUT8:
++ m = 0x3; break;
++ case OMAP_DSS_COLOR_RGB12U:
++ m = 0x4; break;
++ case OMAP_DSS_COLOR_ARGB16:
++ m = 0x5; break;
++ case OMAP_DSS_COLOR_RGB16:
++ m = 0x6; break;
++ case OMAP_DSS_COLOR_RGB24U:
++ m = 0x8; break;
++ case OMAP_DSS_COLOR_RGB24P:
++ m = 0x9; break;
++ case OMAP_DSS_COLOR_YUV2:
++ m = 0xa; break;
++ case OMAP_DSS_COLOR_UYVY:
++ m = 0xb; break;
++ case OMAP_DSS_COLOR_ARGB32:
++ m = 0xc; break;
++ case OMAP_DSS_COLOR_RGBA32:
++ m = 0xd; break;
++ case OMAP_DSS_COLOR_RGBX32:
++ m = 0xe; break;
++ default:
++ BUG(); break;
++ }
++
++ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
++}
++
++static void _dispc_set_channel_out(enum omap_plane plane,
++ enum omap_channel channel)
++{
++ int shift;
++ u32 val;
++
++ switch (plane) {
++ case OMAP_DSS_GFX:
++ shift = 8;
++ break;
++ case OMAP_DSS_VIDEO1:
++ case OMAP_DSS_VIDEO2:
++ shift = 16;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, channel, shift, shift);
++ dispc_write_reg(dispc_reg_att[plane], val);
++}
++
++void dispc_set_burst_size(enum omap_plane plane,
++ enum omap_burst_size burst_size)
++{
++ int shift;
++ u32 val;
++
++ enable_clocks(1);
++
++ switch (plane) {
++ case OMAP_DSS_GFX:
++ shift = 6;
++ break;
++ case OMAP_DSS_VIDEO1:
++ case OMAP_DSS_VIDEO2:
++ shift = 14;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, burst_size, shift+1, shift);
++ dispc_write_reg(dispc_reg_att[plane], val);
++
++ enable_clocks(0);
++}
++
++static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
++{
++ u32 val;
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, enable, 9, 9);
++ dispc_write_reg(dispc_reg_att[plane], val);
++}
++
++void dispc_enable_replication(enum omap_plane plane, bool enable)
++{
++ int bit;
++
++ if (plane == OMAP_DSS_GFX)
++ bit = 5;
++ else
++ bit = 10;
++
++ enable_clocks(1);
++ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
++ enable_clocks(0);
++}
++
++void dispc_set_lcd_size(u16 width, u16 height)
++{
++ u32 val;
++ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ enable_clocks(1);
++ dispc_write_reg(DISPC_SIZE_LCD, val);
++ enable_clocks(0);
++}
++
++void dispc_set_digit_size(u16 width, u16 height)
++{
++ u32 val;
++ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ enable_clocks(1);
++ dispc_write_reg(DISPC_SIZE_DIG, val);
++ enable_clocks(0);
++}
++
++static void dispc_read_plane_fifo_sizes(void)
++{
++ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
++ DISPC_VID_FIFO_SIZE_STATUS(0),
++ DISPC_VID_FIFO_SIZE_STATUS(1) };
++ u32 size;
++ int plane;
++
++ enable_clocks(1);
++
++ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
++ if (cpu_is_omap24xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
++ else if (cpu_is_omap34xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
++ else
++ BUG();
++
++ dispc.fifo_size[plane] = size;
++ }
++
++ enable_clocks(0);
++}
++
++u32 dispc_get_plane_fifo_size(enum omap_plane plane)
++{
++ return dispc.fifo_size[plane];
++}
++
++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
++{
++ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
++ DISPC_VID_FIFO_THRESHOLD(0),
++ DISPC_VID_FIFO_THRESHOLD(1) };
++ enable_clocks(1);
++
++ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
++ plane,
++ REG_GET(ftrs_reg[plane], 11, 0),
++ REG_GET(ftrs_reg[plane], 27, 16),
++ low, high);
++
++ if (cpu_is_omap24xx())
++ dispc_write_reg(ftrs_reg[plane],
++ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
++ else
++ dispc_write_reg(ftrs_reg[plane],
++ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
++
++ enable_clocks(0);
++}
++
++void dispc_enable_fifomerge(bool enable)
++{
++ enable_clocks(1);
++
++ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
++
++ enable_clocks(0);
++}
++
++static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
++{
++ u32 val;
++ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
++ DISPC_VID_FIR(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ if (cpu_is_omap24xx())
++ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
++ else
++ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
++ dispc_write_reg(fir_reg[plane-1], val);
++}
++
++static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
++{
++ u32 val;
++ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
++ DISPC_VID_ACCU0(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
++ dispc_write_reg(ac0_reg[plane-1], val);
++}
++
++static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
++{
++ u32 val;
++ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
++ DISPC_VID_ACCU1(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
++ dispc_write_reg(ac1_reg[plane-1], val);
++}
++
++
++static void _dispc_set_scaling(enum omap_plane plane,
++ u16 orig_width, u16 orig_height,
++ u16 out_width, u16 out_height,
++ bool ilace, bool five_taps,
++ bool fieldmode)
++{
++ int fir_hinc;
++ int fir_vinc;
++ int hscaleup, vscaleup;
++ int accu0 = 0;
++ int accu1 = 0;
++ u32 l;
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ hscaleup = orig_width <= out_width;
++ vscaleup = orig_height <= out_height;
++
++ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
++
++ if (!orig_width || orig_width == out_width)
++ fir_hinc = 0;
++ else
++ fir_hinc = 1024 * orig_width / out_width;
++
++ if (!orig_height || orig_height == out_height)
++ fir_vinc = 0;
++ else
++ fir_vinc = 1024 * orig_height / out_height;
++
++ _dispc_set_fir(plane, fir_hinc, fir_vinc);
++
++ l = dispc_read_reg(dispc_reg_att[plane]);
++ l &= ~((0x0f << 5) | (0x3 << 21));
++
++ l |= fir_hinc ? (1 << 5) : 0;
++ l |= fir_vinc ? (1 << 6) : 0;
++
++ l |= hscaleup ? 0 : (1 << 7);
++ l |= vscaleup ? 0 : (1 << 8);
++
++ l |= five_taps ? (1 << 21) : 0;
++ l |= five_taps ? (1 << 22) : 0;
++
++ dispc_write_reg(dispc_reg_att[plane], l);
++
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
++ if (ilace && !fieldmode) {
++ accu1 = 0;
++ accu0 = (fir_vinc / 2) & 0x3ff;
++ if (accu0 >= 1024/2) {
++ accu1 = 1024/2;
++ accu0 -= accu1;
++ }
++ }
++
++ _dispc_set_vid_accu0(plane, 0, accu0);
++ _dispc_set_vid_accu1(plane, 0, accu1);
++}
++
++static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
++ bool mirroring, enum omap_color_mode color_mode)
++{
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY) {
++ int vidrot = 0;
++
++ if (mirroring) {
++ switch (rotation) {
++ case 0:
++ vidrot = 2;
++ break;
++ case 1:
++ vidrot = 1;
++ break;
++ case 2:
++ vidrot = 0;
++ break;
++ case 3:
++ vidrot = 3;
++ break;
++ }
++ } else {
++ switch (rotation) {
++ case 0:
++ vidrot = 0;
++ break;
++ case 1:
++ vidrot = 1;
++ break;
++ case 2:
++ vidrot = 2;
++ break;
++ case 3:
++ vidrot = 3;
++ break;
++ }
++ }
++
++ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
++
++ if (rotation == 1 || rotation == 3)
++ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
++ else
++ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
++ } else {
++ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
++ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
++ }
++}
++
++static s32 pixinc(int pixels, u8 ps)
++{
++ if (pixels == 1)
++ return 1;
++ else if (pixels > 1)
++ return 1 + (pixels - 1) * ps;
++ else if (pixels < 0)
++ return 1 - (-pixels + 1) * ps;
++ else
++ BUG();
++}
++
++static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
++ u16 screen_width,
++ u16 width, u16 height,
++ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned int field_offset,
++ unsigned *offset0, unsigned *offset1,
++ s32 *row_inc, s32 *pix_inc)
++{
++ u8 ps;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ ps = 2;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ ps = 3;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ ps = 4;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
++ width, height);
++
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
++ switch (rotation + mirror * 4) {
++ case 0:
++ case 2:
++ /*
++ * If the pixel format is YUV or UYVY divide the width
++ * of the image by 2 for 0 and 180 degree rotation.
++ */
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY)
++ width = width >> 1;
++ case 1:
++ case 3:
++ *offset1 = 0;
++ if (field_offset)
++ *offset0 = field_offset * screen_width * ps;
++ else
++ *offset0 = 0;
++
++ *row_inc = pixinc(1 + (screen_width - width) +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ case 4:
++ case 6:
++ /* If the pixel format is YUV or UYVY divide the width
++ * of the image by 2 for 0 degree and 180 degree
++ */
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY)
++ width = width >> 1;
++ case 5:
++ case 7:
++ *offset1 = 0;
++ if (field_offset)
++ *offset0 = field_offset * screen_width * ps;
++ else
++ *offset0 = 0;
++ *row_inc = pixinc(1 - (screen_width + width) -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ default:
++ BUG();
++ }
++}
++
++static void calc_dma_rotation_offset(u8 rotation, bool mirror,
++ u16 screen_width,
++ u16 width, u16 height,
++ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned int field_offset,
++ unsigned *offset0, unsigned *offset1,
++ s32 *row_inc, s32 *pix_inc)
++{
++ u8 ps;
++ u16 fbw, fbh;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ ps = 2;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ ps = 3;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ ps = 4;
++ break;
++
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ ps = 2;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
++ width, height);
++
++ /* width & height are overlay sizes, convert to fb sizes */
++
++ if (rotation == 0 || rotation == 2) {
++ fbw = width;
++ fbh = height;
++ } else {
++ fbw = height;
++ fbh = width;
++ }
++
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
++ switch (rotation + mirror * 4) {
++ case 0:
++ *offset1 = 0;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * screen_width * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(1 + (screen_width - fbw) +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++ case 1:
++ *offset1 = screen_width * (fbh - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
++ (fieldmode ? 1 : 0), ps);
++ *pix_inc = pixinc(-screen_width, ps);
++ break;
++ case 2:
++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * screen_width * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(-1 -
++ (screen_width - fbw) -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(-1, ps);
++ break;
++ case 3:
++ *offset1 = (fbw - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
++ (fieldmode ? 1 : 0), ps);
++ *pix_inc = pixinc(screen_width, ps);
++ break;
++
++ /* mirroring */
++ case 0 + 4:
++ *offset1 = (fbw - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * screen_width * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(screen_width * 2 - 1 +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(-1, ps);
++ break;
++
++ case 1 + 4:
++ *offset1 = 0;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
++ (fieldmode ? 1 : 0),
++ ps);
++ *pix_inc = pixinc(screen_width, ps);
++ break;
++
++ case 2 + 4:
++ *offset1 = screen_width * (fbh - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * screen_width * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(1 - screen_width * 2 -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ case 3 + 4:
++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * ps;
++ else
++ *offset0 = *offset1;
++ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
++ (fieldmode ? 1 : 0),
++ ps);
++ *pix_inc = pixinc(-screen_width, ps);
++ break;
++
++ default:
++ BUG();
++ }
++}
++
++static unsigned long calc_fclk_five_taps(u16 width, u16 height,
++ u16 out_width, u16 out_height, enum omap_color_mode color_mode)
++{
++ u32 fclk = 0;
++ /* FIXME venc pclk? */
++ u64 tmp, pclk = dispc_pclk_rate();
++
++ if (height > out_height) {
++ /* FIXME get real display PPL */
++ unsigned int ppl = 800;
++
++ tmp = pclk * height * out_width;
++ do_div(tmp, 2 * out_height * ppl);
++ fclk = tmp;
++
++ if (height > 2 * out_height && ppl != out_width) {
++ tmp = pclk * (height - 2 * out_height) * out_width;
++ do_div(tmp, 2 * out_height * (ppl - out_width));
++ fclk = max(fclk, (u32) tmp);
++ }
++ }
++
++ if (width > out_width) {
++ tmp = pclk * width;
++ do_div(tmp, out_width);
++ fclk = max(fclk, (u32) tmp);
++
++ if (color_mode == OMAP_DSS_COLOR_RGB24U)
++ fclk <<= 1;
++ }
++
++ return fclk;
++}
++
++static unsigned long calc_fclk(u16 width, u16 height,
++ u16 out_width, u16 out_height)
++{
++ unsigned int hf, vf;
++
++ /*
++ * FIXME how to determine the 'A' factor
++ * for the no downscaling case ?
++ */
++
++ if (width > 3 * out_width)
++ hf = 4;
++ else if (width > 2 * out_width)
++ hf = 3;
++ else if (width > out_width)
++ hf = 2;
++ else
++ hf = 1;
++
++ if (height > out_height)
++ vf = 2;
++ else
++ vf = 1;
++
++ /* FIXME venc pclk? */
++ return dispc_pclk_rate() * vf * hf;
++}
++
++void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
++{
++ enable_clocks(1);
++ _dispc_set_channel_out(plane, channel_out);
++ enable_clocks(0);
++}
++
++static int _dispc_setup_plane(enum omap_plane plane,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
++ u8 rotation, int mirror,
++ u8 global_alpha)
++{
++ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
++ bool five_taps = 0;
++ bool fieldmode = 0;
++ int cconv = 0;
++ unsigned offset0, offset1;
++ s32 row_inc;
++ s32 pix_inc;
++ u16 frame_height = height;
++ unsigned int field_offset = 0;
++
++ if (paddr == 0)
++ return -EINVAL;
++
++ if (ilace && height == out_height)
++ fieldmode = 1;
++
++ if (ilace) {
++ if (fieldmode)
++ height /= 2;
++ pos_y /= 2;
++ out_height /= 2;
++
++ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
++ "out_height %d\n",
++ height, pos_y, out_height);
++ }
++
++ if (plane == OMAP_DSS_GFX) {
++ if (width != out_width || height != out_height)
++ return -EINVAL;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_RGB24P:
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ } else {
++ /* video plane */
++
++ unsigned long fclk = 0;
++
++ if (out_width < width / maxdownscale ||
++ out_width > width * 8)
++ return -EINVAL;
++
++ if (out_height < height / maxdownscale ||
++ out_height > height * 8)
++ return -EINVAL;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_RGB24P:
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_RGBX32:
++ break;
++
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ if (plane == OMAP_DSS_VIDEO1)
++ return -EINVAL;
++ break;
++
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ cconv = 1;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ /* Must use 5-tap filter? */
++ five_taps = height > out_height * 2;
++
++ if (!five_taps) {
++ fclk = calc_fclk(width, height,
++ out_width, out_height);
++
++ /* Try 5-tap filter if 3-tap fclk is too high */
++ if (cpu_is_omap34xx() && height > out_height &&
++ fclk > dispc_fclk_rate())
++ five_taps = true;
++ }
++
++ if (width > (2048 >> five_taps))
++ return -EINVAL;
++
++ if (five_taps)
++ fclk = calc_fclk_five_taps(width, height,
++ out_width, out_height, color_mode);
++
++ DSSDBG("required fclk rate = %lu Hz\n", fclk);
++ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
++
++ if (fclk > dispc_fclk_rate()) {
++ DSSERR("failed to set up scaling, "
++ "required fclk rate = %lu Hz, "
++ "current fclk rate = %lu Hz\n",
++ fclk, dispc_fclk_rate());
++ return -EINVAL;
++ }
++ }
++
++ if (ilace && !fieldmode) {
++ /*
++ * when downscaling the bottom field may have to start several
++ * source lines below the top field. Unfortunately ACCUI
++ * registers will only hold the fractional part of the offset
++ * so the integer part must be added to the base address of the
++ * bottom field.
++ */
++ if (!height || height == out_height)
++ field_offset = 0;
++ else
++ field_offset = height / out_height / 2;
++ }
++
++ /* Fields are independent but interleaved in memory. */
++ if (fieldmode)
++ field_offset = 1;
++
++ if (rotation_type == OMAP_DSS_ROT_DMA)
++ calc_dma_rotation_offset(rotation, mirror,
++ screen_width, width, frame_height, color_mode,
++ fieldmode, field_offset,
++ &offset0, &offset1, &row_inc, &pix_inc);
++ else
++ calc_vrfb_rotation_offset(rotation, mirror,
++ screen_width, width, frame_height, color_mode,
++ fieldmode, field_offset,
++ &offset0, &offset1, &row_inc, &pix_inc);
++
++ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
++ offset0, offset1, row_inc, pix_inc);
++
++ _dispc_set_color_mode(plane, color_mode);
++
++ _dispc_set_plane_ba0(plane, paddr + offset0);
++ _dispc_set_plane_ba1(plane, paddr + offset1);
++
++ _dispc_set_row_inc(plane, row_inc);
++ _dispc_set_pix_inc(plane, pix_inc);
++
++ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
++ out_width, out_height);
++
++ _dispc_set_plane_pos(plane, pos_x, pos_y);
++
++ _dispc_set_pic_size(plane, width, height);
++
++ if (plane != OMAP_DSS_GFX) {
++ _dispc_set_scaling(plane, width, height,
++ out_width, out_height,
++ ilace, five_taps, fieldmode);
++ _dispc_set_vid_size(plane, out_width, out_height);
++ _dispc_set_vid_color_conv(plane, cconv);
++ }
++
++ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
++
++ if (plane != OMAP_DSS_VIDEO1)
++ _dispc_setup_global_alpha(plane, global_alpha);
++
++ return 0;
++}
++
++static void _dispc_enable_plane(enum omap_plane plane, bool enable)
++{
++ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
++}
++
++static void dispc_disable_isr(void *data, u32 mask)
++{
++ struct completion *compl = data;
++ complete(compl);
++}
++
++static void _enable_lcd_out(bool enable)
++{
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
++}
++
++void dispc_enable_lcd_out(bool enable)
++{
++ struct completion frame_done_completion;
++ bool is_on;
++ int r;
++
++ enable_clocks(1);
++
++ /* When we disable LCD output, we need to wait until frame is done.
++ * Otherwise the DSS is still working, and turning off the clocks
++ * prevents DSS from going to OFF mode */
++ is_on = REG_GET(DISPC_CONTROL, 0, 0);
++
++ if (!enable && is_on) {
++ init_completion(&frame_done_completion);
++
++ r = omap_dispc_register_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_FRAMEDONE);
++
++ if (r)
++ DSSERR("failed to register FRAMEDONE isr\n");
++ }
++
++ _enable_lcd_out(enable);
++
++ if (!enable && is_on) {
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for FRAME DONE\n");
++
++ r = omap_dispc_unregister_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_FRAMEDONE);
++
++ if (r)
++ DSSERR("failed to unregister FRAMEDONE isr\n");
++ }
++
++ enable_clocks(0);
++}
++
++static void _enable_digit_out(bool enable)
++{
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
++}
++
++void dispc_enable_digit_out(bool enable)
++{
++ struct completion frame_done_completion;
++ int r;
++
++ enable_clocks(1);
++
++ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
++ enable_clocks(0);
++ return;
++ }
++
++ if (enable) {
++ unsigned long flags;
++ /* When we enable digit output, we'll get an extra digit
++ * sync lost interrupt, that we need to ignore */
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++ }
++
++ /* When we disable digit output, we need to wait until fields are done.
++ * Otherwise the DSS is still working, and turning off the clocks
++ * prevents DSS from going to OFF mode. And when enabling, we need to
++ * wait for the extra sync losts */
++ init_completion(&frame_done_completion);
++
++ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
++ if (r)
++ DSSERR("failed to register EVSYNC isr\n");
++
++ _enable_digit_out(enable);
++
++ /* XXX I understand from TRM that we should only wait for the
++ * current field to complete. But it seems we have to wait
++ * for both fields */
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for EVSYNC\n");
++
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for EVSYNC\n");
++
++ r = omap_dispc_unregister_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
++ if (r)
++ DSSERR("failed to unregister EVSYNC isr\n");
++
++ if (enable) {
++ unsigned long flags;
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
++ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++ }
++
++ enable_clocks(0);
++}
++
++void dispc_lcd_enable_signal_polarity(bool act_high)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
++ enable_clocks(0);
++}
++
++void dispc_lcd_enable_signal(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
++ enable_clocks(0);
++}
++
++void dispc_pck_free_enable(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
++ enable_clocks(0);
++}
++
++void dispc_enable_fifohandcheck(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
++ enable_clocks(0);
++}
++
++
++void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
++{
++ int mode;
++
++ switch (type) {
++ case OMAP_DSS_LCD_DISPLAY_STN:
++ mode = 0;
++ break;
++
++ case OMAP_DSS_LCD_DISPLAY_TFT:
++ mode = 1;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
++ enable_clocks(0);
++}
++
++void dispc_set_loadmode(enum omap_dss_load_mode mode)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
++ enable_clocks(0);
++}
++
++
++void dispc_set_default_color(enum omap_channel channel, u32 color)
++{
++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
++ DISPC_DEFAULT_COLOR1 };
++
++ enable_clocks(1);
++ dispc_write_reg(def_reg[channel], color);
++ enable_clocks(0);
++}
++
++u32 dispc_get_default_color(enum omap_channel channel)
++{
++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
++ DISPC_DEFAULT_COLOR1 };
++ u32 l;
++
++ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
++ channel != OMAP_DSS_CHANNEL_LCD);
++
++ enable_clocks(1);
++ l = dispc_read_reg(def_reg[channel]);
++ enable_clocks(0);
++
++ return l;
++}
++
++void dispc_set_trans_key(enum omap_channel ch,
++ enum omap_dss_trans_key_type type,
++ u32 trans_key)
++{
++ const struct dispc_reg tr_reg[] = {
++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
++
++ dispc_write_reg(tr_reg[ch], trans_key);
++ enable_clocks(0);
++}
++
++void dispc_get_trans_key(enum omap_channel ch,
++ enum omap_dss_trans_key_type *type,
++ u32 *trans_key)
++{
++ const struct dispc_reg tr_reg[] = {
++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
++
++ enable_clocks(1);
++ if (type) {
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ *type = REG_GET(DISPC_CONFIG, 11, 11);
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ *type = REG_GET(DISPC_CONFIG, 13, 13);
++ else
++ BUG();
++ }
++
++ if (trans_key)
++ *trans_key = dispc_read_reg(tr_reg[ch]);
++ enable_clocks(0);
++}
++
++void dispc_enable_trans_key(enum omap_channel ch, bool enable)
++{
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
++ enable_clocks(0);
++}
++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
++{
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
++ enable_clocks(0);
++}
++bool dispc_alpha_blending_enabled(enum omap_channel ch)
++{
++ bool enabled;
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ enabled = REG_GET(DISPC_CONFIG, 18, 18);
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ enabled = REG_GET(DISPC_CONFIG, 18, 18);
++ else
++ BUG();
++ enable_clocks(0);
++
++ return enabled;
++
++}
++
++
++bool dispc_trans_key_enabled(enum omap_channel ch)
++{
++ bool enabled;
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ enabled = REG_GET(DISPC_CONFIG, 10, 10);
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ enabled = REG_GET(DISPC_CONFIG, 12, 12);
++ else
++ BUG();
++ enable_clocks(0);
++
++ return enabled;
++}
++
++
++void dispc_set_tft_data_lines(u8 data_lines)
++{
++ int code;
++
++ switch (data_lines) {
++ case 12:
++ code = 0;
++ break;
++ case 16:
++ code = 1;
++ break;
++ case 18:
++ code = 2;
++ break;
++ case 24:
++ code = 3;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
++ enable_clocks(0);
++}
++
++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
++{
++ u32 l;
++ int stallmode;
++ int gpout0 = 1;
++ int gpout1;
++
++ switch (mode) {
++ case OMAP_DSS_PARALLELMODE_BYPASS:
++ stallmode = 0;
++ gpout1 = 1;
++ break;
++
++ case OMAP_DSS_PARALLELMODE_RFBI:
++ stallmode = 1;
++ gpout1 = 0;
++ break;
++
++ case OMAP_DSS_PARALLELMODE_DSI:
++ stallmode = 1;
++ gpout1 = 1;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++
++ l = dispc_read_reg(DISPC_CONTROL);
++
++ l = FLD_MOD(l, stallmode, 11, 11);
++ l = FLD_MOD(l, gpout0, 15, 15);
++ l = FLD_MOD(l, gpout1, 16, 16);
++
++ dispc_write_reg(DISPC_CONTROL, l);
++
++ enable_clocks(0);
++}
++
++static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
++ int vsw, int vfp, int vbp)
++{
++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
++ if (hsw < 1 || hsw > 64 ||
++ hfp < 1 || hfp > 256 ||
++ hbp < 1 || hbp > 256 ||
++ vsw < 1 || vsw > 64 ||
++ vfp < 0 || vfp > 255 ||
++ vbp < 0 || vbp > 255)
++ return false;
++ } else {
++ if (hsw < 1 || hsw > 256 ||
++ hfp < 1 || hfp > 4096 ||
++ hbp < 1 || hbp > 4096 ||
++ vsw < 1 || vsw > 256 ||
++ vfp < 0 || vfp > 4095 ||
++ vbp < 0 || vbp > 4095)
++ return false;
++ }
++
++ return true;
++}
++
++bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
++{
++ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
++ timings->hbp, timings->vsw,
++ timings->vfp, timings->vbp);
++}
++
++static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
++ int vsw, int vfp, int vbp)
++{
++ u32 timing_h, timing_v;
++
++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
++ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
++ FLD_VAL(hbp-1, 27, 20);
++
++ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
++ FLD_VAL(vbp, 27, 20);
++ } else {
++ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
++ FLD_VAL(hbp-1, 31, 20);
++
++ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
++ FLD_VAL(vbp, 31, 20);
++ }
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_TIMING_H, timing_h);
++ dispc_write_reg(DISPC_TIMING_V, timing_v);
++ enable_clocks(0);
++}
++
++/* change name to mode? */
++void dispc_set_lcd_timings(struct omap_video_timings *timings)
++{
++ unsigned xtot, ytot;
++ unsigned long ht, vt;
++
++ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
++ timings->hbp, timings->vsw,
++ timings->vfp, timings->vbp))
++ BUG();
++
++ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
++ timings->vsw, timings->vfp, timings->vbp);
++
++ dispc_set_lcd_size(timings->x_res, timings->y_res);
++
++ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
++ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
++
++ ht = (timings->pixel_clock * 1000) / xtot;
++ vt = (timings->pixel_clock * 1000) / xtot / ytot;
++
++ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
++ DSSDBG("pck %u\n", timings->pixel_clock);
++ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
++ timings->hsw, timings->hfp, timings->hbp,
++ timings->vsw, timings->vfp, timings->vbp);
++
++ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
++}
++
++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
++{
++ BUG_ON(lck_div < 1);
++ BUG_ON(pck_div < 2);
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_DIVISOR,
++ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
++ enable_clocks(0);
++}
++
++static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
++{
++ u32 l;
++ l = dispc_read_reg(DISPC_DIVISOR);
++ *lck_div = FLD_GET(l, 23, 16);
++ *pck_div = FLD_GET(l, 7, 0);
++}
++
++unsigned long dispc_fclk_rate(void)
++{
++ unsigned long r = 0;
++
++ if (dss_get_dispc_clk_source() == 0)
++ r = dss_clk_get_rate(DSS_CLK_FCK1);
++ else
++#ifdef CONFIG_OMAP2_DSS_DSI
++ r = dsi_get_dsi1_pll_rate();
++#else
++ BUG();
++#endif
++ return r;
++}
++
++unsigned long dispc_lclk_rate(void)
++{
++ int lcd;
++ unsigned long r;
++ u32 l;
++
++ l = dispc_read_reg(DISPC_DIVISOR);
++
++ lcd = FLD_GET(l, 23, 16);
++
++ r = dispc_fclk_rate();
++
++ return r / lcd;
++}
++
++unsigned long dispc_pclk_rate(void)
++{
++ int lcd, pcd;
++ unsigned long r;
++ u32 l;
++
++ l = dispc_read_reg(DISPC_DIVISOR);
++
++ lcd = FLD_GET(l, 23, 16);
++ pcd = FLD_GET(l, 7, 0);
++
++ r = dispc_fclk_rate();
++
++ return r / lcd / pcd;
++}
++
++void dispc_dump_clocks(struct seq_file *s)
++{
++ int lcd, pcd;
++
++ enable_clocks(1);
++
++ dispc_get_lcd_divisor(&lcd, &pcd);
++
++ seq_printf(s, "- dispc -\n");
++
++ seq_printf(s, "dispc fclk source = %s\n",
++ dss_get_dispc_clk_source() == 0 ?
++ "dss1_alwon_fclk" : "dsi1_pll_fclk");
++
++ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
++ dispc_fclk_rate(),
++ lcd, pcd,
++ dispc_pclk_rate());
++
++ enable_clocks(0);
++}
++
++void dispc_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DISPC_REVISION);
++ DUMPREG(DISPC_SYSCONFIG);
++ DUMPREG(DISPC_SYSSTATUS);
++ DUMPREG(DISPC_IRQSTATUS);
++ DUMPREG(DISPC_IRQENABLE);
++ DUMPREG(DISPC_CONTROL);
++ DUMPREG(DISPC_CONFIG);
++ DUMPREG(DISPC_CAPABLE);
++ DUMPREG(DISPC_DEFAULT_COLOR0);
++ DUMPREG(DISPC_DEFAULT_COLOR1);
++ DUMPREG(DISPC_TRANS_COLOR0);
++ DUMPREG(DISPC_TRANS_COLOR1);
++ DUMPREG(DISPC_LINE_STATUS);
++ DUMPREG(DISPC_LINE_NUMBER);
++ DUMPREG(DISPC_TIMING_H);
++ DUMPREG(DISPC_TIMING_V);
++ DUMPREG(DISPC_POL_FREQ);
++ DUMPREG(DISPC_DIVISOR);
++ DUMPREG(DISPC_GLOBAL_ALPHA);
++ DUMPREG(DISPC_SIZE_DIG);
++ DUMPREG(DISPC_SIZE_LCD);
++
++ DUMPREG(DISPC_GFX_BA0);
++ DUMPREG(DISPC_GFX_BA1);
++ DUMPREG(DISPC_GFX_POSITION);
++ DUMPREG(DISPC_GFX_SIZE);
++ DUMPREG(DISPC_GFX_ATTRIBUTES);
++ DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
++ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
++ DUMPREG(DISPC_GFX_ROW_INC);
++ DUMPREG(DISPC_GFX_PIXEL_INC);
++ DUMPREG(DISPC_GFX_WINDOW_SKIP);
++ DUMPREG(DISPC_GFX_TABLE_BA);
++
++ DUMPREG(DISPC_DATA_CYCLE1);
++ DUMPREG(DISPC_DATA_CYCLE2);
++ DUMPREG(DISPC_DATA_CYCLE3);
++
++ DUMPREG(DISPC_CPR_COEF_R);
++ DUMPREG(DISPC_CPR_COEF_G);
++ DUMPREG(DISPC_CPR_COEF_B);
++
++ DUMPREG(DISPC_GFX_PRELOAD);
++
++ DUMPREG(DISPC_VID_BA0(0));
++ DUMPREG(DISPC_VID_BA1(0));
++ DUMPREG(DISPC_VID_POSITION(0));
++ DUMPREG(DISPC_VID_SIZE(0));
++ DUMPREG(DISPC_VID_ATTRIBUTES(0));
++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
++ DUMPREG(DISPC_VID_ROW_INC(0));
++ DUMPREG(DISPC_VID_PIXEL_INC(0));
++ DUMPREG(DISPC_VID_FIR(0));
++ DUMPREG(DISPC_VID_PICTURE_SIZE(0));
++ DUMPREG(DISPC_VID_ACCU0(0));
++ DUMPREG(DISPC_VID_ACCU1(0));
++
++ DUMPREG(DISPC_VID_BA0(1));
++ DUMPREG(DISPC_VID_BA1(1));
++ DUMPREG(DISPC_VID_POSITION(1));
++ DUMPREG(DISPC_VID_SIZE(1));
++ DUMPREG(DISPC_VID_ATTRIBUTES(1));
++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
++ DUMPREG(DISPC_VID_ROW_INC(1));
++ DUMPREG(DISPC_VID_PIXEL_INC(1));
++ DUMPREG(DISPC_VID_FIR(1));
++ DUMPREG(DISPC_VID_PICTURE_SIZE(1));
++ DUMPREG(DISPC_VID_ACCU0(1));
++ DUMPREG(DISPC_VID_ACCU1(1));
++
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 0));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 1));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 2));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 3));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
++
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 0));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 1));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 2));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 3));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
++
++ DUMPREG(DISPC_VID_PRELOAD(0));
++ DUMPREG(DISPC_VID_PRELOAD(1));
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
++ bool ihs, bool ivs, u8 acbi, u8 acb)
++{
++ u32 l = 0;
++
++ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
++ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
++
++ l |= FLD_VAL(onoff, 17, 17);
++ l |= FLD_VAL(rf, 16, 16);
++ l |= FLD_VAL(ieo, 15, 15);
++ l |= FLD_VAL(ipc, 14, 14);
++ l |= FLD_VAL(ihs, 13, 13);
++ l |= FLD_VAL(ivs, 12, 12);
++ l |= FLD_VAL(acbi, 11, 8);
++ l |= FLD_VAL(acb, 7, 0);
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_POL_FREQ, l);
++ enable_clocks(0);
++}
++
++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
++{
++ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
++ (config & OMAP_DSS_LCD_RF) != 0,
++ (config & OMAP_DSS_LCD_IEO) != 0,
++ (config & OMAP_DSS_LCD_IPC) != 0,
++ (config & OMAP_DSS_LCD_IHS) != 0,
++ (config & OMAP_DSS_LCD_IVS) != 0,
++ acbi, acb);
++}
++
++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
++ u16 *lck_div, u16 *pck_div)
++{
++ u16 pcd_min = is_tft ? 2 : 3;
++ unsigned long best_pck;
++ u16 best_ld, cur_ld;
++ u16 best_pd, cur_pd;
++
++ best_pck = 0;
++ best_ld = 0;
++ best_pd = 0;
++
++ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
++ unsigned long lck = fck / cur_ld;
++
++ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
++ unsigned long pck = lck / cur_pd;
++ long old_delta = abs(best_pck - req_pck);
++ long new_delta = abs(pck - req_pck);
++
++ if (best_pck == 0 || new_delta < old_delta) {
++ best_pck = pck;
++ best_ld = cur_ld;
++ best_pd = cur_pd;
++
++ if (pck == req_pck)
++ goto found;
++ }
++
++ if (pck < req_pck)
++ break;
++ }
++
++ if (lck / pcd_min < req_pck)
++ break;
++ }
++
++found:
++ *lck_div = best_ld;
++ *pck_div = best_pd;
++}
++
++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
++ struct dispc_clock_info *cinfo)
++{
++ unsigned long prate;
++ struct dispc_clock_info cur, best;
++ int match = 0;
++ int min_fck_per_pck;
++ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
++
++ if (cpu_is_omap34xx())
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ else
++ prate = 0;
++
++ if (req_pck == dispc.cache_req_pck &&
++ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
++ dispc.cache_cinfo.fck == fck_rate)) {
++ DSSDBG("dispc clock info found from cache.\n");
++ *cinfo = dispc.cache_cinfo;
++ return 0;
++ }
++
++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
++
++ if (min_fck_per_pck &&
++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
++ DSSERR("Requested pixel clock not possible with the current "
++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
++ "the constraint off.\n");
++ min_fck_per_pck = 0;
++ }
++
++retry:
++ memset(&cur, 0, sizeof(cur));
++ memset(&best, 0, sizeof(best));
++
++ if (cpu_is_omap24xx()) {
++ /* XXX can we change the clock on omap2? */
++ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
++ cur.fck_div = 1;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck, cur.fck,
++ &cur.lck_div, &cur.pck_div);
++
++ cur.lck = cur.fck / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ best = cur;
++
++ goto found;
++ } else if (cpu_is_omap34xx()) {
++ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
++ cur.fck = prate / cur.fck_div * 2;
++
++ if (cur.fck > DISPC_MAX_FCK)
++ continue;
++
++ if (min_fck_per_pck &&
++ cur.fck < req_pck * min_fck_per_pck)
++ continue;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck, cur.fck,
++ &cur.lck_div, &cur.pck_div);
++
++ cur.lck = cur.fck / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
++ best = cur;
++
++ if (cur.pck == req_pck)
++ goto found;
++ }
++ }
++ } else {
++ BUG();
++ }
++
++found:
++ if (!match) {
++ if (min_fck_per_pck) {
++ DSSERR("Could not find suitable clock settings.\n"
++ "Turning FCK/PCK constraint off and"
++ "trying again.\n");
++ min_fck_per_pck = 0;
++ goto retry;
++ }
++
++ DSSERR("Could not find suitable clock settings.\n");
++
++ return -EINVAL;
++ }
++
++ if (cinfo)
++ *cinfo = best;
++
++ dispc.cache_req_pck = req_pck;
++ dispc.cache_prate = prate;
++ dispc.cache_cinfo = best;
++
++ return 0;
++}
++
++int dispc_set_clock_div(struct dispc_clock_info *cinfo)
++{
++ unsigned long prate;
++ int r;
++
++ if (cpu_is_omap34xx()) {
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ DSSDBG("dpll4_m4 = %ld\n", prate);
++ }
++
++ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
++ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
++ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
++
++ if (cpu_is_omap34xx()) {
++ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
++ if (r)
++ return r;
++ }
++
++ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
++
++ return 0;
++}
++
++int dispc_get_clock_div(struct dispc_clock_info *cinfo)
++{
++ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
++
++ if (cpu_is_omap34xx()) {
++ unsigned long prate;
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ cinfo->fck_div = prate / (cinfo->fck / 2);
++ } else {
++ cinfo->fck_div = 0;
++ }
++
++ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
++ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
++
++ cinfo->lck = cinfo->fck / cinfo->lck_div;
++ cinfo->pck = cinfo->lck / cinfo->pck_div;
++
++ return 0;
++}
++
++/* dispc.irq_lock has to be locked by the caller */
++static void _omap_dispc_set_irqs(void)
++{
++ u32 mask;
++ u32 old_mask;
++ int i;
++ struct omap_dispc_isr_data *isr_data;
++
++ mask = dispc.irq_error_mask;
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++
++ if (isr_data->isr == NULL)
++ continue;
++
++ mask |= isr_data->mask;
++ }
++
++ enable_clocks(1);
++
++ old_mask = dispc_read_reg(DISPC_IRQENABLE);
++ /* clear the irqstatus for newly enabled irqs */
++ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
++
++ dispc_write_reg(DISPC_IRQENABLE, mask);
++
++ enable_clocks(0);
++}
++
++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
++{
++ int i;
++ int ret;
++ unsigned long flags;
++ struct omap_dispc_isr_data *isr_data;
++
++ if (isr == NULL)
++ return -EINVAL;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ /* check for duplicate entry */
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++ if (isr_data->isr == isr && isr_data->arg == arg &&
++ isr_data->mask == mask) {
++ ret = -EINVAL;
++ goto err;
++ }
++ }
++
++ isr_data = NULL;
++ ret = -EBUSY;
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++
++ if (isr_data->isr != NULL)
++ continue;
++
++ isr_data->isr = isr;
++ isr_data->arg = arg;
++ isr_data->mask = mask;
++ ret = 0;
++
++ break;
++ }
++
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ return 0;
++err:
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ return ret;
++}
++EXPORT_SYMBOL(omap_dispc_register_isr);
++
++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
++{
++ int i;
++ unsigned long flags;
++ int ret = -EINVAL;
++ struct omap_dispc_isr_data *isr_data;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++ if (isr_data->isr != isr || isr_data->arg != arg ||
++ isr_data->mask != mask)
++ continue;
++
++ /* found the correct isr */
++
++ isr_data->isr = NULL;
++ isr_data->arg = NULL;
++ isr_data->mask = 0;
++
++ ret = 0;
++ break;
++ }
++
++ if (ret == 0)
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ return ret;
++}
++EXPORT_SYMBOL(omap_dispc_unregister_isr);
++
++#ifdef DEBUG
++static void print_irq_status(u32 status)
++{
++ if ((status & dispc.irq_error_mask) == 0)
++ return;
++
++ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DISPC_IRQ_##x) \
++ printk(#x " ");
++ PIS(GFX_FIFO_UNDERFLOW);
++ PIS(OCP_ERR);
++ PIS(VID1_FIFO_UNDERFLOW);
++ PIS(VID2_FIFO_UNDERFLOW);
++ PIS(SYNC_LOST);
++ PIS(SYNC_LOST_DIGIT);
++#undef PIS
++
++ printk("\n");
++}
++#endif
++
++/* Called from dss.c. Note that we don't touch clocks here,
++ * but we presume they are on because we got an IRQ. However,
++ * an irq handler may turn the clocks off, so we may not have
++ * clock later in the function. */
++void dispc_irq_handler(void)
++{
++ int i;
++ u32 irqstatus;
++ u32 handledirqs = 0;
++ u32 unhandled_errors;
++ struct omap_dispc_isr_data *isr_data;
++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
++
++ spin_lock(&dispc.irq_lock);
++
++ irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++
++#ifdef DEBUG
++ if (dss_debug)
++ print_irq_status(irqstatus);
++#endif
++ /* Ack the interrupt. Do it here before clocks are possibly turned
++ * off */
++ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
++
++ /* make a copy and unlock, so that isrs can unregister
++ * themselves */
++ memcpy(registered_isr, dispc.registered_isr,
++ sizeof(registered_isr));
++
++ spin_unlock(&dispc.irq_lock);
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &registered_isr[i];
++
++ if (!isr_data->isr)
++ continue;
++
++ if (isr_data->mask & irqstatus) {
++ isr_data->isr(isr_data->arg, irqstatus);
++ handledirqs |= isr_data->mask;
++ }
++ }
++
++ spin_lock(&dispc.irq_lock);
++
++ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
++
++ if (unhandled_errors) {
++ dispc.error_irqs |= unhandled_errors;
++
++ dispc.irq_error_mask &= ~unhandled_errors;
++ _omap_dispc_set_irqs();
++
++ schedule_work(&dispc.error_work);
++ }
++
++ spin_unlock(&dispc.irq_lock);
++}
++
++static void dispc_error_worker(struct work_struct *work)
++{
++ int i;
++ u32 errors;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++ errors = dispc.error_irqs;
++ dispc.error_irqs = 0;
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
++ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 0) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
++ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 1) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
++ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 2) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_SYNC_LOST) {
++ struct omap_overlay_manager *manager = NULL;
++ bool enable = false;
++
++ DSSERR("SYNC_LOST, disabling LCD\n");
++
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
++ manager = mgr;
++ enable = mgr->device->state ==
++ OMAP_DSS_DISPLAY_ACTIVE;
++ mgr->device->disable(mgr->device);
++ break;
++ }
++ }
++
++ if (manager) {
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id != 0 && ovl->manager == manager)
++ dispc_enable_plane(ovl->id, 0);
++ }
++
++ dispc_go(manager->id);
++ mdelay(50);
++ if (enable)
++ manager->device->enable(manager->device);
++ }
++ }
++
++ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
++ struct omap_overlay_manager *manager = NULL;
++ bool enable = false;
++
++ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
++
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
++ manager = mgr;
++ enable = mgr->device->state ==
++ OMAP_DSS_DISPLAY_ACTIVE;
++ mgr->device->disable(mgr->device);
++ break;
++ }
++ }
++
++ if (manager) {
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id != 0 && ovl->manager == manager)
++ dispc_enable_plane(ovl->id, 0);
++ }
++
++ dispc_go(manager->id);
++ mdelay(50);
++ if (enable)
++ manager->device->enable(manager->device);
++ }
++ }
++
++ if (errors & DISPC_IRQ_OCP_ERR) {
++ DSSERR("OCP_ERR\n");
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
++ mgr->device->disable(mgr->device);
++ }
++ }
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++ dispc.irq_error_mask |= errors;
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++}
++
++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
++{
++ void dispc_irq_wait_handler(void *data, u32 mask)
++ {
++ complete((struct completion *)data);
++ }
++
++ int r;
++ DECLARE_COMPLETION_ONSTACK(completion);
++
++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
++ irqmask);
++
++ if (r)
++ return r;
++
++ timeout = wait_for_completion_timeout(&completion, timeout);
++
++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
++
++ if (timeout == 0)
++ return -ETIMEDOUT;
++
++ if (timeout == -ERESTARTSYS)
++ return -ERESTARTSYS;
++
++ return 0;
++}
++
++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
++ unsigned long timeout)
++{
++ void dispc_irq_wait_handler(void *data, u32 mask)
++ {
++ complete((struct completion *)data);
++ }
++
++ int r;
++ DECLARE_COMPLETION_ONSTACK(completion);
++
++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
++ irqmask);
++
++ if (r)
++ return r;
++
++ timeout = wait_for_completion_interruptible_timeout(&completion,
++ timeout);
++
++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
++
++ if (timeout == 0)
++ return -ETIMEDOUT;
++
++ if (timeout == -ERESTARTSYS)
++ return -ERESTARTSYS;
++
++ return 0;
++}
++
++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
++void dispc_fake_vsync_irq(void)
++{
++ u32 irqstatus = DISPC_IRQ_VSYNC;
++ int i;
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ struct omap_dispc_isr_data *isr_data;
++ isr_data = &dispc.registered_isr[i];
++
++ if (!isr_data->isr)
++ continue;
++
++ if (isr_data->mask & irqstatus)
++ isr_data->isr(isr_data->arg, irqstatus);
++ }
++}
++#endif
++
++static void _omap_dispc_initialize_irq(void)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
++
++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
++
++ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
++ * so clear it */
++ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
++
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++}
++
++void dispc_enable_sidle(void)
++{
++ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
++}
++
++void dispc_disable_sidle(void)
++{
++ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
++}
++
++static void _omap_dispc_initial_config(void)
++{
++ u32 l;
++
++ l = dispc_read_reg(DISPC_SYSCONFIG);
++ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
++ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
++ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
++ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
++ dispc_write_reg(DISPC_SYSCONFIG, l);
++
++ /* FUNCGATED */
++ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
++
++ /* L3 firewall setting: enable access to OCM RAM */
++ if (cpu_is_omap24xx())
++ __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0));
++
++ _dispc_setup_color_conv_coef();
++
++ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
++
++ dispc_read_plane_fifo_sizes();
++}
++
++int dispc_init(void)
++{
++ u32 rev;
++
++ spin_lock_init(&dispc.irq_lock);
++
++ INIT_WORK(&dispc.error_work, dispc_error_worker);
++
++ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
++ if (!dispc.base) {
++ DSSERR("can't ioremap DISPC\n");
++ return -ENOMEM;
++ }
++
++ if (cpu_is_omap34xx()) {
++ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
++ if (IS_ERR(dispc.dpll4_m4_ck)) {
++ DSSERR("Failed to get dpll4_m4_ck\n");
++ return -ENODEV;
++ }
++ }
++
++ enable_clocks(1);
++
++ _omap_dispc_initial_config();
++
++ _omap_dispc_initialize_irq();
++
++ dispc_save_context();
++
++ rev = dispc_read_reg(DISPC_REVISION);
++ printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ enable_clocks(0);
++
++ return 0;
++}
++
++void dispc_exit(void)
++{
++ if (cpu_is_omap34xx())
++ clk_put(dispc.dpll4_m4_ck);
++ iounmap(dispc.base);
++}
++
++int dispc_enable_plane(enum omap_plane plane, bool enable)
++{
++ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
++
++ enable_clocks(1);
++ _dispc_enable_plane(plane, enable);
++ enable_clocks(0);
++
++ return 0;
++}
++
++int dispc_setup_plane(enum omap_plane plane,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
++ u8 rotation, bool mirror, u8 global_alpha)
++{
++ int r = 0;
++
++ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
++ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
++ plane, paddr, screen_width, pos_x, pos_y,
++ width, height,
++ out_width, out_height,
++ ilace, color_mode,
++ rotation, mirror);
++
++ enable_clocks(1);
++
++ r = _dispc_setup_plane(plane,
++ paddr, screen_width,
++ pos_x, pos_y,
++ width, height,
++ out_width, out_height,
++ color_mode, ilace,
++ rotation_type,
++ rotation, mirror,
++ global_alpha);
++
++ enable_clocks(0);
++
++ return r;
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch
new file mode 100644
index 0000000000..db6d780552
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch
@@ -0,0 +1,410 @@
+From 544b715d21a38a64bcafe850e31ae0dfd5227e9f Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 13:15:50 +0300
+Subject: [PATCH 10/18] OMAP: DSS2: DPI driver
+
+This implements MIPI DPI interface.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dpi.c | 388 +++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 388 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/dpi.c
+
+diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
+new file mode 100644
+index 0000000..b6543c8
+--- /dev/null
++++ b/drivers/video/omap2/dss/dpi.c
+@@ -0,0 +1,388 @@
++/*
++ * linux/drivers/video/omap2/dss/dpi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DPI"
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include <mach/cpu.h>
++
++#include "dss.h"
++
++static struct {
++ int update_enabled;
++} dpi;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
++ unsigned long *fck, int *lck_div, int *pck_div)
++{
++ struct dsi_clock_info cinfo;
++ int r;
++
++ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
++ if (r)
++ return r;
++
++ r = dsi_pll_program(&cinfo);
++ if (r)
++ return r;
++
++ dss_select_clk_source(0, 1);
++
++ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
++
++ *fck = cinfo.dsi1_pll_fclk;
++ *lck_div = cinfo.lck_div;
++ *pck_div = cinfo.pck_div;
++
++ return 0;
++}
++#else
++static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
++ unsigned long *fck, int *lck_div, int *pck_div)
++{
++ struct dispc_clock_info cinfo;
++ int r;
++
++ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
++ if (r)
++ return r;
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r)
++ return r;
++
++ *fck = cinfo.fck;
++ *lck_div = cinfo.lck_div;
++ *pck_div = cinfo.pck_div;
++
++ return 0;
++}
++#endif
++
++static int dpi_set_mode(struct omap_dss_device *dssdev)
++{
++ struct omap_video_timings *t = &dssdev->panel.timings;
++ int lck_div, pck_div;
++ unsigned long fck;
++ unsigned long pck;
++ bool is_tft;
++ int r = 0;
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
++ dssdev->panel.acb);
++
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
++ &fck, &lck_div, &pck_div);
++#else
++ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
++ &fck, &lck_div, &pck_div);
++#endif
++ if (r)
++ goto err0;
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ if (pck != t->pixel_clock) {
++ DSSWARN("Could not find exact pixel clock. "
++ "Requested %d kHz, got %lu kHz\n",
++ t->pixel_clock, pck);
++
++ t->pixel_clock = pck;
++ }
++
++ dispc_set_lcd_timings(t);
++
++err0:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return r;
++}
++
++static int dpi_basic_init(struct omap_dss_device *dssdev)
++{
++ bool is_tft;
++
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
++ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
++ OMAP_DSS_LCD_DISPLAY_STN);
++ dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
++
++ return 0;
++}
++
++static int dpi_display_enable(struct omap_dss_device *dssdev)
++{
++ int r;
++
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("display already enabled\n");
++ r = -EINVAL;
++ goto err1;
++ }
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ r = dpi_basic_init(dssdev);
++ if (r)
++ goto err2;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dss_clk_enable(DSS_CLK_FCK2);
++ r = dsi_pll_init(0, 1);
++ if (r)
++ goto err3;
++#endif
++ r = dpi_set_mode(dssdev);
++ if (r)
++ goto err4;
++
++ mdelay(2);
++
++ dispc_enable_lcd_out(1);
++
++ r = dssdev->driver->enable(dssdev);
++ if (r)
++ goto err5;
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++
++err5:
++ dispc_enable_lcd_out(0);
++err4:
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dsi_pll_uninit();
++err3:
++ dss_clk_disable(DSS_CLK_FCK2);
++#endif
++err2:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
++ return r;
++}
++
++static int dpi_display_resume(struct omap_dss_device *dssdev);
++
++static void dpi_display_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
++ return;
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ dpi_display_resume(dssdev);
++
++ dssdev->driver->disable(dssdev);
++
++ dispc_enable_lcd_out(0);
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dss_select_clk_source(0, 0);
++ dsi_pll_uninit();
++ dss_clk_disable(DSS_CLK_FCK2);
++#endif
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ omap_dss_stop_device(dssdev);
++}
++
++static int dpi_display_suspend(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EINVAL;
++
++ DSSDBG("dpi_display_suspend\n");
++
++ if (dssdev->driver->suspend)
++ dssdev->driver->suspend(dssdev);
++
++ dispc_enable_lcd_out(0);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ return 0;
++}
++
++static int dpi_display_resume(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ return -EINVAL;
++
++ DSSDBG("dpi_display_resume\n");
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dispc_enable_lcd_out(1);
++
++ if (dssdev->driver->resume)
++ dssdev->driver->resume(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++}
++
++static void dpi_set_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("dpi_set_timings\n");
++ dssdev->panel.timings = *timings;
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ dpi_set_mode(dssdev);
++ dispc_go(OMAP_DSS_CHANNEL_LCD);
++ }
++}
++
++static int dpi_check_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ bool is_tft;
++ int r;
++ int lck_div, pck_div;
++ unsigned long fck;
++ unsigned long pck;
++
++ if (!dispc_lcd_timings_ok(timings))
++ return -EINVAL;
++
++ if (timings->pixel_clock == 0)
++ return -EINVAL;
++
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ {
++ struct dsi_clock_info cinfo;
++ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
++ &cinfo);
++
++ if (r)
++ return r;
++
++ fck = cinfo.dsi1_pll_fclk;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++ }
++#else
++ {
++ struct dispc_clock_info cinfo;
++ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
++ &cinfo);
++
++ if (r)
++ return r;
++
++ fck = cinfo.fck;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++ }
++#endif
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ timings->pixel_clock = pck;
++
++ return 0;
++}
++
++static void dpi_get_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ *timings = dssdev->panel.timings;
++}
++
++static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
++ enum omap_dss_update_mode mode)
++{
++ if (mode == OMAP_DSS_UPDATE_MANUAL)
++ return -EINVAL;
++
++ if (mode == OMAP_DSS_UPDATE_DISABLED) {
++ dispc_enable_lcd_out(0);
++ dpi.update_enabled = 0;
++ } else {
++ dispc_enable_lcd_out(1);
++ dpi.update_enabled = 1;
++ }
++
++ return 0;
++}
++
++static enum omap_dss_update_mode dpi_display_get_update_mode(
++ struct omap_dss_device *dssdev)
++{
++ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
++ OMAP_DSS_UPDATE_DISABLED;
++}
++
++int dpi_init_display(struct omap_dss_device *dssdev)
++{
++ DSSDBG("init_display\n");
++
++ dssdev->enable = dpi_display_enable;
++ dssdev->disable = dpi_display_disable;
++ dssdev->suspend = dpi_display_suspend;
++ dssdev->resume = dpi_display_resume;
++ dssdev->set_timings = dpi_set_timings;
++ dssdev->check_timings = dpi_check_timings;
++ dssdev->get_timings = dpi_get_timings;
++ dssdev->set_update_mode = dpi_display_set_update_mode;
++ dssdev->get_update_mode = dpi_display_get_update_mode;
++
++ return 0;
++}
++
++int dpi_init(void)
++{
++ return 0;
++}
++
++void dpi_exit(void)
++{
++}
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch
new file mode 100644
index 0000000000..f3cb9ab56f
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch
@@ -0,0 +1,821 @@
+From e954e1ef739c39ffe671981ee8adbc7e9bb0249e Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 5 Aug 2009 16:18:06 +0300
+Subject: [PATCH 11/18] OMAP: DSS2: Video encoder driver
+
+VENC (video encoder) driver implements OMAP's analog S-Video/Composite
+TV-out.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ drivers/video/omap2/dss/venc.c | 797 ++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 797 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/venc.c
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+new file mode 100644
+index 0000000..cf7827e
+--- /dev/null
++++ b/drivers/video/omap2/dss/venc.c
+@@ -0,0 +1,797 @@
++/*
++ * linux/drivers/video/omap2/dss/venc.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * VENC settings from TI's DSS driver
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "VENC"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/seq_file.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++
++#include <mach/display.h>
++#include <mach/cpu.h>
++
++#include "dss.h"
++
++#define VENC_BASE 0x48050C00
++
++/* Venc registers */
++#define VENC_REV_ID 0x00
++#define VENC_STATUS 0x04
++#define VENC_F_CONTROL 0x08
++#define VENC_VIDOUT_CTRL 0x10
++#define VENC_SYNC_CTRL 0x14
++#define VENC_LLEN 0x1C
++#define VENC_FLENS 0x20
++#define VENC_HFLTR_CTRL 0x24
++#define VENC_CC_CARR_WSS_CARR 0x28
++#define VENC_C_PHASE 0x2C
++#define VENC_GAIN_U 0x30
++#define VENC_GAIN_V 0x34
++#define VENC_GAIN_Y 0x38
++#define VENC_BLACK_LEVEL 0x3C
++#define VENC_BLANK_LEVEL 0x40
++#define VENC_X_COLOR 0x44
++#define VENC_M_CONTROL 0x48
++#define VENC_BSTAMP_WSS_DATA 0x4C
++#define VENC_S_CARR 0x50
++#define VENC_LINE21 0x54
++#define VENC_LN_SEL 0x58
++#define VENC_L21__WC_CTL 0x5C
++#define VENC_HTRIGGER_VTRIGGER 0x60
++#define VENC_SAVID__EAVID 0x64
++#define VENC_FLEN__FAL 0x68
++#define VENC_LAL__PHASE_RESET 0x6C
++#define VENC_HS_INT_START_STOP_X 0x70
++#define VENC_HS_EXT_START_STOP_X 0x74
++#define VENC_VS_INT_START_X 0x78
++#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
++#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
++#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
++#define VENC_VS_EXT_STOP_Y 0x88
++#define VENC_AVID_START_STOP_X 0x90
++#define VENC_AVID_START_STOP_Y 0x94
++#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
++#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
++#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
++#define VENC_TVDETGP_INT_START_STOP_X 0xB0
++#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
++#define VENC_GEN_CTRL 0xB8
++#define VENC_OUTPUT_CONTROL 0xC4
++#define VENC_OUTPUT_TEST 0xC8
++#define VENC_DAC_B__DAC_C 0xC8
++
++struct venc_config {
++ u32 f_control;
++ u32 vidout_ctrl;
++ u32 sync_ctrl;
++ u32 llen;
++ u32 flens;
++ u32 hfltr_ctrl;
++ u32 cc_carr_wss_carr;
++ u32 c_phase;
++ u32 gain_u;
++ u32 gain_v;
++ u32 gain_y;
++ u32 black_level;
++ u32 blank_level;
++ u32 x_color;
++ u32 m_control;
++ u32 bstamp_wss_data;
++ u32 s_carr;
++ u32 line21;
++ u32 ln_sel;
++ u32 l21__wc_ctl;
++ u32 htrigger_vtrigger;
++ u32 savid__eavid;
++ u32 flen__fal;
++ u32 lal__phase_reset;
++ u32 hs_int_start_stop_x;
++ u32 hs_ext_start_stop_x;
++ u32 vs_int_start_x;
++ u32 vs_int_stop_x__vs_int_start_y;
++ u32 vs_int_stop_y__vs_ext_start_x;
++ u32 vs_ext_stop_x__vs_ext_start_y;
++ u32 vs_ext_stop_y;
++ u32 avid_start_stop_x;
++ u32 avid_start_stop_y;
++ u32 fid_int_start_x__fid_int_start_y;
++ u32 fid_int_offset_y__fid_ext_start_x;
++ u32 fid_ext_start_y__fid_ext_offset_y;
++ u32 tvdetgp_int_start_stop_x;
++ u32 tvdetgp_int_start_stop_y;
++ u32 gen_ctrl;
++};
++
++/* from TRM */
++static const struct venc_config venc_config_pal_trm = {
++ .f_control = 0,
++ .vidout_ctrl = 1,
++ .sync_ctrl = 0x40,
++ .llen = 0x35F, /* 863 */
++ .flens = 0x270, /* 624 */
++ .hfltr_ctrl = 0,
++ .cc_carr_wss_carr = 0x2F7225ED,
++ .c_phase = 0,
++ .gain_u = 0x111,
++ .gain_v = 0x181,
++ .gain_y = 0x140,
++ .black_level = 0x3B,
++ .blank_level = 0x3B,
++ .x_color = 0x7,
++ .m_control = 0x2,
++ .bstamp_wss_data = 0x3F,
++ .s_carr = 0x2A098ACB,
++ .line21 = 0,
++ .ln_sel = 0x01290015,
++ .l21__wc_ctl = 0x0000F603,
++ .htrigger_vtrigger = 0,
++
++ .savid__eavid = 0x06A70108,
++ .flen__fal = 0x00180270,
++ .lal__phase_reset = 0x00040135,
++ .hs_int_start_stop_x = 0x00880358,
++ .hs_ext_start_stop_x = 0x000F035F,
++ .vs_int_start_x = 0x01A70000,
++ .vs_int_stop_x__vs_int_start_y = 0x000001A7,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
++ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
++ .vs_ext_stop_y = 0x00000025,
++ .avid_start_stop_x = 0x03530083,
++ .avid_start_stop_y = 0x026C002E,
++ .fid_int_start_x__fid_int_start_y = 0x0001008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
++
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00FF0000,
++};
++
++/* from TRM */
++static const struct venc_config venc_config_ntsc_trm = {
++ .f_control = 0,
++ .vidout_ctrl = 1,
++ .sync_ctrl = 0x8040,
++ .llen = 0x359,
++ .flens = 0x20C,
++ .hfltr_ctrl = 0,
++ .cc_carr_wss_carr = 0x043F2631,
++ .c_phase = 0,
++ .gain_u = 0x102,
++ .gain_v = 0x16C,
++ .gain_y = 0x12F,
++ .black_level = 0x43,
++ .blank_level = 0x38,
++ .x_color = 0x7,
++ .m_control = 0x1,
++ .bstamp_wss_data = 0x38,
++ .s_carr = 0x21F07C1F,
++ .line21 = 0,
++ .ln_sel = 0x01310011,
++ .l21__wc_ctl = 0x0000F003,
++ .htrigger_vtrigger = 0,
++
++ .savid__eavid = 0x069300F4,
++ .flen__fal = 0x0016020C,
++ .lal__phase_reset = 0x00060107,
++ .hs_int_start_stop_x = 0x008E0350,
++ .hs_ext_start_stop_x = 0x000F0359,
++ .vs_int_start_x = 0x01A00000,
++ .vs_int_stop_x__vs_int_start_y = 0x020701A0,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
++ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
++ .vs_ext_stop_y = 0x00000006,
++ .avid_start_stop_x = 0x03480078,
++ .avid_start_stop_y = 0x02060024,
++ .fid_int_start_x__fid_int_start_y = 0x0001008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
++
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00F90000,
++};
++
++static const struct venc_config venc_config_pal_bdghi = {
++ .f_control = 0,
++ .vidout_ctrl = 0,
++ .sync_ctrl = 0,
++ .hfltr_ctrl = 0,
++ .x_color = 0,
++ .line21 = 0,
++ .ln_sel = 21,
++ .htrigger_vtrigger = 0,
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00FB0000,
++
++ .llen = 864-1,
++ .flens = 625-1,
++ .cc_carr_wss_carr = 0x2F7625ED,
++ .c_phase = 0xDF,
++ .gain_u = 0x111,
++ .gain_v = 0x181,
++ .gain_y = 0x140,
++ .black_level = 0x3e,
++ .blank_level = 0x3e,
++ .m_control = 0<<2 | 1<<1,
++ .bstamp_wss_data = 0x42,
++ .s_carr = 0x2a098acb,
++ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
++ .savid__eavid = 0x06A70108,
++ .flen__fal = 23<<16 | 624<<0,
++ .lal__phase_reset = 2<<17 | 310<<0,
++ .hs_int_start_stop_x = 0x00920358,
++ .hs_ext_start_stop_x = 0x000F035F,
++ .vs_int_start_x = 0x1a7<<16,
++ .vs_int_stop_x__vs_int_start_y = 0x000601A7,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
++ .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
++ .vs_ext_stop_y = 0x05,
++ .avid_start_stop_x = 0x03530082,
++ .avid_start_stop_y = 0x0270002E,
++ .fid_int_start_x__fid_int_start_y = 0x0005008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
++};
++
++const struct omap_video_timings omap_dss_pal_timings = {
++ .x_res = 720,
++ .y_res = 574,
++ .pixel_clock = 13500,
++ .hsw = 64,
++ .hfp = 12,
++ .hbp = 68,
++ .vsw = 5,
++ .vfp = 5,
++ .vbp = 41,
++};
++EXPORT_SYMBOL(omap_dss_pal_timings);
++
++const struct omap_video_timings omap_dss_ntsc_timings = {
++ .x_res = 720,
++ .y_res = 482,
++ .pixel_clock = 13500,
++ .hsw = 64,
++ .hfp = 16,
++ .hbp = 58,
++ .vsw = 6,
++ .vfp = 6,
++ .vbp = 31,
++};
++EXPORT_SYMBOL(omap_dss_ntsc_timings);
++
++static struct {
++ void __iomem *base;
++ struct mutex venc_lock;
++ u32 wss_data;
++ struct regulator *vdda_dac_reg;
++} venc;
++
++static inline void venc_write_reg(int idx, u32 val)
++{
++ __raw_writel(val, venc.base + idx);
++}
++
++static inline u32 venc_read_reg(int idx)
++{
++ u32 l = __raw_readl(venc.base + idx);
++ return l;
++}
++
++static void venc_write_config(const struct venc_config *config)
++{
++ DSSDBG("write venc conf\n");
++
++ venc_write_reg(VENC_LLEN, config->llen);
++ venc_write_reg(VENC_FLENS, config->flens);
++ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
++ venc_write_reg(VENC_C_PHASE, config->c_phase);
++ venc_write_reg(VENC_GAIN_U, config->gain_u);
++ venc_write_reg(VENC_GAIN_V, config->gain_v);
++ venc_write_reg(VENC_GAIN_Y, config->gain_y);
++ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
++ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
++ venc_write_reg(VENC_M_CONTROL, config->m_control);
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
++ venc.wss_data);
++ venc_write_reg(VENC_S_CARR, config->s_carr);
++ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
++ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
++ venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
++ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
++ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
++ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
++ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
++ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
++ config->vs_int_stop_x__vs_int_start_y);
++ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
++ config->vs_int_stop_y__vs_ext_start_x);
++ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
++ config->vs_ext_stop_x__vs_ext_start_y);
++ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
++ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
++ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
++ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
++ config->fid_int_start_x__fid_int_start_y);
++ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
++ config->fid_int_offset_y__fid_ext_start_x);
++ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
++ config->fid_ext_start_y__fid_ext_offset_y);
++
++ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
++ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
++ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
++ venc_write_reg(VENC_X_COLOR, config->x_color);
++ venc_write_reg(VENC_LINE21, config->line21);
++ venc_write_reg(VENC_LN_SEL, config->ln_sel);
++ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
++ config->tvdetgp_int_start_stop_x);
++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
++ config->tvdetgp_int_start_stop_y);
++ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
++ venc_write_reg(VENC_F_CONTROL, config->f_control);
++ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
++}
++
++static void venc_reset(void)
++{
++ int t = 1000;
++
++ venc_write_reg(VENC_F_CONTROL, 1<<8);
++ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
++ if (--t == 0) {
++ DSSERR("Failed to reset venc\n");
++ return;
++ }
++ }
++
++ /* the magical sleep that makes things work */
++ msleep(20);
++}
++
++static void venc_enable_clocks(int enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++ DSS_CLK_96M);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++ DSS_CLK_96M);
++}
++
++static const struct venc_config *venc_timings_to_config(
++ struct omap_video_timings *timings)
++{
++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
++ return &venc_config_pal_trm;
++
++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
++ return &venc_config_ntsc_trm;
++
++ BUG();
++}
++
++
++
++
++
++/* driver */
++static int venc_panel_probe(struct omap_dss_device *dssdev)
++{
++ dssdev->panel.timings = omap_dss_pal_timings;
++
++ return 0;
++}
++
++static void venc_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++static int venc_panel_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ return r;
++}
++
++static void venc_panel_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++
++ msleep(100);
++}
++
++static int venc_panel_suspend(struct omap_dss_device *dssdev)
++{
++ venc_panel_disable(dssdev);
++ return 0;
++}
++
++static int venc_panel_resume(struct omap_dss_device *dssdev)
++{
++ return venc_panel_enable(dssdev);
++}
++
++static struct omap_dss_driver venc_driver = {
++ .probe = venc_panel_probe,
++ .remove = venc_panel_remove,
++
++ .enable = venc_panel_enable,
++ .disable = venc_panel_disable,
++ .suspend = venc_panel_suspend,
++ .resume = venc_panel_resume,
++
++ .driver = {
++ .name = "venc",
++ .owner = THIS_MODULE,
++ },
++};
++/* driver end */
++
++
++
++int venc_init(struct platform_device *pdev)
++{
++ u8 rev_id;
++
++ mutex_init(&venc.venc_lock);
++
++ venc.wss_data = 0;
++
++ venc.base = ioremap(VENC_BASE, SZ_1K);
++ if (!venc.base) {
++ DSSERR("can't ioremap VENC\n");
++ return -ENOMEM;
++ }
++
++ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
++ if (IS_ERR(venc.vdda_dac_reg)) {
++ iounmap(venc.base);
++ DSSERR("can't get VDDA_DAC regulator\n");
++ return PTR_ERR(venc.vdda_dac_reg);
++ }
++
++ venc_enable_clocks(1);
++
++ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
++ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
++
++ venc_enable_clocks(0);
++
++ return omap_dss_register_driver(&venc_driver);
++}
++
++void venc_exit(void)
++{
++ omap_dss_unregister_driver(&venc_driver);
++
++ regulator_put(venc.vdda_dac_reg);
++
++ iounmap(venc.base);
++}
++
++static void venc_power_on(struct omap_dss_device *dssdev)
++{
++ u32 l;
++
++ venc_enable_clocks(1);
++
++ venc_reset();
++ venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
++
++ dss_set_venc_output(dssdev->phy.venc.type);
++ dss_set_dac_pwrdn_bgz(1);
++
++ l = 0;
++
++ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
++ l |= 1 << 1;
++ else /* S-Video */
++ l |= (1 << 0) | (1 << 2);
++
++ if (dssdev->phy.venc.invert_polarity == false)
++ l |= 1 << 3;
++
++ venc_write_reg(VENC_OUTPUT_CONTROL, l);
++
++ dispc_set_digit_size(dssdev->panel.timings.x_res,
++ dssdev->panel.timings.y_res/2);
++
++ regulator_enable(venc.vdda_dac_reg);
++
++ if (dssdev->platform_enable)
++ dssdev->platform_enable(dssdev);
++
++ dispc_enable_digit_out(1);
++}
++
++static void venc_power_off(struct omap_dss_device *dssdev)
++{
++ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
++ dss_set_dac_pwrdn_bgz(0);
++
++ dispc_enable_digit_out(0);
++
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ regulator_disable(venc.vdda_dac_reg);
++
++ venc_enable_clocks(0);
++}
++
++static int venc_enable_display(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ DSSDBG("venc_enable_display\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_on(dssdev);
++
++ venc.wss_data = 0;
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static void venc_disable_display(struct omap_dss_device *dssdev)
++{
++ DSSDBG("venc_disable_display\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
++ goto end;
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
++ /* suspended is the same as disabled with venc */
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++ goto end;
++ }
++
++ venc_power_off(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++end:
++ mutex_unlock(&venc.venc_lock);
++}
++
++static int venc_display_suspend(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ DSSDBG("venc_display_suspend\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_off(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static int venc_display_resume(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ DSSDBG("venc_display_resume\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_on(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static void venc_get_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ *timings = dssdev->panel.timings;
++}
++
++static void venc_set_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("venc_set_timings\n");
++
++ /* Reset WSS data when the TV standard changes. */
++ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
++ venc.wss_data = 0;
++
++ dssdev->panel.timings = *timings;
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ /* turn the venc off and on to get new timings to use */
++ venc_disable_display(dssdev);
++ venc_enable_display(dssdev);
++ }
++}
++
++static int venc_check_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("venc_check_timings\n");
++
++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
++ return 0;
++
++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
++ return 0;
++
++ return -EINVAL;
++}
++
++static u32 venc_get_wss(struct omap_dss_device *dssdev)
++{
++ /* Invert due to VENC_L21_WC_CTL:INV=1 */
++ return (venc.wss_data >> 8) ^ 0xfffff;
++}
++
++static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
++{
++ const struct venc_config *config;
++
++ DSSDBG("venc_set_wss\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ config = venc_timings_to_config(&dssdev->panel.timings);
++
++ /* Invert due to VENC_L21_WC_CTL:INV=1 */
++ venc.wss_data = (wss ^ 0xfffff) << 8;
++
++ venc_enable_clocks(1);
++
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
++ venc.wss_data);
++
++ venc_enable_clocks(0);
++
++ mutex_unlock(&venc.venc_lock);
++
++ return 0;
++}
++
++static enum omap_dss_update_mode venc_display_get_update_mode(
++ struct omap_dss_device *dssdev)
++{
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
++ return OMAP_DSS_UPDATE_AUTO;
++ else
++ return OMAP_DSS_UPDATE_DISABLED;
++}
++
++int venc_init_display(struct omap_dss_device *dssdev)
++{
++ DSSDBG("init_display\n");
++
++ dssdev->enable = venc_enable_display;
++ dssdev->disable = venc_disable_display;
++ dssdev->suspend = venc_display_suspend;
++ dssdev->resume = venc_display_resume;
++ dssdev->get_timings = venc_get_timings;
++ dssdev->set_timings = venc_set_timings;
++ dssdev->check_timings = venc_check_timings;
++ dssdev->get_wss = venc_get_wss;
++ dssdev->set_wss = venc_set_wss;
++ dssdev->get_update_mode = venc_display_get_update_mode;
++
++ return 0;
++}
++
++void venc_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
++
++ venc_enable_clocks(1);
++
++ DUMPREG(VENC_F_CONTROL);
++ DUMPREG(VENC_VIDOUT_CTRL);
++ DUMPREG(VENC_SYNC_CTRL);
++ DUMPREG(VENC_LLEN);
++ DUMPREG(VENC_FLENS);
++ DUMPREG(VENC_HFLTR_CTRL);
++ DUMPREG(VENC_CC_CARR_WSS_CARR);
++ DUMPREG(VENC_C_PHASE);
++ DUMPREG(VENC_GAIN_U);
++ DUMPREG(VENC_GAIN_V);
++ DUMPREG(VENC_GAIN_Y);
++ DUMPREG(VENC_BLACK_LEVEL);
++ DUMPREG(VENC_BLANK_LEVEL);
++ DUMPREG(VENC_X_COLOR);
++ DUMPREG(VENC_M_CONTROL);
++ DUMPREG(VENC_BSTAMP_WSS_DATA);
++ DUMPREG(VENC_S_CARR);
++ DUMPREG(VENC_LINE21);
++ DUMPREG(VENC_LN_SEL);
++ DUMPREG(VENC_L21__WC_CTL);
++ DUMPREG(VENC_HTRIGGER_VTRIGGER);
++ DUMPREG(VENC_SAVID__EAVID);
++ DUMPREG(VENC_FLEN__FAL);
++ DUMPREG(VENC_LAL__PHASE_RESET);
++ DUMPREG(VENC_HS_INT_START_STOP_X);
++ DUMPREG(VENC_HS_EXT_START_STOP_X);
++ DUMPREG(VENC_VS_INT_START_X);
++ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
++ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
++ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
++ DUMPREG(VENC_VS_EXT_STOP_Y);
++ DUMPREG(VENC_AVID_START_STOP_X);
++ DUMPREG(VENC_AVID_START_STOP_Y);
++ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
++ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
++ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
++ DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
++ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
++ DUMPREG(VENC_GEN_CTRL);
++ DUMPREG(VENC_OUTPUT_CONTROL);
++ DUMPREG(VENC_OUTPUT_TEST);
++
++ venc_enable_clocks(0);
++
++#undef DUMPREG
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch
new file mode 100644
index 0000000000..7fe06c3843
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch
@@ -0,0 +1,1332 @@
+From 6770052329a65dd34cf0a9d6356b650aacb3a535 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 5 Aug 2009 16:18:31 +0300
+Subject: [PATCH 12/18] OMAP: DSS2: RFBI driver
+
+RFBI (Remote FrameBuffer Interface) implements MIPI DBI interface.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/rfbi.c | 1310 ++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 1310 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/rfbi.c
+
+diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
+new file mode 100644
+index 0000000..9dd2349
+--- /dev/null
++++ b/drivers/video/omap2/dss/rfbi.c
+@@ -0,0 +1,1310 @@
++/*
++ * linux/drivers/video/omap2/dss/rfbi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "RFBI"
++
++#include <linux/kernel.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/kfifo.h>
++#include <linux/ktime.h>
++#include <linux/hrtimer.h>
++#include <linux/seq_file.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include "dss.h"
++
++/*#define MEASURE_PERF*/
++
++#define RFBI_BASE 0x48050800
++
++struct rfbi_reg { u16 idx; };
++
++#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
++
++#define RFBI_REVISION RFBI_REG(0x0000)
++#define RFBI_SYSCONFIG RFBI_REG(0x0010)
++#define RFBI_SYSSTATUS RFBI_REG(0x0014)
++#define RFBI_CONTROL RFBI_REG(0x0040)
++#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
++#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
++#define RFBI_CMD RFBI_REG(0x004c)
++#define RFBI_PARAM RFBI_REG(0x0050)
++#define RFBI_DATA RFBI_REG(0x0054)
++#define RFBI_READ RFBI_REG(0x0058)
++#define RFBI_STATUS RFBI_REG(0x005c)
++
++#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
++#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
++#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
++#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
++#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
++#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
++
++#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
++#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
++
++#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
++
++/* To work around an RFBI transfer rate limitation */
++#define OMAP_RFBI_RATE_LIMIT 1
++
++enum omap_rfbi_cycleformat {
++ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
++ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
++ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
++ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
++};
++
++enum omap_rfbi_datatype {
++ OMAP_DSS_RFBI_DATATYPE_12 = 0,
++ OMAP_DSS_RFBI_DATATYPE_16 = 1,
++ OMAP_DSS_RFBI_DATATYPE_18 = 2,
++ OMAP_DSS_RFBI_DATATYPE_24 = 3,
++};
++
++enum omap_rfbi_parallelmode {
++ OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
++ OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
++ OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
++ OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
++};
++
++enum update_cmd {
++ RFBI_CMD_UPDATE = 0,
++ RFBI_CMD_SYNC = 1,
++};
++
++static int rfbi_convert_timings(struct rfbi_timings *t);
++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
++static void process_cmd_fifo(void);
++
++static struct {
++ void __iomem *base;
++
++ unsigned long l4_khz;
++
++ enum omap_rfbi_datatype datatype;
++ enum omap_rfbi_parallelmode parallelmode;
++
++ enum omap_rfbi_te_mode te_mode;
++ int te_enabled;
++
++ void (*framedone_callback)(void *data);
++ void *framedone_callback_data;
++
++ struct omap_dss_device *dssdev[2];
++
++ struct kfifo *cmd_fifo;
++ spinlock_t cmd_lock;
++ struct completion cmd_done;
++ atomic_t cmd_fifo_full;
++ atomic_t cmd_pending;
++#ifdef MEASURE_PERF
++ unsigned perf_bytes;
++ ktime_t perf_setup_time;
++ ktime_t perf_start_time;
++#endif
++} rfbi;
++
++struct update_region {
++ u16 x;
++ u16 y;
++ u16 w;
++ u16 h;
++};
++
++struct update_param {
++ u8 rfbi_module;
++ u8 cmd;
++
++ union {
++ struct update_region r;
++ struct completion *sync;
++ } par;
++};
++
++static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
++{
++ __raw_writel(val, rfbi.base + idx.idx);
++}
++
++static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
++{
++ return __raw_readl(rfbi.base + idx.idx);
++}
++
++static void rfbi_enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++void omap_rfbi_write_command(const void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ const u8 *b = buf;
++ for (; len; len--)
++ rfbi_write_reg(RFBI_CMD, *b++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ const u16 *w = buf;
++ BUG_ON(len & 1);
++ for (; len; len -= 2)
++ rfbi_write_reg(RFBI_CMD, *w++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_command);
++
++void omap_rfbi_read_data(void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ u8 *b = buf;
++ for (; len; len--) {
++ rfbi_write_reg(RFBI_READ, 0);
++ *b++ = rfbi_read_reg(RFBI_READ);
++ }
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ u16 *w = buf;
++ BUG_ON(len & ~1);
++ for (; len; len -= 2) {
++ rfbi_write_reg(RFBI_READ, 0);
++ *w++ = rfbi_read_reg(RFBI_READ);
++ }
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_read_data);
++
++void omap_rfbi_write_data(const void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ const u8 *b = buf;
++ for (; len; len--)
++ rfbi_write_reg(RFBI_PARAM, *b++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ const u16 *w = buf;
++ BUG_ON(len & 1);
++ for (; len; len -= 2)
++ rfbi_write_reg(RFBI_PARAM, *w++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_data);
++
++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
++ u16 x, u16 y,
++ u16 w, u16 h)
++{
++ int start_offset = scr_width * y + x;
++ int horiz_offset = scr_width - w;
++ int i;
++
++ rfbi_enable_clocks(1);
++
++ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
++ const u16 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ const u8 __iomem *b = (const u8 __iomem *)pd;
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
++ const u32 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ const u8 __iomem *b = (const u8 __iomem *)pd;
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
++ const u16 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else {
++ BUG();
++ }
++
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_pixels);
++
++#ifdef MEASURE_PERF
++static void perf_mark_setup(void)
++{
++ rfbi.perf_setup_time = ktime_get();
++}
++
++static void perf_mark_start(void)
++{
++ rfbi.perf_start_time = ktime_get();
++}
++
++static void perf_show(const char *name)
++{
++ ktime_t t, setup_time, trans_time;
++ u32 total_bytes;
++ u32 setup_us, trans_us, total_us;
++
++ t = ktime_get();
++
++ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
++ setup_us = (u32)ktime_to_us(setup_time);
++ if (setup_us == 0)
++ setup_us = 1;
++
++ trans_time = ktime_sub(t, rfbi.perf_start_time);
++ trans_us = (u32)ktime_to_us(trans_time);
++ if (trans_us == 0)
++ trans_us = 1;
++
++ total_us = setup_us + trans_us;
++
++ total_bytes = rfbi.perf_bytes;
++
++ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
++ "%u kbytes/sec\n",
++ name,
++ setup_us,
++ trans_us,
++ total_us,
++ 1000*1000 / total_us,
++ total_bytes,
++ total_bytes * 1000 / total_us);
++}
++#else
++#define perf_mark_setup()
++#define perf_mark_start()
++#define perf_show(x)
++#endif
++
++void rfbi_transfer_area(u16 width, u16 height,
++ void (callback)(void *data), void *data)
++{
++ u32 l;
++
++ /*BUG_ON(callback == 0);*/
++ BUG_ON(rfbi.framedone_callback != NULL);
++
++ DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
++
++ dispc_set_lcd_size(width, height);
++
++ dispc_enable_lcd_out(1);
++
++ rfbi.framedone_callback = callback;
++ rfbi.framedone_callback_data = data;
++
++ rfbi_enable_clocks(1);
++
++ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++ l = FLD_MOD(l, 1, 0, 0); /* enable */
++ if (!rfbi.te_enabled)
++ l = FLD_MOD(l, 1, 4, 4); /* ITE */
++
++ perf_mark_start();
++
++ rfbi_write_reg(RFBI_CONTROL, l);
++}
++
++static void framedone_callback(void *data, u32 mask)
++{
++ void (*callback)(void *data);
++
++ DSSDBG("FRAMEDONE\n");
++
++ perf_show("DISPC");
++
++ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
++
++ rfbi_enable_clocks(0);
++
++ callback = rfbi.framedone_callback;
++ rfbi.framedone_callback = NULL;
++
++ /*callback(rfbi.framedone_callback_data);*/
++
++ atomic_set(&rfbi.cmd_pending, 0);
++
++ process_cmd_fifo();
++}
++
++#if 1 /* VERBOSE */
++static void rfbi_print_timings(void)
++{
++ u32 l;
++ u32 time;
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ time = 1000000000 / rfbi.l4_khz;
++ if (l & (1 << 4))
++ time *= 2;
++
++ DSSDBG("Tick time %u ps\n", time);
++ l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
++ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
++ "REONTIME %d, REOFFTIME %d\n",
++ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
++ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
++
++ l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
++ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
++ "ACCESSTIME %d\n",
++ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
++ (l >> 22) & 0x3f);
++}
++#else
++static void rfbi_print_timings(void) {}
++#endif
++
++
++
++
++static u32 extif_clk_period;
++
++static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
++{
++ int bus_tick = extif_clk_period * div;
++ return (ps + bus_tick - 1) / bus_tick * bus_tick;
++}
++
++static int calc_reg_timing(struct rfbi_timings *t, int div)
++{
++ t->clk_div = div;
++
++ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
++
++ t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
++ t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
++ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
++
++ t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
++ t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
++ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
++
++ t->access_time = round_to_extif_ticks(t->access_time, div);
++ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
++ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
++
++ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
++ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
++ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
++ t->we_on_time, t->we_off_time, t->re_cycle_time,
++ t->we_cycle_time);
++ DSSDBG("[reg]rdaccess %d cspulse %d\n",
++ t->access_time, t->cs_pulse_width);
++
++ return rfbi_convert_timings(t);
++}
++
++static int calc_extif_timings(struct rfbi_timings *t)
++{
++ u32 max_clk_div;
++ int div;
++
++ rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
++ for (div = 1; div <= max_clk_div; div++) {
++ if (calc_reg_timing(t, div) == 0)
++ break;
++ }
++
++ if (div <= max_clk_div)
++ return 0;
++
++ DSSERR("can't setup timings\n");
++ return -1;
++}
++
++
++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
++{
++ int r;
++
++ if (!t->converted) {
++ r = calc_extif_timings(t);
++ if (r < 0)
++ DSSERR("Failed to calc timings\n");
++ }
++
++ BUG_ON(!t->converted);
++
++ rfbi_enable_clocks(1);
++ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
++ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
++
++ /* TIMEGRANULARITY */
++ REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
++ (t->tim[2] ? 1 : 0), 4, 4);
++
++ rfbi_print_timings();
++ rfbi_enable_clocks(0);
++}
++
++static int ps_to_rfbi_ticks(int time, int div)
++{
++ unsigned long tick_ps;
++ int ret;
++
++ /* Calculate in picosecs to yield more exact results */
++ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
++
++ ret = (time + tick_ps - 1) / tick_ps;
++
++ return ret;
++}
++
++#ifdef OMAP_RFBI_RATE_LIMIT
++unsigned long rfbi_get_max_tx_rate(void)
++{
++ unsigned long l4_rate, dss1_rate;
++ int min_l4_ticks = 0;
++ int i;
++
++ /* According to TI this can't be calculated so make the
++ * adjustments for a couple of known frequencies and warn for
++ * others.
++ */
++ static const struct {
++ unsigned long l4_clk; /* HZ */
++ unsigned long dss1_clk; /* HZ */
++ unsigned long min_l4_ticks;
++ } ftab[] = {
++ { 55, 132, 7, }, /* 7.86 MPix/s */
++ { 110, 110, 12, }, /* 9.16 MPix/s */
++ { 110, 132, 10, }, /* 11 Mpix/s */
++ { 120, 120, 10, }, /* 12 Mpix/s */
++ { 133, 133, 10, }, /* 13.3 Mpix/s */
++ };
++
++ l4_rate = rfbi.l4_khz / 1000;
++ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
++
++ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
++ /* Use a window instead of an exact match, to account
++ * for different DPLL multiplier / divider pairs.
++ */
++ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
++ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
++ min_l4_ticks = ftab[i].min_l4_ticks;
++ break;
++ }
++ }
++ if (i == ARRAY_SIZE(ftab)) {
++ /* Can't be sure, return anyway the maximum not
++ * rate-limited. This might cause a problem only for the
++ * tearing synchronisation.
++ */
++ DSSERR("can't determine maximum RFBI transfer rate\n");
++ return rfbi.l4_khz * 1000;
++ }
++ return rfbi.l4_khz * 1000 / min_l4_ticks;
++}
++#else
++int rfbi_get_max_tx_rate(void)
++{
++ return rfbi.l4_khz * 1000;
++}
++#endif
++
++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
++{
++ *clk_period = 1000000000 / rfbi.l4_khz;
++ *max_clk_div = 2;
++}
++
++static int rfbi_convert_timings(struct rfbi_timings *t)
++{
++ u32 l;
++ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
++ int actim, recyc, wecyc;
++ int div = t->clk_div;
++
++ if (div <= 0 || div > 2)
++ return -1;
++
++ /* Make sure that after conversion it still holds that:
++ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
++ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
++ */
++ weon = ps_to_rfbi_ticks(t->we_on_time, div);
++ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
++ if (weoff <= weon)
++ weoff = weon + 1;
++ if (weon > 0x0f)
++ return -1;
++ if (weoff > 0x3f)
++ return -1;
++
++ reon = ps_to_rfbi_ticks(t->re_on_time, div);
++ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
++ if (reoff <= reon)
++ reoff = reon + 1;
++ if (reon > 0x0f)
++ return -1;
++ if (reoff > 0x3f)
++ return -1;
++
++ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
++ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
++ if (csoff <= cson)
++ csoff = cson + 1;
++ if (csoff < max(weoff, reoff))
++ csoff = max(weoff, reoff);
++ if (cson > 0x0f)
++ return -1;
++ if (csoff > 0x3f)
++ return -1;
++
++ l = cson;
++ l |= csoff << 4;
++ l |= weon << 10;
++ l |= weoff << 14;
++ l |= reon << 20;
++ l |= reoff << 24;
++
++ t->tim[0] = l;
++
++ actim = ps_to_rfbi_ticks(t->access_time, div);
++ if (actim <= reon)
++ actim = reon + 1;
++ if (actim > 0x3f)
++ return -1;
++
++ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
++ if (wecyc < weoff)
++ wecyc = weoff;
++ if (wecyc > 0x3f)
++ return -1;
++
++ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
++ if (recyc < reoff)
++ recyc = reoff;
++ if (recyc > 0x3f)
++ return -1;
++
++ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
++ if (cs_pulse > 0x3f)
++ return -1;
++
++ l = wecyc;
++ l |= recyc << 6;
++ l |= cs_pulse << 12;
++ l |= actim << 22;
++
++ t->tim[1] = l;
++
++ t->tim[2] = div - 1;
++
++ t->converted = 1;
++
++ return 0;
++}
++
++/* xxx FIX module selection missing */
++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int extif_div)
++{
++ int hs, vs;
++ int min;
++ u32 l;
++
++ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
++ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
++ if (hs < 2)
++ return -EDOM;
++ if (mode == OMAP_DSS_RFBI_TE_MODE_2)
++ min = 2;
++ else /* OMAP_DSS_RFBI_TE_MODE_1 */
++ min = 4;
++ if (vs < min)
++ return -EDOM;
++ if (vs == hs)
++ return -EINVAL;
++ rfbi.te_mode = mode;
++ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
++ mode, hs, vs, hs_pol_inv, vs_pol_inv);
++
++ rfbi_enable_clocks(1);
++ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
++ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ if (hs_pol_inv)
++ l &= ~(1 << 21);
++ else
++ l |= 1 << 21;
++ if (vs_pol_inv)
++ l &= ~(1 << 20);
++ else
++ l |= 1 << 20;
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(omap_rfbi_setup_te);
++
++/* xxx FIX module selection missing */
++int omap_rfbi_enable_te(bool enable, unsigned line)
++{
++ u32 l;
++
++ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
++ if (line > (1 << 11) - 1)
++ return -EINVAL;
++
++ rfbi_enable_clocks(1);
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ l &= ~(0x3 << 2);
++ if (enable) {
++ rfbi.te_enabled = 1;
++ l |= rfbi.te_mode << 2;
++ } else
++ rfbi.te_enabled = 0;
++ rfbi_write_reg(RFBI_CONFIG(0), l);
++ rfbi_write_reg(RFBI_LINE_NUMBER, line);
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(omap_rfbi_enable_te);
++
++#if 0
++static void rfbi_enable_config(int enable1, int enable2)
++{
++ u32 l;
++ int cs = 0;
++
++ if (enable1)
++ cs |= 1<<0;
++ if (enable2)
++ cs |= 1<<1;
++
++ rfbi_enable_clocks(1);
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++
++ l = FLD_MOD(l, cs, 3, 2);
++ l = FLD_MOD(l, 0, 1, 1);
++
++ rfbi_write_reg(RFBI_CONTROL, l);
++
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
++ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
++ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
++
++ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
++ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
++ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
++
++ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
++ rfbi_write_reg(RFBI_CONFIG(0), l);
++
++ rfbi_enable_clocks(0);
++}
++#endif
++
++int rfbi_configure(int rfbi_module, int bpp, int lines)
++{
++ u32 l;
++ int cycle1 = 0, cycle2 = 0, cycle3 = 0;
++ enum omap_rfbi_cycleformat cycleformat;
++ enum omap_rfbi_datatype datatype;
++ enum omap_rfbi_parallelmode parallelmode;
++
++ switch (bpp) {
++ case 12:
++ datatype = OMAP_DSS_RFBI_DATATYPE_12;
++ break;
++ case 16:
++ datatype = OMAP_DSS_RFBI_DATATYPE_16;
++ break;
++ case 18:
++ datatype = OMAP_DSS_RFBI_DATATYPE_18;
++ break;
++ case 24:
++ datatype = OMAP_DSS_RFBI_DATATYPE_24;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ rfbi.datatype = datatype;
++
++ switch (lines) {
++ case 8:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
++ break;
++ case 9:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
++ break;
++ case 12:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
++ break;
++ case 16:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ rfbi.parallelmode = parallelmode;
++
++ if ((bpp % lines) == 0) {
++ switch (bpp / lines) {
++ case 1:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
++ break;
++ case 2:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
++ break;
++ case 3:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ } else if ((2 * bpp % lines) == 0) {
++ if ((2 * bpp / lines) == 3)
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
++ else {
++ BUG();
++ return 1;
++ }
++ } else {
++ BUG();
++ return 1;
++ }
++
++ switch (cycleformat) {
++ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
++ cycle1 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
++ cycle1 = lines;
++ cycle2 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
++ cycle1 = lines;
++ cycle2 = lines;
++ cycle3 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
++ cycle1 = lines;
++ cycle2 = (lines / 2) | ((lines / 2) << 16);
++ cycle3 = (lines << 16);
++ break;
++ }
++
++ rfbi_enable_clocks(1);
++
++ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
++
++ l = 0;
++ l |= FLD_VAL(parallelmode, 1, 0);
++ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
++ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
++ l |= FLD_VAL(datatype, 6, 5);
++ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
++ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
++ l |= FLD_VAL(cycleformat, 10, 9);
++ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
++ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
++ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
++ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
++ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
++ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
++ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
++ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
++
++ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
++ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
++ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
++
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
++ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
++ rfbi_write_reg(RFBI_CONTROL, l);
++
++
++ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
++ bpp, lines, cycle1, cycle2, cycle3);
++
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(rfbi_configure);
++
++static int rfbi_find_display(struct omap_dss_device *dssdev)
++{
++ if (dssdev == rfbi.dssdev[0])
++ return 0;
++
++ if (dssdev == rfbi.dssdev[1])
++ return 1;
++
++ BUG();
++ return -1;
++}
++
++
++static void signal_fifo_waiters(void)
++{
++ if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
++ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
++ complete(&rfbi.cmd_done);
++ atomic_dec(&rfbi.cmd_fifo_full);
++ }
++}
++
++/* returns 1 for async op, and 0 for sync op */
++static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
++{
++ u16 x = upd->x;
++ u16 y = upd->y;
++ u16 w = upd->w;
++ u16 h = upd->h;
++
++ perf_mark_setup();
++
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ /*dssdev->driver->enable_te(dssdev, 1); */
++ dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
++ }
++
++#ifdef MEASURE_PERF
++ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
++#endif
++
++ dssdev->driver->setup_update(dssdev, x, y, w, h);
++
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ rfbi_transfer_area(w, h, NULL, NULL);
++ return 1;
++ } else {
++ struct omap_overlay *ovl;
++ void __iomem *addr;
++ int scr_width;
++
++ ovl = dssdev->manager->overlays[0];
++ scr_width = ovl->info.screen_width;
++ addr = ovl->info.vaddr;
++
++ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
++
++ perf_show("L4");
++
++ return 0;
++ }
++}
++
++static void process_cmd_fifo(void)
++{
++ int len;
++ struct update_param p;
++ struct omap_dss_device *dssdev;
++ unsigned long flags;
++
++ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
++ return;
++
++ while (true) {
++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
++
++ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
++ sizeof(struct update_param));
++ if (len == 0) {
++ DSSDBG("nothing more in fifo\n");
++ atomic_set(&rfbi.cmd_pending, 0);
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++ break;
++ }
++
++ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
++
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++
++ BUG_ON(len != sizeof(struct update_param));
++ BUG_ON(p.rfbi_module > 1);
++
++ dssdev = rfbi.dssdev[p.rfbi_module];
++
++ if (p.cmd == RFBI_CMD_UPDATE) {
++ if (do_update(dssdev, &p.par.r))
++ break; /* async op */
++ } else if (p.cmd == RFBI_CMD_SYNC) {
++ DSSDBG("Signaling SYNC done!\n");
++ complete(p.par.sync);
++ } else
++ BUG();
++ }
++
++ signal_fifo_waiters();
++}
++
++static void rfbi_push_cmd(struct update_param *p)
++{
++ int ret;
++
++ while (1) {
++ unsigned long flags;
++ int available;
++
++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
++ available = RFBI_CMD_FIFO_LEN_BYTES -
++ __kfifo_len(rfbi.cmd_fifo);
++
++/* DSSDBG("%d bytes left in fifo\n", available); */
++ if (available < sizeof(struct update_param)) {
++ DSSDBG("Going to wait because FIFO FULL..\n");
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++ atomic_inc(&rfbi.cmd_fifo_full);
++ wait_for_completion(&rfbi.cmd_done);
++ /*DSSDBG("Woke up because fifo not full anymore\n");*/
++ continue;
++ }
++
++ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
++ sizeof(struct update_param));
++/* DSSDBG("pushed %d bytes\n", ret);*/
++
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++
++ BUG_ON(ret != sizeof(struct update_param));
++
++ break;
++ }
++}
++
++static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
++{
++ struct update_param p;
++
++ p.rfbi_module = rfbi_module;
++ p.cmd = RFBI_CMD_UPDATE;
++
++ p.par.r.x = x;
++ p.par.r.y = y;
++ p.par.r.w = w;
++ p.par.r.h = h;
++
++ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
++
++ rfbi_push_cmd(&p);
++
++ process_cmd_fifo();
++}
++
++static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
++{
++ struct update_param p;
++
++ p.rfbi_module = rfbi_module;
++ p.cmd = RFBI_CMD_SYNC;
++ p.par.sync = sync_comp;
++
++ rfbi_push_cmd(&p);
++
++ DSSDBG("RFBI sync pushed to cmd fifo\n");
++
++ process_cmd_fifo();
++}
++
++void rfbi_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(RFBI_REVISION);
++ DUMPREG(RFBI_SYSCONFIG);
++ DUMPREG(RFBI_SYSSTATUS);
++ DUMPREG(RFBI_CONTROL);
++ DUMPREG(RFBI_PIXEL_CNT);
++ DUMPREG(RFBI_LINE_NUMBER);
++ DUMPREG(RFBI_CMD);
++ DUMPREG(RFBI_PARAM);
++ DUMPREG(RFBI_DATA);
++ DUMPREG(RFBI_READ);
++ DUMPREG(RFBI_STATUS);
++
++ DUMPREG(RFBI_CONFIG(0));
++ DUMPREG(RFBI_ONOFF_TIME(0));
++ DUMPREG(RFBI_CYCLE_TIME(0));
++ DUMPREG(RFBI_DATA_CYCLE1(0));
++ DUMPREG(RFBI_DATA_CYCLE2(0));
++ DUMPREG(RFBI_DATA_CYCLE3(0));
++
++ DUMPREG(RFBI_CONFIG(1));
++ DUMPREG(RFBI_ONOFF_TIME(1));
++ DUMPREG(RFBI_CYCLE_TIME(1));
++ DUMPREG(RFBI_DATA_CYCLE1(1));
++ DUMPREG(RFBI_DATA_CYCLE2(1));
++ DUMPREG(RFBI_DATA_CYCLE3(1));
++
++ DUMPREG(RFBI_VSYNC_WIDTH);
++ DUMPREG(RFBI_HSYNC_WIDTH);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++int rfbi_init(void)
++{
++ u32 rev;
++ u32 l;
++
++ spin_lock_init(&rfbi.cmd_lock);
++ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
++ &rfbi.cmd_lock);
++ if (IS_ERR(rfbi.cmd_fifo))
++ return -ENOMEM;
++
++ init_completion(&rfbi.cmd_done);
++ atomic_set(&rfbi.cmd_fifo_full, 0);
++ atomic_set(&rfbi.cmd_pending, 0);
++
++ rfbi.base = ioremap(RFBI_BASE, SZ_256);
++ if (!rfbi.base) {
++ DSSERR("can't ioremap RFBI\n");
++ return -ENOMEM;
++ }
++
++ rfbi_enable_clocks(1);
++
++ msleep(10);
++
++ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
++
++ /* Enable autoidle and smart-idle */
++ l = rfbi_read_reg(RFBI_SYSCONFIG);
++ l |= (1 << 0) | (2 << 3);
++ rfbi_write_reg(RFBI_SYSCONFIG, l);
++
++ rev = rfbi_read_reg(RFBI_REVISION);
++ printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++
++void rfbi_exit(void)
++{
++ DSSDBG("rfbi_exit\n");
++
++ kfifo_free(rfbi.cmd_fifo);
++
++ iounmap(rfbi.base);
++}
++
++/* struct omap_display support */
++static int rfbi_display_update(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int rfbi_module;
++
++ if (w == 0 || h == 0)
++ return 0;
++
++ rfbi_module = rfbi_find_display(dssdev);
++
++ rfbi_push_update(rfbi_module, x, y, w, h);
++
++ return 0;
++}
++
++static int rfbi_display_sync(struct omap_dss_device *dssdev)
++{
++ struct completion sync_comp;
++ int rfbi_module;
++
++ rfbi_module = rfbi_find_display(dssdev);
++
++ init_completion(&sync_comp);
++ rfbi_push_sync(rfbi_module, &sync_comp);
++ DSSDBG("Waiting for SYNC to happen...\n");
++ wait_for_completion(&sync_comp);
++ DSSDBG("Released from SYNC\n");
++ return 0;
++}
++
++static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
++{
++ dssdev->driver->enable_te(dssdev, enable);
++ return 0;
++}
++
++static int rfbi_display_enable(struct omap_dss_device *dssdev)
++{
++ int r;
++
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ r = omap_dispc_register_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++ if (r) {
++ DSSERR("can't get FRAMEDONE irq\n");
++ goto err1;
++ }
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
++
++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
++
++ rfbi_configure(dssdev->phy.rfbi.channel,
++ dssdev->ctrl.pixel_size,
++ dssdev->phy.rfbi.data_lines);
++
++ rfbi_set_timings(dssdev->phy.rfbi.channel,
++ &dssdev->ctrl.rfbi_timings);
++
++
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
++ if (r)
++ goto err2;
++ }
++
++ return 0;
++err2:
++ omap_dispc_unregister_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
++ return r;
++}
++
++static void rfbi_display_disable(struct omap_dss_device *dssdev)
++{
++ dssdev->driver->disable(dssdev);
++ omap_dispc_unregister_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++ omap_dss_stop_device(dssdev);
++}
++
++int rfbi_init_display(struct omap_dss_device *dssdev)
++{
++ dssdev->enable = rfbi_display_enable;
++ dssdev->disable = rfbi_display_disable;
++ dssdev->update = rfbi_display_update;
++ dssdev->sync = rfbi_display_sync;
++ dssdev->enable_te = rfbi_display_enable_te;
++
++ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
++
++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ return 0;
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch
new file mode 100644
index 0000000000..698d4fb893
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch
@@ -0,0 +1,284 @@
+From 6191570efd848a073fcdfb619ba28cc0d66b2842 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 5 Aug 2009 16:18:44 +0300
+Subject: [PATCH 13/18] OMAP: DSS2: SDI driver
+
+SDI (Serial Display Interface) implements TI Flatlink 3G display
+interface.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/sdi.c | 261 +++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 261 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/sdi.c
+
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+new file mode 100644
+index 0000000..a9c727e
+--- /dev/null
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -0,0 +1,261 @@
++/*
++ * linux/drivers/video/omap2/dss/sdi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "SDI"
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include "dss.h"
++
++static struct {
++ bool skip_init;
++ bool update_enabled;
++} sdi;
++
++static void sdi_basic_init(void)
++{
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++ dispc_set_tft_data_lines(24);
++ dispc_lcd_enable_signal_polarity(1);
++}
++
++static int sdi_display_enable(struct omap_dss_device *dssdev)
++{
++ struct omap_video_timings *t = &dssdev->panel.timings;
++ struct dispc_clock_info cinfo;
++ u16 lck_div, pck_div;
++ unsigned long fck;
++ unsigned long pck;
++ int r;
++
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("dssdev already enabled\n");
++ r = -EINVAL;
++ goto err1;
++ }
++
++ /* In case of skip_init sdi_init has already enabled the clocks */
++ if (!sdi.skip_init)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ sdi_basic_init();
++
++ /* 15.5.9.1.2 */
++ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
++
++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
++ dssdev->panel.acb);
++
++ if (!sdi.skip_init)
++ r = dispc_calc_clock_div(1, t->pixel_clock * 1000,
++ &cinfo);
++ else
++ r = dispc_get_clock_div(&cinfo);
++
++ if (r)
++ goto err2;
++
++ fck = cinfo.fck;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ if (pck != t->pixel_clock) {
++ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
++ "got %lu kHz\n",
++ t->pixel_clock, pck);
++
++ t->pixel_clock = pck;
++ }
++
++
++ dispc_set_lcd_timings(t);
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r)
++ goto err2;
++
++ if (!sdi.skip_init) {
++ dss_sdi_init(dssdev->phy.sdi.datapairs);
++ dss_sdi_enable();
++ mdelay(2);
++ }
++
++ dispc_enable_lcd_out(1);
++
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
++ if (r)
++ goto err3;
++ }
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ sdi.skip_init = 0;
++
++ return 0;
++err3:
++ dispc_enable_lcd_out(0);
++err2:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
++ return r;
++}
++
++static int sdi_display_resume(struct omap_dss_device *dssdev);
++
++static void sdi_display_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
++ return;
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ sdi_display_resume(dssdev);
++
++ if (dssdev->driver->disable)
++ dssdev->driver->disable(dssdev);
++
++ dispc_enable_lcd_out(0);
++
++ dss_sdi_disable();
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ omap_dss_stop_device(dssdev);
++}
++
++static int sdi_display_suspend(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EINVAL;
++
++ if (dssdev->driver->suspend)
++ dssdev->driver->suspend(dssdev);
++
++ dispc_enable_lcd_out(0);
++
++ dss_sdi_disable();
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ return 0;
++}
++
++static int sdi_display_resume(struct omap_dss_device *dssdev)
++{
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ return -EINVAL;
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dss_sdi_enable();
++ mdelay(2);
++
++ dispc_enable_lcd_out(1);
++
++ if (dssdev->driver->resume)
++ dssdev->driver->resume(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++}
++
++static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
++ enum omap_dss_update_mode mode)
++{
++ if (mode == OMAP_DSS_UPDATE_MANUAL)
++ return -EINVAL;
++
++ if (mode == OMAP_DSS_UPDATE_DISABLED) {
++ dispc_enable_lcd_out(0);
++ sdi.update_enabled = 0;
++ } else {
++ dispc_enable_lcd_out(1);
++ sdi.update_enabled = 1;
++ }
++
++ return 0;
++}
++
++static enum omap_dss_update_mode sdi_display_get_update_mode(
++ struct omap_dss_device *dssdev)
++{
++ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
++ OMAP_DSS_UPDATE_DISABLED;
++}
++
++static void sdi_get_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ *timings = dssdev->panel.timings;
++}
++
++int sdi_init_display(struct omap_dss_device *dssdev)
++{
++ DSSDBG("SDI init\n");
++
++ dssdev->enable = sdi_display_enable;
++ dssdev->disable = sdi_display_disable;
++ dssdev->suspend = sdi_display_suspend;
++ dssdev->resume = sdi_display_resume;
++ dssdev->set_update_mode = sdi_display_set_update_mode;
++ dssdev->get_update_mode = sdi_display_get_update_mode;
++ dssdev->get_timings = sdi_get_timings;
++
++ return 0;
++}
++
++int sdi_init(bool skip_init)
++{
++ /* we store this for first display enable, then clear it */
++ sdi.skip_init = skip_init;
++
++ /*
++ * Enable clocks already here, otherwise there would be a toggle
++ * of them until sdi_display_enable is called.
++ */
++ if (skip_init)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return 0;
++}
++
++void sdi_exit(void)
++{
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch
new file mode 100644
index 0000000000..51020416fe
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch
@@ -0,0 +1,3531 @@
+From 1452422be43114972e71ac2bbb9e1055f4616602 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 5 Aug 2009 16:18:57 +0300
+Subject: [PATCH 14/18] OMAP: DSS2: DSI driver
+
+DSI (Display Serial Interface) driver implements MIPI DSI interface.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 3509 +++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 3509 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/dsi.c
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+new file mode 100644
+index 0000000..d43b9ce
+--- /dev/null
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -0,0 +1,3509 @@
++/*
++ * linux/drivers/video/omap2/dss/dsi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DSI"
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/mutex.h>
++#include <linux/seq_file.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include <mach/clock.h>
++
++#include "dss.h"
++
++/*#define VERBOSE_IRQ*/
++
++#define DSI_BASE 0x4804FC00
++
++struct dsi_reg { u16 idx; };
++
++#define DSI_REG(idx) ((const struct dsi_reg) { idx })
++
++#define DSI_SZ_REGS SZ_1K
++/* DSI Protocol Engine */
++
++#define DSI_REVISION DSI_REG(0x0000)
++#define DSI_SYSCONFIG DSI_REG(0x0010)
++#define DSI_SYSSTATUS DSI_REG(0x0014)
++#define DSI_IRQSTATUS DSI_REG(0x0018)
++#define DSI_IRQENABLE DSI_REG(0x001C)
++#define DSI_CTRL DSI_REG(0x0040)
++#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
++#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
++#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
++#define DSI_CLK_CTRL DSI_REG(0x0054)
++#define DSI_TIMING1 DSI_REG(0x0058)
++#define DSI_TIMING2 DSI_REG(0x005C)
++#define DSI_VM_TIMING1 DSI_REG(0x0060)
++#define DSI_VM_TIMING2 DSI_REG(0x0064)
++#define DSI_VM_TIMING3 DSI_REG(0x0068)
++#define DSI_CLK_TIMING DSI_REG(0x006C)
++#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
++#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
++#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
++#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
++#define DSI_VM_TIMING4 DSI_REG(0x0080)
++#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
++#define DSI_VM_TIMING5 DSI_REG(0x0088)
++#define DSI_VM_TIMING6 DSI_REG(0x008C)
++#define DSI_VM_TIMING7 DSI_REG(0x0090)
++#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
++#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
++#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
++#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
++#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
++#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
++#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
++#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
++
++/* DSIPHY_SCP */
++
++#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
++#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
++#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
++#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
++
++/* DSI_PLL_CTRL_SCP */
++
++#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
++#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
++#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
++#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
++#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dsi_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
++
++/* Global interrupts */
++#define DSI_IRQ_VC0 (1 << 0)
++#define DSI_IRQ_VC1 (1 << 1)
++#define DSI_IRQ_VC2 (1 << 2)
++#define DSI_IRQ_VC3 (1 << 3)
++#define DSI_IRQ_WAKEUP (1 << 4)
++#define DSI_IRQ_RESYNC (1 << 5)
++#define DSI_IRQ_PLL_LOCK (1 << 7)
++#define DSI_IRQ_PLL_UNLOCK (1 << 8)
++#define DSI_IRQ_PLL_RECALL (1 << 9)
++#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
++#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
++#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
++#define DSI_IRQ_TE_TRIGGER (1 << 16)
++#define DSI_IRQ_ACK_TRIGGER (1 << 17)
++#define DSI_IRQ_SYNC_LOST (1 << 18)
++#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
++#define DSI_IRQ_TA_TIMEOUT (1 << 20)
++#define DSI_IRQ_ERROR_MASK \
++ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
++ DSI_IRQ_TA_TIMEOUT)
++#define DSI_IRQ_CHANNEL_MASK 0xf
++
++/* Virtual channel interrupts */
++#define DSI_VC_IRQ_CS (1 << 0)
++#define DSI_VC_IRQ_ECC_CORR (1 << 1)
++#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
++#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
++#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
++#define DSI_VC_IRQ_BTA (1 << 5)
++#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
++#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
++#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
++#define DSI_VC_IRQ_ERROR_MASK \
++ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
++ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
++ DSI_VC_IRQ_FIFO_TX_UDF)
++
++/* ComplexIO interrupts */
++#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
++#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
++#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
++#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
++#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
++#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
++#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
++#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
++#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
++#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
++#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
++#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
++
++#define DSI_DT_DCS_SHORT_WRITE_0 0x05
++#define DSI_DT_DCS_SHORT_WRITE_1 0x15
++#define DSI_DT_DCS_READ 0x06
++#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
++#define DSI_DT_NULL_PACKET 0x09
++#define DSI_DT_DCS_LONG_WRITE 0x39
++
++#define DSI_DT_RX_ACK_WITH_ERR 0x02
++#define DSI_DT_RX_DCS_LONG_READ 0x1c
++#define DSI_DT_RX_SHORT_READ_1 0x21
++#define DSI_DT_RX_SHORT_READ_2 0x22
++
++#define FINT_MAX 2100000
++#define FINT_MIN 750000
++#define REGN_MAX (1 << 7)
++#define REGM_MAX ((1 << 11) - 1)
++#define REGM3_MAX (1 << 4)
++#define REGM4_MAX (1 << 4)
++
++enum fifo_size {
++ DSI_FIFO_SIZE_0 = 0,
++ DSI_FIFO_SIZE_32 = 1,
++ DSI_FIFO_SIZE_64 = 2,
++ DSI_FIFO_SIZE_96 = 3,
++ DSI_FIFO_SIZE_128 = 4,
++};
++
++enum dsi_vc_mode {
++ DSI_VC_MODE_L4 = 0,
++ DSI_VC_MODE_VP,
++};
++
++struct dsi_update_region {
++ bool dirty;
++ u16 x, y, w, h;
++ struct omap_dss_device *device;
++};
++
++static struct
++{
++ void __iomem *base;
++
++ unsigned long dsi1_pll_fclk; /* Hz */
++ unsigned long dsi2_pll_fclk; /* Hz */
++ unsigned long dsiphy; /* Hz */
++ unsigned long ddr_clk; /* Hz */
++
++ struct regulator *vdds_dsi_reg;
++
++ struct {
++ enum dsi_vc_mode mode;
++ struct omap_dss_device *dssdev;
++ enum fifo_size fifo_size;
++ int dest_per; /* destination peripheral 0-3 */
++ } vc[4];
++
++ struct mutex lock;
++ struct mutex bus_lock;
++
++ unsigned pll_locked;
++
++ struct completion bta_completion;
++
++ struct task_struct *thread;
++ wait_queue_head_t waitqueue;
++
++ spinlock_t update_lock;
++ bool framedone_received;
++ struct dsi_update_region update_region;
++ struct dsi_update_region active_update_region;
++ struct completion update_completion;
++
++ enum omap_dss_update_mode user_update_mode;
++ enum omap_dss_update_mode update_mode;
++ bool te_enabled;
++ bool use_ext_te;
++
++ unsigned long cache_req_pck;
++ unsigned long cache_clk_freq;
++ struct dsi_clock_info cache_cinfo;
++
++ u32 errors;
++ spinlock_t errors_lock;
++#ifdef DEBUG
++ ktime_t perf_setup_time;
++ ktime_t perf_start_time;
++ ktime_t perf_start_time_auto;
++ int perf_measure_frames;
++#endif
++ int debug_read;
++ int debug_write;
++} dsi;
++
++#ifdef DEBUG
++static unsigned int dsi_perf;
++module_param_named(dsi_perf, dsi_perf, bool, 0644);
++#endif
++
++static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
++{
++ __raw_writel(val, dsi.base + idx.idx);
++}
++
++static inline u32 dsi_read_reg(const struct dsi_reg idx)
++{
++ return __raw_readl(dsi.base + idx.idx);
++}
++
++
++void dsi_save_context(void)
++{
++}
++
++void dsi_restore_context(void)
++{
++}
++
++void dsi_bus_lock(void)
++{
++ mutex_lock(&dsi.bus_lock);
++}
++EXPORT_SYMBOL(dsi_bus_lock);
++
++void dsi_bus_unlock(void)
++{
++ mutex_unlock(&dsi.bus_lock);
++}
++EXPORT_SYMBOL(dsi_bus_unlock);
++
++static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
++ int value)
++{
++ int t = 100000;
++
++ while (REG_GET(idx, bitnum, bitnum) != value) {
++ if (--t == 0)
++ return !value;
++ }
++
++ return value;
++}
++
++#ifdef DEBUG
++static void dsi_perf_mark_setup(void)
++{
++ dsi.perf_setup_time = ktime_get();
++}
++
++static void dsi_perf_mark_start(void)
++{
++ dsi.perf_start_time = ktime_get();
++}
++
++static void dsi_perf_mark_start_auto(void)
++{
++ dsi.perf_measure_frames = 0;
++ dsi.perf_start_time_auto = ktime_get();
++}
++
++static void dsi_perf_show(const char *name)
++{
++ ktime_t t, setup_time, trans_time;
++ u32 total_bytes;
++ u32 setup_us, trans_us, total_us;
++
++ if (!dsi_perf)
++ return;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
++ return;
++
++ t = ktime_get();
++
++ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
++ setup_us = (u32)ktime_to_us(setup_time);
++ if (setup_us == 0)
++ setup_us = 1;
++
++ trans_time = ktime_sub(t, dsi.perf_start_time);
++ trans_us = (u32)ktime_to_us(trans_time);
++ if (trans_us == 0)
++ trans_us = 1;
++
++ total_us = setup_us + trans_us;
++
++ total_bytes = dsi.active_update_region.w *
++ dsi.active_update_region.h *
++ dsi.active_update_region.device->ctrl.pixel_size / 8;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
++ static u32 s_total_trans_us, s_total_setup_us;
++ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
++ static u32 s_max_trans_us, s_max_setup_us;
++ const int numframes = 100;
++ ktime_t total_time_auto;
++ u32 total_time_auto_us;
++
++ dsi.perf_measure_frames++;
++
++ if (setup_us < s_min_setup_us)
++ s_min_setup_us = setup_us;
++
++ if (setup_us > s_max_setup_us)
++ s_max_setup_us = setup_us;
++
++ s_total_setup_us += setup_us;
++
++ if (trans_us < s_min_trans_us)
++ s_min_trans_us = trans_us;
++
++ if (trans_us > s_max_trans_us)
++ s_max_trans_us = trans_us;
++
++ s_total_trans_us += trans_us;
++
++ if (dsi.perf_measure_frames < numframes)
++ return;
++
++ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
++ total_time_auto_us = (u32)ktime_to_us(total_time_auto);
++
++ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
++ "trans %u/%u/%u\n",
++ name,
++ 1000 * 1000 * numframes / total_time_auto_us,
++ s_min_setup_us,
++ s_max_setup_us,
++ s_total_setup_us / numframes,
++ s_min_trans_us,
++ s_max_trans_us,
++ s_total_trans_us / numframes);
++
++ s_total_setup_us = 0;
++ s_min_setup_us = 0xffffffff;
++ s_max_setup_us = 0;
++ s_total_trans_us = 0;
++ s_min_trans_us = 0xffffffff;
++ s_max_trans_us = 0;
++ dsi_perf_mark_start_auto();
++ } else {
++ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
++ "%u bytes, %u kbytes/sec\n",
++ name,
++ setup_us,
++ trans_us,
++ total_us,
++ 1000*1000 / total_us,
++ total_bytes,
++ total_bytes * 1000 / total_us);
++ }
++}
++#else
++#define dsi_perf_mark_setup()
++#define dsi_perf_mark_start()
++#define dsi_perf_mark_start_auto()
++#define dsi_perf_show(x)
++#endif
++
++static void print_irq_status(u32 status)
++{
++#ifndef VERBOSE_IRQ
++ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
++ return;
++#endif
++ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DSI_IRQ_##x) \
++ printk(#x " ");
++#ifdef VERBOSE_IRQ
++ PIS(VC0);
++ PIS(VC1);
++ PIS(VC2);
++ PIS(VC3);
++#endif
++ PIS(WAKEUP);
++ PIS(RESYNC);
++ PIS(PLL_LOCK);
++ PIS(PLL_UNLOCK);
++ PIS(PLL_RECALL);
++ PIS(COMPLEXIO_ERR);
++ PIS(HS_TX_TIMEOUT);
++ PIS(LP_RX_TIMEOUT);
++ PIS(TE_TRIGGER);
++ PIS(ACK_TRIGGER);
++ PIS(SYNC_LOST);
++ PIS(LDO_POWER_GOOD);
++ PIS(TA_TIMEOUT);
++#undef PIS
++
++ printk("\n");
++}
++
++static void print_irq_status_vc(int channel, u32 status)
++{
++#ifndef VERBOSE_IRQ
++ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
++ return;
++#endif
++ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
++
++#define PIS(x) \
++ if (status & DSI_VC_IRQ_##x) \
++ printk(#x " ");
++ PIS(CS);
++ PIS(ECC_CORR);
++#ifdef VERBOSE_IRQ
++ PIS(PACKET_SENT);
++#endif
++ PIS(FIFO_TX_OVF);
++ PIS(FIFO_RX_OVF);
++ PIS(BTA);
++ PIS(ECC_NO_CORR);
++ PIS(FIFO_TX_UDF);
++ PIS(PP_BUSY_CHANGE);
++#undef PIS
++ printk("\n");
++}
++
++static void print_irq_status_cio(u32 status)
++{
++ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DSI_CIO_IRQ_##x) \
++ printk(#x " ");
++ PIS(ERRSYNCESC1);
++ PIS(ERRSYNCESC2);
++ PIS(ERRSYNCESC3);
++ PIS(ERRESC1);
++ PIS(ERRESC2);
++ PIS(ERRESC3);
++ PIS(ERRCONTROL1);
++ PIS(ERRCONTROL2);
++ PIS(ERRCONTROL3);
++ PIS(STATEULPS1);
++ PIS(STATEULPS2);
++ PIS(STATEULPS3);
++ PIS(ERRCONTENTIONLP0_1);
++ PIS(ERRCONTENTIONLP1_1);
++ PIS(ERRCONTENTIONLP0_2);
++ PIS(ERRCONTENTIONLP1_2);
++ PIS(ERRCONTENTIONLP0_3);
++ PIS(ERRCONTENTIONLP1_3);
++ PIS(ULPSACTIVENOT_ALL0);
++ PIS(ULPSACTIVENOT_ALL1);
++#undef PIS
++
++ printk("\n");
++}
++
++static int debug_irq;
++
++/* called from dss */
++void dsi_irq_handler(void)
++{
++ u32 irqstatus, vcstatus, ciostatus;
++ int i;
++
++ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
++
++ if (irqstatus & DSI_IRQ_ERROR_MASK) {
++ DSSERR("DSI error, irqstatus %x\n", irqstatus);
++ print_irq_status(irqstatus);
++ spin_lock(&dsi.errors_lock);
++ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
++ spin_unlock(&dsi.errors_lock);
++ } else if (debug_irq) {
++ print_irq_status(irqstatus);
++ }
++
++ for (i = 0; i < 4; ++i) {
++ if ((irqstatus & (1<<i)) == 0)
++ continue;
++
++ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
++
++ if (vcstatus & DSI_VC_IRQ_BTA)
++ complete(&dsi.bta_completion);
++
++ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
++ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
++ i, vcstatus);
++ print_irq_status_vc(i, vcstatus);
++ } else if (debug_irq) {
++ print_irq_status_vc(i, vcstatus);
++ }
++
++ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
++ }
++
++ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
++ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
++
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
++
++ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
++ print_irq_status_cio(ciostatus);
++ }
++
++ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
++}
++
++
++static void _dsi_initialize_irq(void)
++{
++ u32 l;
++ int i;
++
++ /* disable all interrupts */
++ dsi_write_reg(DSI_IRQENABLE, 0);
++ for (i = 0; i < 4; ++i)
++ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
++
++ /* clear interrupt status */
++ l = dsi_read_reg(DSI_IRQSTATUS);
++ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
++
++ for (i = 0; i < 4; ++i) {
++ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
++ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
++ }
++
++ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
++
++ /* enable error irqs */
++ l = DSI_IRQ_ERROR_MASK;
++ dsi_write_reg(DSI_IRQENABLE, l);
++
++ l = DSI_VC_IRQ_ERROR_MASK;
++ for (i = 0; i < 4; ++i)
++ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
++
++ /* XXX zonda responds incorrectly, causing control error:
++ Exit from LP-ESC mode to LP11 uses wrong transition states on the
++ data lines LP0 and LN0. */
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
++ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
++}
++
++static u32 dsi_get_errors(void)
++{
++ unsigned long flags;
++ u32 e;
++ spin_lock_irqsave(&dsi.errors_lock, flags);
++ e = dsi.errors;
++ dsi.errors = 0;
++ spin_unlock_irqrestore(&dsi.errors_lock, flags);
++ return e;
++}
++
++static void dsi_vc_enable_bta_irq(int channel)
++{
++ u32 l;
++
++ dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
++
++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
++ l |= DSI_VC_IRQ_BTA;
++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
++}
++
++static void dsi_vc_disable_bta_irq(int channel)
++{
++ u32 l;
++
++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
++ l &= ~DSI_VC_IRQ_BTA;
++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
++}
++
++/* DSI func clock. this could also be DSI2_PLL_FCLK */
++static inline void enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++/* source clock for DSI PLL. this could also be PCLKFREE */
++static inline void dsi_enable_pll_clock(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_FCK2);
++ else
++ dss_clk_disable(DSS_CLK_FCK2);
++
++ if (enable && dsi.pll_locked) {
++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
++ DSSERR("cannot lock PLL when enabling clocks\n");
++ }
++}
++
++#ifdef DEBUG
++static void _dsi_print_reset_status(void)
++{
++ u32 l;
++
++ if (!dss_debug)
++ return;
++
++ /* A dummy read using the SCP interface to any DSIPHY register is
++ * required after DSIPHY reset to complete the reset of the DSI complex
++ * I/O. */
++ l = dsi_read_reg(DSI_DSIPHY_CFG5);
++
++ printk(KERN_DEBUG "DSI resets: ");
++
++ l = dsi_read_reg(DSI_PLL_STATUS);
++ printk("PLL (%d) ", FLD_GET(l, 0, 0));
++
++ l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
++ printk("CIO (%d) ", FLD_GET(l, 29, 29));
++
++ l = dsi_read_reg(DSI_DSIPHY_CFG5);
++ printk("PHY (%x, %d, %d, %d)\n",
++ FLD_GET(l, 28, 26),
++ FLD_GET(l, 29, 29),
++ FLD_GET(l, 30, 30),
++ FLD_GET(l, 31, 31));
++}
++#else
++#define _dsi_print_reset_status()
++#endif
++
++static inline int dsi_if_enable(bool enable)
++{
++ DSSDBG("dsi_if_enable(%d)\n", enable);
++
++ enable = enable ? 1 : 0;
++ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
++
++ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
++ DSSERR("Failed to set dsi_if_enable to %d\n", enable);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static unsigned long dsi_fclk_rate(void)
++{
++ unsigned long r;
++
++ if (dss_get_dsi_clk_source() == 0) {
++ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
++ r = dss_clk_get_rate(DSS_CLK_FCK1);
++ } else {
++ /* DSI FCLK source is DSI2_PLL_FCLK */
++ r = dsi.dsi2_pll_fclk;
++ }
++
++ return r;
++}
++
++static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
++{
++ unsigned n;
++ unsigned long dsi_fclk;
++ unsigned long lp_clk, lp_clk_req;
++
++ dsi_fclk = dsi_fclk_rate();
++
++ lp_clk_req = dssdev->phy.dsi.lp_clk_hz;
++
++ for (n = 1; n < (1 << 13) - 1; ++n) {
++ lp_clk = dsi_fclk / 2 / n;
++ if (lp_clk <= lp_clk_req)
++ break;
++ }
++
++ if (n == (1 << 13) - 1) {
++ DSSERR("Failed to find LP_CLK_DIVISOR\n");
++ return -EINVAL;
++ }
++
++ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
++
++ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
++ if (dsi_fclk > 30*1000*1000)
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
++
++ return 0;
++}
++
++
++enum dsi_pll_power_state {
++ DSI_PLL_POWER_OFF = 0x0,
++ DSI_PLL_POWER_ON_HSCLK = 0x1,
++ DSI_PLL_POWER_ON_ALL = 0x2,
++ DSI_PLL_POWER_ON_DIV = 0x3,
++};
++
++static int dsi_pll_power(enum dsi_pll_power_state state)
++{
++ int t = 0;
++
++ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
++
++ /* PLL_PWR_STATUS */
++ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
++ udelay(1);
++ if (t++ > 1000) {
++ DSSERR("Failed to set DSI PLL power mode to %d\n",
++ state);
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
++ struct dsi_clock_info *cinfo)
++{
++ struct dsi_clock_info cur, best;
++ int min_fck_per_pck;
++ int match = 0;
++ unsigned long dss_clk_fck2;
++
++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
++
++ if (req_pck == dsi.cache_req_pck &&
++ dsi.cache_cinfo.clkin == dss_clk_fck2) {
++ DSSDBG("DSI clock info found from cache\n");
++ *cinfo = dsi.cache_cinfo;
++ return 0;
++ }
++
++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
++
++ if (min_fck_per_pck &&
++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
++ DSSERR("Requested pixel clock not possible with the current "
++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
++ "the constraint off.\n");
++ min_fck_per_pck = 0;
++ }
++
++ DSSDBG("dsi_pll_calc\n");
++
++retry:
++ memset(&best, 0, sizeof(best));
++
++ memset(&cur, 0, sizeof(cur));
++ cur.clkin = dss_clk_fck2;
++ cur.use_dss2_fck = 1;
++ cur.highfreq = 0;
++
++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
++ if (cur.highfreq == 0)
++ cur.fint = cur.clkin / cur.regn;
++ else
++ cur.fint = cur.clkin / (2 * cur.regn);
++
++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
++ continue;
++
++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
++ unsigned long a, b;
++
++ a = 2 * cur.regm * (cur.clkin/1000);
++ b = cur.regn * (cur.highfreq + 1);
++ cur.dsiphy = a / b * 1000;
++
++ if (cur.dsiphy > 1800 * 1000 * 1000)
++ break;
++
++ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
++ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
++ ++cur.regm3) {
++ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
++
++ /* this will narrow down the search a bit,
++ * but still give pixclocks below what was
++ * requested */
++ if (cur.dsi1_pll_fclk < req_pck)
++ break;
++
++ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
++ continue;
++
++ if (min_fck_per_pck &&
++ cur.dsi1_pll_fclk <
++ req_pck * min_fck_per_pck)
++ continue;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck,
++ cur.dsi1_pll_fclk,
++ &cur.lck_div,
++ &cur.pck_div);
++
++ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ if (abs(cur.pck - req_pck) <
++ abs(best.pck - req_pck)) {
++ best = cur;
++
++ if (cur.pck == req_pck)
++ goto found;
++ }
++ }
++ }
++ }
++found:
++ if (!match) {
++ if (min_fck_per_pck) {
++ DSSERR("Could not find suitable clock settings.\n"
++ "Turning FCK/PCK constraint off and"
++ "trying again.\n");
++ min_fck_per_pck = 0;
++ goto retry;
++ }
++
++ DSSERR("Could not find suitable clock settings.\n");
++
++ return -EINVAL;
++ }
++
++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
++ best.regm4 = best.dsiphy / 48000000;
++ if (best.regm4 > REGM4_MAX)
++ best.regm4 = REGM4_MAX;
++ else if (best.regm4 == 0)
++ best.regm4 = 1;
++ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
++
++ if (cinfo)
++ *cinfo = best;
++
++ dsi.cache_req_pck = req_pck;
++ dsi.cache_clk_freq = 0;
++ dsi.cache_cinfo = best;
++
++ return 0;
++}
++
++static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
++ struct dsi_clock_info *cinfo)
++{
++ struct dsi_clock_info cur, best;
++ const bool use_dss2_fck = 1;
++ unsigned long datafreq;
++ unsigned long dss_clk_fck2;
++
++ DSSDBG("dsi_pll_calc_ddrfreq\n");
++
++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
++
++ if (clk_freq == dsi.cache_clk_freq &&
++ dsi.cache_cinfo.clkin == dss_clk_fck2) {
++ DSSDBG("DSI clock info found from cache\n");
++ *cinfo = dsi.cache_cinfo;
++ return 0;
++ }
++
++ datafreq = clk_freq * 4;
++
++ memset(&best, 0, sizeof(best));
++
++ memset(&cur, 0, sizeof(cur));
++ cur.use_dss2_fck = use_dss2_fck;
++ if (use_dss2_fck) {
++ cur.clkin = dss_clk_fck2;
++ cur.highfreq = 0;
++ } else {
++ cur.clkin = dispc_pclk_rate();
++ if (cur.clkin < 32000000)
++ cur.highfreq = 0;
++ else
++ cur.highfreq = 1;
++ }
++
++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
++ if (cur.highfreq == 0)
++ cur.fint = cur.clkin / cur.regn;
++ else
++ cur.fint = cur.clkin / (2 * cur.regn);
++
++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
++ continue;
++
++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
++ unsigned long a, b;
++
++ a = 2 * cur.regm * (cur.clkin/1000);
++ b = cur.regn * (cur.highfreq + 1);
++ cur.dsiphy = a / b * 1000;
++
++ if (cur.dsiphy > 1800 * 1000 * 1000)
++ break;
++
++ if (abs(cur.dsiphy - datafreq) <
++ abs(best.dsiphy - datafreq)) {
++ best = cur;
++ /* DSSDBG("best %ld\n", best.dsiphy); */
++ }
++
++ if (cur.dsiphy == datafreq)
++ goto found;
++ }
++ }
++found:
++ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
++ best.regm3 = best.dsiphy / 48000000;
++ if (best.regm3 > REGM3_MAX)
++ best.regm3 = REGM3_MAX;
++ else if (best.regm3 == 0)
++ best.regm3 = 1;
++ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
++
++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
++ best.regm4 = best.dsiphy / 48000000;
++ if (best.regm4 > REGM4_MAX)
++ best.regm4 = REGM4_MAX;
++ else if (best.regm4 == 0)
++ best.regm4 = 1;
++ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
++
++ if (cinfo)
++ *cinfo = best;
++
++ dsi.cache_clk_freq = clk_freq;
++ dsi.cache_req_pck = 0;
++ dsi.cache_cinfo = best;
++
++ return 0;
++}
++
++int dsi_pll_program(struct dsi_clock_info *cinfo)
++{
++ int r = 0;
++ u32 l;
++
++ DSSDBG("dsi_pll_program\n");
++
++ dsi.dsiphy = cinfo->dsiphy;
++ dsi.ddr_clk = dsi.dsiphy / 4;
++ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
++ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
++
++ DSSDBG("DSI Fint %ld\n", cinfo->fint);
++
++ DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
++ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
++ cinfo->clkin,
++ cinfo->highfreq);
++
++ /* DSIPHY == CLKIN4DDR */
++ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
++ cinfo->regm,
++ cinfo->regn,
++ cinfo->clkin,
++ cinfo->highfreq + 1,
++ cinfo->dsiphy);
++
++ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
++ dsi.dsiphy / 1000 / 1000 / 2);
++
++ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
++
++ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
++ cinfo->regm3, cinfo->dsi1_pll_fclk);
++ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
++ cinfo->regm4, cinfo->dsi2_pll_fclk);
++
++ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
++ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
++ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
++ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
++ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
++ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
++ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
++ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
++ /* DSI_PLL_CLKSEL */
++ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
++ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
++ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
++ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
++
++ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
++
++ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
++ DSSERR("dsi pll go bit not going down.\n");
++ r = -EIO;
++ goto err;
++ }
++
++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
++ DSSERR("cannot lock PLL\n");
++ r = -EIO;
++ goto err;
++ }
++
++ dsi.pll_locked = 1;
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
++ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
++ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
++ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
++ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
++ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
++ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
++ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
++ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
++ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
++ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
++ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
++ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
++ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
++
++ DSSDBG("PLL config done\n");
++err:
++ return r;
++}
++
++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
++{
++ int r = 0;
++ enum dsi_pll_power_state pwstate;
++ struct dispc_clock_info cinfo;
++
++ DSSDBG("PLL init\n");
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ /* XXX this should be calculated depending on the screen size,
++ * required framerate and DSI speed.
++ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
++ * with two lanes */
++ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
++ if (r)
++ goto err0;
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r) {
++ DSSERR("Failed to set basic clocks\n");
++ goto err0;
++ }
++
++ r = regulator_enable(dsi.vdds_dsi_reg);
++ if (r)
++ goto err0;
++
++ /* XXX PLL does not come out of reset without this... */
++ dispc_pck_free_enable(1);
++
++ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
++ DSSERR("PLL not coming out of reset.\n");
++ r = -ENODEV;
++ goto err1;
++ }
++
++ /* XXX ... but if left on, we get problems when planes do not
++ * fill the whole display. No idea about this */
++ dispc_pck_free_enable(0);
++
++ if (enable_hsclk && enable_hsdiv)
++ pwstate = DSI_PLL_POWER_ON_ALL;
++ else if (enable_hsclk)
++ pwstate = DSI_PLL_POWER_ON_HSCLK;
++ else if (enable_hsdiv)
++ pwstate = DSI_PLL_POWER_ON_DIV;
++ else
++ pwstate = DSI_PLL_POWER_OFF;
++
++ r = dsi_pll_power(pwstate);
++
++ if (r)
++ goto err1;
++
++ DSSDBG("PLL init done\n");
++
++ return 0;
++err1:
++ regulator_disable(dsi.vdds_dsi_reg);
++err0:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++ return r;
++}
++
++void dsi_pll_uninit(void)
++{
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++
++ dsi.pll_locked = 0;
++ dsi_pll_power(DSI_PLL_POWER_OFF);
++ regulator_disable(dsi.vdds_dsi_reg);
++ DSSDBG("PLL uninit done\n");
++}
++
++unsigned long dsi_get_dsi1_pll_rate(void)
++{
++ return dsi.dsi1_pll_fclk;
++}
++
++unsigned long dsi_get_dsi2_pll_rate(void)
++{
++ return dsi.dsi2_pll_fclk;
++}
++
++void dsi_dump_clocks(struct seq_file *s)
++{
++ int clksel;
++
++ enable_clocks(1);
++
++ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
++
++ seq_printf(s, "- dsi -\n");
++
++ seq_printf(s, "dsi fclk source = %s\n",
++ dss_get_dsi_clk_source() == 0 ?
++ "dss1_alwon_fclk" : "dsi2_pll_fclk");
++
++ seq_printf(s, "dsi pll source = %s\n",
++ clksel == 0 ?
++ "dss2_alwon_fclk" : "pclkfree");
++
++ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
++ dsi.dsiphy, dsi.ddr_clk);
++
++ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n"
++ "dsi2_pll_fck\t%lu (%s)\n",
++ dsi.dsi1_pll_fclk,
++ dss_get_dispc_clk_source() == 0 ? "off" : "on",
++ dsi.dsi2_pll_fclk,
++ dss_get_dsi_clk_source() == 0 ? "off" : "on");
++
++ enable_clocks(0);
++}
++
++void dsi_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DSI_REVISION);
++ DUMPREG(DSI_SYSCONFIG);
++ DUMPREG(DSI_SYSSTATUS);
++ DUMPREG(DSI_IRQSTATUS);
++ DUMPREG(DSI_IRQENABLE);
++ DUMPREG(DSI_CTRL);
++ DUMPREG(DSI_COMPLEXIO_CFG1);
++ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
++ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
++ DUMPREG(DSI_CLK_CTRL);
++ DUMPREG(DSI_TIMING1);
++ DUMPREG(DSI_TIMING2);
++ DUMPREG(DSI_VM_TIMING1);
++ DUMPREG(DSI_VM_TIMING2);
++ DUMPREG(DSI_VM_TIMING3);
++ DUMPREG(DSI_CLK_TIMING);
++ DUMPREG(DSI_TX_FIFO_VC_SIZE);
++ DUMPREG(DSI_RX_FIFO_VC_SIZE);
++ DUMPREG(DSI_COMPLEXIO_CFG2);
++ DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
++ DUMPREG(DSI_VM_TIMING4);
++ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
++ DUMPREG(DSI_VM_TIMING5);
++ DUMPREG(DSI_VM_TIMING6);
++ DUMPREG(DSI_VM_TIMING7);
++ DUMPREG(DSI_STOPCLK_TIMING);
++
++ DUMPREG(DSI_VC_CTRL(0));
++ DUMPREG(DSI_VC_TE(0));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
++ DUMPREG(DSI_VC_IRQSTATUS(0));
++ DUMPREG(DSI_VC_IRQENABLE(0));
++
++ DUMPREG(DSI_VC_CTRL(1));
++ DUMPREG(DSI_VC_TE(1));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
++ DUMPREG(DSI_VC_IRQSTATUS(1));
++ DUMPREG(DSI_VC_IRQENABLE(1));
++
++ DUMPREG(DSI_VC_CTRL(2));
++ DUMPREG(DSI_VC_TE(2));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
++ DUMPREG(DSI_VC_IRQSTATUS(2));
++ DUMPREG(DSI_VC_IRQENABLE(2));
++
++ DUMPREG(DSI_VC_CTRL(3));
++ DUMPREG(DSI_VC_TE(3));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
++ DUMPREG(DSI_VC_IRQSTATUS(3));
++ DUMPREG(DSI_VC_IRQENABLE(3));
++
++ DUMPREG(DSI_DSIPHY_CFG0);
++ DUMPREG(DSI_DSIPHY_CFG1);
++ DUMPREG(DSI_DSIPHY_CFG2);
++ DUMPREG(DSI_DSIPHY_CFG5);
++
++ DUMPREG(DSI_PLL_CONTROL);
++ DUMPREG(DSI_PLL_STATUS);
++ DUMPREG(DSI_PLL_GO);
++ DUMPREG(DSI_PLL_CONFIGURATION1);
++ DUMPREG(DSI_PLL_CONFIGURATION2);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++enum dsi_complexio_power_state {
++ DSI_COMPLEXIO_POWER_OFF = 0x0,
++ DSI_COMPLEXIO_POWER_ON = 0x1,
++ DSI_COMPLEXIO_POWER_ULPS = 0x2,
++};
++
++static int dsi_complexio_power(enum dsi_complexio_power_state state)
++{
++ int t = 0;
++
++ /* PWR_CMD */
++ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
++
++ /* PWR_STATUS */
++ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
++ udelay(1);
++ if (t++ > 1000) {
++ DSSERR("failed to set complexio power state to "
++ "%d\n", state);
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++static void dsi_complexio_config(struct omap_dss_device *dssdev)
++{
++ u32 r;
++
++ int clk_lane = dssdev->phy.dsi.clk_lane;
++ int data1_lane = dssdev->phy.dsi.data1_lane;
++ int data2_lane = dssdev->phy.dsi.data2_lane;
++ int clk_pol = dssdev->phy.dsi.clk_pol;
++ int data1_pol = dssdev->phy.dsi.data1_pol;
++ int data2_pol = dssdev->phy.dsi.data2_pol;
++
++ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
++ r = FLD_MOD(r, clk_lane, 2, 0);
++ r = FLD_MOD(r, clk_pol, 3, 3);
++ r = FLD_MOD(r, data1_lane, 6, 4);
++ r = FLD_MOD(r, data1_pol, 7, 7);
++ r = FLD_MOD(r, data2_lane, 10, 8);
++ r = FLD_MOD(r, data2_pol, 11, 11);
++ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
++
++ /* The configuration of the DSI complex I/O (number of data lanes,
++ position, differential order) should not be changed while
++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
++ the hardware to take into account a new configuration of the complex
++ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
++ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
++ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
++ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
++ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
++ DSI complex I/O configuration is unknown. */
++
++ /*
++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
++ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
++ */
++}
++
++static inline unsigned ns2ddr(unsigned ns)
++{
++ /* convert time in ns to ddr ticks, rounding up */
++ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
++}
++
++static inline unsigned ddr2ns(unsigned ddr)
++{
++ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
++}
++
++static void dsi_complexio_timings(void)
++{
++ u32 r;
++ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
++ u32 tlpx_half, tclk_trail, tclk_zero;
++ u32 tclk_prepare;
++
++ /* calculate timings */
++
++ /* 1 * DDR_CLK = 2 * UI */
++
++ /* min 40ns + 4*UI max 85ns + 6*UI */
++ ths_prepare = ns2ddr(70) + 2;
++
++ /* min 145ns + 10*UI */
++ ths_prepare_ths_zero = ns2ddr(175) + 2;
++
++ /* min max(8*UI, 60ns+4*UI) */
++ ths_trail = ns2ddr(60) + 5;
++
++ /* min 100ns */
++ ths_exit = ns2ddr(145);
++
++ /* tlpx min 50n */
++ tlpx_half = ns2ddr(25);
++
++ /* min 60ns */
++ tclk_trail = ns2ddr(60) + 2;
++
++ /* min 38ns, max 95ns */
++ tclk_prepare = ns2ddr(65);
++
++ /* min tclk-prepare + tclk-zero = 300ns */
++ tclk_zero = ns2ddr(260);
++
++ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
++ ths_prepare, ddr2ns(ths_prepare),
++ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
++ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
++ ths_trail, ddr2ns(ths_trail),
++ ths_exit, ddr2ns(ths_exit));
++
++ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
++ "tclk_zero %u (%uns)\n",
++ tlpx_half, ddr2ns(tlpx_half),
++ tclk_trail, ddr2ns(tclk_trail),
++ tclk_zero, ddr2ns(tclk_zero));
++ DSSDBG("tclk_prepare %u (%uns)\n",
++ tclk_prepare, ddr2ns(tclk_prepare));
++
++ /* program timings */
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG0);
++ r = FLD_MOD(r, ths_prepare, 31, 24);
++ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
++ r = FLD_MOD(r, ths_trail, 15, 8);
++ r = FLD_MOD(r, ths_exit, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG0, r);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG1);
++ r = FLD_MOD(r, tlpx_half, 22, 16);
++ r = FLD_MOD(r, tclk_trail, 15, 8);
++ r = FLD_MOD(r, tclk_zero, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG1, r);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG2);
++ r = FLD_MOD(r, tclk_prepare, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG2, r);
++}
++
++
++static int dsi_complexio_init(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ DSSDBG("dsi_complexio_init\n");
++
++ /* CIO_CLK_ICG, enable L3 clk to CIO */
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
++
++ /* A dummy read using the SCP interface to any DSIPHY register is
++ * required after DSIPHY reset to complete the reset of the DSI complex
++ * I/O. */
++ dsi_read_reg(DSI_DSIPHY_CFG5);
++
++ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
++ DSSERR("ComplexIO PHY not coming out of reset.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ dsi_complexio_config(dssdev);
++
++ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
++
++ if (r)
++ goto err;
++
++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
++ DSSERR("ComplexIO not coming out of reset.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
++ DSSERR("ComplexIO LDO power down.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ dsi_complexio_timings();
++
++ /*
++ The configuration of the DSI complex I/O (number of data lanes,
++ position, differential order) should not be changed while
++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
++ hardware to recognize a new configuration of the complex I/O (done
++ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
++ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
++ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
++ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
++ bit to 1. If the sequence is not followed, the DSi complex I/O
++ configuration is undetermined.
++ */
++ dsi_if_enable(1);
++ dsi_if_enable(0);
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
++ dsi_if_enable(1);
++ dsi_if_enable(0);
++
++ DSSDBG("CIO init done\n");
++err:
++ return r;
++}
++
++static void dsi_complexio_uninit(void)
++{
++ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
++}
++
++static int _dsi_wait_reset(void)
++{
++ int i = 0;
++
++ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
++ if (i++ > 5) {
++ DSSERR("soft reset failed\n");
++ return -ENODEV;
++ }
++ udelay(1);
++ }
++
++ return 0;
++}
++
++static int _dsi_reset(void)
++{
++ /* Soft reset */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
++ return _dsi_wait_reset();
++}
++
++
++static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
++ enum fifo_size size3, enum fifo_size size4)
++{
++ u32 r = 0;
++ int add = 0;
++ int i;
++
++ dsi.vc[0].fifo_size = size1;
++ dsi.vc[1].fifo_size = size2;
++ dsi.vc[2].fifo_size = size3;
++ dsi.vc[3].fifo_size = size4;
++
++ for (i = 0; i < 4; i++) {
++ u8 v;
++ int size = dsi.vc[i].fifo_size;
++
++ if (add + size > 4) {
++ DSSERR("Illegal FIFO configuration\n");
++ BUG();
++ }
++
++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
++ r |= v << (8 * i);
++ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
++ add += size;
++ }
++
++ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
++}
++
++static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
++ enum fifo_size size3, enum fifo_size size4)
++{
++ u32 r = 0;
++ int add = 0;
++ int i;
++
++ dsi.vc[0].fifo_size = size1;
++ dsi.vc[1].fifo_size = size2;
++ dsi.vc[2].fifo_size = size3;
++ dsi.vc[3].fifo_size = size4;
++
++ for (i = 0; i < 4; i++) {
++ u8 v;
++ int size = dsi.vc[i].fifo_size;
++
++ if (add + size > 4) {
++ DSSERR("Illegal FIFO configuration\n");
++ BUG();
++ }
++
++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
++ r |= v << (8 * i);
++ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
++ add += size;
++ }
++
++ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
++}
++
++static int dsi_force_tx_stop_mode_io(void)
++{
++ u32 r;
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
++ DSSERR("TX_STOP bit not going down\n");
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void dsi_vc_print_status(int channel)
++{
++ u32 r;
++
++ r = dsi_read_reg(DSI_VC_CTRL(channel));
++ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
++ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
++ channel,
++ FLD_GET(r, 5, 5),
++ FLD_GET(r, 6, 6),
++ FLD_GET(r, 15, 15),
++ FLD_GET(r, 16, 16),
++ FLD_GET(r, 20, 20));
++
++ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
++ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
++}
++
++static int dsi_vc_enable(int channel, bool enable)
++{
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBG("dsi_vc_enable channel %d, enable %d\n",
++ channel, enable);
++
++ enable = enable ? 1 : 0;
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
++
++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void dsi_vc_initial_config(int channel)
++{
++ u32 r;
++
++ DSSDBGF("%d", channel);
++
++ r = dsi_read_reg(DSI_VC_CTRL(channel));
++
++ if (FLD_GET(r, 15, 15)) /* VC_BUSY */
++ DSSERR("VC(%d) busy when trying to configure it!\n",
++ channel);
++
++ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
++ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
++ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
++ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
++ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
++ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
++ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
++
++ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
++ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
++
++ dsi_write_reg(DSI_VC_CTRL(channel), r);
++
++ dsi.vc[channel].mode = DSI_VC_MODE_L4;
++}
++
++static void dsi_vc_config_l4(int channel)
++{
++ if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
++ return;
++
++ DSSDBGF("%d", channel);
++
++ dsi_vc_enable(channel, 0);
++
++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
++ DSSERR("vc(%d) busy when trying to config for L4\n", channel);
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
++
++ dsi_vc_enable(channel, 1);
++
++ dsi.vc[channel].mode = DSI_VC_MODE_L4;
++}
++
++static void dsi_vc_config_vp(int channel)
++{
++ if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
++ return;
++
++ DSSDBGF("%d", channel);
++
++ dsi_vc_enable(channel, 0);
++
++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
++ DSSERR("vc(%d) busy when trying to config for VP\n", channel);
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
++
++ dsi_vc_enable(channel, 1);
++
++ dsi.vc[channel].mode = DSI_VC_MODE_VP;
++}
++
++
++static void dsi_vc_enable_hs(int channel, bool enable)
++{
++ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
++
++ dsi_vc_enable(channel, 0);
++ dsi_if_enable(0);
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
++
++ dsi_vc_enable(channel, 1);
++ dsi_if_enable(1);
++
++ dsi_force_tx_stop_mode_io();
++}
++
++static void dsi_vc_flush_long_data(int channel)
++{
++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
++ u32 val;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
++ (val >> 0) & 0xff,
++ (val >> 8) & 0xff,
++ (val >> 16) & 0xff,
++ (val >> 24) & 0xff);
++ }
++}
++
++static void dsi_show_rx_ack_with_err(u16 err)
++{
++ DSSERR("\tACK with ERROR (%#x):\n", err);
++ if (err & (1 << 0))
++ DSSERR("\t\tSoT Error\n");
++ if (err & (1 << 1))
++ DSSERR("\t\tSoT Sync Error\n");
++ if (err & (1 << 2))
++ DSSERR("\t\tEoT Sync Error\n");
++ if (err & (1 << 3))
++ DSSERR("\t\tEscape Mode Entry Command Error\n");
++ if (err & (1 << 4))
++ DSSERR("\t\tLP Transmit Sync Error\n");
++ if (err & (1 << 5))
++ DSSERR("\t\tHS Receive Timeout Error\n");
++ if (err & (1 << 6))
++ DSSERR("\t\tFalse Control Error\n");
++ if (err & (1 << 7))
++ DSSERR("\t\t(reserved7)\n");
++ if (err & (1 << 8))
++ DSSERR("\t\tECC Error, single-bit (corrected)\n");
++ if (err & (1 << 9))
++ DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
++ if (err & (1 << 10))
++ DSSERR("\t\tChecksum Error\n");
++ if (err & (1 << 11))
++ DSSERR("\t\tData type not recognized\n");
++ if (err & (1 << 12))
++ DSSERR("\t\tInvalid VC ID\n");
++ if (err & (1 << 13))
++ DSSERR("\t\tInvalid Transmission Length\n");
++ if (err & (1 << 14))
++ DSSERR("\t\t(reserved14)\n");
++ if (err & (1 << 15))
++ DSSERR("\t\tDSI Protocol Violation\n");
++}
++
++static u16 dsi_vc_flush_receive_data(int channel)
++{
++ /* RX_FIFO_NOT_EMPTY */
++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
++ u32 val;
++ u8 dt;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ DSSDBG("\trawval %#08x\n", val);
++ dt = FLD_GET(val, 5, 0);
++ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
++ u16 err = FLD_GET(val, 23, 8);
++ dsi_show_rx_ack_with_err(err);
++ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
++ DSSDBG("\tDCS short response, 1 byte: %#x\n",
++ FLD_GET(val, 23, 8));
++ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
++ DSSDBG("\tDCS short response, 2 byte: %#x\n",
++ FLD_GET(val, 23, 8));
++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
++ DSSDBG("\tDCS long response, len %d\n",
++ FLD_GET(val, 23, 8));
++ dsi_vc_flush_long_data(channel);
++ } else {
++ DSSERR("\tunknown datatype 0x%02x\n", dt);
++ }
++ }
++ return 0;
++}
++
++static int dsi_vc_send_bta(int channel)
++{
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
++ (dsi.debug_write || dsi.debug_read))
++ DSSDBG("dsi_vc_send_bta %d\n", channel);
++
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
++
++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
++ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
++ dsi_vc_flush_receive_data(channel);
++ }
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
++
++ return 0;
++}
++
++int dsi_vc_send_bta_sync(int channel)
++{
++ int r = 0;
++ u32 err;
++
++ INIT_COMPLETION(dsi.bta_completion);
++
++ dsi_vc_enable_bta_irq(channel);
++
++ r = dsi_vc_send_bta(channel);
++ if (r)
++ goto err;
++
++ if (wait_for_completion_timeout(&dsi.bta_completion,
++ msecs_to_jiffies(500)) == 0) {
++ DSSERR("Failed to receive BTA\n");
++ r = -EIO;
++ goto err;
++ }
++
++ err = dsi_get_errors();
++ if (err) {
++ DSSERR("Error while sending BTA: %x\n", err);
++ r = -EIO;
++ goto err;
++ }
++err:
++ dsi_vc_disable_bta_irq(channel);
++
++ return r;
++}
++EXPORT_SYMBOL(dsi_vc_send_bta_sync);
++
++static inline void dsi_vc_write_long_header(int channel, u8 data_type,
++ u16 len, u8 ecc)
++{
++ u32 val;
++ u8 data_id;
++
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
++
++ /*data_id = data_type | channel << 6; */
++ data_id = data_type | dsi.vc[channel].dest_per << 6;
++
++ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
++ FLD_VAL(ecc, 31, 24);
++
++ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
++}
++
++static inline void dsi_vc_write_long_payload(int channel,
++ u8 b1, u8 b2, u8 b3, u8 b4)
++{
++ u32 val;
++
++ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
++
++/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
++ b1, b2, b3, b4, val); */
++
++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
++}
++
++static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
++ u8 ecc)
++{
++ /*u32 val; */
++ int i;
++ u8 *p;
++ int r = 0;
++ u8 b1, b2, b3, b4;
++
++ if (dsi.debug_write)
++ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
++
++ /* len + header */
++ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
++ DSSERR("unable to send long packet: packet too long.\n");
++ return -EINVAL;
++ }
++
++ dsi_vc_config_l4(channel);
++
++ dsi_vc_write_long_header(channel, data_type, len, ecc);
++
++ /*dsi_vc_print_status(0); */
++
++ p = data;
++ for (i = 0; i < len >> 2; i++) {
++ if (dsi.debug_write)
++ DSSDBG("\tsending full packet %d\n", i);
++ /*dsi_vc_print_status(0); */
++
++ b1 = *p++;
++ b2 = *p++;
++ b3 = *p++;
++ b4 = *p++;
++
++ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
++ }
++
++ i = len % 4;
++ if (i) {
++ b1 = 0; b2 = 0; b3 = 0;
++
++ if (dsi.debug_write)
++ DSSDBG("\tsending remainder bytes %d\n", i);
++
++ switch (i) {
++ case 3:
++ b1 = *p++;
++ b2 = *p++;
++ b3 = *p++;
++ break;
++ case 2:
++ b1 = *p++;
++ b2 = *p++;
++ break;
++ case 1:
++ b1 = *p++;
++ break;
++ }
++
++ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
++ }
++
++ return r;
++}
++
++static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
++{
++ u32 r;
++ u8 data_id;
++
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
++
++ if (dsi.debug_write)
++ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
++ channel,
++ data_type, data & 0xff, (data >> 8) & 0xff);
++
++ dsi_vc_config_l4(channel);
++
++ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
++ DSSERR("ERROR FIFO FULL, aborting transfer\n");
++ return -EINVAL;
++ }
++
++ data_id = data_type | channel << 6;
++
++ r = (data_id << 0) | (data << 8) | (ecc << 24);
++
++ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
++
++ return 0;
++}
++
++int dsi_vc_send_null(int channel)
++{
++ u8 nullpkg[] = {0, 0, 0, 0};
++ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
++}
++EXPORT_SYMBOL(dsi_vc_send_null);
++
++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
++{
++ int r;
++
++ BUG_ON(len == 0);
++
++ if (len == 1) {
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
++ data[0], 0);
++ } else if (len == 2) {
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
++ data[0] | (data[1] << 8), 0);
++ } else {
++ /* 0x39 = DCS Long Write */
++ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
++ data, len, 0);
++ }
++
++ return r;
++}
++EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
++
++int dsi_vc_dcs_write(int channel, u8 *data, int len)
++{
++ int r;
++
++ r = dsi_vc_dcs_write_nosync(channel, data, len);
++ if (r)
++ return r;
++
++ r = dsi_vc_send_bta_sync(channel);
++
++ return r;
++}
++EXPORT_SYMBOL(dsi_vc_dcs_write);
++
++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
++{
++ u32 val;
++ u8 dt;
++ int r;
++
++ if (dsi.debug_read)
++ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
++
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
++ if (r)
++ return r;
++
++ r = dsi_vc_send_bta_sync(channel);
++ if (r)
++ return r;
++
++ /* RX_FIFO_NOT_EMPTY */
++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
++ DSSERR("RX fifo empty when trying to read.\n");
++ return -EIO;
++ }
++
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ if (dsi.debug_read)
++ DSSDBG("\theader: %08x\n", val);
++ dt = FLD_GET(val, 5, 0);
++ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
++ u16 err = FLD_GET(val, 23, 8);
++ dsi_show_rx_ack_with_err(err);
++ return -EIO;
++
++ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
++ u8 data = FLD_GET(val, 15, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
++
++ if (buflen < 1)
++ return -EIO;
++
++ buf[0] = data;
++
++ return 1;
++ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
++ u16 data = FLD_GET(val, 23, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
++
++ if (buflen < 2)
++ return -EIO;
++
++ buf[0] = data & 0xff;
++ buf[1] = (data >> 8) & 0xff;
++
++ return 2;
++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
++ int w;
++ int len = FLD_GET(val, 23, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS long response, len %d\n", len);
++
++ if (len > buflen)
++ return -EIO;
++
++ /* two byte checksum ends the packet, not included in len */
++ for (w = 0; w < len + 2;) {
++ int b;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ if (dsi.debug_read)
++ DSSDBG("\t\t%02x %02x %02x %02x\n",
++ (val >> 0) & 0xff,
++ (val >> 8) & 0xff,
++ (val >> 16) & 0xff,
++ (val >> 24) & 0xff);
++
++ for (b = 0; b < 4; ++b) {
++ if (w < len)
++ buf[w] = (val >> (b * 8)) & 0xff;
++ /* we discard the 2 byte checksum */
++ ++w;
++ }
++ }
++
++ return len;
++
++ } else {
++ DSSERR("\tunknown datatype 0x%02x\n", dt);
++ return -EIO;
++ }
++}
++EXPORT_SYMBOL(dsi_vc_dcs_read);
++
++
++int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
++{
++ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
++ len, 0);
++}
++EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
++
++
++static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("LP_TX_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING2);
++ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
++ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
++ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
++ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
++ dsi_write_reg(DSI_TIMING2, r);
++
++ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_ta_timeout(int ns, int x8, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("TA_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
++ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
++ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
++ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ DSSDBG("TA_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_stop_state_counter(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("STOP_STATE_COUNTER_IO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
++ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
++ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
++ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in TxByteClkHS */
++
++ fck = dsi.ddr_clk / 4;
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("HS_TX_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING2);
++ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
++ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
++ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
++ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
++ dsi_write_reg(DSI_TIMING2, r);
++
++ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++static int dsi_proto_config(struct omap_dss_device *dssdev)
++{
++ u32 r;
++ int buswidth = 0;
++ int div;
++
++ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0);
++
++ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0);
++
++ /* XXX what values for the timeouts? */
++ dsi_set_stop_state_counter(1000, 0, 0);
++
++ dsi_set_ta_timeout(50000, 1, 1);
++
++ /* 3000ns * 16 */
++ dsi_set_lp_rx_timeout(3000, 0, 1);
++
++ /* 10000ns * 4 */
++ dsi_set_hs_tx_timeout(10000, 1, 0);
++
++ switch (dssdev->ctrl.pixel_size) {
++ case 16:
++ buswidth = 0;
++ break;
++ case 18:
++ buswidth = 1;
++ break;
++ case 24:
++ buswidth = 2;
++ break;
++ default:
++ BUG();
++ }
++
++ r = dsi_read_reg(DSI_CTRL);
++ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
++ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
++ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
++
++ div = dispc_lclk_rate() / dispc_pclk_rate();
++ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
++ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
++ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
++ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
++ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
++ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
++ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
++ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
++
++ dsi_write_reg(DSI_CTRL, r);
++
++ dsi_vc_initial_config(0);
++
++ /* set all vc targets to peripheral 0 */
++ dsi.vc[0].dest_per = 0;
++ dsi.vc[1].dest_per = 0;
++ dsi.vc[2].dest_per = 0;
++ dsi.vc[3].dest_per = 0;
++
++ return 0;
++}
++
++static void dsi_proto_timings(struct omap_dss_device *dssdev)
++{
++ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
++ unsigned tclk_pre, tclk_post;
++ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
++ unsigned ths_trail, ths_exit;
++ unsigned ddr_clk_pre, ddr_clk_post;
++ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
++ unsigned ths_eot;
++ u32 r;
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG0);
++ ths_prepare = FLD_GET(r, 31, 24);
++ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
++ ths_zero = ths_prepare_ths_zero - ths_prepare;
++ ths_trail = FLD_GET(r, 15, 8);
++ ths_exit = FLD_GET(r, 7, 0);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG1);
++ tlpx = FLD_GET(r, 22, 16) * 2;
++ tclk_trail = FLD_GET(r, 15, 8);
++ tclk_zero = FLD_GET(r, 7, 0);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG2);
++ tclk_prepare = FLD_GET(r, 7, 0);
++
++ /* min 8*UI */
++ tclk_pre = 20;
++ /* min 60ns + 52*UI */
++ tclk_post = ns2ddr(60) + 26;
++
++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
++ if (dssdev->phy.dsi.data1_lane != 0 &&
++ dssdev->phy.dsi.data2_lane != 0)
++ ths_eot = 2;
++ else
++ ths_eot = 4;
++
++ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
++ 4);
++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
++
++ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
++ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
++
++ r = dsi_read_reg(DSI_CLK_TIMING);
++ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
++ r = FLD_MOD(r, ddr_clk_post, 7, 0);
++ dsi_write_reg(DSI_CLK_TIMING, r);
++
++ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
++ ddr_clk_pre,
++ ddr_clk_post);
++
++ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
++ DIV_ROUND_UP(ths_prepare, 4) +
++ DIV_ROUND_UP(ths_zero + 3, 4);
++
++ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
++
++ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
++ FLD_VAL(exit_hs_mode_lat, 15, 0);
++ dsi_write_reg(DSI_VM_TIMING7, r);
++
++ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
++ enter_hs_mode_lat, exit_hs_mode_lat);
++}
++
++
++#define DSI_DECL_VARS \
++ int __dsi_cb = 0; u32 __dsi_cv = 0;
++
++#define DSI_FLUSH(ch) \
++ if (__dsi_cb > 0) { \
++ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
++ __dsi_cb = __dsi_cv = 0; \
++ }
++
++#define DSI_PUSH(ch, data) \
++ do { \
++ __dsi_cv |= (data) << (__dsi_cb * 8); \
++ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
++ if (++__dsi_cb > 3) \
++ DSI_FLUSH(ch); \
++ } while (0)
++
++static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
++ int x, int y, int w, int h)
++{
++ /* Note: supports only 24bit colors in 32bit container */
++ int first = 1;
++ int fifo_stalls = 0;
++ int max_dsi_packet_size;
++ int max_data_per_packet;
++ int max_pixels_per_packet;
++ int pixels_left;
++ int bytespp = dssdev->ctrl.pixel_size / 8;
++ int scr_width;
++ u32 __iomem *data;
++ int start_offset;
++ int horiz_inc;
++ int current_x;
++ struct omap_overlay *ovl;
++
++ debug_irq = 0;
++
++ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
++ x, y, w, h);
++
++ ovl = dssdev->manager->overlays[0];
++
++ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
++ return -EINVAL;
++
++ if (dssdev->ctrl.pixel_size != 24)
++ return -EINVAL;
++
++ scr_width = ovl->info.screen_width;
++ data = ovl->info.vaddr;
++
++ start_offset = scr_width * y + x;
++ horiz_inc = scr_width - w;
++ current_x = x;
++
++ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
++ * in fifo */
++
++ /* When using CPU, max long packet size is TX buffer size */
++ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
++
++ /* we seem to get better perf if we divide the tx fifo to half,
++ and while the other half is being sent, we fill the other half
++ max_dsi_packet_size /= 2; */
++
++ max_data_per_packet = max_dsi_packet_size - 4 - 1;
++
++ max_pixels_per_packet = max_data_per_packet / bytespp;
++
++ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
++
++ pixels_left = w * h;
++
++ DSSDBG("total pixels %d\n", pixels_left);
++
++ data += start_offset;
++
++ while (pixels_left > 0) {
++ /* 0x2c = write_memory_start */
++ /* 0x3c = write_memory_continue */
++ u8 dcs_cmd = first ? 0x2c : 0x3c;
++ int pixels;
++ DSI_DECL_VARS;
++ first = 0;
++
++#if 1
++ /* using fifo not empty */
++ /* TX_FIFO_NOT_EMPTY */
++ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
++ udelay(1);
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#elif 1
++ /* using fifo emptiness */
++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
++ max_dsi_packet_size) {
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#else
++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#endif
++ pixels = min(max_pixels_per_packet, pixels_left);
++
++ pixels_left -= pixels;
++
++ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
++ 1 + pixels * bytespp, 0);
++
++ DSI_PUSH(0, dcs_cmd);
++
++ while (pixels-- > 0) {
++ u32 pix = __raw_readl(data++);
++
++ DSI_PUSH(0, (pix >> 16) & 0xff);
++ DSI_PUSH(0, (pix >> 8) & 0xff);
++ DSI_PUSH(0, (pix >> 0) & 0xff);
++
++ current_x++;
++ if (current_x == x+w) {
++ current_x = x;
++ data += horiz_inc;
++ }
++ }
++
++ DSI_FLUSH(0);
++ }
++
++ return 0;
++}
++
++static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int bytespp = dssdev->ctrl.pixel_size / 8;
++ int len;
++ int total_len;
++ int packet_payload;
++ int packet_len;
++ u32 l;
++ bool use_te_trigger;
++ const int channel = 0;
++
++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
++
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
++ x, y, w, h);
++
++ len = w * h * bytespp;
++
++ /* XXX: one packet could be longer, I think? Line buffer is
++ * 1024 x 24bits, but we have to put DCS cmd there also.
++ * 1023 * 3 should work, but causes strange color effects. */
++ packet_payload = min(w, (u16)1020) * bytespp;
++
++ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
++ total_len = (len / packet_payload) * packet_len;
++
++ if (len % packet_payload)
++ total_len += (len % packet_payload) + 1;
++
++ if (0)
++ dsi_vc_print_status(1);
++
++ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
++ dsi_write_reg(DSI_VC_TE(channel), l);
++
++ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
++
++ if (use_te_trigger)
++ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
++ else
++ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
++ dsi_write_reg(DSI_VC_TE(channel), l);
++
++ /* We put SIDLEMODE to no-idle for the duration of the transfer,
++ * because DSS interrupts are not capable of waking up the CPU and the
++ * framedone interrupt could be delayed for quite a long time. I think
++ * the same goes for any DSS interrupts, but for some reason I have not
++ * seen the problem anywhere else than here.
++ */
++ dispc_disable_sidle();
++
++ dss_start_update(dssdev);
++
++ if (use_te_trigger) {
++ /* disable LP_RX_TO, so that we can receive TE. Time to wait
++ * for TE is longer than the timer allows */
++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
++
++ dsi_vc_send_bta(channel);
++ }
++}
++
++static void dsi_framedone_irq_callback(void *data, u32 mask)
++{
++ /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
++ * turns itself off. However, DSI still has the pixels in its buffers,
++ * and is sending the data.
++ */
++
++ /* SIDLEMODE back to smart-idle */
++ dispc_enable_sidle();
++
++ dsi.framedone_received = true;
++ wake_up(&dsi.waitqueue);
++}
++
++static void dsi_set_update_region(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ spin_lock(&dsi.update_lock);
++ if (dsi.update_region.dirty) {
++ dsi.update_region.x = min(x, dsi.update_region.x);
++ dsi.update_region.y = min(y, dsi.update_region.y);
++ dsi.update_region.w = max(w, dsi.update_region.w);
++ dsi.update_region.h = max(h, dsi.update_region.h);
++ } else {
++ dsi.update_region.x = x;
++ dsi.update_region.y = y;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ }
++
++ dsi.update_region.device = dssdev;
++ dsi.update_region.dirty = true;
++
++ spin_unlock(&dsi.update_lock);
++
++}
++
++static void dsi_start_auto_update(struct omap_dss_device *dssdev)
++{
++ u16 w, h;
++ int i;
++
++ DSSDBG("starting auto update\n");
++
++ /* In automatic mode the overlay settings are applied like on DPI/SDI.
++ * Mark the overlays dirty, so that we get the overlays configured, as
++ * manual mode has left them in bad shape after config partia planes */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++ if (ovl->manager == dssdev->manager)
++ ovl->info_dirty = true;
++ }
++ dssdev->manager->apply(dssdev->manager);
++
++ dssdev->get_resolution(dssdev, &w, &h);
++
++ dsi_set_update_region(dssdev, 0, 0, w, h);
++
++ dsi_perf_mark_start_auto();
++
++ wake_up(&dsi.waitqueue);
++}
++
++static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
++{
++ int r;
++ r = dssdev->driver->enable_te(dssdev, enable);
++ /* XXX for some reason, DSI TE breaks if we don't wait here.
++ * Panel bug? Needs more studying */
++ msleep(100);
++ return r;
++}
++
++static void dsi_handle_framedone(void)
++{
++ int r;
++ const int channel = 0;
++ bool use_te_trigger;
++
++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
++
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBG("FRAMEDONE\n");
++
++ if (use_te_trigger) {
++ /* enable LP_RX_TO again after the TE */
++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++ }
++
++ /* Send BTA after the frame. We need this for the TE to work, as TE
++ * trigger is only sent for BTAs without preceding packet. Thus we need
++ * to BTA after the pixel packets so that next BTA will cause TE
++ * trigger.
++ *
++ * This is not needed when TE is not in use, but we do it anyway to
++ * make sure that the transfer has been completed. It would be more
++ * optimal, but more complex, to wait only just before starting next
++ * transfer. */
++ r = dsi_vc_send_bta_sync(channel);
++ if (r)
++ DSSERR("BTA after framedone failed\n");
++
++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
++ dispc_fake_vsync_irq();
++#endif
++}
++
++static int dsi_update_thread(void *data)
++{
++ unsigned long timeout;
++ struct omap_dss_device *device;
++ u16 x, y, w, h;
++
++ while (1) {
++ bool sched;
++
++ wait_event_interruptible(dsi.waitqueue,
++ dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
++ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
++ dsi.update_region.dirty == true) ||
++ kthread_should_stop());
++
++ if (kthread_should_stop())
++ break;
++
++ dsi_bus_lock();
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
++ kthread_should_stop()) {
++ dsi_bus_unlock();
++ break;
++ }
++
++ dsi_perf_mark_setup();
++
++ if (dsi.update_region.dirty) {
++ spin_lock(&dsi.update_lock);
++ dsi.active_update_region = dsi.update_region;
++ dsi.update_region.dirty = false;
++ spin_unlock(&dsi.update_lock);
++ }
++
++ device = dsi.active_update_region.device;
++ x = dsi.active_update_region.x;
++ y = dsi.active_update_region.y;
++ w = dsi.active_update_region.w;
++ h = dsi.active_update_region.h;
++
++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
++ dss_setup_partial_planes(device,
++ &x, &y, &w, &h);
++#if 1
++ /* XXX there seems to be a bug in this driver
++ * or OMAP hardware. Some updates with certain
++ * widths and x coordinates fail. These widths
++ * are always odd, so "fix" it here for now */
++ if (w & 1) {
++ u16 dw, dh;
++ device->get_resolution(device,
++ &dw, &dh);
++ if (x + w == dw)
++ x &= ~1;
++ ++w;
++
++ dss_setup_partial_planes(device,
++ &x, &y, &w, &h);
++ }
++#endif
++ }
++
++ dispc_set_lcd_size(w, h);
++ }
++
++ if (dsi.active_update_region.dirty) {
++ dsi.active_update_region.dirty = false;
++ /* XXX TODO we don't need to send the coords, if they
++ * are the same that are already programmed to the
++ * panel. That should speed up manual update a bit */
++ device->driver->setup_update(device, x, y, w, h);
++ }
++
++ dsi_perf_mark_start();
++
++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ dsi_vc_config_vp(0);
++
++ if (dsi.te_enabled && dsi.use_ext_te)
++ device->driver->wait_for_te(device);
++
++ dsi.framedone_received = false;
++
++ dsi_update_screen_dispc(device, x, y, w, h);
++
++ /* wait for framedone */
++ timeout = msecs_to_jiffies(1000);
++ timeout = wait_event_timeout(dsi.waitqueue,
++ dsi.framedone_received == true,
++ timeout);
++
++ if (timeout == 0) {
++ DSSERR("framedone timeout\n");
++ DSSERR("failed update %d,%d %dx%d\n",
++ x, y, w, h);
++
++ dispc_enable_sidle();
++ dispc_enable_lcd_out(0);
++ } else {
++ dsi_handle_framedone();
++ dsi_perf_show("DISPC");
++ }
++ } else {
++ dsi_update_screen_l4(device, x, y, w, h);
++ dsi_perf_show("L4");
++ }
++
++ sched = atomic_read(&dsi.bus_lock.count) < 0;
++
++ complete_all(&dsi.update_completion);
++
++ dsi_bus_unlock();
++
++ /* XXX We need to give others chance to get the bus lock. Is
++ * there a better way for this? */
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
++ schedule_timeout_interruptible(1);
++ }
++
++ DSSDBG("update thread exiting\n");
++
++ return 0;
++}
++
++
++
++/* Display funcs */
++
++static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
++{
++ int r;
++
++ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++ if (r) {
++ DSSERR("can't get FRAMEDONE irq\n");
++ return r;
++ }
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
++ dispc_enable_fifohandcheck(1);
++
++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
++
++ {
++ struct omap_video_timings timings = {
++ .hsw = 1,
++ .hfp = 1,
++ .hbp = 1,
++ .vsw = 1,
++ .vfp = 0,
++ .vbp = 0,
++ };
++
++ dispc_set_lcd_timings(&timings);
++ }
++
++ return 0;
++}
++
++static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
++{
++ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++}
++
++static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
++{
++ struct dsi_clock_info cinfo;
++ int r;
++
++ _dsi_print_reset_status();
++
++ r = dsi_pll_init(1, 0);
++ if (r)
++ goto err0;
++
++ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo);
++ if (r)
++ goto err1;
++
++ r = dsi_pll_program(&cinfo);
++ if (r)
++ goto err1;
++
++ DSSDBG("PLL OK\n");
++
++ r = dsi_complexio_init(dssdev);
++ if (r)
++ goto err1;
++
++ _dsi_print_reset_status();
++
++ dsi_proto_timings(dssdev);
++ dsi_set_lp_clk_divisor(dssdev);
++
++ if (1)
++ _dsi_print_reset_status();
++
++ r = dsi_proto_config(dssdev);
++ if (r)
++ goto err2;
++
++ /* enable interface */
++ dsi_vc_enable(0, 1);
++ dsi_if_enable(1);
++ dsi_force_tx_stop_mode_io();
++
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
++ if (r)
++ goto err3;
++ }
++
++ /* enable high-speed after initial config */
++ dsi_vc_enable_hs(0, 1);
++
++ return 0;
++err3:
++ dsi_if_enable(0);
++err2:
++ dsi_complexio_uninit();
++err1:
++ dsi_pll_uninit();
++err0:
++ return r;
++}
++
++static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
++{
++ if (dssdev->driver->disable)
++ dssdev->driver->disable(dssdev);
++
++ dsi_complexio_uninit();
++ dsi_pll_uninit();
++}
++
++static int dsi_core_init(void)
++{
++ /* Autoidle */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
++
++ /* ENWAKEUP */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
++
++ /* SIDLEMODE smart-idle */
++ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
++
++ _dsi_initialize_irq();
++
++ return 0;
++}
++
++static int dsi_display_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ DSSDBG("dsi_display_enable\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("dssdev already enabled\n");
++ r = -EINVAL;
++ goto err1;
++ }
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ r = _dsi_reset();
++ if (r)
++ goto err2;
++
++ dsi_core_init();
++
++ r = dsi_display_init_dispc(dssdev);
++ if (r)
++ goto err2;
++
++ r = dsi_display_init_dsi(dssdev);
++ if (r)
++ goto err3;
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ dsi.use_ext_te = dssdev->phy.dsi.ext_te;
++ r = dsi_set_te(dssdev, dsi.te_enabled);
++ if (r)
++ goto err3;
++
++ dsi.update_mode = dsi.user_update_mode;
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
++
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ return 0;
++
++err3:
++ dsi_display_uninit_dispc(dssdev);
++err2:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++ DSSDBG("dsi_display_enable FAILED\n");
++ return r;
++}
++
++static void dsi_display_disable(struct omap_dss_device *dssdev)
++{
++ DSSDBG("dsi_display_disable\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ goto end;
++
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ dsi_display_uninit_dispc(dssdev);
++
++ dsi_display_uninit_dsi(dssdev);
++
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++
++ omap_dss_stop_device(dssdev);
++end:
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++}
++
++static int dsi_display_suspend(struct omap_dss_device *dssdev)
++{
++ DSSDBG("dsi_display_suspend\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ goto end;
++
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ dsi_display_uninit_dispc(dssdev);
++
++ dsi_display_uninit_dsi(dssdev);
++
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++end:
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ return 0;
++}
++
++static int dsi_display_resume(struct omap_dss_device *dssdev)
++{
++ int r;
++
++ DSSDBG("dsi_display_resume\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
++ DSSERR("dssdev not suspended\n");
++ r = -EINVAL;
++ goto err0;
++ }
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ r = _dsi_reset();
++ if (r)
++ goto err1;
++
++ dsi_core_init();
++
++ r = dsi_display_init_dispc(dssdev);
++ if (r)
++ goto err1;
++
++ r = dsi_display_init_dsi(dssdev);
++ if (r)
++ goto err2;
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ r = dsi_set_te(dssdev, dsi.te_enabled);
++ if (r)
++ goto err2;
++
++ dsi.update_mode = dsi.user_update_mode;
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
++
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ return 0;
++
++err2:
++ dsi_display_uninit_dispc(dssdev);
++err1:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++err0:
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++ DSSDBG("dsi_display_resume FAILED\n");
++ return r;
++}
++
++static int dsi_display_update(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int r = 0;
++ u16 dw, dh;
++
++ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
++
++ mutex_lock(&dsi.lock);
++
++ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
++ goto end;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto end;
++
++ dssdev->get_resolution(dssdev, &dw, &dh);
++
++ if (x > dw || y > dh)
++ goto end;
++
++ if (x + w > dw)
++ w = dw - x;
++
++ if (y + h > dh)
++ h = dh - y;
++
++ if (w == 0 || h == 0)
++ goto end;
++
++ dsi_set_update_region(dssdev, x, y, w, h);
++
++ wake_up(&dsi.waitqueue);
++
++end:
++ mutex_unlock(&dsi.lock);
++
++ return r;
++}
++
++static int dsi_display_sync(struct omap_dss_device *dssdev)
++{
++ bool wait;
++
++ DSSDBG("dsi_display_sync()\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
++ dsi.update_region.dirty) {
++ INIT_COMPLETION(dsi.update_completion);
++ wait = true;
++ } else {
++ wait = false;
++ }
++
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ if (wait)
++ wait_for_completion_interruptible(&dsi.update_completion);
++
++ DSSDBG("dsi_display_sync() done\n");
++ return 0;
++}
++
++static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
++ enum omap_dss_update_mode mode)
++{
++ DSSDBGF("%d", mode);
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dsi.update_mode != mode) {
++ dsi.user_update_mode = mode;
++ dsi.update_mode = mode;
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
++ mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
++ }
++
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ return 0;
++}
++
++static enum omap_dss_update_mode dsi_display_get_update_mode(
++ struct omap_dss_device *dssdev)
++{
++ return dsi.update_mode;
++}
++
++
++static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
++{
++ int r = 0;
++
++ DSSDBGF("%d", enable);
++
++ if (!dssdev->driver->enable_te)
++ return -ENOENT;
++
++ dsi_bus_lock();
++
++ dsi.te_enabled = enable;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto end;
++
++ r = dsi_set_te(dssdev, enable);
++end:
++ dsi_bus_unlock();
++
++ return r;
++}
++
++static int dsi_display_get_te(struct omap_dss_device *dssdev)
++{
++ return dsi.te_enabled;
++}
++
++static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
++{
++
++ DSSDBGF("%d", rotate);
++
++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
++ return -EINVAL;
++
++ dsi_bus_lock();
++ dssdev->driver->set_rotate(dssdev, rotate);
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
++ u16 w, h;
++ /* the display dimensions may have changed, so set a new
++ * update region */
++ dssdev->get_resolution(dssdev, &w, &h);
++ dsi_set_update_region(dssdev, 0, 0, w, h);
++ }
++ dsi_bus_unlock();
++
++ return 0;
++}
++
++static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
++{
++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
++ return 0;
++
++ return dssdev->driver->get_rotate(dssdev);
++}
++
++static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
++{
++ DSSDBGF("%d", mirror);
++
++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
++ return -EINVAL;
++
++ dsi_bus_lock();
++ dssdev->driver->set_mirror(dssdev, mirror);
++ dsi_bus_unlock();
++
++ return 0;
++}
++
++static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
++{
++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
++ return 0;
++
++ return dssdev->driver->get_mirror(dssdev);
++}
++
++static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
++{
++ int r;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EIO;
++
++ DSSDBGF("%d", test_num);
++
++ dsi_bus_lock();
++
++ /* run test first in low speed mode */
++ dsi_vc_enable_hs(0, 0);
++
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test_num);
++ if (r)
++ goto end;
++ }
++
++ /* then in high speed */
++ dsi_vc_enable_hs(0, 1);
++
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test_num);
++ if (r)
++ goto end;
++ }
++
++end:
++ dsi_vc_enable_hs(0, 1);
++
++ dsi_bus_unlock();
++
++ return r;
++}
++
++static int dsi_display_memory_read(struct omap_dss_device *dssdev,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int r;
++
++ DSSDBGF("");
++
++ if (!dssdev->driver->memory_read)
++ return -EINVAL;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EIO;
++
++ dsi_bus_lock();
++
++ r = dssdev->driver->memory_read(dssdev, buf, size,
++ x, y, w, h);
++
++ dsi_bus_unlock();
++
++ return r;
++}
++
++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high)
++{
++ unsigned burst_size_bytes;
++
++ *burst_size = OMAP_DSS_BURST_16x32;
++ burst_size_bytes = 16 * 32 / 8;
++
++ *fifo_high = fifo_size - burst_size_bytes;
++ *fifo_low = 0;
++}
++
++int dsi_init_display(struct omap_dss_device *dssdev)
++{
++ DSSDBG("DSI init\n");
++
++ dssdev->enable = dsi_display_enable;
++ dssdev->disable = dsi_display_disable;
++ dssdev->suspend = dsi_display_suspend;
++ dssdev->resume = dsi_display_resume;
++ dssdev->update = dsi_display_update;
++ dssdev->sync = dsi_display_sync;
++ dssdev->set_update_mode = dsi_display_set_update_mode;
++ dssdev->get_update_mode = dsi_display_get_update_mode;
++ dssdev->enable_te = dsi_display_enable_te;
++ dssdev->get_te = dsi_display_get_te;
++
++ dssdev->get_rotate = dsi_display_get_rotate;
++ dssdev->set_rotate = dsi_display_set_rotate;
++
++ dssdev->get_mirror = dsi_display_get_mirror;
++ dssdev->set_mirror = dsi_display_set_mirror;
++
++ dssdev->run_test = dsi_display_run_test;
++ dssdev->memory_read = dsi_display_memory_read;
++
++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ dsi.vc[0].dssdev = dssdev;
++ dsi.vc[1].dssdev = dssdev;
++
++ return 0;
++}
++
++int dsi_init(struct platform_device *pdev)
++{
++ u32 rev;
++ struct sched_param param = {
++ .sched_priority = MAX_USER_RT_PRIO-1
++ };
++
++ spin_lock_init(&dsi.errors_lock);
++ dsi.errors = 0;
++
++ /* XXX fail properly */
++
++ init_completion(&dsi.bta_completion);
++ init_completion(&dsi.update_completion);
++
++ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
++ if (IS_ERR(dsi.thread)) {
++ DSSERR("cannot create kthread\n");
++ return PTR_ERR(dsi.thread);
++ }
++ sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
++
++ init_waitqueue_head(&dsi.waitqueue);
++ spin_lock_init(&dsi.update_lock);
++
++ mutex_init(&dsi.lock);
++ mutex_init(&dsi.bus_lock);
++
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
++ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
++
++ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
++ if (!dsi.base) {
++ DSSERR("can't ioremap DSI\n");
++ return -ENOMEM;
++ }
++
++ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
++ if (IS_ERR(dsi.vdds_dsi_reg)) {
++ iounmap(dsi.base);
++ DSSERR("can't get VDDS_DSI regulator\n");
++ return PTR_ERR(dsi.vdds_dsi_reg);
++ }
++
++ enable_clocks(1);
++
++ rev = dsi_read_reg(DSI_REVISION);
++ printk(KERN_INFO "OMAP DSI rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ enable_clocks(0);
++
++ wake_up_process(dsi.thread);
++
++ return 0;
++}
++
++void dsi_exit(void)
++{
++ kthread_stop(dsi.thread);
++
++ regulator_put(dsi.vdds_dsi_reg);
++
++ iounmap(dsi.base);
++
++ DSSDBG("omap_dsi_exit\n");
++}
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch
new file mode 100644
index 0000000000..a3ccb7499c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch
@@ -0,0 +1,3801 @@
+From 13656d59fba28e21311ae0478b6c222339367e72 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 4 Aug 2009 16:12:50 +0300
+Subject: [PATCH 15/18] OMAP: DSS2: omapfb driver
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/fb.c | 39 +-
+ drivers/video/omap/Kconfig | 5 +-
+ drivers/video/omap2/Kconfig | 1 +
+ drivers/video/omap2/Makefile | 1 +
+ drivers/video/omap2/omapfb/Kconfig | 37 +
+ drivers/video/omap2/omapfb/Makefile | 2 +
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 727 ++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c | 2137 +++++++++++++++++++++++++++++
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 507 +++++++
+ drivers/video/omap2/omapfb/omapfb.h | 146 ++
+ include/linux/omapfb.h | 45 +
+ 11 files changed, 3644 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/video/omap2/omapfb/Kconfig
+ create mode 100644 drivers/video/omap2/omapfb/Makefile
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-ioctl.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-main.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-sysfs.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb.h
+
+diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
+index 40615a6..70fbeae 100644
+--- a/arch/arm/plat-omap/fb.c
++++ b/arch/arm/plat-omap/fb.c
+@@ -327,7 +327,33 @@ static inline int omap_init_fb(void)
+
+ arch_initcall(omap_init_fb);
+
+-#else
++#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
++
++static u64 omap_fb_dma_mask = ~(u32)0;
++static struct omapfb_platform_data omapfb_config;
++
++static struct platform_device omap_fb_device = {
++ .name = "omapfb",
++ .id = -1,
++ .dev = {
++ .dma_mask = &omap_fb_dma_mask,
++ .coherent_dma_mask = ~(u32)0,
++ .platform_data = &omapfb_config,
++ },
++ .num_resources = 0,
++};
++
++void omapfb_set_platform_data(struct omapfb_platform_data *data)
++{
++ omapfb_config = *data;
++}
++
++static inline int omap_init_fb(void)
++{
++ return platform_device_register(&omap_fb_device);
++}
++
++arch_initcall(omap_init_fb);
+
+ void omapfb_reserve_sdram(void) {}
+ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+@@ -339,5 +365,16 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+ return 0;
+ }
+
++#else
++
++void omapfb_reserve_sdram(void) {}
++unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long start_avail,
++ unsigned long size_avail)
++{
++ return 0;
++}
+
+ #endif
+diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
+index 4440885..0c8f3a5 100644
+--- a/drivers/video/omap/Kconfig
++++ b/drivers/video/omap/Kconfig
+@@ -1,6 +1,7 @@
+ config FB_OMAP
+ tristate "OMAP frame buffer support (EXPERIMENTAL)"
+- depends on FB && ARCH_OMAP
++ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
++
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+@@ -9,7 +10,7 @@ config FB_OMAP
+
+ config FB_OMAP_BOOTLOADER_INIT
+ bool "Check bootloader initialization"
+- depends on FB_OMAP
++ depends on FB_OMAP || FB_OMAP2
+ help
+ Say Y here if you want to enable checking if the bootloader has
+ already initialized the display controller. In this case the
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+index 55b4c42..3e60d7e 100644
+--- a/drivers/video/omap2/Kconfig
++++ b/drivers/video/omap2/Kconfig
+@@ -5,3 +5,4 @@ config OMAP2_VRFB
+ bool
+
+ source "drivers/video/omap2/dss/Kconfig"
++source "drivers/video/omap2/omapfb/Kconfig"
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+index ee0644f..3ba6ef5 100644
+--- a/drivers/video/omap2/Makefile
++++ b/drivers/video/omap2/Makefile
+@@ -2,3 +2,4 @@ obj-$(CONFIG_OMAP2_VRAM) += vram.o
+ obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
+
+ obj-y += dss/
++obj-y += omapfb/
+diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
+new file mode 100644
+index 0000000..bb694cc
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/Kconfig
+@@ -0,0 +1,37 @@
++menuconfig FB_OMAP2
++ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
++ depends on FB && OMAP2_DSS
++
++ select OMAP2_VRAM
++ select OMAP2_VRFB
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ help
++ Frame buffer driver for OMAP2/3 based boards.
++
++config FB_OMAP2_DEBUG_SUPPORT
++ bool "Debug support for OMAP2/3 FB"
++ default y
++ depends on FB_OMAP2
++ help
++ Support for debug output. You have to enable the actual printing
++ with debug module parameter.
++
++config FB_OMAP2_FORCE_AUTO_UPDATE
++ bool "Force main display to automatic update mode"
++ depends on FB_OMAP2
++ help
++ Forces main display to automatic update mode (if possible),
++ and also enables tearsync (if possible). By default
++ displays that support manual update are started in manual
++ update mode.
++
++config FB_OMAP2_NUM_FBS
++ int "Number of framebuffers"
++ range 1 10
++ default 3
++ depends on FB_OMAP2
++ help
++ Select the number of framebuffers created. OMAP2/3 has 3 overlays
++ so normally this would be 3.
+diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
+new file mode 100644
+index 0000000..51c2e00
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_FB_OMAP2) += omapfb.o
++omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+new file mode 100644
+index 0000000..70fb64e
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -0,0 +1,727 @@
++/*
++ * linux/drivers/video/omap2/omapfb-ioctl.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/fb.h>
++#include <linux/device.h>
++#include <linux/uaccess.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/omapfb.h>
++#include <linux/vmalloc.h>
++
++#include <mach/display.h>
++#include <mach/vrfb.h>
++#include <mach/vram.h>
++
++#include "omapfb.h"
++
++static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_dss_device *display = fb2display(fbi);
++ struct omap_overlay *ovl;
++ struct omap_overlay_info info;
++ int r = 0;
++
++ DBG("omapfb_setup_plane\n");
++
++ if (ofbi->num_overlays != 1) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ /* XXX uses only the first overlay */
++ ovl = ofbi->overlays[0];
++
++ if (pi->enabled && !ofbi->region.size) {
++ /*
++ * This plane's memory was freed, can't enable it
++ * until it's reallocated.
++ */
++ r = -EINVAL;
++ goto out;
++ }
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.pos_x = pi->pos_x;
++ info.pos_y = pi->pos_y;
++ info.out_width = pi->out_width;
++ info.out_height = pi->out_height;
++ info.enabled = pi->enabled;
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ goto out;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ goto out;
++ }
++
++ if (display) {
++ u16 w, h;
++
++ if (display->sync)
++ display->sync(display);
++
++ display->get_resolution(display, &w, &h);
++
++ if (display->update)
++ display->update(display, 0, 0, w, h);
++ }
++
++out:
++ if (r)
++ dev_err(fbdev->dev, "setup_plane failed\n");
++ return r;
++}
++
++static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ if (ofbi->num_overlays != 1) {
++ memset(pi, 0, sizeof(*pi));
++ } else {
++ struct omap_overlay_info *ovli;
++ struct omap_overlay *ovl;
++
++ ovl = ofbi->overlays[0];
++ ovli = &ovl->info;
++
++ pi->pos_x = ovli->pos_x;
++ pi->pos_y = ovli->pos_y;
++ pi->enabled = ovli->enabled;
++ pi->channel_out = 0; /* xxx */
++ pi->mirror = 0;
++ pi->out_width = ovli->out_width;
++ pi->out_height = ovli->out_height;
++ }
++
++ return 0;
++}
++
++static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++ int r, i;
++ size_t size;
++
++ if (mi->type > OMAPFB_MEMTYPE_MAX)
++ return -EINVAL;
++
++ size = PAGE_ALIGN(mi->size);
++
++ rg = &ofbi->region;
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->info.enabled)
++ return -EBUSY;
++ }
++
++ if (rg->size != size || rg->type != mi->type) {
++ r = omapfb_realloc_fbmem(fbi, size, mi->type);
++ if (r) {
++ dev_err(fbdev->dev, "realloc fbmem failed\n");
++ return r;
++ }
++ }
++
++ return 0;
++}
++
++static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_mem_region *rg;
++
++ rg = &ofbi->region;
++ memset(mi, 0, sizeof(*mi));
++
++ mi->size = rg->size;
++ mi->type = rg->type;
++
++ return 0;
++}
++
++static int omapfb_update_window(struct fb_info *fbi,
++ u32 x, u32 y, u32 w, u32 h)
++{
++ struct omap_dss_device *display = fb2display(fbi);
++ u16 dw, dh;
++
++ if (!display)
++ return 0;
++
++ if (w == 0 || h == 0)
++ return 0;
++
++ display->get_resolution(display, &dw, &dh);
++
++ if (x + w > dw || y + h > dh)
++ return -EINVAL;
++
++ display->update(display, x, y, w, h);
++
++ return 0;
++}
++
++static int omapfb_set_update_mode(struct fb_info *fbi,
++ enum omapfb_update_mode mode)
++{
++ struct omap_dss_device *display = fb2display(fbi);
++ enum omap_dss_update_mode um;
++ int r;
++
++ if (!display || !display->set_update_mode)
++ return -EINVAL;
++
++ switch (mode) {
++ case OMAPFB_UPDATE_DISABLED:
++ um = OMAP_DSS_UPDATE_DISABLED;
++ break;
++
++ case OMAPFB_AUTO_UPDATE:
++ um = OMAP_DSS_UPDATE_AUTO;
++ break;
++
++ case OMAPFB_MANUAL_UPDATE:
++ um = OMAP_DSS_UPDATE_MANUAL;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ r = display->set_update_mode(display, um);
++
++ return r;
++}
++
++static int omapfb_get_update_mode(struct fb_info *fbi,
++ enum omapfb_update_mode *mode)
++{
++ struct omap_dss_device *display = fb2display(fbi);
++ enum omap_dss_update_mode m;
++
++ if (!display || !display->get_update_mode)
++ return -EINVAL;
++
++ m = display->get_update_mode(display);
++
++ switch (m) {
++ case OMAP_DSS_UPDATE_DISABLED:
++ *mode = OMAPFB_UPDATE_DISABLED;
++ break;
++ case OMAP_DSS_UPDATE_AUTO:
++ *mode = OMAPFB_AUTO_UPDATE;
++ break;
++ case OMAP_DSS_UPDATE_MANUAL:
++ *mode = OMAPFB_MANUAL_UPDATE;
++ break;
++ default:
++ BUG();
++ }
++
++ return 0;
++}
++
++/* XXX this color key handling is a hack... */
++static struct omapfb_color_key omapfb_color_keys[2];
++
++static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
++ struct omapfb_color_key *ck)
++{
++ struct omap_overlay_manager_info info;
++ enum omap_dss_trans_key_type kt;
++ int r;
++
++ mgr->get_manager_info(mgr, &info);
++
++ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
++ info.trans_enabled = false;
++ omapfb_color_keys[mgr->id] = *ck;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++
++ return r;
++ }
++
++ switch (ck->key_type) {
++ case OMAPFB_COLOR_KEY_GFX_DST:
++ kt = OMAP_DSS_COLOR_KEY_GFX_DST;
++ break;
++ case OMAPFB_COLOR_KEY_VID_SRC:
++ kt = OMAP_DSS_COLOR_KEY_VID_SRC;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ info.default_color = ck->background;
++ info.trans_key = ck->trans_key;
++ info.trans_key_type = kt;
++ info.trans_enabled = true;
++
++ omapfb_color_keys[mgr->id] = *ck;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++
++ return r;
++}
++
++static int omapfb_set_color_key(struct fb_info *fbi,
++ struct omapfb_color_key *ck)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ int r;
++ int i;
++ struct omap_overlay_manager *mgr = NULL;
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager) {
++ mgr = ofbi->overlays[i]->manager;
++ break;
++ }
++ }
++
++ if (!mgr) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ r = _omapfb_set_color_key(mgr, ck);
++err:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_get_color_key(struct fb_info *fbi,
++ struct omapfb_color_key *ck)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_overlay_manager *mgr = NULL;
++ int r = 0;
++ int i;
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager) {
++ mgr = ofbi->overlays[i]->manager;
++ break;
++ }
++ }
++
++ if (!mgr) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ *ck = omapfb_color_keys[mgr->id];
++err:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_memory_read(struct fb_info *fbi,
++ struct omapfb_memory_read *mr)
++{
++ struct omap_dss_device *display = fb2display(fbi);
++ void *buf;
++ int r;
++
++ if (!display || !display->memory_read)
++ return -ENOENT;
++
++ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
++ return -EFAULT;
++
++ if (mr->w * mr->h * 3 > mr->buffer_size)
++ return -EINVAL;
++
++ buf = vmalloc(mr->buffer_size);
++ if (!buf) {
++ DBG("vmalloc failed\n");
++ return -ENOMEM;
++ }
++
++ r = display->memory_read(display, buf, mr->buffer_size,
++ mr->x, mr->y, mr->w, mr->h);
++
++ if (r > 0) {
++ if (copy_to_user(mr->buffer, buf, mr->buffer_size))
++ r = -EFAULT;
++ }
++
++ vfree(buf);
++
++ return r;
++}
++
++static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
++ struct omapfb_ovl_colormode *mode)
++{
++ int ovl_idx = mode->overlay_idx;
++ int mode_idx = mode->mode_idx;
++ struct omap_overlay *ovl;
++ enum omap_color_mode supported_modes;
++ struct fb_var_screeninfo var;
++ int i;
++
++ if (ovl_idx >= fbdev->num_overlays)
++ return -ENODEV;
++ ovl = fbdev->overlays[ovl_idx];
++ supported_modes = ovl->supported_modes;
++
++ mode_idx = mode->mode_idx;
++
++ for (i = 0; i < sizeof(supported_modes) * 8; i++) {
++ if (!(supported_modes & (1 << i)))
++ continue;
++ /*
++ * It's possible that the FB doesn't support a mode
++ * that is supported by the overlay, so call the
++ * following here.
++ */
++ if (dss_mode_to_fb_mode(1 << i, &var) < 0)
++ continue;
++
++ mode_idx--;
++ if (mode_idx < 0)
++ break;
++ }
++
++ if (i == sizeof(supported_modes) * 8)
++ return -ENOENT;
++
++ mode->bits_per_pixel = var.bits_per_pixel;
++ mode->nonstd = var.nonstd;
++ mode->red = var.red;
++ mode->green = var.green;
++ mode->blue = var.blue;
++ mode->transp = var.transp;
++
++ return 0;
++}
++
++static int omapfb_wait_for_go(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int r = 0;
++ int i;
++
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ struct omap_overlay *ovl = ofbi->overlays[i];
++ r = ovl->wait_for_go(ovl);
++ if (r)
++ break;
++ }
++
++ return r;
++}
++
++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_dss_device *display = fb2display(fbi);
++
++ union {
++ struct omapfb_update_window_old uwnd_o;
++ struct omapfb_update_window uwnd;
++ struct omapfb_plane_info plane_info;
++ struct omapfb_caps caps;
++ struct omapfb_mem_info mem_info;
++ struct omapfb_color_key color_key;
++ struct omapfb_ovl_colormode ovl_colormode;
++ enum omapfb_update_mode update_mode;
++ int test_num;
++ struct omapfb_memory_read memory_read;
++ struct omapfb_vram_info vram_info;
++ } p;
++
++ int r = 0;
++
++ switch (cmd) {
++ case OMAPFB_SYNC_GFX:
++ DBG("ioctl SYNC_GFX\n");
++ if (!display || !display->sync) {
++ /* DSS1 never returns an error here, so we neither */
++ /*r = -EINVAL;*/
++ break;
++ }
++
++ r = display->sync(display);
++ break;
++
++ case OMAPFB_UPDATE_WINDOW_OLD:
++ DBG("ioctl UPDATE_WINDOW_OLD\n");
++ if (!display || !display->update) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&p.uwnd_o,
++ (void __user *)arg,
++ sizeof(p.uwnd_o))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
++ p.uwnd_o.width, p.uwnd_o.height);
++ break;
++
++ case OMAPFB_UPDATE_WINDOW:
++ DBG("ioctl UPDATE_WINDOW\n");
++ if (!display || !display->update) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&p.uwnd, (void __user *)arg,
++ sizeof(p.uwnd))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
++ p.uwnd.width, p.uwnd.height);
++ break;
++
++ case OMAPFB_SETUP_PLANE:
++ DBG("ioctl SETUP_PLANE\n");
++ if (copy_from_user(&p.plane_info, (void __user *)arg,
++ sizeof(p.plane_info)))
++ r = -EFAULT;
++ else
++ r = omapfb_setup_plane(fbi, &p.plane_info);
++ break;
++
++ case OMAPFB_QUERY_PLANE:
++ DBG("ioctl QUERY_PLANE\n");
++ r = omapfb_query_plane(fbi, &p.plane_info);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.plane_info,
++ sizeof(p.plane_info)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SETUP_MEM:
++ DBG("ioctl SETUP_MEM\n");
++ if (copy_from_user(&p.mem_info, (void __user *)arg,
++ sizeof(p.mem_info)))
++ r = -EFAULT;
++ else
++ r = omapfb_setup_mem(fbi, &p.mem_info);
++ break;
++
++ case OMAPFB_QUERY_MEM:
++ DBG("ioctl QUERY_MEM\n");
++ r = omapfb_query_mem(fbi, &p.mem_info);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.mem_info,
++ sizeof(p.mem_info)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_GET_CAPS:
++ DBG("ioctl GET_CAPS\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ memset(&p.caps, 0, sizeof(p.caps));
++ p.caps.ctrl = display->caps;
++
++ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_GET_OVERLAY_COLORMODE:
++ DBG("ioctl GET_OVERLAY_COLORMODE\n");
++ if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
++ sizeof(p.ovl_colormode))) {
++ r = -EFAULT;
++ break;
++ }
++ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.ovl_colormode,
++ sizeof(p.ovl_colormode)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SET_UPDATE_MODE:
++ DBG("ioctl SET_UPDATE_MODE\n");
++ if (get_user(p.update_mode, (int __user *)arg))
++ r = -EFAULT;
++ else
++ r = omapfb_set_update_mode(fbi, p.update_mode);
++ break;
++
++ case OMAPFB_GET_UPDATE_MODE:
++ DBG("ioctl GET_UPDATE_MODE\n");
++ r = omapfb_get_update_mode(fbi, &p.update_mode);
++ if (r)
++ break;
++ if (put_user(p.update_mode,
++ (enum omapfb_update_mode __user *)arg))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SET_COLOR_KEY:
++ DBG("ioctl SET_COLOR_KEY\n");
++ if (copy_from_user(&p.color_key, (void __user *)arg,
++ sizeof(p.color_key)))
++ r = -EFAULT;
++ else
++ r = omapfb_set_color_key(fbi, &p.color_key);
++ break;
++
++ case OMAPFB_GET_COLOR_KEY:
++ DBG("ioctl GET_COLOR_KEY\n");
++ r = omapfb_get_color_key(fbi, &p.color_key);
++ if (r)
++ break;
++ if (copy_to_user((void __user *)arg, &p.color_key,
++ sizeof(p.color_key)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_WAITFORVSYNC:
++ DBG("ioctl WAITFORVSYNC\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->wait_vsync(display);
++ break;
++
++ case OMAPFB_WAITFORGO:
++ DBG("ioctl WAITFORGO\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = omapfb_wait_for_go(fbi);
++ break;
++
++ /* LCD and CTRL tests do the same thing for backward
++ * compatibility */
++ case OMAPFB_LCD_TEST:
++ DBG("ioctl LCD_TEST\n");
++ if (get_user(p.test_num, (int __user *)arg)) {
++ r = -EFAULT;
++ break;
++ }
++ if (!display || !display->run_test) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->run_test(display, p.test_num);
++
++ break;
++
++ case OMAPFB_CTRL_TEST:
++ DBG("ioctl CTRL_TEST\n");
++ if (get_user(p.test_num, (int __user *)arg)) {
++ r = -EFAULT;
++ break;
++ }
++ if (!display || !display->run_test) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->run_test(display, p.test_num);
++
++ break;
++
++ case OMAPFB_MEMORY_READ:
++ DBG("ioctl MEMORY_READ\n");
++
++ if (copy_from_user(&p.memory_read, (void __user *)arg,
++ sizeof(p.memory_read))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_memory_read(fbi, &p.memory_read);
++
++ break;
++
++ case OMAPFB_GET_VRAM_INFO: {
++ unsigned long vram, free, largest;
++
++ DBG("ioctl GET_VRAM_INFO\n");
++
++ omap_vram_get_info(&vram, &free, &largest);
++ p.vram_info.total = vram;
++ p.vram_info.free = free;
++ p.vram_info.largest_free_block = largest;
++
++ if (copy_to_user((void __user *)arg, &p.vram_info,
++ sizeof(p.vram_info)))
++ r = -EFAULT;
++ break;
++ }
++
++ default:
++ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
++ r = -EINVAL;
++ }
++
++ if (r < 0)
++ DBG("ioctl failed: %d\n", r);
++
++ return r;
++}
++
++
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+new file mode 100644
+index 0000000..7f5ec3b
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -0,0 +1,2137 @@
++/*
++ * linux/drivers/video/omap2/omapfb-main.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/omapfb.h>
++
++#include <mach/display.h>
++#include <mach/vram.h>
++#include <mach/vrfb.h>
++
++#include "omapfb.h"
++
++#define MODULE_NAME "omapfb"
++
++#define OMAPFB_PLANE_XRES_MIN 8
++#define OMAPFB_PLANE_YRES_MIN 8
++
++static char *def_mode;
++static char *def_vram;
++static int def_vrfb;
++static int def_rotate;
++static int def_mirror;
++
++#ifdef DEBUG
++unsigned int omapfb_debug;
++module_param_named(debug, omapfb_debug, bool, 0644);
++static unsigned int omapfb_test_pattern;
++module_param_named(test, omapfb_test_pattern, bool, 0644);
++#endif
++
++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
++
++#ifdef DEBUG
++static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ void __iomem *addr = fbi->screen_base;
++ const unsigned bytespp = var->bits_per_pixel >> 3;
++ const unsigned line_len = fix->line_length / bytespp;
++
++ int r = (color >> 16) & 0xff;
++ int g = (color >> 8) & 0xff;
++ int b = (color >> 0) & 0xff;
++
++ if (var->bits_per_pixel == 16) {
++ u16 __iomem *p = (u16 __iomem *)addr;
++ p += y * line_len + x;
++
++ r = r * 32 / 256;
++ g = g * 64 / 256;
++ b = b * 32 / 256;
++
++ __raw_writew((r << 11) | (g << 5) | (b << 0), p);
++ } else if (var->bits_per_pixel == 24) {
++ u8 __iomem *p = (u8 __iomem *)addr;
++ p += (y * line_len + x) * 3;
++
++ __raw_writeb(b, p + 0);
++ __raw_writeb(g, p + 1);
++ __raw_writeb(r, p + 2);
++ } else if (var->bits_per_pixel == 32) {
++ u32 __iomem *p = (u32 __iomem *)addr;
++ p += y * line_len + x;
++ __raw_writel(color, p);
++ }
++}
++
++static void fill_fb(struct fb_info *fbi)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ const short w = var->xres_virtual;
++ const short h = var->yres_virtual;
++ void __iomem *addr = fbi->screen_base;
++ int y, x;
++
++ if (!addr)
++ return;
++
++ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
++
++ for (y = 0; y < h; y++) {
++ for (x = 0; x < w; x++) {
++ if (x < 20 && y < 20)
++ draw_pixel(fbi, x, y, 0xffffff);
++ else if (x < 20 && (y > 20 && y < h - 20))
++ draw_pixel(fbi, x, y, 0xff);
++ else if (y < 20 && (x > 20 && x < w - 20))
++ draw_pixel(fbi, x, y, 0xff00);
++ else if (x > w - 20 && (y > 20 && y < h - 20))
++ draw_pixel(fbi, x, y, 0xff0000);
++ else if (y > h - 20 && (x > 20 && x < w - 20))
++ draw_pixel(fbi, x, y, 0xffff00);
++ else if (x == 20 || x == w - 20 ||
++ y == 20 || y == h - 20)
++ draw_pixel(fbi, x, y, 0xffffff);
++ else if (x == y || w - x == h - y)
++ draw_pixel(fbi, x, y, 0xff00ff);
++ else if (w - x == y || x == h - y)
++ draw_pixel(fbi, x, y, 0x00ffff);
++ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
++ int t = x * 3 / w;
++ unsigned r = 0, g = 0, b = 0;
++ unsigned c;
++ if (var->bits_per_pixel == 16) {
++ if (t == 0)
++ b = (y % 32) * 256 / 32;
++ else if (t == 1)
++ g = (y % 64) * 256 / 64;
++ else if (t == 2)
++ r = (y % 32) * 256 / 32;
++ } else {
++ if (t == 0)
++ b = (y % 256);
++ else if (t == 1)
++ g = (y % 256);
++ else if (t == 2)
++ r = (y % 256);
++ }
++ c = (r << 16) | (g << 8) | (b << 0);
++ draw_pixel(fbi, x, y, c);
++ } else {
++ draw_pixel(fbi, x, y, 0);
++ }
++ }
++ }
++}
++#endif
++
++static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
++{
++ struct vrfb *vrfb = &ofbi->region.vrfb;
++ unsigned offset;
++
++ switch (rot) {
++ case FB_ROTATE_UR:
++ offset = 0;
++ break;
++ case FB_ROTATE_CW:
++ offset = vrfb->yoffset;
++ break;
++ case FB_ROTATE_UD:
++ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
++ break;
++ case FB_ROTATE_CCW:
++ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
++ break;
++ default:
++ BUG();
++ }
++
++ offset *= vrfb->bytespp;
++
++ return offset;
++}
++
++static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
++{
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ return ofbi->region.vrfb.paddr[rot]
++ + omapfb_get_vrfb_offset(ofbi, rot);
++ } else {
++ return ofbi->region.paddr;
++ }
++}
++
++static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
++{
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
++ return ofbi->region.vrfb.paddr[0];
++ else
++ return ofbi->region.paddr;
++}
++
++static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
++{
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
++ return ofbi->region.vrfb.vaddr[0];
++ else
++ return ofbi->region.vaddr;
++}
++
++static struct omapfb_colormode omapfb_colormodes[] = {
++ {
++ .dssmode = OMAP_DSS_COLOR_UYVY,
++ .bits_per_pixel = 16,
++ .nonstd = OMAPFB_COLOR_YUV422,
++ }, {
++ .dssmode = OMAP_DSS_COLOR_YUV2,
++ .bits_per_pixel = 16,
++ .nonstd = OMAPFB_COLOR_YUY422,
++ }, {
++ .dssmode = OMAP_DSS_COLOR_ARGB16,
++ .bits_per_pixel = 16,
++ .red = { .length = 4, .offset = 8, .msb_right = 0 },
++ .green = { .length = 4, .offset = 4, .msb_right = 0 },
++ .blue = { .length = 4, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 4, .offset = 12, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB16,
++ .bits_per_pixel = 16,
++ .red = { .length = 5, .offset = 11, .msb_right = 0 },
++ .green = { .length = 6, .offset = 5, .msb_right = 0 },
++ .blue = { .length = 5, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB24P,
++ .bits_per_pixel = 24,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB24U,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_ARGB32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 8, .offset = 24, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGBA32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 24, .msb_right = 0 },
++ .green = { .length = 8, .offset = 16, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
++ .transp = { .length = 8, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGBX32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 24, .msb_right = 0 },
++ .green = { .length = 8, .offset = 16, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ },
++};
++
++static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
++ struct omapfb_colormode *color)
++{
++ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
++ {
++ return f1->length == f2->length &&
++ f1->offset == f2->offset &&
++ f1->msb_right == f2->msb_right;
++ }
++
++ if (var->bits_per_pixel == 0 ||
++ var->red.length == 0 ||
++ var->blue.length == 0 ||
++ var->green.length == 0)
++ return 0;
++
++ return var->bits_per_pixel == color->bits_per_pixel &&
++ cmp_component(&var->red, &color->red) &&
++ cmp_component(&var->green, &color->green) &&
++ cmp_component(&var->blue, &color->blue) &&
++ cmp_component(&var->transp, &color->transp);
++}
++
++static void assign_colormode_to_var(struct fb_var_screeninfo *var,
++ struct omapfb_colormode *color)
++{
++ var->bits_per_pixel = color->bits_per_pixel;
++ var->nonstd = color->nonstd;
++ var->red = color->red;
++ var->green = color->green;
++ var->blue = color->blue;
++ var->transp = color->transp;
++}
++
++static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
++{
++ enum omap_color_mode dssmode;
++ int i;
++
++ /* first match with nonstd field */
++ if (var->nonstd) {
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (var->nonstd == mode->nonstd) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ return -EINVAL;
++ }
++
++ /* then try exact match of bpp and colors */
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (cmp_var_to_colormode(var, mode)) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ /* match with bpp if user has not filled color fields
++ * properly */
++ switch (var->bits_per_pixel) {
++ case 1:
++ dssmode = OMAP_DSS_COLOR_CLUT1;
++ break;
++ case 2:
++ dssmode = OMAP_DSS_COLOR_CLUT2;
++ break;
++ case 4:
++ dssmode = OMAP_DSS_COLOR_CLUT4;
++ break;
++ case 8:
++ dssmode = OMAP_DSS_COLOR_CLUT8;
++ break;
++ case 12:
++ dssmode = OMAP_DSS_COLOR_RGB12U;
++ break;
++ case 16:
++ dssmode = OMAP_DSS_COLOR_RGB16;
++ break;
++ case 24:
++ dssmode = OMAP_DSS_COLOR_RGB24P;
++ break;
++ case 32:
++ dssmode = OMAP_DSS_COLOR_RGB24U;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (dssmode == mode->dssmode) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ return -EINVAL;
++}
++
++int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
++ struct fb_var_screeninfo *var)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (dssmode == mode->dssmode) {
++ assign_colormode_to_var(var, mode);
++ return 0;
++ }
++ }
++ return -ENOENT;
++}
++
++void set_fb_fix(struct fb_info *fbi)
++{
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_mem_region *rg = &ofbi->region;
++
++ DBG("set_fb_fix\n");
++
++ /* used by open/write in fbmem.c */
++ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
++
++ DBG("changing rotation to %d\n", var->rotate);
++
++ /* used by mmap in fbmem.c */
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ switch (var->nonstd) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUY422:
++ fix->line_length =
++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
++ break;
++ default:
++ fix->line_length =
++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
++ break;
++ }
++ } else
++ fix->line_length =
++ (var->xres_virtual * var->bits_per_pixel) >> 3;
++ fix->smem_start = omapfb_get_region_paddr(ofbi);
++ fix->smem_len = rg->size;
++
++ fix->type = FB_TYPE_PACKED_PIXELS;
++
++ if (var->nonstd)
++ fix->visual = FB_VISUAL_PSEUDOCOLOR;
++ else {
++ switch (var->bits_per_pixel) {
++ case 32:
++ case 24:
++ case 16:
++ case 12:
++ fix->visual = FB_VISUAL_TRUECOLOR;
++ /* 12bpp is stored in 16 bits */
++ break;
++ case 1:
++ case 2:
++ case 4:
++ case 8:
++ fix->visual = FB_VISUAL_PSEUDOCOLOR;
++ break;
++ }
++ }
++
++ fix->accel = FB_ACCEL_NONE;
++
++ fix->xpanstep = 1;
++ fix->ypanstep = 1;
++
++ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ unsigned bytespp;
++ bool yuv_mode;
++ enum omap_color_mode mode;
++
++ mode = fb_mode_to_dss_mode(var);
++
++ bytespp = var->bits_per_pixel >> 3;
++
++ if (mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY)
++ yuv_mode = true;
++ else
++ yuv_mode = false;
++
++ omap_vrfb_setup(&rg->vrfb, rg->paddr,
++ var->xres_virtual,
++ var->yres_virtual,
++ bytespp, yuv_mode);
++ }
++}
++
++/* check new var and possibly modify it to be ok */
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
++ unsigned long max_frame_size;
++ unsigned long line_size;
++ int xres_min, yres_min;
++ int xres_max, yres_max;
++ enum omap_color_mode mode = 0;
++ int i;
++ int bytespp;
++
++ DBG("check_fb_var %d\n", ofbi->id);
++
++ if (ofbi->region.size == 0)
++ return 0;
++
++ mode = fb_mode_to_dss_mode(var);
++ if (mode < 0) {
++ DBG("cannot convert var to omap dss mode\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
++ DBG("invalid mode\n");
++ return -EINVAL;
++ }
++ }
++
++ if (var->rotate < 0 || var->rotate > 3)
++ return -EINVAL;
++
++ xres_min = OMAPFB_PLANE_XRES_MIN;
++ xres_max = 2048;
++ yres_min = OMAPFB_PLANE_YRES_MIN;
++ yres_max = 2048;
++
++ bytespp = var->bits_per_pixel >> 3;
++
++ /* XXX: some applications seem to set virtual res to 0. */
++ if (var->xres_virtual == 0)
++ var->xres_virtual = var->xres;
++
++ if (var->yres_virtual == 0)
++ var->yres_virtual = var->yres;
++
++ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
++ return -EINVAL;
++
++ if (var->xres < xres_min)
++ var->xres = xres_min;
++ if (var->yres < yres_min)
++ var->yres = yres_min;
++ if (var->xres > xres_max)
++ var->xres = xres_max;
++ if (var->yres > yres_max)
++ var->yres = yres_max;
++
++ if (var->xres > var->xres_virtual)
++ var->xres = var->xres_virtual;
++ if (var->yres > var->yres_virtual)
++ var->yres = var->yres_virtual;
++
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
++ line_size = OMAP_VRFB_LINE_LEN * bytespp;
++ else
++ line_size = var->xres_virtual * bytespp;
++
++ max_frame_size = ofbi->region.size;
++
++ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("can't fit FB into memory, reducing y\n");
++ var->yres_virtual = max_frame_size / line_size;
++
++ if (var->yres_virtual < yres_min)
++ var->yres_virtual = yres_min;
++
++ if (var->yres > var->yres_virtual)
++ var->yres = var->yres_virtual;
++ }
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("can't fit FB into memory, reducing x\n");
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
++ return -EINVAL;
++
++ var->xres_virtual = max_frame_size / var->yres_virtual /
++ bytespp;
++
++ if (var->xres_virtual < xres_min)
++ var->xres_virtual = xres_min;
++
++ if (var->xres > var->xres_virtual)
++ var->xres = var->xres_virtual;
++
++ line_size = var->xres_virtual * bytespp;
++ }
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("cannot fit FB to memory\n");
++ return -EINVAL;
++ }
++
++ if (var->xres + var->xoffset > var->xres_virtual)
++ var->xoffset = var->xres_virtual - var->xres;
++ if (var->yres + var->yoffset > var->yres_virtual)
++ var->yoffset = var->yres_virtual - var->yres;
++
++ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
++ var->xres, var->yres,
++ var->xres_virtual, var->yres_virtual);
++
++ var->height = -1;
++ var->width = -1;
++ var->grayscale = 0;
++
++ if (display && display->get_timings) {
++ struct omap_video_timings timings;
++ display->get_timings(display, &timings);
++
++ /* pixclock in ps, the rest in pixclock */
++ var->pixclock = timings.pixel_clock != 0 ?
++ KHZ2PICOS(timings.pixel_clock) :
++ 0;
++ var->left_margin = timings.hfp;
++ var->right_margin = timings.hbp;
++ var->upper_margin = timings.vfp;
++ var->lower_margin = timings.vbp;
++ var->hsync_len = timings.hsw;
++ var->vsync_len = timings.vsw;
++ } else {
++ var->pixclock = 0;
++ var->left_margin = 0;
++ var->right_margin = 0;
++ var->upper_margin = 0;
++ var->lower_margin = 0;
++ var->hsync_len = 0;
++ var->vsync_len = 0;
++ }
++
++ /* TODO: get these from panel->config */
++ var->vmode = FB_VMODE_NONINTERLACED;
++ var->sync = 0;
++
++ return 0;
++}
++
++/*
++ * ---------------------------------------------------------------------------
++ * fbdev framework callbacks
++ * ---------------------------------------------------------------------------
++ */
++static int omapfb_open(struct fb_info *fbi, int user)
++{
++ return 0;
++}
++
++static int omapfb_release(struct fb_info *fbi, int user)
++{
++#if 0
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_dss_device *display = fb2display(fbi);
++
++ DBG("Closing fb with plane index %d\n", ofbi->id);
++
++ omapfb_lock(fbdev);
++
++ if (display && display->get_update_mode && display->update) {
++ /* XXX this update should be removed, I think. But it's
++ * good for debugging */
++ if (display->get_update_mode(display) ==
++ OMAP_DSS_UPDATE_MANUAL) {
++ u16 w, h;
++
++ if (display->sync)
++ display->sync(display);
++
++ display->get_resolution(display, &w, &h);
++ display->update(display, 0, 0, w, h);
++ }
++ }
++
++ if (display && display->sync)
++ display->sync(display);
++
++ omapfb_unlock(fbdev);
++#endif
++ return 0;
++}
++
++/* setup overlay according to the fb */
++static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
++ u16 posx, u16 posy, u16 outw, u16 outh)
++{
++ int r = 0;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ enum omap_color_mode mode = 0;
++ int offset;
++ u32 data_start_p;
++ void __iomem *data_start_v;
++ struct omap_overlay_info info;
++ int xres, yres;
++ int screen_width;
++ int mirror;
++ int rotation = var->rotate;
++ int i;
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ovl != ofbi->overlays[i])
++ continue;
++
++ rotation = (rotation + ofbi->rotation[i]) % 4;
++ break;
++ }
++
++ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
++ posx, posy, outw, outh);
++
++ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
++ xres = var->yres;
++ yres = var->xres;
++ } else {
++ xres = var->xres;
++ yres = var->yres;
++ }
++
++ offset = ((var->yoffset * var->xres_virtual +
++ var->xoffset) * var->bits_per_pixel) >> 3;
++
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
++ data_start_v = NULL;
++ } else {
++ data_start_p = omapfb_get_region_paddr(ofbi);
++ data_start_v = omapfb_get_region_vaddr(ofbi);
++ }
++
++ data_start_p += offset;
++ data_start_v += offset;
++
++ mode = fb_mode_to_dss_mode(var);
++
++ if (mode == -EINVAL) {
++ DBG("fb_mode_to_dss_mode failed");
++ r = -EINVAL;
++ goto err;
++ }
++
++ switch (var->nonstd) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUY422:
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ screen_width = fix->line_length
++ / (var->bits_per_pixel >> 2);
++ break;
++ }
++ default:
++ screen_width = fix->line_length / (var->bits_per_pixel >> 3);
++ break;
++ }
++
++ ovl->get_overlay_info(ovl, &info);
++
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
++ mirror = 0;
++ else
++ mirror = ofbi->mirror;
++
++ info.paddr = data_start_p;
++ info.vaddr = data_start_v;
++ info.screen_width = screen_width;
++ info.width = xres;
++ info.height = yres;
++ info.color_mode = mode;
++ info.rotation_type = ofbi->rotation_type;
++ info.rotation = rotation;
++ info.mirror = mirror;
++
++ info.pos_x = posx;
++ info.pos_y = posy;
++ info.out_width = outw;
++ info.out_height = outh;
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r) {
++ DBG("ovl->setup_overlay_info failed\n");
++ goto err;
++ }
++
++ return 0;
++
++err:
++ DBG("setup_overlay failed\n");
++ return r;
++}
++
++/* apply var to the overlay */
++int omapfb_apply_changes(struct fb_info *fbi, int init)
++{
++ int r = 0;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct omap_overlay *ovl;
++ u16 posx, posy;
++ u16 outw, outh;
++ int i;
++
++#ifdef DEBUG
++ if (omapfb_test_pattern)
++ fill_fb(fbi);
++#endif
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ ovl = ofbi->overlays[i];
++
++ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
++
++ if (ofbi->region.size == 0) {
++ /* the fb is not available. disable the overlay */
++ omapfb_overlay_enable(ovl, 0);
++ if (!init && ovl->manager)
++ ovl->manager->apply(ovl->manager);
++ continue;
++ }
++
++ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
++ int rotation = (var->rotate + ofbi->rotation[i]) % 4;
++ if (rotation == FB_ROTATE_CW ||
++ rotation == FB_ROTATE_CCW) {
++ outw = var->yres;
++ outh = var->xres;
++ } else {
++ outw = var->xres;
++ outh = var->yres;
++ }
++ } else {
++ outw = ovl->info.out_width;
++ outh = ovl->info.out_height;
++ }
++
++ if (init) {
++ posx = 0;
++ posy = 0;
++ } else {
++ posx = ovl->info.pos_x;
++ posy = ovl->info.pos_y;
++ }
++
++ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
++ if (r)
++ goto err;
++
++ if (!init && ovl->manager)
++ ovl->manager->apply(ovl->manager);
++ }
++ return 0;
++err:
++ DBG("apply_changes failed\n");
++ return r;
++}
++
++/* checks var and eventually tweaks it to something supported,
++ * DO NOT MODIFY PAR */
++static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
++{
++ int r;
++
++ DBG("check_var(%d)\n", FB2OFB(fbi)->id);
++
++ r = check_fb_var(fbi, var);
++
++ return r;
++}
++
++/* set the video mode according to info->var */
++static int omapfb_set_par(struct fb_info *fbi)
++{
++ int r;
++
++ DBG("set_par(%d)\n", FB2OFB(fbi)->id);
++
++ set_fb_fix(fbi);
++ r = omapfb_apply_changes(fbi, 0);
++
++ return r;
++}
++
++static int omapfb_pan_display(struct fb_var_screeninfo *var,
++ struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int r = 0;
++
++ DBG("pan_display(%d)\n", ofbi->id);
++
++ if (var->xoffset != fbi->var.xoffset ||
++ var->yoffset != fbi->var.yoffset) {
++ struct fb_var_screeninfo new_var;
++
++ new_var = fbi->var;
++ new_var.xoffset = var->xoffset;
++ new_var.yoffset = var->yoffset;
++
++ r = check_fb_var(fbi, &new_var);
++
++ if (r == 0) {
++ fbi->var = new_var;
++ set_fb_fix(fbi);
++ r = omapfb_apply_changes(fbi, 0);
++ }
++ }
++
++ return r;
++}
++
++static void mmap_user_open(struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++ atomic_inc(&ofbi->map_count);
++}
++
++static void mmap_user_close(struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++ atomic_dec(&ofbi->map_count);
++}
++
++static struct vm_operations_struct mmap_user_ops = {
++ .open = mmap_user_open,
++ .close = mmap_user_close,
++};
++
++static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ unsigned long off;
++ unsigned long start;
++ u32 len;
++
++ if (vma->vm_end - vma->vm_start == 0)
++ return 0;
++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
++ return -EINVAL;
++ off = vma->vm_pgoff << PAGE_SHIFT;
++
++ start = omapfb_get_region_paddr(ofbi);
++ len = fix->smem_len;
++ if (off >= len)
++ return -EINVAL;
++ if ((vma->vm_end - vma->vm_start + off) > len)
++ return -EINVAL;
++
++ off += start;
++
++ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
++
++ vma->vm_pgoff = off >> PAGE_SHIFT;
++ vma->vm_flags |= VM_IO | VM_RESERVED;
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ vma->vm_ops = &mmap_user_ops;
++ vma->vm_private_data = ofbi;
++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot))
++ return -EAGAIN;
++ /* vm_ops.open won't be called for mmap itself. */
++ atomic_inc(&ofbi->map_count);
++ return 0;
++}
++
++/* Store a single color palette entry into a pseudo palette or the hardware
++ * palette if one is available. For now we support only 16bpp and thus store
++ * the entry only to the pseudo palette.
++ */
++static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
++ u_int blue, u_int transp, int update_hw_pal)
++{
++ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
++ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
++ struct fb_var_screeninfo *var = &fbi->var;
++ int r = 0;
++
++ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
++
++ /*switch (plane->color_mode) {*/
++ switch (mode) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUV420:
++ case OMAPFB_COLOR_YUY422:
++ r = -EINVAL;
++ break;
++ case OMAPFB_COLOR_CLUT_8BPP:
++ case OMAPFB_COLOR_CLUT_4BPP:
++ case OMAPFB_COLOR_CLUT_2BPP:
++ case OMAPFB_COLOR_CLUT_1BPP:
++ /*
++ if (fbdev->ctrl->setcolreg)
++ r = fbdev->ctrl->setcolreg(regno, red, green, blue,
++ transp, update_hw_pal);
++ */
++ /* Fallthrough */
++ r = -EINVAL;
++ break;
++ case OMAPFB_COLOR_RGB565:
++ case OMAPFB_COLOR_RGB444:
++ case OMAPFB_COLOR_RGB24P:
++ case OMAPFB_COLOR_RGB24U:
++ if (r != 0)
++ break;
++
++ if (regno < 0) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (regno < 16) {
++ u16 pal;
++ pal = ((red >> (16 - var->red.length)) <<
++ var->red.offset) |
++ ((green >> (16 - var->green.length)) <<
++ var->green.offset) |
++ (blue >> (16 - var->blue.length));
++ ((u32 *)(fbi->pseudo_palette))[regno] = pal;
++ }
++ break;
++ default:
++ BUG();
++ }
++ return r;
++}
++
++static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++ u_int transp, struct fb_info *info)
++{
++ DBG("setcolreg\n");
++
++ return _setcolreg(info, regno, red, green, blue, transp, 1);
++}
++
++static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
++{
++ int count, index, r;
++ u16 *red, *green, *blue, *transp;
++ u16 trans = 0xffff;
++
++ DBG("setcmap\n");
++
++ red = cmap->red;
++ green = cmap->green;
++ blue = cmap->blue;
++ transp = cmap->transp;
++ index = cmap->start;
++
++ for (count = 0; count < cmap->len; count++) {
++ if (transp)
++ trans = *transp++;
++ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
++ count == cmap->len - 1);
++ if (r != 0)
++ return r;
++ }
++
++ return 0;
++}
++
++static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
++ }
++}
++
++static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_resume_ctx(&ofbi->region.vrfb);
++ }
++}
++
++static int omapfb_blank(int blank, struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_dss_device *display = fb2display(fbi);
++ int do_update = 0;
++ int r = 0;
++
++ omapfb_lock(fbdev);
++
++ switch (blank) {
++ case FB_BLANK_UNBLANK:
++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ goto exit;
++
++ omapfb_vrfb_resume_all(fbdev);
++
++ if (display->resume)
++ r = display->resume(display);
++
++ if (r == 0 && display->get_update_mode &&
++ display->get_update_mode(display) ==
++ OMAP_DSS_UPDATE_MANUAL)
++ do_update = 1;
++
++ break;
++
++ case FB_BLANK_NORMAL:
++ /* FB_BLANK_NORMAL could be implemented.
++ * Needs DSS additions. */
++ case FB_BLANK_VSYNC_SUSPEND:
++ case FB_BLANK_HSYNC_SUSPEND:
++ case FB_BLANK_POWERDOWN:
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto exit;
++
++ if (display->suspend)
++ r = display->suspend(display);
++
++ omapfb_vrfb_suspend_all(fbdev);
++
++ break;
++
++ default:
++ r = -EINVAL;
++ }
++
++exit:
++ omapfb_unlock(fbdev);
++
++ if (r == 0 && do_update && display->update) {
++ u16 w, h;
++ display->get_resolution(display, &w, &h);
++
++ r = display->update(display, 0, 0, w, h);
++ }
++
++ return r;
++}
++
++#if 0
++/* XXX fb_read and fb_write are needed for VRFB */
++ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
++ /* XXX needed for VRFB */
++ return count;
++}
++#endif
++
++static struct fb_ops omapfb_ops = {
++ .owner = THIS_MODULE,
++ .fb_open = omapfb_open,
++ .fb_release = omapfb_release,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_blank = omapfb_blank,
++ .fb_ioctl = omapfb_ioctl,
++ .fb_check_var = omapfb_check_var,
++ .fb_set_par = omapfb_set_par,
++ .fb_pan_display = omapfb_pan_display,
++ .fb_mmap = omapfb_mmap,
++ .fb_setcolreg = omapfb_setcolreg,
++ .fb_setcmap = omapfb_setcmap,
++ /*.fb_write = omapfb_write,*/
++};
++
++static void omapfb_free_fbmem(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++
++ rg = &ofbi->region;
++
++ if (rg->paddr)
++ if (omap_vram_free(rg->paddr, rg->size))
++ dev_err(fbdev->dev, "VRAM FREE failed\n");
++
++ if (rg->vaddr)
++ iounmap(rg->vaddr);
++
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ /* unmap the 0 angle rotation */
++ if (rg->vrfb.vaddr[0]) {
++ iounmap(rg->vrfb.vaddr[0]);
++ omap_vrfb_release_ctx(&rg->vrfb);
++ }
++ }
++
++ rg->vaddr = NULL;
++ rg->paddr = 0;
++ rg->alloc = 0;
++ rg->size = 0;
++}
++
++static void clear_fb_info(struct fb_info *fbi)
++{
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
++}
++
++static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ DBG("free all fbmem\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct fb_info *fbi = fbdev->fbs[i];
++ omapfb_free_fbmem(fbi);
++ clear_fb_info(fbi);
++ }
++
++ return 0;
++}
++
++static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
++ unsigned long paddr)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++ void __iomem *vaddr;
++ int r;
++
++ rg = &ofbi->region;
++ memset(rg, 0, sizeof(*rg));
++
++ size = PAGE_ALIGN(size);
++
++ if (!paddr) {
++ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
++ r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
++ } else {
++ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
++ ofbi->id);
++ r = omap_vram_reserve(paddr, size);
++ }
++
++ if (r) {
++ dev_err(fbdev->dev, "failed to allocate framebuffer\n");
++ return -ENOMEM;
++ }
++
++ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
++ vaddr = ioremap_wc(paddr, size);
++
++ if (!vaddr) {
++ dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
++ omap_vram_free(paddr, size);
++ return -ENOMEM;
++ }
++
++ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
++ } else {
++ void __iomem *va;
++
++ r = omap_vrfb_request_ctx(&rg->vrfb);
++ if (r) {
++ dev_err(fbdev->dev, "vrfb create ctx failed\n");
++ return r;
++ }
++
++ /* only ioremap the 0 angle view */
++ va = ioremap_wc(rg->vrfb.paddr[0], size);
++
++ if (!va) {
++ printk(KERN_ERR "vrfb: ioremap failed\n");
++ omap_vrfb_release_ctx(&rg->vrfb);
++ return -ENOMEM;
++ }
++
++ DBG("ioremapped vrfb area 0 to %p\n", va);
++
++ rg->vrfb.vaddr[0] = va;
++
++ vaddr = NULL;
++ }
++
++ rg->paddr = paddr;
++ rg->vaddr = vaddr;
++ rg->size = size;
++ rg->alloc = 1;
++
++ return 0;
++}
++
++/* allocate fbmem using display resolution as reference */
++static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
++ unsigned long paddr)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omap_dss_device *display;
++ int bytespp;
++
++ display = fb2display(fbi);
++
++ if (!display)
++ return 0;
++
++ switch (display->get_recommended_bpp(display)) {
++ case 16:
++ bytespp = 2;
++ break;
++ case 24:
++ bytespp = 4;
++ break;
++ default:
++ bytespp = 4;
++ break;
++ }
++
++ if (!size) {
++ u16 w, h;
++
++ display->get_resolution(display, &w, &h);
++
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++#ifdef DEBUG
++ int oldw = w, oldh = h;
++#endif
++
++ omap_vrfb_adjust_size(&w, &h, bytespp);
++
++ /* Because we change the resolution of the 0 degree
++ * view, we need to alloc max(w, h) for height */
++ h = max(w, h);
++ w = OMAP_VRFB_LINE_LEN;
++
++ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n",
++ oldw, oldh, w, h);
++ }
++
++ size = w * h * bytespp;
++ }
++
++ if (!size)
++ return 0;
++
++ return omapfb_alloc_fbmem(fbi, size, paddr);
++}
++
++static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
++{
++ enum omap_color_mode mode;
++
++ switch (fmt) {
++ case OMAPFB_COLOR_RGB565:
++ mode = OMAP_DSS_COLOR_RGB16;
++ break;
++ case OMAPFB_COLOR_YUV422:
++ mode = OMAP_DSS_COLOR_YUV2;
++ break;
++ case OMAPFB_COLOR_CLUT_8BPP:
++ mode = OMAP_DSS_COLOR_CLUT8;
++ break;
++ case OMAPFB_COLOR_CLUT_4BPP:
++ mode = OMAP_DSS_COLOR_CLUT4;
++ break;
++ case OMAPFB_COLOR_CLUT_2BPP:
++ mode = OMAP_DSS_COLOR_CLUT2;
++ break;
++ case OMAPFB_COLOR_CLUT_1BPP:
++ mode = OMAP_DSS_COLOR_CLUT1;
++ break;
++ case OMAPFB_COLOR_RGB444:
++ mode = OMAP_DSS_COLOR_RGB12U;
++ break;
++ case OMAPFB_COLOR_YUY422:
++ mode = OMAP_DSS_COLOR_UYVY;
++ break;
++ case OMAPFB_COLOR_ARGB16:
++ mode = OMAP_DSS_COLOR_ARGB16;
++ break;
++ case OMAPFB_COLOR_RGB24U:
++ mode = OMAP_DSS_COLOR_RGB24U;
++ break;
++ case OMAPFB_COLOR_RGB24P:
++ mode = OMAP_DSS_COLOR_RGB24P;
++ break;
++ case OMAPFB_COLOR_ARGB32:
++ mode = OMAP_DSS_COLOR_ARGB32;
++ break;
++ case OMAPFB_COLOR_RGBA32:
++ mode = OMAP_DSS_COLOR_RGBA32;
++ break;
++ case OMAPFB_COLOR_RGBX32:
++ mode = OMAP_DSS_COLOR_RGBX32;
++ break;
++ default:
++ mode = -EINVAL;
++ }
++
++ return mode;
++}
++
++static int omapfb_parse_vram_param(const char *param, int max_entries,
++ unsigned long *sizes, unsigned long *paddrs)
++{
++ int fbnum;
++ unsigned long size;
++ unsigned long paddr = 0;
++ char *p, *start;
++
++ start = (char *)param;
++
++ while (1) {
++ p = start;
++
++ fbnum = simple_strtoul(p, &p, 10);
++
++ if (p == param)
++ return -EINVAL;
++
++ if (*p != ':')
++ return -EINVAL;
++
++ if (fbnum >= max_entries)
++ return -EINVAL;
++
++ size = memparse(p + 1, &p);
++
++ if (!size)
++ return -EINVAL;
++
++ paddr = 0;
++
++ if (*p == '@') {
++ paddr = simple_strtoul(p + 1, &p, 16);
++
++ if (!paddr)
++ return -EINVAL;
++
++ }
++
++ paddrs[fbnum] = paddr;
++ sizes[fbnum] = size;
++
++ if (*p == 0)
++ break;
++
++ if (*p != ',')
++ return -EINVAL;
++
++ ++p;
++
++ start = p;
++ }
++
++ return 0;
++}
++
++static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
++{
++ int i, r;
++ unsigned long vram_sizes[10];
++ unsigned long vram_paddrs[10];
++
++ memset(&vram_sizes, 0, sizeof(vram_sizes));
++ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
++
++ if (def_vram && omapfb_parse_vram_param(def_vram, 10,
++ vram_sizes, vram_paddrs)) {
++ dev_err(fbdev->dev, "failed to parse vram parameter\n");
++
++ memset(&vram_sizes, 0, sizeof(vram_sizes));
++ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
++ }
++
++ if (fbdev->dev->platform_data) {
++ struct omapfb_platform_data *opd;
++ opd = fbdev->dev->platform_data;
++ for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
++ if (!vram_sizes[i]) {
++ unsigned long size;
++ unsigned long paddr;
++
++ size = opd->mem_desc.region[i].size;
++ paddr = opd->mem_desc.region[i].paddr;
++
++ vram_sizes[i] = size;
++ vram_paddrs[i] = paddr;
++ }
++ }
++ }
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ /* allocate memory automatically only for fb0, or if
++ * excplicitly defined with vram or plat data option */
++ if (i == 0 || vram_sizes[i] != 0) {
++ r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
++ vram_sizes[i], vram_paddrs[i]);
++
++ if (r)
++ return r;
++ }
++ }
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++ struct omapfb2_mem_region *rg;
++ rg = &ofbi->region;
++
++ DBG("region%d phys %08x virt %p size=%lu\n",
++ i,
++ rg->paddr,
++ rg->vaddr,
++ rg->size);
++ }
++
++ return 0;
++}
++
++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_dss_device *display = fb2display(fbi);
++ struct omapfb2_mem_region *rg = &ofbi->region;
++ unsigned long old_size = rg->size;
++ unsigned long old_paddr = rg->paddr;
++ int old_type = rg->type;
++ int r;
++
++ if (type > OMAPFB_MEMTYPE_MAX)
++ return -EINVAL;
++
++ size = PAGE_ALIGN(size);
++
++ if (old_size == size && old_type == type)
++ return 0;
++
++ if (display && display->sync)
++ display->sync(display);
++
++ omapfb_free_fbmem(fbi);
++
++ if (size == 0) {
++ clear_fb_info(fbi);
++ return 0;
++ }
++
++ r = omapfb_alloc_fbmem(fbi, size, 0);
++
++ if (r) {
++ if (old_size)
++ omapfb_alloc_fbmem(fbi, old_size, old_paddr);
++
++ if (rg->size == 0)
++ clear_fb_info(fbi);
++
++ return r;
++ }
++
++ if (old_size == size)
++ return 0;
++
++ if (old_size == 0) {
++ DBG("initializing fb %d\n", ofbi->id);
++ r = omapfb_fb_init(fbdev, fbi);
++ if (r) {
++ DBG("omapfb_fb_init failed\n");
++ goto err;
++ }
++ r = omapfb_apply_changes(fbi, 1);
++ if (r) {
++ DBG("omapfb_apply_changes failed\n");
++ goto err;
++ }
++ } else {
++ struct fb_var_screeninfo new_var;
++ memcpy(&new_var, &fbi->var, sizeof(new_var));
++ r = check_fb_var(fbi, &new_var);
++ if (r)
++ goto err;
++ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
++ set_fb_fix(fbi);
++ }
++
++ return 0;
++err:
++ omapfb_free_fbmem(fbi);
++ clear_fb_info(fbi);
++ return r;
++}
++
++/* initialize fb_info, var, fix to something sane based on the display */
++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct omap_dss_device *display = fb2display(fbi);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int r = 0;
++
++ fbi->fbops = &omapfb_ops;
++ fbi->flags = FBINFO_FLAG_DEFAULT;
++ fbi->pseudo_palette = fbdev->pseudo_palette;
++
++ if (ofbi->region.size == 0) {
++ clear_fb_info(fbi);
++ return 0;
++ }
++
++ var->nonstd = 0;
++ var->bits_per_pixel = 0;
++
++ var->rotate = def_rotate;
++
++ /*
++ * Check if there is a default color format set in the board file,
++ * and use this format instead the default deducted from the
++ * display bpp.
++ */
++ if (fbdev->dev->platform_data) {
++ struct omapfb_platform_data *opd;
++ int id = ofbi->id;
++
++ opd = fbdev->dev->platform_data;
++ if (opd->mem_desc.region[id].format_used) {
++ enum omap_color_mode mode;
++ enum omapfb_color_format format;
++
++ format = opd->mem_desc.region[id].format;
++ mode = fb_format_to_dss_mode(format);
++ if (mode < 0) {
++ r = mode;
++ goto err;
++ }
++ r = dss_mode_to_fb_mode(mode, var);
++ if (r < 0)
++ goto err;
++ }
++ }
++
++ if (display) {
++ u16 w, h;
++ int rotation = (var->rotate + ofbi->rotation[0]) % 4;
++
++ display->get_resolution(display, &w, &h);
++
++ if (rotation == FB_ROTATE_CW ||
++ rotation == FB_ROTATE_CCW) {
++ var->xres = h;
++ var->yres = w;
++ } else {
++ var->xres = w;
++ var->yres = h;
++ }
++
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++
++ if (!var->bits_per_pixel) {
++ switch (display->get_recommended_bpp(display)) {
++ case 16:
++ var->bits_per_pixel = 16;
++ break;
++ case 24:
++ var->bits_per_pixel = 32;
++ break;
++ default:
++ dev_err(fbdev->dev, "illegal display "
++ "bpp\n");
++ return -EINVAL;
++ }
++ }
++ } else {
++ /* if there's no display, let's just guess some basic values */
++ var->xres = 320;
++ var->yres = 240;
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++ if (!var->bits_per_pixel)
++ var->bits_per_pixel = 16;
++ }
++
++ r = check_fb_var(fbi, var);
++ if (r)
++ goto err;
++
++ set_fb_fix(fbi);
++
++ r = fb_alloc_cmap(&fbi->cmap, 256, 0);
++ if (r)
++ dev_err(fbdev->dev, "unable to allocate color map memory\n");
++
++err:
++ return r;
++}
++
++static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
++{
++ fb_dealloc_cmap(&fbi->cmap);
++}
++
++
++static void omapfb_free_resources(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ DBG("free_resources\n");
++
++ if (fbdev == NULL)
++ return;
++
++ for (i = 0; i < fbdev->num_fbs; i++)
++ unregister_framebuffer(fbdev->fbs[i]);
++
++ /* free the reserved fbmem */
++ omapfb_free_all_fbmem(fbdev);
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ fbinfo_cleanup(fbdev, fbdev->fbs[i]);
++ framebuffer_release(fbdev->fbs[i]);
++ }
++
++ for (i = 0; i < fbdev->num_displays; i++) {
++ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
++ fbdev->displays[i]->disable(fbdev->displays[i]);
++
++ omap_dss_put_device(fbdev->displays[i]);
++ }
++
++ dev_set_drvdata(fbdev->dev, NULL);
++ kfree(fbdev);
++}
++
++static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
++{
++ int r, i;
++
++ fbdev->num_fbs = 0;
++
++ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
++
++ /* allocate fb_infos */
++ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
++ struct fb_info *fbi;
++ struct omapfb_info *ofbi;
++
++ fbi = framebuffer_alloc(sizeof(struct omapfb_info),
++ fbdev->dev);
++
++ if (fbi == NULL) {
++ dev_err(fbdev->dev,
++ "unable to allocate memory for plane info\n");
++ return -ENOMEM;
++ }
++
++ clear_fb_info(fbi);
++
++ fbdev->fbs[i] = fbi;
++
++ ofbi = FB2OFB(fbi);
++ ofbi->fbdev = fbdev;
++ ofbi->id = i;
++
++ /* assign these early, so that fb alloc can use them */
++ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
++ OMAP_DSS_ROT_DMA;
++ ofbi->mirror = def_mirror;
++
++ fbdev->num_fbs++;
++ }
++
++ DBG("fb_infos allocated\n");
++
++ /* assign overlays for the fbs */
++ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ ofbi->overlays[0] = fbdev->overlays[i];
++ ofbi->num_overlays = 1;
++ }
++
++ /* allocate fb memories */
++ r = omapfb_allocate_all_fbs(fbdev);
++ if (r) {
++ dev_err(fbdev->dev, "failed to allocate fbmem\n");
++ return r;
++ }
++
++ DBG("fbmems allocated\n");
++
++ /* setup fb_infos */
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
++ if (r) {
++ dev_err(fbdev->dev, "failed to setup fb_info\n");
++ return r;
++ }
++ }
++
++ DBG("fb_infos initialized\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = register_framebuffer(fbdev->fbs[i]);
++ if (r != 0) {
++ dev_err(fbdev->dev,
++ "registering framebuffer %d failed\n", i);
++ return r;
++ }
++ }
++
++ DBG("framebuffers registered\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = omapfb_apply_changes(fbdev->fbs[i], 1);
++ if (r) {
++ dev_err(fbdev->dev, "failed to change mode\n");
++ return r;
++ }
++ }
++
++ DBG("create sysfs for fbs\n");
++ r = omapfb_create_sysfs(fbdev);
++ if (r) {
++ dev_err(fbdev->dev, "failed to create sysfs entries\n");
++ return r;
++ }
++
++ /* Enable fb0 */
++ if (fbdev->num_fbs > 0) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
++
++ if (ofbi->num_overlays > 0) {
++ struct omap_overlay *ovl = ofbi->overlays[0];
++
++ r = omapfb_overlay_enable(ovl, 1);
++
++ if (r) {
++ dev_err(fbdev->dev,
++ "failed to enable overlay\n");
++ return r;
++ }
++ }
++ }
++
++ DBG("create_framebuffers done\n");
++
++ return 0;
++}
++
++static int omapfb_mode_to_timings(const char *mode_str,
++ struct omap_video_timings *timings, u8 *bpp)
++{
++ struct fb_info fbi;
++ struct fb_var_screeninfo var;
++ struct fb_ops fbops;
++ int r;
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ if (strcmp(mode_str, "pal") == 0) {
++ *timings = omap_dss_pal_timings;
++ *bpp = 0;
++ return 0;
++ } else if (strcmp(mode_str, "ntsc") == 0) {
++ *timings = omap_dss_ntsc_timings;
++ *bpp = 0;
++ return 0;
++ }
++#endif
++
++ /* this is quite a hack, but I wanted to use the modedb and for
++ * that we need fb_info and var, so we create dummy ones */
++
++ memset(&fbi, 0, sizeof(fbi));
++ memset(&var, 0, sizeof(var));
++ memset(&fbops, 0, sizeof(fbops));
++ fbi.fbops = &fbops;
++
++ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
++
++ if (r != 0) {
++ timings->pixel_clock = PICOS2KHZ(var.pixclock);
++ timings->hfp = var.left_margin;
++ timings->hbp = var.right_margin;
++ timings->vfp = var.upper_margin;
++ timings->vbp = var.lower_margin;
++ timings->hsw = var.hsync_len;
++ timings->vsw = var.vsync_len;
++ timings->x_res = var.xres;
++ timings->y_res = var.yres;
++
++ switch (var.bits_per_pixel) {
++ case 16:
++ *bpp = 16;
++ break;
++ case 24:
++ case 32:
++ default:
++ *bpp = 24;
++ break;
++ }
++
++ return 0;
++ } else {
++ return -EINVAL;
++ }
++}
++
++static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
++{
++ int r;
++ u8 bpp;
++ struct omap_video_timings timings;
++
++ r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
++ if (r)
++ return r;
++
++ display->panel.recommended_bpp = bpp;
++
++ if (!display->check_timings || !display->set_timings)
++ return -EINVAL;
++
++ r = display->check_timings(display, &timings);
++ if (r)
++ return r;
++
++ display->set_timings(display, &timings);
++
++ return 0;
++}
++
++static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
++{
++ char *str, *options, *this_opt;
++ int r = 0;
++
++ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
++ strcpy(str, def_mode);
++ options = str;
++
++ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
++ char *p, *display_str, *mode_str;
++ struct omap_dss_device *display;
++ int i;
++
++ p = strchr(this_opt, ':');
++ if (!p) {
++ r = -EINVAL;
++ break;
++ }
++
++ *p = 0;
++ display_str = this_opt;
++ mode_str = p + 1;
++
++ display = NULL;
++ for (i = 0; i < fbdev->num_displays; ++i) {
++ if (strcmp(fbdev->displays[i]->name,
++ display_str) == 0) {
++ display = fbdev->displays[i];
++ break;
++ }
++ }
++
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = omapfb_set_def_mode(display, mode_str);
++ if (r)
++ break;
++ }
++
++ kfree(str);
++
++ return r;
++}
++
++static int omapfb_probe(struct platform_device *pdev)
++{
++ struct omapfb2_device *fbdev = NULL;
++ int r = 0;
++ int i;
++ struct omap_overlay *ovl;
++ struct omap_dss_device *def_display;
++ struct omap_dss_device *dssdev;
++
++ DBG("omapfb_probe\n");
++
++ if (pdev->num_resources != 0) {
++ dev_err(&pdev->dev, "probed for an unknown device\n");
++ r = -ENODEV;
++ goto err0;
++ }
++
++ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
++ if (fbdev == NULL) {
++ r = -ENOMEM;
++ goto err0;
++ }
++
++ mutex_init(&fbdev->mtx);
++
++ fbdev->dev = &pdev->dev;
++ platform_set_drvdata(pdev, fbdev);
++
++ fbdev->num_displays = 0;
++ dssdev = NULL;
++ for_each_dss_dev(dssdev) {
++ omap_dss_get_device(dssdev);
++ fbdev->displays[fbdev->num_displays++] = dssdev;
++ }
++
++ if (fbdev->num_displays == 0) {
++ dev_err(&pdev->dev, "no displays\n");
++ r = -EINVAL;
++ goto cleanup;
++ }
++
++ fbdev->num_overlays = omap_dss_get_num_overlays();
++ for (i = 0; i < fbdev->num_overlays; i++)
++ fbdev->overlays[i] = omap_dss_get_overlay(i);
++
++ fbdev->num_managers = omap_dss_get_num_overlay_managers();
++ for (i = 0; i < fbdev->num_managers; i++)
++ fbdev->managers[i] = omap_dss_get_overlay_manager(i);
++
++ if (def_mode && strlen(def_mode) > 0) {
++ if (omapfb_parse_def_modes(fbdev))
++ dev_warn(&pdev->dev, "cannot parse default modes\n");
++ }
++
++ r = omapfb_create_framebuffers(fbdev);
++ if (r)
++ goto cleanup;
++
++ for (i = 0; i < fbdev->num_managers; i++) {
++ struct omap_overlay_manager *mgr;
++ mgr = fbdev->managers[i];
++ r = mgr->apply(mgr);
++ if (r)
++ dev_warn(fbdev->dev, "failed to apply dispc config\n");
++ }
++
++ DBG("mgr->apply'ed\n");
++
++ /* gfx overlay should be the default one. find a display
++ * connected to that, and use it as default display */
++ ovl = omap_dss_get_overlay(0);
++ if (ovl->manager && ovl->manager->device) {
++ def_display = ovl->manager->device;
++ } else {
++ dev_warn(&pdev->dev, "cannot find default display\n");
++ def_display = NULL;
++ }
++
++ if (def_display) {
++ u16 w, h;
++ r = def_display->enable(def_display);
++ if (r)
++ dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
++ def_display->name);
++
++ /* set the update mode */
++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 1);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++#else /* MANUAL_UPDATE */
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 0);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_MANUAL);
++
++ def_display->get_resolution(def_display, &w, &h);
++ def_display->update(def_display, 0, 0, w, h);
++#endif
++ } else {
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++ }
++ }
++
++ return 0;
++
++cleanup:
++ omapfb_free_resources(fbdev);
++err0:
++ dev_err(&pdev->dev, "failed to setup omapfb\n");
++ return r;
++}
++
++static int omapfb_remove(struct platform_device *pdev)
++{
++ struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
++
++ /* FIXME: wait till completion of pending events */
++
++ omapfb_remove_sysfs(fbdev);
++
++ omapfb_free_resources(fbdev);
++
++ return 0;
++}
++
++static struct platform_driver omapfb_driver = {
++ .probe = omapfb_probe,
++ .remove = omapfb_remove,
++ .driver = {
++ .name = "omapfb",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init omapfb_init(void)
++{
++ DBG("omapfb_init\n");
++
++ if (platform_driver_register(&omapfb_driver)) {
++ printk(KERN_ERR "failed to register omapfb driver\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static void __exit omapfb_exit(void)
++{
++ DBG("omapfb_exit\n");
++ platform_driver_unregister(&omapfb_driver);
++}
++
++module_param_named(mode, def_mode, charp, 0);
++module_param_named(vram, def_vram, charp, 0);
++module_param_named(rotate, def_rotate, int, 0);
++module_param_named(vrfb, def_vrfb, bool, 0);
++module_param_named(mirror, def_mirror, bool, 0);
++
++/* late_initcall to let panel/ctrl drivers loaded first.
++ * I guess better option would be a more dynamic approach,
++ * so that omapfb reacts to new panels when they are loaded */
++late_initcall(omapfb_init);
++/*module_init(omapfb_init);*/
++module_exit(omapfb_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+new file mode 100644
+index 0000000..ef30e0e
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -0,0 +1,507 @@
++/*
++ * linux/drivers/video/omap2/omapfb-sysfs.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/fb.h>
++#include <linux/sysfs.h>
++#include <linux/device.h>
++#include <linux/uaccess.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/omapfb.h>
++
++#include <mach/display.h>
++#include <mach/vrfb.h>
++
++#include "omapfb.h"
++
++static ssize_t show_rotate_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
++}
++
++static ssize_t store_rotate_type(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ enum omap_dss_rotation_type rot_type;
++ int r;
++
++ rot_type = simple_strtoul(buf, NULL, 0);
++
++ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
++ return -EINVAL;
++
++ lock_fb_info(fbi);
++
++ r = 0;
++ if (rot_type == ofbi->rotation_type)
++ goto out;
++
++ if (ofbi->region.size) {
++ r = -EBUSY;
++ goto out;
++ }
++
++ ofbi->rotation_type = rot_type;
++
++ /*
++ * Since the VRAM for this FB is not allocated at the moment we don't
++ * need to do any further parameter checking at this point.
++ */
++out:
++ unlock_fb_info(fbi);
++
++ return r ? r : count;
++}
++
++
++static ssize_t show_mirror(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
++}
++
++static ssize_t store_mirror(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ bool mirror;
++ int r;
++ struct fb_var_screeninfo new_var;
++
++ mirror = simple_strtoul(buf, NULL, 0);
++
++ if (mirror != 0 && mirror != 1)
++ return -EINVAL;
++
++ lock_fb_info(fbi);
++
++ ofbi->mirror = mirror;
++
++ memcpy(&new_var, &fbi->var, sizeof(new_var));
++ r = check_fb_var(fbi, &new_var);
++ if (r)
++ goto out;
++ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
++
++ set_fb_fix(fbi);
++
++ r = omapfb_apply_changes(fbi, 0);
++ if (r)
++ goto out;
++
++ r = count;
++out:
++ unlock_fb_info(fbi);
++
++ return r;
++}
++
++static ssize_t show_overlays(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ ssize_t l = 0;
++ int t;
++
++ omapfb_lock(fbdev);
++ lock_fb_info(fbi);
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ struct omap_overlay *ovl = ofbi->overlays[t];
++ int ovlnum;
++
++ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
++ if (ovl == fbdev->overlays[ovlnum])
++ break;
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
++ t == 0 ? "" : ",", ovlnum);
++ }
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
++
++ unlock_fb_info(fbi);
++ omapfb_unlock(fbdev);
++
++ return l;
++}
++
++static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
++ struct omap_overlay *ovl)
++{
++ int i, t;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ if (ofbi->overlays[t] == ovl)
++ return ofbi;
++ }
++ }
++
++ return NULL;
++}
++
++static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
++ struct omap_overlay *ovl;
++ int num_ovls, r, i;
++ int len;
++ bool added = false;
++
++ num_ovls = 0;
++
++ len = strlen(buf);
++ if (buf[len - 1] == '\n')
++ len = len - 1;
++
++ omapfb_lock(fbdev);
++ lock_fb_info(fbi);
++
++ if (len > 0) {
++ char *p = (char *)buf;
++ int ovlnum;
++
++ while (p < buf + len) {
++ int found;
++ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ ovlnum = simple_strtoul(p, &p, 0);
++ if (ovlnum > fbdev->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ found = 0;
++ for (i = 0; i < num_ovls; ++i) {
++ if (ovls[i] == fbdev->overlays[ovlnum]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ ovls[num_ovls++] = fbdev->overlays[ovlnum];
++
++ p++;
++ }
++ }
++
++ for (i = 0; i < num_ovls; ++i) {
++ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
++ if (ofbi2 && ofbi2 != ofbi) {
++ dev_err(fbdev->dev, "overlay already in use\n");
++ r = -EINVAL;
++ goto out;
++ }
++ }
++
++ /* detach unused overlays */
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ int t, found;
++
++ ovl = ofbi->overlays[i];
++
++ found = 0;
++
++ for (t = 0; t < num_ovls; ++t) {
++ if (ovl == ovls[t]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (found)
++ continue;
++
++ DBG("detaching %d\n", ofbi->overlays[i]->id);
++
++ omapfb_overlay_enable(ovl, 0);
++
++ if (ovl->manager)
++ ovl->manager->apply(ovl->manager);
++
++ for (t = i + 1; t < ofbi->num_overlays; t++) {
++ ofbi->rotation[t-1] = ofbi->rotation[t];
++ ofbi->overlays[t-1] = ofbi->overlays[t];
++ }
++
++ ofbi->num_overlays--;
++ i--;
++ }
++
++ for (i = 0; i < num_ovls; ++i) {
++ int t, found;
++
++ ovl = ovls[i];
++
++ found = 0;
++
++ for (t = 0; t < ofbi->num_overlays; ++t) {
++ if (ovl == ofbi->overlays[t]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (found)
++ continue;
++ ofbi->rotation[ofbi->num_overlays] = 0;
++ ofbi->overlays[ofbi->num_overlays++] = ovl;
++
++ added = true;
++ }
++
++ if (added) {
++ r = omapfb_apply_changes(fbi, 0);
++ if (r)
++ goto out;
++ }
++
++ r = count;
++out:
++ unlock_fb_info(fbi);
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static ssize_t show_overlays_rotate(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ ssize_t l = 0;
++ int t;
++
++ lock_fb_info(fbi);
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
++ t == 0 ? "" : ",", ofbi->rotation[t]);
++ }
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
++
++ unlock_fb_info(fbi);
++
++ return l;
++}
++
++static ssize_t store_overlays_rotate(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int num_ovls = 0, r, i;
++ int len;
++ bool changed = false;
++ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
++
++ len = strlen(buf);
++ if (buf[len - 1] == '\n')
++ len = len - 1;
++
++ lock_fb_info(fbi);
++
++ if (len > 0) {
++ char *p = (char *)buf;
++
++ while (p < buf + len) {
++ int rot;
++
++ if (num_ovls == ofbi->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ rot = simple_strtoul(p, &p, 0);
++ if (rot < 0 || rot > 3) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ if (ofbi->rotation[num_ovls] != rot)
++ changed = true;
++
++ rotation[num_ovls++] = rot;
++
++ p++;
++ }
++ }
++
++ if (num_ovls != ofbi->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ if (changed) {
++ for (i = 0; i < num_ovls; ++i)
++ ofbi->rotation[i] = rotation[i];
++
++ r = omapfb_apply_changes(fbi, 0);
++ if (r)
++ goto out;
++
++ /* FIXME error handling? */
++ }
++
++ r = count;
++out:
++ unlock_fb_info(fbi);
++
++ return r;
++}
++
++static ssize_t show_size(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
++}
++
++static ssize_t store_size(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ unsigned long size;
++ int r;
++ int i;
++
++ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
++
++ lock_fb_info(fbi);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->info.enabled) {
++ r = -EBUSY;
++ goto out;
++ }
++ }
++
++ if (size != ofbi->region.size) {
++ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
++ if (r) {
++ dev_err(dev, "realloc fbmem failed\n");
++ goto out;
++ }
++ }
++
++ r = count;
++out:
++ unlock_fb_info(fbi);
++
++ return r;
++}
++
++static ssize_t show_phys(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
++}
++
++static ssize_t show_virt(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
++}
++
++static struct device_attribute omapfb_attrs[] = {
++ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
++ store_rotate_type),
++ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
++ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
++ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
++ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
++ store_overlays_rotate),
++ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
++ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
++};
++
++int omapfb_create_sysfs(struct omapfb2_device *fbdev)
++{
++ int i;
++ int r;
++
++ DBG("create sysfs for fbs\n");
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ int t;
++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
++ r = device_create_file(fbdev->fbs[i]->dev,
++ &omapfb_attrs[t]);
++
++ if (r) {
++ dev_err(fbdev->dev, "failed to create sysfs "
++ "file\n");
++ return r;
++ }
++ }
++ }
++
++ return 0;
++}
++
++void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
++{
++ int i, t;
++
++ DBG("remove sysfs for fbs\n");
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
++ device_remove_file(fbdev->fbs[i]->dev,
++ &omapfb_attrs[t]);
++ }
++}
++
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+new file mode 100644
+index 0000000..d9ee986
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -0,0 +1,146 @@
++/*
++ * linux/drivers/video/omap2/omapfb.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
++#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
++
++#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
++#define DEBUG
++#endif
++
++#include <mach/display.h>
++
++#ifdef DEBUG
++extern unsigned int omapfb_debug;
++#define DBG(format, ...) \
++ if (omapfb_debug) \
++ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
++
++/* max number of overlays to which a framebuffer data can be direct */
++#define OMAPFB_MAX_OVL_PER_FB 3
++
++struct omapfb2_mem_region {
++ u32 paddr;
++ void __iomem *vaddr;
++ struct vrfb vrfb;
++ unsigned long size;
++ u8 type; /* OMAPFB_PLANE_MEM_* */
++ bool alloc; /* allocated by the driver */
++ bool map; /* kernel mapped by the driver */
++};
++
++/* appended to fb_info */
++struct omapfb_info {
++ int id;
++ struct omapfb2_mem_region region;
++ atomic_t map_count;
++ int num_overlays;
++ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
++ struct omapfb2_device *fbdev;
++ enum omap_dss_rotation_type rotation_type;
++ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
++ bool mirror;
++};
++
++struct omapfb2_device {
++ struct device *dev;
++ struct mutex mtx;
++
++ u32 pseudo_palette[17];
++
++ int state;
++
++ unsigned num_fbs;
++ struct fb_info *fbs[10];
++
++ unsigned num_displays;
++ struct omap_dss_device *displays[10];
++ unsigned num_overlays;
++ struct omap_overlay *overlays[10];
++ unsigned num_managers;
++ struct omap_overlay_manager *managers[10];
++};
++
++struct omapfb_colormode {
++ enum omap_color_mode dssmode;
++ u32 bits_per_pixel;
++ u32 nonstd;
++ struct fb_bitfield red;
++ struct fb_bitfield green;
++ struct fb_bitfield blue;
++ struct fb_bitfield transp;
++};
++
++void set_fb_fix(struct fb_info *fbi);
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
++int omapfb_apply_changes(struct fb_info *fbi, int init);
++
++int omapfb_create_sysfs(struct omapfb2_device *fbdev);
++void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
++
++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
++
++int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
++ struct fb_var_screeninfo *var);
++
++/* find the display connected to this fb, if any */
++static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int i;
++
++ /* XXX: returns the display connected to first attached overlay */
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager)
++ return ofbi->overlays[i]->manager->device;
++ }
++
++ return NULL;
++}
++
++static inline void omapfb_lock(struct omapfb2_device *fbdev)
++{
++ mutex_lock(&fbdev->mtx);
++}
++
++static inline void omapfb_unlock(struct omapfb2_device *fbdev)
++{
++ mutex_unlock(&fbdev->mtx);
++}
++
++static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
++ int enable)
++{
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++ info.enabled = enable;
++ return ovl->set_overlay_info(ovl, &info);
++}
++
++#endif
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index a3611d3..52e0987 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -24,6 +24,7 @@
+ #ifndef __LINUX_OMAPFB_H__
+ #define __LINUX_OMAPFB_H__
+
++#include <linux/fb.h>
+ #include <linux/ioctl.h>
+ #include <linux/types.h>
+
+@@ -50,6 +51,11 @@
+ #define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
+ #define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
+ #define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
++#define OMAPFB_WAITFORVSYNC OMAP_IO(57)
++#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
++#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
++#define OMAPFB_WAITFORGO OMAP_IO(60)
++#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info)
+
+ #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+ #define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+@@ -87,6 +93,13 @@ enum omapfb_color_format {
+ OMAPFB_COLOR_CLUT_1BPP,
+ OMAPFB_COLOR_RGB444,
+ OMAPFB_COLOR_YUY422,
++
++ OMAPFB_COLOR_ARGB16,
++ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */
++ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */
++ OMAPFB_COLOR_ARGB32,
++ OMAPFB_COLOR_RGBA32,
++ OMAPFB_COLOR_RGBX32,
+ };
+
+ struct omapfb_update_window {
+@@ -158,6 +171,33 @@ enum omapfb_update_mode {
+ OMAPFB_MANUAL_UPDATE
+ };
+
++struct omapfb_memory_read {
++ __u16 x;
++ __u16 y;
++ __u16 w;
++ __u16 h;
++ size_t buffer_size;
++ void __user *buffer;
++};
++
++struct omapfb_ovl_colormode {
++ __u8 overlay_idx;
++ __u8 mode_idx;
++ __u32 bits_per_pixel;
++ __u32 nonstd;
++ struct fb_bitfield red;
++ struct fb_bitfield green;
++ struct fb_bitfield blue;
++ struct fb_bitfield transp;
++};
++
++struct omapfb_vram_info {
++ __u32 total;
++ __u32 free;
++ __u32 largest_free_block;
++ __u32 reserved[5];
++};
++
+ #ifdef __KERNEL__
+
+ #include <mach/board.h>
+@@ -173,6 +213,11 @@ struct omapfb_mem_region {
+ void __iomem *vaddr;
+ unsigned long size;
+ u8 type; /* OMAPFB_PLANE_MEM_* */
++ enum omapfb_color_format format;/* OMAPFB_COLOR_* */
++ unsigned format_used:1; /* Must be set when format is set.
++ * Needed b/c of the badly chosen 0
++ * base for OMAPFB_COLOR_* values
++ */
+ unsigned alloc:1; /* allocated by the driver */
+ unsigned map:1; /* kernel mapped by the driver */
+ };
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch b/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch
new file mode 100644
index 0000000000..fd9db5ae27
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch
@@ -0,0 +1,471 @@
+From e2ddc67b0d9a3450382110edfaca18ecd44804bc Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 4 Aug 2009 16:41:45 +0300
+Subject: [PATCH 16/18] OMAP: DSS2: Add DPI panel drivers
+
+- Generic panel
+- Samsung LTE430WQ-F0C LCD Panel
+- Sharp LS037V7DW01 LCD Panel
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/Kconfig | 1 +
+ drivers/video/omap2/Makefile | 1 +
+ drivers/video/omap2/displays/Kconfig | 22 +++
+ drivers/video/omap2/displays/Makefile | 3 +
+ drivers/video/omap2/displays/panel-generic.c | 104 +++++++++++++
+ .../omap2/displays/panel-samsung-lte430wq-f0c.c | 113 +++++++++++++++
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 153 ++++++++++++++++++++
+ 7 files changed, 397 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/displays/Kconfig
+ create mode 100644 drivers/video/omap2/displays/Makefile
+ create mode 100644 drivers/video/omap2/displays/panel-generic.c
+ create mode 100644 drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+ create mode 100644 drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+index 3e60d7e..d877c36 100644
+--- a/drivers/video/omap2/Kconfig
++++ b/drivers/video/omap2/Kconfig
+@@ -6,3 +6,4 @@ config OMAP2_VRFB
+
+ source "drivers/video/omap2/dss/Kconfig"
+ source "drivers/video/omap2/omapfb/Kconfig"
++source "drivers/video/omap2/displays/Kconfig"
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+index 3ba6ef5..d853d05 100644
+--- a/drivers/video/omap2/Makefile
++++ b/drivers/video/omap2/Makefile
+@@ -3,3 +3,4 @@ obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
+
+ obj-y += dss/
+ obj-y += omapfb/
++obj-y += displays/
+diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
+new file mode 100644
+index 0000000..396905d
+--- /dev/null
++++ b/drivers/video/omap2/displays/Kconfig
+@@ -0,0 +1,22 @@
++menu "OMAP2/3 Display Device Drivers"
++ depends on OMAP2_DSS
++
++config PANEL_GENERIC
++ tristate "Generic Panel"
++ help
++ Generic panel driver.
++ Used for DVI output for Beagle and OMAP3 SDP.
++
++config PANEL_SAMSUNG_LTE430WQ_F0C
++ tristate "Samsung LTE430WQ-F0C LCD Panel"
++ depends on OMAP2_DSS
++ help
++ LCD Panel used on Overo Palo43
++
++config PANEL_SHARP_LS037V7DW01
++ tristate "Sharp LS037V7DW01 LCD Panel"
++ depends on OMAP2_DSS
++ help
++ LCD Panel used in TI's SDP3430 and EVM boards
++
++endmenu
+diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
+new file mode 100644
+index 0000000..a26bbd2
+--- /dev/null
++++ b/drivers/video/omap2/displays/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
++obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
++obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
+new file mode 100644
+index 0000000..738147e
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-generic.c
+@@ -0,0 +1,104 @@
++/*
++ * Generic panel support
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static struct omap_video_timings generic_panel_timings = {
++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
++ .x_res = 640,
++ .y_res = 480,
++ .pixel_clock = 23500,
++ .hfp = 48,
++ .hsw = 32,
++ .hbp = 80,
++ .vfp = 3,
++ .vsw = 4,
++ .vbp = 7,
++};
++
++static int generic_panel_probe(struct omap_dss_device *dssdev)
++{
++ dssdev->panel.config = OMAP_DSS_LCD_TFT;
++ dssdev->panel.timings = generic_panel_timings;
++
++ return 0;
++}
++
++static void generic_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++static int generic_panel_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ return r;
++}
++
++static void generic_panel_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++}
++
++static int generic_panel_suspend(struct omap_dss_device *dssdev)
++{
++ generic_panel_disable(dssdev);
++ return 0;
++}
++
++static int generic_panel_resume(struct omap_dss_device *dssdev)
++{
++ return generic_panel_enable(dssdev);
++}
++
++static struct omap_dss_driver generic_driver = {
++ .probe = generic_panel_probe,
++ .remove = generic_panel_remove,
++
++ .enable = generic_panel_enable,
++ .disable = generic_panel_disable,
++ .suspend = generic_panel_suspend,
++ .resume = generic_panel_resume,
++
++ .driver = {
++ .name = "generic_panel",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init generic_panel_drv_init(void)
++{
++ return omap_dss_register_driver(&generic_driver);
++}
++
++static void __exit generic_panel_drv_exit(void)
++{
++ omap_dss_unregister_driver(&generic_driver);
++}
++
++module_init(generic_panel_drv_init);
++module_exit(generic_panel_drv_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+new file mode 100644
+index 0000000..eafe581
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+@@ -0,0 +1,113 @@
++/*
++ * LCD panel driver for Samsung LTE430WQ-F0C
++ *
++ * Author: Steve Sakoman <steve@sakoman.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static struct omap_video_timings samsung_lte_timings = {
++ .x_res = 480,
++ .y_res = 272,
++
++ .pixel_clock = 9200,
++
++ .hsw = 41,
++ .hfp = 8,
++ .hbp = 45-41,
++
++ .vsw = 10,
++ .vfp = 4,
++ .vbp = 12-10,
++};
++
++static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
++{
++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
++ OMAP_DSS_LCD_IHS;
++ dssdev->panel.timings = samsung_lte_timings;
++
++ return 0;
++}
++
++static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ return r;
++}
++
++static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++
++ msleep(100);
++}
++
++static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
++{
++ samsung_lte_panel_disable(dssdev);
++ return 0;
++}
++
++static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
++{
++ return samsung_lte_panel_enable(dssdev);
++}
++
++static struct omap_dss_driver samsung_lte_driver = {
++ .probe = samsung_lte_panel_probe,
++ .remove = samsung_lte_panel_remove,
++
++ .enable = samsung_lte_panel_enable,
++ .disable = samsung_lte_panel_disable,
++ .suspend = samsung_lte_panel_suspend,
++ .resume = samsung_lte_panel_resume,
++
++ .driver = {
++ .name = "samsung_lte_panel",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init samsung_lte_panel_drv_init(void)
++{
++ return omap_dss_register_driver(&samsung_lte_driver);
++}
++
++static void __exit samsung_lte_panel_drv_exit(void)
++{
++ omap_dss_unregister_driver(&samsung_lte_driver);
++}
++
++module_init(samsung_lte_panel_drv_init);
++module_exit(samsung_lte_panel_drv_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+new file mode 100644
+index 0000000..2f8f0df
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+@@ -0,0 +1,153 @@
++/*
++ * LCD panel driver for Sharp LS037V7DW01
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/err.h>
++
++#include <mach/display.h>
++
++struct sharp_data {
++ /* XXX This regulator should actually be in SDP board file, not here,
++ * as it doesn't actually power the LCD, but something else that
++ * affects the output to LCD (I think. Somebody clarify). It doesn't do
++ * harm here, as SDP is the only board using this currently */
++ struct regulator *vdvi_reg;
++};
++
++static struct omap_video_timings sharp_ls_timings = {
++ .x_res = 480,
++ .y_res = 640,
++
++ .pixel_clock = 19200,
++
++ .hsw = 2,
++ .hfp = 1,
++ .hbp = 28,
++
++ .vsw = 1,
++ .vfp = 1,
++ .vbp = 1,
++};
++
++static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
++{
++ struct sharp_data *sd;
++
++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
++ OMAP_DSS_LCD_IHS;
++ dssdev->panel.acb = 0x28;
++ dssdev->panel.timings = sharp_ls_timings;
++
++ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
++ if (!sd)
++ return -ENOMEM;
++
++ dev_set_drvdata(&dssdev->dev, sd);
++
++ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
++ if (IS_ERR(sd->vdvi_reg)) {
++ kfree(sd);
++ pr_err("failed to get VDVI regulator\n");
++ return PTR_ERR(sd->vdvi_reg);
++ }
++
++ return 0;
++}
++
++static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
++{
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
++
++ regulator_put(sd->vdvi_reg);
++
++ kfree(sd);
++}
++
++static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
++{
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ regulator_enable(sd->vdvi_reg);
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ return r;
++}
++
++static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
++{
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
++
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ regulator_disable(sd->vdvi_reg);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++
++ msleep(100);
++}
++
++static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
++{
++ sharp_ls_panel_disable(dssdev);
++ return 0;
++}
++
++static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
++{
++ return sharp_ls_panel_enable(dssdev);
++}
++
++static struct omap_dss_driver sharp_ls_driver = {
++ .probe = sharp_ls_panel_probe,
++ .remove = sharp_ls_panel_remove,
++
++ .enable = sharp_ls_panel_enable,
++ .disable = sharp_ls_panel_disable,
++ .suspend = sharp_ls_panel_suspend,
++ .resume = sharp_ls_panel_resume,
++
++ .driver = {
++ .name = "sharp_ls_panel",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init sharp_ls_panel_drv_init(void)
++{
++ return omap_dss_register_driver(&sharp_ls_driver);
++}
++
++static void __exit sharp_ls_panel_drv_exit(void)
++{
++ omap_dss_unregister_driver(&sharp_ls_driver);
++}
++
++module_init(sharp_ls_panel_drv_init);
++module_exit(sharp_ls_panel_drv_exit);
++MODULE_LICENSE("GPL");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch
new file mode 100644
index 0000000000..c58ce9d36b
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch
@@ -0,0 +1,947 @@
+From fc8cd50c04b519f3839e9dc505532e725c7af080 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 7 Aug 2009 14:45:05 +0300
+Subject: [PATCH 17/18] OMAP: DSS2: Taal DSI command mode panel driver
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/displays/Kconfig | 6 +
+ drivers/video/omap2/displays/Makefile | 2 +
+ drivers/video/omap2/displays/panel-taal.c | 900 +++++++++++++++++++++++++++++
+ 3 files changed, 908 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/displays/panel-taal.c
+
+diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
+index 396905d..79d2861 100644
+--- a/drivers/video/omap2/displays/Kconfig
++++ b/drivers/video/omap2/displays/Kconfig
+@@ -19,4 +19,10 @@ config PANEL_SHARP_LS037V7DW01
+ help
+ LCD Panel used in TI's SDP3430 and EVM boards
+
++config PANEL_TAAL
++ tristate "Taal DSI Panel"
++ depends on OMAP2_DSS_DSI
++ help
++ Taal DSI command mode panel from TPO.
++
+ endmenu
+diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
+index a26bbd2..d44e765 100644
+--- a/drivers/video/omap2/displays/Makefile
++++ b/drivers/video/omap2/displays/Makefile
+@@ -1,3 +1,5 @@
+ obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
+ obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
+ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
++
++obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
+new file mode 100644
+index 0000000..84f0d47
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-taal.c
+@@ -0,0 +1,900 @@
++/*
++ * Taal DSI command mode panel
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*#define DEBUG*/
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/jiffies.h>
++#include <linux/sched.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++#include <linux/interrupt.h>
++#include <linux/gpio.h>
++#include <linux/completion.h>
++
++#include <mach/display.h>
++
++/* DSI Virtual channel. Hardcoded for now. */
++#define TCH 0
++
++#define DCS_READ_NUM_ERRORS 0x05
++#define DCS_READ_POWER_MODE 0x0a
++#define DCS_READ_MADCTL 0x0b
++#define DCS_READ_PIXEL_FORMAT 0x0c
++#define DCS_SLEEP_IN 0x10
++#define DCS_SLEEP_OUT 0x11
++#define DCS_DISPLAY_OFF 0x28
++#define DCS_DISPLAY_ON 0x29
++#define DCS_COLUMN_ADDR 0x2a
++#define DCS_PAGE_ADDR 0x2b
++#define DCS_MEMORY_WRITE 0x2c
++#define DCS_TEAR_OFF 0x34
++#define DCS_TEAR_ON 0x35
++#define DCS_MEM_ACC_CTRL 0x36
++#define DCS_PIXEL_FORMAT 0x3a
++#define DCS_BRIGHTNESS 0x51
++#define DCS_CTRL_DISPLAY 0x53
++#define DCS_WRITE_CABC 0x55
++#define DCS_READ_CABC 0x56
++#define DCS_GET_ID1 0xda
++#define DCS_GET_ID2 0xdb
++#define DCS_GET_ID3 0xdc
++
++struct taal_data {
++ struct backlight_device *bldev;
++
++ unsigned long hw_guard_end; /* next value of jiffies when we can
++ * issue the next sleep in/out command
++ */
++ unsigned long hw_guard_wait; /* max guard time in jiffies */
++
++ struct omap_dss_device *dssdev;
++
++ bool enabled;
++ u8 rotate;
++ bool mirror;
++
++ bool te_enabled;
++ bool use_ext_te;
++ struct completion te_completion;
++
++ bool use_dsi_bl;
++
++ bool cabc_broken;
++ unsigned cabc_mode;
++
++ bool intro_printed;
++};
++
++static void hw_guard_start(struct taal_data *td, int guard_msec)
++{
++ td->hw_guard_wait = msecs_to_jiffies(guard_msec);
++ td->hw_guard_end = jiffies + td->hw_guard_wait;
++}
++
++static void hw_guard_wait(struct taal_data *td)
++{
++ unsigned long wait = td->hw_guard_end - jiffies;
++
++ if ((long)wait > 0 && wait <= td->hw_guard_wait) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(wait);
++ }
++}
++
++static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
++{
++ int r;
++ u8 buf[1];
++
++ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
++
++ if (r < 0)
++ return r;
++
++ *data = buf[0];
++
++ return 0;
++}
++
++static int taal_dcs_write_0(u8 dcs_cmd)
++{
++ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
++}
++
++static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
++{
++ u8 buf[2];
++ buf[0] = dcs_cmd;
++ buf[1] = param;
++ return dsi_vc_dcs_write(TCH, buf, 2);
++}
++
++static int taal_sleep_in(struct taal_data *td)
++
++{
++ u8 cmd;
++ int r;
++
++ hw_guard_wait(td);
++
++ cmd = DCS_SLEEP_IN;
++ r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
++ if (r)
++ return r;
++
++ hw_guard_start(td, 120);
++
++ msleep(5);
++
++ return 0;
++}
++
++static int taal_sleep_out(struct taal_data *td)
++{
++ int r;
++
++ hw_guard_wait(td);
++
++ r = taal_dcs_write_0(DCS_SLEEP_OUT);
++ if (r)
++ return r;
++
++ hw_guard_start(td, 120);
++
++ msleep(5);
++
++ return 0;
++}
++
++static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
++{
++ int r;
++
++ r = taal_dcs_read_1(DCS_GET_ID1, id1);
++ if (r)
++ return r;
++ r = taal_dcs_read_1(DCS_GET_ID2, id2);
++ if (r)
++ return r;
++ r = taal_dcs_read_1(DCS_GET_ID3, id3);
++ if (r)
++ return r;
++
++ return 0;
++}
++
++static int taal_set_addr_mode(u8 rotate, bool mirror)
++{
++ int r;
++ u8 mode;
++ int b5, b6, b7;
++
++ r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
++ if (r)
++ return r;
++
++ switch (rotate) {
++ default:
++ case 0:
++ b7 = 0;
++ b6 = 0;
++ b5 = 0;
++ break;
++ case 1:
++ b7 = 0;
++ b6 = 1;
++ b5 = 1;
++ break;
++ case 2:
++ b7 = 1;
++ b6 = 1;
++ b5 = 0;
++ break;
++ case 3:
++ b7 = 1;
++ b6 = 0;
++ b5 = 1;
++ break;
++ }
++
++ if (mirror)
++ b6 = !b6;
++
++ mode &= ~((1<<7) | (1<<6) | (1<<5));
++ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
++
++ return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
++}
++
++static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
++{
++ int r;
++ u16 x1 = x;
++ u16 x2 = x + w - 1;
++ u16 y1 = y;
++ u16 y2 = y + h - 1;
++
++ u8 buf[5];
++ buf[0] = DCS_COLUMN_ADDR;
++ buf[1] = (x1 >> 8) & 0xff;
++ buf[2] = (x1 >> 0) & 0xff;
++ buf[3] = (x2 >> 8) & 0xff;
++ buf[4] = (x2 >> 0) & 0xff;
++
++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
++ if (r)
++ return r;
++
++ buf[0] = DCS_PAGE_ADDR;
++ buf[1] = (y1 >> 8) & 0xff;
++ buf[2] = (y1 >> 0) & 0xff;
++ buf[3] = (y2 >> 8) & 0xff;
++ buf[4] = (y2 >> 0) & 0xff;
++
++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
++ if (r)
++ return r;
++
++ dsi_vc_send_bta_sync(TCH);
++
++ return r;
++}
++
++static int taal_bl_update_status(struct backlight_device *dev)
++{
++ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ int r;
++ int level;
++
++ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
++ dev->props.power == FB_BLANK_UNBLANK)
++ level = dev->props.brightness;
++ else
++ level = 0;
++
++ dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
++
++ if (td->use_dsi_bl) {
++ if (td->enabled) {
++ dsi_bus_lock();
++ r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
++ dsi_bus_unlock();
++ if (r)
++ return r;
++ }
++ } else {
++ if (!dssdev->set_backlight)
++ return -EINVAL;
++
++ r = dssdev->set_backlight(dssdev, level);
++ if (r)
++ return r;
++ }
++
++ return 0;
++}
++
++static int taal_bl_get_intensity(struct backlight_device *dev)
++{
++ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
++ dev->props.power == FB_BLANK_UNBLANK)
++ return dev->props.brightness;
++
++ return 0;
++}
++
++static struct backlight_ops taal_bl_ops = {
++ .get_brightness = taal_bl_get_intensity,
++ .update_status = taal_bl_update_status,
++};
++
++static void taal_get_timings(struct omap_dss_device *dssdev,
++ struct omap_video_timings *timings)
++{
++ *timings = dssdev->panel.timings;
++}
++
++static void taal_get_resolution(struct omap_dss_device *dssdev,
++ u16 *xres, u16 *yres)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++
++ if (td->rotate == 0 || td->rotate == 2) {
++ *xres = dssdev->panel.timings.x_res;
++ *yres = dssdev->panel.timings.y_res;
++ } else {
++ *yres = dssdev->panel.timings.x_res;
++ *xres = dssdev->panel.timings.y_res;
++ }
++}
++
++static irqreturn_t taal_te_isr(int irq, void *data)
++{
++ struct omap_dss_device *dssdev = data;
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++
++ complete_all(&td->te_completion);
++
++ return IRQ_HANDLED;
++}
++
++static ssize_t taal_num_errors_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ u8 errors;
++ int r;
++
++ if (td->enabled) {
++ dsi_bus_lock();
++ r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
++ dsi_bus_unlock();
++ } else {
++ r = -ENODEV;
++ }
++
++ if (r)
++ return r;
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", errors);
++}
++
++static ssize_t taal_hw_revision_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ u8 id1, id2, id3;
++ int r;
++
++ if (td->enabled) {
++ dsi_bus_lock();
++ r = taal_get_id(&id1, &id2, &id3);
++ dsi_bus_unlock();
++ } else {
++ r = -ENODEV;
++ }
++
++ if (r)
++ return r;
++
++ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
++}
++
++static const char *cabc_modes[] = {
++ "off", /* used also always when CABC is not supported */
++ "ui",
++ "still-image",
++ "moving-image",
++};
++
++static ssize_t show_cabc_mode(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ const char *mode_str;
++ int mode;
++ int len;
++
++ mode = td->cabc_mode;
++
++ mode_str = "unknown";
++ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
++ mode_str = cabc_modes[mode];
++ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
++
++ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
++}
++
++static ssize_t store_cabc_mode(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
++ if (sysfs_streq(cabc_modes[i], buf))
++ break;
++ }
++
++ if (i == ARRAY_SIZE(cabc_modes))
++ return -EINVAL;
++
++ if (td->enabled) {
++ dsi_bus_lock();
++ if (!td->cabc_broken)
++ taal_dcs_write_1(DCS_WRITE_CABC, i);
++ dsi_bus_unlock();
++ }
++
++ td->cabc_mode = i;
++
++ return count;
++}
++
++static ssize_t show_cabc_available_modes(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ int len;
++ int i;
++
++ for (i = 0, len = 0;
++ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
++ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
++ i ? " " : "", cabc_modes[i],
++ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
++
++ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
++}
++
++static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
++static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
++static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
++ show_cabc_mode, store_cabc_mode);
++static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
++ show_cabc_available_modes, NULL);
++
++static struct attribute *taal_attrs[] = {
++ &dev_attr_num_dsi_errors.attr,
++ &dev_attr_hw_revision.attr,
++ &dev_attr_cabc_mode.attr,
++ &dev_attr_cabc_available_modes.attr,
++ NULL,
++};
++
++static struct attribute_group taal_attr_group = {
++ .attrs = taal_attrs,
++};
++
++static int taal_probe(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td;
++ struct backlight_device *bldev;
++ int r;
++
++ const struct omap_video_timings taal_panel_timings = {
++ .x_res = 864,
++ .y_res = 480,
++ };
++
++ dev_dbg(&dssdev->dev, "probe\n");
++
++ dssdev->panel.config = OMAP_DSS_LCD_TFT;
++ dssdev->panel.timings = taal_panel_timings;
++ dssdev->ctrl.pixel_size = 24;
++
++ td = kzalloc(sizeof(*td), GFP_KERNEL);
++ if (!td) {
++ r = -ENOMEM;
++ goto err0;
++ }
++
++ dev_set_drvdata(&dssdev->dev, td);
++
++ dssdev->get_timings = taal_get_timings;
++ dssdev->get_resolution = taal_get_resolution;
++
++ /* if no platform set_backlight() defined, presume DSI backlight
++ * control */
++ if (!dssdev->set_backlight)
++ td->use_dsi_bl = true;
++
++ bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
++ &taal_bl_ops);
++ if (IS_ERR(bldev)) {
++ r = PTR_ERR(bldev);
++ goto err1;
++ }
++
++ td->bldev = bldev;
++
++ bldev->props.fb_blank = FB_BLANK_UNBLANK;
++ bldev->props.power = FB_BLANK_UNBLANK;
++ if (td->use_dsi_bl) {
++ bldev->props.max_brightness = 255;
++ bldev->props.brightness = 255;
++ } else {
++ bldev->props.max_brightness = 127;
++ bldev->props.brightness = 127;
++ }
++
++ taal_bl_update_status(bldev);
++
++ if (dssdev->phy.dsi.ext_te) {
++ int gpio = dssdev->phy.dsi.ext_te_gpio;
++
++ r = gpio_request(gpio, "taal irq");
++ if (r) {
++ dev_err(&dssdev->dev, "GPIO request failed\n");
++ goto err2;
++ }
++
++ gpio_direction_input(gpio);
++
++ r = request_irq(gpio_to_irq(gpio), taal_te_isr,
++ IRQF_DISABLED | IRQF_TRIGGER_RISING,
++ "taal vsync", dssdev);
++
++ if (r) {
++ dev_err(&dssdev->dev, "IRQ request failed\n");
++ gpio_free(gpio);
++ goto err2;
++ }
++
++ init_completion(&td->te_completion);
++
++ td->use_ext_te = true;
++ }
++
++ r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
++ if (r) {
++ dev_err(&dssdev->dev, "failed to create sysfs files\n");
++ goto err3;
++ }
++
++ return 0;
++err3:
++ if (td->use_ext_te) {
++ int gpio = dssdev->phy.dsi.ext_te_gpio;
++ free_irq(gpio_to_irq(gpio), dssdev);
++ gpio_free(gpio);
++ }
++err2:
++ backlight_device_unregister(bldev);
++err1:
++ kfree(td);
++err0:
++ return r;
++}
++
++static void taal_remove(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ struct backlight_device *bldev;
++
++ dev_dbg(&dssdev->dev, "remove\n");
++
++ sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
++
++ if (td->use_ext_te) {
++ int gpio = dssdev->phy.dsi.ext_te_gpio;
++ free_irq(gpio_to_irq(gpio), dssdev);
++ gpio_free(gpio);
++ }
++
++ bldev = td->bldev;
++ bldev->props.power = FB_BLANK_POWERDOWN;
++ taal_bl_update_status(bldev);
++ backlight_device_unregister(bldev);
++
++ kfree(td);
++}
++
++static int taal_enable(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ u8 id1, id2, id3;
++ int r;
++
++ dev_dbg(&dssdev->dev, "enable\n");
++
++ if (dssdev->platform_enable) {
++ r = dssdev->platform_enable(dssdev);
++ if (r)
++ return r;
++ }
++
++ /* it seems we have to wait a bit until taal is ready */
++ msleep(5);
++
++ r = taal_sleep_out(td);
++ if (r)
++ return r;
++
++ r = taal_get_id(&id1, &id2, &id3);
++ if (r)
++ return r;
++
++ /* on early revisions CABC is broken */
++ if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
++ td->cabc_broken = true;
++
++ taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
++ taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
++
++ taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
++
++ taal_set_addr_mode(td->rotate, td->mirror);
++ if (!td->cabc_broken)
++ taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
++
++ taal_dcs_write_0(DCS_DISPLAY_ON);
++
++ td->enabled = 1;
++
++ if (!td->intro_printed) {
++ dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
++ id1, id2, id3);
++ if (td->cabc_broken)
++ dev_info(&dssdev->dev,
++ "old Taal version, CABC disabled\n");
++ td->intro_printed = true;
++ }
++
++ return 0;
++}
++
++static void taal_disable(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++
++ dev_dbg(&dssdev->dev, "disable\n");
++
++ taal_dcs_write_0(DCS_DISPLAY_OFF);
++ taal_sleep_in(td);
++
++ /* wait a bit so that the message goes through */
++ msleep(10);
++
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ td->enabled = 0;
++}
++
++static int taal_suspend(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ struct backlight_device *bldev = td->bldev;
++
++ bldev->props.power = FB_BLANK_POWERDOWN;
++ taal_bl_update_status(bldev);
++
++ return 0;
++}
++
++static int taal_resume(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ struct backlight_device *bldev = td->bldev;
++
++ bldev->props.power = FB_BLANK_UNBLANK;
++ taal_bl_update_status(bldev);
++
++ return 0;
++}
++
++static void taal_setup_update(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ taal_set_update_window(x, y, w, h);
++}
++
++static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ int r;
++
++ td->te_enabled = enable;
++
++ if (enable)
++ r = taal_dcs_write_1(DCS_TEAR_ON, 0);
++ else
++ r = taal_dcs_write_0(DCS_TEAR_OFF);
++
++ return r;
++}
++
++static int taal_wait_te(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ long wait = msecs_to_jiffies(500);
++
++ if (!td->use_ext_te || !td->te_enabled)
++ return 0;
++
++ INIT_COMPLETION(td->te_completion);
++ wait = wait_for_completion_timeout(&td->te_completion, wait);
++ if (wait == 0) {
++ dev_err(&dssdev->dev, "timeout waiting TE\n");
++ return -ETIME;
++ }
++
++ return 0;
++}
++
++static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ int r;
++
++ dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
++
++ if (td->enabled) {
++ r = taal_set_addr_mode(rotate, td->mirror);
++
++ if (r)
++ return r;
++ }
++
++ td->rotate = rotate;
++
++ return 0;
++}
++
++static u8 taal_get_rotate(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ return td->rotate;
++}
++
++static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ int r;
++
++ dev_dbg(&dssdev->dev, "mirror %d\n", enable);
++
++ if (td->enabled) {
++ r = taal_set_addr_mode(td->rotate, enable);
++
++ if (r)
++ return r;
++ }
++
++ td->mirror = enable;
++
++ return 0;
++}
++
++static bool taal_get_mirror(struct omap_dss_device *dssdev)
++{
++ struct taal_data *td = dev_get_drvdata(&dssdev->dev);
++ return td->mirror;
++}
++
++static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
++{
++ u8 id1, id2, id3;
++ int r;
++
++ r = taal_dcs_read_1(DCS_GET_ID1, &id1);
++ if (r)
++ return r;
++ r = taal_dcs_read_1(DCS_GET_ID2, &id2);
++ if (r)
++ return r;
++ r = taal_dcs_read_1(DCS_GET_ID3, &id3);
++ if (r)
++ return r;
++
++ return 0;
++}
++
++static int taal_memory_read(struct omap_dss_device *dssdev,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int r;
++ int first = 1;
++ int plen;
++ unsigned buf_used = 0;
++
++ if (size < w * h * 3)
++ return -ENOMEM;
++
++ size = min(w * h * 3,
++ dssdev->panel.timings.x_res *
++ dssdev->panel.timings.y_res * 3);
++
++ /* plen 1 or 2 goes into short packet. until checksum error is fixed,
++ * use short packets. plen 32 works, but bigger packets seem to cause
++ * an error. */
++ if (size % 2)
++ plen = 1;
++ else
++ plen = 2;
++
++ taal_setup_update(dssdev, x, y, w, h);
++
++ r = dsi_vc_set_max_rx_packet_size(TCH, plen);
++ if (r)
++ return r;
++
++ while (buf_used < size) {
++ u8 dcs_cmd = first ? 0x2e : 0x3e;
++ first = 0;
++
++ r = dsi_vc_dcs_read(TCH, dcs_cmd,
++ buf + buf_used, size - buf_used);
++
++ if (r < 0) {
++ dev_err(&dssdev->dev, "read error\n");
++ goto err;
++ }
++
++ buf_used += r;
++
++ if (r < plen) {
++ dev_err(&dssdev->dev, "short read\n");
++ break;
++ }
++ }
++
++ r = buf_used;
++
++err:
++ dsi_vc_set_max_rx_packet_size(TCH, 1);
++
++ return r;
++}
++
++static struct omap_dss_driver taal_driver = {
++ .probe = taal_probe,
++ .remove = taal_remove,
++
++ .enable = taal_enable,
++ .disable = taal_disable,
++ .suspend = taal_suspend,
++ .resume = taal_resume,
++
++ .setup_update = taal_setup_update,
++ .enable_te = taal_enable_te,
++ .wait_for_te = taal_wait_te,
++ .set_rotate = taal_rotate,
++ .get_rotate = taal_get_rotate,
++ .set_mirror = taal_mirror,
++ .get_mirror = taal_get_mirror,
++ .run_test = taal_run_test,
++ .memory_read = taal_memory_read,
++
++ .driver = {
++ .name = "taal",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init taal_init(void)
++{
++ omap_dss_register_driver(&taal_driver);
++
++ return 0;
++}
++
++static void __exit taal_exit(void)
++{
++ omap_dss_unregister_driver(&taal_driver);
++}
++
++module_init(taal_init);
++module_exit(taal_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("Taal Driver");
++MODULE_LICENSE("GPL");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch b/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch
new file mode 100644
index 0000000000..98cd5adb79
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch
@@ -0,0 +1,327 @@
+From 8319bb7f267e0434e2d26f30b6f50ff2b0701bd1 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 5 Aug 2009 16:07:26 +0300
+Subject: [PATCH 18/18] OMAP: SDP: Enable DSS2 for OMAP3 SDP board
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/configs/omap_3430sdp_defconfig | 61 +++++++++++-
+ arch/arm/mach-omap2/board-3430sdp.c | 172 +++++++++++++++++++++++++++---
+ 2 files changed, 214 insertions(+), 19 deletions(-)
+
+diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig
+index 8fb918d..de063f9 100644
+--- a/arch/arm/configs/omap_3430sdp_defconfig
++++ b/arch/arm/configs/omap_3430sdp_defconfig
+@@ -1314,7 +1314,56 @@ CONFIG_DVB_ISL6421=m
+ #
+ # CONFIG_VGASTATE is not set
+ # CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
++CONFIG_OMAP2_DSS=y
++CONFIG_OMAP2_VRAM_SIZE=0
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_RFBI is not set
++CONFIG_OMAP2_DSS_VENC=y
++# CONFIG_OMAP2_DSS_SDI is not set
++# CONFIG_OMAP2_DSS_DSI is not set
++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++CONFIG_FB_OMAP2=y
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
++CONFIG_FB_OMAP2_NUM_FBS=3
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC=y
++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
++CONFIG_PANEL_SHARP_LS037V7DW01=y
+ # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+@@ -1331,6 +1380,16 @@ CONFIG_DISPLAY_SUPPORT=y
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++# CONFIG_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
+ CONFIG_SOUND=y
+ CONFIG_SOUND_OSS_CORE=y
+ CONFIG_SND=y
+diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
+index ac262cd..a1ebc3f 100644
+--- a/arch/arm/mach-omap2/board-3430sdp.c
++++ b/arch/arm/mach-omap2/board-3430sdp.c
+@@ -36,6 +36,7 @@
+ #include <mach/common.h>
+ #include <mach/dma.h>
+ #include <mach/gpmc.h>
++#include <mach/display.h>
+
+ #include <mach/control.h>
+ #include <mach/keypad.h>
+@@ -148,23 +149,149 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
+ },
+ };
+
+-static struct platform_device sdp3430_lcd_device = {
+- .name = "sdp2430_lcd",
+- .id = -1,
++
++#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8
++#define SDP3430_LCD_PANEL_ENABLE_GPIO 5
++
++static unsigned backlight_gpio;
++static unsigned enable_gpio;
++static int lcd_enabled;
++static int dvi_enabled;
++
++static void __init sdp3430_display_init(void)
++{
++ int r;
++
++ enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
++ backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
++
++ r = gpio_request(enable_gpio, "LCD reset");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD reset GPIO\n");
++ goto err0;
++ }
++
++ r = gpio_request(backlight_gpio, "LCD Backlight");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD backlight GPIO\n");
++ goto err1;
++ }
++
++ gpio_direction_output(enable_gpio, 0);
++ gpio_direction_output(backlight_gpio, 0);
++
++ return;
++err1:
++ gpio_free(enable_gpio);
++err0:
++ return;
++}
++
++static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++
++ gpio_direction_output(enable_gpio, 1);
++ gpio_direction_output(backlight_gpio, 1);
++
++ lcd_enabled = 1;
++
++ return 0;
++}
++
++static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
++{
++ lcd_enabled = 0;
++
++ gpio_direction_output(enable_gpio, 0);
++ gpio_direction_output(backlight_gpio, 0);
++}
++
++static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++
++ dvi_enabled = 1;
++
++ return 0;
++}
++
++static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
++{
++ dvi_enabled = 0;
++}
++
++static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
++{
++ return 0;
++}
++
++static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
++{
++}
++
++
++static struct omap_dss_device sdp3430_lcd_device = {
++ .name = "lcd",
++ .driver_name = "sharp_ls_panel",
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .phy.dpi.data_lines = 16,
++ .platform_enable = sdp3430_panel_enable_lcd,
++ .platform_disable = sdp3430_panel_disable_lcd,
+ };
+
+-static struct regulator_consumer_supply sdp3430_vdac_supply = {
+- .supply = "vdac",
+- .dev = &sdp3430_lcd_device.dev,
++static struct omap_dss_device sdp3430_dvi_device = {
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .phy.dpi.data_lines = 24,
++ .platform_enable = sdp3430_panel_enable_dvi,
++ .platform_disable = sdp3430_panel_disable_dvi,
+ };
+
+-static struct regulator_consumer_supply sdp3430_vdvi_supply = {
+- .supply = "vdvi",
+- .dev = &sdp3430_lcd_device.dev,
++static struct omap_dss_device sdp3430_tv_device = {
++ .name = "tv",
++ .driver_name = "venc",
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .platform_enable = sdp3430_panel_enable_tv,
++ .platform_disable = sdp3430_panel_disable_tv,
+ };
+
+-static struct platform_device *sdp3430_devices[] __initdata = {
++
++static struct omap_dss_device *sdp3430_dss_devices[] = {
+ &sdp3430_lcd_device,
++ &sdp3430_dvi_device,
++ &sdp3430_tv_device,
++};
++
++static struct omap_dss_board_info sdp3430_dss_data = {
++ .num_devices = ARRAY_SIZE(sdp3430_dss_devices),
++ .devices = sdp3430_dss_devices,
++ .default_device = &sdp3430_lcd_device,
++};
++
++static struct platform_device sdp3430_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &sdp3430_dss_data,
++ },
++};
++
++static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
++ .supply = "vdda_dac",
++ .dev = &sdp3430_dss_device.dev,
++};
++
++static struct platform_device *sdp3430_devices[] __initdata = {
++ &sdp3430_dss_device,
+ };
+
+ static void __init omap_3430sdp_init_irq(void)
+@@ -178,13 +305,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+ };
+
+-static struct omap_lcd_config sdp3430_lcd_config __initdata = {
+- .ctrl_name = "internal",
+-};
+-
+ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
+ { OMAP_TAG_UART, &sdp3430_uart_config },
+- { OMAP_TAG_LCD, &sdp3430_lcd_config },
+ };
+
+ static int sdp3430_batt_table[] = {
+@@ -391,22 +513,34 @@ static struct regulator_init_data sdp3430_vdac = {
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+- .consumer_supplies = &sdp3430_vdac_supply,
++ .consumer_supplies = &sdp3430_vdda_dac_supply,
+ };
+
+ /* VPLL2 for digital video outputs */
++static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
++ {
++ .supply = "vdvi",
++ .dev = &sdp3430_lcd_device.dev,
++ },
++ {
++ .supply = "vdds_dsi",
++ .dev = &sdp3430_dss_device.dev,
++ }
++};
++
+ static struct regulator_init_data sdp3430_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
++ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+- .num_consumer_supplies = 1,
+- .consumer_supplies = &sdp3430_vdvi_supply,
++ .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies),
++ .consumer_supplies = sdp3430_vpll2_supplies,
+ };
+
+ static struct twl4030_platform_data sdp3430_twldata = {
+@@ -495,6 +629,8 @@ static void __init omap_3430sdp_init(void)
+ omap_serial_init();
+ usb_musb_init();
+ board_smc91x_init();
++
++ sdp3430_display_init();
+ }
+
+ static void __init omap_3430sdp_map_io(void)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/dss2/beagle-dss2-support.patch b/recipes/linux/linux-omap-2.6.31/dss2/beagle-dss2-support.patch
new file mode 100644
index 0000000000..53f921e087
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/dss2/beagle-dss2-support.patch
@@ -0,0 +1,326 @@
+--- /tmp/board-omap3beagle.c 2009-09-17 17:44:58.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-09-17 18:48:57.000000000 +0200
+@@ -31,6 +31,7 @@
+
+ #include <linux/regulator/machine.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -45,6 +46,7 @@
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/timer-gp.h>
++#include <mach/display.h>
+
+ #include "mmc-twl4030.h"
+
+@@ -169,15 +171,6 @@
+ {} /* Terminator */
+ };
+
+-static struct platform_device omap3_beagle_lcd_device = {
+- .name = "omap3beagle_lcd",
+- .id = -1,
+-};
+-
+-static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
+- .ctrl_name = "internal",
+-};
+-
+ static struct regulator_consumer_supply beagle_vmmc1_supply = {
+ .supply = "vmmc",
+ };
+@@ -228,16 +221,6 @@
+ .setup = beagle_twl_gpio_setup,
+ };
+
+-static struct regulator_consumer_supply beagle_vdac_supply = {
+- .supply = "vdac",
+- .dev = &omap3_beagle_lcd_device.dev,
+-};
+-
+-static struct regulator_consumer_supply beagle_vdvi_supply = {
+- .supply = "vdvi",
+- .dev = &omap3_beagle_lcd_device.dev,
+-};
+-
+ /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+ static struct regulator_init_data beagle_vmmc1 = {
+ .constraints = {
+@@ -268,61 +251,10 @@
+ .consumer_supplies = &beagle_vsim_supply,
+ };
+
+-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+-static struct regulator_init_data beagle_vdac = {
+- .constraints = {
+- .min_uV = 1800000,
+- .max_uV = 1800000,
+- .valid_modes_mask = REGULATOR_MODE_NORMAL
+- | REGULATOR_MODE_STANDBY,
+- .valid_ops_mask = REGULATOR_CHANGE_MODE
+- | REGULATOR_CHANGE_STATUS,
+- },
+- .num_consumer_supplies = 1,
+- .consumer_supplies = &beagle_vdac_supply,
+-};
+-
+-/* VPLL2 for digital video outputs */
+-static struct regulator_init_data beagle_vpll2 = {
+- .constraints = {
+- .name = "VDVI",
+- .min_uV = 1800000,
+- .max_uV = 1800000,
+- .valid_modes_mask = REGULATOR_MODE_NORMAL
+- | REGULATOR_MODE_STANDBY,
+- .valid_ops_mask = REGULATOR_CHANGE_MODE
+- | REGULATOR_CHANGE_STATUS,
+- },
+- .num_consumer_supplies = 1,
+- .consumer_supplies = &beagle_vdvi_supply,
+-};
+-
+ static struct twl4030_usb_data beagle_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+ };
+
+-static struct twl4030_platform_data beagle_twldata = {
+- .irq_base = TWL4030_IRQ_BASE,
+- .irq_end = TWL4030_IRQ_END,
+-
+- /* platform_data for children goes here */
+- .usb = &beagle_usb_data,
+- .gpio = &beagle_gpio_data,
+- .vmmc1 = &beagle_vmmc1,
+- .vsim = &beagle_vsim,
+- .vdac = &beagle_vdac,
+- .vpll2 = &beagle_vpll2,
+-};
+-
+-static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
+- {
+- I2C_BOARD_INFO("twl4030", 0x48),
+- .flags = I2C_CLIENT_WAKE,
+- .irq = INT_34XX_SYS_NIRQ,
+- .platform_data = &beagle_twldata,
+- },
+-};
+-
+ #if defined(CONFIG_RTC_DRV_DS1307) || \
+ defined(CONFIG_RTC_DRV_DS1307_MODULE)
+
+@@ -335,18 +267,6 @@
+ static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
+ #endif
+
+-static int __init omap3_beagle_i2c_init(void)
+-{
+- omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
+- ARRAY_SIZE(beagle_i2c1_boardinfo));
+- omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
+- ARRAY_SIZE(beagle_i2c2_boardinfo));
+- /* Bus 3 is attached to the DVI port where devices like the pico DLP
+- * projector don't work reliably with 400kHz */
+- omap_register_i2c_bus(3, 100, NULL, 0);
+- return 0;
+-}
+-
+ static struct gpio_led gpio_leds[] = {
+ {
+ .name = "beagleboard::usr0",
+@@ -400,14 +320,158 @@
+ },
+ };
+
+-static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+- { OMAP_TAG_LCD, &omap3_beagle_lcd_config },
++/* DSS */
++
++static int beagle_enable_dvi(struct omap_dss_device *dssdev)
++{
++ if (dssdev->reset_gpio != -1)
++ gpio_set_value(dssdev->reset_gpio, 1);
++
++ return 0;
++}
++
++static void beagle_disable_dvi(struct omap_dss_device *dssdev)
++{
++ if (dssdev->reset_gpio != -1)
++ gpio_set_value(dssdev->reset_gpio, 0);
++}
++
++static struct omap_dss_device beagle_dvi_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .phy.dpi.data_lines = 24,
++ .reset_gpio = 170,
++ .platform_enable = beagle_enable_dvi,
++ .platform_disable = beagle_disable_dvi,
+ };
+
++static int beagle_panel_enable_tv(struct omap_dss_device *dssdev)
++{
++ return 0;
++}
++
++static void beagle_panel_disable_tv(struct omap_dss_device *dssdev)
++{
++}
++
++static struct omap_dss_device beagle_tv_device = {
++ .name = "tv",
++ .driver_name = "venc",
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .platform_enable = beagle_panel_enable_tv,
++ .platform_disable = beagle_panel_disable_tv,
++};
++
++static struct omap_dss_device *beagle_dss_devices[] = {
++ &beagle_dvi_device,
++ &beagle_tv_device,
++};
++
++static struct omap_dss_board_info beagle_dss_data = {
++ .num_devices = ARRAY_SIZE(beagle_dss_devices),
++ .devices = beagle_dss_devices,
++ .default_device = &beagle_dvi_device,
++};
++
++static struct platform_device beagle_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &beagle_dss_data,
++ },
++};
++
++static struct regulator_consumer_supply beagle_vdda_dac_supply = {
++ .supply = "vdda_dac",
++ .dev = &beagle_dss_device.dev,
++};
++
++static struct regulator_consumer_supply beagle_vdds_dsi_supply = {
++ .supply = "vdds_dsi",
++ .dev = &beagle_dss_device.dev,
++};
++
++static void __init beagle_display_init(void)
++{
++ int r;
++
++ r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset");
++ if (r < 0) {
++ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
++ return;
++ }
++
++ gpio_direction_output(beagle_dvi_device.reset_gpio, 0);
++}
++
++/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
++static struct regulator_init_data beagle_vdac = {
++ .constraints = {
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .apply_uV = true,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vdda_dac_supply,
++};
++
++/* VPLL2 for digital video outputs */
++static struct regulator_init_data beagle_vpll2 = {
++ .constraints = {
++ .name = "VDVI",
++ .min_uV = 1800000,
++ .max_uV = 1800000, .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vdds_dsi_supply,
++};
++
++static struct twl4030_platform_data beagle_twldata = {
++ .irq_base = TWL4030_IRQ_BASE,
++ .irq_end = TWL4030_IRQ_END,
++
++ /* platform_data for children goes here */
++ .usb = &beagle_usb_data,
++ .gpio = &beagle_gpio_data,
++ .vmmc1 = &beagle_vmmc1,
++ .vsim = &beagle_vsim,
++ .vdac = &beagle_vdac,
++ .vpll2 = &beagle_vpll2,
++};
++
++static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
++ {
++ I2C_BOARD_INFO("twl4030", 0x48),
++ .flags = I2C_CLIENT_WAKE,
++ .irq = INT_34XX_SYS_NIRQ,
++ .platform_data = &beagle_twldata,
++ },
++};
++
++static int __init omap3_beagle_i2c_init(void)
++{
++ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
++ ARRAY_SIZE(beagle_i2c1_boardinfo));
++ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
++ ARRAY_SIZE(beagle_i2c2_boardinfo));
++ /* Bus 3 is attached to the DVI port where devices like the pico DLP
++ * projector don't work reliably with 400kHz */
++ omap_register_i2c_bus(3, 100, NULL, 0);
++ return 0;
++}
++
++
+ static void __init omap3_beagle_init_irq(void)
+ {
+- omap_board_config = omap3_beagle_config;
+- omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+ omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
+ omap_init_irq();
+@@ -418,7 +482,7 @@
+ }
+
+ static struct platform_device *omap3_beagle_devices[] __initdata = {
+- &omap3_beagle_lcd_device,
++ &beagle_dss_device,
+ &leds_gpio,
+ &keys_gpio,
+ };
+@@ -480,11 +544,8 @@
+ platform_add_devices(omap3_beagle_devices,
+ ARRAY_SIZE(omap3_beagle_devices));
+ omap_serial_init();
+-
++
+ omap_cfg_reg(J25_34XX_GPIO170);
+- gpio_request(170, "DVI_nPD");
+- /* REVISIT leave DVI powered down until it's needed ... */
+- gpio_direction_output(170, true);
+
+ omap3beagle_enc28j60_init();
+
+@@ -492,6 +553,8 @@
+ usb_ehci_init(&ehci_pdata);
+ omap3beagle_flash_init();
+
++ beagle_display_init();
++
+ /* Ensure SDRC pins are mux'd for self-refresh */
+ omap_cfg_reg(H16_34XX_SDRC_CKE0);
+ omap_cfg_reg(H17_34XX_SDRC_CKE1);
diff --git a/recipes/linux/linux-omap-2.6.31/echi.patch b/recipes/linux/linux-omap-2.6.31/echi.patch
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/echi.patch
diff --git a/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch b/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch
new file mode 100644
index 0000000000..71d96bcc86
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch
@@ -0,0 +1,122 @@
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 55db61e..1172887 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/leds.h>
+ #include <linux/gpio.h>
++#include <linux/irq.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
+
+@@ -56,6 +57,49 @@
+
+ #define NAND_BLOCK_SIZE SZ_128K
+
++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
++
++#include <mach/mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
++
++static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
++ .turbo_mode = 0,
++ .single_channel = 1, /* 0: slave, 1: master */
++};
++
++static struct spi_board_info omap3beagle_spi_board_info[] __initdata = {
++ {
++ .modalias = "enc28j60",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 20000000,
++ .controller_data = &enc28j60_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_enc28j60_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
++ omap3beagle_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
++ set_irq_type(omap3beagle_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_spi_board_info,
++ ARRAY_SIZE(omap3beagle_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_enc28j60_init(void) { return; }
++#endif
++
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -126,6 +170,14 @@ static struct twl4030_hsmmc_info mmc[] = {
+ .wires = 8,
+ .gpio_wp = 29,
+ },
++ {
++ .mmc = 2,
++ .wires = 4,
++ .gpio_wp = 141,
++ .gpio_cd = 162,
++ .transceiver = true,
++ .ocr_mask = 0x00100000, /* 3.3V */
++ },
+ {} /* Terminator */
+ };
+
+@@ -289,7 +341,7 @@ static struct twl4030_platform_data beagle_twldata = {
+ .vpll2 = &beagle_vpll2,
+ };
+
+-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
++static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+@@ -298,10 +350,24 @@ static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+ },
+ };
+
++#if defined(CONFIG_RTC_DRV_DS1307) || \
++ defined(CONFIG_RTC_DRV_DS1307_MODULE)
++
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
++ {
++ I2C_BOARD_INFO("ds1307", 0x68),
++ },
++};
++#else
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+- ARRAY_SIZE(beagle_i2c_boardinfo));
++ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
++ ARRAY_SIZE(beagle_i2c1_boardinfo));
++ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
++ ARRAY_SIZE(beagle_i2c2_boardinfo));
+ /* Bus 3 is attached to the DVI port where devices like the pico DLP
+ * projector don't work reliably with 400kHz */
+ omap_register_i2c_bus(3, 100, NULL, 0);
+@@ -512,6 +578,8 @@ static void __init omap3_beagle_init(void)
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
++ omap3beagle_enc28j60_init();
++
+ usb_musb_init();
+ usb_ehci_init();
+ omap3beagle_flash_init();
diff --git a/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch b/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch
new file mode 100644
index 0000000000..63f742e3f9
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch
@@ -0,0 +1,708 @@
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 491ac0f..3605b5d 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -108,6 +108,27 @@ config TWL4030_CORE
+ high speed USB OTG transceiver, an audio codec (on most
+ versions) and many other features.
+
++config TWL4030_MADC
++ tristate "TWL4030 MADC Driver"
++ depends on TWL4030_CORE
++ help
++ The TWL4030 Monitoring ADC driver enables the host
++ processor to monitor analog signals using analog-to-digital
++ conversions on the input source. TWL4030 MADC provides the
++ following features:
++ - Single 10-bit ADC with successive approximation register (SAR) conversion;
++ - Analog multiplexer for 16 inputs;
++ - Seven (of the 16) inputs are freely available;
++ - Battery voltage monitoring;
++ - Concurrent conversion request management;
++ - Interrupt signal to Primary Interrupt Handler;
++ - Averaging feature;
++ - Selective enable/disable of the averaging feature.
++
++ Say 'y' here to statically link this module into the kernel or 'm'
++ to build it as a dinamically loadable module. The module will be
++ called twl4030-madc.ko
++
+ config MFD_TMIO
+ bool
+ default n
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index 6f8a9a1..e8d0ee6 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -23,6 +23,7 @@ obj-$(CONFIG_TPS65010) += tps65010.o
+ obj-$(CONFIG_MENELAUS) += menelaus.o
+
+ obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
++obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
+
+ obj-$(CONFIG_MFD_CORE) += mfd-core.o
+
+diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
+new file mode 100644
+index 0000000..551c932
+--- /dev/null
++++ b/drivers/mfd/twl4030-madc.c
+@@ -0,0 +1,526 @@
++/*
++ * TWL4030 MADC module driver
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Mikko Ylinen <mikko.k.ylinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/miscdevice.h>
++#include <linux/i2c/twl4030.h>
++#include <linux/i2c/twl4030-madc.h>
++
++#include <asm/uaccess.h>
++
++#define TWL4030_MADC_PFX "twl4030-madc: "
++
++struct twl4030_madc_data {
++ struct device *dev;
++ struct mutex lock;
++ struct work_struct ws;
++ struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
++ int imr;
++ int isr;
++};
++
++static struct twl4030_madc_data *the_madc;
++
++static
++const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
++ [TWL4030_MADC_RT] = {
++ .sel = TWL4030_MADC_RTSELECT_LSB,
++ .avg = TWL4030_MADC_RTAVERAGE_LSB,
++ .rbase = TWL4030_MADC_RTCH0_LSB,
++ },
++ [TWL4030_MADC_SW1] = {
++ .sel = TWL4030_MADC_SW1SELECT_LSB,
++ .avg = TWL4030_MADC_SW1AVERAGE_LSB,
++ .rbase = TWL4030_MADC_GPCH0_LSB,
++ .ctrl = TWL4030_MADC_CTRL_SW1,
++ },
++ [TWL4030_MADC_SW2] = {
++ .sel = TWL4030_MADC_SW2SELECT_LSB,
++ .avg = TWL4030_MADC_SW2AVERAGE_LSB,
++ .rbase = TWL4030_MADC_GPCH0_LSB,
++ .ctrl = TWL4030_MADC_CTRL_SW2,
++ },
++};
++
++static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
++{
++ int ret;
++ u8 val;
++
++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, &val, reg);
++ if (ret) {
++ dev_dbg(madc->dev, "unable to read register 0x%X\n", reg);
++ return ret;
++ }
++
++ return val;
++}
++
++static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val)
++{
++ int ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
++ if (ret)
++ dev_err(madc->dev, "unable to write register 0x%X\n", reg);
++}
++
++static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
++{
++ u8 msb, lsb;
++
++ /* For each ADC channel, we have MSB and LSB register pair. MSB address
++ * is always LSB address+1. reg parameter is the addr of LSB register */
++ msb = twl4030_madc_read(madc, reg + 1);
++ lsb = twl4030_madc_read(madc, reg);
++
++ return (int)(((msb << 8) | lsb) >> 6);
++}
++
++static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
++ u8 reg_base, u16 channels, int *buf)
++{
++ int count = 0;
++ u8 reg, i;
++
++ if (unlikely(!buf))
++ return 0;
++
++ for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) {
++ if (channels & (1<<i)) {
++ reg = reg_base + 2*i;
++ buf[i] = twl4030_madc_channel_raw_read(madc, reg);
++ count++;
++ }
++ }
++ return count;
++}
++
++static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id)
++{
++ u8 val;
++
++ val = twl4030_madc_read(madc, madc->imr);
++ val &= ~(1 << id);
++ twl4030_madc_write(madc, madc->imr, val);
++}
++
++static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id)
++{
++ u8 val;
++
++ val = twl4030_madc_read(madc, madc->imr);
++ val |= (1 << id);
++ twl4030_madc_write(madc, madc->imr, val);
++}
++
++static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc)
++{
++ struct twl4030_madc_data *madc = _madc;
++ u8 isr_val, imr_val;
++ int i;
++
++#ifdef CONFIG_LOCKDEP
++ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
++ * we don't want and can't tolerate. Although it might be
++ * friendlier not to borrow this thread context...
++ */
++ local_irq_enable();
++#endif
++
++ /* Use COR to ack interrupts since we have no shared IRQs in ISRx */
++ isr_val = twl4030_madc_read(madc, madc->isr);
++ imr_val = twl4030_madc_read(madc, madc->imr);
++
++ isr_val &= ~imr_val;
++
++ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
++
++ if (!(isr_val & (1<<i)))
++ continue;
++
++ twl4030_madc_disable_irq(madc, i);
++ madc->requests[i].result_pending = 1;
++ }
++
++ schedule_work(&madc->ws);
++
++ return IRQ_HANDLED;
++}
++
++static void twl4030_madc_work(struct work_struct *ws)
++{
++ const struct twl4030_madc_conversion_method *method;
++ struct twl4030_madc_data *madc;
++ struct twl4030_madc_request *r;
++ int len, i;
++
++ madc = container_of(ws, struct twl4030_madc_data, ws);
++ mutex_lock(&madc->lock);
++
++ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
++
++ r = &madc->requests[i];
++
++ /* No pending results for this method, move to next one */
++ if (!r->result_pending)
++ continue;
++
++ method = &twl4030_conversion_methods[r->method];
++
++ /* Read results */
++ len = twl4030_madc_read_channels(madc, method->rbase,
++ r->channels, r->rbuf);
++
++ /* Return results to caller */
++ if (r->func_cb != NULL) {
++ r->func_cb(len, r->channels, r->rbuf);
++ r->func_cb = NULL;
++ }
++
++ /* Free request */
++ r->result_pending = 0;
++ r->active = 0;
++ }
++
++ mutex_unlock(&madc->lock);
++}
++
++static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
++ struct twl4030_madc_request *req)
++{
++ struct twl4030_madc_request *p;
++
++ p = &madc->requests[req->method];
++
++ memcpy(p, req, sizeof *req);
++
++ twl4030_madc_enable_irq(madc, req->method);
++
++ return 0;
++}
++
++static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
++ int conv_method)
++{
++ const struct twl4030_madc_conversion_method *method;
++
++ method = &twl4030_conversion_methods[conv_method];
++
++ switch (conv_method) {
++ case TWL4030_MADC_SW1:
++ case TWL4030_MADC_SW2:
++ twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START);
++ break;
++ case TWL4030_MADC_RT:
++ default:
++ break;
++ }
++}
++
++static int twl4030_madc_wait_conversion_ready(
++ struct twl4030_madc_data *madc,
++ unsigned int timeout_ms, u8 status_reg)
++{
++ unsigned long timeout;
++
++ timeout = jiffies + msecs_to_jiffies(timeout_ms);
++ do {
++ u8 reg;
++
++ reg = twl4030_madc_read(madc, status_reg);
++ if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
++ return 0;
++ } while (!time_after(jiffies, timeout));
++
++ return -EAGAIN;
++}
++
++int twl4030_madc_conversion(struct twl4030_madc_request *req)
++{
++ const struct twl4030_madc_conversion_method *method;
++ u8 ch_msb, ch_lsb;
++ int ret;
++
++ if (unlikely(!req))
++ return -EINVAL;
++
++ mutex_lock(&the_madc->lock);
++
++ /* Do we have a conversion request ongoing */
++ if (the_madc->requests[req->method].active) {
++ ret = -EBUSY;
++ goto out;
++ }
++
++ ch_msb = (req->channels >> 8) & 0xff;
++ ch_lsb = req->channels & 0xff;
++
++ method = &twl4030_conversion_methods[req->method];
++
++ /* Select channels to be converted */
++ twl4030_madc_write(the_madc, method->sel + 1, ch_msb);
++ twl4030_madc_write(the_madc, method->sel, ch_lsb);
++
++ /* Select averaging for all channels if do_avg is set */
++ if (req->do_avg) {
++ twl4030_madc_write(the_madc, method->avg + 1, ch_msb);
++ twl4030_madc_write(the_madc, method->avg, ch_lsb);
++ }
++
++ if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) {
++ twl4030_madc_set_irq(the_madc, req);
++ twl4030_madc_start_conversion(the_madc, req->method);
++ the_madc->requests[req->method].active = 1;
++ ret = 0;
++ goto out;
++ }
++
++ /* With RT method we should not be here anymore */
++ if (req->method == TWL4030_MADC_RT) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ twl4030_madc_start_conversion(the_madc, req->method);
++ the_madc->requests[req->method].active = 1;
++
++ /* Wait until conversion is ready (ctrl register returns EOC) */
++ ret = twl4030_madc_wait_conversion_ready(the_madc, 5, method->ctrl);
++ if (ret) {
++ dev_dbg(the_madc->dev, "conversion timeout!\n");
++ the_madc->requests[req->method].active = 0;
++ goto out;
++ }
++
++ ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels,
++ req->rbuf);
++
++ the_madc->requests[req->method].active = 0;
++
++out:
++ mutex_unlock(&the_madc->lock);
++
++ return ret;
++}
++EXPORT_SYMBOL(twl4030_madc_conversion);
++
++static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
++ int chan, int on)
++{
++ int ret;
++ u8 regval;
++
++ /* Current generator is only available for ADCIN0 and ADCIN1. NB:
++ * ADCIN1 current generator only works when AC or VBUS is present */
++ if (chan > 1)
++ return EINVAL;
++
++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
++ &regval, TWL4030_BCI_BCICTL1);
++ if (on)
++ regval |= (chan) ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
++ else
++ regval &= (chan) ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
++ regval, TWL4030_BCI_BCICTL1);
++
++ return ret;
++}
++
++static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
++{
++ u8 regval;
++
++ regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1);
++ if (on)
++ regval |= TWL4030_MADC_MADCON;
++ else
++ regval &= ~TWL4030_MADC_MADCON;
++ twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval);
++
++ return 0;
++}
++
++static long twl4030_madc_ioctl(struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct twl4030_madc_user_parms par;
++ int val, ret;
++
++ ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
++ if (ret) {
++ dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret);
++ return -EACCES;
++ }
++
++ switch (cmd) {
++ case TWL4030_MADC_IOCX_ADC_RAW_READ: {
++ struct twl4030_madc_request req;
++ if (par.channel >= TWL4030_MADC_MAX_CHANNELS)
++ return -EINVAL;
++
++ req.channels = (1 << par.channel);
++ req.do_avg = par.average;
++ req.method = TWL4030_MADC_SW1;
++ req.func_cb = NULL;
++
++ val = twl4030_madc_conversion(&req);
++ if (val <= 0) {
++ par.status = -1;
++ } else {
++ par.status = 0;
++ par.result = (u16)req.rbuf[par.channel];
++ }
++ break;
++ }
++ default:
++ return -EINVAL;
++ }
++
++ ret = copy_to_user((void __user *) arg, &par, sizeof(par));
++ if (ret) {
++ dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret);
++ return -EACCES;
++ }
++
++ return 0;
++}
++
++static struct file_operations twl4030_madc_fileops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = twl4030_madc_ioctl
++};
++
++static struct miscdevice twl4030_madc_device = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = "twl4030-madc",
++ .fops = &twl4030_madc_fileops
++};
++
++static int __init twl4030_madc_probe(struct platform_device *pdev)
++{
++ struct twl4030_madc_data *madc;
++ struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
++ int ret;
++ u8 regval;
++
++ madc = kzalloc(sizeof *madc, GFP_KERNEL);
++ if (!madc)
++ return -ENOMEM;
++
++ if (!pdata) {
++ dev_dbg(&pdev->dev, "platform_data not available\n");
++ ret = -EINVAL;
++ goto err_pdata;
++ }
++
++ madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
++ madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
++
++ ret = misc_register(&twl4030_madc_device);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not register misc_device\n");
++ goto err_misc;
++ }
++ twl4030_madc_set_power(madc, 1);
++ twl4030_madc_set_current_generator(madc, 0, 1);
++
++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
++ &regval, TWL4030_BCI_BCICTL1);
++
++ regval |= TWL4030_BCI_MESBAT;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
++ regval, TWL4030_BCI_BCICTL1);
++
++ ret = request_irq(platform_get_irq(pdev, 0), twl4030_madc_irq_handler,
++ 0, "twl4030_madc", madc);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not request irq\n");
++ goto err_irq;
++ }
++
++ platform_set_drvdata(pdev, madc);
++ mutex_init(&madc->lock);
++ INIT_WORK(&madc->ws, twl4030_madc_work);
++
++ the_madc = madc;
++
++ return 0;
++
++err_irq:
++ misc_deregister(&twl4030_madc_device);
++
++err_misc:
++err_pdata:
++ kfree(madc);
++
++ return ret;
++}
++
++static int __exit twl4030_madc_remove(struct platform_device *pdev)
++{
++ struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
++
++ twl4030_madc_set_power(madc, 0);
++ twl4030_madc_set_current_generator(madc, 0, 0);
++ free_irq(platform_get_irq(pdev, 0), madc);
++ cancel_work_sync(&madc->ws);
++ misc_deregister(&twl4030_madc_device);
++
++ return 0;
++}
++
++static struct platform_driver twl4030_madc_driver = {
++ .probe = twl4030_madc_probe,
++ .remove = __exit_p(twl4030_madc_remove),
++ .driver = {
++ .name = "twl4030_madc",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init twl4030_madc_init(void)
++{
++ return platform_driver_register(&twl4030_madc_driver);
++}
++module_init(twl4030_madc_init);
++
++static void __exit twl4030_madc_exit(void)
++{
++ platform_driver_unregister(&twl4030_madc_driver);
++}
++module_exit(twl4030_madc_exit);
++
++MODULE_ALIAS("platform:twl4030-madc");
++MODULE_AUTHOR("Nokia Corporation");
++MODULE_DESCRIPTION("twl4030 ADC driver");
++MODULE_LICENSE("GPL");
++
+diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h
+new file mode 100644
+index 0000000..24523b5
+--- /dev/null
++++ b/include/linux/i2c/twl4030-madc.h
+@@ -0,0 +1,126 @@
++/*
++ * include/linux/i2c/twl4030-madc.h
++ *
++ * TWL4030 MADC module driver header
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Mikko Ylinen <mikko.k.ylinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#ifndef _TWL4030_MADC_H
++#define _TWL4030_MADC_H
++
++struct twl4030_madc_conversion_method {
++ u8 sel;
++ u8 avg;
++ u8 rbase;
++ u8 ctrl;
++};
++
++#define TWL4030_MADC_MAX_CHANNELS 16
++
++struct twl4030_madc_request {
++ u16 channels;
++ u16 do_avg;
++ u16 method;
++ u16 type;
++ int active;
++ int result_pending;
++ int rbuf[TWL4030_MADC_MAX_CHANNELS];
++ void (*func_cb)(int len, int channels, int *buf);
++};
++
++enum conversion_methods {
++ TWL4030_MADC_RT,
++ TWL4030_MADC_SW1,
++ TWL4030_MADC_SW2,
++ TWL4030_MADC_NUM_METHODS
++};
++
++enum sample_type {
++ TWL4030_MADC_WAIT,
++ TWL4030_MADC_IRQ_ONESHOT,
++ TWL4030_MADC_IRQ_REARM
++};
++
++#define TWL4030_MADC_CTRL1 0x00
++#define TWL4030_MADC_CTRL2 0x01
++
++#define TWL4030_MADC_RTSELECT_LSB 0x02
++#define TWL4030_MADC_SW1SELECT_LSB 0x06
++#define TWL4030_MADC_SW2SELECT_LSB 0x0A
++
++#define TWL4030_MADC_RTAVERAGE_LSB 0x04
++#define TWL4030_MADC_SW1AVERAGE_LSB 0x08
++#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C
++
++#define TWL4030_MADC_CTRL_SW1 0x12
++#define TWL4030_MADC_CTRL_SW2 0x13
++
++#define TWL4030_MADC_RTCH0_LSB 0x17
++#define TWL4030_MADC_GPCH0_LSB 0x37
++
++#define TWL4030_MADC_MADCON (1<<0) /* MADC power on */
++#define TWL4030_MADC_BUSY (1<<0) /* MADC busy */
++#define TWL4030_MADC_EOC_SW (1<<1) /* MADC conversion completion */
++#define TWL4030_MADC_SW_START (1<<5) /* MADC SWx start conversion */
++
++#define TWL4030_MADC_ADCIN0 (1<<0)
++#define TWL4030_MADC_ADCIN1 (1<<1)
++#define TWL4030_MADC_ADCIN2 (1<<2)
++#define TWL4030_MADC_ADCIN3 (1<<3)
++#define TWL4030_MADC_ADCIN4 (1<<4)
++#define TWL4030_MADC_ADCIN5 (1<<5)
++#define TWL4030_MADC_ADCIN6 (1<<6)
++#define TWL4030_MADC_ADCIN7 (1<<7)
++#define TWL4030_MADC_ADCIN8 (1<<8)
++#define TWL4030_MADC_ADCIN9 (1<<9)
++#define TWL4030_MADC_ADCIN10 (1<<10)
++#define TWL4030_MADC_ADCIN11 (1<<11)
++#define TWL4030_MADC_ADCIN12 (1<<12)
++#define TWL4030_MADC_ADCIN13 (1<<13)
++#define TWL4030_MADC_ADCIN14 (1<<14)
++#define TWL4030_MADC_ADCIN15 (1<<15)
++
++/* Fixed channels */
++#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1
++#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8
++#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9
++#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10
++#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11
++#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12
++
++/* BCI related - XXX To be moved elsewhere */
++#define TWL4030_BCI_BCICTL1 0x23
++#define TWL4030_BCI_MESBAT (1<<1)
++#define TWL4030_BCI_TYPEN (1<<4)
++#define TWL4030_BCI_ITHEN (1<<3)
++
++#define TWL4030_MADC_IOC_MAGIC '`'
++#define TWL4030_MADC_IOCX_ADC_RAW_READ _IO(TWL4030_MADC_IOC_MAGIC, 0)
++
++struct twl4030_madc_user_parms {
++ int channel;
++ int average;
++ int status;
++ u16 result;
++};
++
++int twl4030_madc_conversion(struct twl4030_madc_request *conv);
++
++#endif
diff --git a/recipes/linux/linux-omap-2.6.31/madc/madc.patch b/recipes/linux/linux-omap-2.6.31/madc/madc.patch
new file mode 100644
index 0000000000..dbbd50f662
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/madc/madc.patch
@@ -0,0 +1,56 @@
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index 48f9932..ce84ee7 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -340,10 +340,15 @@ static struct regulator_init_data overo_vmmc1 = {
+
+ /* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
+
++static struct twl4030_madc_platform_data overo_madc_data = {
++ .irq_line = 1,
++};
++
+ static struct twl4030_platform_data overo_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+ .gpio = &overo_gpio_data,
++ .madc = &overo_madc_data,
+ .usb = &overo_usb_data,
+ .power = GENERIC3430_T2SCRIPTS_DATA,
+ .vmmc1 = &overo_vmmc1,
+diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
+index 769b34b..c5ca36d 100644
+--- a/drivers/mfd/twl4030-core.c
++++ b/drivers/mfd/twl4030-core.c
+@@ -159,6 +159,7 @@
+
+ /* Few power values */
+ #define R_CFG_BOOT 0x05
++#define R_GPBR1 0x0C
+ #define R_PROTECT_KEY 0x0E
+
+ /* access control values for R_PROTECT_KEY */
+@@ -166,6 +167,10 @@
+ #define KEY_UNLOCK2 0xec
+ #define KEY_LOCK 0x00
+
++/* MADC clock values for R_GPBR1 */
++#define MADC_HFCLK_EN 0x80
++#define DEFAULT_MADC_CLK_EN 0x10
++
+ /* some fields in R_CFG_BOOT */
+ #define HFCLK_FREQ_19p2_MHZ (1 << 0)
+ #define HFCLK_FREQ_26_MHZ (2 << 0)
+@@ -717,6 +722,11 @@ static void __init clocks_init(struct device *dev)
+ ctrl |= HIGH_PERF_SQ;
+ e |= unprotect_pm_master();
+ /* effect->MADC+USB ck en */
++
++ if (twl_has_madc())
++ e |= twl4030_i2c_write_u8(TWL4030_MODULE_INTBR,
++ MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, R_GPBR1);
++
+ e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
+ e |= protect_pm_master();
+
+
diff --git a/recipes/linux/linux-omap-2.6.31/modedb-hd720.patch b/recipes/linux/linux-omap-2.6.31/modedb-hd720.patch
new file mode 100644
index 0000000000..0166de651a
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/modedb-hd720.patch
@@ -0,0 +1,13 @@
+--- orig/drivers/video/modedb.c.orig 2009-04-07 11:40:10.000000000 +0200
++++ git/drivers/video/modedb.c 2009-04-07 10:35:29.000000000 +0200
+@@ -44,6 +44,10 @@
+ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
+ }, {
++ /* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */
++ "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
++ 0, FB_VMODE_NONINTERLACED
++ }, {
+ /* 800x600 @ 56 Hz, 35.15 kHz hsync */
+ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
+ 0, FB_VMODE_NONINTERLACED
diff --git a/recipes/linux/linux-omap-2.6.31/omapzoom2/defconfig b/recipes/linux/linux-omap-2.6.31/omapzoom2/defconfig
new file mode 100644
index 0000000000..366e259870
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/omapzoom2/defconfig
@@ -0,0 +1,1366 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc1-omap1
+# Fri Jul 10 18:12:43 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+CONFIG_MACH_OMAP_ZOOM2=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_HDQ_MASTER_OMAP is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_LCD_MIPID is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-2.6.31/overo/ehci.patch b/recipes/linux/linux-omap-2.6.31/overo/ehci.patch
new file mode 100644
index 0000000000..2fec9d3cc8
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/overo/ehci.patch
@@ -0,0 +1,47 @@
+From 01984da4f7009c118c18fa251b703de74f26ced2 Mon Sep 17 00:00:00 2001
+From: Steve Sakoman <steve@sakoman.com>
+Date: Sun, 16 Aug 2009 14:19:55 -0700
+Subject: [PATCH] ARM: OMAP3: Fix EHCI initialization for Overo
+
+Overo uses port 2, not port 1. Use OVERO_GPIO_USBH_NRESET rather than hard coded value
+
+Note: this alone will not give functional EHCI. Also required is:
+
+[PATCH 4/9] ehci: fix phy_reset init in ehci probe
+from Ajay Kumar Gupta
+---
+ arch/arm/mach-omap2/board-overo.c | 11 ++---------
+ 1 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index a9d7c2e..a220a54 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -394,7 +394,8 @@ static void __init overo_init(void)
+ omap_serial_init(&overo_uart_config);
+ overo_flash_init();
+ usb_musb_init();
+- usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, 183, -EINVAL);
++ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true,
++ -EINVAL, OVERO_GPIO_USBH_NRESET);
+ overo_ads7846_init();
+ overo_init_smsc911x();
+
+@@ -437,14 +438,6 @@ static void __init overo_init(void)
+ else
+ printk(KERN_ERR "could not obtain gpio for "
+ "OVERO_GPIO_USBH_CPEN\n");
+-
+- if ((gpio_request(OVERO_GPIO_USBH_NRESET,
+- "OVERO_GPIO_USBH_NRESET") == 0) &&
+- (gpio_direction_output(OVERO_GPIO_USBH_NRESET, 1) == 0))
+- gpio_export(OVERO_GPIO_USBH_NRESET, 0);
+- else
+- printk(KERN_ERR "could not obtain gpio for "
+- "OVERO_GPIO_USBH_NRESET\n");
+ }
+
+ static void __init overo_map_io(void)
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch b/recipes/linux/linux-omap-2.6.31/usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch
new file mode 100644
index 0000000000..ecd37f78a9
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch
@@ -0,0 +1,37 @@
+From 416c7ba6ec7041dc4d61340adf73c9467ff8073a Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@beagleboard.org>
+Date: Wed, 23 Sep 2009 09:35:15 +0200
+Subject: [PATCH] ARM: OMAP: Fix beagleboard EHCI setup
+
+The EHCI configuration in the beagleboard board file was copy/pasted
+from the sdp one and hence wrong. The beagleboard only used one port
+and lacks a charge pump.
+
+Tested on revision C1D and C3 boards
+
+Signed-off-by: Koen Kooi <koen@beagleboard.org>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 496b4a0..aa403e6 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -406,10 +406,10 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+- .chargepump = true,
++ .chargepump = false,
+ .phy_reset = true,
+- .reset_gpio_port[0] = 57,
+- .reset_gpio_port[1] = 61,
++ .reset_gpio_port[0] = -EINVAL,
++ .reset_gpio_port[1] = 147,
+ .reset_gpio_port[2] = -EINVAL
+ };
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0001-musb-fix-put_device-call-sequence.patch b/recipes/linux/linux-omap-2.6.31/usb/0001-musb-fix-put_device-call-sequence.patch
new file mode 100644
index 0000000000..1164fcb417
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0001-musb-fix-put_device-call-sequence.patch
@@ -0,0 +1,45 @@
+From f5d23fe1ff54df953c7b65699d6065b4a6336932 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Mon, 3 Aug 2009 11:16:18 +0530
+Subject: [PATCH 01/16] musb: fix put_device() call sequence
+
+Invoke put_device(musb->xceiv->dev) before musb_platform_exit()as
+xceiv is getting unregistered in musb_platform_exit().
+
+Fixes put_device() panic when module insert/removal is performed
+multiple times.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/musb_core.c | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index c7c1ca0..129f9dc 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1850,6 +1850,10 @@ static void musb_free(struct musb *musb)
+ dma_controller_destroy(c);
+ }
+
++#ifdef CONFIG_USB_MUSB_OTG
++ put_device(musb->xceiv->dev);
++#endif
++
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_platform_exit(musb);
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+@@ -1859,10 +1863,6 @@ static void musb_free(struct musb *musb)
+ clk_put(musb->clock);
+ }
+
+-#ifdef CONFIG_USB_MUSB_OTG
+- put_device(musb->xceiv->dev);
+-#endif
+-
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ usb_put_hcd(musb_to_hcd(musb));
+ #else
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch b/recipes/linux/linux-omap-2.6.31/usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch
new file mode 100644
index 0000000000..25764aa52c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch
@@ -0,0 +1,41 @@
+From 073182af5855d4114ab3d40db3fba1298573f0be Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri, 10 Jul 2009 12:15:04 +0530
+Subject: [PATCH 08/16] omap3: Add CHIP_GE_OMAP3430ES3 for HSUSB
+
+OMAP3 HSUSB ports can be individually programmed in PHY or TLL
+mode in ES3.0 onwards whereas this is not supported in ES2.1
+and earlier versions.
+
+CHIP_GE_OMAP3430ES3 is added to program this behavior at runtime.
+
+Also updated the existing macros to use the priviously defined
+*_GE_* logic instead of repeating the same logic again.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ arch/arm/plat-omap/include/mach/cpu.h | 7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h
+index 7a5f9e8..60d867c 100644
+--- a/arch/arm/plat-omap/include/mach/cpu.h
++++ b/arch/arm/plat-omap/include/mach/cpu.h
+@@ -414,10 +414,11 @@ IS_OMAP_TYPE(3430, 0x3430)
+ * chips at ES2 and beyond, but not, for example, any OMAP lines after
+ * OMAP3.
+ */
+-#define CHIP_GE_OMAP3430ES2 (CHIP_IS_OMAP3430ES2 | \
+- CHIP_IS_OMAP3430ES3_0 | \
+- CHIP_IS_OMAP3430ES3_1)
+ #define CHIP_GE_OMAP3430ES3_1 (CHIP_IS_OMAP3430ES3_1)
++#define CHIP_GE_OMAP3430ES3 (CHIP_IS_OMAP3430ES3_0 | \
++ CHIP_GE_OMAP3430ES3_1)
++#define CHIP_GE_OMAP3430ES2 (CHIP_IS_OMAP3430ES2 | \
++ CHIP_GE_OMAP3430ES3)
+
+
+ int omap_chip_is(struct omap_chip_id oci);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch b/recipes/linux/linux-omap-2.6.31/usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch
new file mode 100644
index 0000000000..0d74743ac0
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch
@@ -0,0 +1,31 @@
+From 1adaab4805926b3674fd083e7e0ac2b29a30a34a Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri, 12 Jun 2009 19:01:42 +0530
+Subject: [PATCH 11/16] musb: fix musb->gadget_driver != NULL bug
+
+musb->gadget_driver != NULL is observed when CONFIG_SUSPEND is
+enabled causing failure in gadget driver registration.
+
+Fixing this by making musb->gadget_driver = NULL during musb
+initialization.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/musb_gadget.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index 8b3c4e2..d69d98e 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -1650,6 +1650,7 @@ int __init musb_gadget_setup(struct musb *musb)
+ musb->g.dev.dma_mask = musb->controller->dma_mask;
+ musb->g.dev.release = musb_gadget_release;
+ musb->g.name = musb_driver_name;
++ musb->gadget_driver = NULL;
+
+ if (is_otg_enabled(musb))
+ musb->g.is_otg = 1;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0012-musb-Add-back-old-musb-procfs-file.patch b/recipes/linux/linux-omap-2.6.31/usb/0012-musb-Add-back-old-musb-procfs-file.patch
new file mode 100644
index 0000000000..bc1ad5a648
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0012-musb-Add-back-old-musb-procfs-file.patch
@@ -0,0 +1,947 @@
+From 7f43c6297c781c2d403ee397fe2cfccaaf3eea42 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Sat, 20 Jun 2009 14:06:38 +0530
+Subject: [PATCH 12/16] musb: Add back old musb procfs file
+
+Procfs file is removed from musb and an equivalent debugfs is
+expected to replace it.
+
+Adding the old file back to retain the debug functionalities untill
+we get debugfs equivalent in mainline.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/Makefile | 3 +
+ drivers/usb/musb/musb_core.c | 8 +-
+ drivers/usb/musb/musb_core.h | 19 +
+ drivers/usb/musb/musb_procfs.c | 838 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 863 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/usb/musb/musb_procfs.c
+
+diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
+index 85710cc..06969c5 100644
+--- a/drivers/usb/musb/Makefile
++++ b/drivers/usb/musb/Makefile
+@@ -74,4 +74,7 @@ endif
+
+ ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
++ ifeq ($(CONFIG_PROC_FS),y)
++ musb_hdrc-objs += musb_procfs.o
++ endif
+ endif
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 129f9dc..f5ca435 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2046,8 +2046,6 @@ bad_config:
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+
+ status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+- if (status)
+- goto fail;
+
+ DBG(1, "%s mode, status %d, devctl %02x %c\n",
+ "HOST", status,
+@@ -2062,8 +2060,6 @@ bad_config:
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+
+ status = musb_gadget_setup(musb);
+- if (status)
+- goto fail;
+
+ DBG(1, "%s mode, status %d, dev%02x\n",
+ is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
+@@ -2082,7 +2078,8 @@ bad_config:
+ #endif
+ if (status)
+ goto fail2;
+-
++ if (status == 0)
++ musb_debug_create("driver/musb_hdrc", musb);
+ return 0;
+
+ fail2:
+@@ -2152,6 +2149,7 @@ static int __devexit musb_remove(struct platform_device *pdev)
+ * - OTG mode: both roles are deactivated (or never-activated)
+ */
+ musb_shutdown(pdev);
++ musb_debug_delete("driver/musb_hdrc", musb);
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ if (musb->board_mode == MUSB_HOST)
+ usb_remove_hcd(musb_to_hcd(musb));
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index 381d648..b0b4fbd 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -562,4 +562,23 @@ extern int musb_platform_get_vbus_status(struct musb *musb);
+ extern int __init musb_platform_init(struct musb *musb);
+ extern int musb_platform_exit(struct musb *musb);
+
++/*-------------------------- ProcFS definitions ---------------------*/
++
++struct proc_dir_entry;
++
++#if (CONFIG_USB_MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
++extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
++extern void musb_debug_delete(char *name, struct musb *data);
++
++#else
++static inline struct proc_dir_entry *
++musb_debug_create(char *name, struct musb *data)
++{
++ return NULL;
++}
++static inline void musb_debug_delete(char *name, struct musb *data)
++{
++}
++#endif
++
+ #endif /* __MUSB_CORE_H__ */
+diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c
+new file mode 100644
+index 0000000..d789d4d
+--- /dev/null
++++ b/drivers/usb/musb/musb_procfs.c
+@@ -0,0 +1,838 @@
++/*
++ * MUSB OTG driver debug support
++ *
++ * Copyright 2005 Mentor Graphics Corporation
++ * Copyright (C) 2005-2006 by Texas Instruments
++ * Copyright (C) 2006-2007 Nokia Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/uaccess.h> /* FIXME remove procfs writes */
++#include <mach/hardware.h>
++
++#include "musb_core.h"
++
++#include "davinci.h"
++
++#ifdef CONFIG_USB_MUSB_HDRC_HCD
++
++static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
++{
++ int count;
++ int tmp;
++ struct usb_host_endpoint *hep = qh->hep;
++ struct urb *urb;
++
++ count = snprintf(buf, max, " qh %p dev%d ep%d%s max%d\n",
++ qh, qh->dev->devnum, qh->epnum,
++ ({ char *s; switch (qh->type) {
++ case USB_ENDPOINT_XFER_BULK:
++ s = "-bulk"; break;
++ case USB_ENDPOINT_XFER_INT:
++ s = "-int"; break;
++ case USB_ENDPOINT_XFER_CONTROL:
++ s = ""; break;
++ default:
++ s = "iso"; break;
++ }; s; }),
++ qh->maxpacket);
++ if (count <= 0)
++ return 0;
++ buf += count;
++ max -= count;
++
++ list_for_each_entry(urb, &hep->urb_list, urb_list) {
++ tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
++ usb_pipein(urb->pipe) ? "in" : "out",
++ urb, urb->actual_length,
++ urb->transfer_buffer_length);
++ if (tmp <= 0)
++ break;
++ tmp = min(tmp, (int)max);
++ count += tmp;
++ buf += tmp;
++ max -= tmp;
++ }
++ return count;
++}
++
++static int
++dump_queue(struct list_head *q, char *buf, unsigned max)
++{
++ int count = 0;
++ struct musb_qh *qh;
++
++ list_for_each_entry(qh, q, ring) {
++ int tmp;
++
++ tmp = dump_qh(qh, buf, max);
++ if (tmp <= 0)
++ break;
++ tmp = min(tmp, (int)max);
++ count += tmp;
++ buf += tmp;
++ max -= tmp;
++ }
++ return count;
++}
++
++#endif /* HCD */
++
++#ifdef CONFIG_USB_GADGET_MUSB_HDRC
++static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
++{
++ char *buf = buffer;
++ int code = 0;
++ void __iomem *regs = ep->hw_ep->regs;
++ char *mode = "1buf";
++
++ if (ep->is_in) {
++ if (ep->hw_ep->tx_double_buffered)
++ mode = "2buf";
++ } else {
++ if (ep->hw_ep->rx_double_buffered)
++ mode = "2buf";
++ }
++
++ do {
++ struct usb_request *req;
++
++ code = snprintf(buf, max,
++ "\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
++ ep->name, ep->current_epnum,
++ mode, ep->dma ? " dma" : "",
++ musb_readw(regs,
++ (ep->is_in || !ep->current_epnum)
++ ? MUSB_TXCSR
++ : MUSB_RXCSR),
++ musb_readw(regs, ep->is_in
++ ? MUSB_TXMAXP
++ : MUSB_RXMAXP)
++ );
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++
++ if (is_cppi_enabled() && ep->current_epnum) {
++ unsigned cppi = ep->current_epnum - 1;
++ void __iomem *base = ep->musb->ctrl_base;
++ unsigned off1 = cppi << 2;
++ void __iomem *ram = base;
++ char tmp[16];
++
++ if (ep->is_in) {
++ ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
++ tmp[0] = 0;
++ } else {
++ ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
++ snprintf(tmp, sizeof tmp, "%d left, ",
++ musb_readl(base,
++ DAVINCI_RXCPPI_BUFCNT0_REG + off1));
++ }
++
++ code = snprintf(buf, max, "%cX DMA%d: %s"
++ "%08x %08x, %08x %08x; "
++ "%08x %08x %08x .. %08x\n",
++ ep->is_in ? 'T' : 'R',
++ ep->current_epnum - 1, tmp,
++ musb_readl(ram, 0 * 4),
++ musb_readl(ram, 1 * 4),
++ musb_readl(ram, 2 * 4),
++ musb_readl(ram, 3 * 4),
++ musb_readl(ram, 4 * 4),
++ musb_readl(ram, 5 * 4),
++ musb_readl(ram, 6 * 4),
++ musb_readl(ram, 7 * 4));
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++
++ if (list_empty(&ep->req_list)) {
++ code = snprintf(buf, max, "\t(queue empty)\n");
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ break;
++ }
++ list_for_each_entry(req, &ep->req_list, list) {
++ code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
++ req,
++ req->zero ? "zero, " : "",
++ req->short_not_ok ? "!short, " : "",
++ req->actual, req->length);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++ } while (0);
++ return buf - buffer;
++}
++#endif
++
++static int
++dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
++{
++ int code = 0;
++ char *buf = aBuffer;
++ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
++
++ do {
++ musb_ep_select(musb->mregs, epnum);
++#ifdef CONFIG_USB_MUSB_HDRC_HCD
++ if (is_host_active(musb)) {
++ int dump_rx, dump_tx;
++ void __iomem *regs = hw_ep->regs;
++
++ /* TEMPORARY (!) until we have a real periodic
++ * schedule tree ...
++ */
++ if (!epnum) {
++ /* control is shared, uses RX queue
++ * but (mostly) shadowed tx registers
++ */
++ dump_tx = !list_empty(&musb->control);
++ dump_rx = 0;
++ } else if (hw_ep == musb->bulk_ep) {
++ dump_tx = !list_empty(&musb->out_bulk);
++ dump_rx = !list_empty(&musb->in_bulk);
++ } else if (hw_ep->in_qh || hw_ep->out_qh) {
++ if (hw_ep->in_qh)
++ dump_rx = 1;
++ else
++ dump_rx = 0;
++ dump_tx = !dump_rx;
++ } else
++ break;
++ /* END TEMPORARY */
++
++
++ if (dump_rx) {
++ code = snprintf(buf, max,
++ "\nRX%d: %s rxcsr %04x interval %02x "
++ "max %04x type %02x; "
++ "dev %d hub %d port %d"
++ "\n",
++ epnum,
++ hw_ep->rx_double_buffered
++ ? "2buf" : "1buf",
++ musb_readw(regs, MUSB_RXCSR),
++ musb_readb(regs, MUSB_RXINTERVAL),
++ musb_readw(regs, MUSB_RXMAXP),
++ musb_readb(regs, MUSB_RXTYPE),
++ /* FIXME: assumes multipoint */
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_RXFUNCADDR)),
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_RXHUBADDR)),
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_RXHUBPORT))
++ );
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++
++ if (is_cppi_enabled()
++ && epnum
++ && hw_ep->rx_channel) {
++ unsigned cppi = epnum - 1;
++ unsigned off1 = cppi << 2;
++ void __iomem *base;
++ void __iomem *ram;
++ char tmp[16];
++
++ base = musb->ctrl_base;
++ ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
++ cppi) + base;
++ snprintf(tmp, sizeof tmp, "%d left, ",
++ musb_readl(base,
++ DAVINCI_RXCPPI_BUFCNT0_REG
++ + off1));
++
++ code = snprintf(buf, max,
++ " rx dma%d: %s"
++ "%08x %08x, %08x %08x; "
++ "%08x %08x %08x .. %08x\n",
++ cppi, tmp,
++ musb_readl(ram, 0 * 4),
++ musb_readl(ram, 1 * 4),
++ musb_readl(ram, 2 * 4),
++ musb_readl(ram, 3 * 4),
++ musb_readl(ram, 4 * 4),
++ musb_readl(ram, 5 * 4),
++ musb_readl(ram, 6 * 4),
++ musb_readl(ram, 7 * 4));
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++
++ if (hw_ep == musb->bulk_ep
++ && !list_empty(
++ &musb->in_bulk)) {
++ code = dump_queue(&musb->in_bulk,
++ buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ } else if (hw_ep->in_qh) {
++ code = dump_qh(hw_ep->in_qh,
++ buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++ }
++
++ if (dump_tx) {
++ code = snprintf(buf, max,
++ "\nTX%d: %s txcsr %04x interval %02x "
++ "max %04x type %02x; "
++ "dev %d hub %d port %d"
++ "\n",
++ epnum,
++ hw_ep->tx_double_buffered
++ ? "2buf" : "1buf",
++ musb_readw(regs, MUSB_TXCSR),
++ musb_readb(regs, MUSB_TXINTERVAL),
++ musb_readw(regs, MUSB_TXMAXP),
++ musb_readb(regs, MUSB_TXTYPE),
++ /* FIXME: assumes multipoint */
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_TXFUNCADDR)),
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_TXHUBADDR)),
++ musb_readb(musb->mregs,
++ MUSB_BUSCTL_OFFSET(epnum,
++ MUSB_TXHUBPORT))
++ );
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++
++ if (is_cppi_enabled()
++ && epnum
++ && hw_ep->tx_channel) {
++ unsigned cppi = epnum - 1;
++ void __iomem *base;
++ void __iomem *ram;
++
++ base = musb->ctrl_base;
++ ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
++ cppi) + base;
++ code = snprintf(buf, max,
++ " tx dma%d: "
++ "%08x %08x, %08x %08x; "
++ "%08x %08x %08x .. %08x\n",
++ cppi,
++ musb_readl(ram, 0 * 4),
++ musb_readl(ram, 1 * 4),
++ musb_readl(ram, 2 * 4),
++ musb_readl(ram, 3 * 4),
++ musb_readl(ram, 4 * 4),
++ musb_readl(ram, 5 * 4),
++ musb_readl(ram, 6 * 4),
++ musb_readl(ram, 7 * 4));
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++
++ if (hw_ep == musb->control_ep
++ && !list_empty(
++ &musb->control)) {
++ code = dump_queue(&musb->control,
++ buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ } else if (hw_ep == musb->bulk_ep
++ && !list_empty(
++ &musb->out_bulk)) {
++ code = dump_queue(&musb->out_bulk,
++ buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ } else if (hw_ep->out_qh) {
++ code = dump_qh(hw_ep->out_qh,
++ buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++ }
++ }
++#endif
++#ifdef CONFIG_USB_GADGET_MUSB_HDRC
++ if (is_peripheral_active(musb)) {
++ code = 0;
++
++ if (hw_ep->ep_in.desc || !epnum) {
++ code = dump_ep(&hw_ep->ep_in, buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++ if (hw_ep->ep_out.desc) {
++ code = dump_ep(&hw_ep->ep_out, buf, max);
++ if (code <= 0)
++ break;
++ code = min(code, (int) max);
++ buf += code;
++ max -= code;
++ }
++ }
++#endif
++ } while (0);
++
++ return buf - aBuffer;
++}
++
++/* Dump the current status and compile options.
++ * @param musb the device driver instance
++ * @param buffer where to dump the status; it must be big enough to hold the
++ * result otherwise "BAD THINGS HAPPENS(TM)".
++ */
++static int dump_header_stats(struct musb *musb, char *buffer)
++{
++ int code, count = 0;
++ const void __iomem *mbase = musb->mregs;
++
++ *buffer = 0;
++ count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
++ "(Power=%02x, DevCtl=%02x)\n",
++ (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
++ musb_readb(mbase, MUSB_POWER),
++ musb_readb(mbase, MUSB_DEVCTL));
++ if (count <= 0)
++ return 0;
++ buffer += count;
++
++ code = sprintf(buffer, "OTG state: %s; %sactive\n",
++ otg_state_string(musb),
++ musb->is_active ? "" : "in");
++ if (code <= 0)
++ goto done;
++ buffer += code;
++ count += code;
++
++ code = sprintf(buffer,
++ "Options: "
++#ifdef CONFIG_MUSB_PIO_ONLY
++ "pio"
++#elif defined(CONFIG_USB_TI_CPPI_DMA)
++ "cppi-dma"
++#elif defined(CONFIG_USB_INVENTRA_DMA)
++ "musb-dma"
++#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
++ "tusb-omap-dma"
++#else
++ "?dma?"
++#endif
++ ", "
++#ifdef CONFIG_USB_MUSB_OTG
++ "otg (peripheral+host)"
++#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
++ "peripheral"
++#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
++ "host"
++#endif
++ ", debug=%d [eps=%d]\n",
++ musb_debug,
++ musb->nr_endpoints);
++ if (code <= 0)
++ goto done;
++ count += code;
++ buffer += code;
++
++#ifdef CONFIG_USB_GADGET_MUSB_HDRC
++ code = sprintf(buffer, "Peripheral address: %02x\n",
++ musb_readb(musb->ctrl_base, MUSB_FADDR));
++ if (code <= 0)
++ goto done;
++ buffer += code;
++ count += code;
++#endif
++
++#ifdef CONFIG_USB_MUSB_HDRC_HCD
++ code = sprintf(buffer, "Root port status: %08x\n",
++ musb->port1_status);
++ if (code <= 0)
++ goto done;
++ buffer += code;
++ count += code;
++#endif
++
++#ifdef CONFIG_ARCH_DAVINCI
++ code = sprintf(buffer,
++ "DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
++ "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
++ "\n",
++ musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
++ musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
++ __raw_readl((void __force __iomem *)
++ IO_ADDRESS(USBPHY_CTL_PADDR)),
++ musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
++ musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_USB_INT_SOURCE_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_USB_INT_MASK_REG));
++ if (code <= 0)
++ goto done;
++ count += code;
++ buffer += code;
++#endif /* DAVINCI */
++
++#ifdef CONFIG_USB_TUSB6010
++ code = sprintf(buffer,
++ "TUSB6010: devconf %08x, phy enable %08x drive %08x"
++ "\n\totg %03x timer %08x"
++ "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
++ "\n",
++ musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
++ musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
++ musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
++ musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
++ musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
++ musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
++ musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
++ musb_readl(musb->ctrl_base, TUSB_INT_SRC),
++ musb_readl(musb->ctrl_base, TUSB_INT_MASK));
++ if (code <= 0)
++ goto done;
++ count += code;
++ buffer += code;
++#endif /* DAVINCI */
++
++ if (is_cppi_enabled() && musb->dma_controller) {
++ code = sprintf(buffer,
++ "CPPI: txcr=%d txsrc=%01x txena=%01x; "
++ "rxcr=%d rxsrc=%01x rxena=%01x "
++ "\n",
++ musb_readl(musb->ctrl_base,
++ DAVINCI_TXCPPI_CTRL_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_TXCPPI_RAW_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_TXCPPI_INTENAB_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_RXCPPI_CTRL_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_RXCPPI_RAW_REG),
++ musb_readl(musb->ctrl_base,
++ DAVINCI_RXCPPI_INTENAB_REG));
++ if (code <= 0)
++ goto done;
++ count += code;
++ buffer += code;
++ }
++
++#ifdef CONFIG_USB_GADGET_MUSB_HDRC
++ if (is_peripheral_enabled(musb)) {
++ code = sprintf(buffer, "Gadget driver: %s\n",
++ musb->gadget_driver
++ ? musb->gadget_driver->driver.name
++ : "(none)");
++ if (code <= 0)
++ goto done;
++ count += code;
++ buffer += code;
++ }
++#endif
++
++done:
++ return count;
++}
++
++/* Write to ProcFS
++ *
++ * C soft-connect
++ * c soft-disconnect
++ * I enable HS
++ * i disable HS
++ * s stop session
++ * F force session (OTG-unfriendly)
++ * E rElinquish bus (OTG)
++ * H request host mode
++ * h cancel host request
++ * T start sending TEST_PACKET
++ * D<num> set/query the debug level
++ */
++static int musb_proc_write(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char cmd;
++ u8 reg;
++ struct musb *musb = (struct musb *)data;
++ void __iomem *mbase = musb->mregs;
++
++ /* MOD_INC_USE_COUNT; */
++
++ if (unlikely(copy_from_user(&cmd, buffer, 1)))
++ return -EFAULT;
++
++ switch (cmd) {
++ case 'S':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_POWER)
++ | MUSB_POWER_SUSPENDM;
++ musb_writeb(mbase, MUSB_POWER, reg);
++ }
++ break;
++
++ case 'C':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_POWER)
++ | MUSB_POWER_SOFTCONN;
++ musb_writeb(mbase, MUSB_POWER, reg);
++ }
++ break;
++
++ case 'c':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_POWER)
++ & ~MUSB_POWER_SOFTCONN;
++ musb_writeb(mbase, MUSB_POWER, reg);
++ }
++ break;
++
++ case 'I':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_POWER)
++ | MUSB_POWER_HSENAB;
++ musb_writeb(mbase, MUSB_POWER, reg);
++ }
++ break;
++
++ case 'i':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_POWER)
++ & ~MUSB_POWER_HSENAB;
++ musb_writeb(mbase, MUSB_POWER, reg);
++ }
++ break;
++
++ case 'F':
++ reg = musb_readb(mbase, MUSB_DEVCTL);
++ reg |= MUSB_DEVCTL_SESSION;
++ musb_writeb(mbase, MUSB_DEVCTL, reg);
++ break;
++
++ case 'H':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_DEVCTL);
++ reg |= MUSB_DEVCTL_HR;
++ musb_writeb(mbase, MUSB_DEVCTL, reg);
++ /* MUSB_HST_MODE( ((struct musb*)data) ); */
++ /* WARNING("Host Mode\n"); */
++ }
++ break;
++
++ case 'h':
++ if (mbase) {
++ reg = musb_readb(mbase, MUSB_DEVCTL);
++ reg &= ~MUSB_DEVCTL_HR;
++ musb_writeb(mbase, MUSB_DEVCTL, reg);
++ }
++ break;
++
++ case 'T':
++ if (mbase) {
++ musb_load_testpacket(musb);
++ musb_writeb(mbase, MUSB_TESTMODE,
++ MUSB_TEST_PACKET);
++ }
++ break;
++
++#if (CONFIG_USB_MUSB_DEBUG > 0)
++ /* set/read debug level */
++ case 'D':{
++ if (count > 1) {
++ char digits[8], *p = digits;
++ int i = 0, level = 0, sign = 1;
++ int len = min(count - 1, (unsigned long)8);
++
++ if (copy_from_user(&digits, &buffer[1], len))
++ return -EFAULT;
++
++ /* optional sign */
++ if (*p == '-') {
++ len -= 1;
++ sign = -sign;
++ p++;
++ }
++
++ /* read it */
++ while (i++ < len && *p > '0' && *p < '9') {
++ level = level * 10 + (*p - '0');
++ p++;
++ }
++
++ level *= sign;
++ DBG(1, "debug level %d\n", level);
++ musb_debug = level;
++ }
++ }
++ break;
++
++
++ case '?':
++ INFO("?: you are seeing it\n");
++ INFO("S: suspend the usb bus\n");
++ INFO("C/c: soft connect enable/disable\n");
++ INFO("I/i: hispeed enable/disable\n");
++ INFO("F: force session start\n");
++ INFO("H: host mode\n");
++ INFO("T: start sending TEST_PACKET\n");
++ INFO("D: set/read dbug level\n");
++ break;
++#endif
++
++ default:
++ ERR("Command %c not implemented\n", cmd);
++ break;
++ }
++
++ musb_platform_try_idle(musb, 0);
++
++ return count;
++}
++
++static int musb_proc_read(char *page, char **start,
++ off_t off, int count, int *eof, void *data)
++{
++ char *buffer = page;
++ int code = 0;
++ unsigned long flags;
++ struct musb *musb = data;
++ unsigned epnum;
++
++ count -= off;
++ count -= 1; /* for NUL at end */
++ if (count <= 0)
++ return -EINVAL;
++
++ spin_lock_irqsave(&musb->lock, flags);
++
++ code = dump_header_stats(musb, buffer);
++ if (code > 0) {
++ buffer += code;
++ count -= code;
++ }
++
++ /* generate the report for the end points */
++ /* REVISIT ... not unless something's connected! */
++ for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
++ epnum++) {
++ code = dump_end_info(musb, epnum, buffer, count);
++ if (code > 0) {
++ buffer += code;
++ count -= code;
++ }
++ }
++
++ musb_platform_try_idle(musb, 0);
++
++ spin_unlock_irqrestore(&musb->lock, flags);
++ *eof = 1;
++
++ return buffer - page;
++}
++
++void __devexit musb_debug_delete(char *name, struct musb *musb)
++{
++ if (musb->proc_entry)
++ remove_proc_entry(name, NULL);
++}
++
++struct proc_dir_entry *__init
++musb_debug_create(char *name, struct musb *data)
++{
++ struct proc_dir_entry *pde;
++
++ /* FIXME convert everything to seq_file; then later, debugfs */
++
++ if (!name)
++ return NULL;
++
++ pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
++ data->proc_entry = pde;
++ if (pde) {
++ pde->data = data;
++ /* pde->owner = THIS_MODULE; */
++
++ pde->read_proc = musb_proc_read;
++ pde->write_proc = musb_proc_write;
++
++ pde->size = 0;
++
++ pr_debug("Registered /proc/%s\n", name);
++ } else {
++ pr_debug("Cannot create a valid proc file entry");
++ }
++
++ return pde;
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch b/recipes/linux/linux-omap-2.6.31/usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch
new file mode 100644
index 0000000000..4d18b3e49c
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch
@@ -0,0 +1,29 @@
+From 2fa09793f0da931d7b893291d684162d03eccef2 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Sat, 20 Jun 2009 14:09:15 +0530
+Subject: [PATCH 13/16] musb: Remove USB_SUSPEND auto select with OTG
+
+As USB power management is not yet supported in MUSB but we want to
+use OTG build image so disable auto selection of USB_SUSPEND with
+OTG till power management is supported.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/core/Kconfig | 1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index ad92594..4c7d6e8 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -109,7 +109,6 @@ config USB_SUSPEND
+ config USB_OTG
+ bool
+ depends on USB && EXPERIMENTAL
+- select USB_SUSPEND
+ default n
+
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch b/recipes/linux/linux-omap-2.6.31/usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch
new file mode 100644
index 0000000000..f93c2a2ed6
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch
@@ -0,0 +1,34 @@
+From 9d49c81b7ebf7942efc14bc9533a14cb64cd68e6 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri, 12 Jun 2009 19:07:13 +0530
+Subject: [PATCH 14/16] musb: disable PING on status phase of control transfer
+
+PING token is not mandatory in status phase of control transfer
+so some high speed USB sticks doesn't support this.If such devices
+are connected to MUSB then they would not respond to PING token
+causing delayed or failed enumeration.
+
+Fixing this issue by disabling PING token in status phase of control
+transfers.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/musb_host.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index cf94511..4d301d2 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -1056,6 +1056,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
+ else
+ csr = MUSB_CSR0_H_STATUSPKT
+ | MUSB_CSR0_TXPKTRDY;
++ /* disable ping token in status phase */
++ csr |= MUSB_CSR0_H_DIS_PING;
+
+ /* flag status stage */
+ musb->ep0_stage = MUSB_EP0_STATUS;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch b/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch
new file mode 100644
index 0000000000..3bf368c79f
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch
@@ -0,0 +1,422 @@
+From 2b65475db2df6c0b7ebb8960e77e3aaf27147bda Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 3 Sep 2009 17:07:40 +0530
+Subject: [PATCH 15/16] musb: Add context save and restore support
+
+Adding support for MUSB register save and restore during system
+suspend and resume.
+
+Changes:
+ - Added musb_save/restore_context() functions
+ - Added platform specific musb_platform_save/restore_context()
+ to handle platform specific jobs.
+ - Maintaining BlackFin compatibility by adding read/write
+ functions for registers which are not available in BlackFin
+
+Tested system suspend and resume on OMAP3EVM board.
+
+Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/musb_core.c | 157 +++++++++++++++++++++++++++++++++++++++++-
+ drivers/usb/musb/musb_core.h | 39 ++++++++++
+ drivers/usb/musb/musb_regs.h | 90 ++++++++++++++++++++++++
+ drivers/usb/musb/omap2430.c | 16 ++++
+ 4 files changed, 300 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index f5ca435..0de19da 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2165,20 +2165,169 @@ static int __devexit musb_remove(struct platform_device *pdev)
+
+ #ifdef CONFIG_PM
+
++static struct musb_context_registers musb_context;
++
++void musb_save_context(void __iomem *musb_base)
++{
++ int i;
++
++ musb_platform_save_context(&musb_context);
++
++ musb_context.faddr = musb_readb(musb_base, MUSB_FADDR);
++ musb_context.power = musb_readb(musb_base, MUSB_POWER);
++ musb_context.intrtx = musb_readw(musb_base, MUSB_INTRTX);
++ musb_context.intrrx = musb_readw(musb_base, MUSB_INTRRX);
++ musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
++ musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
++ musb_context.intrusb = musb_readb(musb_base, MUSB_INTRUSB);
++ musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
++ musb_context.frame = musb_readw(musb_base, MUSB_FRAME);
++ musb_context.index = musb_readb(musb_base, MUSB_INDEX);
++ musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
++ musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
++
++ for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
++ musb_writeb(musb_base, MUSB_INDEX, i);
++ musb_context.index_regs[i].txmaxp =
++ musb_readw(musb_base, 0x10 + MUSB_TXMAXP);
++ musb_context.index_regs[i].txcsr =
++ musb_readw(musb_base, 0x10 + MUSB_TXCSR);
++ musb_context.index_regs[i].rxmaxp =
++ musb_readw(musb_base, 0x10 + MUSB_RXMAXP);
++ musb_context.index_regs[i].rxcsr =
++ musb_readw(musb_base, 0x10 + MUSB_RXCSR);
++ musb_context.index_regs[i].rxcount =
++ musb_readw(musb_base, 0x10 + MUSB_RXCOUNT);
++ musb_context.index_regs[i].txtype =
++ musb_readb(musb_base, 0x10 + MUSB_TXTYPE);
++ musb_context.index_regs[i].txinterval =
++ musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL);
++ musb_context.index_regs[i].rxtype =
++ musb_readb(musb_base, 0x10 + MUSB_RXTYPE);
++ musb_context.index_regs[i].rxinterval =
++ musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL);
++
++ musb_context.index_regs[i].txfifoadd =
++ musb_read_txfifoadd(musb_base);
++ musb_context.index_regs[i].rxfifoadd =
++ musb_read_rxfifoadd(musb_base);
++ musb_context.index_regs[i].txfifosz =
++ musb_read_txfifosz(musb_base);
++ musb_context.index_regs[i].rxfifosz =
++ musb_read_rxfifosz(musb_base);
++
++ musb_context.index_regs[i].txfunaddr =
++ musb_read_txfunaddr(musb_base, i);
++ musb_context.index_regs[i].txhubaddr =
++ musb_read_txhubaddr(musb_base, i);
++ musb_context.index_regs[i].txhubport =
++ musb_read_txhubport(musb_base, i);
++
++ musb_context.index_regs[i].rxfunaddr =
++ musb_read_rxfunaddr(musb_base, i);
++ musb_context.index_regs[i].rxhubaddr =
++ musb_read_rxhubaddr(musb_base, i);
++ musb_context.index_regs[i].rxhubport =
++ musb_read_rxhubport(musb_base, i);
++ }
++
++ musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
++}
++
++void musb_restore_context(void __iomem *musb_base)
++{
++ int i;
++ void __iomem *ep_target_regs;
++
++ musb_writeb(musb_base, MUSB_FADDR, musb_context.faddr);
++ musb_writeb(musb_base, MUSB_POWER, musb_context.power);
++ musb_writew(musb_base, MUSB_INTRTX, musb_context.intrtx);
++ musb_writew(musb_base, MUSB_INTRRX, musb_context.intrrx);
++ musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe);
++ musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe);
++ musb_writeb(musb_base, MUSB_INTRUSB, musb_context.intrusb);
++ musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe);
++ musb_writew(musb_base, MUSB_FRAME, musb_context.frame);
++ musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode);
++ musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl);
++
++
++ for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
++ musb_writeb(musb_base, MUSB_INDEX, i);
++ musb_writew(musb_base, 0x10 + MUSB_TXMAXP,
++ musb_context.index_regs[i].txmaxp);
++ musb_writew(musb_base, 0x10 + MUSB_TXCSR,
++ musb_context.index_regs[i].txcsr);
++ musb_writew(musb_base, 0x10 + MUSB_RXMAXP,
++ musb_context.index_regs[i].rxmaxp);
++ musb_writew(musb_base, 0x10 + MUSB_RXCSR,
++ musb_context.index_regs[i].rxcsr);
++ musb_writew(musb_base, 0x10 + MUSB_RXCOUNT,
++ musb_context.index_regs[i].rxcount);
++ musb_writeb(musb_base, 0x10 + MUSB_TXTYPE,
++ musb_context.index_regs[i].txtype);
++ musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL,
++ musb_context.index_regs[i].txinterval);
++ musb_writeb(musb_base, 0x10 + MUSB_RXTYPE,
++ musb_context.index_regs[i].rxtype);
++ musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL,
++ musb_context.index_regs[i].rxinterval);
++
++ musb_write_txfifosz(musb_base,
++ musb_context.index_regs[i].txfifosz);
++ musb_write_rxfifosz(musb_base,
++ musb_context.index_regs[i].rxfifosz);
++ musb_write_txfifoadd(musb_base,
++ musb_context.index_regs[i].txfifoadd);
++ musb_write_rxfifoadd(musb_base,
++ musb_context.index_regs[i].rxfifoadd);
++
++ musb_write_txfunaddr(musb_base, i,
++ musb_context.index_regs[i].txfunaddr);
++ musb_write_txhubaddr(musb_base, i,
++ musb_context.index_regs[i].txhubaddr);
++ musb_write_txhubport(musb_base, i,
++ musb_context.index_regs[i].txhubport);
++
++ ep_target_regs = musb_read_target_reg_base(i, musb_base);
++
++ musb_write_rxfunaddr(ep_target_regs,
++ musb_context.index_regs[i].rxfunaddr);
++ musb_write_rxhubaddr(ep_target_regs,
++ musb_context.index_regs[i].rxhubaddr);
++ musb_write_rxhubport(ep_target_regs,
++ musb_context.index_regs[i].rxhubport);
++ }
++
++ musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
++
++ musb_platform_restore_context(&musb_context);
++}
++
+ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
+ {
+ unsigned long flags;
+ struct musb *musb = dev_to_musb(&pdev->dev);
++ u8 reg;
+
+ if (!musb->clock)
+ return 0;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
++ musb_save_context(musb->mregs);
++
+ if (is_peripheral_active(musb)) {
+- /* FIXME force disconnect unless we know USB will wake
+- * the system up quickly enough to respond ...
++ /* System is entering into suspend where gadget would not be
++ * able to respond to host and thus it will be in an unknown
++ * state for host.Re-enumemation of gadget is required after
++ * resume to make the gadget functional thus doing a force
++ * disconnect.
+ */
++ reg = musb_readb(musb->mregs, MUSB_POWER);
++ reg &= ~MUSB_POWER_SOFTCONN;
++ musb_writeb(musb->mregs, MUSB_POWER, reg);
++
+ } else if (is_host_active(musb)) {
+ /* we know all the children are suspended; sometimes
+ * they will even be wakeup-enabled.
+@@ -2205,6 +2354,8 @@ static int musb_resume_early(struct platform_device *pdev)
+ else
+ clk_enable(musb->clock);
+
++ musb_restore_context(musb->mregs);
++
+ /* for static cmos like DaVinci, register values were preserved
+ * unless for some reason the whole soc powered down or the USB
+ * module got reset through the PSC (vs just being disabled).
+@@ -2215,6 +2366,8 @@ static int musb_resume_early(struct platform_device *pdev)
+ #else
+ #define musb_suspend NULL
+ #define musb_resume_early NULL
++#define musb_save_context do {} while (0)
++#define musb_restore_context do {} while (0)
+ #endif
+
+ static struct platform_driver musb_driver = {
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index b0b4fbd..4568a8e 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -446,6 +446,45 @@ struct musb {
+ #endif
+ };
+
++#ifdef CONFIG_PM
++struct musb_csr_regs {
++ /* FIFO registers */
++ u16 txmaxp, txcsr, rxmaxp, rxcsr, rxcount;
++ u16 rxfifoadd, txfifoadd;
++ u8 txtype, txinterval, rxtype, rxinterval;
++ u8 rxfifosz, txfifosz;
++ u8 txfunaddr, txhubaddr, txhubport;
++ u8 rxfunaddr, rxhubaddr, rxhubport;
++};
++
++struct musb_context_registers {
++
++#if defined(CONFIG_ARCH_OMAP34XX)
++ u32 otg_sysconfig, otg_forcestandby;
++#endif
++ u8 faddr, power;
++ u16 intrtx, intrrx, intrtxe, intrrxe;
++ u8 intrusb, intrusbe;
++ u16 frame;
++ u8 index, testmode;
++
++ u8 devctl, misc;
++
++ struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
++};
++
++#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430)
++extern void musb_platform_save_context(struct musb_context_registers
++ *musb_context);
++extern void musb_platform_restore_context(struct musb_context_registers
++ *musb_context);
++#else
++#define musb_platform_save_context(x) do {} while (0)
++#define musb_platform_restore_context(x) do {} while (0)
++#endif
++
++#endif
++
+ static inline void musb_set_vbus(struct musb *musb, int is_on)
+ {
+ musb->board_set_vbus(musb, is_on);
+diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
+index fbfd3fd..a8e19da 100644
+--- a/drivers/usb/musb/musb_regs.h
++++ b/drivers/usb/musb/musb_regs.h
+@@ -321,6 +321,26 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+ musb_writew(mbase, MUSB_RXFIFOADD, c_off);
+ }
+
++static inline u8 musb_read_txfifosz(void __iomem *mbase)
++{
++ return musb_readb(mbase, MUSB_TXFIFOSZ);
++}
++
++static inline u16 musb_read_txfifoadd(void __iomem *mbase)
++{
++ return musb_readw(mbase, MUSB_TXFIFOADD);
++}
++
++static inline u8 musb_read_rxfifosz(void __iomem *mbase)
++{
++ return musb_readb(mbase, MUSB_RXFIFOSZ);
++}
++
++static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
++{
++ return musb_readw(mbase, MUSB_RXFIFOADD);
++}
++
+ static inline u8 musb_read_configdata(void __iomem *mbase)
+ {
+ musb_writeb(mbase, MUSB_INDEX, 0);
+@@ -376,6 +396,36 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ qh_h_port_reg);
+ }
+
++static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR));
++}
++
++static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR));
++}
++
++static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT));
++}
++
++static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR));
++}
++
++static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR));
++}
++
++static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
++{
++ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT));
++}
++
+ #else /* CONFIG_BLACKFIN */
+
+ #define USB_BASE USB_FADDR
+@@ -464,6 +514,22 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+ {
+ }
+
++static inline u8 musb_read_txfifosz(void __iomem *mbase)
++{
++}
++
++static inline u16 musb_read_txfifoadd(void __iomem *mbase)
++{
++}
++
++static inline u8 musb_read_rxfifosz(void __iomem *mbase)
++{
++}
++
++static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
++{
++}
++
+ static inline u8 musb_read_configdata(void __iomem *mbase)
+ {
+ return 0;
+@@ -509,6 +575,30 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ {
+ }
+
++static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
++{
++}
++
++static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
++{
++}
++
++static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
++{
++}
++
++static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
++{
++}
++
++static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
++{
++}
++
++static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum)
++{
++}
++
+ #endif /* CONFIG_BLACKFIN */
+
+ #endif /* __MUSB_REGS_H__ */
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 3487520..84af3b3 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -255,6 +255,22 @@ int __init musb_platform_init(struct musb *musb)
+ return 0;
+ }
+
++#ifdef CONFIG_PM
++void musb_platform_save_context(struct musb_context_registers
++ *musb_context)
++{
++ musb_context->otg_sysconfig = omap_readl(OTG_SYSCONFIG);
++ musb_context->otg_forcestandby = omap_readl(OTG_FORCESTDBY);
++}
++
++void musb_platform_restore_context(struct musb_context_registers
++ *musb_context)
++{
++ omap_writel(musb_context->otg_sysconfig, OTG_SYSCONFIG);
++ omap_writel(musb_context->otg_forcestandby, OTG_FORCESTDBY);
++}
++#endif
++
+ int musb_platform_suspend(struct musb *musb)
+ {
+ u32 l;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0016-usb-update-defconfig.patch b/recipes/linux/linux-omap-2.6.31/usb/0016-usb-update-defconfig.patch
new file mode 100644
index 0000000000..865016aca7
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.31/usb/0016-usb-update-defconfig.patch
@@ -0,0 +1,618 @@
+From cbcea73d911a840a420b9e0dbf5e0715d00533b0 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri, 11 Sep 2009 10:48:54 +0530
+Subject: [PATCH 16/16] usb: update defconfig
+
+ - Enabled USB Audio/Video (UVC)
+ - Enabled RNDIS gadget builtin
+ - ENabled EHCI
+---
+ arch/arm/configs/omap3_evm_defconfig | 229 +++++++++++++++++++++++++---------
+ 1 files changed, 171 insertions(+), 58 deletions(-)
+
+diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig
+index d5ff477..8a8b4b0 100644
+--- a/arch/arm/configs/omap3_evm_defconfig
++++ b/arch/arm/configs/omap3_evm_defconfig
+@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
+ CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_STACKTRACE_SUPPORT=y
+ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+@@ -18,13 +17,12 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
+
+ #
+ # General setup
+@@ -77,7 +75,6 @@ CONFIG_UID16=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ CONFIG_KALLSYMS_EXTRA_PASS=y
+-# CONFIG_STRIP_ASM_SYMS is not set
+ CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
+@@ -90,7 +87,12 @@ CONFIG_TIMERFD=y
+ CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+ CONFIG_AIO=y
++
++#
++# Performance Counters
++#
+ CONFIG_VM_EVENT_COUNTERS=y
++# CONFIG_STRIP_ASM_SYMS is not set
+ CONFIG_COMPAT_BRK=y
+ CONFIG_SLAB=y
+ # CONFIG_SLUB is not set
+@@ -102,6 +104,10 @@ CONFIG_HAVE_OPROFILE=y
+ CONFIG_HAVE_KPROBES=y
+ CONFIG_HAVE_KRETPROBES=y
+ CONFIG_HAVE_CLK=y
++
++#
++# GCOV-based kernel profiling
++#
+ # CONFIG_SLOW_WORK is not set
+ CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+ CONFIG_SLABINFO=y
+@@ -114,7 +120,7 @@ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_BLK_DEV_INTEGRITY is not set
+
+@@ -141,13 +147,14 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_VERSATILE is not set
+ # CONFIG_ARCH_AT91 is not set
+ # CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
+ # CONFIG_ARCH_EBSA110 is not set
+ # CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_GEMINI is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_STMP3XXX is not set
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+ # CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+@@ -156,25 +163,25 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
+ # CONFIG_ARCH_KIRKWOOD is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+ # CONFIG_ARCH_LOKI is not set
+ # CONFIG_ARCH_MV78XX0 is not set
+-# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_MSM is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_S3C64XX is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
+ # CONFIG_ARCH_DAVINCI is not set
+ CONFIG_ARCH_OMAP=y
+-# CONFIG_ARCH_MSM is not set
+-# CONFIG_ARCH_W90X900 is not set
+
+ #
+ # TI OMAP Implementations
+@@ -183,6 +190,7 @@ CONFIG_ARCH_OMAP_OTG=y
+ # CONFIG_ARCH_OMAP1 is not set
+ # CONFIG_ARCH_OMAP2 is not set
+ CONFIG_ARCH_OMAP3=y
++# CONFIG_ARCH_OMAP4 is not set
+
+ #
+ # OMAP Feature Selections
+@@ -202,7 +210,8 @@ CONFIG_OMAP_DM_TIMER=y
+ CONFIG_OMAP_LL_DEBUG_UART1=y
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART3 is not set
+-CONFIG_OMAP_SERIAL_WAKE=y
++# CONFIG_OMAP_PM_NONE is not set
++CONFIG_OMAP_PM_NOOP=y
+ CONFIG_ARCH_OMAP34XX=y
+ CONFIG_ARCH_OMAP3430=y
+
+@@ -216,6 +225,7 @@ CONFIG_MACH_OMAP3EVM=y
+ # CONFIG_MACH_OMAP3_PANDORA is not set
+ # CONFIG_MACH_OMAP_3430SDP is not set
+ # CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+ #
+ # Processor Type
+@@ -243,7 +253,6 @@ CONFIG_ARM_THUMB=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_BPREDICT_DISABLE is not set
+ CONFIG_HAS_TLS_REG=y
+-# CONFIG_OUTER_CACHE is not set
+ # CONFIG_ARM_ERRATA_430973 is not set
+ # CONFIG_ARM_ERRATA_458693 is not set
+ # CONFIG_ARM_ERRATA_460075 is not set
+@@ -271,7 +280,6 @@ CONFIG_PAGE_OFFSET=0xC0000000
+ CONFIG_HZ=128
+ CONFIG_AEABI=y
+ CONFIG_OABI_COMPAT=y
+-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+ # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+ # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+ # CONFIG_HIGHMEM is not set
+@@ -286,11 +294,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_PHYS_ADDR_T_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=0
+ CONFIG_VIRT_TO_BUS=y
+-CONFIG_UNEVICTABLE_LRU=y
+ CONFIG_HAVE_MLOCK=y
+ CONFIG_HAVE_MLOCKED_PAGE_BIT=y
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+ #
+ # Boot options
+@@ -401,6 +410,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+ # CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_DCB is not set
+
+@@ -418,7 +428,11 @@ CONFIG_WIRELESS=y
+ # CONFIG_WIRELESS_OLD_REGULATORY is not set
+ # CONFIG_WIRELESS_EXT is not set
+ # CONFIG_LIB80211 is not set
+-# CONFIG_MAC80211 is not set
++
++#
++# CFG80211 needs to be enabled for MAC80211
++#
++CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+ # CONFIG_WIMAX is not set
+ # CONFIG_RFKILL is not set
+ # CONFIG_NET_9P is not set
+@@ -516,6 +530,7 @@ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_ECC_SMC is not set
+ # CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ # CONFIG_MTD_NAND_GPIO is not set
++# CONFIG_MTD_NAND_OMAP2 is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ # CONFIG_MTD_NAND_NANDSIM is not set
+@@ -551,6 +566,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384
+ # CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
+ # CONFIG_MISC_DEVICES is not set
+ CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+@@ -574,10 +590,6 @@ CONFIG_BLK_DEV_SD=y
+ # CONFIG_BLK_DEV_SR is not set
+ # CONFIG_CHR_DEV_SG is not set
+ # CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+@@ -602,7 +614,6 @@ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ATA is not set
+ # CONFIG_MD is not set
+ CONFIG_NETDEVICES=y
+-CONFIG_COMPAT_NET_DEV_OPS=y
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
+ # CONFIG_MACVLAN is not set
+@@ -628,6 +639,8 @@ CONFIG_SMC911X=y
+ # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+ # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+ # CONFIG_B44 is not set
++# CONFIG_KS8842 is not set
++# CONFIG_KS8851 is not set
+ # CONFIG_NETDEV_1000 is not set
+ # CONFIG_NETDEV_10000 is not set
+
+@@ -677,12 +690,13 @@ CONFIG_INPUT_EVDEV=y
+ #
+ CONFIG_INPUT_KEYBOARD=y
+ # CONFIG_KEYBOARD_ATKBD is not set
+-# CONFIG_KEYBOARD_SUNKBD is not set
+ # CONFIG_KEYBOARD_LKKBD is not set
+-# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_GPIO is not set
++# CONFIG_KEYBOARD_MATRIX is not set
+ # CONFIG_KEYBOARD_NEWTON is not set
+ # CONFIG_KEYBOARD_STOWAWAY is not set
+-# CONFIG_KEYBOARD_GPIO is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+ # CONFIG_INPUT_TABLET is not set
+@@ -692,6 +706,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
+ # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+ # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+ # CONFIG_TOUCHSCREEN_AD7879 is not set
++# CONFIG_TOUCHSCREEN_EETI is not set
+ # CONFIG_TOUCHSCREEN_FUJITSU is not set
+ # CONFIG_TOUCHSCREEN_GUNZE is not set
+ # CONFIG_TOUCHSCREEN_ELO is not set
+@@ -705,6 +720,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
+ # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+ # CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
+ # CONFIG_INPUT_MISC is not set
+
+ #
+@@ -764,6 +780,7 @@ CONFIG_I2C_HELPER_AUTO=y
+ #
+ # I2C system bus drivers (mostly embedded / system-on-chip)
+ #
++# CONFIG_I2C_DESIGNWARE is not set
+ # CONFIG_I2C_GPIO is not set
+ # CONFIG_I2C_OCORES is not set
+ CONFIG_I2C_OMAP=y
+@@ -789,7 +806,6 @@ CONFIG_I2C_OMAP=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+@@ -850,6 +866,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
+ #
+ # CONFIG_SOFT_WATCHDOG is not set
+ CONFIG_OMAP_WATCHDOG=y
++# CONFIG_TWL4030_WATCHDOG is not set
+
+ #
+ # USB-based Watchdog Cards
+@@ -880,23 +897,74 @@ CONFIG_TWL4030_CORE=y
+ # CONFIG_MFD_WM8400 is not set
+ # CONFIG_MFD_WM8350_I2C is not set
+ # CONFIG_MFD_PCF50633 is not set
+-
+-#
+-# Multimedia devices
+-#
++# CONFIG_AB3100_CORE is not set
++# CONFIG_EZX_PCAP is not set
++CONFIG_MEDIA_SUPPORT=y
+
+ #
+ # Multimedia core support
+ #
+-# CONFIG_VIDEO_DEV is not set
++CONFIG_VIDEO_DEV=y
++CONFIG_VIDEO_V4L2_COMMON=y
++CONFIG_VIDEO_ALLOW_V4L1=y
++CONFIG_VIDEO_V4L1_COMPAT=y
+ # CONFIG_DVB_CORE is not set
+-# CONFIG_VIDEO_MEDIA is not set
++CONFIG_VIDEO_MEDIA=y
+
+ #
+ # Multimedia drivers
+ #
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_MEDIA_ATTACH is not set
++CONFIG_MEDIA_TUNER=y
++# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
++CONFIG_MEDIA_TUNER_SIMPLE=y
++CONFIG_MEDIA_TUNER_TDA8290=y
++CONFIG_MEDIA_TUNER_TDA9887=y
++CONFIG_MEDIA_TUNER_TEA5761=y
++CONFIG_MEDIA_TUNER_TEA5767=y
++CONFIG_MEDIA_TUNER_MT20XX=y
++CONFIG_MEDIA_TUNER_XC2028=y
++CONFIG_MEDIA_TUNER_XC5000=y
++CONFIG_MEDIA_TUNER_MC44S803=y
++CONFIG_VIDEO_V4L2=y
++CONFIG_VIDEO_V4L1=y
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_VIVI is not set
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_CPIA2 is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_SOC_CAMERA is not set
++CONFIG_V4L_USB_DRIVERS=y
++CONFIG_USB_VIDEO_CLASS=y
++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
++# CONFIG_USB_GSPCA is not set
++# CONFIG_VIDEO_PVRUSB2 is not set
++# CONFIG_VIDEO_HDPVR is not set
++# CONFIG_VIDEO_EM28XX is not set
++# CONFIG_VIDEO_CX231XX is not set
++# CONFIG_VIDEO_USBVISION is not set
++# CONFIG_USB_VICAM is not set
++# CONFIG_USB_IBMCAM is not set
++# CONFIG_USB_KONICAWC is not set
++# CONFIG_USB_QUICKCAM_MESSENGER is not set
++# CONFIG_USB_ET61X251 is not set
++# CONFIG_VIDEO_OVCAMCHIP is not set
++# CONFIG_USB_OV511 is not set
++# CONFIG_USB_SE401 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_STV680 is not set
++# CONFIG_USB_ZC0301 is not set
++# CONFIG_USB_PWC is not set
++# CONFIG_USB_PWC_INPUT_EVDEV is not set
++# CONFIG_USB_ZR364XX is not set
++# CONFIG_USB_STKWEBCAM is not set
++# CONFIG_USB_S2255 is not set
++# CONFIG_RADIO_ADAPTERS is not set
++# CONFIG_DAB is not set
+
+ #
+ # Graphics support
+@@ -916,7 +984,35 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_SOUND is not set
++CONFIG_SOUND=y
++# CONFIG_SOUND_OSS_CORE is not set
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_HWDEP=y
++CONFIG_SND_RAWMIDI=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_HRTIMER is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++# CONFIG_SND_RAWMIDI_SEQ is not set
++# CONFIG_SND_OPL3_LIB_SEQ is not set
++# CONFIG_SND_OPL4_LIB_SEQ is not set
++# CONFIG_SND_SBAWE_SEQ is not set
++# CONFIG_SND_EMU10K1_SEQ is not set
++# CONFIG_SND_DRIVERS is not set
++# CONFIG_SND_ARM is not set
++# CONFIG_SND_SPI is not set
++CONFIG_SND_USB=y
++CONFIG_SND_USB_AUDIO=y
++# CONFIG_SND_USB_CAIAQ is not set
++# CONFIG_SND_SOC is not set
++# CONFIG_SOUND_PRIME is not set
+ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+ # CONFIG_HID_DEBUG is not set
+@@ -938,7 +1034,7 @@ CONFIG_USB_HID=y
+ # CONFIG_HID_CHERRY is not set
+ # CONFIG_HID_CHICONY is not set
+ # CONFIG_HID_CYPRESS is not set
+-# CONFIG_DRAGONRISE_FF is not set
++# CONFIG_HID_DRAGONRISE is not set
+ # CONFIG_HID_EZKEY is not set
+ # CONFIG_HID_KYE is not set
+ # CONFIG_HID_GYRATION is not set
+@@ -952,14 +1048,15 @@ CONFIG_USB_HID=y
+ # CONFIG_HID_SAMSUNG is not set
+ # CONFIG_HID_SONY is not set
+ # CONFIG_HID_SUNPLUS is not set
+-# CONFIG_GREENASIA_FF is not set
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
+ # CONFIG_HID_TOPSEED is not set
+-# CONFIG_THRUSTMASTER_FF is not set
+-# CONFIG_ZEROPLUS_FF is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_ZEROPLUS is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
+ CONFIG_USB=y
+ # CONFIG_USB_DEBUG is not set
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+@@ -974,7 +1071,7 @@ CONFIG_USB_SUSPEND=y
+ CONFIG_USB_OTG=y
+ # CONFIG_USB_OTG_WHITELIST is not set
+ # CONFIG_USB_OTG_BLACKLIST_HUB is not set
+-CONFIG_USB_MON=y
++# CONFIG_USB_MON is not set
+ # CONFIG_USB_WUSB is not set
+ # CONFIG_USB_WUSB_CBAF is not set
+
+@@ -982,6 +1079,9 @@ CONFIG_USB_MON=y
+ # USB Host Controller Drivers
+ #
+ # CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+ # CONFIG_USB_OXU210HP_HCD is not set
+ # CONFIG_USB_ISP116X_HCD is not set
+ # CONFIG_USB_ISP1760_HCD is not set
+@@ -1003,7 +1103,7 @@ CONFIG_USB_MUSB_HDRC_HCD=y
+ # CONFIG_MUSB_PIO_ONLY is not set
+ CONFIG_USB_INVENTRA_DMA=y
+ # CONFIG_USB_TI_CPPI_DMA is not set
+-# CONFIG_USB_MUSB_DEBUG is not set
++CONFIG_USB_MUSB_DEBUG=y
+
+ #
+ # USB Device Class drivers
+@@ -1063,10 +1163,11 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_IDMOUSE is not set
+ # CONFIG_USB_FTDI_ELAN is not set
+ # CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
+ # CONFIG_USB_IOWARRIOR is not set
+-CONFIG_USB_TEST=y
++# CONFIG_USB_TEST is not set
+ # CONFIG_USB_ISIGHTFW is not set
+ # CONFIG_USB_VST is not set
+ CONFIG_USB_GADGET=y
+@@ -1081,19 +1182,22 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_OMAP is not set
+ # CONFIG_USB_GADGET_PXA25X is not set
+ # CONFIG_USB_GADGET_PXA27X is not set
+-# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_S3C_HSOTG is not set
+ # CONFIG_USB_GADGET_IMX is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ # CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_AMD5536UDC is not set
+ # CONFIG_USB_GADGET_FSL_QE is not set
+ # CONFIG_USB_GADGET_CI13XXX is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+ CONFIG_USB_GADGET_DUALSPEED=y
+-CONFIG_USB_ZERO=m
+-# CONFIG_USB_ZERO_HNPTEST is not set
+-# CONFIG_USB_ETH is not set
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
+ # CONFIG_USB_GADGETFS is not set
+ # CONFIG_USB_FILE_STORAGE is not set
+ # CONFIG_USB_G_SERIAL is not set
+@@ -1108,7 +1212,7 @@ CONFIG_USB_OTG_UTILS=y
+ # CONFIG_USB_GPIO_VBUS is not set
+ # CONFIG_ISP1301_OMAP is not set
+ # CONFIG_TWL4030_USB is not set
+-# CONFIG_NOP_USB_XCEIV is not set
++CONFIG_NOP_USB_XCEIV=y
+ CONFIG_MMC=y
+ # CONFIG_MMC_DEBUG is not set
+ # CONFIG_MMC_UNSAFE_RESUME is not set
+@@ -1125,7 +1229,6 @@ CONFIG_MMC_BLOCK_BOUNCE=y
+ # MMC/SD/SDIO Host Controller Drivers
+ #
+ # CONFIG_MMC_SDHCI is not set
+-# CONFIG_MMC_OMAP is not set
+ CONFIG_MMC_OMAP_HS=m
+ # CONFIG_MMC_SPI is not set
+ # CONFIG_MEMSTICK is not set
+@@ -1139,12 +1242,20 @@ CONFIG_REGULATOR=y
+ # CONFIG_REGULATOR_DEBUG is not set
+ # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+ # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+ # CONFIG_REGULATOR_BQ24022 is not set
++# CONFIG_REGULATOR_MAX1586 is not set
+ CONFIG_REGULATOR_TWL4030=y
++# CONFIG_REGULATOR_LP3971 is not set
+ # CONFIG_UIO is not set
+ # CONFIG_STAGING is not set
+
+ #
++# CBUS support
++#
++# CONFIG_CBUS is not set
++
++#
+ # File systems
+ #
+ CONFIG_EXT2_FS=y
+@@ -1158,10 +1269,12 @@ CONFIG_JBD=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+-CONFIG_FILE_LOCKING=y
+ # CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+ # CONFIG_BTRFS_FS is not set
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
+ CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+@@ -1247,6 +1360,7 @@ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+ CONFIG_NFS_V4=y
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+ # CONFIG_NFSD is not set
+ CONFIG_LOCKD=y
+@@ -1349,6 +1463,7 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+ # CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_OBJECTS is not set
+ # CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_KMEMLEAK is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+@@ -1377,17 +1492,15 @@ CONFIG_DEBUG_INFO=y
+ # CONFIG_PAGE_POISONING is not set
+ CONFIG_HAVE_FUNCTION_TRACER=y
+ CONFIG_TRACING_SUPPORT=y
+-
+-#
+-# Tracers
+-#
++CONFIG_FTRACE=y
+ # CONFIG_FUNCTION_TRACER is not set
+ # CONFIG_IRQSOFF_TRACER is not set
+ # CONFIG_SCHED_TRACER is not set
+-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+-# CONFIG_EVENT_TRACER is not set
++# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+ # CONFIG_BOOT_TRACER is not set
+-# CONFIG_TRACE_BRANCH_PROFILING is not set
++CONFIG_BRANCH_PROFILE_NONE=y
++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
++# CONFIG_PROFILE_ALL_BRANCHES is not set
+ # CONFIG_STACK_TRACER is not set
+ # CONFIG_KMEMTRACE is not set
+ # CONFIG_WORKQUEUE_TRACER is not set
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/0001-ASoC-Add-support-for-OMAP3-EVM.patch b/recipes/linux/linux-omap-pm-2.6.29/0001-ASoC-Add-support-for-OMAP3-EVM.patch
new file mode 100644
index 0000000000..a76e96e444
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/0001-ASoC-Add-support-for-OMAP3-EVM.patch
@@ -0,0 +1,206 @@
+From c1dad0b6b434300ae64c902d11611c54c513ea10 Mon Sep 17 00:00:00 2001
+From: Anuj Aggarwal <anuj.aggarwal@ti.com>
+Date: Fri, 21 Nov 2008 17:41:03 +0530
+Subject: [PATCH] ASoC: Add support for OMAP3 EVM
+
+This patch adds ALSA SoC support for OMAP3 EVM using TWL4030 audio codec.
+
+Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
+---
+ sound/soc/omap/Kconfig | 8 +++
+ sound/soc/omap/Makefile | 3 +-
+ sound/soc/omap/omap3evm.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 157 insertions(+), 1 deletions(-)
+ create mode 100644 sound/soc/omap/omap3evm.c
+
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 0daeee4..deb6ba9 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -22,6 +22,14 @@ config SND_OMAP_SOC_OMAP3_BEAGLE
+ help
+ Say Y if you want to add support for SoC audio on the Beagleboard.
+
++config SND_OMAP_SOC_OMAP3EVM
++ tristate "SoC Audio support for OMAP3EVM board"
++ depends on SND_OMAP_SOC && MACH_OMAP3EVM
++ select SND_OMAP_SOC_MCBSP
++ select SND_SOC_TWL4030
++ help
++ Say Y if you want to add support for SoC audio on the omap3evm board.
++
+ config SND_OMAP_SOC_OSK5912
+ tristate "SoC Audio support for omap osk5912"
+ depends on SND_OMAP_SOC && MACH_OMAP_OSK
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index 4bae404..ef31c25 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -10,9 +10,10 @@ snd-soc-n810-objs := n810.o
+ snd-soc-omap3beagle-objs := omap3beagle.o
+ snd-soc-osk5912-objs := osk5912.o
+ snd-soc-overo-objs := overo.o
++snd-soc-omap3evm-objs := omap3evm.o
+
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
+ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+-
++obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
+diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
+new file mode 100644
+index 0000000..570af55
+--- /dev/null
++++ b/sound/soc/omap/omap3evm.c
+@@ -0,0 +1,147 @@
++/*
++ * omap3evm.c -- ALSA SoC support for OMAP3 EVM
++ *
++ * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
++ *
++ * Based on sound/soc/omap/beagle.c by Steve Sakoman
++ *
++ * Copyright (C) 2008 Texas Instruments, Incorporated
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
++ * whether express or implied; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/mach-types.h>
++#include <mach/hardware.h>
++#include <mach/gpio.h>
++#include <mach/mcbsp.h>
++
++#include "omap-mcbsp.h"
++#include "omap-pcm.h"
++#include "../codecs/twl4030.h"
++
++static int omap3evm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
++ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
++ int ret;
++
++ /* Set codec DAI configuration */
++ ret = snd_soc_dai_set_fmt(codec_dai,
++ SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM);
++ if (ret < 0) {
++ printk(KERN_ERR "can't set codec DAI configuration\n");
++ return ret;
++ }
++
++ /* Set cpu DAI configuration */
++ ret = snd_soc_dai_set_fmt(cpu_dai,
++ SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBM_CFM);
++ if (ret < 0) {
++ printk(KERN_ERR "can't set cpu DAI configuration\n");
++ return ret;
++ }
++
++ /* Set the codec system clock for DAC and ADC */
++ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
++ SND_SOC_CLOCK_IN);
++ if (ret < 0) {
++ printk(KERN_ERR "can't set codec system clock\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static struct snd_soc_ops omap3evm_ops = {
++ .hw_params = omap3evm_hw_params,
++};
++
++/* Digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link omap3evm_dai = {
++ .name = "TWL4030",
++ .stream_name = "TWL4030",
++ .cpu_dai = &omap_mcbsp_dai[0],
++ .codec_dai = &twl4030_dai,
++ .ops = &omap3evm_ops,
++};
++
++/* Audio machine driver */
++static struct snd_soc_machine snd_soc_machine_omap3evm = {
++ .name = "omap3evm",
++ .dai_link = &omap3evm_dai,
++ .num_links = 1,
++};
++
++/* Audio subsystem */
++static struct snd_soc_device omap3evm_snd_devdata = {
++ .machine = &snd_soc_machine_omap3evm,
++ .platform = &omap_soc_platform,
++ .codec_dev = &soc_codec_dev_twl4030,
++};
++
++static struct platform_device *omap3evm_snd_device;
++
++static int __init omap3evm_soc_init(void)
++{
++ int ret;
++
++ if (!machine_is_omap3evm()) {
++ pr_debug("Not OMAP3 EVM!\n");
++ return -ENODEV;
++ }
++ pr_info("OMAP3 EVM SoC init\n");
++
++ omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
++ if (!omap3evm_snd_device) {
++ printk(KERN_ERR "Platform device allocation failed\n");
++ return -ENOMEM;
++ }
++
++ platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata);
++ omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev;
++ *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
++
++ ret = platform_device_add(omap3evm_snd_device);
++ if (ret)
++ goto err1;
++
++ return 0;
++
++err1:
++ printk(KERN_ERR "Unable to add platform device\n");
++ platform_device_put(omap3evm_snd_device);
++
++ return ret;
++}
++
++static void __exit omap3evm_soc_exit(void)
++{
++ platform_device_unregister(omap3evm_snd_device);
++}
++
++module_init(omap3evm_soc_init);
++module_exit(omap3evm_soc_exit);
++
++MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
++MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
++MODULE_LICENSE("GPL");
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/0001-This-merges-Steve-Kipisz-USB-EHCI-support.-He-star.patch b/recipes/linux/linux-omap-pm-2.6.29/0001-This-merges-Steve-Kipisz-USB-EHCI-support.-He-star.patch
new file mode 100644
index 0000000000..d590f8ffb9
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/0001-This-merges-Steve-Kipisz-USB-EHCI-support.-He-star.patch
@@ -0,0 +1,146 @@
+From f8f10f496bce396416d7156da876222c6ce8c341 Mon Sep 17 00:00:00 2001
+From: Steven Kipisz <skipisz@beagleboard.org>
+Date: Wed, 9 Jan 2009 12:01:11 -0600
+Subject: [PATCH-USB] Omap3 beagleboard: add support for EHCI in revision C1 boards
+
+Signed-off-by: Jason Kridner <jkridner@beagleboard.org>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 10 +---------
+ arch/arm/mach-omap2/usb-ehci.c | 4 +---
+ drivers/usb/host/ehci-omap.c | 26 ++++++++++++++++++++++++++
+ 3 files changed, 28 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index fe97bab..de81153 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -140,15 +140,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ * power switch and overcurrent detect
+ */
+
+- gpio_request(gpio + 1, "EHCI_nOC");
+- gpio_direction_input(gpio + 1);
+-
+- /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+- gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+-
+- /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+- gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
++ /* TODO: This needs to be modified to not rely on u-boot */
+
+ return 0;
+ }
+diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
+index 489439d..2c6305b 100644
+--- a/arch/arm/mach-omap2/usb-ehci.c
++++ b/arch/arm/mach-omap2/usb-ehci.c
+@@ -152,9 +152,7 @@ static void setup_ehci_io_mux(void)
+ void __init usb_ehci_init(void)
+ {
+ #if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+- /* Setup Pin IO MUX for EHCI */
+- if (cpu_is_omap34xx())
+- setup_ehci_io_mux();
++ /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+
+ if (platform_device_register(&ehci_device) < 0) {
+ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index 1b3266c..8472996 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,26 @@
+ * to get the PHY state machine in working state
+ */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OMAP3_BEAGLE
++#define EXT_PHY_RESET_GPIO_PORT2 (147)
++#else
+ #define EXT_PHY_RESET_GPIO_PORT1 (57)
+ #define EXT_PHY_RESET_GPIO_PORT2 (61)
++#endif
+ #define EXT_PHY_RESET_DELAY (10)
+
++#define PHY_STP_PULLUP_ENABLE (0x10)
++#define PHY_STP_PULLUP_DISABLE (0x90)
++
++
+ /* ISSUE2:
+ * USBHOST supports External charge pump PHYs only
+ * Use the VBUS from Port1 to power VBUS of Port2 externally
+ * So use Port2 as the working ULPI port
+ */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+
+@@ -225,14 +235,43 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+
+ #ifdef EXTERNAL_PHY_RESET
+ /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+ gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(EXT_PHY_RESET_DELAY);
+ #endif
+
++ /*
++ * The PHY register 0x7 - Interface Control register is
++ * configured to disable the integrated STP pull-up resistor
++ * used for interface protection.
++ *
++ * May not need to be here.
++ */
++ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (PHY_STP_PULLUP_DISABLE),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++ /* Force PHY to HS */
++ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (0x40),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+ /* Configure TLL for 60Mhz clk for ULPI */
+ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +346,9 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+ * Hold the PHY in RESET for enough time till PHY is settled and ready
+ */
+ udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+
+@@ -393,7 +434,9 @@ static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+
+
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
+
+--
+1.6.0.4.790.gaa14a
diff --git a/recipes/linux/linux-omap-pm-2.6.29/0001-board-ldp-add-regulator-info-to-get-the-microSD-slo.patch b/recipes/linux/linux-omap-pm-2.6.29/0001-board-ldp-add-regulator-info-to-get-the-microSD-slo.patch
new file mode 100644
index 0000000000..49045f7bb1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/0001-board-ldp-add-regulator-info-to-get-the-microSD-slo.patch
@@ -0,0 +1,90 @@
+From 7efa7cc5b807cb840c62b5bf54bf47181c9b95a6 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@openembedded.org>
+Date: Mon, 30 Mar 2009 15:21:37 +0200
+Subject: [PATCH v2] ARM: OMAP: board-ldp: add regulator info to get the microSD slot working again
+
+The ldp board was left behind when other boards got updated. The ldp info was copied from the beagleboard board file and s/beagle/ldp/g
+
+Changes since v1:
+ * dropped vsim portion since only 4 pins are hooked up
+
+Signed-off-by: Koen Kooi <koen@beagleboard.org>
+---
+ arch/arm/mach-omap2/board-ldp.c | 32 ++++++++++++++++++++++++++++++++
+ 1 files changed, 32 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
+index 30926b0..19a5c15 100644
+--- a/arch/arm/mach-omap2/board-ldp.c
++++ b/arch/arm/mach-omap2/board-ldp.c
+@@ -22,6 +22,7 @@
+ #include <linux/clk.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
++#include <linux/regulator/machine.h>
+ #include <linux/i2c/twl4030.h>
+
+ #include <mach/hardware.h>
+@@ -450,7 +451,16 @@ static struct twl4030_script *twl4030_scripts[] __initdata = {
+ &wrst_script,
+ };
+
++static const struct twl4030_resconfig ldp_resconfig[] = {
++ /* disable regulators that u-boot left enabled; the
++ * devices' drivers should be managing these.
++ */
++ { .resource = RES_VMMC1, },
++ { 0, },
++};
++
+ static struct twl4030_power_data sdp3430_t2scripts_data __initdata = {
++ .resource_config = ldp_resconfig,
+ .scripts = twl4030_scripts,
+ .size = ARRAY_SIZE(twl4030_scripts),
+ };
+@@ -474,6 +484,25 @@ static struct twl4030_madc_platform_data ldp_madc_data = {
+ .irq_line = 1,
+ };
+
++static struct regulator_consumer_supply ldp_vmmc1_supply = {
++ .supply = "vmmc",
++};
++
++/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
++static struct regulator_init_data ldp_vmmc1 = {
++ .constraints = {
++ .min_uV = 1850000,
++ .max_uV = 3150000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
++ | REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &ldp_vmmc1_supply,
++};
++
+ static struct twl4030_platform_data ldp_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+@@ -483,6 +512,7 @@ static struct twl4030_platform_data ldp_twldata = {
+ .madc = &ldp_madc_data,
+ .usb = &ldp_usb_data,
+ .power = &sdp3430_t2scripts_data,
++ .vmmc1 = &ldp_vmmc1,
+ .gpio = &ldp_gpio_data,
+ .keypad = &ldp_kp_twl4030_data,
+ };
+@@ -530,6 +560,8 @@ static void __init omap_ldp_init(void)
+ omap_serial_init();
+ usb_musb_init();
+ twl4030_mmc_init(mmc);
++ /* link regulators to MMC adapters */
++ ldp_vmmc1_supply.dev = mmc[0].dev;
+ }
+
+ static void __init omap_ldp_map_io(void)
+--
+1.6.2
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/0124-leds-gpio-broken-with-current-git.patch b/recipes/linux/linux-omap-pm-2.6.29/0124-leds-gpio-broken-with-current-git.patch
new file mode 100644
index 0000000000..dc6e190e89
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/0124-leds-gpio-broken-with-current-git.patch
@@ -0,0 +1,79 @@
+From c810e850d830330cf04225a4cff8e981e153f269 Mon Sep 17 00:00:00 2001
+From: David Brownell <david-b@pacbell.net>
+Date: Mon, 23 Feb 2009 14:08:14 -0800
+Subject: [PATCH 124/133] leds-gpio broken with current git?
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+On Monday 23 February 2009, David Brownell wrote:
+>
+> > Perhaps something broke with Tony's RC1 merge?
+> > The LEDs are broken for me as well.
+>
+> Still works for me.  Did you maybe not enable the twl4030
+> GPIO support in Kconfig?
+
+Oh, and if you did *not*, please give this patch a try.
+I've been meaning to test it.
+
+- Dave
+
+==============
+Sometimes it's awkward to make sure that the array in the
+platform_data handed to the leds-gpio driver has only valid
+data ... some leds may not be always available, and coping
+with that currently requires patching or rebuilding the array.
+
+This patch fixes that by making it be OK to pass an invalid
+GPIO (such as "-EINVAL") ... such table entries are skipped.
+---
+ drivers/leds/leds-gpio.c | 12 +++++++++++-
+ 1 files changed, 11 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index b13bd29..83737e6 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -90,13 +90,19 @@ static int gpio_led_probe(struct platform_device *pdev)
+ cur_led = &pdata->leds[i];
+ led_dat = &leds_data[i];
+
++ /* skip leds that aren't available */
++ led_dat->gpio = cur_led->gpio;
++ if (!gpio_is_valid(led_dat->gpio)) {
++ dev_dbg(&pdev->dev, "skipping %s\n", cur_led->name);
++ continue;
++ }
++
+ ret = gpio_request(cur_led->gpio, cur_led->name);
+ if (ret < 0)
+ goto err;
+
+ led_dat->cdev.name = cur_led->name;
+ led_dat->cdev.default_trigger = cur_led->default_trigger;
+- led_dat->gpio = cur_led->gpio;
+ led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
+ led_dat->active_low = cur_led->active_low;
+ if (pdata->gpio_blink_set) {
+@@ -124,6 +130,8 @@ static int gpio_led_probe(struct platform_device *pdev)
+ err:
+ if (i > 0) {
+ for (i = i - 1; i >= 0; i--) {
++ if (!gpio_is_valid(leds_data[i].gpio))
++ continue;
+ led_classdev_unregister(&leds_data[i].cdev);
+ cancel_work_sync(&leds_data[i].work);
+ gpio_free(leds_data[i].gpio);
+@@ -144,6 +152,8 @@ static int __devexit gpio_led_remove(struct platform_device *pdev)
+ leds_data = platform_get_drvdata(pdev);
+
+ for (i = 0; i < pdata->num_leds; i++) {
++ if (!gpio_is_valid(leds_data[i].gpio))
++ continue;
+ led_classdev_unregister(&leds_data[i].cdev);
+ cancel_work_sync(&leds_data[i].work);
+ gpio_free(leds_data[i].gpio);
+--
+1.6.0.4.790.gaa14a
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/ads7846-detection.patch b/recipes/linux/linux-omap-pm-2.6.29/ads7846-detection.patch
new file mode 100644
index 0000000000..25a1cb052c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/ads7846-detection.patch
@@ -0,0 +1,41 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 2ae5ab8..a68b0a6 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -1154,9 +1154,16 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+ /* take a first sample, leaving nPENIRQ active and vREF off; avoid
+ * the touchscreen, in case it's not connected.
+ */
+- (void) ads7846_read12_ser(&spi->dev,
++ err = ads7846_read12_ser(&spi->dev,
+ READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+
++ /* if sample is all 0's or all 1's then there is no device on spi */
++ if ( (err == 0x000) || (err == 0xfff)) {
++ dev_info(&spi->dev, "no device detected, test read result was 0x%08X\n", err);
++ err = -ENODEV;
++ goto err_free_irq;
++ }
++
+ err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group);
+ if (err)
+ goto err_remove_hwmon;
+@@ -1174,7 +1181,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+ err_free_irq:
+ free_irq(spi->irq, ts);
+ err_free_gpio:
+- if (ts->gpio_pendown != -1)
++ if (!ts->get_pendown_state && ts->gpio_pendown != -1)
+ gpio_free(ts->gpio_pendown);
+ err_cleanup_filter:
+ if (ts->filter_cleanup)
+@@ -1201,7 +1208,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
+ /* suspend left the IRQ disabled */
+ enable_irq(ts->spi->irq);
+
+- if (ts->gpio_pendown != -1)
++ if (!ts->get_pendown_state && ts->gpio_pendown != -1)
+ gpio_free(ts->gpio_pendown);
+
+ if (ts->filter_cleanup)
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/arch-has-holes.diff b/recipes/linux/linux-omap-pm-2.6.29/arch-has-holes.diff
new file mode 100644
index 0000000000..f3935eb90a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/arch-has-holes.diff
@@ -0,0 +1,235 @@
+diff -purN git2/arch/arm/include/asm/memory.h git/arch/arm/include/asm/memory.h
+--- git2/arch/arm/include/asm/memory.h 2009-06-08 06:42:26.000000000 +0530
++++ git/arch/arm/include/asm/memory.h 2009-08-17 11:58:07.000000000 +0530
+@@ -204,7 +204,6 @@ static inline __deprecated void *bus_to_
+ *
+ * page_to_pfn(page) convert a struct page * to a PFN number
+ * pfn_to_page(pfn) convert a _valid_ PFN number to struct page *
+- * pfn_valid(pfn) indicates whether a PFN number is valid
+ *
+ * virt_to_page(k) convert a _valid_ virtual address to struct page *
+ * virt_addr_valid(k) indicates whether a virtual address is valid
+@@ -213,10 +212,6 @@ static inline __deprecated void *bus_to_
+
+ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
+
+-#ifndef CONFIG_SPARSEMEM
+-#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
+-#endif
+-
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+
+@@ -233,18 +228,6 @@ static inline __deprecated void *bus_to_
+ #define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
+ #define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
+
+-#define pfn_valid(pfn) \
+- ({ \
+- unsigned int nid = PFN_TO_NID(pfn); \
+- int valid = nid < MAX_NUMNODES; \
+- if (valid) { \
+- pg_data_t *node = NODE_DATA(nid); \
+- valid = (pfn - node->node_start_pfn) < \
+- node->node_spanned_pages; \
+- } \
+- valid; \
+- })
+-
+ #define virt_to_page(kaddr) \
+ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
+diff -purN git2/arch/arm/include/asm/page.h git/arch/arm/include/asm/page.h
+--- git2/arch/arm/include/asm/page.h 2009-06-08 06:42:26.000000000 +0530
++++ git/arch/arm/include/asm/page.h 2009-08-17 11:58:07.000000000 +0530
+@@ -186,6 +186,10 @@ typedef unsigned long pgprot_t;
+
+ typedef struct page *pgtable_t;
+
++#ifndef CONFIG_SPARSEMEM
++extern int pfn_valid(unsigned long);
++#endif
++
+ #include <asm/memory.h>
+
+ #endif /* !__ASSEMBLY__ */
+diff -purN git2/arch/arm/Kconfig git/arch/arm/Kconfig
+--- git2/arch/arm/Kconfig 2009-07-20 05:07:12.000000000 +0530
++++ git/arch/arm/Kconfig 2009-08-17 12:08:37.000000000 +0530
+@@ -272,6 +272,7 @@ config ARCH_EP93XX
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_HAS_HOLES_MEMORYMODEL
+ help
+ This enables support for the Cirrus EP93xx series of CPUs.
+
+@@ -569,6 +570,7 @@ config ARCH_OMAP
+ select ARCH_REQUIRE_GPIOLIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
++ select ARCH_HAS_HOLES_MEMORYMODEL
+ help
+ Support for TI's OMAP platform (OMAP1 and OMAP2).
+
+@@ -891,10 +893,9 @@ config OABI_COMPAT
+ UNPREDICTABLE (in fact it can be predicted that it won't work
+ at all). If in doubt say Y.
+
+-config ARCH_FLATMEM_HAS_HOLES
++config ARCH_HAS_HOLES_MEMORYMODEL
+ bool
+- default y
+- depends on FLATMEM
++ default n
+
+ # Discontigmem is deprecated
+ config ARCH_DISCONTIGMEM_ENABLE
+diff -purN git2/arch/arm/mm/init.c git/arch/arm/mm/init.c
+--- git2/arch/arm/mm/init.c 2009-06-08 06:42:27.000000000 +0530
++++ git/arch/arm/mm/init.c 2009-08-17 12:03:16.000000000 +0530
+@@ -15,7 +15,7 @@
+ #include <linux/mman.h>
+ #include <linux/nodemask.h>
+ #include <linux/initrd.h>
+-
++#include <linux/sort.h>
+ #include <asm/mach-types.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
+@@ -333,12 +333,40 @@ static void __init bootmem_free_node(int
+ free_area_init_node(node, zone_size, start_pfn, zhole_size);
+ }
+
++#ifndef CONFIG_SPARSEMEM
++int pfn_valid(unsigned long pfn)
++{
++ struct meminfo *mi = &meminfo;
++ unsigned int mid, left = 0, right = mi->nr_banks;
++
++ while ((mid = (right - left) / 2) > 0) {
++ struct membank *bank = &mi->bank[mid];
++
++ if (pfn < bank_pfn_start(bank))
++ right = mid;
++ else if (pfn >= bank_pfn_end(bank))
++ left = mid + 1;
++ else
++ return 1;
++ }
++ return 0;
++}
++EXPORT_SYMBOL(pfn_valid);
++#endif
++
++static int __init meminfo_cmp(const void *_a, const void *_b) {
++ const struct membank *a = _a, *b = _b;
++ long cmp = bank_pfn_start(a) - bank_pfn_start(b);
++ return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; }
++
+ void __init bootmem_init(void)
+ {
+ struct meminfo *mi = &meminfo;
+ unsigned long memend_pfn = 0;
+ int node, initrd_node;
+
++ sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL);
++
+ /*
+ * Locate which node contains the ramdisk image, if any.
+ */
+diff -purN git2/include/linux/mmzone.h git/include/linux/mmzone.h
+--- git2/include/linux/mmzone.h 2009-06-08 06:42:40.000000000 +0530
++++ git/include/linux/mmzone.h 2009-08-17 11:57:17.000000000 +0530
+@@ -1095,6 +1095,32 @@ unsigned long __init node_memmap_size_by
+ #define pfn_valid_within(pfn) (1)
+ #endif
+
++#ifdef CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
++/*
++ * pfn_valid() is meant to be able to tell if a given PFN has valid memmap
++ * associated with it or not. In FLATMEM, it is expected that holes always
++ * have valid memmap as long as there is valid PFNs either side of the hole.
++ * In SPARSEMEM, it is assumed that a valid section has a memmap for the
++ * entire section.
++ *
++ * However, an ARM, and maybe other embedded architectures in the future
++ * free memmap backing holes to save memory on the assumption the memmap is
++ * never used. The page_zone linkages are then broken even though pfn_valid()
++ * returns true. A walker of the full memmap must then do this additional
++ * check to ensure the memmap they are looking at is sane by making sure
++ * the zone and PFN linkages are still valid. This is expensive, but walkers
++ * of the full memmap are extremely rare.
++ */
++int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone);
++#else
++static inline int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone)
++{
++ return 1;
++}
++#endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
++
+ #endif /* !__GENERATING_BOUNDS.H */
+ #endif /* !__ASSEMBLY__ */
+ #endif /* _LINUX_MMZONE_H */
+diff -purN git2/mm/mmzone.c git/mm/mmzone.c
+--- git2/mm/mmzone.c 2009-06-08 06:42:41.000000000 +0530
++++ git/mm/mmzone.c 2009-08-17 11:57:17.000000000 +0530
+@@ -6,6 +6,7 @@
+
+
+ #include <linux/stddef.h>
++#include <linux/mm.h>
+ #include <linux/mmzone.h>
+ #include <linux/module.h>
+
+@@ -72,3 +73,17 @@ struct zoneref *next_zones_zonelist(stru
+ *zone = zonelist_zone(z);
+ return z;
+ }
++
++#ifdef CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
++int memmap_valid_within(unsigned long pfn,
++ struct page *page, struct zone *zone)
++{
++ if (page_to_pfn(page) != pfn)
++ return 0;
++
++ if (page_zone(page) != zone)
++ return 0;
++
++ return 1;
++}
++#endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
+diff -purN git2/mm/vmstat.c git/mm/vmstat.c
+--- git2/mm/vmstat.c 2009-06-08 06:42:41.000000000 +0530
++++ git/mm/vmstat.c 2009-08-17 11:57:17.000000000 +0530
+@@ -516,22 +516,11 @@ static void pagetypeinfo_showblockcount_
+ continue;
+
+ page = pfn_to_page(pfn);
+-#ifdef CONFIG_ARCH_FLATMEM_HAS_HOLES
+- /*
+- * Ordinarily, memory holes in flatmem still have a valid
+- * memmap for the PFN range. However, an architecture for
+- * embedded systems (e.g. ARM) can free up the memmap backing
+- * holes to save memory on the assumption the memmap is
+- * never used. The page_zone linkages are then broken even
+- * though pfn_valid() returns true. Skip the page if the
+- * linkages are broken. Even if this test passed, the impact
+- * is that the counters for the movable type are off but
+- * fragmentation monitoring is likely meaningless on small
+- * systems.
+- */
+- if (page_zone(page) != zone)
++
++ /* Watch for unexpected holes punched in the memmap */
++ if (!memmap_valid_within(pfn, page, zone))
+ continue;
+-#endif
++
+ mtype = get_pageblock_migratetype(page);
+
+ if (mtype < MIGRATE_TYPES)
diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig
new file mode 100644
index 0000000000..9cb8ab5bc9
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig
@@ -0,0 +1,2748 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Wed Sep 2 21:59:02 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=m
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+# CONFIG_OMAP_PM_NOOP is not set
+CONFIG_OMAP_PM_SRF=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_OVERO=y
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=6
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=m
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=m
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+CONFIG_ENC28J60=y
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_SMC911X=m
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_VIDEO_OMAP3=m
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_OMAP_SOC_OVERO=m
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=m
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/ehci.patch b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/ehci.patch
new file mode 100644
index 0000000000..5a8c84471b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/ehci.patch
@@ -0,0 +1,131 @@
+Index: git/arch/arm/mach-omap2/board-omap3beagle.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
++++ git/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -154,6 +154,7 @@ static int beagle_twl_gpio_setup(struct
+ * power switch and overcurrent detect
+ */
+
++#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+ gpio_request(gpio + 1, "EHCI_nOC");
+ gpio_direction_input(gpio + 1);
+
+@@ -163,7 +164,7 @@ static int beagle_twl_gpio_setup(struct
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+-
++#endif
+ return 0;
+ }
+
+Index: git/arch/arm/mach-omap2/usb-ehci.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/usb-ehci.c
++++ git/arch/arm/mach-omap2/usb-ehci.c
+@@ -147,9 +147,11 @@ static void setup_ehci_io_mux(void)
+
+ void __init usb_ehci_init(void)
+ {
++#if 0 /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+ /* Setup Pin IO MUX for EHCI */
+ if (cpu_is_omap34xx())
+ setup_ehci_io_mux();
++#endif
+
+ if (platform_device_register(&ehci_device) < 0) {
+ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+Index: git/drivers/usb/host/ehci-omap.c
+===================================================================
+--- git.orig/drivers/usb/host/ehci-omap.c
++++ git/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,25 @@
+ * to get the PHY state machine in working state
+ */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OMAP3_BEAGLE
++#define EXT_PHY_RESET_GPIO_PORT2 (147)
++#else
+ #define EXT_PHY_RESET_GPIO_PORT1 (57)
+ #define EXT_PHY_RESET_GPIO_PORT2 (61)
++#endif
+ #define EXT_PHY_RESET_DELAY (10)
+
++#define PHY_STP_PULLUP_ENABLE (0x10)
++#define PHY_STP_PULLUP_DISABLE (0x90)
++
+ /* ISSUE2:
+ * USBHOST supports External charge pump PHYs only
+ * Use the VBUS from Port1 to power VBUS of Port2 externally
+ * So use Port2 as the working ULPI port
+ */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+
+@@ -225,14 +234,43 @@ static int omap_start_ehc(struct platfor
+
+ #ifdef EXTERNAL_PHY_RESET
+ /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+ gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(EXT_PHY_RESET_DELAY);
+ #endif
+
++ /*
++ * The PHY register 0x7 - Interface Control register is
++ * configured to disable the integrated STP pull-up resistor
++ * used for interface protection.
++ *
++ * May not need to be here.
++ */
++ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (PHY_STP_PULLUP_DISABLE),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++ /* Force PHY to HS */
++ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (0x40),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+ /* Configure TLL for 60Mhz clk for ULPI */
+ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +345,9 @@ static int omap_start_ehc(struct platfor
+ * Hold the PHY in RESET for enough time till PHY is settled and ready
+ */
+ udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+
+@@ -393,7 +433,9 @@ static void omap_stop_ehc(struct platfor
+
+
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/logo_linux_clut224.ppm b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/logo_linux_clut224.ppm
new file mode 100644
index 0000000000..d29fc1c544
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/logo_linux_clut224.ppm
@@ -0,0 +1,73147 @@
+P3
+# CREATOR: GIMP PNM Filter Version 1.1
+387 63
+255
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+248
+138
+64
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+247
+143
+74
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+248
+138
+64
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+130
+53
+247
+130
+60
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+152
+92
+249
+146
+83
+250
+139
+73
+247
+130
+60
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+247
+150
+84
+246
+156
+93
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+123
+41
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+152
+92
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+60
+250
+139
+73
+247
+150
+84
+249
+159
+103
+247
+165
+111
+249
+174
+124
+248
+180
+134
+252
+185
+144
+240
+181
+138
+219
+170
+138
+219
+170
+138
+230
+173
+136
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+159
+103
+214
+151
+109
+121
+100
+85
+65
+67
+64
+74
+68
+68
+129
+102
+78
+214
+151
+109
+246
+156
+93
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+204
+141
+99
+102
+91
+75
+65
+67
+64
+81
+77
+76
+146
+111
+88
+238
+159
+107
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+248
+138
+64
+247
+150
+84
+245
+162
+103
+162
+125
+96
+81
+77
+76
+55
+66
+67
+99
+90
+79
+187
+140
+108
+249
+159
+103
+247
+150
+84
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+187
+140
+108
+102
+91
+75
+58
+69
+70
+76
+78
+76
+146
+111
+88
+238
+159
+107
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+159
+103
+251
+168
+115
+248
+180
+134
+239
+182
+144
+186
+157
+134
+124
+111
+99
+82
+69
+65
+65
+58
+56
+55
+48
+48
+65
+58
+56
+65
+58
+56
+65
+58
+56
+99
+90
+79
+158
+130
+108
+230
+173
+136
+250
+176
+132
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+214
+151
+109
+74
+68
+68
+56
+64
+60
+95
+87
+59
+88
+82
+59
+56
+64
+60
+81
+77
+76
+238
+159
+107
+249
+152
+92
+248
+138
+64
+247
+130
+53
+246
+116
+28
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+187
+140
+108
+51
+62
+63
+69
+69
+61
+95
+87
+59
+83
+78
+61
+48
+58
+59
+121
+100
+85
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+123
+41
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+247
+165
+111
+139
+115
+96
+48
+58
+59
+95
+78
+64
+118
+86
+65
+81
+73
+62
+48
+58
+59
+162
+125
+96
+249
+159
+103
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+187
+140
+108
+48
+58
+59
+76
+70
+64
+118
+86
+65
+95
+78
+64
+51
+62
+63
+121
+100
+85
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+152
+92
+247
+165
+111
+250
+176
+132
+251
+192
+154
+167
+142
+123
+65
+58
+56
+35
+31
+30
+71
+60
+43
+108
+87
+46
+129
+106
+52
+137
+110
+49
+156
+125
+62
+187
+166
+150
+129
+106
+52
+101
+83
+47
+59
+50
+39
+55
+48
+48
+139
+115
+96
+240
+181
+138
+249
+174
+124
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+247
+165
+111
+124
+111
+99
+56
+64
+60
+137
+110
+49
+171
+129
+45
+171
+129
+45
+129
+106
+52
+51
+62
+63
+162
+125
+96
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+245
+169
+119
+81
+77
+76
+69
+69
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+105
+93
+60
+48
+58
+59
+187
+140
+108
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+250
+139
+73
+249
+159
+103
+210
+156
+119
+51
+62
+63
+112
+85
+63
+234
+126
+45
+234
+126
+45
+225
+124
+48
+95
+78
+64
+63
+74
+74
+234
+168
+124
+246
+156
+93
+250
+139
+73
+247
+123
+41
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+245
+169
+119
+81
+77
+76
+81
+73
+62
+212
+120
+56
+234
+126
+45
+234
+126
+45
+135
+94
+64
+41
+58
+57
+187
+140
+108
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+249
+174
+124
+249
+189
+146
+236
+186
+153
+99
+90
+79
+47
+40
+38
+85
+71
+43
+145
+114
+49
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+160
+120
+43
+195
+167
+113
+216
+194
+154
+168
+127
+42
+168
+127
+42
+123
+102
+54
+59
+50
+39
+82
+69
+65
+230
+173
+136
+249
+174
+124
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+246
+156
+93
+245
+169
+119
+84
+85
+82
+83
+78
+61
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+101
+100
+92
+249
+174
+124
+246
+156
+93
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+210
+156
+119
+48
+58
+59
+105
+93
+60
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+62
+63
+61
+139
+115
+96
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+247
+165
+111
+158
+130
+108
+51
+62
+63
+188
+112
+56
+234
+125
+52
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+210
+156
+119
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+247
+165
+111
+210
+156
+119
+55
+66
+67
+146
+97
+64
+234
+126
+45
+224
+123
+55
+234
+125
+52
+199
+115
+54
+62
+63
+61
+139
+115
+96
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+250
+176
+132
+219
+170
+138
+150
+125
+114
+65
+58
+56
+24
+22
+23
+59
+50
+39
+152
+119
+47
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+158
+125
+46
+227
+196
+175
+192
+155
+91
+160
+120
+43
+171
+129
+45
+158
+125
+46
+85
+71
+43
+65
+58
+56
+219
+170
+138
+249
+174
+124
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+230
+173
+136
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+252
+185
+144
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+203
+161
+131
+43
+57
+62
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+133
+120
+107
+250
+176
+132
+246
+156
+93
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+154
+133
+118
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+186
+157
+134
+250
+176
+132
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+249
+174
+124
+209
+171
+139
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+133
+120
+107
+249
+174
+124
+246
+156
+93
+248
+138
+64
+247
+123
+41
+247
+111
+26
+246
+109
+10
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+158
+130
+108
+47
+40
+38
+59
+50
+39
+85
+71
+43
+85
+71
+43
+59
+50
+39
+35
+31
+30
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+192
+155
+91
+224
+207
+180
+158
+125
+46
+160
+120
+43
+168
+127
+42
+171
+129
+45
+71
+60
+43
+82
+69
+65
+239
+182
+144
+249
+174
+124
+249
+152
+92
+248
+138
+64
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+247
+165
+111
+239
+182
+144
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+250
+197
+158
+250
+176
+132
+249
+159
+103
+247
+143
+74
+247
+130
+60
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+248
+180
+134
+212
+173
+150
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+248
+180
+134
+249
+159
+103
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+249
+159
+103
+250
+176
+132
+167
+142
+123
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+249
+189
+146
+251
+168
+115
+249
+152
+92
+250
+139
+73
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+150
+84
+247
+165
+111
+252
+185
+144
+212
+173
+150
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+133
+120
+107
+248
+180
+134
+249
+159
+103
+250
+139
+73
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+103
+7
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+249
+159
+103
+250
+176
+132
+167
+142
+123
+24
+22
+23
+85
+71
+43
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+85
+71
+43
+35
+31
+30
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+216
+194
+154
+195
+167
+113
+152
+119
+47
+158
+125
+46
+168
+127
+42
+158
+125
+46
+59
+50
+39
+139
+115
+96
+252
+185
+144
+247
+165
+111
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+251
+168
+115
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+251
+209
+178
+249
+189
+146
+249
+174
+124
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+248
+138
+64
+247
+143
+74
+246
+156
+93
+249
+174
+124
+251
+192
+154
+207
+178
+158
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+159
+103
+252
+185
+144
+167
+142
+123
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+51
+62
+63
+187
+166
+150
+250
+200
+166
+248
+180
+134
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+249
+152
+92
+247
+165
+111
+248
+180
+134
+250
+197
+158
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+252
+185
+144
+249
+159
+103
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+247
+150
+84
+251
+168
+115
+230
+173
+136
+47
+40
+38
+59
+50
+39
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+171
+129
+45
+59
+50
+39
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+170
+137
+67
+239
+227
+208
+170
+137
+67
+160
+120
+43
+158
+125
+46
+171
+129
+45
+123
+102
+54
+47
+40
+38
+209
+171
+139
+248
+180
+134
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+249
+174
+124
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+253
+204
+176
+249
+189
+146
+249
+174
+124
+247
+165
+111
+246
+156
+93
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+246
+116
+28
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+249
+146
+83
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+174
+124
+252
+185
+144
+250
+200
+166
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+251
+192
+154
+249
+174
+124
+246
+156
+93
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+249
+146
+83
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+150
+84
+251
+168
+115
+249
+189
+146
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+253
+212
+188
+250
+197
+158
+248
+180
+134
+251
+168
+115
+249
+159
+103
+247
+150
+84
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+247
+150
+84
+249
+146
+83
+247
+143
+74
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+109
+10
+246
+109
+10
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+60
+248
+138
+64
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+250
+139
+73
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+248
+138
+64
+250
+139
+73
+250
+139
+73
+250
+139
+73
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+247
+150
+84
+249
+159
+103
+251
+168
+115
+248
+180
+134
+250
+197
+158
+253
+212
+188
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+111
+26
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+130
+60
+250
+139
+73
+247
+143
+74
+249
+146
+83
+247
+150
+84
+247
+150
+84
+249
+146
+83
+247
+143
+74
+250
+139
+73
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+118
+39
+247
+118
+39
+247
+118
+39
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+248
+138
+64
+248
+138
+64
+250
+139
+73
+250
+139
+73
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+143
+74
+247
+143
+74
+250
+139
+73
+250
+139
+73
+248
+138
+64
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+139
+115
+96
+35
+31
+30
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+35
+31
+30
+152
+119
+47
+168
+127
+42
+168
+127
+42
+160
+120
+43
+168
+127
+42
+171
+129
+45
+152
+119
+47
+216
+194
+154
+224
+207
+180
+160
+120
+43
+160
+120
+43
+137
+110
+49
+102
+91
+75
+35
+31
+30
+115
+102
+92
+250
+200
+166
+250
+176
+132
+249
+159
+103
+249
+146
+83
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+236
+186
+153
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+253
+204
+176
+250
+197
+158
+252
+185
+144
+249
+174
+124
+251
+168
+115
+249
+159
+103
+246
+156
+93
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+246
+116
+28
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+60
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+249
+146
+83
+247
+143
+74
+248
+138
+64
+247
+130
+60
+247
+130
+60
+247
+130
+60
+248
+138
+64
+250
+139
+73
+249
+146
+83
+249
+152
+92
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+247
+165
+111
+251
+168
+115
+250
+176
+132
+252
+185
+144
+250
+200
+166
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+250
+200
+166
+250
+176
+132
+247
+165
+111
+249
+152
+92
+247
+150
+84
+249
+146
+83
+247
+150
+84
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+246
+156
+93
+247
+150
+84
+247
+143
+74
+250
+139
+73
+247
+143
+74
+249
+146
+83
+249
+159
+103
+249
+174
+124
+251
+192
+154
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+187
+166
+150
+255
+215
+190
+253
+212
+188
+250
+200
+166
+249
+189
+146
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+246
+116
+28
+247
+111
+26
+246
+116
+28
+247
+118
+39
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+246
+156
+93
+246
+156
+93
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+152
+92
+249
+152
+92
+247
+150
+84
+249
+146
+83
+249
+146
+83
+249
+146
+83
+247
+150
+84
+249
+152
+92
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+250
+176
+132
+249
+189
+146
+250
+200
+166
+253
+212
+188
+255
+215
+190
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+249
+159
+103
+249
+152
+92
+249
+146
+83
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+60
+248
+138
+64
+247
+143
+74
+249
+146
+83
+249
+152
+92
+246
+156
+93
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+249
+159
+103
+246
+156
+93
+249
+152
+92
+247
+150
+84
+249
+146
+83
+247
+143
+74
+247
+143
+74
+247
+143
+74
+249
+146
+83
+247
+150
+84
+246
+156
+93
+249
+159
+103
+247
+165
+111
+247
+165
+111
+251
+168
+115
+251
+168
+115
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+249
+159
+103
+249
+159
+103
+246
+156
+93
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+103
+7
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+236
+186
+153
+47
+40
+38
+59
+50
+39
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+47
+40
+38
+108
+87
+46
+168
+127
+42
+111
+94
+57
+76
+70
+64
+59
+50
+39
+101
+83
+47
+160
+120
+43
+170
+137
+67
+253
+255
+252
+195
+167
+113
+145
+114
+49
+69
+69
+61
+120
+114
+108
+35
+31
+30
+47
+40
+38
+217
+187
+166
+250
+197
+158
+250
+176
+132
+249
+159
+103
+249
+146
+83
+248
+138
+64
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+250
+139
+73
+246
+156
+93
+250
+176
+132
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+245
+212
+186
+227
+196
+175
+212
+173
+150
+209
+171
+139
+219
+170
+138
+240
+181
+138
+250
+176
+132
+251
+168
+115
+249
+159
+103
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+53
+247
+130
+53
+248
+138
+64
+249
+146
+83
+246
+156
+93
+247
+165
+111
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+250
+176
+132
+249
+174
+124
+249
+159
+103
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+53
+248
+138
+64
+249
+146
+83
+246
+156
+93
+247
+165
+111
+249
+174
+124
+245
+179
+138
+230
+173
+136
+203
+161
+131
+203
+161
+131
+219
+170
+138
+239
+182
+144
+251
+192
+154
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+245
+169
+119
+234
+168
+124
+247
+165
+111
+249
+159
+103
+249
+152
+92
+247
+150
+84
+247
+150
+84
+247
+150
+84
+249
+152
+92
+249
+159
+103
+247
+165
+111
+249
+174
+124
+248
+180
+134
+230
+173
+136
+219
+170
+138
+203
+161
+131
+209
+171
+139
+239
+182
+144
+251
+192
+154
+249
+189
+146
+249
+189
+146
+252
+185
+144
+252
+185
+144
+249
+189
+146
+236
+186
+153
+250
+200
+166
+255
+215
+190
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+253
+204
+176
+252
+185
+144
+249
+174
+124
+247
+165
+111
+247
+165
+111
+247
+165
+111
+251
+168
+115
+249
+174
+124
+248
+180
+134
+230
+173
+136
+219
+170
+138
+203
+161
+131
+209
+171
+139
+230
+173
+136
+245
+179
+138
+250
+176
+132
+251
+168
+115
+249
+159
+103
+249
+159
+103
+246
+156
+93
+249
+159
+103
+251
+168
+115
+248
+180
+134
+250
+197
+158
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+187
+166
+150
+255
+215
+190
+255
+215
+190
+234
+204
+183
+207
+178
+158
+209
+171
+139
+209
+171
+139
+230
+173
+136
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+248
+138
+64
+247
+143
+74
+249
+152
+92
+247
+165
+111
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+152
+92
+247
+143
+74
+248
+138
+64
+247
+130
+53
+247
+123
+41
+247
+123
+41
+247
+123
+41
+247
+130
+53
+247
+130
+60
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+174
+124
+250
+176
+132
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+230
+173
+136
+251
+192
+154
+249
+189
+146
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+250
+176
+132
+248
+180
+134
+250
+176
+132
+250
+176
+132
+250
+176
+132
+248
+180
+134
+248
+180
+134
+230
+173
+136
+240
+181
+138
+252
+185
+144
+252
+185
+144
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+234
+168
+124
+249
+174
+124
+251
+168
+115
+247
+165
+111
+247
+165
+111
+247
+165
+111
+251
+168
+115
+249
+174
+124
+250
+176
+132
+248
+180
+134
+230
+173
+136
+219
+170
+138
+209
+171
+139
+207
+178
+158
+227
+196
+175
+253
+212
+188
+255
+215
+190
+217
+187
+166
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+246
+116
+28
+247
+111
+26
+246
+109
+10
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+247
+143
+74
+249
+152
+92
+249
+159
+103
+249
+174
+124
+248
+180
+134
+240
+181
+138
+219
+170
+138
+203
+161
+131
+203
+161
+131
+219
+170
+138
+240
+181
+138
+248
+180
+134
+249
+174
+124
+247
+165
+111
+249
+159
+103
+247
+150
+84
+249
+146
+83
+247
+143
+74
+247
+143
+74
+249
+146
+83
+249
+152
+92
+249
+159
+103
+247
+165
+111
+234
+168
+124
+234
+168
+124
+248
+180
+134
+252
+185
+144
+252
+185
+144
+252
+185
+144
+248
+180
+134
+250
+176
+132
+234
+168
+124
+249
+174
+124
+251
+168
+115
+247
+165
+111
+247
+165
+111
+249
+159
+103
+247
+165
+111
+251
+168
+115
+249
+174
+124
+250
+176
+132
+248
+180
+134
+230
+173
+136
+203
+161
+131
+203
+161
+131
+219
+170
+138
+239
+182
+144
+251
+192
+154
+249
+189
+146
+252
+185
+144
+252
+185
+144
+248
+180
+134
+234
+168
+124
+238
+159
+107
+247
+165
+111
+249
+152
+92
+247
+143
+74
+247
+130
+60
+247
+123
+41
+246
+116
+28
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+247
+143
+74
+247
+165
+111
+252
+185
+144
+154
+133
+118
+24
+22
+23
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+85
+71
+43
+101
+83
+47
+89
+84
+82
+152
+147
+147
+24
+22
+23
+24
+22
+23
+108
+87
+46
+168
+127
+42
+224
+207
+180
+253
+255
+252
+209
+171
+139
+101
+83
+47
+24
+22
+23
+35
+31
+30
+35
+31
+30
+167
+142
+123
+253
+212
+188
+250
+197
+158
+248
+180
+134
+247
+165
+111
+247
+150
+84
+250
+139
+73
+247
+130
+60
+247
+130
+60
+248
+138
+64
+249
+146
+83
+249
+159
+103
+250
+176
+132
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+217
+187
+166
+137
+127
+115
+91
+92
+89
+55
+66
+67
+48
+58
+59
+48
+58
+59
+55
+66
+67
+84
+85
+82
+133
+120
+107
+209
+171
+139
+248
+180
+134
+251
+168
+115
+249
+159
+103
+247
+150
+84
+247
+143
+74
+250
+139
+73
+250
+139
+73
+249
+146
+83
+249
+152
+92
+247
+165
+111
+249
+174
+124
+245
+179
+138
+178
+146
+122
+124
+111
+99
+76
+78
+76
+51
+62
+63
+48
+58
+59
+48
+58
+59
+58
+69
+70
+91
+92
+89
+144
+125
+110
+203
+161
+131
+248
+180
+134
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+248
+138
+64
+250
+139
+73
+249
+146
+83
+246
+156
+93
+247
+165
+111
+250
+176
+132
+230
+173
+136
+154
+133
+118
+101
+100
+92
+58
+69
+70
+48
+58
+59
+48
+58
+59
+51
+62
+63
+84
+85
+82
+137
+127
+115
+217
+187
+166
+253
+212
+188
+227
+196
+175
+144
+125
+110
+89
+84
+82
+81
+77
+76
+115
+102
+92
+210
+156
+119
+249
+174
+124
+251
+168
+115
+251
+168
+115
+251
+168
+115
+249
+174
+124
+250
+176
+132
+252
+185
+144
+195
+157
+134
+124
+111
+99
+76
+78
+76
+51
+62
+63
+48
+58
+59
+48
+58
+59
+70
+79
+77
+120
+114
+108
+187
+166
+150
+253
+212
+188
+253
+212
+188
+172
+150
+134
+101
+100
+92
+77
+85
+81
+101
+100
+92
+176
+156
+141
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+253
+212
+188
+250
+197
+158
+252
+185
+144
+248
+180
+134
+248
+180
+134
+252
+185
+144
+239
+182
+144
+167
+142
+123
+109
+106
+99
+70
+79
+77
+48
+58
+59
+48
+58
+59
+48
+58
+59
+58
+69
+70
+91
+92
+89
+150
+125
+114
+219
+170
+138
+248
+180
+134
+249
+174
+124
+249
+174
+124
+249
+174
+124
+250
+176
+132
+249
+189
+146
+253
+204
+176
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+176
+156
+141
+187
+166
+150
+109
+106
+99
+63
+74
+74
+43
+57
+62
+43
+57
+62
+43
+57
+62
+63
+74
+74
+109
+106
+99
+178
+146
+122
+245
+179
+138
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+248
+138
+64
+248
+138
+64
+247
+143
+74
+247
+150
+84
+249
+159
+103
+249
+174
+124
+252
+185
+144
+195
+157
+134
+124
+111
+99
+77
+85
+81
+51
+62
+63
+41
+58
+57
+43
+57
+62
+51
+62
+63
+77
+85
+81
+124
+111
+99
+195
+157
+134
+252
+185
+144
+249
+174
+124
+249
+159
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+247
+130
+60
+248
+138
+64
+250
+139
+73
+247
+150
+84
+249
+159
+103
+251
+168
+115
+248
+180
+134
+203
+161
+131
+124
+111
+99
+77
+85
+81
+48
+58
+59
+43
+57
+62
+43
+57
+62
+63
+74
+74
+109
+106
+99
+187
+166
+150
+253
+212
+188
+253
+212
+188
+187
+166
+150
+109
+106
+99
+77
+85
+81
+84
+85
+82
+150
+125
+114
+232
+190
+161
+253
+204
+176
+253
+204
+176
+172
+150
+134
+101
+100
+92
+77
+85
+81
+91
+92
+89
+137
+127
+115
+227
+196
+175
+253
+212
+188
+186
+157
+134
+109
+106
+99
+77
+85
+81
+84
+85
+82
+124
+111
+99
+219
+170
+138
+249
+189
+146
+249
+189
+146
+249
+189
+146
+251
+192
+154
+250
+197
+158
+186
+157
+134
+109
+106
+99
+70
+79
+77
+43
+57
+62
+43
+57
+62
+41
+58
+57
+63
+74
+74
+101
+100
+92
+176
+156
+141
+194
+173
+157
+55
+66
+67
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+249
+189
+146
+247
+165
+111
+247
+143
+74
+247
+130
+53
+247
+118
+39
+247
+111
+26
+246
+109
+10
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+249
+159
+103
+249
+174
+124
+252
+185
+144
+203
+161
+131
+133
+120
+107
+84
+85
+82
+55
+66
+67
+43
+57
+62
+41
+58
+57
+51
+62
+63
+77
+85
+81
+124
+111
+99
+178
+146
+122
+239
+182
+144
+250
+176
+132
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+210
+156
+119
+124
+111
+99
+77
+85
+81
+77
+85
+81
+109
+106
+99
+194
+173
+157
+253
+212
+188
+217
+187
+166
+133
+120
+107
+89
+84
+82
+76
+78
+76
+101
+100
+92
+178
+146
+122
+249
+189
+146
+252
+185
+144
+252
+185
+144
+252
+185
+144
+251
+192
+154
+236
+186
+153
+167
+142
+123
+101
+100
+92
+63
+74
+74
+41
+58
+57
+43
+57
+62
+51
+62
+63
+77
+85
+81
+137
+127
+115
+217
+187
+166
+253
+212
+188
+227
+196
+175
+144
+125
+110
+84
+85
+82
+76
+78
+76
+115
+102
+92
+204
+141
+99
+249
+159
+103
+247
+143
+74
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+250
+197
+158
+82
+69
+65
+47
+40
+38
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+101
+83
+47
+59
+50
+39
+101
+83
+47
+24
+22
+23
+35
+31
+30
+24
+22
+23
+24
+22
+23
+108
+87
+46
+168
+127
+42
+195
+167
+113
+253
+255
+252
+253
+255
+252
+239
+227
+208
+186
+157
+134
+162
+125
+96
+105
+93
+60
+47
+40
+38
+150
+125
+114
+217
+187
+166
+250
+200
+166
+252
+185
+144
+251
+168
+115
+246
+156
+93
+249
+146
+83
+247
+143
+74
+249
+146
+83
+249
+152
+92
+247
+165
+111
+252
+185
+144
+232
+190
+161
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+58
+69
+70
+56
+64
+60
+83
+78
+61
+105
+93
+60
+117
+98
+55
+117
+98
+55
+105
+93
+60
+83
+78
+61
+56
+64
+60
+55
+66
+67
+144
+125
+110
+239
+182
+144
+250
+176
+132
+247
+165
+111
+249
+159
+103
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+252
+185
+144
+195
+157
+134
+89
+84
+82
+48
+58
+59
+63
+69
+60
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+105
+93
+60
+83
+78
+61
+56
+64
+60
+51
+62
+63
+124
+111
+99
+219
+170
+138
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+249
+152
+92
+246
+156
+93
+247
+165
+111
+249
+174
+124
+252
+185
+144
+167
+142
+123
+70
+79
+77
+51
+62
+63
+75
+74
+61
+100
+89
+56
+117
+98
+55
+123
+102
+54
+105
+93
+60
+83
+78
+61
+51
+62
+63
+63
+74
+74
+172
+150
+134
+109
+106
+99
+51
+62
+63
+83
+78
+61
+95
+87
+59
+65
+67
+64
+65
+67
+64
+209
+171
+139
+249
+189
+146
+249
+189
+146
+249
+189
+146
+250
+197
+158
+212
+173
+150
+109
+106
+99
+48
+58
+59
+63
+69
+60
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+95
+87
+59
+62
+63
+61
+48
+58
+59
+137
+127
+115
+146
+135
+124
+48
+58
+59
+75
+74
+61
+95
+87
+59
+75
+74
+61
+48
+58
+59
+161
+144
+134
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+250
+200
+166
+172
+150
+134
+77
+85
+81
+48
+58
+59
+69
+69
+61
+95
+87
+59
+111
+94
+57
+123
+102
+54
+117
+98
+55
+100
+89
+56
+75
+74
+61
+56
+64
+60
+55
+66
+67
+133
+120
+107
+236
+186
+153
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+253
+212
+188
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+51
+62
+63
+63
+74
+74
+48
+58
+59
+76
+70
+64
+118
+86
+65
+146
+97
+64
+155
+100
+63
+146
+97
+64
+118
+86
+65
+76
+70
+64
+43
+57
+62
+91
+92
+89
+203
+161
+131
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+247
+150
+84
+249
+152
+92
+249
+159
+103
+251
+168
+115
+248
+180
+134
+209
+171
+139
+101
+100
+92
+43
+57
+62
+69
+69
+61
+106
+82
+65
+135
+94
+64
+155
+100
+63
+155
+100
+63
+135
+94
+64
+106
+82
+65
+65
+67
+64
+43
+57
+62
+101
+100
+92
+209
+171
+139
+248
+180
+134
+251
+168
+115
+249
+159
+103
+249
+152
+92
+247
+150
+84
+247
+150
+84
+246
+156
+93
+247
+165
+111
+250
+176
+132
+219
+170
+138
+124
+111
+99
+48
+58
+59
+62
+63
+61
+106
+82
+65
+139
+96
+61
+155
+100
+63
+146
+97
+64
+125
+90
+64
+76
+70
+64
+41
+58
+57
+120
+114
+108
+172
+150
+134
+51
+62
+63
+69
+69
+61
+112
+85
+63
+95
+78
+64
+51
+62
+63
+120
+114
+108
+245
+212
+186
+146
+135
+124
+43
+57
+62
+81
+73
+62
+118
+86
+65
+95
+78
+64
+56
+64
+60
+101
+100
+92
+133
+120
+107
+43
+57
+62
+76
+70
+64
+112
+85
+63
+106
+82
+65
+62
+63
+61
+77
+85
+81
+227
+196
+175
+253
+212
+188
+253
+212
+188
+217
+187
+166
+109
+106
+99
+41
+58
+57
+69
+69
+61
+112
+85
+63
+139
+96
+61
+155
+100
+63
+146
+97
+64
+118
+86
+65
+81
+73
+62
+48
+58
+59
+58
+69
+70
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+111
+26
+246
+116
+28
+247
+123
+41
+248
+138
+64
+249
+146
+83
+249
+159
+103
+250
+176
+132
+219
+170
+138
+124
+111
+99
+43
+57
+62
+62
+63
+61
+106
+82
+65
+135
+94
+64
+155
+100
+63
+155
+100
+63
+139
+96
+61
+106
+82
+65
+69
+69
+61
+43
+57
+62
+91
+92
+89
+195
+157
+134
+251
+192
+154
+252
+185
+144
+248
+180
+134
+248
+180
+134
+252
+185
+144
+203
+161
+131
+63
+74
+74
+62
+63
+61
+106
+82
+65
+112
+85
+63
+69
+69
+61
+55
+66
+67
+146
+135
+124
+63
+74
+74
+56
+64
+60
+95
+78
+64
+112
+85
+63
+76
+70
+64
+48
+58
+59
+172
+150
+134
+253
+204
+176
+251
+209
+178
+251
+209
+178
+187
+166
+150
+77
+85
+81
+48
+58
+59
+81
+73
+62
+125
+90
+64
+146
+97
+64
+155
+100
+63
+139
+96
+61
+95
+78
+64
+56
+64
+60
+58
+69
+70
+161
+144
+134
+109
+106
+99
+51
+62
+63
+95
+78
+64
+112
+85
+63
+65
+67
+64
+65
+67
+64
+204
+141
+99
+246
+156
+93
+250
+139
+73
+247
+130
+53
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+209
+171
+139
+24
+22
+23
+85
+71
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+47
+40
+38
+137
+110
+49
+101
+83
+47
+59
+50
+39
+59
+50
+39
+101
+83
+47
+158
+125
+46
+160
+120
+43
+192
+155
+91
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+152
+147
+147
+81
+77
+76
+55
+48
+48
+115
+102
+92
+212
+173
+150
+251
+192
+154
+249
+174
+124
+247
+165
+111
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+249
+189
+146
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+43
+57
+62
+95
+87
+59
+145
+114
+49
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+145
+114
+49
+95
+87
+59
+48
+58
+59
+109
+106
+99
+236
+186
+153
+252
+185
+144
+248
+180
+134
+250
+176
+132
+250
+176
+132
+252
+185
+144
+251
+192
+154
+150
+125
+114
+48
+58
+59
+69
+69
+61
+117
+98
+55
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+152
+119
+47
+100
+89
+56
+56
+64
+60
+63
+74
+74
+186
+157
+134
+249
+189
+146
+248
+180
+134
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+251
+192
+154
+133
+120
+107
+48
+58
+59
+75
+74
+61
+137
+110
+49
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+145
+114
+49
+75
+74
+61
+43
+57
+62
+51
+62
+63
+123
+102
+54
+171
+129
+45
+171
+129
+45
+145
+114
+49
+56
+64
+60
+133
+120
+107
+253
+212
+188
+251
+209
+178
+253
+212
+188
+194
+173
+157
+63
+74
+74
+56
+64
+60
+111
+94
+57
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+158
+125
+46
+105
+93
+60
+51
+62
+63
+43
+57
+62
+88
+82
+59
+168
+127
+42
+171
+129
+45
+168
+127
+42
+88
+82
+59
+63
+74
+74
+187
+166
+150
+55
+66
+67
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+133
+120
+107
+48
+58
+59
+75
+74
+61
+129
+106
+52
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+171
+129
+45
+168
+127
+42
+145
+114
+49
+95
+87
+59
+51
+62
+63
+77
+85
+81
+212
+173
+150
+253
+204
+176
+253
+204
+176
+251
+209
+178
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+41
+58
+57
+69
+69
+61
+155
+100
+63
+214
+121
+50
+234
+126
+45
+234
+126
+45
+234
+126
+45
+234
+126
+45
+234
+126
+45
+224
+123
+55
+155
+100
+63
+69
+69
+61
+51
+62
+63
+178
+146
+122
+249
+189
+146
+250
+176
+132
+251
+168
+115
+251
+168
+115
+249
+174
+124
+250
+176
+132
+249
+189
+146
+167
+142
+123
+55
+66
+67
+65
+67
+64
+146
+97
+64
+212
+120
+56
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+125
+52
+209
+117
+53
+146
+97
+64
+65
+67
+64
+55
+66
+67
+178
+146
+122
+249
+189
+146
+250
+176
+132
+251
+168
+115
+247
+165
+111
+251
+168
+115
+249
+174
+124
+252
+185
+144
+203
+161
+131
+63
+74
+74
+56
+64
+60
+125
+90
+64
+209
+117
+53
+234
+126
+45
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+126
+45
+214
+121
+50
+146
+97
+64
+56
+64
+60
+41
+58
+57
+81
+73
+62
+209
+117
+53
+234
+126
+45
+234
+126
+45
+125
+90
+64
+51
+62
+63
+176
+156
+141
+55
+66
+67
+106
+82
+65
+225
+124
+48
+234
+126
+45
+234
+126
+45
+146
+97
+64
+41
+58
+57
+43
+57
+62
+125
+90
+64
+214
+121
+50
+234
+126
+45
+234
+126
+45
+183
+110
+59
+56
+64
+60
+137
+127
+115
+255
+215
+190
+194
+173
+157
+63
+74
+74
+62
+63
+61
+146
+97
+64
+214
+121
+50
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+125
+52
+234
+126
+45
+225
+124
+48
+173
+106
+60
+81
+73
+62
+35
+56
+60
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+118
+39
+246
+116
+28
+246
+116
+28
+247
+123
+41
+247
+130
+60
+249
+146
+83
+247
+165
+111
+248
+180
+134
+186
+157
+134
+58
+69
+70
+56
+64
+60
+135
+94
+64
+199
+115
+54
+234
+125
+52
+234
+126
+45
+234
+125
+52
+234
+125
+52
+234
+126
+45
+234
+125
+52
+212
+120
+56
+155
+100
+63
+76
+70
+64
+51
+62
+63
+146
+135
+124
+251
+209
+178
+253
+204
+176
+250
+200
+166
+253
+204
+176
+101
+100
+92
+69
+69
+61
+194
+112
+58
+234
+126
+45
+234
+126
+45
+199
+115
+54
+65
+67
+64
+35
+56
+60
+81
+73
+62
+194
+112
+58
+234
+125
+52
+234
+126
+45
+214
+121
+50
+95
+78
+64
+63
+74
+74
+238
+205
+179
+255
+215
+190
+161
+144
+134
+43
+57
+62
+81
+73
+62
+173
+106
+60
+225
+124
+48
+234
+126
+45
+234
+126
+45
+234
+125
+52
+234
+126
+45
+234
+126
+45
+194
+112
+58
+95
+78
+64
+41
+58
+57
+48
+58
+59
+155
+100
+63
+234
+126
+45
+234
+126
+45
+199
+115
+54
+69
+69
+61
+99
+90
+79
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+249
+174
+124
+251
+192
+154
+124
+111
+99
+35
+31
+30
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+47
+40
+38
+108
+87
+46
+175
+132
+40
+161
+127
+40
+168
+127
+42
+171
+129
+45
+158
+125
+46
+152
+119
+47
+203
+161
+131
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+89
+84
+82
+47
+40
+38
+139
+115
+96
+236
+186
+153
+252
+185
+144
+250
+176
+132
+249
+174
+124
+250
+176
+132
+252
+185
+144
+250
+197
+158
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+111
+94
+57
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+111
+94
+57
+48
+58
+59
+109
+106
+99
+253
+204
+176
+250
+200
+166
+250
+200
+166
+250
+200
+166
+253
+204
+176
+137
+127
+115
+43
+57
+62
+88
+82
+59
+158
+125
+46
+171
+129
+45
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+145
+114
+49
+69
+69
+61
+51
+62
+63
+187
+166
+150
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+253
+204
+176
+133
+120
+107
+48
+58
+59
+95
+87
+59
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+158
+125
+46
+75
+74
+61
+62
+63
+61
+168
+127
+42
+161
+127
+40
+158
+125
+46
+171
+129
+45
+83
+78
+61
+91
+92
+89
+255
+215
+190
+255
+215
+190
+207
+178
+158
+58
+69
+70
+63
+69
+60
+145
+114
+49
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+105
+93
+60
+43
+57
+62
+137
+110
+49
+171
+129
+45
+158
+125
+46
+171
+129
+45
+137
+110
+49
+51
+62
+63
+146
+135
+124
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+65
+67
+64
+137
+127
+115
+255
+215
+190
+255
+215
+190
+245
+212
+186
+120
+114
+108
+48
+58
+59
+100
+89
+56
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+129
+106
+52
+61
+67
+58
+63
+74
+74
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+95
+78
+64
+209
+117
+53
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+209
+117
+53
+89
+75
+66
+51
+62
+63
+187
+166
+150
+250
+197
+158
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+161
+144
+134
+41
+58
+57
+95
+78
+64
+199
+115
+54
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+199
+115
+54
+89
+75
+66
+41
+58
+57
+167
+142
+123
+250
+200
+166
+251
+192
+154
+252
+185
+144
+249
+189
+146
+250
+197
+158
+212
+173
+150
+63
+74
+74
+69
+69
+61
+183
+110
+59
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+163
+104
+61
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+234
+125
+52
+188
+112
+56
+51
+62
+63
+109
+106
+99
+51
+62
+63
+188
+112
+56
+234
+126
+45
+224
+123
+55
+234
+125
+52
+188
+112
+56
+43
+57
+62
+112
+85
+63
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+95
+78
+64
+109
+106
+99
+217
+187
+166
+58
+69
+70
+69
+69
+61
+188
+112
+56
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+214
+121
+50
+95
+78
+64
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+53
+247
+123
+41
+247
+118
+39
+247
+123
+41
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+186
+157
+134
+51
+62
+63
+81
+73
+62
+188
+112
+56
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+212
+120
+56
+106
+82
+65
+41
+58
+57
+146
+135
+124
+255
+215
+190
+255
+215
+190
+234
+204
+183
+63
+74
+74
+125
+90
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+234
+125
+52
+89
+75
+66
+62
+63
+61
+199
+115
+54
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+217
+187
+166
+172
+150
+134
+41
+58
+57
+106
+82
+65
+214
+121
+50
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+69
+69
+61
+227
+126
+50
+227
+126
+50
+224
+123
+55
+238
+123
+45
+125
+90
+64
+55
+66
+67
+250
+176
+132
+246
+156
+93
+250
+139
+73
+247
+123
+41
+247
+111
+26
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+248
+180
+134
+232
+190
+161
+47
+40
+38
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+71
+60
+43
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+170
+137
+67
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+74
+68
+68
+89
+75
+66
+212
+173
+150
+250
+197
+158
+251
+192
+154
+249
+189
+146
+251
+192
+154
+253
+204
+176
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+111
+94
+57
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+48
+58
+59
+95
+87
+59
+168
+127
+42
+168
+127
+42
+158
+125
+46
+161
+127
+40
+171
+129
+45
+158
+125
+46
+152
+119
+47
+152
+119
+47
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+69
+69
+61
+58
+69
+70
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+43
+57
+62
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+158
+125
+46
+168
+127
+42
+137
+110
+49
+83
+78
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+238
+205
+179
+84
+85
+82
+62
+63
+61
+145
+114
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+161
+127
+40
+158
+125
+46
+88
+82
+59
+152
+119
+47
+161
+127
+40
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+63
+69
+60
+137
+127
+115
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+105
+93
+60
+171
+129
+45
+161
+127
+40
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+152
+119
+47
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+145
+114
+49
+62
+63
+61
+70
+79
+77
+227
+196
+175
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+234
+126
+45
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+76
+70
+64
+70
+79
+77
+234
+204
+183
+253
+212
+188
+251
+209
+178
+253
+212
+188
+187
+166
+150
+43
+57
+62
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+95
+78
+64
+48
+58
+59
+194
+173
+157
+253
+212
+188
+251
+209
+178
+251
+209
+178
+245
+212
+186
+91
+92
+89
+62
+63
+61
+188
+112
+56
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+126
+45
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+212
+120
+56
+183
+110
+59
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+95
+78
+64
+84
+85
+82
+91
+92
+89
+62
+63
+61
+188
+112
+56
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+123
+41
+247
+123
+41
+247
+130
+53
+248
+138
+64
+249
+152
+92
+249
+174
+124
+209
+171
+139
+58
+69
+70
+81
+73
+62
+209
+117
+53
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+112
+85
+63
+41
+58
+57
+172
+150
+134
+255
+215
+190
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+194
+112
+58
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+238
+128
+40
+163
+104
+61
+55
+66
+67
+161
+144
+134
+58
+69
+70
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+126
+45
+234
+125
+52
+227
+126
+50
+234
+125
+52
+173
+106
+60
+118
+86
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+146
+97
+64
+51
+62
+63
+252
+185
+144
+249
+159
+103
+247
+143
+74
+247
+130
+53
+246
+116
+28
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+251
+168
+115
+251
+192
+154
+154
+133
+118
+24
+22
+23
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+108
+87
+46
+47
+40
+38
+158
+125
+46
+158
+125
+46
+158
+125
+46
+160
+120
+43
+156
+125
+62
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+152
+147
+147
+35
+31
+30
+55
+48
+48
+154
+133
+118
+217
+187
+166
+253
+204
+176
+253
+204
+176
+253
+212
+188
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+168
+127
+42
+158
+125
+46
+123
+102
+54
+105
+93
+60
+111
+94
+57
+129
+106
+52
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+83
+78
+61
+58
+69
+70
+227
+196
+175
+255
+215
+190
+217
+187
+166
+58
+69
+70
+75
+74
+61
+168
+127
+42
+161
+127
+40
+158
+125
+46
+168
+127
+42
+152
+119
+47
+105
+93
+60
+69
+69
+61
+62
+63
+61
+62
+63
+61
+75
+74
+61
+117
+98
+55
+161
+127
+40
+161
+127
+40
+158
+125
+46
+171
+129
+45
+145
+114
+49
+56
+64
+60
+97
+98
+96
+245
+212
+186
+255
+215
+190
+227
+196
+175
+63
+74
+74
+75
+74
+61
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+129
+106
+52
+111
+94
+57
+105
+93
+60
+129
+106
+52
+158
+125
+46
+168
+127
+42
+161
+127
+40
+152
+119
+47
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+84
+85
+82
+255
+215
+190
+161
+144
+134
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+117
+98
+55
+105
+93
+60
+117
+98
+55
+145
+114
+49
+171
+129
+45
+168
+127
+42
+152
+119
+47
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+194
+173
+157
+48
+58
+59
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+95
+87
+59
+69
+69
+61
+62
+63
+61
+62
+63
+61
+83
+78
+61
+123
+102
+54
+168
+127
+42
+161
+127
+40
+158
+125
+46
+171
+129
+45
+129
+106
+52
+51
+62
+63
+120
+114
+108
+255
+215
+190
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+188
+112
+56
+146
+97
+64
+135
+94
+64
+146
+97
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+173
+106
+60
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+76
+70
+64
+214
+121
+50
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+163
+104
+61
+135
+94
+64
+135
+94
+64
+163
+104
+61
+224
+123
+55
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+212
+120
+56
+76
+70
+64
+77
+85
+81
+238
+205
+179
+255
+215
+190
+255
+215
+190
+161
+144
+134
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+199
+115
+54
+155
+100
+63
+135
+94
+64
+146
+97
+64
+188
+112
+56
+227
+126
+50
+227
+126
+50
+214
+121
+50
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+199
+115
+54
+125
+90
+64
+51
+62
+63
+55
+66
+67
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+209
+117
+53
+155
+100
+63
+135
+94
+64
+139
+96
+61
+183
+110
+59
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+247
+130
+60
+247
+130
+53
+247
+130
+53
+247
+130
+60
+249
+146
+83
+247
+165
+111
+252
+185
+144
+101
+100
+92
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+173
+106
+60
+135
+94
+64
+135
+94
+64
+163
+104
+61
+214
+121
+50
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+81
+73
+62
+58
+69
+70
+227
+196
+175
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+125
+52
+212
+120
+56
+155
+100
+63
+69
+69
+61
+76
+78
+76
+84
+85
+82
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+183
+110
+59
+139
+96
+61
+135
+94
+64
+155
+100
+63
+209
+117
+53
+234
+125
+52
+224
+123
+55
+212
+120
+56
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+251
+192
+154
+251
+168
+115
+249
+146
+83
+247
+130
+53
+247
+118
+39
+246
+109
+10
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+250
+176
+132
+232
+190
+161
+65
+58
+56
+59
+50
+39
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+47
+40
+38
+129
+106
+52
+168
+127
+42
+160
+120
+43
+158
+125
+46
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+62
+63
+61
+35
+31
+30
+91
+92
+89
+164
+158
+157
+186
+181
+179
+82
+69
+65
+176
+156
+141
+255
+215
+190
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+65
+67
+64
+48
+58
+59
+55
+66
+67
+55
+66
+67
+48
+58
+59
+83
+78
+61
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+146
+135
+124
+255
+215
+190
+120
+114
+108
+56
+64
+60
+145
+114
+49
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+69
+69
+61
+43
+57
+62
+109
+106
+99
+146
+135
+124
+137
+127
+115
+91
+92
+89
+43
+57
+62
+88
+82
+59
+158
+125
+46
+161
+127
+40
+158
+125
+46
+171
+129
+45
+117
+98
+55
+48
+58
+59
+172
+150
+134
+255
+215
+190
+146
+135
+124
+51
+62
+63
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+75
+74
+61
+48
+58
+59
+55
+66
+67
+55
+66
+67
+48
+58
+59
+69
+69
+61
+137
+110
+49
+168
+127
+42
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+234
+204
+183
+70
+79
+77
+83
+78
+61
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+111
+94
+57
+56
+64
+60
+43
+57
+62
+58
+69
+70
+48
+58
+59
+56
+64
+60
+100
+89
+56
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+137
+127
+115
+255
+215
+190
+97
+98
+96
+62
+63
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+137
+110
+49
+62
+63
+61
+51
+62
+63
+120
+114
+108
+146
+135
+124
+137
+127
+115
+84
+85
+82
+43
+57
+62
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+100
+89
+56
+43
+57
+62
+194
+173
+157
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+118
+86
+65
+51
+62
+63
+43
+57
+62
+58
+69
+70
+41
+58
+57
+56
+64
+60
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+106
+82
+65
+63
+74
+74
+234
+204
+183
+255
+215
+190
+161
+144
+134
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+183
+110
+59
+76
+70
+64
+43
+57
+62
+55
+66
+67
+55
+66
+67
+48
+58
+59
+81
+73
+62
+183
+110
+59
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+48
+58
+59
+161
+144
+134
+255
+215
+190
+234
+204
+183
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+62
+63
+61
+43
+57
+62
+58
+69
+70
+43
+57
+62
+51
+62
+63
+125
+90
+64
+225
+124
+48
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+227
+126
+50
+173
+106
+60
+95
+78
+64
+56
+64
+60
+51
+62
+63
+120
+114
+108
+70
+79
+77
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+163
+104
+61
+65
+67
+64
+41
+58
+57
+55
+66
+67
+51
+62
+63
+48
+58
+59
+106
+82
+65
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+249
+146
+83
+248
+138
+64
+247
+130
+53
+247
+130
+60
+250
+139
+73
+246
+156
+93
+250
+176
+132
+186
+157
+134
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+199
+115
+54
+89
+75
+66
+48
+58
+59
+51
+62
+63
+55
+66
+67
+43
+57
+62
+76
+70
+64
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+137
+127
+115
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+199
+115
+54
+125
+90
+64
+69
+69
+61
+41
+58
+57
+97
+98
+96
+146
+135
+124
+51
+62
+63
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+106
+82
+65
+48
+58
+59
+51
+62
+63
+55
+66
+67
+41
+58
+57
+65
+67
+64
+163
+104
+61
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+197
+158
+251
+168
+115
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+252
+185
+144
+154
+133
+118
+24
+22
+23
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+71
+60
+43
+85
+71
+43
+171
+129
+45
+160
+120
+43
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+65
+58
+56
+62
+63
+61
+219
+212
+208
+253
+255
+252
+237
+233
+225
+120
+114
+108
+35
+31
+30
+55
+48
+48
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+84
+85
+82
+187
+166
+150
+227
+196
+175
+227
+196
+175
+161
+144
+134
+51
+62
+63
+69
+69
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+91
+92
+89
+217
+187
+166
+55
+66
+67
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+58
+69
+70
+187
+166
+150
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+161
+144
+134
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+84
+85
+82
+234
+204
+183
+76
+78
+76
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+62
+63
+61
+63
+74
+74
+176
+156
+141
+227
+196
+175
+227
+196
+175
+176
+156
+141
+70
+79
+77
+62
+63
+61
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+172
+150
+134
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+43
+57
+62
+120
+114
+108
+207
+178
+158
+227
+196
+175
+217
+187
+166
+120
+114
+108
+41
+58
+57
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+146
+135
+124
+207
+178
+158
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+62
+63
+61
+70
+79
+77
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+238
+205
+179
+137
+127
+115
+43
+57
+62
+117
+98
+55
+168
+127
+42
+158
+125
+46
+168
+127
+42
+152
+119
+47
+62
+63
+61
+109
+106
+99
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+41
+58
+57
+137
+127
+115
+217
+187
+166
+227
+196
+175
+207
+178
+158
+109
+106
+99
+41
+58
+57
+146
+97
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+176
+156
+141
+245
+212
+186
+70
+79
+77
+95
+78
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+188
+112
+56
+56
+64
+60
+70
+79
+77
+176
+156
+141
+227
+196
+175
+227
+196
+175
+176
+156
+141
+63
+74
+74
+62
+63
+61
+194
+112
+58
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+77
+85
+81
+245
+212
+186
+172
+150
+134
+48
+58
+59
+173
+106
+60
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+135
+94
+64
+35
+56
+60
+120
+114
+108
+207
+178
+158
+227
+196
+175
+217
+187
+166
+133
+120
+107
+35
+56
+60
+118
+86
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+95
+78
+64
+48
+58
+59
+70
+79
+77
+146
+135
+124
+217
+187
+166
+207
+178
+158
+51
+62
+63
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+91
+92
+89
+194
+173
+157
+227
+196
+175
+217
+187
+166
+146
+135
+124
+43
+57
+62
+89
+75
+66
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+247
+165
+111
+247
+150
+84
+248
+138
+64
+247
+130
+60
+248
+138
+64
+249
+146
+83
+247
+165
+111
+239
+182
+144
+91
+92
+89
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+76
+70
+64
+55
+66
+67
+172
+150
+134
+227
+196
+175
+227
+196
+175
+187
+166
+150
+77
+85
+81
+51
+62
+63
+173
+106
+60
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+118
+86
+65
+58
+69
+70
+217
+187
+166
+70
+79
+77
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+125
+90
+64
+56
+64
+60
+55
+66
+67
+120
+114
+108
+187
+166
+150
+245
+212
+186
+120
+114
+108
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+225
+124
+48
+95
+78
+64
+43
+57
+62
+146
+135
+124
+217
+187
+166
+227
+196
+175
+194
+173
+157
+91
+92
+89
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+197
+158
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+249
+146
+83
+251
+168
+115
+239
+182
+144
+65
+58
+56
+59
+50
+39
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+108
+87
+46
+47
+40
+38
+152
+119
+47
+170
+137
+67
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+174
+168
+167
+24
+22
+23
+109
+106
+99
+152
+147
+147
+97
+98
+96
+47
+40
+38
+24
+22
+23
+35
+31
+30
+35
+31
+30
+176
+156
+141
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+76
+78
+76
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+187
+166
+150
+51
+62
+63
+95
+87
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+55
+66
+67
+109
+106
+99
+48
+58
+59
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+117
+98
+55
+48
+58
+59
+187
+166
+150
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+171
+129
+45
+117
+98
+55
+55
+66
+67
+137
+127
+115
+55
+66
+67
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+58
+69
+70
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+91
+92
+89
+109
+106
+99
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+120
+114
+108
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+146
+135
+124
+146
+135
+124
+62
+63
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+100
+89
+56
+51
+62
+63
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+109
+106
+99
+63
+69
+60
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+100
+89
+56
+51
+62
+63
+227
+196
+175
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+41
+58
+57
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+109
+106
+99
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+76
+70
+64
+109
+106
+99
+194
+173
+157
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+225
+124
+48
+89
+75
+66
+63
+74
+74
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+58
+69
+70
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+43
+57
+62
+207
+178
+158
+109
+106
+99
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+120
+114
+108
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+188
+112
+56
+62
+63
+61
+58
+69
+70
+161
+144
+134
+234
+204
+183
+255
+215
+190
+255
+215
+190
+137
+127
+115
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+69
+69
+61
+77
+85
+81
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+176
+156
+141
+35
+56
+60
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+247
+150
+84
+250
+139
+73
+248
+138
+64
+250
+139
+73
+249
+152
+92
+249
+174
+124
+209
+171
+139
+43
+57
+62
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+112
+85
+63
+51
+62
+63
+194
+173
+157
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+227
+196
+175
+70
+79
+77
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+146
+135
+124
+77
+85
+81
+135
+94
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+95
+78
+64
+35
+56
+60
+120
+114
+108
+217
+187
+166
+255
+215
+190
+255
+215
+190
+227
+196
+175
+58
+69
+70
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+41
+58
+57
+172
+150
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+51
+62
+63
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+178
+146
+122
+24
+22
+23
+101
+83
+47
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+47
+40
+38
+123
+102
+54
+209
+171
+139
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+164
+158
+157
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+47
+40
+38
+194
+173
+157
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+176
+156
+141
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+120
+114
+108
+56
+64
+60
+152
+119
+47
+161
+127
+40
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+48
+58
+59
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+63
+74
+74
+194
+173
+157
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+172
+150
+134
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+51
+62
+63
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+70
+79
+77
+63
+74
+74
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+55
+66
+67
+227
+196
+175
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+234
+204
+183
+70
+79
+77
+88
+82
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+97
+98
+96
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+84
+85
+82
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+207
+178
+158
+217
+187
+166
+146
+135
+124
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+187
+166
+150
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+70
+79
+77
+245
+212
+186
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+217
+187
+166
+43
+57
+62
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+106
+82
+65
+77
+85
+81
+133
+120
+107
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+48
+58
+59
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+77
+85
+81
+118
+86
+65
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+55
+66
+67
+227
+196
+175
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+234
+204
+183
+63
+74
+74
+106
+82
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+224
+123
+55
+89
+75
+66
+63
+74
+74
+217
+187
+166
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+91
+92
+89
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+146
+97
+64
+43
+57
+62
+187
+166
+150
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+101
+100
+92
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+247
+150
+84
+250
+139
+73
+250
+139
+73
+247
+143
+74
+249
+159
+103
+250
+176
+132
+154
+133
+118
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+176
+156
+141
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+91
+92
+89
+70
+79
+77
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+146
+97
+64
+35
+56
+60
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+97
+98
+96
+255
+215
+190
+255
+215
+190
+255
+215
+190
+253
+212
+188
+255
+215
+190
+255
+215
+190
+187
+166
+150
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+159
+103
+248
+180
+134
+124
+111
+99
+35
+31
+30
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+59
+50
+39
+85
+71
+43
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+207
+202
+200
+47
+40
+38
+24
+22
+23
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+65
+58
+56
+238
+205
+179
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+100
+89
+56
+63
+74
+74
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+194
+173
+157
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+43
+57
+62
+95
+87
+59
+168
+127
+42
+158
+125
+46
+161
+127
+40
+158
+125
+46
+63
+69
+60
+43
+57
+62
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+43
+57
+62
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+43
+57
+62
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+51
+62
+63
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+217
+187
+166
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+109
+106
+99
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+120
+114
+108
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+120
+114
+108
+70
+79
+77
+105
+93
+60
+171
+129
+45
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+51
+62
+63
+43
+57
+62
+111
+94
+57
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+62
+63
+61
+146
+135
+124
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+212
+188
+250
+200
+166
+250
+200
+166
+253
+204
+176
+253
+212
+188
+253
+212
+188
+97
+98
+96
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+63
+74
+74
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+135
+94
+64
+55
+66
+67
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+217
+187
+166
+51
+62
+63
+139
+96
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+58
+69
+70
+51
+62
+63
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+224
+123
+55
+81
+73
+62
+109
+106
+99
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+120
+114
+108
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+70
+79
+77
+118
+86
+65
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+77
+85
+81
+245
+212
+186
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+176
+156
+141
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+251
+168
+115
+249
+152
+92
+247
+143
+74
+247
+143
+74
+247
+150
+84
+249
+159
+103
+248
+180
+134
+120
+114
+108
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+43
+57
+62
+194
+173
+157
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+234
+204
+183
+63
+74
+74
+112
+85
+63
+234
+125
+52
+227
+126
+50
+224
+123
+55
+234
+125
+52
+106
+82
+65
+58
+69
+70
+55
+66
+67
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+77
+85
+81
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+172
+150
+134
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+245
+212
+186
+63
+74
+74
+112
+85
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+252
+185
+144
+82
+69
+65
+47
+40
+38
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+85
+71
+43
+59
+50
+39
+216
+194
+154
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+164
+158
+157
+47
+40
+38
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+65
+67
+64
+65
+58
+56
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+227
+196
+175
+58
+69
+70
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+41
+58
+57
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+137
+110
+49
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+41
+58
+57
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+70
+79
+77
+245
+212
+186
+253
+212
+188
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+238
+205
+179
+70
+79
+77
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+152
+119
+47
+56
+64
+60
+146
+135
+124
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+253
+204
+176
+255
+215
+190
+172
+150
+134
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+97
+98
+96
+55
+66
+67
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+123
+102
+54
+117
+98
+55
+145
+114
+49
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+137
+127
+115
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+187
+166
+150
+255
+215
+190
+253
+204
+176
+251
+192
+154
+251
+192
+154
+250
+197
+158
+253
+204
+176
+255
+215
+190
+137
+127
+115
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+43
+57
+62
+41
+58
+57
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+77
+85
+81
+245
+212
+186
+251
+209
+178
+250
+197
+158
+249
+189
+146
+251
+192
+154
+250
+197
+158
+251
+209
+178
+238
+205
+179
+77
+85
+81
+112
+85
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+106
+82
+65
+41
+58
+57
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+253
+204
+176
+255
+215
+190
+176
+156
+141
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+234
+125
+52
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+176
+156
+141
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+227
+196
+175
+58
+69
+70
+139
+96
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+255
+215
+190
+207
+178
+158
+48
+58
+59
+163
+104
+61
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+192
+154
+249
+174
+124
+246
+156
+93
+247
+150
+84
+249
+146
+83
+249
+152
+92
+251
+168
+115
+249
+189
+146
+97
+98
+96
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+58
+69
+70
+227
+196
+175
+253
+212
+188
+250
+200
+166
+251
+192
+154
+249
+189
+146
+250
+197
+158
+251
+209
+178
+255
+215
+190
+97
+98
+96
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+43
+57
+62
+43
+57
+62
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+69
+69
+61
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+126
+45
+155
+100
+63
+43
+57
+62
+207
+178
+158
+255
+215
+190
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+197
+158
+251
+209
+178
+255
+215
+190
+109
+106
+99
+89
+75
+66
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+143
+74
+249
+159
+103
+252
+185
+144
+55
+48
+48
+59
+50
+39
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+101
+83
+47
+59
+50
+39
+209
+171
+139
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+137
+127
+115
+101
+100
+92
+120
+114
+108
+186
+181
+179
+152
+147
+147
+55
+48
+48
+227
+196
+175
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+234
+204
+183
+70
+79
+77
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+41
+58
+57
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+75
+74
+61
+41
+58
+57
+88
+82
+59
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+77
+85
+81
+245
+212
+186
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+245
+212
+186
+84
+85
+82
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+161
+144
+134
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+187
+166
+150
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+65
+67
+64
+91
+92
+89
+55
+66
+67
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+63
+69
+60
+137
+127
+115
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+173
+106
+60
+48
+58
+59
+187
+166
+150
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+41
+58
+57
+118
+86
+65
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+95
+78
+64
+91
+92
+89
+255
+215
+190
+253
+204
+176
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+253
+204
+176
+245
+212
+186
+91
+92
+89
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+41
+58
+57
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+227
+126
+50
+199
+115
+54
+56
+64
+60
+161
+144
+134
+255
+215
+190
+250
+200
+166
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+187
+166
+150
+48
+58
+59
+183
+110
+59
+234
+125
+52
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+217
+187
+166
+55
+66
+67
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+69
+69
+61
+137
+127
+115
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+249
+189
+146
+250
+200
+166
+253
+212
+188
+217
+187
+166
+51
+62
+63
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+250
+197
+158
+249
+174
+124
+249
+159
+103
+249
+152
+92
+249
+152
+92
+249
+159
+103
+249
+174
+124
+250
+197
+158
+91
+92
+89
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+125
+90
+64
+70
+79
+77
+234
+204
+183
+251
+209
+178
+250
+197
+158
+249
+189
+146
+252
+185
+144
+251
+192
+154
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+126
+45
+135
+94
+64
+41
+58
+57
+41
+58
+57
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+212
+188
+253
+212
+188
+251
+209
+178
+251
+209
+178
+255
+215
+190
+137
+127
+115
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+146
+97
+64
+51
+62
+63
+227
+196
+175
+253
+212
+188
+250
+197
+158
+249
+189
+146
+249
+189
+146
+251
+192
+154
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+252
+185
+144
+55
+48
+48
+59
+50
+39
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+154
+125
+71
+170
+137
+67
+108
+87
+46
+59
+50
+39
+192
+155
+91
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+186
+181
+179
+47
+40
+38
+65
+58
+56
+245
+212
+186
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+253
+212
+188
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+234
+204
+183
+63
+74
+74
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+75
+74
+61
+41
+58
+57
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+111
+94
+57
+56
+64
+60
+43
+57
+62
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+95
+87
+59
+70
+79
+77
+245
+212
+186
+251
+209
+178
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+197
+158
+251
+209
+178
+245
+212
+186
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+152
+119
+47
+56
+64
+60
+161
+144
+134
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+176
+156
+141
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+91
+92
+89
+55
+66
+67
+123
+102
+54
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+145
+114
+49
+100
+89
+56
+48
+58
+59
+187
+166
+150
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+255
+215
+190
+250
+200
+166
+251
+192
+154
+251
+192
+154
+250
+197
+158
+253
+204
+176
+255
+215
+190
+146
+135
+124
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+41
+58
+57
+112
+85
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+84
+85
+82
+255
+215
+190
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+251
+209
+178
+238
+205
+179
+84
+85
+82
+106
+82
+65
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+106
+82
+65
+41
+58
+57
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+146
+135
+124
+255
+215
+190
+253
+204
+176
+251
+192
+154
+249
+189
+146
+251
+192
+154
+250
+200
+166
+255
+215
+190
+176
+156
+141
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+253
+212
+188
+253
+204
+176
+250
+200
+166
+253
+204
+176
+217
+187
+166
+55
+66
+67
+146
+97
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+253
+204
+176
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+200
+166
+253
+212
+188
+207
+178
+158
+48
+58
+59
+163
+104
+61
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+250
+200
+166
+248
+180
+134
+251
+168
+115
+247
+165
+111
+247
+165
+111
+251
+168
+115
+248
+180
+134
+250
+200
+166
+91
+92
+89
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+126
+45
+125
+90
+64
+63
+74
+74
+227
+196
+175
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+197
+158
+253
+204
+176
+255
+215
+190
+109
+106
+99
+89
+75
+66
+225
+124
+48
+227
+126
+50
+224
+123
+55
+234
+125
+52
+125
+90
+64
+43
+57
+62
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+251
+209
+178
+137
+127
+115
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+43
+57
+62
+217
+187
+166
+253
+212
+188
+250
+200
+166
+251
+192
+154
+249
+189
+146
+250
+197
+158
+253
+204
+176
+255
+215
+190
+120
+114
+108
+81
+73
+62
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+250
+139
+73
+249
+159
+103
+248
+180
+134
+76
+70
+64
+47
+40
+38
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+170
+137
+67
+101
+83
+47
+59
+50
+39
+170
+137
+67
+255
+238
+227
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+152
+147
+147
+35
+31
+30
+24
+22
+23
+115
+102
+92
+255
+215
+190
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+58
+69
+70
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+207
+178
+158
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+161
+127
+40
+158
+125
+46
+75
+74
+61
+48
+58
+59
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+48
+58
+59
+101
+100
+92
+91
+92
+89
+75
+74
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+111
+94
+57
+55
+66
+67
+227
+196
+175
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+255
+215
+190
+227
+196
+175
+51
+62
+63
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+48
+58
+59
+48
+58
+59
+123
+102
+54
+168
+127
+42
+158
+125
+46
+161
+127
+40
+158
+125
+46
+69
+69
+61
+120
+114
+108
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+251
+209
+178
+255
+215
+190
+146
+135
+124
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+109
+106
+99
+63
+74
+74
+111
+94
+57
+171
+129
+45
+158
+125
+46
+161
+127
+40
+152
+119
+47
+69
+69
+61
+51
+62
+63
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+56
+64
+60
+51
+62
+63
+48
+58
+59
+120
+114
+108
+245
+212
+186
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+137
+127
+115
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+200
+166
+250
+200
+166
+253
+212
+188
+255
+215
+190
+109
+106
+99
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+125
+52
+155
+100
+63
+48
+58
+59
+43
+57
+62
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+125
+90
+64
+63
+74
+74
+227
+196
+175
+253
+212
+188
+250
+200
+166
+250
+197
+158
+250
+197
+158
+253
+204
+176
+255
+215
+190
+227
+196
+175
+55
+66
+67
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+48
+58
+59
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+120
+114
+108
+255
+215
+190
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+251
+209
+178
+255
+215
+190
+137
+127
+115
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+48
+58
+59
+176
+156
+141
+251
+209
+178
+250
+200
+166
+250
+197
+158
+250
+200
+166
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+91
+92
+89
+253
+212
+188
+253
+212
+188
+250
+200
+166
+250
+200
+166
+250
+200
+166
+251
+209
+178
+255
+215
+190
+172
+150
+134
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+251
+209
+178
+251
+192
+154
+250
+176
+132
+249
+174
+124
+249
+174
+124
+248
+180
+134
+251
+192
+154
+251
+209
+178
+109
+106
+99
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+146
+97
+64
+43
+57
+62
+217
+187
+166
+255
+215
+190
+253
+204
+176
+250
+197
+158
+250
+197
+158
+250
+200
+166
+253
+212
+188
+245
+212
+186
+70
+79
+77
+106
+82
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+51
+62
+63
+51
+62
+63
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+245
+212
+186
+250
+200
+166
+251
+192
+154
+250
+197
+158
+253
+204
+176
+146
+135
+124
+65
+67
+64
+209
+117
+53
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+187
+166
+150
+255
+215
+190
+253
+204
+176
+250
+200
+166
+250
+197
+158
+250
+200
+166
+253
+212
+188
+255
+215
+190
+84
+85
+82
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+109
+10
+247
+111
+26
+247
+123
+41
+248
+138
+64
+249
+152
+92
+249
+174
+124
+121
+100
+85
+35
+31
+30
+108
+87
+46
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+171
+129
+45
+85
+71
+43
+71
+60
+43
+171
+129
+45
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+237
+233
+225
+174
+168
+167
+81
+77
+76
+24
+22
+23
+35
+31
+30
+35
+31
+30
+187
+166
+150
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+51
+62
+63
+176
+156
+141
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+146
+135
+124
+51
+62
+63
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+152
+119
+47
+56
+64
+60
+43
+57
+62
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+48
+58
+59
+146
+135
+124
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+172
+150
+134
+172
+150
+134
+146
+135
+124
+146
+135
+124
+194
+173
+157
+245
+212
+186
+137
+127
+115
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+161
+144
+134
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+161
+144
+134
+48
+58
+59
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+55
+66
+67
+51
+62
+63
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+70
+79
+77
+245
+212
+186
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+255
+215
+190
+255
+215
+190
+91
+92
+89
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+133
+120
+107
+84
+85
+82
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+55
+66
+67
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+161
+144
+134
+172
+150
+134
+172
+150
+134
+137
+127
+115
+146
+135
+124
+207
+178
+158
+245
+212
+186
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+76
+78
+76
+245
+212
+186
+255
+215
+190
+253
+212
+188
+253
+212
+188
+253
+212
+188
+255
+215
+190
+227
+196
+175
+58
+69
+70
+118
+86
+65
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+125
+90
+64
+63
+74
+74
+97
+98
+96
+76
+70
+64
+214
+121
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+163
+104
+61
+48
+58
+59
+187
+166
+150
+255
+215
+190
+255
+215
+190
+251
+209
+178
+251
+209
+178
+255
+215
+190
+255
+215
+190
+176
+156
+141
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+227
+126
+50
+212
+120
+56
+69
+69
+61
+101
+100
+92
+63
+74
+74
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+106
+82
+65
+63
+74
+74
+234
+204
+183
+255
+215
+190
+253
+212
+188
+253
+212
+188
+253
+212
+188
+255
+215
+190
+245
+212
+186
+70
+79
+77
+89
+75
+66
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+176
+156
+141
+253
+204
+176
+251
+192
+154
+251
+192
+154
+251
+192
+154
+250
+200
+166
+77
+85
+81
+106
+82
+65
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+135
+94
+64
+51
+62
+63
+217
+187
+166
+255
+215
+190
+255
+215
+190
+253
+212
+188
+253
+212
+188
+255
+215
+190
+255
+215
+190
+109
+106
+99
+76
+70
+64
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+250
+200
+166
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+250
+200
+166
+255
+215
+190
+146
+135
+124
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+51
+62
+63
+146
+135
+124
+255
+215
+190
+255
+215
+190
+251
+209
+178
+251
+209
+178
+253
+212
+188
+255
+215
+190
+194
+173
+157
+43
+57
+62
+146
+97
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+77
+85
+81
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+251
+209
+178
+250
+197
+158
+249
+189
+146
+249
+189
+146
+250
+200
+166
+172
+150
+134
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+120
+114
+108
+255
+215
+190
+255
+215
+190
+253
+212
+188
+251
+209
+178
+253
+212
+188
+255
+215
+190
+217
+187
+166
+51
+62
+63
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+60
+247
+150
+84
+251
+168
+115
+187
+140
+108
+24
+22
+23
+59
+50
+39
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+154
+125
+71
+156
+125
+62
+158
+125
+46
+47
+40
+38
+108
+87
+46
+158
+125
+46
+195
+167
+113
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+164
+158
+157
+109
+106
+99
+65
+58
+56
+24
+22
+23
+24
+22
+23
+94
+60
+47
+178
+86
+46
+59
+50
+39
+150
+125
+114
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+69
+69
+61
+84
+85
+82
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+55
+66
+67
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+123
+102
+54
+51
+62
+63
+76
+78
+76
+56
+64
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+217
+187
+166
+133
+120
+107
+77
+85
+81
+77
+85
+81
+146
+135
+124
+245
+212
+186
+176
+156
+141
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+75
+74
+61
+63
+74
+74
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+76
+78
+76
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+77
+85
+81
+77
+85
+81
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+172
+150
+134
+48
+58
+59
+117
+98
+55
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+120
+114
+108
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+111
+94
+57
+51
+62
+63
+176
+156
+141
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+120
+114
+108
+70
+79
+77
+84
+85
+82
+161
+144
+134
+255
+215
+190
+255
+215
+190
+161
+144
+134
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+155
+100
+63
+41
+58
+57
+161
+144
+134
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+137
+127
+115
+48
+58
+59
+183
+110
+59
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+89
+75
+66
+97
+98
+96
+172
+150
+134
+48
+58
+59
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+214
+121
+50
+76
+70
+64
+84
+85
+82
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+77
+85
+81
+81
+73
+62
+224
+123
+55
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+176
+156
+141
+97
+98
+96
+95
+78
+64
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+161
+144
+134
+41
+58
+57
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+250
+200
+166
+249
+189
+146
+252
+185
+144
+249
+189
+146
+250
+200
+166
+120
+114
+108
+69
+69
+61
+214
+121
+50
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+101
+100
+92
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+187
+166
+150
+43
+57
+62
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+253
+212
+188
+253
+204
+176
+250
+200
+166
+250
+200
+166
+253
+204
+176
+253
+212
+188
+255
+215
+190
+187
+166
+150
+41
+58
+57
+155
+100
+63
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+95
+78
+64
+58
+69
+70
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+91
+92
+89
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+62
+63
+61
+133
+120
+107
+77
+85
+81
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+253
+204
+176
+251
+192
+154
+252
+185
+144
+252
+185
+144
+251
+192
+154
+212
+173
+150
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+118
+86
+65
+51
+62
+63
+207
+178
+158
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+109
+106
+99
+56
+64
+60
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+247
+111
+26
+246
+116
+28
+247
+130
+53
+247
+143
+74
+249
+159
+103
+248
+180
+134
+89
+75
+66
+24
+22
+23
+85
+71
+43
+171
+129
+45
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+154
+125
+71
+156
+125
+62
+175
+132
+40
+85
+71
+43
+47
+40
+38
+158
+125
+46
+158
+125
+46
+170
+137
+67
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+207
+202
+200
+164
+158
+157
+146
+135
+124
+120
+114
+108
+89
+84
+82
+65
+58
+56
+47
+40
+38
+24
+22
+23
+24
+22
+23
+35
+31
+30
+94
+60
+47
+178
+86
+46
+226
+110
+35
+241
+100
+24
+144
+77
+47
+65
+58
+56
+253
+212
+188
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+129
+106
+52
+48
+58
+59
+101
+100
+92
+217
+187
+166
+245
+212
+186
+245
+212
+186
+194
+173
+157
+76
+78
+76
+56
+64
+60
+145
+114
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+77
+85
+81
+176
+156
+141
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+95
+87
+59
+41
+58
+57
+137
+127
+115
+227
+196
+175
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+207
+178
+158
+120
+114
+108
+48
+58
+59
+62
+63
+61
+100
+89
+56
+95
+87
+59
+51
+62
+63
+120
+114
+108
+227
+196
+175
+55
+66
+67
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+84
+85
+82
+207
+178
+158
+245
+212
+186
+245
+212
+186
+207
+178
+158
+97
+98
+96
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+91
+92
+89
+120
+114
+108
+63
+69
+60
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+43
+57
+62
+161
+144
+134
+227
+196
+175
+253
+212
+188
+234
+204
+183
+161
+144
+134
+51
+62
+63
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+176
+156
+141
+48
+58
+59
+137
+110
+49
+171
+129
+45
+158
+125
+46
+161
+127
+40
+158
+125
+46
+75
+74
+61
+43
+57
+62
+161
+144
+134
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+194
+173
+157
+109
+106
+99
+43
+57
+62
+69
+69
+61
+105
+93
+60
+88
+82
+59
+48
+58
+59
+146
+135
+124
+255
+215
+190
+161
+144
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+225
+124
+48
+95
+78
+64
+43
+57
+62
+161
+144
+134
+234
+204
+183
+245
+212
+186
+227
+196
+175
+146
+135
+124
+35
+56
+60
+125
+90
+64
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+188
+112
+56
+51
+62
+63
+161
+144
+134
+234
+204
+183
+51
+62
+63
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+125
+52
+163
+104
+61
+43
+57
+62
+97
+98
+96
+207
+178
+158
+245
+212
+186
+245
+212
+186
+207
+178
+158
+91
+92
+89
+48
+58
+59
+173
+106
+60
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+118
+86
+65
+55
+66
+67
+234
+204
+183
+146
+135
+124
+56
+64
+60
+194
+112
+58
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+35
+56
+60
+146
+135
+124
+227
+196
+175
+253
+212
+188
+234
+204
+183
+161
+144
+134
+43
+57
+62
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+176
+156
+141
+250
+197
+158
+252
+185
+144
+248
+180
+134
+248
+180
+134
+251
+192
+154
+172
+150
+134
+48
+58
+59
+173
+106
+60
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+41
+58
+57
+120
+114
+108
+217
+187
+166
+245
+212
+186
+234
+204
+183
+176
+156
+141
+58
+69
+70
+81
+73
+62
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+255
+215
+190
+217
+187
+166
+133
+120
+107
+84
+85
+82
+91
+92
+89
+146
+135
+124
+234
+204
+183
+238
+205
+179
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+84
+85
+82
+194
+173
+157
+245
+212
+186
+245
+212
+186
+217
+187
+166
+109
+106
+99
+41
+58
+57
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+146
+97
+64
+51
+62
+63
+187
+166
+150
+76
+78
+76
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+97
+98
+96
+250
+200
+166
+249
+189
+146
+248
+180
+134
+248
+180
+134
+252
+185
+144
+232
+190
+161
+70
+79
+77
+112
+85
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+199
+115
+54
+65
+67
+64
+70
+79
+77
+187
+166
+150
+238
+205
+179
+245
+212
+186
+217
+187
+166
+133
+120
+107
+35
+56
+60
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+123
+41
+247
+130
+60
+247
+150
+84
+251
+168
+115
+203
+161
+131
+55
+48
+48
+24
+22
+23
+71
+60
+43
+145
+114
+49
+171
+129
+45
+171
+129
+45
+158
+125
+46
+156
+125
+62
+154
+125
+71
+154
+125
+71
+156
+125
+62
+156
+125
+62
+171
+129
+45
+171
+129
+45
+101
+83
+47
+35
+31
+30
+123
+102
+54
+171
+129
+45
+158
+125
+46
+160
+120
+43
+224
+207
+180
+253
+255
+252
+253
+255
+252
+219
+212
+208
+47
+40
+38
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+24
+22
+23
+47
+40
+38
+226
+110
+35
+241
+100
+24
+226
+110
+35
+226
+110
+35
+144
+77
+47
+55
+48
+48
+238
+205
+179
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+123
+102
+54
+56
+64
+60
+51
+62
+63
+84
+85
+82
+84
+85
+82
+48
+58
+59
+63
+69
+60
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+245
+212
+186
+84
+85
+82
+69
+69
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+95
+87
+59
+48
+58
+59
+63
+74
+74
+109
+106
+99
+133
+120
+107
+133
+120
+107
+91
+92
+89
+51
+62
+63
+56
+64
+60
+100
+89
+56
+152
+119
+47
+171
+129
+45
+175
+132
+40
+100
+89
+56
+48
+58
+59
+217
+187
+166
+120
+114
+108
+63
+69
+60
+152
+119
+47
+161
+127
+40
+158
+125
+46
+158
+125
+46
+168
+127
+42
+129
+106
+52
+61
+67
+58
+51
+62
+63
+84
+85
+82
+84
+85
+82
+51
+62
+63
+56
+64
+60
+123
+102
+54
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+97
+98
+96
+187
+166
+150
+48
+58
+59
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+83
+78
+61
+48
+58
+59
+63
+74
+74
+91
+92
+89
+70
+79
+77
+48
+58
+59
+75
+74
+61
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+146
+135
+124
+234
+204
+183
+63
+74
+74
+83
+78
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+83
+78
+61
+48
+58
+59
+70
+79
+77
+109
+106
+99
+133
+120
+107
+120
+114
+108
+84
+85
+82
+48
+58
+59
+61
+67
+58
+111
+94
+57
+158
+125
+46
+171
+129
+45
+171
+129
+45
+88
+82
+59
+58
+69
+70
+238
+205
+179
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+212
+120
+56
+95
+78
+64
+43
+57
+62
+70
+79
+77
+84
+85
+82
+63
+74
+74
+48
+58
+59
+118
+86
+65
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+112
+85
+63
+55
+66
+67
+227
+196
+175
+255
+215
+190
+120
+114
+108
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+155
+100
+63
+62
+63
+61
+51
+62
+63
+77
+85
+81
+77
+85
+81
+51
+62
+63
+62
+63
+61
+155
+100
+63
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+199
+115
+54
+56
+64
+60
+120
+114
+108
+255
+215
+190
+217
+187
+166
+43
+57
+62
+125
+90
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+106
+82
+65
+48
+58
+59
+63
+74
+74
+84
+85
+82
+70
+79
+77
+43
+57
+62
+95
+78
+64
+212
+120
+56
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+172
+150
+134
+251
+192
+154
+248
+180
+134
+249
+174
+124
+249
+174
+124
+248
+180
+134
+236
+186
+153
+63
+74
+74
+95
+78
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+51
+62
+63
+55
+66
+67
+84
+85
+82
+70
+79
+77
+41
+58
+57
+81
+73
+62
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+255
+215
+190
+194
+173
+157
+58
+69
+70
+62
+63
+61
+106
+82
+65
+95
+78
+64
+51
+62
+63
+91
+92
+89
+238
+205
+179
+161
+144
+134
+48
+58
+59
+183
+110
+59
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+125
+52
+173
+106
+60
+65
+67
+64
+48
+58
+59
+77
+85
+81
+84
+85
+82
+55
+66
+67
+56
+64
+60
+146
+97
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+69
+69
+61
+101
+100
+92
+227
+196
+175
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+250
+197
+158
+252
+185
+144
+249
+174
+124
+249
+174
+124
+250
+176
+132
+251
+192
+154
+120
+114
+108
+62
+63
+61
+209
+117
+53
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+188
+112
+56
+76
+70
+64
+41
+58
+57
+77
+85
+81
+84
+85
+82
+58
+69
+70
+48
+58
+59
+125
+90
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+243
+101
+2
+247
+103
+7
+247
+103
+7
+247
+111
+26
+247
+118
+39
+247
+130
+53
+250
+139
+73
+246
+156
+93
+249
+174
+124
+203
+161
+131
+55
+48
+48
+24
+22
+23
+35
+31
+30
+85
+71
+43
+137
+110
+49
+152
+119
+47
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+152
+119
+47
+117
+98
+55
+59
+50
+39
+35
+31
+30
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+224
+207
+180
+253
+255
+252
+253
+255
+252
+253
+255
+252
+146
+135
+124
+65
+58
+56
+35
+31
+30
+24
+22
+23
+24
+22
+23
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+83
+53
+42
+236
+108
+29
+236
+108
+29
+226
+110
+35
+94
+60
+47
+65
+58
+56
+253
+212
+188
+255
+215
+190
+238
+205
+179
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+145
+114
+49
+105
+93
+60
+83
+78
+61
+83
+78
+61
+111
+94
+57
+158
+125
+46
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+88
+82
+59
+51
+62
+63
+217
+187
+166
+255
+215
+190
+176
+156
+141
+43
+57
+62
+105
+93
+60
+171
+129
+45
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+137
+110
+49
+88
+82
+59
+69
+69
+61
+62
+63
+61
+63
+69
+60
+75
+74
+61
+105
+93
+60
+152
+119
+47
+171
+129
+45
+168
+127
+42
+158
+125
+46
+171
+129
+45
+129
+106
+52
+48
+58
+59
+194
+173
+157
+207
+178
+158
+43
+57
+62
+100
+89
+56
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+152
+119
+47
+111
+94
+57
+83
+78
+61
+83
+78
+61
+105
+93
+60
+145
+114
+49
+168
+127
+42
+161
+127
+40
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+245
+212
+186
+77
+85
+81
+75
+74
+61
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+129
+106
+52
+95
+87
+59
+81
+73
+62
+95
+87
+59
+123
+102
+54
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+56
+64
+60
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+161
+144
+134
+48
+58
+59
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+129
+106
+52
+88
+82
+59
+69
+69
+61
+62
+63
+61
+63
+69
+60
+75
+74
+61
+117
+98
+55
+152
+119
+47
+171
+129
+45
+161
+127
+40
+158
+125
+46
+171
+129
+45
+111
+94
+57
+48
+58
+59
+227
+196
+175
+176
+156
+141
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+163
+104
+61
+112
+85
+63
+95
+78
+64
+118
+86
+65
+173
+106
+60
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+183
+110
+59
+51
+62
+63
+133
+120
+107
+255
+215
+190
+255
+215
+190
+217
+187
+166
+51
+62
+63
+106
+82
+65
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+199
+115
+54
+135
+94
+64
+95
+78
+64
+95
+78
+64
+135
+94
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+106
+82
+65
+51
+62
+63
+217
+187
+166
+255
+215
+190
+255
+215
+190
+120
+114
+108
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+173
+106
+60
+118
+86
+65
+95
+78
+64
+112
+85
+63
+163
+104
+61
+227
+126
+50
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+101
+100
+92
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+172
+150
+134
+252
+185
+144
+249
+174
+124
+247
+165
+111
+247
+165
+111
+249
+174
+124
+252
+185
+144
+154
+133
+118
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+188
+112
+56
+125
+90
+64
+95
+78
+64
+106
+82
+65
+155
+100
+63
+224
+123
+55
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+137
+127
+115
+253
+212
+188
+91
+92
+89
+69
+69
+61
+194
+112
+58
+234
+126
+45
+234
+126
+45
+163
+104
+61
+51
+62
+63
+137
+127
+115
+238
+205
+179
+63
+74
+74
+89
+75
+66
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+209
+117
+53
+146
+97
+64
+106
+82
+65
+95
+78
+64
+125
+90
+64
+194
+112
+58
+234
+126
+45
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+125
+90
+64
+41
+58
+57
+194
+173
+157
+238
+205
+179
+63
+74
+74
+135
+94
+64
+234
+125
+52
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+251
+192
+154
+250
+176
+132
+251
+168
+115
+247
+165
+111
+249
+174
+124
+245
+179
+138
+195
+157
+134
+41
+58
+57
+135
+94
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+146
+97
+64
+106
+82
+65
+95
+78
+64
+125
+90
+64
+183
+110
+59
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+125
+52
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+249
+152
+92
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+247
+103
+7
+246
+109
+10
+247
+111
+26
+247
+118
+39
+247
+130
+53
+247
+143
+74
+249
+159
+103
+250
+176
+132
+219
+170
+138
+115
+102
+92
+47
+40
+38
+24
+22
+23
+35
+31
+30
+47
+40
+38
+59
+50
+39
+59
+50
+39
+59
+50
+39
+59
+50
+39
+47
+40
+38
+47
+40
+38
+71
+60
+43
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+152
+119
+47
+170
+137
+67
+219
+212
+208
+237
+233
+225
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+219
+212
+208
+152
+147
+147
+109
+106
+99
+65
+67
+64
+35
+31
+30
+35
+31
+30
+35
+31
+30
+35
+31
+30
+24
+22
+23
+94
+60
+47
+178
+86
+46
+109
+63
+45
+35
+31
+30
+124
+111
+99
+251
+209
+178
+251
+209
+178
+234
+204
+183
+76
+78
+76
+95
+87
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+117
+98
+55
+129
+106
+52
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+171
+129
+45
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+117
+98
+55
+48
+58
+59
+146
+135
+124
+255
+215
+190
+255
+215
+190
+255
+215
+190
+120
+114
+108
+51
+62
+63
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+152
+119
+47
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+158
+125
+46
+81
+73
+62
+58
+69
+70
+227
+196
+175
+255
+215
+190
+120
+114
+108
+48
+58
+59
+129
+106
+52
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+152
+119
+47
+117
+98
+55
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+88
+82
+59
+84
+85
+82
+255
+215
+190
+176
+156
+141
+48
+58
+59
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+145
+114
+49
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+117
+98
+55
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+63
+69
+60
+137
+127
+115
+255
+215
+190
+238
+205
+179
+91
+92
+89
+56
+64
+60
+137
+110
+49
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+152
+119
+47
+158
+125
+46
+168
+127
+42
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+152
+119
+47
+69
+69
+61
+84
+85
+82
+245
+212
+186
+172
+150
+134
+62
+63
+61
+199
+115
+54
+227
+126
+50
+224
+123
+55
+227
+126
+50
+199
+115
+54
+125
+90
+64
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+125
+52
+227
+126
+50
+234
+125
+52
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+214
+121
+50
+81
+73
+62
+63
+74
+74
+227
+196
+175
+255
+215
+190
+253
+212
+188
+255
+215
+190
+146
+135
+124
+48
+58
+59
+146
+97
+64
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+139
+96
+61
+48
+58
+59
+146
+135
+124
+255
+215
+190
+253
+212
+188
+255
+215
+190
+217
+187
+166
+55
+66
+67
+95
+78
+64
+225
+124
+48
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+163
+104
+61
+183
+110
+59
+227
+126
+50
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+97
+98
+96
+56
+64
+60
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+183
+110
+59
+51
+62
+63
+167
+142
+123
+248
+180
+134
+247
+165
+111
+249
+159
+103
+246
+156
+93
+249
+159
+103
+249
+174
+124
+239
+182
+144
+77
+85
+81
+65
+67
+64
+199
+115
+54
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+135
+94
+64
+188
+112
+56
+227
+126
+50
+224
+123
+55
+227
+126
+50
+209
+117
+53
+65
+67
+64
+146
+135
+124
+227
+196
+175
+43
+57
+62
+146
+97
+64
+234
+126
+45
+224
+123
+55
+224
+123
+55
+234
+126
+45
+106
+82
+65
+70
+79
+77
+253
+212
+188
+176
+156
+141
+41
+58
+57
+125
+90
+64
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+227
+126
+50
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+155
+100
+63
+48
+58
+59
+120
+114
+108
+253
+212
+188
+234
+204
+183
+63
+74
+74
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+252
+185
+144
+245
+169
+119
+249
+159
+103
+249
+159
+103
+247
+165
+111
+249
+174
+124
+251
+192
+154
+109
+106
+99
+62
+63
+61
+188
+112
+56
+234
+125
+52
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+234
+125
+52
+227
+126
+50
+234
+125
+52
+227
+126
+50
+227
+126
+50
+212
+120
+56
+199
+115
+54
+224
+123
+55
+224
+123
+55
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+200
+166
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+243
+101
+2
+243
+101
+2
+247
+103
+7
+247
+111
+26
+247
+111
+26
+247
+123
+41
+247
+130
+60
+243
+141
+78
+249
+159
+103
+250
+176
+132
+251
+192
+154
+207
+178
+158
+154
+133
+118
+82
+69
+65
+24
+22
+23
+71
+60
+43
+101
+83
+47
+101
+83
+47
+101
+83
+47
+117
+98
+55
+145
+114
+49
+171
+129
+45
+168
+127
+42
+160
+120
+43
+160
+120
+43
+158
+125
+46
+192
+155
+91
+237
+233
+225
+81
+77
+76
+55
+48
+48
+74
+68
+68
+81
+77
+76
+89
+84
+82
+91
+92
+89
+89
+84
+82
+81
+77
+76
+65
+58
+56
+47
+40
+38
+35
+31
+30
+55
+48
+48
+115
+102
+92
+172
+150
+134
+55
+48
+48
+24
+22
+23
+24
+22
+23
+24
+22
+23
+65
+58
+56
+230
+173
+136
+251
+192
+154
+250
+197
+158
+250
+200
+166
+84
+85
+82
+88
+82
+59
+171
+129
+45
+158
+125
+46
+158
+125
+46
+171
+129
+45
+83
+78
+61
+69
+69
+61
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+117
+98
+55
+48
+58
+59
+101
+100
+92
+238
+205
+179
+253
+204
+176
+250
+200
+166
+253
+204
+176
+238
+205
+179
+91
+92
+89
+51
+62
+63
+117
+98
+55
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+145
+114
+49
+75
+74
+61
+48
+58
+59
+172
+150
+134
+253
+212
+188
+255
+215
+190
+234
+204
+183
+84
+85
+82
+56
+64
+60
+129
+106
+52
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+81
+73
+62
+63
+69
+60
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+83
+78
+61
+84
+85
+82
+255
+215
+190
+245
+212
+186
+109
+106
+99
+51
+62
+63
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+171
+129
+45
+105
+93
+60
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+137
+127
+115
+58
+69
+70
+111
+94
+57
+171
+129
+45
+158
+125
+46
+158
+125
+46
+158
+125
+46
+62
+63
+61
+137
+127
+115
+255
+215
+190
+255
+215
+190
+227
+196
+175
+77
+85
+81
+56
+64
+60
+129
+106
+52
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+161
+127
+40
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+168
+127
+42
+137
+110
+49
+69
+69
+61
+51
+62
+63
+187
+166
+150
+255
+215
+190
+172
+150
+134
+51
+62
+63
+194
+112
+58
+227
+126
+50
+224
+123
+55
+234
+125
+52
+183
+110
+59
+48
+58
+59
+155
+100
+63
+234
+126
+45
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+125
+52
+209
+117
+53
+89
+75
+66
+48
+58
+59
+187
+166
+150
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+109
+106
+99
+48
+58
+59
+135
+94
+64
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+135
+94
+64
+43
+57
+62
+120
+114
+108
+250
+200
+166
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+172
+150
+134
+41
+58
+57
+106
+82
+65
+214
+121
+50
+234
+125
+52
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+234
+126
+45
+183
+110
+59
+48
+58
+59
+135
+94
+64
+234
+126
+45
+224
+123
+55
+227
+126
+50
+188
+112
+56
+51
+62
+63
+109
+106
+99
+51
+62
+63
+183
+110
+59
+227
+126
+50
+224
+123
+55
+234
+125
+52
+173
+106
+60
+48
+58
+59
+178
+146
+122
+245
+169
+119
+246
+156
+93
+247
+150
+84
+249
+146
+83
+247
+150
+84
+249
+159
+103
+249
+174
+124
+203
+161
+131
+58
+69
+70
+76
+70
+64
+194
+112
+58
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+183
+110
+59
+48
+58
+59
+163
+104
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+209
+117
+53
+62
+63
+61
+146
+135
+124
+217
+187
+166
+43
+57
+62
+163
+104
+61
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+58
+69
+70
+234
+204
+183
+255
+215
+190
+137
+127
+115
+41
+58
+57
+118
+86
+65
+225
+124
+48
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+146
+97
+64
+51
+62
+63
+97
+98
+96
+238
+205
+179
+255
+215
+190
+234
+204
+183
+63
+74
+74
+118
+86
+65
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+81
+73
+62
+101
+100
+92
+250
+176
+132
+247
+165
+111
+246
+156
+93
+249
+152
+92
+249
+159
+103
+251
+168
+115
+252
+185
+144
+217
+187
+166
+58
+69
+70
+69
+69
+61
+199
+115
+54
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+224
+123
+55
+227
+126
+50
+225
+124
+48
+81
+73
+62
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+55
+66
+67
+250
+197
+158
+249
+174
+124
+247
+150
+84
+247
+130
+60
+247
+118
+39
+247
+111
+26
+247
+103
+7
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+243
+101
+2
+247
+103
+7
+236
+102
+14
+247
+111
+26
+246
+116
+28
+247
+123
+41
+247
+130
+60
+243
+141
+78
+249
+159
+103
+249
+174
+124
+249
+189
+146
+253
+204
+176
+124
+111
+99
+35
+31
+30
+145
+114
+49
+175
+132
+40
+171
+129
+45
+168
+127
+42
+192
+155
+91
+216
+194
+154
+224
+207
+180
+224
+207
+180
+216
+194
+154
+216
+194
+154
+239
+227
+208
+253
+255
+252
+253
+255
+252
+186
+181
+179
+146
+135
+124
+120
+114
+108
+109
+106
+99
+95
+78
+64
+71
+60
+43
+85
+71
+43
+101
+83
+47
+108
+87
+46
+35
+31
+30
+150
+125
+114
+227
+196
+175
+255
+215
+190
+253
+212
+188
+212
+173
+150
+121
+100
+85
+95
+78
+64
+129
+102
+78
+234
+168
+124
+250
+176
+132
+250
+176
+132
+248
+180
+134
+249
+189
+146
+124
+111
+99
+62
+63
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+145
+114
+49
+56
+64
+60
+43
+57
+62
+83
+78
+61
+152
+119
+47
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+152
+119
+47
+95
+87
+59
+48
+58
+59
+101
+100
+92
+236
+186
+153
+251
+192
+154
+252
+185
+144
+248
+180
+134
+245
+179
+138
+249
+189
+146
+236
+186
+153
+101
+100
+92
+48
+58
+59
+88
+82
+59
+137
+110
+49
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+168
+127
+42
+145
+114
+49
+100
+89
+56
+56
+64
+60
+58
+69
+70
+172
+150
+134
+250
+200
+166
+251
+192
+154
+250
+197
+158
+250
+200
+166
+217
+187
+166
+84
+85
+82
+51
+62
+63
+105
+93
+60
+158
+125
+46
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+152
+119
+47
+83
+78
+61
+43
+57
+62
+48
+58
+59
+129
+106
+52
+175
+132
+40
+171
+129
+45
+158
+125
+46
+63
+69
+60
+120
+114
+108
+255
+215
+190
+255
+215
+190
+227
+196
+175
+84
+85
+82
+51
+62
+63
+105
+93
+60
+158
+125
+46
+171
+129
+45
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+158
+125
+46
+105
+93
+60
+48
+58
+59
+48
+58
+59
+129
+106
+52
+168
+127
+42
+158
+125
+46
+168
+127
+42
+145
+114
+49
+51
+62
+63
+172
+150
+134
+91
+92
+89
+75
+74
+61
+168
+127
+42
+171
+129
+45
+175
+132
+40
+117
+98
+55
+48
+58
+59
+176
+156
+141
+253
+204
+176
+253
+204
+176
+253
+204
+176
+217
+187
+166
+84
+85
+82
+48
+58
+59
+95
+87
+59
+145
+114
+49
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+171
+129
+45
+158
+125
+46
+137
+110
+49
+95
+87
+59
+51
+62
+63
+70
+79
+77
+187
+166
+150
+251
+209
+178
+251
+209
+178
+207
+178
+158
+43
+57
+62
+135
+94
+64
+238
+123
+45
+234
+126
+45
+234
+126
+45
+118
+86
+65
+35
+56
+60
+56
+64
+60
+155
+100
+63
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+126
+45
+227
+126
+50
+163
+104
+61
+76
+70
+64
+51
+62
+63
+167
+142
+123
+251
+192
+154
+248
+180
+134
+249
+174
+124
+249
+174
+124
+250
+176
+132
+245
+179
+138
+236
+186
+153
+109
+106
+99
+41
+58
+57
+95
+78
+64
+183
+110
+59
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+227
+126
+50
+183
+110
+59
+95
+78
+64
+43
+57
+62
+124
+111
+99
+236
+186
+153
+252
+185
+144
+250
+176
+132
+249
+174
+124
+249
+174
+124
+248
+180
+134
+251
+192
+154
+154
+133
+118
+43
+57
+62
+81
+73
+62
+173
+106
+60
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+125
+52
+155
+100
+63
+56
+64
+60
+35
+56
+60
+89
+75
+66
+227
+126
+50
+234
+126
+45
+238
+128
+40
+146
+97
+64
+43
+57
+62
+176
+156
+141
+58
+69
+70
+118
+86
+65
+234
+126
+45
+234
+126
+45
+234
+126
+45
+112
+85
+63
+43
+57
+62
+210
+156
+119
+245
+162
+103
+247
+150
+84
+247
+143
+74
+248
+138
+64
+241
+138
+68
+249
+146
+83
+249
+159
+103
+250
+176
+132
+195
+157
+134
+58
+69
+70
+65
+67
+64
+155
+100
+63
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+126
+45
+173
+106
+60
+65
+67
+64
+35
+56
+60
+106
+82
+65
+234
+126
+45
+234
+126
+45
+238
+128
+40
+146
+97
+64
+43
+57
+62
+187
+166
+150
+234
+204
+183
+55
+66
+67
+106
+82
+65
+234
+126
+45
+234
+125
+52
+234
+125
+52
+224
+123
+55
+81
+73
+62
+91
+92
+89
+245
+212
+186
+253
+212
+188
+253
+212
+188
+137
+127
+115
+41
+58
+57
+89
+75
+66
+173
+106
+60
+227
+126
+50
+234
+126
+45
+227
+126
+50
+227
+126
+50
+227
+126
+50
+234
+125
+52
+234
+126
+45
+234
+125
+52
+194
+112
+58
+106
+82
+65
+43
+57
+62
+101
+100
+92
+227
+196
+175
+251
+209
+178
+251
+209
+178
+253
+212
+188
+97
+98
+96
+69
+69
+61
+209
+117
+53
+234
+126
+45
+238
+128
+40
+173
+106
+60
+51
+62
+63
+139
+115
+96
+251
+168
+115
+246
+156
+93
+247
+150
+84
+249
+146
+83
+249
+152
+92
+247
+165
+111
+248
+180
+134
+250
+200
+166
+187
+166
+150
+55
+66
+67
+69
+69
+61
+163
+104
+61
+234
+125
+52
+234
+126
+45
+234
+125
+52
+227
+126
+50
+227
+126
+50
+234
+126
+45
+234
+126
+45
+199
+115
+54
+95
+78
+64
+35
+56
+60
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+139
+96
+61
+51
+62
+63
+250
+197
+158
+245
+169
+119
+247
+150
+84
+247
+130
+60
+247
+118
+39
+235
+107
+16
+243
+101
+2
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+246
+97
+3
+237
+95
+0
+243
+101
+2
+247
+103
+7
+236
+102
+14
+247
+111
+26
+246
+116
+28
+238
+123
+45
+241
+132
+59
+247
+143
+74
+246
+156
+93
+245
+169
+119
+230
+173
+136
+47
+40
+38
+59
+50
+39
+168
+127
+42
+161
+127
+40
+160
+120
+43
+192
+155
+91
+255
+238
+227
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+253
+255
+252
+239
+227
+208
+170
+137
+67
+171
+129
+45
+171
+129
+45
+171
+129
+45
+59
+50
+39
+154
+133
+118
+250
+200
+166
+250
+197
+158
+249
+189
+146
+248
+180
+134
+249
+174
+124
+247
+165
+111
+247
+165
+111
+245
+162
+103
+249
+159
+103
+245
+162
+103
+247
+165
+111
+249
+174
+124
+203
+161
+131
+55
+66
+67
+69
+69
+61
+111
+94
+57
+105
+93
+60
+69
+69
+61
+63
+74
+74
+137
+127
+115
+51
+62
+63
+62
+63
+61
+95
+87
+59
+129
+106
+52
+137
+110
+49
+137
+110
+49
+123
+102
+54
+95
+87
+59
+62
+63
+61
+51
+62
+63
+133
+120
+107
+239
+182
+144
+248
+180
+134
+245
+169
+119
+247
+165
+111
+249
+159
+103
+245
+162
+103
+251
+168
+115
+250
+176
+132
+239
+182
+144
+154
+133
+118
+63
+74
+74
+51
+62
+63
+75
+74
+61
+105
+93
+60
+123
+102
+54
+137
+110
+49
+137
+110
+49
+137
+110
+49
+123
+102
+54
+100
+89
+56
+75
+74
+61
+56
+64
+60
+55
+66
+67
+124
+111
+99
+219
+170
+138
+252
+185
+144
+250
+176
+132
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+236
+186
+153
+124
+111
+99
+48
+58
+59
+63
+69
+60
+95
+87
+59
+123
+102
+54
+137
+110
+49
+137
+110
+49
+129
+106
+52
+95
+87
+59
+62
+63
+61
+55
+66
+67
+146
+135
+124
+77
+85
+81
+61
+67
+58
+105
+93
+60
+111
+94
+57
+75
+74
+61
+48
+58
+59
+194
+173
+157
+255
+215
+190
+255
+215
+190
+255
+215
+190
+234
+204
+183
+120
+114
+108
+43
+57
+62
+69
+69
+61
+100
+89
+56
+129
+106
+52
+137
+110
+49
+137
+110
+49
+129
+106
+52
+105
+93
+60
+69
+69
+61
+48
+58
+59
+77
+85
+81
+51
+62
+63
+137
+110
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+137
+110
+49
+51
+62
+63
+187
+166
+150
+187
+166
+150
+48
+58
+59
+75
+74
+61
+111
+94
+57
+95
+87
+59
+56
+64
+60
+99
+90
+79
+239
+182
+144
+252
+185
+144
+245
+179
+138
+252
+185
+144
+249
+189
+146
+236
+186
+153
+137
+127
+115
+55
+66
+67
+56
+64
+60
+83
+78
+61
+111
+94
+57
+129
+106
+52
+137
+110
+49
+137
+110
+49
+129
+106
+52
+117
+98
+55
+95
+87
+59
+69
+69
+61
+51
+62
+63
+63
+74
+74
+133
+120
+107
+236
+186
+153
+250
+197
+158
+251
+192
+154
+251
+192
+154
+250
+197
+158
+124
+111
+99
+51
+62
+63
+112
+85
+63
+146
+97
+64
+106
+82
+65
+48
+58
+59
+120
+114
+108
+101
+100
+92
+48
+58
+59
+95
+78
+64
+146
+97
+64
+183
+110
+59
+188
+112
+56
+173
+106
+60
+139
+96
+61
+89
+75
+66
+48
+58
+59
+77
+85
+81
+186
+157
+134
+245
+179
+138
+245
+169
+119
+245
+162
+103
+246
+156
+93
+246
+156
+93
+246
+156
+93
+247
+165
+111
+249
+174
+124
+249
+189
+146
+154
+133
+118
+58
+69
+70
+51
+62
+63
+95
+78
+64
+139
+96
+61
+173
+106
+60
+183
+110
+59
+183
+110
+59
+173
+106
+60
+139
+96
+61
+95
+78
+64
+51
+62
+63
+63
+74
+74
+167
+142
+123
+249
+189
+146
+249
+174
+124
+247
+165
+111
+246
+156
+93
+246
+156
+93
+246
+156
+93
+245
+162
+103
+245
+169
+119
+245
+179
+138
+178
+146
+122
+70
+79
+77
+48
+58
+59
+89
+75
+66
+139
+96
+61
+173
+106
+60
+188
+112
+56
+183
+110
+59
+155
+100
+63
+95
+78
+64
+48
+58
+59
+101
+100
+92
+146
+135
+124
+48
+58
+59
+95
+78
+64
+146
+97
+64
+125
+90
+64
+62
+63
+61
+101
+100
+92
+245
+212
+186
+137
+127
+115
+48
+58
+59
+106
+82
+65
+146
+97
+64
+106
+82
+65
+48
+58
+59
+124
+111
+99
+247
+165
+111
+247
+150
+84
+241
+138
+68
+241
+132
+59
+247
+130
+53
+247
+130
+53
+242
+133
+67
+241
+145
+79
+245
+162
+103
+250
+176
+132
+203
+161
+131
+91
+92
+89
+43
+57
+62
+81
+73
+62
+135
+94
+64
+173
+106
+60
+188
+112
+56
+183
+110
+59
+155
+100
+63
+106
+82
+65
+51
+62
+63
+91
+92
+89
+133
+120
+107
+48
+58
+59
+95
+78
+64
+146
+97
+64
+118
+86
+65
+56
+64
+60
+101
+100
+92
+245
+212
+186
+253
+212
+188
+146
+135
+124
+48
+58
+59
+118
+86
+65
+183
+110
+59
+173
+106
+60
+95
+78
+64
+43
+57
+62
+186
+157
+134
+250
+197
+158
+251
+192
+154
+250
+197
+158
+250
+200
+166
+172
+150
+134
+70
+79
+77
+48
+58
+59
+89
+75
+66
+135
+94
+64
+163
+104
+61
+183
+110
+59
+183
+110
+59
+173
+106
+60
+146
+97
+64
+95
+78
+64
+56
+64
+60
+55
+66
+67
+150
+125
+114
+236
+186
+153
+251
+192
+154
+249
+189
+146
+249
+189
+146
+251
+192
+154
+195
+157
+134
+51
+62
+63
+76
+70
+64
+139
+96
+61
+125
+90
+64
+65
+67
+64
+76
+78
+76
+234
+168
+124
+249
+159
+103
+247
+150
+84
+243
+141
+78
+247
+143
+74
+247
+150
+84
+249
+159
+103
+250
+176
+132
+250
+197
+158
+255
+215
+190
+207
+178
+158
+84
+85
+82
+48
+58
+59
+89
+75
+66
+146
+97
+64
+173
+106
+60
+183
+110
+59
+183
+110
+59
+163
+104
+61
+118
+86
+65
+62
+63
+61
+58
+69
+70
+63
+74
+74
+81
+73
+62
+227
+126
+50
+227
+126
+50
+224
+123
+55
+234
+126
+45
+135
+94
+64
+58
+69
+70
+251
+192
+154
+245
+169
+119
+249
+146
+83
+247
+130
+53
+238
+116
+34
+235
+107
+16
+243
+101
+2
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+246
+97
+3
+246
+97
+3
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+243
+101
+2
+236
+102
+14
+236
+102
+14
+235
+107
+16
+246
+116
+28
+239
+117
+44
+241
+132
+59
+247
+143
+74
+249
+152
+92
+214
+151
+109
+118
+86
+65
+146
+111
+88
+192
+155
+91
+192
+155
+91
+195
+167
+113
+239
+227
+208
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+255
+238
+227
+216
+194
+154
+192
+155
+91
+192
+155
+91
+192
+155
+91
+146
+111
+88
+162
+125
+96
+250
+176
+132
+245
+169
+119
+247
+165
+111
+249
+159
+103
+246
+156
+93
+247
+150
+84
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+145
+79
+247
+150
+84
+249
+159
+103
+245
+169
+119
+187
+140
+108
+89
+84
+82
+48
+58
+59
+48
+58
+59
+91
+92
+89
+194
+173
+157
+255
+215
+190
+207
+178
+158
+109
+106
+99
+51
+62
+63
+48
+58
+59
+51
+62
+63
+48
+58
+59
+48
+58
+59
+55
+66
+67
+124
+111
+99
+203
+161
+131
+248
+180
+134
+245
+169
+119
+249
+159
+103
+247
+150
+84
+243
+141
+78
+243
+141
+78
+243
+141
+78
+247
+150
+84
+249
+159
+103
+245
+169
+119
+248
+180
+134
+219
+170
+138
+154
+133
+118
+84
+85
+82
+51
+62
+63
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+48
+58
+59
+55
+66
+67
+91
+92
+89
+154
+133
+118
+209
+171
+139
+245
+179
+138
+249
+174
+124
+247
+165
+111
+249
+159
+103
+246
+156
+93
+246
+156
+93
+249
+159
+103
+247
+165
+111
+249
+174
+124
+252
+185
+144
+195
+157
+134
+109
+106
+99
+55
+66
+67
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+51
+62
+63
+109
+106
+99
+207
+178
+158
+255
+215
+190
+217
+187
+166
+91
+92
+89
+51
+62
+63
+48
+58
+59
+76
+78
+76
+172
+150
+134
+253
+212
+188
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+255
+215
+190
+194
+173
+157
+101
+100
+92
+51
+62
+63
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+48
+58
+59
+97
+98
+96
+194
+173
+157
+146
+135
+124
+56
+64
+60
+145
+114
+49
+168
+127
+42
+158
+125
+46
+168
+127
+42
+129
+106
+52
+48
+58
+59
+194
+173
+157
+255
+215
+190
+176
+156
+141
+76
+78
+76
+48
+58
+59
+55
+66
+67
+115
+102
+92
+234
+168
+124
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+245
+179
+138
+209
+171
+139
+144
+125
+110
+76
+78
+76
+48
+58
+59
+48
+58
+59
+51
+62
+63
+51
+62
+63
+48
+58
+59
+48
+58
+59
+58
+69
+70
+101
+100
+92
+154
+133
+118
+219
+170
+138
+252
+185
+144
+248
+180
+134
+249
+174
+124
+245
+169
+119
+249
+174
+124
+250
+176
+132
+230
+173
+136
+124
+111
+99
+55
+66
+67
+43
+57
+62
+58
+69
+70
+137
+127
+115
+245
+212
+186
+245
+212
+186
+161
+144
+134
+70
+79
+77
+43
+57
+62
+51
+62
+63
+51
+62
+63
+48
+58
+59
+43
+57
+62
+84
+85
+82
+154
+133
+118
+240
+181
+138
+249
+174
+124
+247
+165
+111
+249
+152
+92
+243
+141
+78
+241
+138
+68
+242
+133
+67
+241
+138
+68
+241
+145
+79
+246
+156
+93
+247
+165
+111
+250
+176
+132
+219
+170
+138
+144
+125
+110
+77
+85
+81
+43
+57
+62
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+77
+85
+81
+150
+125
+114
+219
+170
+138
+250
+176
+132
+247
+165
+111
+246
+156
+93
+241
+145
+79
+241
+138
+68
+241
+138
+68
+241
+138
+68
+243
+141
+78
+249
+152
+92
+247
+165
+111
+250
+176
+132
+230
+173
+136
+154
+133
+118
+77
+85
+81
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+70
+79
+77
+161
+144
+134
+245
+212
+186
+255
+215
+190
+161
+144
+134
+63
+74
+74
+43
+57
+62
+51
+62
+63
+109
+106
+99
+217
+187
+166
+251
+209
+178
+238
+205
+179
+137
+127
+115
+58
+69
+70
+43
+57
+62
+58
+69
+70
+139
+115
+96
+238
+159
+107
+249
+152
+92
+241
+138
+68
+247
+130
+53
+238
+123
+45
+239
+117
+44
+247
+118
+39
+238
+123
+45
+241
+132
+59
+241
+145
+79
+249
+159
+103
+249
+174
+124
+240
+181
+138
+167
+142
+123
+91
+92
+89
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+63
+74
+74
+137
+127
+115
+234
+204
+183
+255
+215
+190
+146
+135
+124
+63
+74
+74
+43
+57
+62
+51
+62
+63
+115
+102
+92
+236
+186
+153
+251
+192
+154
+251
+192
+154
+236
+186
+153
+133
+120
+107
+43
+57
+62
+48
+58
+59
+48
+58
+59
+55
+66
+67
+158
+130
+108
+248
+180
+134
+250
+176
+132
+249
+174
+124
+249
+174
+124
+250
+176
+132
+252
+185
+144
+239
+182
+144
+154
+133
+118
+84
+85
+82
+43
+57
+62
+48
+58
+59
+48
+58
+59
+51
+62
+63
+48
+58
+59
+43
+57
+62
+70
+79
+77
+133
+120
+107
+219
+170
+138
+245
+179
+138
+250
+176
+132
+245
+169
+119
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+187
+140
+108
+81
+77
+76
+43
+57
+62
+43
+57
+62
+99
+90
+79
+214
+151
+109
+249
+159
+103
+247
+150
+84
+247
+143
+74
+241
+138
+68
+241
+138
+68
+249
+146
+83
+249
+159
+103
+250
+176
+132
+250
+197
+158
+255
+215
+190
+255
+215
+190
+245
+212
+186
+161
+144
+134
+77
+85
+81
+43
+57
+62
+48
+58
+59
+51
+62
+63
+48
+58
+59
+41
+58
+57
+55
+66
+67
+120
+114
+108
+217
+187
+166
+97
+98
+96
+95
+78
+64
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+112
+85
+63
+70
+79
+77
+249
+189
+146
+247
+165
+111
+243
+141
+78
+247
+130
+53
+238
+116
+34
+236
+102
+14
+243
+101
+2
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+247
+165
+111
+249
+174
+124
+250
+176
+132
+245
+179
+138
+252
+185
+144
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+249
+189
+146
+252
+185
+144
+245
+179
+138
+250
+176
+132
+249
+174
+124
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+242
+133
+67
+243
+141
+78
+241
+145
+86
+249
+159
+103
+238
+159
+107
+210
+156
+119
+210
+156
+119
+240
+181
+138
+249
+189
+146
+251
+192
+154
+251
+192
+154
+250
+197
+158
+212
+173
+150
+186
+157
+134
+167
+142
+123
+167
+142
+123
+195
+157
+134
+219
+170
+138
+248
+180
+134
+245
+169
+119
+245
+162
+103
+247
+150
+84
+243
+141
+78
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+138
+68
+247
+150
+84
+245
+162
+103
+245
+169
+119
+250
+176
+132
+239
+182
+144
+219
+170
+138
+186
+157
+134
+167
+142
+123
+167
+142
+123
+172
+150
+134
+195
+157
+134
+219
+170
+138
+239
+182
+144
+248
+180
+134
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+79
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+145
+79
+241
+153
+96
+247
+165
+111
+249
+174
+124
+245
+179
+138
+219
+170
+138
+186
+157
+134
+167
+142
+123
+167
+142
+123
+186
+157
+134
+212
+173
+150
+250
+197
+158
+251
+192
+154
+251
+192
+154
+249
+189
+146
+239
+182
+144
+219
+170
+138
+219
+170
+138
+239
+182
+144
+250
+197
+158
+250
+200
+166
+251
+209
+178
+238
+205
+179
+172
+150
+134
+137
+127
+115
+161
+144
+134
+217
+187
+166
+253
+212
+188
+227
+196
+175
+194
+173
+157
+176
+156
+141
+172
+150
+134
+187
+166
+150
+217
+187
+166
+255
+215
+190
+245
+212
+186
+76
+78
+76
+75
+74
+61
+158
+125
+46
+158
+125
+46
+158
+125
+46
+171
+129
+45
+105
+93
+60
+58
+69
+70
+217
+187
+166
+255
+215
+190
+253
+204
+176
+236
+186
+153
+210
+156
+119
+210
+156
+119
+247
+165
+111
+249
+159
+103
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+145
+79
+247
+150
+84
+241
+153
+96
+245
+162
+103
+245
+169
+119
+248
+180
+134
+239
+182
+144
+209
+171
+139
+186
+157
+134
+167
+142
+123
+167
+142
+123
+178
+146
+122
+195
+157
+134
+230
+173
+136
+239
+182
+144
+250
+176
+132
+245
+169
+119
+247
+165
+111
+249
+159
+103
+241
+153
+96
+249
+152
+92
+249
+152
+92
+241
+153
+96
+245
+162
+103
+247
+165
+111
+210
+156
+119
+210
+156
+119
+230
+173
+136
+249
+189
+146
+249
+189
+146
+251
+192
+154
+250
+197
+158
+236
+186
+153
+203
+161
+131
+167
+142
+123
+167
+142
+123
+178
+146
+122
+203
+161
+131
+240
+181
+138
+249
+174
+124
+247
+165
+111
+241
+153
+96
+243
+141
+78
+242
+133
+67
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+249
+159
+103
+245
+169
+119
+250
+176
+132
+240
+181
+138
+209
+171
+139
+178
+146
+122
+167
+142
+123
+167
+142
+123
+186
+157
+134
+209
+171
+139
+240
+181
+138
+250
+176
+132
+245
+169
+119
+249
+159
+103
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+238
+123
+45
+238
+123
+45
+247
+130
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+247
+165
+111
+250
+176
+132
+240
+181
+138
+203
+161
+131
+178
+146
+122
+167
+142
+123
+167
+142
+123
+195
+157
+134
+236
+186
+153
+251
+192
+154
+251
+192
+154
+249
+189
+146
+249
+189
+146
+230
+173
+136
+203
+161
+131
+219
+170
+138
+245
+179
+138
+245
+179
+138
+245
+179
+138
+245
+179
+138
+248
+180
+134
+234
+168
+124
+214
+151
+109
+214
+151
+109
+245
+162
+103
+241
+145
+86
+241
+138
+68
+238
+123
+53
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+238
+116
+34
+238
+123
+45
+241
+132
+59
+243
+141
+78
+241
+153
+96
+247
+165
+111
+249
+174
+124
+240
+181
+138
+209
+171
+139
+178
+146
+122
+167
+142
+123
+167
+142
+123
+195
+157
+134
+236
+186
+153
+250
+197
+158
+251
+192
+154
+249
+189
+146
+249
+189
+146
+230
+173
+136
+210
+156
+119
+210
+156
+119
+250
+176
+132
+249
+174
+124
+249
+174
+124
+249
+174
+124
+249
+174
+124
+250
+176
+132
+210
+156
+119
+162
+125
+96
+162
+125
+96
+214
+151
+109
+247
+165
+111
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+159
+103
+247
+165
+111
+245
+169
+119
+250
+176
+132
+240
+181
+138
+209
+171
+139
+186
+157
+134
+167
+142
+123
+167
+142
+123
+178
+146
+122
+203
+161
+131
+239
+182
+144
+248
+180
+134
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+145
+86
+241
+145
+86
+247
+150
+84
+241
+153
+96
+245
+162
+103
+238
+159
+107
+204
+141
+99
+214
+151
+109
+241
+153
+96
+249
+152
+92
+243
+141
+78
+242
+133
+67
+241
+132
+59
+241
+132
+59
+241
+138
+68
+241
+145
+79
+245
+162
+103
+248
+180
+134
+212
+173
+150
+146
+135
+124
+137
+127
+115
+176
+156
+141
+234
+204
+183
+253
+212
+188
+217
+187
+166
+187
+166
+150
+172
+150
+134
+176
+156
+141
+194
+173
+157
+234
+204
+183
+255
+215
+190
+194
+173
+157
+43
+57
+62
+139
+96
+61
+234
+126
+45
+224
+123
+55
+227
+126
+50
+227
+126
+50
+89
+75
+66
+101
+100
+92
+245
+179
+138
+245
+162
+103
+241
+138
+68
+238
+123
+45
+236
+108
+29
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+79
+249
+152
+92
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+243
+141
+78
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+132
+59
+238
+123
+53
+239
+117
+44
+238
+116
+34
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+249
+174
+124
+250
+176
+132
+250
+176
+132
+250
+176
+132
+249
+174
+124
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+242
+133
+67
+241
+132
+59
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+241
+132
+59
+242
+133
+67
+243
+141
+78
+249
+152
+92
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+169
+119
+249
+174
+124
+245
+179
+138
+251
+192
+154
+232
+190
+161
+101
+100
+92
+51
+62
+63
+63
+69
+60
+51
+62
+63
+55
+66
+67
+109
+106
+99
+176
+156
+141
+234
+204
+183
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+207
+178
+158
+91
+92
+89
+51
+62
+63
+129
+106
+52
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+75
+74
+61
+91
+92
+89
+245
+212
+186
+250
+200
+166
+252
+185
+144
+249
+174
+124
+247
+165
+111
+241
+153
+96
+241
+145
+79
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+247
+165
+111
+245
+169
+119
+249
+174
+124
+250
+176
+132
+250
+176
+132
+249
+174
+124
+249
+174
+124
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+145
+79
+241
+138
+68
+242
+133
+67
+242
+133
+67
+242
+133
+67
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+241
+153
+96
+245
+162
+103
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+245
+162
+103
+241
+153
+96
+241
+145
+79
+241
+138
+68
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+169
+119
+249
+174
+124
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+162
+103
+241
+153
+96
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+138
+68
+241
+145
+86
+241
+153
+96
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+132
+59
+238
+123
+53
+239
+117
+44
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+79
+241
+153
+96
+245
+162
+103
+247
+165
+111
+245
+169
+119
+245
+169
+119
+249
+174
+124
+245
+169
+119
+245
+169
+119
+245
+169
+119
+245
+169
+119
+247
+165
+111
+247
+165
+111
+245
+162
+103
+245
+162
+103
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+169
+119
+249
+174
+124
+249
+174
+124
+249
+174
+124
+245
+169
+119
+247
+165
+111
+241
+153
+96
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+79
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+242
+133
+67
+241
+145
+86
+247
+165
+111
+210
+156
+119
+63
+74
+74
+62
+63
+61
+69
+69
+61
+48
+58
+59
+63
+74
+74
+133
+120
+107
+194
+173
+157
+245
+212
+186
+255
+215
+190
+255
+215
+190
+255
+215
+190
+245
+212
+186
+176
+156
+141
+55
+66
+67
+76
+70
+64
+212
+120
+56
+227
+126
+50
+224
+123
+55
+234
+125
+52
+194
+112
+58
+56
+64
+60
+154
+133
+118
+250
+176
+132
+241
+153
+96
+242
+133
+67
+239
+117
+44
+236
+108
+29
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+138
+68
+243
+141
+78
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+79
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+132
+59
+242
+133
+67
+241
+138
+68
+243
+141
+78
+243
+141
+78
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+249
+152
+92
+241
+153
+96
+241
+153
+96
+241
+153
+96
+249
+152
+92
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+241
+145
+79
+241
+145
+79
+241
+145
+86
+241
+153
+96
+245
+162
+103
+245
+169
+119
+245
+179
+138
+144
+125
+110
+51
+62
+63
+117
+98
+55
+158
+125
+46
+145
+114
+49
+105
+93
+60
+69
+69
+61
+48
+58
+59
+58
+69
+70
+91
+92
+89
+120
+114
+108
+120
+114
+108
+91
+92
+89
+48
+58
+59
+56
+64
+60
+123
+102
+54
+171
+129
+45
+158
+125
+46
+158
+125
+46
+168
+127
+42
+137
+110
+49
+48
+58
+59
+161
+144
+134
+250
+197
+158
+248
+180
+134
+247
+165
+111
+241
+153
+96
+241
+145
+79
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+249
+152
+92
+241
+153
+96
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+123
+45
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+138
+68
+241
+138
+68
+243
+141
+78
+241
+145
+79
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+243
+141
+78
+242
+133
+67
+241
+132
+59
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+145
+86
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+45
+239
+117
+44
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+238
+123
+45
+241
+132
+59
+242
+133
+67
+243
+141
+78
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+241
+145
+79
+243
+141
+78
+243
+141
+78
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+116
+34
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+238
+123
+45
+238
+123
+53
+242
+133
+67
+241
+138
+68
+241
+145
+79
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+86
+241
+145
+79
+243
+141
+78
+243
+141
+78
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+242
+133
+67
+242
+133
+67
+241
+138
+68
+241
+138
+68
+241
+138
+68
+241
+138
+68
+242
+133
+67
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+138
+68
+243
+141
+78
+241
+145
+86
+241
+145
+86
+241
+153
+96
+241
+153
+96
+241
+145
+86
+241
+145
+86
+243
+141
+78
+241
+138
+68
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+53
+242
+133
+67
+241
+145
+86
+238
+159
+107
+84
+85
+82
+69
+69
+61
+188
+112
+56
+214
+121
+50
+173
+106
+60
+112
+85
+63
+62
+63
+61
+41
+58
+57
+63
+74
+74
+97
+98
+96
+120
+114
+108
+109
+106
+99
+77
+85
+81
+41
+58
+57
+81
+73
+62
+194
+112
+58
+234
+125
+52
+224
+123
+55
+224
+123
+55
+234
+126
+45
+125
+90
+64
+51
+62
+63
+209
+171
+139
+245
+169
+119
+241
+145
+86
+241
+132
+59
+238
+116
+34
+235
+107
+16
+236
+102
+14
+235
+94
+9
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+237
+95
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+138
+68
+241
+145
+86
+238
+159
+107
+234
+168
+124
+84
+85
+82
+83
+78
+61
+171
+129
+45
+158
+125
+46
+168
+127
+42
+168
+127
+42
+158
+125
+46
+129
+106
+52
+100
+89
+56
+83
+78
+61
+75
+74
+61
+69
+69
+61
+83
+78
+61
+105
+93
+60
+152
+119
+47
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+75
+74
+61
+63
+74
+74
+236
+186
+153
+245
+179
+138
+238
+159
+107
+241
+145
+86
+241
+138
+68
+241
+132
+59
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+53
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+53
+238
+123
+53
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+238
+123
+45
+239
+117
+44
+239
+117
+44
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+239
+117
+44
+238
+123
+45
+238
+123
+53
+238
+123
+53
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+241
+132
+59
+238
+123
+53
+238
+123
+45
+239
+117
+44
+238
+116
+34
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+123
+45
+241
+132
+59
+241
+145
+86
+204
+141
+99
+41
+58
+57
+155
+100
+63
+234
+126
+45
+227
+126
+50
+227
+126
+50
+234
+125
+52
+209
+117
+53
+155
+100
+63
+118
+86
+65
+89
+75
+66
+81
+73
+62
+81
+73
+62
+106
+82
+65
+155
+100
+63
+214
+121
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+194
+112
+58
+56
+64
+60
+109
+106
+99
+245
+179
+138
+245
+162
+103
+241
+138
+68
+238
+123
+45
+235
+113
+30
+236
+102
+14
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+123
+45
+238
+123
+53
+241
+138
+68
+241
+145
+86
+238
+159
+107
+89
+84
+82
+75
+74
+61
+168
+127
+42
+168
+127
+42
+158
+125
+46
+158
+125
+46
+161
+127
+40
+168
+127
+42
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+95
+87
+59
+48
+58
+59
+167
+142
+123
+245
+179
+138
+238
+159
+107
+241
+145
+86
+242
+133
+67
+238
+123
+45
+238
+116
+34
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+239
+117
+44
+239
+117
+44
+239
+117
+44
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+113
+30
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+235
+113
+30
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+113
+30
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+238
+116
+34
+235
+113
+30
+236
+108
+29
+236
+108
+29
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+236
+108
+29
+236
+108
+29
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+108
+29
+235
+113
+30
+239
+117
+44
+241
+132
+59
+241
+145
+79
+204
+141
+99
+48
+58
+59
+139
+96
+61
+234
+126
+45
+224
+123
+55
+224
+123
+55
+224
+123
+55
+227
+126
+50
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+126
+45
+234
+126
+45
+227
+126
+50
+224
+123
+55
+224
+123
+55
+234
+125
+52
+214
+121
+50
+81
+73
+62
+58
+69
+70
+219
+170
+138
+245
+169
+119
+241
+145
+86
+241
+132
+59
+239
+117
+44
+236
+108
+29
+236
+102
+14
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+229
+102
+7
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+224
+98
+18
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+229
+102
+7
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+236
+108
+29
+239
+117
+44
+234
+125
+52
+231
+136
+72
+241
+153
+96
+162
+125
+96
+48
+58
+59
+95
+87
+59
+158
+125
+46
+171
+129
+45
+168
+127
+42
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+158
+125
+46
+168
+127
+42
+171
+129
+45
+158
+125
+46
+95
+87
+59
+48
+58
+59
+124
+111
+99
+245
+179
+138
+247
+165
+111
+241
+145
+86
+241
+132
+59
+238
+123
+45
+238
+116
+34
+236
+108
+29
+224
+98
+18
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+230
+97
+5
+230
+97
+5
+235
+94
+9
+230
+97
+5
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+224
+98
+18
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+235
+94
+9
+235
+94
+9
+229
+102
+7
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+235
+107
+16
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+224
+98
+18
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+236
+102
+14
+235
+94
+9
+230
+97
+5
+235
+94
+9
+235
+94
+9
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+235
+94
+9
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+224
+98
+18
+236
+102
+14
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+236
+102
+14
+224
+98
+18
+236
+102
+14
+236
+102
+14
+236
+102
+14
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+236
+102
+14
+236
+102
+14
+224
+98
+18
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+235
+107
+16
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+230
+97
+5
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+235
+94
+9
+230
+97
+5
+235
+94
+9
+236
+102
+14
+236
+102
+14
+236
+102
+14
+229
+102
+7
+230
+97
+5
+229
+102
+7
+224
+98
+18
+236
+108
+29
+238
+116
+34
+238
+123
+53
+243
+141
+78
+241
+153
+96
+99
+90
+79
+56
+64
+60
+155
+100
+63
+234
+126
+45
+234
+126
+45
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+227
+126
+50
+224
+123
+55
+224
+123
+55
+227
+126
+50
+227
+126
+50
+234
+126
+45
+194
+112
+58
+81
+73
+62
+48
+58
+59
+178
+146
+122
+249
+174
+124
+241
+153
+96
+231
+136
+72
+234
+125
+52
+238
+116
+34
+235
+107
+16
+229
+102
+7
+235
+94
+9
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+236
+102
+14
+235
+113
+30
+239
+117
+44
+230
+128
+60
+236
+147
+85
+238
+159
+107
+139
+115
+96
+48
+58
+59
+69
+69
+61
+111
+94
+57
+145
+114
+49
+158
+125
+46
+168
+127
+42
+171
+129
+45
+168
+127
+42
+168
+127
+42
+168
+127
+42
+168
+127
+42
+171
+129
+45
+168
+127
+42
+152
+119
+47
+117
+98
+55
+69
+69
+61
+48
+58
+59
+144
+125
+110
+240
+181
+138
+247
+165
+111
+236
+147
+85
+242
+133
+67
+238
+123
+45
+235
+113
+30
+235
+107
+16
+236
+102
+14
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+230
+97
+5
+229
+102
+7
+235
+107
+16
+235
+113
+30
+238
+123
+45
+242
+133
+67
+241
+153
+96
+214
+151
+109
+99
+90
+79
+48
+58
+59
+95
+78
+64
+155
+100
+63
+209
+117
+53
+227
+126
+50
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+125
+52
+234
+126
+45
+234
+126
+45
+227
+126
+50
+194
+112
+58
+125
+90
+64
+56
+64
+60
+58
+69
+70
+178
+146
+122
+250
+176
+132
+238
+159
+107
+241
+145
+79
+234
+125
+52
+239
+117
+44
+236
+108
+29
+224
+98
+18
+230
+97
+5
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+230
+97
+5
+229
+102
+7
+223
+103
+18
+226
+110
+35
+234
+125
+52
+231
+136
+72
+241
+153
+96
+245
+169
+119
+178
+146
+122
+101
+100
+92
+48
+58
+59
+56
+64
+60
+69
+69
+61
+95
+87
+59
+111
+94
+57
+123
+102
+54
+129
+106
+52
+129
+106
+52
+123
+102
+54
+105
+93
+60
+88
+82
+59
+62
+63
+61
+48
+58
+59
+91
+92
+89
+186
+157
+134
+245
+179
+138
+238
+159
+107
+236
+147
+85
+230
+128
+60
+234
+125
+52
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+230
+97
+5
+224
+98
+18
+236
+108
+29
+239
+117
+44
+230
+123
+57
+243
+141
+78
+238
+159
+107
+234
+168
+124
+158
+130
+108
+76
+78
+76
+41
+58
+57
+62
+63
+61
+95
+78
+64
+125
+90
+64
+146
+97
+64
+163
+104
+61
+173
+106
+60
+163
+104
+61
+155
+100
+63
+125
+90
+64
+95
+78
+64
+56
+64
+60
+43
+57
+62
+124
+111
+99
+209
+171
+139
+234
+168
+124
+238
+159
+107
+241
+145
+79
+230
+128
+60
+239
+117
+44
+236
+108
+29
+236
+102
+14
+229
+102
+7
+230
+97
+5
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+231
+91
+2
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+226
+93
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+230
+97
+5
+224
+98
+18
+236
+108
+29
+226
+110
+35
+230
+123
+57
+231
+136
+72
+241
+153
+96
+238
+159
+107
+240
+181
+138
+203
+161
+131
+150
+125
+114
+101
+100
+92
+76
+78
+76
+55
+66
+67
+48
+58
+59
+48
+58
+59
+48
+58
+59
+48
+58
+59
+58
+69
+70
+84
+85
+82
+124
+111
+99
+178
+146
+122
+240
+181
+138
+234
+168
+124
+238
+159
+107
+236
+147
+85
+230
+128
+60
+234
+125
+52
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+128
+60
+236
+147
+85
+241
+153
+96
+234
+168
+124
+230
+173
+136
+186
+157
+134
+133
+120
+107
+91
+92
+89
+63
+74
+74
+51
+62
+63
+48
+58
+59
+48
+58
+59
+48
+58
+59
+51
+62
+63
+63
+74
+74
+91
+92
+89
+144
+125
+110
+203
+161
+131
+240
+181
+138
+245
+169
+119
+241
+153
+96
+241
+145
+79
+230
+128
+60
+225
+124
+48
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+239
+117
+44
+230
+123
+57
+231
+136
+72
+236
+147
+85
+238
+159
+107
+245
+169
+119
+234
+168
+124
+240
+181
+138
+239
+182
+144
+236
+186
+153
+250
+197
+158
+250
+197
+158
+250
+197
+158
+251
+192
+154
+236
+186
+153
+239
+182
+144
+245
+179
+138
+234
+168
+124
+238
+159
+107
+241
+153
+96
+231
+136
+72
+230
+128
+60
+225
+124
+48
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+230
+97
+5
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+128
+60
+231
+136
+72
+241
+153
+96
+238
+159
+107
+234
+168
+124
+240
+181
+138
+239
+182
+144
+236
+186
+153
+251
+192
+154
+250
+197
+158
+250
+197
+158
+250
+197
+158
+236
+186
+153
+239
+182
+144
+240
+181
+138
+234
+168
+124
+245
+169
+119
+238
+159
+107
+236
+147
+85
+231
+136
+72
+230
+123
+57
+239
+117
+44
+226
+110
+35
+223
+103
+18
+224
+98
+18
+230
+97
+5
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+225
+92
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+128
+60
+231
+136
+72
+236
+147
+85
+241
+153
+96
+238
+159
+107
+238
+159
+107
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+238
+159
+107
+238
+159
+107
+241
+153
+96
+236
+147
+85
+231
+136
+72
+230
+128
+60
+230
+123
+57
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+225
+124
+48
+230
+123
+57
+230
+128
+60
+231
+136
+72
+236
+147
+85
+241
+153
+96
+238
+159
+107
+238
+159
+107
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+234
+168
+124
+238
+159
+107
+238
+159
+107
+241
+153
+96
+236
+147
+85
+231
+136
+72
+230
+128
+60
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+128
+60
+230
+128
+60
+231
+136
+72
+231
+136
+72
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+231
+136
+72
+231
+136
+72
+231
+136
+72
+230
+128
+60
+227
+126
+50
+225
+124
+48
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+230
+123
+57
+230
+128
+60
+231
+136
+72
+231
+136
+72
+231
+136
+72
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+236
+147
+85
+231
+136
+72
+231
+136
+72
+230
+128
+60
+230
+123
+57
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+225
+124
+48
+225
+124
+48
+225
+124
+48
+224
+123
+55
+224
+123
+55
+224
+123
+55
+230
+123
+57
+224
+123
+55
+224
+123
+55
+225
+124
+48
+225
+124
+48
+226
+110
+35
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+225
+124
+48
+225
+124
+48
+224
+123
+55
+230
+123
+57
+230
+123
+57
+230
+123
+57
+230
+123
+57
+230
+123
+57
+225
+124
+48
+225
+124
+48
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+221
+89
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+223
+103
+18
+223
+103
+18
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+226
+110
+35
+223
+103
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+224
+98
+18
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+220
+93
+11
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+218
+87
+5
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+217
+86
+3
+217
+86
+3
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
+214
+84
+0
diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-puppy.diff b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-puppy.diff
new file mode 100644
index 0000000000..c7856731e5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-puppy.diff
@@ -0,0 +1,66 @@
+--- /tmp/board-omap3beagle.c 2009-07-01 01:06:44.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-01 01:06:50.000000000 +0200
+@@ -125,6 +125,13 @@
+ .wires = 8,
+ .gpio_wp = 29,
+ },
++ {
++ .mmc = 2,
++ .wires = 4,
++ .gpio_wp = 141,
++ .gpio_cd = 162,
++ .transceiver = true,
++ },
+ {} /* Terminator */
+ };
+
+@@ -132,6 +139,11 @@
+ .supply = "vmmc",
+ };
+
++static struct regulator_consumer_supply beagle_vmmc2_supply = {
++ .supply = "vmmc",
++};
++
++
+ static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+ };
+@@ -148,6 +160,7 @@
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
++ beagle_vmmc2_supply.dev = mmc[1].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+@@ -209,6 +222,21 @@
+ .consumer_supplies = &beagle_vmmc1_supply,
+ };
+
++/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .min_uV = 2700000,
++ .max_uV = 3150000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
++ | REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
+ /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+ static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+@@ -284,6 +312,7 @@
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
++ .vmmc2 = &beagle_vmmc2,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-zippy.diff b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-zippy.diff
new file mode 100644
index 0000000000..cab479e5d3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/tincantools-zippy.diff
@@ -0,0 +1,103 @@
+--- /tmp/board-omap3beagle.c 2009-08-13 12:35:01.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-08-13 12:44:00.000000000 +0200
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/leds.h>
+ #include <linux/gpio.h>
++#include <linux/irq.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
+
+@@ -54,6 +55,47 @@
+ #define GPMC_CS_SIZE 0x30
+
+ #define NAND_BLOCK_SIZE SZ_128K
++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
++
++#include <mach/mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
++
++static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
++ .turbo_mode = 0,
++ .single_channel = 1, /* 0: slave, 1: master */
++};
++
++static struct spi_board_info omap3beagle_spi_board_info[] __initdata = {
++ {
++ .modalias = "enc28j60",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 20000000,
++ .controller_data = &enc28j60_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_enc28j60_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
++ omap3beagle_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
++ set_irq_type(omap3beagle_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_spi_board_info,
++ ARRAY_SIZE(omap3beagle_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_enc28j60_init(void) { return; }
++#endif
+
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+@@ -318,7 +360,7 @@
+ .vpll2 = &beagle_vpll2,
+ };
+
+-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
++static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+@@ -327,10 +369,24 @@
+ },
+ };
+
++#if defined(CONFIG_RTC_DRV_DS1307) || \
++ defined(CONFIG_RTC_DRV_DS1307_MODULE)
++
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
++ {
++ I2C_BOARD_INFO("ds1307", 0x68),
++ },
++};
++#else
++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+- ARRAY_SIZE(beagle_i2c_boardinfo));
++ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
++ ARRAY_SIZE(beagle_i2c1_boardinfo));
++ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
++ ARRAY_SIZE(beagle_i2c2_boardinfo));
+ /* Bus 3 is attached to the DVI port where devices like the pico DLP
+ * projector don't work reliably with 400kHz */
+ omap_register_i2c_bus(3, 100, NULL, 0);
+@@ -542,6 +598,8 @@
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
++ omap3beagle_enc28j60_init();
++
+ usb_musb_init();
+ usb_ehci_init();
+ omap3beagle_flash_init();
diff --git a/recipes/linux/linux-omap-pm-2.6.29/cache-display-fix.patch b/recipes/linux/linux-omap-pm-2.6.29/cache-display-fix.patch
new file mode 100644
index 0000000000..019fd5acf1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/cache-display-fix.patch
@@ -0,0 +1,238 @@
+On Tue, 2008-07-01 at 06:23 +0100, Dirk Behme wrote:
+> Catalin Marinas wrote:
+> > But, anyway, if you want a patch, Harry is updating it to a recent
+> > kernel.
+>
+> Any news on this? I think there are some people wanting a patch ;)
+
+See below for a preliminary patch updated to 2.6.26-rc8. Note that I
+don't plan to submit it in its current form but clean it up a bit first.
+
+
+Show the cache type of ARMv7 CPUs
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+---
+
+ arch/arm/kernel/setup.c | 137 +++++++++++++++++++++++++++++++++++++++++++++-
+ include/asm-arm/system.h | 18 ++++++
+ 2 files changed, 153 insertions(+), 2 deletions(-)
+
+
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index 5ae0eb2..0cd238d 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -256,6 +256,24 @@ static const char *proc_arch[] = {
+ "?(17)",
+ };
+
++static const char *v7_cache_policy[4] = {
++ "reserved",
++ "AVIVT",
++ "VIPT",
++ "PIPT",
++};
++
++static const char *v7_cache_type[8] = {
++ "none",
++ "instruction only",
++ "data only",
++ "separate instruction and data",
++ "unified",
++ "unknown type",
++ "unknown type",
++ "unknown type",
++};
++
+ #define CACHE_TYPE(x) (((x) >> 25) & 15)
+ #define CACHE_S(x) ((x) & (1 << 24))
+ #define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
+@@ -266,6 +284,22 @@ static const char *proc_arch[] = {
+ #define CACHE_M(y) ((y) & (1 << 2))
+ #define CACHE_LINE(y) ((y) & 3)
+
++#define CACHE_TYPE_V7(x) (((x) >> 14) & 3)
++#define CACHE_UNIFIED(x) ((((x) >> 27) & 7)+1)
++#define CACHE_COHERENT(x) ((((x) >> 24) & 7)+1)
++
++#define CACHE_ID_LEVEL_MASK 7
++#define CACHE_ID_LEVEL_BITS 3
++
++#define CACHE_LINE_V7(v) ((1 << (((v) & 7)+4)))
++#define CACHE_ASSOC_V7(v) ((((v) >> 3) & ((1<<10)-1))+1)
++#define CACHE_SETS_V7(v) ((((v) >> 13) & ((1<<15)-1))+1)
++#define CACHE_SIZE_V7(v) (CACHE_LINE_V7(v)*CACHE_ASSOC_V7(v)*CACHE_SETS_V7(v))
++#define CACHE_WA_V7(v) (((v) & (1<<28)) != 0)
++#define CACHE_RA_V7(v) (((v) & (1<<29)) != 0)
++#define CACHE_WB_V7(v) (((v) & (1<<30)) != 0)
++#define CACHE_WT_V7(v) (((v) & (1<<31)) != 0)
++
+ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
+ {
+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
+@@ -279,11 +313,57 @@ static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
+ CACHE_LINE(cache)));
+ }
+
++static void dump_v7_cache(const char *type, int cpu, unsigned int level)
++{
++ unsigned int cachesize;
++
++ write_extended_cpuid(2,0,0,0,level); /* Set the cache size selection register */
++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */
++ cachesize = read_extended_cpuid(1,0,0,0);
++
++ printk("CPU%u: %s cache: %d bytes, associativity %d, %d byte lines, %d sets,\n supports%s%s%s%s\n",
++ cpu, type,
++ CACHE_SIZE_V7(cachesize),CACHE_ASSOC_V7(cachesize),
++ CACHE_LINE_V7(cachesize),CACHE_SETS_V7(cachesize),
++ CACHE_WA_V7(cachesize) ? " WA" : "",
++ CACHE_RA_V7(cachesize) ? " RA" : "",
++ CACHE_WB_V7(cachesize) ? " WB" : "",
++ CACHE_WT_V7(cachesize) ? " WT" : "");
++}
++
+ static void __init dump_cpu_info(int cpu)
+ {
+ unsigned int info = read_cpuid(CPUID_CACHETYPE);
+
+- if (info != processor_id) {
++ if (info != processor_id && (info & (1 << 31))) {
++ /* ARMv7 style of cache info register */
++ unsigned int id = read_extended_cpuid(1,0,0,1);
++ unsigned int level = 0;
++ printk("CPU%u: L1 I %s cache. Caches unified at level %u, coherent at level %u\n",
++ cpu,
++ v7_cache_policy[CACHE_TYPE_V7(info)],
++ CACHE_UNIFIED(id),
++ CACHE_COHERENT(id));
++
++ while (id & CACHE_ID_LEVEL_MASK) {
++ printk("CPU%u: Level %u cache is %s\n",
++ cpu, (level >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
++
++ if (id & 1) {
++ /* Dump I at this level */
++ dump_v7_cache("I", cpu, level | 1);
++ }
++
++ if (id & (4 | 2)) {
++ /* Dump D or unified at this level */
++ dump_v7_cache((id & 4) ? "unified" : "D", cpu, level);
++ }
++
++ /* Next level out */
++ level += 2;
++ id >>= CACHE_ID_LEVEL_BITS;
++ }
++ } else if (info != processor_id) {
+ printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
+ cache_types[CACHE_TYPE(info)]);
+ if (CACHE_S(info)) {
+@@ -916,6 +996,30 @@ c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
+ CACHE_LINE(cache)));
+ }
+
++static void c_show_v7_cache(struct seq_file *m, const char *type, unsigned int levelselect)
++{
++ unsigned int cachesize;
++ unsigned int level = (levelselect >> 1) + 1;
++
++ write_extended_cpuid(2,0,0,0,levelselect); /* Set the cache size selection register */
++ write_extended_cpuid(0,7,5,4,0); /* Prefetch flush to wait for above */
++ cachesize = read_extended_cpuid(1,0,0,0);
++
++ seq_printf(m, "L%u %s size\t\t: %d bytes\n"
++ "L%u %s assoc\t\t: %d\n"
++ "L%u %s line length\t: %d\n"
++ "L%u %s sets\t\t: %d\n"
++ "L%u %s supports\t\t:%s%s%s%s\n",
++ level, type, CACHE_SIZE_V7(cachesize),
++ level, type, CACHE_ASSOC_V7(cachesize),
++ level, type, CACHE_LINE_V7(cachesize),
++ level, type, CACHE_SETS_V7(cachesize),
++ level, type, CACHE_WA_V7(cachesize) ? " WA" : "",
++ CACHE_RA_V7(cachesize) ? " RA" : "",
++ CACHE_WB_V7(cachesize) ? " WB" : "",
++ CACHE_WT_V7(cachesize) ? " WT" : "");
++}
++
+ static int c_show(struct seq_file *m, void *v)
+ {
+ int i;
+@@ -971,7 +1075,36 @@ static int c_show(struct seq_file *m, void *v)
+
+ {
+ unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
+- if (cache_info != processor_id) {
++ if (cache_info != processor_id && (cache_info & (1<<31))) {
++ /* V7 style of cache info register */
++ unsigned int id = read_extended_cpuid(1,0,0,1);
++ unsigned int levelselect = 0;
++ seq_printf(m, "L1 I cache\t:%s\n"
++ "Cache unification level\t: %u\n"
++ "Cache coherency level\t: %u\n",
++ v7_cache_policy[CACHE_TYPE_V7(cache_info)],
++ CACHE_UNIFIED(id),
++ CACHE_COHERENT(id));
++
++ while (id & CACHE_ID_LEVEL_MASK) {
++ seq_printf(m, "Level %u cache\t\t: %s\n",
++ (levelselect >> 1)+1, v7_cache_type[id & CACHE_ID_LEVEL_MASK]);
++
++ if (id & 1) {
++ /* Dump I at this level */
++ c_show_v7_cache(m, "I", levelselect | 1);
++ }
++
++ if (id & (4 | 2)) {
++ /* Dump D or unified at this level */
++ c_show_v7_cache(m, (id & 4) ? "cache" : "D", levelselect);
++ }
++
++ /* Next level out */
++ levelselect += 2;
++ id >>= CACHE_ID_LEVEL_BITS;
++ }
++ } else if (cache_info != processor_id) {
+ seq_printf(m, "Cache type\t: %s\n"
+ "Cache clean\t: %s\n"
+ "Cache lockdown\t: %s\n"
+diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
+index 514af79..704738e 100644
+--- a/arch/arm/include/asm/system.h
++++ b/arch/arm/include/asm/system.h
+@@ -74,6 +74,24 @@
+ : "cc"); \
+ __val; \
+ })
++#define read_extended_cpuid(op1,op2,op3,op4) \
++ ({ \
++ unsigned int __val; \
++ asm("mrc p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \
++ : "=r" (__val) \
++ : \
++ : "cc"); \
++ __val; \
++ })
++
++#define write_extended_cpuid(op1,op2,op3,op4,v) \
++ ({ \
++ unsigned int __val = v; \
++ asm("mcr p15," __stringify(op1) ",%0,c" __stringify(op2)",c" __stringify(op3)"," __stringify(op4) \
++ : \
++ : "r" (__val) \
++ : "cc"); \
++ })
+ #else
+ extern unsigned int processor_id;
+ #define read_cpuid(reg) (processor_id)
+
+
+--
+Catalin
+
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch
new file mode 100644
index 0000000000..9da374041c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch
@@ -0,0 +1,169 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line
+Date: Wed, 2 Sep 2009 20:19:58 +0300
+Lines: 92
+Approved: news@gmane.org
+Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name>
+References: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1MiqiI-0003K3-An
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 14:20:23 +0000
+Original-Received: by bwz22 with SMTP id 22so788877bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540;
+ Wed, 02 Sep 2009 07:20:06 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT)
+X-Mailer: git-send-email 1.6.4.2
+In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk>
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04
+X-CRM114-Status: UNSURE ( 9.59 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.2 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -1.6 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025>
+
+Optimized version of copy_page() was written with assumption that cache
+line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes.
+
+This patch tries to generalize copy_page() to work with any cache line
+size if cache line size is multiple of 16 and page size is multiple of
+two cache line size.
+
+After this optimization we've got ~25% speedup on OMAP3(tested in
+userspace).
+
+There is test for kernelspace which trigger copy-on-write after fork():
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+ #define BUF_SIZE (10000*4096)
+ #define NFORK 200
+
+ int main(int argc, char **argv)
+ {
+ char *buf = malloc(BUF_SIZE);
+ int i;
+
+ memset(buf, 0, BUF_SIZE);
+
+ for(i = 0; i < NFORK; i++) {
+ if (fork()) {
+ wait(NULL);
+ } else {
+ int j;
+
+ for(j = 0; j < BUF_SIZE; j+= 4096)
+ buf[j] = (j & 0xFF) + 1;
+ break;
+ }
+ }
+
+ free(buf);
+ return 0;
+ }
+
+Before optimization this test takes ~66 seconds, after optimization
+takes ~56 seconds.
+
+Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com>
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/lib/copy_page.S | 16 ++++++++--------
+ 1 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
+index 6ae04db..6ee2f67 100644
+--- a/arch/arm/lib/copy_page.S
++++ b/arch/arm/lib/copy_page.S
+@@ -12,8 +12,9 @@
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+ #include <asm/asm-offsets.h>
++#include <asm/cache.h>
+
+-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 ))
+
+ .text
+ .align 5
+@@ -26,17 +27,16 @@
+ ENTRY(copy_page)
+ stmfd sp!, {r4, lr} @ 2
+ PLD( pld [r1, #0] )
+- PLD( pld [r1, #32] )
++ PLD( pld [r1, #L1_CACHE_BYTES] )
+ mov r2, #COPY_COUNT @ 1
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+-1: PLD( pld [r1, #64] )
+- PLD( pld [r1, #96] )
+-2: stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
+- stmia r0!, {r3, r4, ip, lr} @ 4
+- ldmia r1!, {r3, r4, ip, lr} @ 4+1
++1: PLD( pld [r1, #2 * L1_CACHE_BYTES])
++ PLD( pld [r1, #3 * L1_CACHE_BYTES])
++2:
++ .rept (2 * L1_CACHE_BYTES / 16 - 1)
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
++ .endr
+ subs r2, r2, #1 @ 1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmgtia r1!, {r3, r4, ip, lr} @ 4
+--
+1.6.4.2
diff --git a/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch b/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch
new file mode 100644
index 0000000000..e58d49c7a3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch
@@ -0,0 +1,115 @@
+Path: news.gmane.org!not-for-mail
+From: "Kirill A. Shutemov" <kirill@shutemov.name>
+Newsgroups: gmane.linux.ports.arm.kernel
+Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line
+ size
+Date: Wed, 2 Sep 2009 19:11:52 +0300
+Lines: 39
+Approved: news@gmane.org
+Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name>
+NNTP-Posting-Host: lo.gmane.org
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT)
+X-Complaints-To: usenet@ger.gmane.org
+NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC)
+Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>,
+ "Kirill A. Shutemov" <kirill@shutemov.name>,
+ Siarhei Siamashka <siarhei.siamashka@nokia.com>,
+ Moiseichuk Leonid <leonid.moiseichuk@nokia.com>,
+ Koskinen Aaro <aaro.koskinen@nokia.com>
+To: linux-arm-kernel@lists.infradead.org,
+ linux-kernel@vger.kernel.org
+Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009
+Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
+Envelope-to: linux-arm-kernel@m.gmane.org
+Original-Received: from bombadil.infradead.org ([18.85.46.34])
+ by lo.gmane.org with esmtp (Exim 4.50)
+ id 1Mipeu-0000ZH-G2
+ for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200
+Original-Received: from localhost ([::1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000
+Original-Received: from mail-bw0-f222.google.com ([209.85.218.222])
+ by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
+ id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org;
+ Wed, 02 Sep 2009 13:12:04 +0000
+Original-Received: by bwz22 with SMTP id 22so735896bwz.18
+ for <linux-arm-kernel@lists.infradead.org>;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013;
+ Wed, 02 Sep 2009 06:11:56 -0700 (PDT)
+Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14])
+ by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54
+ (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT)
+X-Mailer: git-send-email 1.6.3.4
+X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) )
+ MR-646709E3
+X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2
+X-CRM114-Status: UNSURE ( 8.83 )
+X-CRM114-Notice: Please train this message.
+X-Spam-Score: -4.6 (----)
+X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary:
+ Content analysis details: (-4.6 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1%
+ [score: 0.0000]
+ -2.0 AWL AWL: From: address is in the auto white-list
+X-BeenThere: linux-arm-kernel@lists.infradead.org
+X-Mailman-Version: 2.1.12
+Precedence: list
+List-Id: <linux-arm-kernel.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
+List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
+List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
+ <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
+Original-Sender: linux-arm-kernel-bounces@lists.infradead.org
+Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
+Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017
+Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017>
+
+Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5.
+It's not true at least for CPUs based on Cortex-A8.
+
+List of CPUs with cache line size != 32 should be expanded later.
+
+Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
+---
+ arch/arm/include/asm/cache.h | 2 +-
+ arch/arm/mm/Kconfig | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
+index feaa75f..2ee7743 100644
+--- a/arch/arm/include/asm/cache.h
++++ b/arch/arm/include/asm/cache.h
+@@ -4,7 +4,7 @@
+ #ifndef __ASMARM_CACHE_H
+ #define __ASMARM_CACHE_H
+
+-#define L1_CACHE_SHIFT 5
++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT)
+ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+ /*
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index 83c025e..3c37d4c 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -771,3 +771,8 @@ config CACHE_XSC3L2
+ select OUTER_CACHE
+ help
+ This option enables the L2 cache on XScale3.
++
++config ARM_L1_CACHE_SHIFT
++ int
++ default 6 if ARCH_OMAP3
++ default 5
+--
+1.6.3.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch
index aeab62f105..ac26554845 100644
--- a/recipes/linux/linux-omap-pm/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch
@@ -1,7 +1,7 @@
From 26abf45ac80be4c54a63fecf1c3c1e1efb416e0a Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 1 Apr 2009 18:27:09 +0300
-Subject: [PATCH] Revert "gro: Fix legacy path napi_complete crash"
+Subject: [PATCH 01/69] Revert "gro: Fix legacy path napi_complete crash"
This reverts commit 303c6a0251852ecbdc5c15e466dcaff5971f7517.
@@ -35,5 +35,5 @@ index e3fe5c7..c1e9dc0 100644
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch
index 5873ae280c..5873ae280c 100644
--- a/recipes/linux/linux-omap-pm/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch
diff --git a/recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
index c3523362c6..4610e28704 100644
--- a/recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch
@@ -1,7 +1,7 @@
From 284deec412f9c6f15c971d8eaf4d0156a51a2f3b Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 10:23:42 +0300
-Subject: [PATCH] DSS2: OMAP2/3 Display Subsystem driver
+Subject: [PATCH 03/69] DSS2: OMAP2/3 Display Subsystem driver
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---
@@ -14446,5 +14446,5 @@ index 0000000..aceed9f
+ display->check_timings = venc_check_timings;
+}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0004-DSS2-OMAP-framebuffer-driver.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0004-DSS2-OMAP-framebuffer-driver.patch
index 09afa7e5be..877bb43c56 100644
--- a/recipes/linux/linux-omap-pm/dss2/0004-DSS2-OMAP-framebuffer-driver.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0004-DSS2-OMAP-framebuffer-driver.patch
@@ -1,7 +1,7 @@
From db9314f01a207e256d545244d3d00dc4ce535280 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 10:25:48 +0300
-Subject: [PATCH] DSS2: OMAP framebuffer driver
+Subject: [PATCH 04/69] DSS2: OMAP framebuffer driver
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---
@@ -3399,5 +3399,5 @@ index b226bdf..96190b2 100644
extern void omapfb_register_panel(struct lcd_panel *panel);
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0005-DSS2-Add-panel-drivers.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0005-DSS2-Add-panel-drivers.patch
index d12586ca2f..c68c89e171 100644
--- a/recipes/linux/linux-omap-pm/dss2/0005-DSS2-Add-panel-drivers.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0005-DSS2-Add-panel-drivers.patch
@@ -1,7 +1,7 @@
From 4cc0368574f587f448231ccd121266bed4bf9729 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 10:29:56 +0300
-Subject: [PATCH] DSS2: Add panel drivers
+Subject: [PATCH 05/69] DSS2: Add panel drivers
- Generic panel
- Samsung LTE430WQ-F0C LCD Panel
@@ -254,7 +254,7 @@ index 0000000..e4bb781
+ .vfp = 4,
+ .vbp = 12-10,
+ },
-+ .recommended_bpp = 16,
++
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS,
+};
+
@@ -392,5 +392,5 @@ index 0000000..1f99150
+module_exit(sharp_ls_panel_drv_exit);
+MODULE_LICENSE("GPL");
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
index 0025f1aa8b..258b0b6531 100644
--- a/recipes/linux/linux-omap-pm/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
@@ -1,7 +1,7 @@
From 18a25382e81c03230e022ca2eb7e0fce24479d6a Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 10:31:57 +0300
-Subject: [PATCH] DSS2: HACK: Add DSS2 support for N800
+Subject: [PATCH 06/69] DSS2: HACK: Add DSS2 support for N800
Works, but it an ugly quick hack.
@@ -1075,5 +1075,5 @@ index 0000000..91d3e37
+MODULE_DESCRIPTION("N800 LCD Driver");
+MODULE_LICENSE("GPL");
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch
index 62d653700e..62d653700e 100644
--- a/recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch
diff --git a/recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch
index 4c8d432dd5..f4cd192bdd 100644
--- a/recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch
@@ -1,7 +1,7 @@
From 4741076cae4f4284e1fff9a03f35475b8455af54 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Wed, 1 Apr 2009 14:36:39 +0200
-Subject: [PATCH] DSS2: Add function to display object to get the backlight level
+Subject: [PATCH 08/69] DSS2: Add function to display object to get the backlight level
This is needed by an upcoming patch that changes the backlight
initialization to use the backlight level set by the bootloader.
@@ -35,5 +35,5 @@ index 6288353..6b702c7 100644
struct device;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0009-DSS2-Add-acx565akm-panel.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch
index 3f55f04460..82a1474056 100644
--- a/recipes/linux/linux-omap-pm/dss2/0009-DSS2-Add-acx565akm-panel.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch
@@ -1,7 +1,7 @@
From 66e16f86d3f4c5b34b37e965c65102b7192371de Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Thu, 2 Apr 2009 11:47:13 +0300
-Subject: [PATCH] DSS2: Add acx565akm panel
+Subject: [PATCH 09/69] DSS2: Add acx565akm panel
Signed-off-by: Imre Deak <imre.deak@nokia.com>
---
@@ -774,5 +774,5 @@ index 0000000..6d3727b
+#endif
+
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch
index c7efc58a05..f994327ec1 100644
--- a/recipes/linux/linux-omap-pm/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch
@@ -1,7 +1,7 @@
From 370510e24ddbf539392ebb6a1e43280965fcb19b Mon Sep 17 00:00:00 2001
From: Vaibhav Hiremath <hvaibhav@ti.com>
Date: Tue, 31 Mar 2009 18:47:32 +0530
-Subject: [PATCH] DSS2: Small VRFB context allocation bug fixed
+Subject: [PATCH 10/69] DSS2: Small VRFB context allocation bug fixed
This is minor bug while requesting and mapping memory for
VRFB space.
@@ -24,5 +24,5 @@ index 852abe5..44febef 100644
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch
index 1a82ed2a22..2dad1d337f 100644
--- a/recipes/linux/linux-omap-pm/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch
@@ -1,7 +1,7 @@
From 370d1f93a32e8fcaeac5c16574417e354af21d08 Mon Sep 17 00:00:00 2001
From: Vaibhav Hiremath <hvaibhav@ti.com>
Date: Tue, 31 Mar 2009 18:38:31 +0530
-Subject: [PATCH] DSS2: Allocated memory for Color Look-up-table
+Subject: [PATCH 11/69] DSS2: Allocated memory for Color Look-up-table
We were not allocating memory for CMAP buffer and due to that
G_CMAP was failing, since it does check for size of CMAP buffer.
@@ -33,5 +33,5 @@ index 44febef..afe40a9 100644
return r;
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0012-DSS2-Fix-DMA-rotation.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0012-DSS2-Fix-DMA-rotation.patch
index 22add6efd2..8e1d139c72 100644
--- a/recipes/linux/linux-omap-pm/dss2/0012-DSS2-Fix-DMA-rotation.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0012-DSS2-Fix-DMA-rotation.patch
@@ -1,7 +1,7 @@
From 9c93bcab724b5935d745604773ed43825efefd87 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 13:47:11 +0300
-Subject: [PATCH] DSS2: Fix DMA rotation
+Subject: [PATCH 12/69] DSS2: Fix DMA rotation
u16 was not a good type for offsets. First, they need to be signed,
and second, 16 bits is not enough.
@@ -61,5 +61,5 @@ index ffb5648..6cea545 100644
if (plane == OMAP_DSS_GFX) {
if (width != out_width || height != out_height)
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch
index 76b8c73630..1abc7a8264 100644
--- a/recipes/linux/linux-omap-pm/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch
@@ -1,7 +1,7 @@
From 360a55ddd309e3a45b227a4a905ae7120dd16169 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 14:21:12 +0300
-Subject: [PATCH] DSS2: Verify that overlay paddr != 0
+Subject: [PATCH 13/69] DSS2: Verify that overlay paddr != 0
---
drivers/video/omap2/dss/dispc.c | 3 +++
@@ -37,5 +37,5 @@ index 968edbe..9209acf 100644
ovl->info = *info;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch
index 3b3fd77a9a..d8aa4eb893 100644
--- a/recipes/linux/linux-omap-pm/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch
@@ -1,7 +1,7 @@
From 832b763db235da8e62f7b6ab02bcb8ad6bcb7a01 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 16:48:41 +0300
-Subject: [PATCH] DSS2: Add function to get DSS logic clock rate
+Subject: [PATCH 14/69] DSS2: Add function to get DSS logic clock rate
---
drivers/video/omap2/dss/dispc.c | 15 +++++++++++++++
@@ -47,5 +47,5 @@ index bac5ece..0be42b6 100644
void dispc_set_pol_freq(struct omap_panel *panel);
void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch
index d6b0cbbb41..a0f2b9f528 100644
--- a/recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch
@@ -1,7 +1,7 @@
From a5c235a6f0094494ae1fc1a1ba4728e0d33dfd3b Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 16:49:27 +0300
-Subject: [PATCH] DSS2: DSI: calculate VP_CLK_RATIO properly
+Subject: [PATCH 15/69] DSS2: DSI: calculate VP_CLK_RATIO properly
---
drivers/video/omap2/dss/dsi.c | 17 +++++++++++------
@@ -64,5 +64,5 @@ index 4442931..aecb89d 100644
r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch
index bca449f169..35d65a996d 100644
--- a/recipes/linux/linux-omap-pm/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch
@@ -1,7 +1,7 @@
From 6b2c9d84c7accdfe1067fcdc8a00e50674aab4bb Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 17:42:26 +0300
-Subject: [PATCH] DSS2: DSI: improve packet len calculation
+Subject: [PATCH 16/69] DSS2: DSI: improve packet len calculation
---
drivers/video/omap2/dss/dsi.c | 21 ++++++++++++++++-----
@@ -54,5 +54,5 @@ index aecb89d..66ac6ea 100644
if (dsi.use_te)
l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch
index 5b68b57da9..e9a5dcc67a 100644
--- a/recipes/linux/linux-omap-pm/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch
@@ -1,7 +1,7 @@
From 85848d329ca3a2d6ee6841cdc11cc5951d187931 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Fri, 3 Apr 2009 19:09:20 +0200
-Subject: [PATCH] DSS2: Disable video planes on sync lost error
+Subject: [PATCH 17/69] DSS2: Disable video planes on sync lost error
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -99,5 +99,5 @@ index 1bc23f7..41734f3 100644
if (errors & DISPC_IRQ_OCP_ERR) {
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch
index 088135c0a8..0261db2bd4 100644
--- a/recipes/linux/linux-omap-pm/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch
@@ -1,7 +1,7 @@
From 63e15ba8d5f95b13d3abf359da718537d769f112 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Tue, 7 Apr 2009 10:01:58 +0300
-Subject: [PATCH] DSS2: check for ovl paddr only when enabling
+Subject: [PATCH 18/69] DSS2: check for ovl paddr only when enabling
It seems Xvideo uses SETUP_PLANE ioctl even when
the fb memory has not been allocated. Sigh.
@@ -36,5 +36,5 @@ index 9209acf..c047206 100644
ovl->info = *info;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
index daa95ca50d..6569c71471 100644
--- a/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
@@ -1,7 +1,7 @@
From 67f3fc050ab4e2006d5b7ec6ec341896627181ab Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 6 Apr 2009 17:32:04 +0200
-Subject: [PATCH] DSS2: Check fclk limits when configuring video planes
+Subject: [PATCH 19/69] DSS2: Check fclk limits when configuring video planes
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -179,5 +179,5 @@ index 41734f3..61861d8 100644
_dispc_set_vid_color_conv(plane, cconv);
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch
index b3248527e8..c6971ea452 100644
--- a/recipes/linux/linux-omap-pm/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch
@@ -1,7 +1,7 @@
From 9f8f1613253656f155b3844c8255a560f86e0acd Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 6 Apr 2009 17:32:05 +0200
-Subject: [PATCH] DSS2: Check scaling limits against proper values
+Subject: [PATCH 20/69] DSS2: Check scaling limits against proper values
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -75,5 +75,5 @@ index 61861d8..ae7be3d 100644
_dispc_set_color_mode(plane, color_mode);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0021-DSS2-Add-venc-register-dump.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0021-DSS2-Add-venc-register-dump.patch
index 31ff180228..44f126e7a4 100644
--- a/recipes/linux/linux-omap-pm/dss2/0021-DSS2-Add-venc-register-dump.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0021-DSS2-Add-venc-register-dump.patch
@@ -1,7 +1,7 @@
From c5e71be877e71c7df329205307e830f158c403bf Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 6 Apr 2009 17:32:06 +0200
-Subject: [PATCH] DSS2: Add venc register dump
+Subject: [PATCH 21/69] DSS2: Add venc register dump
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -92,5 +92,5 @@ index aceed9f..b655df4 100644
+#undef DUMPREG
+}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0022-DSS2-FB-remove-unused-var-warning.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0022-DSS2-FB-remove-unused-var-warning.patch
index d4fb327c76..207a85f115 100644
--- a/recipes/linux/linux-omap-pm/dss2/0022-DSS2-FB-remove-unused-var-warning.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0022-DSS2-FB-remove-unused-var-warning.patch
@@ -1,7 +1,7 @@
From facfd479bb6efad76eec1e74048cb7a31da7287d Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Mon, 6 Apr 2009 22:26:04 +0200
-Subject: [PATCH] DSS2: FB: remove unused var warning
+Subject: [PATCH 22/69] DSS2: FB: remove unused var warning
Signed-off-by: Imre Deak <imre.deak@nokia.com>
---
@@ -23,5 +23,5 @@ index afe40a9..12ce0c3 100644
omap_vrfb_adjust_size(&w, &h, bytespp);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch
index 6492905530..45045c4b4b 100644
--- a/recipes/linux/linux-omap-pm/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch
@@ -1,7 +1,7 @@
From c02b843c2732bc7b15a3e35b5dd715d68225bbd1 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Wed, 8 Apr 2009 12:51:46 +0200
-Subject: [PATCH] DSS2: pass the default FB color format through board info
+Subject: [PATCH 23/69] DSS2: pass the default FB color format through board info
Add a field to the FB memory region platform data, so that board
init code can pass a default color format to the driver. Set this
@@ -210,5 +210,5 @@ index 96190b2..7a34f22 100644
unsigned map:1; /* kernel mapped by the driver */
};
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch
index 559e49f40a..1a68d9425a 100644
--- a/recipes/linux/linux-omap-pm/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch
@@ -1,7 +1,7 @@
From 2710416c43572652cb5355a5eaf68038c95659e8 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 9 Apr 2009 12:10:46 +0300
-Subject: [PATCH] DSS2: Beagle: Use gpio_set_value
+Subject: [PATCH 24/69] DSS2: Beagle: Use gpio_set_value
---
arch/arm/mach-omap2/board-omap3beagle.c | 10 +++++++---
@@ -44,5 +44,5 @@ index b67e7a5..8c1961d 100644
static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch
index e81b1331bb..7f889d95d8 100644
--- a/recipes/linux/linux-omap-pm/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch
@@ -1,7 +1,7 @@
From 990f3160d33361c135ee72e91f202e05a8c378fc Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Mon, 13 Apr 2009 18:50:24 +0530
-Subject: [PATCH] DSS2: VRFB: Macro for calculating base address of the VRFB context was faulty
+Subject: [PATCH 25/69] DSS2: VRFB: Macro for calculating base address of the VRFB context was faulty
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
---
@@ -24,5 +24,5 @@ index 7e0f8fc..d68065f 100644
#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch
index 6ee3908d10..f5c249e045 100644
--- a/recipes/linux/linux-omap-pm/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch
@@ -1,7 +1,7 @@
From a1e8018c0806a1a0579eda4b93b7d6764a2ff643 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 15 Apr 2009 14:06:54 +0300
-Subject: [PATCH] DSS2: DSI: sidlemode to noidle while sending frame
+Subject: [PATCH 26/69] DSS2: DSI: sidlemode to noidle while sending frame
DISPC interrupts are not wake-up capable. Smart-idle in DISPC_SIDLEMODE
causes DSS interface to go to idle at the end of the frame, and the
@@ -74,5 +74,5 @@ index 0be42b6..d0917a8 100644
void dispc_lcd_enable_signal(bool enable);
void dispc_pck_free_enable(bool enable);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch
index b56e32a11c..5265ae6b0a 100644
--- a/recipes/linux/linux-omap-pm/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch
@@ -1,7 +1,7 @@
From 77e848eeba461e9b55b09d39fd0d640caea13e19 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Thu, 9 Apr 2009 12:09:44 +0530
-Subject: [PATCH] DSS2: VRFB rotation and mirroring implemented.
+Subject: [PATCH 27/69] DSS2: VRFB rotation and mirroring implemented.
DSS2 modified to accept the rotation_type input
to get the dma or VRFB rotation.
@@ -320,5 +320,5 @@ index b0fee80..8ca0bbb 100644
ovl->info.mirror);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch
index 6400da3c24..178349ed2a 100644
--- a/recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch
@@ -1,7 +1,7 @@
From c09f1a0642fd58a1b081594ea36dfd1bf71aec52 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Thu, 9 Apr 2009 12:13:07 +0530
-Subject: [PATCH] DSS2: OMAPFB: Added support for the YUV VRFB rotation and mirroring.
+Subject: [PATCH 28/69] DSS2: OMAPFB: Added support for the YUV VRFB rotation and mirroring.
DSS2 now requires roatation_type to be specified by driver.
Added support for that.
@@ -232,5 +232,5 @@ index 2607def..43f6922 100644
bool mirror;
};
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch
index 072978670b..e9f25dfef1 100644
--- a/recipes/linux/linux-omap-pm/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch
@@ -1,7 +1,7 @@
From a8a37babe4856170f4cba86c425a8f21975d9e9e Mon Sep 17 00:00:00 2001
From: Tim Yamin <plasm@roo.me.uk>
Date: Mon, 13 Apr 2009 13:57:42 -0700
-Subject: [PATCH] DSS2: OMAPFB: Set line_length correctly for YUV with VRFB.
+Subject: [PATCH 29/69] DSS2: OMAPFB: Set line_length correctly for YUV with VRFB.
Signed-off-by: Tim Yamin <plasm@roo.me.uk>
---
@@ -57,5 +57,5 @@ index 57f5900..cd63740 100644
ovl->get_overlay_info(ovl, &info);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch
index 7e2bb48938..63b3594ef5 100644
--- a/recipes/linux/linux-omap-pm/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch
@@ -1,7 +1,7 @@
From bda19b9359d9dc60f8b0beb5685e173e236ee30f Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Wed, 15 Apr 2009 17:05:18 +0530
-Subject: [PATCH] DSS2: dispc_get_trans_key was returning wrong key type
+Subject: [PATCH 30/69] DSS2: dispc_get_trans_key was returning wrong key type
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
---
@@ -25,5 +25,5 @@ index 23a8155..076d3d4 100644
BUG();
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch
index ae777ed04e..684857c15f 100644
--- a/recipes/linux/linux-omap-pm/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch
@@ -1,7 +1,7 @@
From 30c40f5e6b1794430f678bf23d3319354321cab7 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Tue, 14 Apr 2009 14:50:11 +0200
-Subject: [PATCH] DSS2: do bootmem reserve for exclusive access
+Subject: [PATCH 31/69] DSS2: do bootmem reserve for exclusive access
BOOTMEM_DEFAULT would allow multiple reservations for the same location,
we need to reserve the region for our exclusive use. Also check if the
@@ -29,5 +29,5 @@ index f24a110..520f260 100644
if (size > sdram_size) {
printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch
index 4959a760b1..df3a7a9dd9 100644
--- a/recipes/linux/linux-omap-pm/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch
@@ -1,7 +1,7 @@
From ed7a9223f6785be03951c55f3b0695b0d5635c80 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Thu, 9 Apr 2009 15:04:44 +0200
-Subject: [PATCH] DSS2: Fix DISPC_VID_FIR value for omap34xx
+Subject: [PATCH 32/69] DSS2: Fix DISPC_VID_FIR value for omap34xx
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -31,5 +31,5 @@ index 076d3d4..b8a3329 100644
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0033-DSS2-Prefer-3-tap-filter.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0033-DSS2-Prefer-3-tap-filter.patch
index f643ca64f3..6457a5b94a 100644
--- a/recipes/linux/linux-omap-pm/dss2/0033-DSS2-Prefer-3-tap-filter.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0033-DSS2-Prefer-3-tap-filter.patch
@@ -1,7 +1,7 @@
From 5390230ed12585a79683733209db34e9130b8e3b Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Thu, 9 Apr 2009 15:04:43 +0200
-Subject: [PATCH] DSS2: Prefer 3-tap filter
+Subject: [PATCH 33/69] DSS2: Prefer 3-tap filter
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -78,5 +78,5 @@ index b8a3329..b631dd8 100644
DSSDBG("required fclk rate = %lu Hz\n", fclk);
DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch
index fdfc25fb47..dd01886406 100644
--- a/recipes/linux/linux-omap-pm/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch
@@ -1,7 +1,7 @@
From 946eb774e95cdc2f2fa5cdc24aa69229f82814b8 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 16 Apr 2009 17:56:00 +0300
-Subject: [PATCH] DSS2: VRAM: improve omap_vram_add_region()
+Subject: [PATCH 34/69] DSS2: VRAM: improve omap_vram_add_region()
Combine postponed and non-posponed versions of omap_vram_add_region.
Make the func non-static, so it can be called from board files.
@@ -131,5 +131,5 @@ index 520f260..8e9fe77 100644
if (reserved)
pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch
index b7b395458f..6b29d50dc0 100644
--- a/recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch
@@ -1,7 +1,7 @@
From f825cafd5ee5c600218740507f85594c825b0c00 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Thu, 16 Apr 2009 18:47:49 +0530
-Subject: [PATCH] DSS2: Added the function pointer for getting default color.
+Subject: [PATCH 35/69] DSS2: Added the function pointer for getting default color.
V4L2 Framework has a CID for getting/setting default color.
So added the function pointer for doing same.
@@ -62,5 +62,5 @@ index 8ca0bbb..12cf7b0 100644
dss_overlay_setup_dispc_manager(mgr);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch
index c6e9f16b3a..ace5079234 100644
--- a/recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch
@@ -1,7 +1,7 @@
From 6c56dc10226c84f41917ac2117b0e654fa080d40 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Thu, 16 Apr 2009 19:00:11 +0530
-Subject: [PATCH] DSS2: Added support for setting and querying alpha blending.
+Subject: [PATCH 36/69] DSS2: Added support for setting and querying alpha blending.
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
---
@@ -114,5 +114,5 @@ index 12cf7b0..90acd28 100644
mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch
index fc62b09512..e7f43ad83d 100644
--- a/recipes/linux/linux-omap-pm/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0037-DSS2-Added-support-for-querying-color-keying.patch
@@ -1,7 +1,7 @@
From 2c9edd6af31a812a9487dd8bc12322e105a29f44 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Fri, 17 Apr 2009 09:42:36 +0530
-Subject: [PATCH] DSS2: Added support for querying color keying.
+Subject: [PATCH 37/69] DSS2: Added support for querying color keying.
V4L2 Framework has a ioctl for getting/setting color keying.
So added the function manager pointers for doing same.
@@ -146,5 +146,5 @@ index 90acd28..e0501c4 100644
&omap_dss_mgr_enable_alpha_blending;
mgr->get_alpha_blending_status =
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch
index 65cb113574..096c976a70 100644
--- a/recipes/linux/linux-omap-pm/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch
@@ -1,7 +1,7 @@
From 9e8877f0e5b17d3ddd101d6a63aa86fdb14d35d5 Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Fri, 17 Apr 2009 09:51:25 +0530
-Subject: [PATCH] DSS2:OMAPFB: Some color keying pointerd renamed in DSS2. Replicated in FB
+Subject: [PATCH 38/69] DSS2:OMAPFB: Some color keying pointerd renamed in DSS2. Replicated in FB
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
---
@@ -52,5 +52,5 @@ index 7f18d2a..79d8916 100644
r = -ENODEV;
goto err;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch
index af8c2cd09b..d731b78008 100644
--- a/recipes/linux/linux-omap-pm/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch
@@ -1,7 +1,7 @@
From 6f1f0c7b19ecb468824b79f9d181ef0da41b7d7d Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Fri, 17 Apr 2009 13:58:21 +0530
-Subject: [PATCH] DSS2: Add sysfs entry to for the alpha blending support.
+Subject: [PATCH 39/69] DSS2: Add sysfs entry to for the alpha blending support.
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
---
@@ -55,5 +55,5 @@ index e0501c4..7965a84 100644
};
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch
index 66be75f3f7..471a2a7f6c 100644
--- a/recipes/linux/linux-omap-pm/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch
@@ -1,7 +1,7 @@
From a5129f272a48aa22629137c9c31e60eddb8c3f5d Mon Sep 17 00:00:00 2001
From: Hardik Shah <hardik.shah@ti.com>
Date: Fri, 17 Apr 2009 14:24:46 +0530
-Subject: [PATCH] DSS2: Provided proper exclusion for destination color keying and alpha blending.
+Subject: [PATCH 40/69] DSS2: Provided proper exclusion for destination color keying and alpha blending.
OMAP does not support destination color key and alpha blending
simultaneously. So this patch does not allow the user
@@ -93,5 +93,5 @@ index 7965a84..108489c 100644
return size;
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch
index 6785ade279..2c90c0cc06 100644
--- a/recipes/linux/linux-omap-pm/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch
@@ -1,7 +1,7 @@
From 9bcac9b9e678f476c83b5679b1215b6bc946130a Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 20 Apr 2009 16:26:18 +0200
-Subject: [PATCH] DSS2: Disable vertical offset with fieldmode
+Subject: [PATCH 41/69] DSS2: Disable vertical offset with fieldmode
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -67,5 +67,5 @@ index 7e551c2..f15614b 100644
_dispc_set_vid_color_conv(plane, cconv);
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch
index 5264911b41..7e2e44d809 100644
--- a/recipes/linux/linux-omap-pm/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch
@@ -1,7 +1,7 @@
From 9c6de0fed6e8a598d026d348533fdf731b737d55 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 20 Apr 2009 16:26:19 +0200
-Subject: [PATCH] DSS2: Don't enable fieldmode automatically
+Subject: [PATCH 42/69] DSS2: Don't enable fieldmode automatically
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -30,5 +30,5 @@ index f15614b..1c036c1 100644
if (ilace) {
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch
index 76e37817c4..2e09335611 100644
--- a/recipes/linux/linux-omap-pm/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch
@@ -1,7 +1,7 @@
From 35e88797e93b107ba602dee1e2ac8ea761dccd4b Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
Date: Mon, 20 Apr 2009 16:26:20 +0200
-Subject: [PATCH] DSS2: Swap field 0 and field 1 registers
+Subject: [PATCH 43/69] DSS2: Swap field 0 and field 1 registers
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
@@ -166,5 +166,5 @@ index 1c036c1..9bab6cf 100644
(fieldmode ? 1 : 0),
ps);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch
index 32def9e8d5..19d24c3a07 100644
--- a/recipes/linux/linux-omap-pm/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch
@@ -1,7 +1,7 @@
From a9b3500bd14609750a2337e866e1df62627c1bac Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Mon, 20 Apr 2009 14:55:33 +0200
-Subject: [PATCH] DSS2: add sysfs entry for seting the rotate type
+Subject: [PATCH 44/69] DSS2: add sysfs entry for seting the rotate type
This can help in utilizing VRAM memory better. Since with VRFB rotation
we waste a lot of physical memory due to the VRFB HW design, provide the
@@ -72,5 +72,5 @@ index 2c88718..4e3da42 100644
__ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
__ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0045-DSS2-Fixed-line-endings-from-to.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0045-DSS2-Fixed-line-endings-from-to.patch
index 9382469850..3206306cc7 100644
--- a/recipes/linux/linux-omap-pm/dss2/0045-DSS2-Fixed-line-endings-from-to.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0045-DSS2-Fixed-line-endings-from-to.patch
@@ -1,7 +1,7 @@
From b0e081456a9b094109c04467d041ff693843ca47 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Tue, 21 Apr 2009 09:25:16 +0300
-Subject: [PATCH] DSS2: Fixed line endings from , to ;
+Subject: [PATCH 45/69] DSS2: Fixed line endings from , to ;
---
drivers/video/omap2/dss/manager.c | 18 +++++++++---------
@@ -44,5 +44,5 @@ index 108489c..bf059e0 100644
dss_overlay_setup_dispc_manager(mgr);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch
index 4ae5fbdd9a..301db79267 100644
--- a/recipes/linux/linux-omap-pm/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch
@@ -1,7 +1,7 @@
From 0f88992b2681aed4f31dc7dd3926b357bbc95154 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Tue, 21 Apr 2009 10:11:55 +0300
-Subject: [PATCH] DSS2: DSI: decrease sync timeout from 60s to 2s
+Subject: [PATCH 46/69] DSS2: DSI: decrease sync timeout from 60s to 2s
The framedone-problem should be ok now, so we shouldn't get long waits.
---
@@ -22,5 +22,5 @@ index 50af925..d59ad38 100644
DSSDBGF("");
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch
index 0b0f104b30..fbc30b8858 100644
--- a/recipes/linux/linux-omap-pm/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch
@@ -1,7 +1,7 @@
From 7ddd5eaa7bc345c3719d613a46a95b7e8052ad2c Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Tue, 21 Apr 2009 15:18:36 +0200
-Subject: [PATCH] DSS2: fix return value for rotate_type sysfs function
+Subject: [PATCH 47/69] DSS2: fix return value for rotate_type sysfs function
Signed-off-by: Imre Deak <imre.deak@nokia.com>
---
@@ -40,5 +40,5 @@ index 4e3da42..13028ae 100644
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch
index cc6663fa21..1097fedabf 100644
--- a/recipes/linux/linux-omap-pm/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch
@@ -1,7 +1,7 @@
From e34564db95627ad20e918b240c45e2bd5555f7e8 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 22 Apr 2009 10:06:08 +0300
-Subject: [PATCH] OMAP2/3: DMA: implement trans copy and const fill
+Subject: [PATCH 48/69] OMAP2/3: DMA: implement trans copy and const fill
Implement transparent copy and constant fill features for OMAP2/3.
@@ -119,5 +119,5 @@ index 224b077..4e34f47 100644
/*----------------------------------------------------------------------------*/
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch
index e9fc76ce15..d9901f95d9 100644
--- a/recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch
@@ -1,7 +1,7 @@
From 02034cc79f69512a6037f03ad1243c28f59fdd8a Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 22 Apr 2009 10:25:20 +0300
-Subject: [PATCH] DSS2: VRAM: clear allocated area with DMA
+Subject: [PATCH 49/69] DSS2: VRAM: clear allocated area with DMA
Use DMA constant fill feature to clear VRAM area when
someone allocates it.
@@ -97,5 +97,5 @@ index 8e9fe77..90276ac 100644
}
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch
index 8c5edd0c3d..4a0a078bc7 100644
--- a/recipes/linux/linux-omap-pm/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch
@@ -1,7 +1,7 @@
From 07482193cccdfe9ede1f47d72790dfbe54343505 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 22 Apr 2009 10:26:06 +0300
-Subject: [PATCH] DSS2: OMAPFB: remove fb clearing code
+Subject: [PATCH 50/69] DSS2: OMAPFB: remove fb clearing code
VRAM manager does the clearing now when the area is allocated.
---
@@ -49,5 +49,5 @@ index cd63740..76e7c6c 100644
rg->paddr = paddr;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch
index 93ff3205d3..739d3cd1a6 100644
--- a/recipes/linux/linux-omap-pm/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch
@@ -1,7 +1,7 @@
From b47aef28536f3c276d232c41cd3084c69389dca4 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Wed, 22 Apr 2009 14:11:52 +0300
-Subject: [PATCH] DSS2: VRAM: use debugfs, not procfs
+Subject: [PATCH 51/69] DSS2: VRAM: use debugfs, not procfs
---
arch/arm/plat-omap/vram.c | 103 +++++++++++++++------------------------------
@@ -166,5 +166,5 @@ index 90276ac..e847579 100644
return 0;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch
index b8f89b6239..a28a96b23b 100644
--- a/recipes/linux/linux-omap-pm/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch
@@ -1,7 +1,7 @@
From 635fa66abe6e502c9b78b1dc66757bf67fd163e1 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@nokia.com>
Date: Wed, 22 Apr 2009 14:40:48 +0200
-Subject: [PATCH] DSS2: VRAM: fix section mismatch warning
+Subject: [PATCH 52/69] DSS2: VRAM: fix section mismatch warning
postponed_regions are accessed from the non __init
omap_vram_add_region().
@@ -30,5 +30,5 @@ index e847579..b126a64 100644
struct vram_alloc {
struct list_head list;
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch
index f591fb700a..38d162d024 100644
--- a/recipes/linux/linux-omap-pm/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch
@@ -1,7 +1,7 @@
From c7ce3c5e9f7e28900b8ea9c3e1afe41dcdc0863d Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 23 Apr 2009 10:46:53 +0300
-Subject: [PATCH] DSS2: disable LCD & DIGIT before resetting DSS
+Subject: [PATCH 53/69] DSS2: disable LCD & DIGIT before resetting DSS
This seems to fix the synclost problem that we get, if the bootloader
starts the DSS and the kernel resets it.
@@ -37,5 +37,5 @@ index adc1f34..aab9758 100644
/* autoidle */
REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
--
-1.5.6.5
+1.6.2.4
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0054-DSS2-DSI-more-error-handling.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0054-DSS2-DSI-more-error-handling.patch
new file mode 100644
index 0000000000..5f4f155452
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0054-DSS2-DSI-more-error-handling.patch
@@ -0,0 +1,85 @@
+From 3b27a3c4f6b84e46c84509f610dfe1456c0d72d3 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 27 Apr 2009 11:06:16 +0300
+Subject: [PATCH 54/69] DSS2: DSI: more error handling
+
+---
+ drivers/video/omap2/dss/dsi.c | 27 +++++++++++++++++++++++++++
+ 1 files changed, 27 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index d59ad38..d8df353 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -289,6 +289,8 @@ static struct
+
+ bool autoupdate_setup;
+
++ u32 errors;
++ spinlock_t errors_lock;
+ #ifdef DEBUG
+ ktime_t perf_setup_time;
+ ktime_t perf_start_time;
+@@ -541,6 +543,9 @@ void dsi_irq_handler(void)
+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
+ DSSERR("DSI error, irqstatus %x\n", irqstatus);
+ print_irq_status(irqstatus);
++ spin_lock(&dsi.errors_lock);
++ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
++ spin_unlock(&dsi.errors_lock);
+ } else if (debug_irq) {
+ print_irq_status(irqstatus);
+ }
+@@ -616,6 +621,17 @@ static void _dsi_initialize_irq(void)
+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
+ }
+
++static u32 dsi_get_errors(void)
++{
++ unsigned long flags;
++ u32 e;
++ spin_lock_irqsave(&dsi.errors_lock, flags);
++ e = dsi.errors;
++ dsi.errors = 0;
++ spin_unlock_irqrestore(&dsi.errors_lock, flags);
++ return e;
++}
++
+ static void dsi_vc_enable_bta_irq(int channel)
+ {
+ u32 l;
+@@ -1807,6 +1823,7 @@ static int dsi_vc_send_bta(int channel)
+ static int dsi_vc_send_bta_sync(int channel)
+ {
+ int r = 0;
++ u32 err;
+
+ init_completion(&dsi.bta_completion);
+
+@@ -1822,6 +1839,13 @@ static int dsi_vc_send_bta_sync(int channel)
+ r = -EIO;
+ goto err;
+ }
++
++ err = dsi_get_errors();
++ if (err) {
++ DSSERR("Error while sending BTA: %x\n", err);
++ r = -EIO;
++ goto err;
++ }
+ err:
+ dsi_vc_disable_bta_irq(channel);
+
+@@ -3720,6 +3744,9 @@ int dsi_init(void)
+ {
+ u32 rev;
+
++ spin_lock_init(&dsi.errors_lock);
++ dsi.errors = 0;
++
+ spin_lock_init(&dsi.cmd_lock);
+ dsi.cmd_fifo = kfifo_alloc(
+ DSI_CMD_FIFO_LEN * sizeof(struct dsi_cmd_item),
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0055-DSS2-Added-global-alpha-support.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0055-DSS2-Added-global-alpha-support.patch
new file mode 100644
index 0000000000..c545b648cc
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0055-DSS2-Added-global-alpha-support.patch
@@ -0,0 +1,230 @@
+From c8588370442424ac31e2392b07891615629eb999 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 24 Apr 2009 15:29:06 +0530
+Subject: [PATCH 55/69] DSS2: Added global alpha support.
+
+global_alpha sysfs entry for video1 plane will always show 255 as
+it does not support global_alpha.
+Initliazied the global alpha field for all the overlays
+to 255 (fully opaque).
+Documentation also updated.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ Documentation/arm/OMAP/DSS | 1 +
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/dispc.c | 25 ++++++++++++++++---
+ drivers/video/omap2/dss/dss.h | 3 +-
+ drivers/video/omap2/dss/manager.c | 3 +-
+ drivers/video/omap2/dss/overlay.c | 37 +++++++++++++++++++++++++++++
+ 6 files changed, 64 insertions(+), 6 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 9e902a2..249e1a3 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -133,6 +133,7 @@ name
+ output_size width,height
+ position x,y
+ screen_width width
++global_alpha global alpha 0-255 0=transparent 255=opaque
+
+ /sys/devices/platform/omapdss/manager? directory:
+ display Destination display
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index d0b4c83..45b16ca 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -363,6 +363,7 @@ struct omap_overlay_info {
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
++ u8 global_alpha;
+ };
+
+ enum omap_overlay_caps {
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 9bab6cf..b6a39f5 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -778,6 +778,17 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+ dispc_write_reg(vsi_reg[plane-1], val);
+ }
+
++static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
++{
++
++ BUG_ON(plane == OMAP_DSS_VIDEO1);
++
++ if (plane == OMAP_DSS_GFX)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
++ else if (plane == OMAP_DSS_VIDEO2)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
++}
++
+ static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+ {
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
+@@ -1444,7 +1455,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, int mirror)
++ u8 rotation, int mirror,
++ u8 global_alpha)
+ {
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+ bool five_taps = 0;
+@@ -1592,6 +1604,9 @@ static int _dispc_setup_plane(enum omap_plane plane,
+
+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+
++ if (plane != OMAP_DSS_VIDEO1)
++ _dispc_setup_global_alpha(plane, global_alpha);
++
+ return 0;
+ }
+
+@@ -3011,7 +3026,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, bool mirror)
++ u8 rotation, bool mirror, u8 global_alpha)
+ {
+ int r = 0;
+
+@@ -3032,7 +3047,8 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+- rotation, mirror);
++ rotation, mirror,
++ global_alpha);
+
+ enable_clocks(0);
+
+@@ -3247,7 +3263,8 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ pi->color_mode, 0,
+ pi->rotation_type,
+ pi->rotation,
+- pi->mirror);
++ pi->mirror,
++ pi->global_alpha);
+
+ dispc_enable_plane(ovl->id, 1);
+ }
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 1d01ff6..20cef0a 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -273,7 +273,8 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, bool mirror);
++ u8 rotation, bool mirror,
++ u8 global_alpha);
+
+ void dispc_go(enum omap_channel channel);
+ void dispc_enable_lcd_out(bool enable);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index bf059e0..1e6cd8d 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -464,7 +464,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ ilace,
+ ovl->info.rotation_type,
+ ovl->info.rotation,
+- ovl->info.mirror);
++ ovl->info.mirror,
++ ovl->info.global_alpha);
+
+ if (r) {
+ DSSERR("dispc_setup_plane failed for ovl %d\n",
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index c047206..035a57a 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -194,6 +194,37 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+ return size;
+ }
+
++static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ ovl->info.global_alpha);
++}
++
++static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ /* Video1 plane does not support global alpha
++ * to always make it 255 completely opaque
++ */
++ if (ovl->id == OMAP_DSS_VIDEO1)
++ info.global_alpha = 255;
++ else
++ info.global_alpha = simple_strtoul(buf, NULL, 10);
++
++ if ((r = ovl->set_overlay_info(ovl, &info)))
++ return r;
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
+ struct overlay_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay *, char *);
+@@ -215,6 +246,8 @@ static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+ overlay_output_size_show, overlay_output_size_store);
+ static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+ overlay_enabled_show, overlay_enabled_store);
++static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
++ overlay_global_alpha_show, overlay_global_alpha_store);
+
+ static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_name.attr,
+@@ -224,6 +257,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_position.attr,
+ &overlay_attr_output_size.attr,
+ &overlay_attr_enabled.attr,
++ &overlay_attr_global_alpha.attr,
+ NULL
+ };
+
+@@ -444,6 +478,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->id = OMAP_DSS_GFX;
+ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ case 1:
+ ovl->name = "vid1";
+@@ -451,6 +486,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ case 2:
+ ovl->name = "vid2";
+@@ -458,6 +494,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0056-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0056-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch
new file mode 100644
index 0000000000..c46fda0d52
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0056-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch
@@ -0,0 +1,35 @@
+From 32cf39c92dfd28e18936c31eea90b4d43a3c0968 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 24 Apr 2009 14:33:48 +0530
+Subject: [PATCH 56/69] DSS2: Rotation attrs for YUV need not to be reversed for 90 and 270
+
+DSS2 supports horizontal mirroing. so only 180 and 0 degree attributes needs
+to be reversed for mirroring.
+Slight corrupt image is seen with 90 ad 270 degree rotation with mirroring
+when the image height and widht is not 32-pixels aligned. To be specific
+resolution is 168X192.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/dss/dispc.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b6a39f5..f79decb 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1110,9 +1110,9 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ if (mirroring) {
+ switch (rotation) {
+ case 0: vidrot = 2; break;
+- case 1: vidrot = 3; break;
++ case 1: vidrot = 1; break;
+ case 2: vidrot = 0; break;
+- case 3: vidrot = 1; break;
++ case 3: vidrot = 3; break;
+ }
+ } else {
+ switch (rotation) {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0057-DSS2-Documentation-update-for-new-sysfs-entries-in.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0057-DSS2-Documentation-update-for-new-sysfs-entries-in.patch
new file mode 100644
index 0000000000..929f41b590
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0057-DSS2-Documentation-update-for-new-sysfs-entries-in.patch
@@ -0,0 +1,32 @@
+From bc67f1fce4472087014fdacd3f44ea732200533e Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Mon, 27 Apr 2009 13:15:07 +0530
+Subject: [PATCH 57/69] DSS2: Documentation update for new sysfs entries in omapdss/manager
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ Documentation/arm/OMAP/DSS | 7 ++++++-
+ 1 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 249e1a3..751000b 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -136,8 +136,13 @@ screen_width width
+ global_alpha global alpha 0-255 0=transparent 255=opaque
+
+ /sys/devices/platform/omapdss/manager? directory:
+-display Destination display
++display Destination display
+ name
++alpha_blending_enabled 0=off 1=on
++color_key_enabled 0=off 1=on
++color_key_type gfx-destination video-source
++color_key_value 0 to 2^24
++default_color default background color RGB24 0 to 2^24
+
+ /sys/devices/platform/omapdss/display? directory:
+ ctrl_name Controller name
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0058-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0058-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch
new file mode 100644
index 0000000000..7a6f23b349
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0058-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch
@@ -0,0 +1,56 @@
+From 9500c899f05048d17ced4340ecfd377656a23934 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 17 Apr 2009 18:34:33 +0200
+Subject: [PATCH 58/69] DSS2: Don't touch plane coordinates when changing fb->ovl mapping
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When attaching overlays to a framebuffer via the 'overlays' sysfs file
+do not touch the planes' coordinates. Without this change attaching
+VID2 to a framebuffer which already has VID1 attached would cause VID1
+to be reset to position 0,0 and scaled to 1:1 size. Also call
+omapfb_apply_changes() only once after all the overlays have been
+attached to avoid fiddling with all the overlays several times.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 13 ++++++-------
+ 1 files changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 13028ae..702199d 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -183,6 +183,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+ struct omap_overlay *ovl;
+ int num_ovls, r, i;
+ int len;
++ bool added = false;
+
+ num_ovls = 0;
+
+@@ -284,15 +285,13 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+
+ ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+- r = omapfb_apply_changes(fbi, 1);
++ added = true;
++ }
++
++ if (added) {
++ r = omapfb_apply_changes(fbi, 0);
+ if (r)
+ goto out;
+-
+- if (ovl->manager) {
+- r = ovl->manager->apply(ovl->manager);
+- if (r)
+- goto out;
+- }
+ }
+
+ r = count;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0059-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0059-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch
new file mode 100644
index 0000000000..9ca0f2eab1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0059-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch
@@ -0,0 +1,97 @@
+From 750f7ddc0881834f3400c40e9a59d11f9427cf99 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 29 Apr 2009 17:26:30 +0300
+Subject: [PATCH 59/69] DSS2: DSI: configure ENTER/EXIT_HS_MODE_LATENCY
+
+---
+ drivers/video/omap2/dss/dsi.c | 49 ++++++++++++++++++++++++++++++++--------
+ 1 files changed, 39 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index d8df353..5225ed6 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2309,15 +2309,26 @@ static int dsi_proto_config(struct omap_display *display)
+ return 0;
+ }
+
+-static void dsi_proto_timings(void)
+-{
+- int tlpx_half, tclk_zero, tclk_prepare, tclk_trail;
+- int tclk_pre, tclk_post;
+- int ddr_clk_pre, ddr_clk_post;
++static void dsi_proto_timings(struct omap_display *display)
++{
++ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
++ unsigned tclk_pre, tclk_post;
++ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
++ unsigned ths_trail, ths_exit;
++ unsigned ddr_clk_pre, ddr_clk_post;
++ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
++ unsigned ths_eot;
+ u32 r;
+
++ r = dsi_read_reg(DSI_DSIPHY_CFG0);
++ ths_prepare = FLD_GET(r, 31, 24);
++ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
++ ths_zero = ths_prepare_ths_zero - ths_prepare;
++ ths_trail = FLD_GET(r, 15, 8);
++ ths_exit = FLD_GET(r, 7, 0);
++
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+- tlpx_half = FLD_GET(r, 22, 16);
++ tlpx = FLD_GET(r, 22, 16) * 2;
+ tclk_trail = FLD_GET(r, 15, 8);
+ tclk_zero = FLD_GET(r, 7, 0);
+
+@@ -2329,17 +2340,35 @@ static void dsi_proto_timings(void)
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
+- ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) / 4;
+- ddr_clk_post = (tclk_post + tclk_trail) / 4;
++ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
++ 4);
++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
+ dsi_write_reg(DSI_CLK_TIMING, r);
+
+- DSSDBG("ddr_clk_pre %d, ddr_clk_post %d\n",
++ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
+ ddr_clk_pre,
+ ddr_clk_post);
++
++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
++ if (display->hw_config.u.dsi.data1_lane != 0 &&
++ display->hw_config.u.dsi.data2_lane != 0)
++ ths_eot = 2;
++ else
++ ths_eot = 4;
++
++ enter_hs_mode_lat = DIV_ROUND_UP(tlpx + ths_prepare + ths_zero, 4) + 4;
++ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
++
++ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
++ FLD_VAL(exit_hs_mode_lat, 15, 0);
++ dsi_write_reg(DSI_VM_TIMING7, r);
++
++ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
++ enter_hs_mode_lat, exit_hs_mode_lat);
+ }
+
+
+@@ -3340,7 +3369,7 @@ static int dsi_display_init_dsi(struct omap_display *display)
+
+ _dsi_print_reset_status();
+
+- dsi_proto_timings();
++ dsi_proto_timings(display);
+ dsi_set_lp_clk_divisor();
+
+ if (1)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0060-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0060-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch
new file mode 100644
index 0000000000..0ff2c7b1a6
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0060-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch
@@ -0,0 +1,34 @@
+From 233a6e4f4ccaf5827f04ab38c590397755e61ecb Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 4 May 2009 16:18:30 +0200
+Subject: [PATCH 60/69] DSS2: Avoid div by zero when calculating required fclk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When calculating the required fclk rate for five tap filtering if the
+display width and output width are equal div by zero could occur. The
+TRM doesn't actually specify how this case should be handled but for
+now just skip the calculation which would trigger the div by zero.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index f79decb..5fc9457 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1399,7 +1399,7 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height,
+ do_div(tmp, 2 * out_height * ppl);
+ fclk = tmp;
+
+- if (height > 2 * out_height) {
++ if (height > 2 * out_height && ppl != out_width) {
+ tmp = pclk * (height - 2 * out_height) * out_width;
+ do_div(tmp, 2 * out_height * (ppl - out_width));
+ fclk = max(fclk, (u32) tmp);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0061-DSS2-VRFB-save-restore-context.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0061-DSS2-VRFB-save-restore-context.patch
new file mode 100644
index 0000000000..a0b694736b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0061-DSS2-VRFB-save-restore-context.patch
@@ -0,0 +1,106 @@
+From e58576ceca922bfe4c793e6f77a873c4ea14f768 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 09:05:12 +0300
+Subject: [PATCH 61/69] DSS2: VRFB: save / restore context
+
+The VRFB is part of the SMS and supplied by the core power domain; do
+the context saving while VRFB is configured and restore it along with
+the rest of the domain context.
+
+This patch only implements the restore functionality, but not the
+actual call to the restore. That belongs to PM functionality.
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 1 +
+ arch/arm/plat-omap/vrfb.c | 50 ++++++++++++++++++++++++++-----
+ 2 files changed, 43 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index 12c7fab..ee6c062 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -44,5 +44,6 @@ extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode);
++extern void omap_vrfb_restore_context(void);
+
+ #endif /* __VRFB_H */
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 2ae0d68..649803e 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -39,6 +39,33 @@
+ /* bitmap of reserved contexts */
+ static unsigned ctx_map;
+
++/*
++ * Access to this happens from client drivers or the PM core after wake-up.
++ * For the first case we require locking at the driver level, for the second
++ * we don't need locking, since no drivers will run until after the wake-up
++ * has finished.
++ */
++struct {
++ u32 physical_ba;
++ u32 control;
++ u32 size;
++} vrfb_hw_context[VRFB_NUM_CTXS];
++
++void omap_vrfb_restore_context(void)
++{
++ int i;
++
++ for (i = 0; i < VRFB_NUM_CTXS; i++) {
++ /* Restore only the active contexts */
++ if (!(ctx_map & (1 << i)))
++ continue;
++ omap_writel(vrfb_hw_context[i].control, SMS_ROT_CONTROL(i));
++ omap_writel(vrfb_hw_context[i].size, SMS_ROT_SIZE(i));
++ omap_writel(vrfb_hw_context[i].physical_ba,
++ SMS_ROT_PHYSICAL_BA(i));
++ }
++}
++
+ void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp)
+ {
+@@ -56,6 +83,8 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 vrfb_height;
+ u8 ctx = vrfb->context;
+ u8 bytespp;
++ u32 size;
++ u32 control;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+ width, height, bytespp);
+@@ -100,15 +129,20 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+
+ DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
+
++ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
++ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
++
++ control = pixel_size_exp << SMS_PS_OFFSET;
++ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
++ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
++
++ vrfb_hw_context[ctx].physical_ba = paddr;
++ vrfb_hw_context[ctx].size = size;
++ vrfb_hw_context[ctx].control = control;
++
+ omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
+- omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
+- (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
+- SMS_ROT_SIZE(ctx));
+-
+- omap_writel(pixel_size_exp << SMS_PS_OFFSET |
+- VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
+- VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
+- SMS_ROT_CONTROL(ctx));
++ omap_writel(size, SMS_ROT_SIZE(ctx));
++ omap_writel(control, SMS_ROT_CONTROL(ctx));
+
+ DBG("vrfb offset pixels %d, %d\n",
+ vrfb_width - width, vrfb_height - height);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0062-DSS2-VRAM-Fix-indentation.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0062-DSS2-VRAM-Fix-indentation.patch
new file mode 100644
index 0000000000..8d5f57866d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0062-DSS2-VRAM-Fix-indentation.patch
@@ -0,0 +1,65 @@
+From 0fb6754f996b5022e1d856fda3d3258382383596 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 6 May 2009 09:03:43 +0300
+Subject: [PATCH 62/69] DSS2: VRAM: Fix indentation
+
+---
+ arch/arm/plat-omap/vram.c | 26 +++++++++++++-------------
+ 1 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index b126a64..f3ce849 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -287,35 +287,35 @@ static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
+ static int _omap_vram_clear(u32 paddr, unsigned pages)
+ {
+ struct completion compl;
+- unsigned elem_count;
+- unsigned frame_count;
++ unsigned elem_count;
++ unsigned frame_count;
+ int r;
+ int lch;
+
+ init_completion(&compl);
+
+- r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
+ _omap_vram_dma_cb,
+- &compl, &lch);
+- if (r) {
++ &compl, &lch);
++ if (r) {
+ pr_err("VRAM: request_dma failed for memory clear\n");
+ return -EBUSY;
+ }
+
+- elem_count = pages * PAGE_SIZE / 4;
+- frame_count = 1;
++ elem_count = pages * PAGE_SIZE / 4;
++ frame_count = 1;
+
+- omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
+- elem_count, frame_count,
+- OMAP_DMA_SYNC_ELEMENT,
+- 0, 0);
++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
++ elem_count, frame_count,
++ OMAP_DMA_SYNC_ELEMENT,
++ 0, 0);
+
+- omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
+ paddr, 0, 0);
+
+ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
+
+- omap_start_dma(lch);
++ omap_start_dma(lch);
+
+ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
+ omap_stop_dma(lch);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0063-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0063-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch
new file mode 100644
index 0000000000..8633921979
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0063-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch
@@ -0,0 +1,82 @@
+From 5d3426ae63c27b9405be8179beabe1e095b44a35 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 19:00:19 +0200
+Subject: [PATCH 63/69] DSS2: fix the usage of get_last_off_on_transaction_id
+
+The function returns int not unsigned since it can fail. Handle the
+failing case as if the context had been lost. So now:
+
+1. No get_last_off_on_transaction_id func in platform data->
+ never restore the context
+2. Return val < 0 -> force the restore
+3. Return val >= 0 do the restore only if the counter has changed.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 +-
+ drivers/video/omap2/dss/core.c | 18 ++++++++++++------
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 45b16ca..31ebb96 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -234,7 +234,7 @@ struct device;
+
+ /* Board specific data */
+ struct omap_dss_board_info {
+- unsigned (*get_last_off_on_transaction_id)(struct device *dev);
++ int (*get_last_off_on_transaction_id)(struct device *dev);
+ int (*dsi_power_up)(void);
+ void (*dsi_power_down)(void);
+ int num_displays;
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index ae7cd06..6d11b04 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -38,7 +38,7 @@
+
+ static struct {
+ struct platform_device *pdev;
+- unsigned ctx_id;
++ int ctx_id;
+
+ struct clk *dss_ick;
+ struct clk *dss1_fck;
+@@ -63,22 +63,28 @@ module_param_named(debug, dss_debug, bool, 0644);
+ #endif
+
+ /* CONTEXT */
+-static unsigned dss_get_ctx_id(void)
++static int dss_get_ctx_id(void)
+ {
+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++ int r;
+
+ if (!pdata->get_last_off_on_transaction_id)
+ return 0;
+-
+- return pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++ if (r < 0) {
++ dev_err(&core.pdev->dev,
++ "getting transaction ID failed, will force context restore\n");
++ r = -1;
++ }
++ return r;
+ }
+
+ int dss_need_ctx_restore(void)
+ {
+ int id = dss_get_ctx_id();
+
+- if (id != core.ctx_id) {
+- DSSDBG("ctx id %u -> id %u\n",
++ if (id < 0 || id != core.ctx_id) {
++ DSSDBG("ctx id %d -> id %d\n",
+ core.ctx_id, id);
+ core.ctx_id = id;
+ return 1;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0064-VRFB-fix-debug-messages.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0064-VRFB-fix-debug-messages.patch
new file mode 100644
index 0000000000..2ba9b1b1a2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0064-VRFB-fix-debug-messages.patch
@@ -0,0 +1,35 @@
+From 784271e9546844c5e69ec6d8f2fd3713847b6ab2 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 11:16:14 +0200
+Subject: [PATCH 64/69] VRFB: fix debug messages
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 649803e..289fc8a 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -87,7 +87,7 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u32 control;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+- width, height, bytespp);
++ width, height, color_mode);
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+@@ -127,7 +127,7 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
+
+- DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
++ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
+
+ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
+ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0065-VRFB-add-suspend-resume-functionality.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0065-VRFB-add-suspend-resume-functionality.patch
new file mode 100644
index 0000000000..17f959cb27
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0065-VRFB-add-suspend-resume-functionality.patch
@@ -0,0 +1,216 @@
+From 1269429fe6ddd6e5f15e3b4edb4fc2bcd6fc0410 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 11:16:13 +0200
+Subject: [PATCH 65/69] VRFB: add suspend/resume functionality
+
+At the moment the VRFB context is restored at each core power domain
+OFF->ON transition. This is not optimal since the VRFB might be unused
+temporarily for example when the screen is blanked. Add a suspend /
+resume function to mark these unused periods during which we'll avoid
+thea the context restore.
+
+Use atomic bitops for ctx_map for consistency.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 2 +
+ arch/arm/plat-omap/vrfb.c | 75 ++++++++++++++++++++++++-----
+ drivers/video/omap2/omapfb/omapfb-main.c | 28 +++++++++++
+ 3 files changed, 92 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index ee6c062..9647d82 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -39,6 +39,8 @@ struct vrfb
+
+ extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
+ extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
+ extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp);
+ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 289fc8a..29f04e2 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -1,7 +1,9 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/ioport.h>
++
+ #include <asm/io.h>
++#include <asm/bitops.h>
+
+ #include <mach/io.h>
+ #include <mach/vrfb.h>
+@@ -37,7 +39,9 @@
+
+ #define VRFB_NUM_CTXS 12
+ /* bitmap of reserved contexts */
+-static unsigned ctx_map;
++static unsigned long ctx_map;
++/* bitmap of contexts for which we have to keep the HW context valid */
++static unsigned long ctx_map_active;
+
+ /*
+ * Access to this happens from client drivers or the PM core after wake-up.
+@@ -51,18 +55,23 @@ struct {
+ u32 size;
+ } vrfb_hw_context[VRFB_NUM_CTXS];
+
++static void inline restore_hw_context(int ctx)
++{
++ omap_writel(vrfb_hw_context[ctx].control, SMS_ROT_CONTROL(ctx));
++ omap_writel(vrfb_hw_context[ctx].size, SMS_ROT_SIZE(ctx));
++ omap_writel(vrfb_hw_context[ctx].physical_ba, SMS_ROT_PHYSICAL_BA(ctx));
++}
++
+ void omap_vrfb_restore_context(void)
+ {
+ int i;
++ unsigned long map = ctx_map_active;
+
+- for (i = 0; i < VRFB_NUM_CTXS; i++) {
+- /* Restore only the active contexts */
+- if (!(ctx_map & (1 << i)))
+- continue;
+- omap_writel(vrfb_hw_context[i].control, SMS_ROT_CONTROL(i));
+- omap_writel(vrfb_hw_context[i].size, SMS_ROT_SIZE(i));
+- omap_writel(vrfb_hw_context[i].physical_ba,
+- SMS_ROT_PHYSICAL_BA(i));
++ for (i = ffs(map); i; i = ffs(map)) {
++ /* i=1..32 */
++ i--;
++ map &= ~(1 << i);
++ restore_hw_context(i);
+ }
+ }
+
+@@ -156,13 +165,20 @@ EXPORT_SYMBOL(omap_vrfb_setup);
+ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ {
+ int rot;
++ int ctx = vrfb->context;
+
+- if (vrfb->context == 0xff)
++ if (ctx == 0xff)
+ return;
+
+- DBG("release ctx %d\n", vrfb->context);
++ DBG("release ctx %d\n", ctx);
+
+- ctx_map &= ~(1 << vrfb->context);
++ if (!(ctx_map & (1 << ctx))) {
++ BUG();
++ return;
++ }
++ WARN_ON(!(ctx_map_active & (1 << ctx)));
++ clear_bit(ctx, &ctx_map_active);
++ clear_bit(ctx, &ctx_map);
+
+ for (rot = 0; rot < 4; ++rot) {
+ if(vrfb->paddr[rot]) {
+@@ -194,7 +210,9 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+
+ DBG("found free ctx %d\n", ctx);
+
+- ctx_map |= 1 << ctx;
++ set_bit(ctx, &ctx_map);
++ WARN_ON(ctx_map_active & (1 << ctx));
++ set_bit(ctx, &ctx_map_active);
+
+ memset(vrfb, 0, sizeof(*vrfb));
+
+@@ -219,3 +237,34 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ }
+ EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
++void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
++{
++ DBG("suspend ctx %d\n", vrfb->context);
++ if (vrfb->context >= VRFB_NUM_CTXS ||
++ (!(1 << vrfb->context) & ctx_map_active)) {
++ BUG();
++ return;
++ }
++ clear_bit(vrfb->context, &ctx_map_active);
++}
++EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
++
++void omap_vrfb_resume_ctx(struct vrfb *vrfb)
++{
++ DBG("resume ctx %d\n", vrfb->context);
++ if (vrfb->context >= VRFB_NUM_CTXS ||
++ ((1 << vrfb->context) & ctx_map_active)) {
++ BUG();
++ return;
++ }
++ /*
++ * omap_vrfb_restore_context is normally called by the core domain
++ * save / restore logic, but since this VRFB context was suspended
++ * those calls didn't actually restore the context and now we might
++ * have an invalid context. Do an explicit restore here.
++ */
++ restore_hw_context(vrfb->context);
++ set_bit(vrfb->context, &ctx_map_active);
++}
++EXPORT_SYMBOL(omap_vrfb_resume_ctx);
++
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 76e7c6c..4bb74b7 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1036,6 +1036,30 @@ static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+ return 0;
+ }
+
++static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
++ }
++}
++
++static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_resume_ctx(&ofbi->region.vrfb);
++ }
++}
++
+ static int omapfb_blank(int blank, struct fb_info *fbi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+@@ -1051,6 +1075,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ goto exit;
+
++ omapfb_vrfb_resume_all(fbdev);
++
+ if (display->resume)
+ r = display->resume(display);
+
+@@ -1073,6 +1099,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
+ if (display->suspend)
+ r = display->suspend(display);
+
++ omapfb_vrfb_suspend_all(fbdev);
++
+ break;
+
+ default:
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0066-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0066-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch
new file mode 100644
index 0000000000..a3af90d959
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0066-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch
@@ -0,0 +1,92 @@
+From 0201b40018d9e264f8c4ea7871223c94e0de61b1 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 7 May 2009 14:32:55 +0300
+Subject: [PATCH 66/69] DSS2: DSI: tune the timings to be more relaxed
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 37 +++++++++++++++++++++----------------
+ 1 files changed, 21 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 5225ed6..67ecfcf 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1396,28 +1396,28 @@ static void dsi_complexio_timings(void)
+ /* 1 * DDR_CLK = 2 * UI */
+
+ /* min 40ns + 4*UI max 85ns + 6*UI */
+- ths_prepare = ns2ddr(59) + 2;
++ ths_prepare = ns2ddr(70) + 2;
+
+ /* min 145ns + 10*UI */
+- ths_prepare_ths_zero = ns2ddr(145) + 5;
++ ths_prepare_ths_zero = ns2ddr(175) + 2;
+
+ /* min max(8*UI, 60ns+4*UI) */
+- ths_trail = max((unsigned)4, ns2ddr(60) + 2);
++ ths_trail = ns2ddr(60) + 5;
+
+ /* min 100ns */
+- ths_exit = ns2ddr(100);
++ ths_exit = ns2ddr(145);
+
+ /* tlpx min 50n */
+ tlpx_half = ns2ddr(25);
+
+ /* min 60ns */
+- tclk_trail = ns2ddr(60);
++ tclk_trail = ns2ddr(60) + 2;
+
+ /* min 38ns, max 95ns */
+- tclk_prepare = ns2ddr(38);
++ tclk_prepare = ns2ddr(65);
+
+ /* min tclk-prepare + tclk-zero = 300ns */
+- tclk_zero = ns2ddr(300 - 38);
++ tclk_zero = ns2ddr(260);
+
+ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
+ ths_prepare, ddr2ns(ths_prepare),
+@@ -2340,9 +2340,19 @@ static void dsi_proto_timings(struct omap_display *display)
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
++ if (display->hw_config.u.dsi.data1_lane != 0 &&
++ display->hw_config.u.dsi.data2_lane != 0)
++ ths_eot = 2;
++ else
++ ths_eot = 4;
++
+ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
+ 4);
+- ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4);
++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
++
++ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
++ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+@@ -2353,14 +2363,9 @@ static void dsi_proto_timings(struct omap_display *display)
+ ddr_clk_pre,
+ ddr_clk_post);
+
+- /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
+- if (display->hw_config.u.dsi.data1_lane != 0 &&
+- display->hw_config.u.dsi.data2_lane != 0)
+- ths_eot = 2;
+- else
+- ths_eot = 4;
+-
+- enter_hs_mode_lat = DIV_ROUND_UP(tlpx + ths_prepare + ths_zero, 4) + 4;
++ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
++ DIV_ROUND_UP(ths_prepare, 4) +
++ DIV_ROUND_UP(ths_zero + 3, 4);
+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0067-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0067-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch
new file mode 100644
index 0000000000..911fe79bfa
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0067-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch
@@ -0,0 +1,29 @@
+From c474849d7aff57d578c639f63a9c3cbdec0501dd Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Mon, 11 May 2009 15:15:52 +0200
+Subject: [PATCH 67/69] DSS2: VRFB: don't WARN when releasing inactive ctx
+
+Releasing an inactive context is valid, it can happen when
+the application first blanks the screen then frees the
+framebuffer.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 29f04e2..34395c2 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -176,7 +176,6 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ BUG();
+ return;
+ }
+- WARN_ON(!(ctx_map_active & (1 << ctx)));
+ clear_bit(ctx, &ctx_map_active);
+ clear_bit(ctx, &ctx_map);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0068-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0068-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch
new file mode 100644
index 0000000000..fba2ebd5db
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0068-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch
@@ -0,0 +1,65 @@
+From 0db37fa025f0eac64f9fdad49e310d7660f48944 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Tue, 12 May 2009 14:38:05 +0200
+Subject: [PATCH 68/69] DSS2: Swap field offset values w/ VRFB rotation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The field 0 and field 1 offset values were still incorrect when VRFB
+rotation is used. Swap them to put the fields into proper order.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 17 +++++++++++------
+ 1 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 5fc9457..b0e4960 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1182,6 +1182,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+
+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+ width, height);
++
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ case 2:
+@@ -1194,11 +1199,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ width = width >> 1;
+ case 1:
+ case 3:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = screen_width * ps;
++ *offset0 = screen_width * ps;
+ else
+- *offset1 = 0;
++ *offset0 = 0;
+
+ *row_inc = pixinc(1 + (screen_width - width) +
+ (fieldmode ? screen_width : 0),
+@@ -1216,11 +1221,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ width = width >> 1;
+ case 5:
+ case 7:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = screen_width * ps;
++ *offset0 = screen_width * ps;
+ else
+- *offset1 = 0;
++ *offset0 = 0;
+ *row_inc = pixinc(1 - (screen_width + width) -
+ (fieldmode ? screen_width : 0),
+ ps);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0069-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch b/recipes/linux/linux-omap-pm-2.6.29/dss2/0069-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch
new file mode 100644
index 0000000000..c637c48602
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0069-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch
@@ -0,0 +1,125 @@
+From b06406f3e5c3958f69185314c969f7c1a3265f71 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 14 May 2009 15:04:17 +0530
+Subject: [PATCH 69/69] DSS2: OMAP3EVM: Added DSI powerup and powerdown functions
+
+Copied fom 3430sdp implementation.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/mach-omap2/board-omap3evm.c | 62 +++++++++++++++++++++-------------
+ 1 files changed, 38 insertions(+), 24 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index 6f5a866..57c4fc7 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -237,6 +237,38 @@ static int __init omap3_evm_i2c_init(void)
+ static int lcd_enabled;
+ static int dvi_enabled;
+
++static void enable_vpll2(int enable)
++{
++ u8 ded_val, grp_val;
++
++ if (enable) {
++ ded_val = ENABLE_VPLL2_DEDICATED;
++ grp_val = ENABLE_VPLL2_DEV_GRP;
++ } else {
++ ded_val = 0;
++ grp_val = 0;
++ }
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ded_val, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ grp_val, TWL4030_VPLL2_DEV_GRP);
++}
++
++static int omap3evm_dsi_power_up(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(1);
++ return 0;
++}
++
++static void omap3evm_dsi_power_down(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(0);
++}
++
++
+ static void __init omap3_evm_display_init(void)
+ {
+ int r;
+@@ -306,12 +338,7 @@ static int omap3_evm_panel_enable_lcd(struct omap_display *display)
+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+ return -EINVAL;
+ }
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
+- }
++ omap3evm_dsi_power_up();
+ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
+ lcd_enabled = 1;
+ return 0;
+@@ -319,12 +346,7 @@ static int omap3_evm_panel_enable_lcd(struct omap_display *display)
+
+ static void omap3_evm_panel_disable_lcd(struct omap_display *display)
+ {
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEV_GRP);
+- }
++ omap3evm_dsi_power_down();
+ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
+ lcd_enabled = 0;
+ }
+@@ -370,13 +392,8 @@ static int omap3_evm_panel_enable_dvi(struct omap_display *display)
+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+ return -EINVAL;
+ }
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
+- }
+
++ omap3evm_dsi_power_up();
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+ TWL4030_GPIODATA_IN3);
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+@@ -388,13 +405,8 @@ static int omap3_evm_panel_enable_dvi(struct omap_display *display)
+
+ static void omap3_evm_panel_disable_dvi(struct omap_display *display)
+ {
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEV_GRP);
+- }
+
++ omap3evm_dsi_power_down();
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+ TWL4030_GPIODATA_IN3);
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+@@ -413,6 +425,8 @@ static struct omap_dss_display_config omap3_evm_display_data_dvi = {
+ };
+
+ static struct omap_dss_board_info omap3_evm_dss_data = {
++ .dsi_power_up = omap3evm_dsi_power_up,
++ .dsi_power_down = omap3evm_dsi_power_down,
+ .num_displays = 3,
+ .displays = {
+ &omap3_evm_display_data,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0070-DSS2-fix-irq1.diff b/recipes/linux/linux-omap-pm-2.6.29/dss2/0070-DSS2-fix-irq1.diff
new file mode 100644
index 0000000000..8f384dfe2d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0070-DSS2-fix-irq1.diff
@@ -0,0 +1,221 @@
+From 093988f36ffcb0201927f8b452e546e1141aa0fa Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Sat, 23 May 2009 15:00:21 +0000
+Subject: DSS2: DISPC: fix irq handling locking
+
+---
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b0e4960..b3685b2 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -154,23 +154,20 @@ static struct {
+
+ struct clk *dpll4_m4_ck;
+
+- spinlock_t irq_lock;
+-
+ unsigned long cache_req_pck;
+ unsigned long cache_prate;
+ struct dispc_clock_info cache_cinfo;
+
+- u32 irq_error_mask;
++ spinlock_t irq_lock;
++ u32 irq_error_mask;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+-
+- spinlock_t error_lock;
+ u32 error_irqs;
+ struct work_struct error_work;
+
+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+ } dispc;
+
+-static void omap_dispc_set_irqs(void);
++static void _omap_dispc_set_irqs(void);
+
+ static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
+ {
+@@ -1691,10 +1688,13 @@ void dispc_enable_digit_out(bool enable)
+ }
+
+ if (enable) {
++ unsigned long flags;
+ /* When we enable digit output, we'll get an extra digit
+ * sync lost interrupt, that we need to ignore */
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ /* When we disable digit output, we need to wait until fields are done.
+@@ -1728,9 +1728,12 @@ void dispc_enable_digit_out(bool enable)
+ DSSERR("failed to unregister EVSYNC isr\n");
+
+ if (enable) {
++ unsigned long flags;
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ enable_clocks(0);
+@@ -2508,14 +2511,14 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+ return 0;
+ }
+
+-static void omap_dispc_set_irqs(void)
++/* dispc.irq_lock has to be locked by the caller */
++static void _omap_dispc_set_irqs(void)
+ {
+- unsigned long flags;
+- u32 mask = dispc.irq_error_mask;
++ u32 mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+- spin_lock_irqsave(&dispc.irq_lock, flags);
++ mask = dispc.irq_error_mask;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+@@ -2528,9 +2531,8 @@ static void omap_dispc_set_irqs(void)
+
+ enable_clocks(1);
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+- enable_clocks(0);
+
+- spin_unlock_irqrestore(&dispc.irq_lock, flags);
++ enable_clocks(0);
+ }
+
+ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+@@ -2571,11 +2573,14 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+
+ break;
+ }
+-err:
++
++ _omap_dispc_set_irqs();
++
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+- if (ret == 0)
+- omap_dispc_set_irqs();
++ return 0;
++err:
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+ }
+@@ -2606,10 +2611,10 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+ break;
+ }
+
+- spin_unlock_irqrestore(&dispc.irq_lock, flags);
+-
+ if (ret == 0)
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+ }
+@@ -2645,11 +2650,15 @@ static void print_irq_status(u32 status)
+ void dispc_irq_handler(void)
+ {
+ int i;
+- u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++ u32 irqstatus;
+ u32 handledirqs = 0;
+ u32 unhandled_errors;
+ struct omap_dispc_isr_data *isr_data;
+
++ spin_lock(&dispc.irq_lock);
++
++ irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++
+ #ifdef DEBUG
+ if (dss_debug)
+ print_irq_status(irqstatus);
+@@ -2673,15 +2682,15 @@ void dispc_irq_handler(void)
+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
+
+ if (unhandled_errors) {
+- spin_lock(&dispc.error_lock);
+ dispc.error_irqs |= unhandled_errors;
+- spin_unlock(&dispc.error_lock);
+
+ dispc.irq_error_mask &= ~unhandled_errors;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
+
+ schedule_work(&dispc.error_work);
+ }
++
++ spin_unlock(&dispc.irq_lock);
+ }
+
+ static void dispc_error_worker(struct work_struct *work)
+@@ -2690,10 +2699,10 @@ static void dispc_error_worker(struct work_struct *work)
+ u32 errors;
+ unsigned long flags;
+
+- spin_lock_irqsave(&dispc.error_lock, flags);
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ errors = dispc.error_irqs;
+ dispc.error_irqs = 0;
+- spin_unlock_irqrestore(&dispc.error_lock, flags);
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
+ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
+@@ -2836,8 +2845,10 @@ static void dispc_error_worker(struct work_struct *work)
+ }
+ }
+
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask |= errors;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
+@@ -2921,6 +2932,10 @@ void dispc_fake_vsync_irq(void)
+
+ static void _omap_dispc_initialize_irq(void)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
+ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
+
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+@@ -2929,7 +2944,9 @@ static void _omap_dispc_initialize_irq(void)
+ * so clear it */
+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ void dispc_enable_sidle(void)
+@@ -2970,7 +2987,6 @@ int dispc_init(void)
+ u32 rev;
+
+ spin_lock_init(&dispc.irq_lock);
+- spin_lock_init(&dispc.error_lock);
+
+ INIT_WORK(&dispc.error_work, dispc_error_worker);
+
+--
+cgit v0.8.2.1-10-g45e7
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/0071-DSS2-fix-irq2.diff b/recipes/linux/linux-omap-pm-2.6.29/dss2/0071-DSS2-fix-irq2.diff
new file mode 100644
index 0000000000..cb8aaf1a28
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/0071-DSS2-fix-irq2.diff
@@ -0,0 +1,35 @@
+From 8af2f6550d6971875e4c5d3f93982f86f4bcf216 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Sat, 23 May 2009 15:00:00 +0000
+Subject: DSS2: DISPC: clear irqstatus for newly enabled irqs
+
+This fixes the problem that when requesting a new irq
+we could get the isr called too early in case irqstatus
+already had that irq flag on.
+---
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b3685b2..2471cfe 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2515,6 +2515,7 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+ static void _omap_dispc_set_irqs(void)
+ {
+ u32 mask;
++ u32 old_mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+@@ -2530,6 +2531,11 @@ static void _omap_dispc_set_irqs(void)
+ }
+
+ enable_clocks(1);
++
++ old_mask = dispc_read_reg(DISPC_IRQENABLE);
++ /* clear the irqstatus for newly enabled irqs */
++ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
++
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+
+ enable_clocks(0);
+--
+cgit v0.8.2.1-10-g45e7
diff --git a/recipes/linux/linux-omap-pm-2.6.29/dss2/merge-fixups.diff b/recipes/linux/linux-omap-pm-2.6.29/dss2/merge-fixups.diff
new file mode 100644
index 0000000000..94e663ce9e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/dss2/merge-fixups.diff
@@ -0,0 +1,49 @@
+
+--- /tmp/io.c 2009-04-23 12:31:45.000000000 +0200
++++ git/arch/arm/mach-omap2/io.c 2009-04-23 12:32:35.000000000 +0200
+@@ -18,6 +18,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
++#include <linux/omapfb.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
+
+@@ -25,7 +26,6 @@
+
+ #include <asm/mach/map.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <mach/sram.h>
+ #include <mach/sdrc.h>
+ #include <mach/gpmc.h>
+--- /tmp/board-3430sdp.c 2009-04-23 12:31:45.000000000 +0200
++++ git/arch/arm/mach-omap2/board-3430sdp.c 2009-04-23 12:32:51.000000000 +0200
+@@ -38,6 +38,7 @@
+ #include <mach/dma.h>
+ #include <mach/gpmc.h>
+ #include <mach/omap-pm.h>
++#include <mach/display.h>
+
+ #include <mach/control.h>
+ #include <mach/clock.h>
+--- /tmp/board-omap3beagle.c 2009-04-23 12:31:45.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-04-23 12:33:07.000000000 +0200
+@@ -46,6 +46,7 @@
+ #include <mach/mux.h>
+ #include <mach/omap-pm.h>
+ #include <mach/clock.h>
++#include <mach/display.h>
+
+ #include "twl4030-generic-scripts.h"
+ #include "mmc-twl4030.h"
+--- /tmp/board-omap3evm.c 2009-04-23 12:31:45.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3evm.c 2009-04-23 12:33:22.000000000 +0200
+@@ -38,6 +38,7 @@
+ #include <mach/mcspi.h>
+ #include <mach/omap-pm.h>
+ #include <mach/clock.h>
++#include <mach/display.h>
+
+ #include "sdram-micron-mt46h32m32lf-6.h"
+ #include "twl4030-generic-scripts.h"
diff --git a/recipes/linux/linux-omap-pm-2.6.29/ehci.patch b/recipes/linux/linux-omap-pm-2.6.29/ehci.patch
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/ehci.patch
diff --git a/recipes/linux/linux-omap-pm-2.6.29/evm-mcspi-ts.diff b/recipes/linux/linux-omap-pm-2.6.29/evm-mcspi-ts.diff
new file mode 100644
index 0000000000..64d797cf96
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/evm-mcspi-ts.diff
@@ -0,0 +1,132 @@
+From linux-omap-owner@vger.kernel.org Sun Nov 02 21:08:25 2008
+Received: from localhost
+ ([127.0.0.1] helo=dominion ident=koen)
+ by dominion.dominion.void with esmtp (Exim 4.69)
+ (envelope-from <linux-omap-owner@vger.kernel.org>)
+ id 1KwjFJ-0008Hg-0T
+ for koen@localhost; Sun, 02 Nov 2008 21:08:25 +0100
+Received: from xs.service.utwente.nl [130.89.5.250]
+ by dominion with POP3 (fetchmail-6.3.9-rc2)
+ for <koen@localhost> (single-drop); Sun, 02 Nov 2008 21:08:25 +0100 (CET)
+Received: from mail.service.utwente.nl ([130.89.5.253]) by exchange.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
+ Sun, 2 Nov 2008 20:57:16 +0100
+Received: from mx.utwente.nl ([130.89.2.13]) by mail.service.utwente.nl with Microsoft SMTPSVC(6.0.3790.3959);
+ Sun, 2 Nov 2008 20:57:16 +0100
+Received: from vger.kernel.org (vger.kernel.org [209.132.176.167])
+ by mx.utwente.nl (8.12.10/SuSE Linux 0.7) with ESMTP id mA2JudEK010968
+ for <k.kooi@student.utwente.nl>; Sun, 2 Nov 2008 20:56:40 +0100
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1752819AbYKBT4i (ORCPT <rfc822;k.kooi@student.utwente.nl>);
+ Sun, 2 Nov 2008 14:56:38 -0500
+Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752829AbYKBT4i
+ (ORCPT <rfc822;linux-omap-outgoing>); Sun, 2 Nov 2008 14:56:38 -0500
+Received: from fg-out-1718.google.com ([72.14.220.153]:32481 "EHLO
+ fg-out-1718.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1752819AbYKBT4h (ORCPT
+ <rfc822;linux-omap@vger.kernel.org>); Sun, 2 Nov 2008 14:56:37 -0500
+Received: by fg-out-1718.google.com with SMTP id 19so1869080fgg.17
+ for <linux-omap@vger.kernel.org>; Sun, 02 Nov 2008 11:56:33 -0800 (PST)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=gmail.com; s=gamma;
+ h=domainkey-signature:received:received:from:to:cc:subject:date
+ :message-id:x-mailer:in-reply-to:references;
+ bh=Ftvoq8kE3ciPRy7pNy5VLkNnZD8o0HYWIrO1LMS/lAY=;
+ b=HpEcngDUbAObGNJuQmBIG3SoNHesUL57GluZGlYO7kxFxfH6N8zeHjKuRSk86+mT5s
+ gMhyCC07wjVp75HnqCtKbOJzNw/8F4ZGbL2lY1LC99+zxHW1JBQv5c3ZaoCVqTw6TuH0
+ bQ8Ew2BwHknT3wGA+QcGoMJJs5aw62AhPiyHY=
+DomainKey-Signature: a=rsa-sha1; c=nofws;
+ d=gmail.com; s=gamma;
+ h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;
+ b=aio1APZhCIcYIrMY844QkdaQzKw0/yiuaVjqfv52fnft1kafGT2qAS3KfXAc61a9If
+ sXHbi2fr/r1a7YZJJVGqkJX0WmWTY0OqdhS1lmugP/dXEMHeqaArKATbvxrq9/svb1bV
+ Vzpkm6sOzLrr54uo+BcZNoxHWqb8W2UrRxuTk=
+Received: by 10.103.131.18 with SMTP id i18mr6668205mun.126.1225655793072;
+ Sun, 02 Nov 2008 11:56:33 -0800 (PST)
+Received: from localhost.localdomain ([78.59.134.74])
+ by mx.google.com with ESMTPS id g1sm23199635muf.8.2008.11.02.11.56.31
+ (version=TLSv1/SSLv3 cipher=RC4-MD5);
+ Sun, 02 Nov 2008 11:56:31 -0800 (PST)
+From: Grazvydas Ignotas <notasas@gmail.com>
+To: linux-omap@vger.kernel.org
+Cc: Grazvydas Ignotas <notasas@gmail.com>
+Subject: Re: omap3evm LCD red-tint workaround
+Date: Sun, 2 Nov 2008 21:56:19 +0200
+Message-Id: <1225655779-18934-1-git-send-email-notasas@gmail.com>
+X-Mailer: git-send-email 1.5.4.3
+In-Reply-To: <57322719-1A5A-45DC-9846-5C0A3B6EF346@student.utwente.nl>
+References: <57322719-1A5A-45DC-9846-5C0A3B6EF346@student.utwente.nl>
+Sender: linux-omap-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <linux-omap.vger.kernel.org>
+X-Mailing-List: linux-omap@vger.kernel.org
+X-UTwente-MailScanner-Information: Scanned by MailScanner. Contact servicedesk@icts.utwente.nl for more information.
+X-UTwente-MailScanner: Found to be clean
+X-UTwente-MailScanner-From: linux-omap-owner@vger.kernel.org
+X-Spam-Status: No
+X-OriginalArrivalTime: 02 Nov 2008 19:57:16.0876 (UTC) FILETIME=[34FBA0C0:01C93D25]
+
+> PS: TS is still unusable with the 16x16 pixel resolution
+This is also the case for Pandora. The patch below fixes the problem,
+but as I have no other boards to test this on, I haven't sent it.
+See if it helps you.
+
+
+From 91f3af26bbf751b846e6265d86387e81be7c1364 Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Tue, 28 Oct 2008 22:01:42 +0200
+Subject: [PATCH] OMAP3: fix McSPI transfers
+
+Currently on OMAP3 if both write and read is set up for a transfer,
+the first byte returned on read is corrupted. Work around this by
+disabling channel between reads and writes, instead of transfers.
+---
+ drivers/spi/omap2_mcspi.c | 7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
+index 454a271..4890b6c 100644
+--- a/drivers/spi/omap2_mcspi.c
++++ b/drivers/spi/omap2_mcspi.c
+@@ -710,7 +710,6 @@ static void omap2_mcspi_work(struct work_struct *work)
+ spi = m->spi;
+ cs = spi->controller_state;
+
+- omap2_mcspi_set_enable(spi, 1);
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+ status = -EINVAL;
+@@ -741,6 +740,8 @@ static void omap2_mcspi_work(struct work_struct *work)
+ if (t->len) {
+ unsigned count;
+
++ omap2_mcspi_set_enable(spi, 1);
++
+ /* RX_ONLY mode needs dummy data in TX reg */
+ if (t->tx_buf == NULL)
+ __raw_writel(0, cs->base
+@@ -752,6 +753,8 @@ static void omap2_mcspi_work(struct work_struct *work)
+ count = omap2_mcspi_txrx_pio(spi, t);
+ m->actual_length += count;
+
++ omap2_mcspi_set_enable(spi, 0);
++
+ if (count != t->len) {
+ status = -EIO;
+ break;
+@@ -777,8 +780,6 @@ static void omap2_mcspi_work(struct work_struct *work)
+ if (cs_active)
+ omap2_mcspi_force_cs(spi, 0);
+
+- omap2_mcspi_set_enable(spi, 0);
+-
+ m->status = status;
+ m->complete(m->context);
+
+--
+1.5.4.3
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/fix-audio-capture.patch b/recipes/linux/linux-omap-pm-2.6.29/fix-audio-capture.patch
new file mode 100644
index 0000000000..c5ff914757
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/fix-audio-capture.patch
@@ -0,0 +1,16 @@
+diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
+index ee2f0d3..8b4aafb 100644
+--- a/sound/soc/codecs/twl4030.c
++++ b/sound/soc/codecs/twl4030.c
+@@ -45,8 +45,8 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
+ 0xc3, /* REG_OPTION (0x2) */
+ 0x00, /* REG_UNKNOWN (0x3) */
+ 0x00, /* REG_MICBIAS_CTL (0x4) */
+- 0x20, /* REG_ANAMICL (0x5) */
+- 0x00, /* REG_ANAMICR (0x6) */
++ 0x34, /* REG_ANAMICL (0x5) */
++ 0x14, /* REG_ANAMICR (0x6) */
+ 0x00, /* REG_AVADC_CTL (0x7) */
+ 0x00, /* REG_ADCMICSEL (0x8) */
+ 0x00, /* REG_DIGMIXING (0x9) */
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/fix-install.patch b/recipes/linux/linux-omap-pm-2.6.29/fix-install.patch
new file mode 100644
index 0000000000..46bc25a50b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/fix-install.patch
@@ -0,0 +1,23 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Mon, 18 Aug 2008 16:07:31 +0000 (-0700)
+Subject: scripts/Makefile.fwinst: add missing space when setting mode in cmd_install
+X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=f039944bdd491cde7327133e9976881d3133ae70
+
+scripts/Makefile.fwinst: add missing space when setting mode in cmd_install
+
+This was causing build failures on some machines
+---
+
+diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
+index 6bf8e87..fb20532 100644
+--- a/scripts/Makefile.fwinst
++++ b/scripts/Makefile.fwinst
+@@ -37,7 +37,7 @@ install-all-dirs: $(installed-fw-dirs)
+ @true
+
+ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
+- cmd_install = $(INSTALL) -m0644 $< $@
++ cmd_install = $(INSTALL) -m 0644 $< $@
+
+ $(installed-fw-dirs):
+ $(call cmd,mkdir)
diff --git a/recipes/linux/linux-omap-pm-2.6.29/fix-unaligned-access.diff b/recipes/linux/linux-omap-pm-2.6.29/fix-unaligned-access.diff
new file mode 100644
index 0000000000..c82090f54a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/fix-unaligned-access.diff
@@ -0,0 +1,41 @@
+From: Mans Rullgard <mans@mansr.com>
+Date: Sat, 28 Mar 2009 12:54:25 +0000 (+0000)
+Subject: NSM: Fix unaligned accesses in nsm_init_private()
+X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=8f2bd6fdde1ebfef57f65b6cf29b29008c23d297
+
+NSM: Fix unaligned accesses in nsm_init_private()
+
+This fixes unaligned accesses in nsm_init_private() when
+creating nlm_reboot keys.
+
+Signed-off-by: Mans Rullgard <mans@mansr.com>
+---
+
+diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
+index 5e2c4d5..6d5d4a4 100644
+--- a/fs/lockd/mon.c
++++ b/fs/lockd/mon.c
+@@ -16,6 +16,8 @@
+ #include <linux/sunrpc/svc.h>
+ #include <linux/lockd/lockd.h>
+
++#include <asm/unaligned.h>
++
+ #define NLMDBG_FACILITY NLMDBG_MONITOR
+ #define NSM_PROGRAM 100024
+ #define NSM_VERSION 1
+@@ -274,10 +276,12 @@ static void nsm_init_private(struct nsm_handle *nsm)
+ {
+ u64 *p = (u64 *)&nsm->sm_priv.data;
+ struct timespec ts;
++ s64 ns;
+
+ ktime_get_ts(&ts);
+- *p++ = timespec_to_ns(&ts);
+- *p = (unsigned long)nsm;
++ ns = timespec_to_ns(&ts);
++ put_unaligned(ns, p);
++ put_unaligned((unsigned long)nsm, p + 1);
+ }
+
+ static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch
new file mode 100644
index 0000000000..c2c9bc2b62
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch
@@ -0,0 +1,1226 @@
+From a62a047ed02162573e4bece18ecf8bdd66ccd06b Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Mon, 26 Jan 2009 15:13:40 +0200
+Subject: [PATCH] omap iommu: tlb and pagetable primitives
+
+This patch provides:
+
+- iotlb_*() : iommu tlb operations
+- iopgtable_*() : iommu pagetable(twl) operations
+- iommu_*() : the other generic operations
+
+and the entry points to register and acquire iommu object.
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/iommu.h | 157 +++++
+ arch/arm/plat-omap/iommu.c | 953 +++++++++++++++++++++++++++++++
+ arch/arm/plat-omap/iopgtable.h | 72 +++
+ 3 files changed, 1182 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
+ create mode 100644 arch/arm/plat-omap/iommu.c
+ create mode 100644 arch/arm/plat-omap/iopgtable.h
+
+diff --git a/arch/arm/plat-omap/include/mach/iommu.h b/arch/arm/plat-omap/include/mach/iommu.h
+new file mode 100644
+index 0000000..ef04d7a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/iommu.h
+@@ -0,0 +1,157 @@
++/*
++ * omap iommu: main structures
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __MACH_IOMMU_H
++#define __MACH_IOMMU_H
++
++struct iotlb_entry {
++ u32 da;
++ u32 pa;
++ u32 pgsz, prsvd, valid;
++ union {
++ u16 ap;
++ struct {
++ u32 endian, elsz, mixed;
++ };
++ };
++};
++
++struct iommu {
++ const char *name;
++ struct module *owner;
++ struct clk *clk;
++ void __iomem *regbase;
++ struct device *dev;
++
++ unsigned int refcount;
++ struct mutex iommu_lock; /* global for this whole object */
++
++ /*
++ * We don't change iopgd for a situation like pgd for a task,
++ * but share it globally for each iommu.
++ */
++ u32 *iopgd;
++ spinlock_t page_table_lock; /* protect iopgd */
++
++ int nr_tlb_entries;
++
++ struct list_head mmap;
++ struct mutex mmap_lock; /* protect mmap */
++
++ int (*isr)(struct iommu *obj);
++
++ void *ctx; /* iommu context: registres saved area */
++};
++
++struct cr_regs {
++ union {
++ struct {
++ u16 cam_l;
++ u16 cam_h;
++ };
++ u32 cam;
++ };
++ union {
++ struct {
++ u16 ram_l;
++ u16 ram_h;
++ };
++ u32 ram;
++ };
++};
++
++struct iotlb_lock {
++ short base;
++ short vict;
++};
++
++/* architecture specific functions */
++struct iommu_functions {
++ unsigned long version;
++
++ int (*enable)(struct iommu *obj);
++ void (*disable)(struct iommu *obj);
++ u32 (*fault_isr)(struct iommu *obj, u32 *ra);
++
++ void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
++ void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
++
++ struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
++ int (*cr_valid)(struct cr_regs *cr);
++ u32 (*cr_to_virt)(struct cr_regs *cr);
++ void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
++ ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
++
++ u32 (*get_pte_attr)(struct iotlb_entry *e);
++
++ void (*save_ctx)(struct iommu *obj);
++ void (*restore_ctx)(struct iommu *obj);
++ ssize_t (*dump_ctx)(struct iommu *obj, char *buf);
++};
++
++struct iommu_platform_data {
++ const char *name;
++ const char *clk_name;
++ const int nr_tlb_entries;
++};
++
++#include <mach/iommu2.h>
++
++/*
++ * utilities for super page(16MB, 1MB, 64KB and 4KB)
++ */
++
++#define iopgsz_max(bytes) \
++ (((bytes) >= SZ_16M) ? SZ_16M : \
++ ((bytes) >= SZ_1M) ? SZ_1M : \
++ ((bytes) >= SZ_64K) ? SZ_64K : \
++ ((bytes) >= SZ_4K) ? SZ_4K : 0)
++
++#define bytes_to_iopgsz(bytes) \
++ (((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M : \
++ ((bytes) == SZ_1M) ? MMU_CAM_PGSZ_1M : \
++ ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K : \
++ ((bytes) == SZ_4K) ? MMU_CAM_PGSZ_4K : -1)
++
++#define iopgsz_to_bytes(iopgsz) \
++ (((iopgsz) == MMU_CAM_PGSZ_16M) ? SZ_16M : \
++ ((iopgsz) == MMU_CAM_PGSZ_1M) ? SZ_1M : \
++ ((iopgsz) == MMU_CAM_PGSZ_64K) ? SZ_64K : \
++ ((iopgsz) == MMU_CAM_PGSZ_4K) ? SZ_4K : 0)
++
++#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0)
++
++/*
++ * global functions
++ */
++extern u32 iommu_arch_version(void);
++
++extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
++extern void flush_iotlb_page(struct iommu *obj, u32 da);
++extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
++extern void flush_iotlb_all(struct iommu *obj);
++
++ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf);
++
++extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
++extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
++
++extern struct iommu *iommu_get(const char *name);
++extern void iommu_put(struct iommu *obj);
++
++extern void iommu_save_ctx(struct iommu *obj);
++extern void iommu_restore_ctx(struct iommu *obj);
++
++extern int install_iommu_arch(const struct iommu_functions *ops);
++extern void uninstall_iommu_arch(const struct iommu_functions *ops);
++
++#endif /* __MACH_IOMMU_H */
+diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
+new file mode 100644
+index 0000000..e638883
+--- /dev/null
++++ b/arch/arm/plat-omap/iommu.c
+@@ -0,0 +1,953 @@
++/*
++ * omap iommu: tlb and pagetable primitives
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
++ * Paul Mundt and Toshihiro Kobayashi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++#include <asm/io.h>
++#include <asm/cacheflush.h>
++
++#include <mach/clock.h>
++#include <mach/iommu.h>
++
++#include "iopgtable.h"
++
++/* accommodate the difference between omap1 and omap2/3 */
++static const struct iommu_functions *arch_iommu;
++
++static struct platform_driver omap_iommu_driver;
++static struct kmem_cache *iopte_cachep;
++
++/**
++ * install_iommu_arch() - Install archtecure specific iommu functions
++ * @ops: a pointer to architecture specific iommu functions
++ *
++ * There are several kind of iommu algorithm(tlb, pagetable) among
++ * omap series. This interface installs such an iommu algorighm.
++ **/
++int install_iommu_arch(const struct iommu_functions *ops)
++{
++ if (arch_iommu)
++ return -EBUSY;
++
++ arch_iommu = ops;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(install_iommu_arch);
++
++/**
++ * uninstall_iommu_arch() - Uninstall archtecure specific iommu functions
++ * @ops: a pointer to architecture specific iommu functions
++ *
++ * This interface uninstalls the iommu algorighm installed previously.
++ **/
++void uninstall_iommu_arch(const struct iommu_functions *ops)
++{
++ if (arch_iommu != ops)
++ pr_err("%s: not your arch\n", __func__);
++
++ arch_iommu = NULL;
++}
++EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
++
++/**
++ * iommu_save_ctx() - Save registers for pm off-mode support
++ * @obj: target iommu
++ **/
++void iommu_save_ctx(struct iommu *obj)
++{
++ arch_iommu->save_ctx(obj);
++}
++EXPORT_SYMBOL_GPL(iommu_save_ctx);
++
++/**
++ * iommu_restore_ctx() - Restore registers for pm off-mode support
++ * @obj: target iommu
++ **/
++void iommu_restore_ctx(struct iommu *obj)
++{
++ arch_iommu->restore_ctx(obj);
++}
++EXPORT_SYMBOL_GPL(iommu_restore_ctx);
++
++/**
++ * iommu_arch_version() - Return running iommu arch version
++ **/
++u32 iommu_arch_version(void)
++{
++ return arch_iommu->version;
++}
++EXPORT_SYMBOL_GPL(iommu_arch_version);
++
++static int iommu_enable(struct iommu *obj)
++{
++ int err;
++
++ if (!obj)
++ return -EINVAL;
++
++ clk_enable(obj->clk);
++
++ err = arch_iommu->enable(obj);
++
++ clk_disable(obj->clk);
++ return err;
++}
++
++static void iommu_disable(struct iommu *obj)
++{
++ if (!obj)
++ return;
++
++ clk_enable(obj->clk);
++
++ arch_iommu->disable(obj);
++
++ clk_disable(obj->clk);
++}
++
++#ifdef DEBUG
++static ssize_t iommu_dump_ctx(struct iommu *obj, char *buf)
++{
++ if (!obj || !buf)
++ return -EINVAL;
++
++ return arch_iommu->dump_ctx(obj, buf);
++}
++#endif
++
++/*
++ * TLB operations
++ */
++static inline void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
++{
++ BUG_ON(!cr || !e);
++
++ arch_iommu->cr_to_e(cr, e);
++}
++
++static inline int iotlb_cr_valid(struct cr_regs *cr)
++{
++ if (!cr)
++ return -EINVAL;
++
++ return arch_iommu->cr_valid(cr);
++}
++
++static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
++ struct iotlb_entry *e)
++{
++ if (!e)
++ return NULL;
++
++ return arch_iommu->alloc_cr(obj, e);
++}
++
++static inline u32 iotlb_cr_to_virt(struct cr_regs *cr)
++{
++ return arch_iommu->cr_to_virt(cr);
++}
++
++static u32 get_iopte_attr(struct iotlb_entry *e)
++{
++ return arch_iommu->get_pte_attr(e);
++}
++
++static u32 iommu_report_fault(struct iommu *obj, u32 *da)
++{
++ return arch_iommu->fault_isr(obj, da);
++}
++
++static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
++{
++ u32 val;
++
++ val = iommu_read_reg(obj, MMU_LOCK);
++
++ l->base = MMU_LOCK_BASE(val);
++ l->vict = MMU_LOCK_VICT(val);
++
++ BUG_ON(l->base != 0); /* Currently no preservation is used */
++}
++
++static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
++{
++ u32 val;
++
++ BUG_ON(l->base != 0); /* Currently no preservation is used */
++
++ val = (l->base << MMU_LOCK_BASE_SHIFT);
++ val |= (l->vict << MMU_LOCK_VICT_SHIFT);
++
++ iommu_write_reg(obj, val, MMU_LOCK);
++}
++
++static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
++{
++ arch_iommu->tlb_read_cr(obj, cr);
++}
++
++static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
++{
++ arch_iommu->tlb_load_cr(obj, cr);
++
++ iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
++ iommu_write_reg(obj, 1, MMU_LD_TLB);
++}
++
++/**
++ * iotlb_dump_cr() - Dump an iommu tlb entry into buf
++ * @obj: target iommu
++ * @cr: contents of cam and ram register
++ * @buf: output buffer
++ **/
++ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
++{
++ BUG_ON(!cr || !buf);
++
++ return arch_iommu->dump_cr(obj, cr, buf);
++}
++EXPORT_SYMBOL_GPL(iotlb_dump_cr);
++
++/**
++ * load_iotlb_entry() - Set an iommu tlb entry
++ * @obj: target iommu
++ * @e: an iommu tlb entry info
++ **/
++int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
++{
++ int i;
++ int err = 0;
++ struct iotlb_lock l;
++ struct cr_regs *cr;
++
++ if (!obj || !obj->nr_tlb_entries || !e)
++ return -EINVAL;
++
++ clk_enable(obj->clk);
++
++ for (i = 0; i < obj->nr_tlb_entries; i++) {
++ struct cr_regs tmp;
++
++ iotlb_lock_get(obj, &l);
++ l.vict = i;
++ iotlb_lock_set(obj, &l);
++ iotlb_read_cr(obj, &tmp);
++ if (!iotlb_cr_valid(&tmp))
++ break;
++ }
++
++ if (i == obj->nr_tlb_entries) {
++ dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
++ err = -EBUSY;
++ goto out;
++ }
++
++ cr = iotlb_alloc_cr(obj, e);
++ if (IS_ERR(cr)) {
++ clk_disable(obj->clk);
++ return PTR_ERR(cr);
++ }
++
++ iotlb_load_cr(obj, cr);
++ kfree(cr);
++
++ /* increment victim for next tlb load */
++ if (++l.vict == obj->nr_tlb_entries)
++ l.vict = 0;
++ iotlb_lock_set(obj, &l);
++out:
++ clk_disable(obj->clk);
++ return err;
++}
++EXPORT_SYMBOL_GPL(load_iotlb_entry);
++
++/**
++ * flush_iotlb_page() - Clear an iommu tlb entry
++ * @obj: target iommu
++ * @da: iommu device virtual address
++ *
++ * Clear an iommu tlb entry which includes 'da' address.
++ **/
++void flush_iotlb_page(struct iommu *obj, u32 da)
++{
++ struct iotlb_lock l;
++ int i;
++
++ clk_enable(obj->clk);
++
++ for (i = 0; i < obj->nr_tlb_entries; i++) {
++ struct cr_regs cr;
++ u32 start;
++ size_t bytes;
++
++ iotlb_lock_get(obj, &l);
++ l.vict = i;
++ iotlb_lock_set(obj, &l);
++ iotlb_read_cr(obj, &cr);
++ if (!iotlb_cr_valid(&cr))
++ continue;
++
++ start = iotlb_cr_to_virt(&cr);
++ bytes = iopgsz_to_bytes(cr.cam & 3);
++
++ if ((start <= da) && (da < start + bytes)) {
++ dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
++ __func__, start, da, bytes);
++
++ iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
++ }
++ }
++ clk_disable(obj->clk);
++
++ if (i == obj->nr_tlb_entries)
++ dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
++}
++EXPORT_SYMBOL_GPL(flush_iotlb_page);
++
++/**
++ * flush_iotlb_range() - Clear an iommu tlb entries
++ * @obj: target iommu
++ * @start: iommu device virtual address(start)
++ * @end: iommu device virtual address(end)
++ *
++ * Clear an iommu tlb entry which includes 'da' address.
++ **/
++void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
++{
++ u32 da = start;
++
++ while (da < end) {
++ flush_iotlb_page(obj, da);
++ /* FIXME: Optimize for multiple page size */
++ da += IOPTE_SIZE;
++ }
++}
++EXPORT_SYMBOL_GPL(flush_iotlb_range);
++
++/**
++ * flush_iotlb_all() - Clear all iommu tlb entries
++ * @obj: target iommu
++ **/
++void flush_iotlb_all(struct iommu *obj)
++{
++ struct iotlb_lock l;
++
++ clk_enable(obj->clk);
++
++ l.base = 0;
++ l.vict = 0;
++ iotlb_lock_set(obj, &l);
++
++ iommu_write_reg(obj, 1, MMU_GFLUSH);
++
++ clk_disable(obj->clk);
++}
++EXPORT_SYMBOL_GPL(flush_iotlb_all);
++
++/*
++ * H/W pagetable operations
++ */
++static void flush_iopgd_range(u32 *first, u32 *last)
++{
++ /* FIXME: L2 cache should be taken care of if it exists */
++ do {
++ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pgd"
++ : : "r" (first));
++ first += L1_CACHE_BYTES / sizeof(*first);
++ } while (first <= last);
++}
++
++static void flush_iopte_range(u32 *first, u32 *last)
++{
++ /* FIXME: L2 cache should be taken care of if it exists */
++ do {
++ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pte"
++ : : "r" (first));
++ first += L1_CACHE_BYTES / sizeof(*first);
++ } while (first <= last);
++}
++
++static void iopte_free(u32 *iopte)
++{
++ /* Note: freed iopte's must be clean ready for re-use */
++ kmem_cache_free(iopte_cachep, iopte);
++}
++
++static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
++{
++ u32 *iopte;
++
++ /* a table has already existed */
++ if (*iopgd)
++ goto pte_ready;
++
++ /*
++ * do the allocation outside the page table lock
++ */
++ spin_unlock(&obj->page_table_lock);
++ iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
++ spin_lock(&obj->page_table_lock);
++
++ if (!*iopgd) {
++ if (!iopte)
++ return ERR_PTR(-ENOMEM);
++
++ *iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
++ flush_iopgd_range(iopgd, iopgd);
++
++ dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
++ } else {
++ /* We raced, free the reduniovant table */
++ iopte_free(iopte);
++ }
++
++pte_ready:
++ iopte = iopte_offset(iopgd, da);
++
++ dev_vdbg(obj->dev,
++ "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
++ __func__, da, iopgd, *iopgd, iopte, *iopte);
++
++ return iopte;
++}
++
++static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
++{
++ u32 *iopgd = iopgd_offset(obj, da);
++
++ *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
++ flush_iopgd_range(iopgd, iopgd);
++ return 0;
++}
++
++static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
++{
++ u32 *iopgd = iopgd_offset(obj, da);
++ int i;
++
++ for (i = 0; i < 16; i++)
++ *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
++ flush_iopgd_range(iopgd, iopgd + 15);
++ return 0;
++}
++
++static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
++{
++ u32 *iopgd = iopgd_offset(obj, da);
++ u32 *iopte = iopte_alloc(obj, iopgd, da);
++
++ if (IS_ERR(iopte))
++ return PTR_ERR(iopte);
++
++ *iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
++ flush_iopte_range(iopte, iopte);
++
++ dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
++ __func__, da, pa, iopte, *iopte);
++
++ return 0;
++}
++
++static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
++{
++ u32 *iopgd = iopgd_offset(obj, da);
++ u32 *iopte = iopte_alloc(obj, iopgd, da);
++ int i;
++
++ if (IS_ERR(iopte))
++ return PTR_ERR(iopte);
++
++ for (i = 0; i < 16; i++)
++ *(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
++ flush_iopte_range(iopte, iopte + 15);
++ return 0;
++}
++
++static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
++{
++ int (*fn)(struct iommu *, u32, u32, u32);
++ u32 prot;
++ int err;
++
++ if (!obj || !e)
++ return -EINVAL;
++
++ switch (e->pgsz) {
++ case MMU_CAM_PGSZ_16M:
++ fn = iopgd_alloc_super;
++ break;
++ case MMU_CAM_PGSZ_1M:
++ fn = iopgd_alloc_section;
++ break;
++ case MMU_CAM_PGSZ_64K:
++ fn = iopte_alloc_large;
++ break;
++ case MMU_CAM_PGSZ_4K:
++ fn = iopte_alloc_page;
++ break;
++ default:
++ fn = NULL;
++ BUG();
++ break;
++ }
++
++ prot = get_iopte_attr(e);
++
++ spin_lock(&obj->page_table_lock);
++ err = fn(obj, e->da, e->pa, prot);
++ spin_unlock(&obj->page_table_lock);
++
++ return err;
++}
++
++#ifdef DEBUG
++static void dump_tlb_entries(struct iommu *obj)
++{
++ int i;
++ struct iotlb_lock l;
++
++ clk_enable(obj->clk);
++
++ pr_info("%8s %8s\n", "cam:", "ram:");
++ pr_info("-----------------------------------------\n");
++
++ for (i = 0; i < obj->nr_tlb_entries; i++) {
++ struct cr_regs cr;
++ static char buf[4096];
++
++ iotlb_lock_get(obj, &l);
++ l.vict = i;
++ iotlb_lock_set(obj, &l);
++ iotlb_read_cr(obj, &cr);
++ if (!iotlb_cr_valid(&cr))
++ continue;
++
++ memset(buf, 0, 4096);
++ iotlb_dump_cr(obj, &cr, buf);
++ pr_err("%s", buf);
++ }
++
++ clk_disable(obj->clk);
++}
++#else
++static inline void dump_tlb_entries(struct iommu *obj) {}
++#endif
++
++/**
++ * iopgtable_store_entry() - Make an iommu pte entry
++ * @obj: target iommu
++ * @e: an iommu tlb entry info
++ **/
++int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
++{
++ int err;
++
++ flush_iotlb_page(obj, e->da);
++ err = iopgtable_store_entry_core(obj, e);
++#ifdef USE_IOTLB
++ if (!err)
++ load_iotlb_entry(obj, e);
++#endif
++ return err;
++}
++EXPORT_SYMBOL_GPL(iopgtable_store_entry);
++
++/**
++ * iopgtable_lookup_entry() - Lookup an iommu pte entry
++ * @obj: target iommu
++ * @da: iommu device virtual address
++ * @ppgd: iommu pgd entry pointer to be returned
++ * @ppte: iommu pte entry pointer to be returned
++ **/
++void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
++{
++ u32 *iopgd, *iopte = NULL;
++
++ iopgd = iopgd_offset(obj, da);
++ if (!*iopgd)
++ goto out;
++
++ if (*iopgd & IOPGD_TABLE)
++ iopte = iopte_offset(iopgd, da);
++out:
++ *ppgd = iopgd;
++ *ppte = iopte;
++}
++EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
++
++static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
++{
++ size_t bytes;
++ u32 *iopgd = iopgd_offset(obj, da);
++ int nent = 1;
++
++ if (!*iopgd)
++ return 0;
++
++ if (*iopgd & IOPGD_TABLE) {
++ int i;
++ u32 *iopte = iopte_offset(iopgd, da);
++
++ bytes = IOPTE_SIZE;
++ if (*iopte & IOPTE_LARGE) {
++ nent *= 16;
++ /* rewind to the 1st entry */
++ iopte = (u32 *)((u32)iopte & IOLARGE_MASK);
++ }
++ bytes *= nent;
++ memset(iopte, 0, nent * sizeof(*iopte));
++ flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
++
++ /*
++ * do table walk to check if this table is necessary or not
++ */
++ iopte = iopte_offset(iopgd, 0);
++ for (i = 0; i < PTRS_PER_IOPTE; i++)
++ if (iopte[i])
++ goto out;
++
++ iopte_free(iopte);
++ nent = 1; /* for the next L1 entry */
++ } else {
++ bytes = IOPGD_SIZE;
++ if (*iopgd & IOPGD_SUPER) {
++ nent *= 16;
++ /* rewind to the 1st entry */
++ iopgd = (u32 *)((u32)iopgd & IOSUPER_MASK);
++ }
++ bytes *= nent;
++ }
++ memset(iopgd, 0, nent * sizeof(*iopgd));
++ flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
++out:
++ return bytes;
++}
++
++/**
++ * iopgtable_clear_entry() - Remove an iommu pte entry
++ * @obj: target iommu
++ * @da: iommu device virtual address
++ **/
++size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
++{
++ size_t bytes;
++
++ spin_lock(&obj->page_table_lock);
++
++ bytes = iopgtable_clear_entry_core(obj, da);
++ flush_iotlb_page(obj, da);
++
++ spin_unlock(&obj->page_table_lock);
++
++ return bytes;
++}
++EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
++
++static void iopgtable_clear_entry_all(struct iommu *obj)
++{
++ int i;
++
++ spin_lock(&obj->page_table_lock);
++
++ for (i = 0; i < PTRS_PER_IOPGD; i++) {
++ u32 da;
++ u32 *iopgd;
++
++ da = i << IOPGD_SHIFT;
++ iopgd = iopgd_offset(obj, da);
++
++ if (!*iopgd)
++ continue;
++
++ if (*iopgd & IOPGD_TABLE)
++ iopte_free(iopte_offset(iopgd, 0));
++
++ *iopgd = 0;
++ flush_iopgd_range(iopgd, iopgd);
++ }
++
++ flush_iotlb_all(obj);
++
++ spin_unlock(&obj->page_table_lock);
++}
++
++/*
++ * Device IOMMU generic operations
++ */
++static irqreturn_t iommu_fault_handler(int irq, void *data)
++{
++ u32 stat, da;
++ u32 *iopgd, *iopte;
++ int err = -EIO;
++ struct iommu *obj = data;
++
++ /* Dynamic loading TLB or PTE */
++ if (obj->isr)
++ err = obj->isr(obj);
++
++ if (!err)
++ return IRQ_HANDLED;
++
++ stat = iommu_report_fault(obj, &da);
++ if (!stat)
++ return IRQ_HANDLED;
++
++ iopgd = iopgd_offset(obj, da);
++
++ if (!(*iopgd & IOPGD_TABLE)) {
++ dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
++ da, iopgd, *iopgd);
++ return IRQ_NONE;
++ }
++
++ iopte = iopte_offset(iopgd, da);
++
++ dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
++ __func__, da, iopgd, *iopgd, iopte, *iopte);
++
++ dump_tlb_entries(obj);
++
++ return IRQ_NONE;
++}
++
++static int device_match_by_alias(struct device *dev, void *data)
++{
++ struct iommu *obj = to_iommu(dev);
++ const char *name = data;
++
++ pr_debug("%s: %s %s\n", __func__, obj->name, name);
++
++ return strcmp(obj->name, name) == 0;
++}
++
++/**
++ * iommu_put() - Get iommu handler
++ * @name: target iommu name
++ **/
++struct iommu *iommu_get(const char *name)
++{
++ int err = -ENOMEM;
++ struct device *dev;
++ struct iommu *obj;
++
++ dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
++ device_match_by_alias);
++ if (!dev)
++ return ERR_PTR(-ENODEV);
++
++ obj = to_iommu(dev);
++
++ mutex_lock(&obj->iommu_lock);
++
++ if (obj->refcount++ == 0) {
++ err = iommu_enable(obj);
++ if (err)
++ goto err_enable;
++ flush_iotlb_all(obj);
++ }
++
++ if (!try_module_get(obj->owner))
++ goto err_module;
++
++ mutex_unlock(&obj->iommu_lock);
++
++ dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
++ return obj;
++
++err_module:
++ if (obj->refcount == 1)
++ iommu_disable(obj);
++err_enable:
++ mutex_unlock(&obj->iommu_lock);
++ return ERR_PTR(err);
++}
++EXPORT_SYMBOL_GPL(iommu_get);
++
++/**
++ * iommu_put() - Put back iommu handler
++ * @obj: target iommu
++ **/
++void iommu_put(struct iommu *obj)
++{
++ if (!obj && IS_ERR(obj))
++ return;
++
++ mutex_lock(&obj->iommu_lock);
++
++ if (--obj->refcount == 0)
++ iommu_disable(obj);
++
++ module_put(obj->owner);
++
++ mutex_unlock(&obj->iommu_lock);
++
++ dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
++}
++EXPORT_SYMBOL_GPL(iommu_put);
++
++/*
++ * OMAP Device MMU(IOMMU) detection
++ */
++static int __devinit omap_iommu_probe(struct platform_device *pdev)
++{
++ int err = -ENODEV;
++ void *p;
++ int irq;
++ struct iommu *obj;
++ struct resource *res;
++ struct iommu_platform_data *pdata = pdev->dev.platform_data;
++
++ if (pdev->num_resources != 2)
++ return -EINVAL;
++
++ obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
++ if (!obj)
++ return -ENOMEM;
++
++ obj->clk = clk_get(&pdev->dev, pdata->clk_name);
++ if (IS_ERR(obj->clk))
++ goto err_clk;
++
++ obj->nr_tlb_entries = pdata->nr_tlb_entries;
++ obj->name = pdata->name;
++ obj->dev = &pdev->dev;
++ obj->ctx = (void *)obj + sizeof(*obj);
++
++ mutex_init(&obj->iommu_lock);
++ mutex_init(&obj->mmap_lock);
++ spin_lock_init(&obj->page_table_lock);
++ INIT_LIST_HEAD(&obj->mmap);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ err = -ENODEV;
++ goto err_mem;
++ }
++ obj->regbase = ioremap(res->start, resource_size(res));
++ if (!obj->regbase) {
++ err = -ENOMEM;
++ goto err_mem;
++ }
++
++ res = request_mem_region(res->start, resource_size(res),
++ dev_name(&pdev->dev));
++ if (!res) {
++ err = -EIO;
++ goto err_mem;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ err = -ENODEV;
++ goto err_irq;
++ }
++ err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
++ dev_name(&pdev->dev), obj);
++ if (err < 0)
++ goto err_irq;
++ platform_set_drvdata(pdev, obj);
++
++ p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
++ if (!p) {
++ err = -ENOMEM;
++ goto err_pgd;
++ }
++ memset(p, 0, IOPGD_TABLE_SIZE);
++ clean_dcache_area(p, IOPGD_TABLE_SIZE);
++ obj->iopgd = p;
++
++ BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
++
++ dev_info(&pdev->dev, "%s registered\n", obj->name);
++ return 0;
++
++err_pgd:
++ free_irq(irq, obj);
++err_irq:
++ release_mem_region(res->start, resource_size(res));
++ iounmap(obj->regbase);
++err_mem:
++ clk_put(obj->clk);
++err_clk:
++ kfree(obj);
++ return err;
++}
++
++static int __devexit omap_iommu_remove(struct platform_device *pdev)
++{
++ int irq;
++ struct resource *res;
++ struct iommu *obj = platform_get_drvdata(pdev);
++
++ platform_set_drvdata(pdev, NULL);
++
++ iopgtable_clear_entry_all(obj);
++ free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
++
++ irq = platform_get_irq(pdev, 0);
++ free_irq(irq, obj);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, resource_size(res));
++ iounmap(obj->regbase);
++
++ clk_put(obj->clk);
++ dev_info(&pdev->dev, "%s removed\n", obj->name);
++ kfree(obj);
++ return 0;
++}
++
++static struct platform_driver omap_iommu_driver = {
++ .probe = omap_iommu_probe,
++ .remove = __devexit_p(omap_iommu_remove),
++ .driver = {
++ .name = "omap-iommu",
++ },
++};
++
++static void iopte_cachep_ctor(void *iopte)
++{
++ clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
++}
++
++static int __init omap_iommu_init(void)
++{
++ struct kmem_cache *p;
++ const unsigned long flags = SLAB_HWCACHE_ALIGN;
++
++ p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, 0, flags,
++ iopte_cachep_ctor);
++ if (!p)
++ return -ENOMEM;
++ iopte_cachep = p;
++
++ return platform_driver_register(&omap_iommu_driver);
++}
++module_init(omap_iommu_init);
++
++static void __exit omap_iommu_exit(void)
++{
++ kmem_cache_destroy(iopte_cachep);
++
++ platform_driver_unregister(&omap_iommu_driver);
++}
++module_exit(omap_iommu_exit);
++
++MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
++MODULE_ALIAS("platform:omap-iommu");
++MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h
+new file mode 100644
+index 0000000..37dac43
+--- /dev/null
++++ b/arch/arm/plat-omap/iopgtable.h
+@@ -0,0 +1,72 @@
++/*
++ * omap iommu: pagetable definitions
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __PLAT_OMAP_IOMMU_H
++#define __PLAT_OMAP_IOMMU_H
++
++#define IOPGD_SHIFT 20
++#define IOPGD_SIZE (1 << IOPGD_SHIFT)
++#define IOPGD_MASK (~(IOPGD_SIZE - 1))
++#define IOSECTION_MASK IOPGD_MASK
++#define PTRS_PER_IOPGD (1 << (32 - IOPGD_SHIFT))
++#define IOPGD_TABLE_SIZE (PTRS_PER_IOPGD * sizeof(u32))
++
++#define IOSUPER_SIZE (IOPGD_SIZE << 4)
++#define IOSUPER_MASK (~(IOSUPER_SIZE - 1))
++
++#define IOPTE_SHIFT 12
++#define IOPTE_SIZE (1 << IOPTE_SHIFT)
++#define IOPTE_MASK (~(IOPTE_SIZE - 1))
++#define IOPAGE_MASK IOPTE_MASK
++#define PTRS_PER_IOPTE (1 << (IOPGD_SHIFT - IOPTE_SHIFT))
++#define IOPTE_TABLE_SIZE (PTRS_PER_IOPTE * sizeof(u32))
++
++#define IOLARGE_SIZE (IOPTE_SIZE << 4)
++#define IOLARGE_MASK (~(IOLARGE_SIZE - 1))
++
++#define IOPGD_TABLE (1 << 0)
++#define IOPGD_SECTION (2 << 0)
++#define IOPGD_SUPER (1 << 18 | 2 << 0)
++
++#define IOPTE_SMALL (2 << 0)
++#define IOPTE_LARGE (1 << 0)
++
++#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
++#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
++
++#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
++#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd)))
++
++#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
++#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da))
++
++static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
++ u32 flags)
++{
++ memset(e, 0, sizeof(*e));
++
++ e->da = da;
++ e->pa = pa;
++ e->valid = 1;
++ /* FIXME: add OMAP1 support */
++ e->pgsz = flags & MMU_CAM_PGSZ_MASK;
++ e->endian = flags & MMU_RAM_ENDIAN_MASK;
++ e->elsz = flags & MMU_RAM_ELSZ_MASK;
++ e->mixed = flags & MMU_RAM_MIXED_MASK;
++
++ return iopgsz_to_bytes(e->pgsz);
++}
++
++#define to_iommu(dev) \
++ (struct iommu *)platform_get_drvdata(to_platform_device(dev))
++
++#endif /* __PLAT_OMAP_IOMMU_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch
new file mode 100644
index 0000000000..d5f78dd14e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch
@@ -0,0 +1,453 @@
+From c79d7959c45f40e47520aa6acd54c19094754787 Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Mon, 26 Jan 2009 15:13:45 +0200
+Subject: [PATCH] omap iommu: omap2 architecture specific functions
+
+The structure 'arch_mmu' accommodates the difference between omap1 and
+omap2/3.
+
+This patch provides omap2/3 specific functions
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/mach-omap2/iommu2.c | 326 ++++++++++++++++++++++++++++++
+ arch/arm/plat-omap/include/mach/iommu2.h | 94 +++++++++
+ 2 files changed, 420 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-omap2/iommu2.c
+ create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h
+
+diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
+new file mode 100644
+index 0000000..88a44f1
+--- /dev/null
++++ b/arch/arm/mach-omap2/iommu2.c
+@@ -0,0 +1,326 @@
++/*
++ * omap iommu: omap2/3 architecture specific functions
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
++ * Paul Mundt and Toshihiro Kobayashi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/err.h>
++#include <linux/device.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/stringify.h>
++
++#include <asm/io.h>
++
++#include <mach/iommu.h>
++#include <mach/iommu2.h>
++
++/*
++ * omap2 architecture specific register bit definitions
++ */
++#define IOMMU_ARCH_VERSION 0x00000011
++
++/* SYSCONF */
++#define MMU_SYS_IDLE_SHIFT 3
++#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
++#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
++#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
++#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
++
++#define MMU_SYS_SOFTRESET (1 << 1)
++#define MMU_SYS_AUTOIDLE 1
++
++/* SYSSTATUS */
++#define MMU_SYS_RESETDONE 1
++
++/* IRQSTATUS & IRQENABLE */
++#define MMU_IRQ_MULTIHITFAULT (1 << 4)
++#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
++#define MMU_IRQ_EMUMISS (1 << 2)
++#define MMU_IRQ_TRANSLATIONFAULT (1 << 1)
++#define MMU_IRQ_TLBMISS (1 << 0)
++#define MMU_IRQ_MASK \
++ (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \
++ MMU_IRQ_TRANSLATIONFAULT)
++
++/* MMU_CNTL */
++#define MMU_CNTL_SHIFT 1
++#define MMU_CNTL_MASK (7 << MMU_CNTL_SHIFT)
++#define MMU_CNTL_EML_TLB (1 << 3)
++#define MMU_CNTL_TWL_EN (1 << 2)
++#define MMU_CNTL_MMU_EN (1 << 1)
++
++#define get_cam_va_mask(pgsz) \
++ (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 : \
++ ((pgsz) == MMU_CAM_PGSZ_1M) ? 0xfff00000 : \
++ ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
++ ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
++
++static int omap2_iommu_enable(struct iommu *obj)
++{
++ u32 l, pa;
++ unsigned long timeout;
++
++ if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
++ return -EINVAL;
++
++ pa = virt_to_phys(obj->iopgd);
++ if (!IS_ALIGNED(pa, SZ_16K))
++ return -EINVAL;
++
++ iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
++
++ timeout = jiffies + msecs_to_jiffies(20);
++ do {
++ l = iommu_read_reg(obj, MMU_SYSSTATUS);
++ if (l & MMU_SYS_RESETDONE)
++ break;
++ } while (time_after(jiffies, timeout));
++
++ if (!(l & MMU_SYS_RESETDONE)) {
++ dev_err(obj->dev, "can't take mmu out of reset\n");
++ return -ENODEV;
++ }
++
++ l = iommu_read_reg(obj, MMU_REVISION);
++ dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
++ (l >> 4) & 0xf, l & 0xf);
++
++ l = iommu_read_reg(obj, MMU_SYSCONFIG);
++ l &= ~MMU_SYS_IDLE_MASK;
++ l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
++ iommu_write_reg(obj, l, MMU_SYSCONFIG);
++
++ iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE);
++ iommu_write_reg(obj, pa, MMU_TTB);
++
++ l = iommu_read_reg(obj, MMU_CNTL);
++ l &= ~MMU_CNTL_MASK;
++ l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
++ iommu_write_reg(obj, l, MMU_CNTL);
++
++ return 0;
++}
++
++static void omap2_iommu_disable(struct iommu *obj)
++{
++ u32 l = iommu_read_reg(obj, MMU_CNTL);
++
++ l &= ~MMU_CNTL_MASK;
++ iommu_write_reg(obj, l, MMU_CNTL);
++ iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
++
++ dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
++}
++
++static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
++{
++ int i;
++ u32 stat, da;
++ const char *err_msg[] = {
++ "tlb miss",
++ "translation fault",
++ "emulation miss",
++ "table walk fault",
++ "multi hit fault",
++ };
++
++ stat = iommu_read_reg(obj, MMU_IRQSTATUS);
++ stat &= MMU_IRQ_MASK;
++ if (!stat)
++ return 0;
++
++ da = iommu_read_reg(obj, MMU_FAULT_AD);
++ *ra = da;
++
++ dev_err(obj->dev, "%s:\tda:%08x ", __func__, da);
++
++ for (i = 0; i < ARRAY_SIZE(err_msg); i++) {
++ if (stat & (1 << i))
++ printk("%s ", err_msg[i]);
++ }
++ printk("\n");
++
++ iommu_write_reg(obj, stat, MMU_IRQSTATUS);
++ return stat;
++}
++
++static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
++{
++ cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
++ cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
++}
++
++static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
++{
++ iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
++ iommu_write_reg(obj, cr->ram, MMU_RAM);
++}
++
++static u32 omap2_cr_to_virt(struct cr_regs *cr)
++{
++ u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
++ u32 mask = get_cam_va_mask(cr->cam & page_size);
++
++ return cr->cam & mask;
++}
++
++static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
++{
++ struct cr_regs *cr;
++
++ if (e->da & ~(get_cam_va_mask(e->pgsz))) {
++ dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
++ e->da);
++ return ERR_PTR(-EINVAL);
++ }
++
++ cr = kmalloc(sizeof(*cr), GFP_KERNEL);
++ if (!cr)
++ return ERR_PTR(-ENOMEM);
++
++ cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz;
++ cr->ram = e->pa | e->endian | e->elsz | e->mixed;
++
++ return cr;
++}
++
++static inline int omap2_cr_valid(struct cr_regs *cr)
++{
++ return cr->cam & MMU_CAM_V;
++}
++
++static u32 omap2_get_pte_attr(struct iotlb_entry *e)
++{
++ u32 attr;
++
++ attr = e->mixed << 5;
++ attr |= e->endian;
++ attr |= e->elsz >> 3;
++ attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
++
++ return attr;
++}
++
++static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
++{
++ char *p = buf;
++
++ /* FIXME: Need more detail analysis of cam/ram */
++ p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram);
++
++ return p - buf;
++}
++
++#define pr_reg(name) \
++ p += sprintf(p, "%20s: %08x\n", \
++ __stringify(name), iommu_read_reg(obj, MMU_##name));
++
++static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf)
++{
++ char *p = buf;
++
++ pr_reg(REVISION);
++ pr_reg(SYSCONFIG);
++ pr_reg(SYSSTATUS);
++ pr_reg(IRQSTATUS);
++ pr_reg(IRQENABLE);
++ pr_reg(WALKING_ST);
++ pr_reg(CNTL);
++ pr_reg(FAULT_AD);
++ pr_reg(TTB);
++ pr_reg(LOCK);
++ pr_reg(LD_TLB);
++ pr_reg(CAM);
++ pr_reg(RAM);
++ pr_reg(GFLUSH);
++ pr_reg(FLUSH_ENTRY);
++ pr_reg(READ_CAM);
++ pr_reg(READ_RAM);
++ pr_reg(EMU_FAULT_AD);
++
++ return p - buf;
++}
++
++static void omap2_iommu_save_ctx(struct iommu *obj)
++{
++ int i;
++ u32 *p = obj->ctx;
++
++ for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
++ p[i] = iommu_read_reg(obj, i * sizeof(u32));
++ dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
++ }
++
++ BUG_ON(p[0] != IOMMU_ARCH_VERSION);
++}
++
++static void omap2_iommu_restore_ctx(struct iommu *obj)
++{
++ int i;
++ u32 *p = obj->ctx;
++
++ for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
++ iommu_write_reg(obj, p[i], i * sizeof(u32));
++ dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
++ }
++
++ BUG_ON(p[0] != IOMMU_ARCH_VERSION);
++}
++
++static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
++{
++ e->da = cr->cam & MMU_CAM_VATAG_MASK;
++ e->pa = cr->ram & MMU_RAM_PADDR_MASK;
++ e->valid = cr->cam & MMU_CAM_V;
++ e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK;
++ e->endian = cr->ram & MMU_RAM_ENDIAN_MASK;
++ e->elsz = cr->ram & MMU_RAM_ELSZ_MASK;
++ e->mixed = cr->ram & MMU_RAM_MIXED;
++}
++
++static const struct iommu_functions omap2_iommu_ops = {
++ .version = IOMMU_ARCH_VERSION,
++
++ .enable = omap2_iommu_enable,
++ .disable = omap2_iommu_disable,
++ .fault_isr = omap2_iommu_fault_isr,
++
++ .tlb_read_cr = omap2_tlb_read_cr,
++ .tlb_load_cr = omap2_tlb_load_cr,
++
++ .cr_to_e = omap2_cr_to_e,
++ .cr_to_virt = omap2_cr_to_virt,
++ .alloc_cr = omap2_alloc_cr,
++ .cr_valid = omap2_cr_valid,
++ .dump_cr = omap2_dump_cr,
++
++ .get_pte_attr = omap2_get_pte_attr,
++
++ .save_ctx = omap2_iommu_save_ctx,
++ .restore_ctx = omap2_iommu_restore_ctx,
++ .dump_ctx = omap2_iommu_dump_ctx,
++};
++
++static int __init omap2_iommu_init(void)
++{
++ return install_iommu_arch(&omap2_iommu_ops);
++}
++module_init(omap2_iommu_init);
++
++static void __exit omap2_iommu_exit(void)
++{
++ uninstall_iommu_arch(&omap2_iommu_ops);
++}
++module_exit(omap2_iommu_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
++MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/plat-omap/include/mach/iommu2.h b/arch/arm/plat-omap/include/mach/iommu2.h
+new file mode 100644
+index 0000000..d746047
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/iommu2.h
+@@ -0,0 +1,94 @@
++/*
++ * omap iommu: omap2 architecture specific definitions
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __MACH_IOMMU2_H
++#define __MACH_IOMMU2_H
++
++/*
++ * MMU Register offsets
++ */
++#define MMU_REVISION 0x00
++#define MMU_SYSCONFIG 0x10
++#define MMU_SYSSTATUS 0x14
++#define MMU_IRQSTATUS 0x18
++#define MMU_IRQENABLE 0x1c
++#define MMU_WALKING_ST 0x40
++#define MMU_CNTL 0x44
++#define MMU_FAULT_AD 0x48
++#define MMU_TTB 0x4c
++#define MMU_LOCK 0x50
++#define MMU_LD_TLB 0x54
++#define MMU_CAM 0x58
++#define MMU_RAM 0x5c
++#define MMU_GFLUSH 0x60
++#define MMU_FLUSH_ENTRY 0x64
++#define MMU_READ_CAM 0x68
++#define MMU_READ_RAM 0x6c
++#define MMU_EMU_FAULT_AD 0x70
++
++#define MMU_REG_SIZE 256
++
++/*
++ * MMU Register bit definitions
++ */
++#define MMU_LOCK_BASE_SHIFT 10
++#define MMU_LOCK_BASE_MASK (0x1f << MMU_LOCK_BASE_SHIFT)
++#define MMU_LOCK_BASE(x) \
++ ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
++
++#define MMU_LOCK_VICT_SHIFT 4
++#define MMU_LOCK_VICT_MASK (0x1f << MMU_LOCK_VICT_SHIFT)
++#define MMU_LOCK_VICT(x) \
++ ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
++
++#define MMU_CAM_VATAG_SHIFT 12
++#define MMU_CAM_VATAG_MASK \
++ ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
++#define MMU_CAM_P (1 << 3)
++#define MMU_CAM_V (1 << 2)
++#define MMU_CAM_PGSZ_MASK 3
++#define MMU_CAM_PGSZ_1M (0 << 0)
++#define MMU_CAM_PGSZ_64K (1 << 0)
++#define MMU_CAM_PGSZ_4K (2 << 0)
++#define MMU_CAM_PGSZ_16M (3 << 0)
++
++#define MMU_RAM_PADDR_SHIFT 12
++#define MMU_RAM_PADDR_MASK \
++ ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
++#define MMU_RAM_ENDIAN_SHIFT 9
++#define MMU_RAM_ENDIAN_MASK (1 << MMU_RAM_ENDIAN_SHIFT)
++#define MMU_RAM_ENDIAN_BIG (1 << MMU_RAM_ENDIAN_SHIFT)
++#define MMU_RAM_ENDIAN_LITTLE (0 << MMU_RAM_ENDIAN_SHIFT)
++#define MMU_RAM_ELSZ_SHIFT 7
++#define MMU_RAM_ELSZ_MASK (3 << MMU_RAM_ELSZ_SHIFT)
++#define MMU_RAM_ELSZ_8 (0 << MMU_RAM_ELSZ_SHIFT)
++#define MMU_RAM_ELSZ_16 (1 << MMU_RAM_ELSZ_SHIFT)
++#define MMU_RAM_ELSZ_32 (2 << MMU_RAM_ELSZ_SHIFT)
++#define MMU_RAM_ELSZ_NONE (3 << MMU_RAM_ELSZ_SHIFT)
++#define MMU_RAM_MIXED_SHIFT 6
++#define MMU_RAM_MIXED_MASK (1 << MMU_RAM_MIXED_SHIFT)
++#define MMU_RAM_MIXED MMU_RAM_MIXED_MASK
++
++/*
++ * register accessors
++ */
++static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
++{
++ return __raw_readl(obj->regbase + offs);
++}
++
++static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
++{
++ __raw_writel(val, obj->regbase + offs);
++}
++
++#endif /* __MACH_IOMMU2_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch
new file mode 100644
index 0000000000..2954c47872
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch
@@ -0,0 +1,124 @@
+From 6a84082597dd322713c5d5951530e3eecb878ad4 Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Wed, 28 Jan 2009 21:32:04 +0200
+Subject: [PATCH] omap iommu: omap3 iommu device registration
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/mach-omap2/omap3-iommu.c | 104 +++++++++++++++++++++++++++++++++++++
+ 1 files changed, 104 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
+
+diff --git a/arch/arm/mach-omap2/omap3-iommu.c b/arch/arm/mach-omap2/omap3-iommu.c
+new file mode 100644
+index 0000000..97481cc
+--- /dev/null
++++ b/arch/arm/mach-omap2/omap3-iommu.c
+@@ -0,0 +1,104 @@
++/*
++ * omap iommu: omap3 device registration
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <linux/io.h>
++
++#include <mach/iommu.h>
++
++#define OMAP3_MMU1_BASE 0x480bd400
++#define OMAP3_MMU2_BASE 0x5d000000
++#define OMAP3_MMU1_IRQ 24
++#define OMAP3_MMU2_IRQ 28
++
++static struct resource omap3_iommu_res[] = {
++ { /* Camera ISP MMU */
++ .start = OMAP3_MMU1_BASE,
++ .end = OMAP3_MMU1_BASE + MMU_REG_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = OMAP3_MMU1_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++ { /* IVA2.2 MMU */
++ .start = OMAP3_MMU2_BASE,
++ .end = OMAP3_MMU2_BASE + MMU_REG_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = OMAP3_MMU2_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++#define NR_IOMMU_RES (ARRAY_SIZE(omap3_iommu_res) / 2)
++
++static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
++ {
++ .name = "isp",
++ .nr_tlb_entries = 8,
++ .clk_name = "cam_ick",
++ },
++ {
++ .name = "iva2",
++ .nr_tlb_entries = 32,
++ .clk_name = "iva2_ck",
++ },
++};
++#define NR_IOMMU_DEVICES ARRAY_SIZE(omap3_iommu_pdata)
++
++static struct platform_device *omap3_iommu_pdev[NR_IOMMU_DEVICES];
++
++static int __init omap3_iommu_init(void)
++{
++ int i, err;
++
++ for (i = 0; i < NR_IOMMU_DEVICES; i++) {
++ struct platform_device *pdev;
++
++ pdev = platform_device_alloc("omap-iommu", i + 1);
++ if (!pdev)
++ goto err_out;
++ err = platform_device_add_resources(pdev,
++ &omap3_iommu_res[2 * i], NR_IOMMU_RES);
++ if (err)
++ goto err_out;
++ err = platform_device_add_data(pdev, &omap3_iommu_pdata[i],
++ sizeof(omap3_iommu_pdata[0]));
++ if (err)
++ goto err_out;
++ err = platform_device_add(pdev);
++ if (err)
++ goto err_out;
++ omap3_iommu_pdev[i] = pdev;
++ }
++ return 0;
++
++err_out:
++ while (i--)
++ platform_device_put(omap3_iommu_pdev[i]);
++ return err;
++}
++module_init(omap3_iommu_init);
++
++static void __exit omap3_iommu_exit(void)
++{
++ int i;
++
++ for (i = 0; i < NR_IOMMU_DEVICES; i++)
++ platform_device_unregister(omap3_iommu_pdev[i]);
++}
++module_exit(omap3_iommu_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU");
++MODULE_DESCRIPTION("omap iommu: omap3 device registration");
++MODULE_LICENSE("GPL v2");
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch
new file mode 100644
index 0000000000..945778b943
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch
@@ -0,0 +1,1083 @@
+From 07365182b998af3dc2b79e822b8e21a3f50262c4 Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Wed, 28 Jan 2009 21:32:08 +0200
+Subject: [PATCH] omap iommu: simple virtual address space management
+
+This patch provides a device drivers, which has a omap iommu, with
+address mapping APIs between device virtual address(iommu), physical
+address and MPU virtual address.
+
+There are 4 possible patterns for iommu virtual address(iova/da) mapping.
+
+ |iova/ mapping iommu_ page
+ | da pa va (d)-(p)-(v) function type
+ ---------------------------------------------------------------------------
+ 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s
+ 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s
+ 3 | c d c 1 - n - 1 _vmap() / _vunmap() s
+ 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n*
+
+ 'iova': device iommu virtual address
+ 'da': alias of 'iova'
+ 'pa': physical address
+ 'va': mpu virtual address
+
+ 'c': contiguous memory area
+ 'd': dicontiguous memory area
+ 'a': anonymous memory allocation
+ '()': optional feature
+
+ 'n': a normal page(4KB) size is used.
+ 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
+
+ '*': not yet, but feasible.
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/include/asm/io.h | 6 +
+ arch/arm/mm/ioremap.c | 11 +
+ arch/arm/plat-omap/include/mach/iovmm.h | 94 ++++
+ arch/arm/plat-omap/iovmm.c | 891 +++++++++++++++++++++++++++++++
+ 4 files changed, 1002 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
+ create mode 100644 arch/arm/plat-omap/iovmm.c
+
+diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
+index d2a59cf..cbdadfe 100644
+--- a/arch/arm/include/asm/io.h
++++ b/arch/arm/include/asm/io.h
+@@ -75,6 +75,12 @@ extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
+ extern void __iounmap(volatile void __iomem *addr);
+
+ /*
++ * external interface to remap single page with appropriate type
++ */
++extern int ioremap_page(unsigned long virt, unsigned long phys,
++ unsigned int mtype);
++
++/*
+ * Bad read/write accesses...
+ */
+ extern void __readwrite_bug(const char *fn);
+diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
+index 9f88dd3..8441351 100644
+--- a/arch/arm/mm/ioremap.c
++++ b/arch/arm/mm/ioremap.c
+@@ -110,6 +110,17 @@ static int remap_area_pages(unsigned long start, unsigned long pfn,
+ return err;
+ }
+
++int ioremap_page(unsigned long virt, unsigned long phys, unsigned int mtype)
++{
++ const struct mem_type *type;
++
++ type = get_mem_type(mtype);
++ if (!type)
++ return -EINVAL;
++
++ return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, type);
++}
++EXPORT_SYMBOL(ioremap_page);
+
+ void __check_kvm_seq(struct mm_struct *mm)
+ {
+diff --git a/arch/arm/plat-omap/include/mach/iovmm.h b/arch/arm/plat-omap/include/mach/iovmm.h
+new file mode 100644
+index 0000000..bdc7ce5
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/iovmm.h
+@@ -0,0 +1,94 @@
++/*
++ * omap iommu: simple virtual address space management
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __IOMMU_MMAP_H
++#define __IOMMU_MMAP_H
++
++struct iovm_struct {
++ struct iommu *iommu; /* iommu object which this belongs to */
++ u32 da_start; /* area definition */
++ u32 da_end;
++ u32 flags; /* IOVMF_: see below */
++ struct list_head list; /* linked in ascending order */
++ const struct sg_table *sgt; /* keep 'page' <-> 'da' mapping */
++ void *va; /* mpu side mapped address */
++};
++
++/*
++ * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
++ *
++ * lower 16 bit is used for h/w and upper 16 bit is for s/w.
++ */
++#define IOVMF_SW_SHIFT 16
++#define IOVMF_HW_SIZE (1 << IOVMF_SW_SHIFT)
++#define IOVMF_HW_MASK (IOVMF_HW_SIZE - 1)
++#define IOVMF_SW_MASK (~IOVMF_HW_MASK)UL
++
++/*
++ * iovma: h/w flags derived from cam and ram attribute
++ */
++#define IOVMF_CAM_MASK (~((1 << 10) - 1))
++#define IOVMF_RAM_MASK (~IOVMF_CAM_MASK)
++
++#define IOVMF_PGSZ_MASK (3 << 0)
++#define IOVMF_PGSZ_1M MMU_CAM_PGSZ_1M
++#define IOVMF_PGSZ_64K MMU_CAM_PGSZ_64K
++#define IOVMF_PGSZ_4K MMU_CAM_PGSZ_4K
++#define IOVMF_PGSZ_16M MMU_CAM_PGSZ_16M
++
++#define IOVMF_ENDIAN_MASK (1 << 9)
++#define IOVMF_ENDIAN_BIG MMU_RAM_ENDIAN_BIG
++#define IOVMF_ENDIAN_LITTLE MMU_RAM_ENDIAN_LITTLE
++
++#define IOVMF_ELSZ_MASK (3 << 7)
++#define IOVMF_ELSZ_8 MMU_RAM_ELSZ_8
++#define IOVMF_ELSZ_16 MMU_RAM_ELSZ_16
++#define IOVMF_ELSZ_32 MMU_RAM_ELSZ_32
++#define IOVMF_ELSZ_NONE MMU_RAM_ELSZ_NONE
++
++#define IOVMF_MIXED_MASK (1 << 6)
++#define IOVMF_MIXED MMU_RAM_MIXED
++
++/*
++ * iovma: s/w flags, used for mapping and umapping internally.
++ */
++#define IOVMF_MMIO (1 << IOVMF_SW_SHIFT)
++#define IOVMF_ALLOC (2 << IOVMF_SW_SHIFT)
++#define IOVMF_ALLOC_MASK (3 << IOVMF_SW_SHIFT)
++
++/* "superpages" is supported just with physically linear pages */
++#define IOVMF_DISCONT (1 << (2 + IOVMF_SW_SHIFT))
++#define IOVMF_LINEAR (2 << (2 + IOVMF_SW_SHIFT))
++#define IOVMF_LINEAR_MASK (3 << (2 + IOVMF_SW_SHIFT))
++
++#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT))
++#define IOVMF_DA_ANON (2 << (4 + IOVMF_SW_SHIFT))
++#define IOVMF_DA_MASK (3 << (4 + IOVMF_SW_SHIFT))
++
++
++extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
++extern u32 iommu_vmap(struct iommu *obj, u32 da,
++ const struct sg_table *sgt, u32 flags);
++extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
++extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
++ u32 flags);
++extern void iommu_vfree(struct iommu *obj, const u32 da);
++extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
++ u32 flags);
++extern void iommu_kunmap(struct iommu *obj, u32 da);
++extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
++ u32 flags);
++extern void iommu_kfree(struct iommu *obj, u32 da);
++
++extern void *da_to_va(struct iommu *obj, u32 da);
++
++#endif /* __IOMMU_MMAP_H */
+diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
+new file mode 100644
+index 0000000..6726d10
+--- /dev/null
++++ b/arch/arm/plat-omap/iovmm.c
+@@ -0,0 +1,891 @@
++/*
++ * omap iommu: simple virtual address space management
++ *
++ * Copyright (C) 2008-2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/err.h>
++#include <linux/vmalloc.h>
++#include <linux/device.h>
++#include <linux/scatterlist.h>
++
++#include <asm/io.h>
++#include <asm/cacheflush.h>
++
++#include <mach/iommu.h>
++#include <mach/iovmm.h>
++
++#include "iopgtable.h"
++
++/*
++ * A device driver needs to create address mappings between:
++ *
++ * - iommu/device address
++ * - physical address
++ * - mpu virtual address
++ *
++ * There are 4 possible patterns for them:
++ *
++ * |iova/ mapping iommu_ page
++ * | da pa va (d)-(p)-(v) function type
++ * ---------------------------------------------------------------------------
++ * 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s
++ * 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s
++ * 3 | c d c 1 - n - 1 _vmap() / _vunmap() s
++ * 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n*
++ *
++ *
++ * 'iova': device iommu virtual address
++ * 'da': alias of 'iova'
++ * 'pa': physical address
++ * 'va': mpu virtual address
++ *
++ * 'c': contiguous memory area
++ * 'd': dicontiguous memory area
++ * 'a': anonymous memory allocation
++ * '()': optional feature
++ *
++ * 'n': a normal page(4KB) size is used.
++ * 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
++ *
++ * '*': not yet, but feasible.
++ */
++
++static struct kmem_cache *iovm_area_cachep;
++
++/* return total bytes of sg buffers */
++static size_t sgtable_len(const struct sg_table *sgt)
++{
++ unsigned int i, total = 0;
++ struct scatterlist *sg;
++
++ if (!sgt)
++ return 0;
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ size_t bytes;
++
++ bytes = sg_dma_len(sg);
++
++ if (!iopgsz_ok(bytes)) {
++ pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
++ __func__, i, bytes);
++ return 0;
++ }
++
++ total += bytes;
++ }
++
++ return total;
++}
++#define sgtable_ok(x) (!!sgtable_len(x))
++
++/*
++ * calculate the optimal number sg elements from total bytes based on
++ * iommu superpages
++ */
++static unsigned int sgtable_nents(size_t bytes)
++{
++ int i;
++ unsigned int nr_entries;
++ const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
++
++ if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
++ pr_err("%s: wrong size %08x\n", __func__, bytes);
++ return 0;
++ }
++
++ nr_entries = 0;
++ for (i = 0; i < ARRAY_SIZE(pagesize); i++) {
++ if (bytes >= pagesize[i]) {
++ nr_entries += (bytes / pagesize[i]);
++ bytes %= pagesize[i];
++ }
++ }
++ BUG_ON(bytes);
++
++ return nr_entries;
++}
++
++/* allocate and initialize sg_table header(a kind of 'superblock') */
++static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
++{
++ unsigned int nr_entries;
++ int err;
++ struct sg_table *sgt;
++
++ if (!bytes)
++ return ERR_PTR(-EINVAL);
++
++ if (!IS_ALIGNED(bytes, PAGE_SIZE))
++ return ERR_PTR(-EINVAL);
++
++ /* FIXME: IOVMF_DA_FIXED should support 'superpages' */
++ if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) {
++ nr_entries = sgtable_nents(bytes);
++ if (!nr_entries)
++ return ERR_PTR(-EINVAL);
++ } else
++ nr_entries = bytes / PAGE_SIZE;
++
++ sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
++ if (!sgt)
++ return ERR_PTR(-ENOMEM);
++
++ err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
++ if (err)
++ return ERR_PTR(err);
++
++ pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
++
++ return sgt;
++}
++
++/* free sg_table header(a kind of superblock) */
++static void sgtable_free(struct sg_table *sgt)
++{
++ if (!sgt)
++ return;
++
++ sg_free_table(sgt);
++ kfree(sgt);
++
++ pr_debug("%s: sgt:%p\n", __func__, sgt);
++}
++
++/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
++static void *vmap_sg(const struct sg_table *sgt)
++{
++ u32 va;
++ size_t total;
++ unsigned int i;
++ struct scatterlist *sg;
++ struct vm_struct *new;
++
++ total = sgtable_len(sgt);
++ if (!total)
++ return ERR_PTR(-EINVAL);
++
++ new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
++ if (!new)
++ return ERR_PTR(-ENOMEM);
++ va = (u32)new->addr;
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ size_t bytes;
++ u32 pa;
++ int err;
++
++ pa = sg_phys(sg);
++ bytes = sg_dma_len(sg);
++
++ BUG_ON(bytes != PAGE_SIZE);
++
++ err = ioremap_page(va, pa, MT_DEVICE);
++ if (err)
++ goto err_out;
++
++ va += bytes;
++ }
++
++ flush_cache_vmap(new->addr, total);
++ return new->addr;
++
++err_out:
++ WARN_ON(1); /* FIXME: cleanup some mpu mappings */
++ vunmap(new->addr);
++ return ERR_PTR(-EAGAIN);
++}
++
++static inline void vunmap_sg(const void *va)
++{
++ vunmap(va);
++}
++
++static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
++{
++ struct iovm_struct *tmp;
++
++ list_for_each_entry(tmp, &obj->mmap, list) {
++ if ((da >= tmp->da_start) && (da < tmp->da_end)) {
++ size_t len;
++
++ len = tmp->da_end - tmp->da_start;
++
++ dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
++ __func__, tmp->da_start, da, tmp->da_end, len,
++ tmp->flags);
++
++ return tmp;
++ }
++ }
++
++ return NULL;
++}
++
++/**
++ * find_iovm_area - find iovma which includes @da
++ * @da: iommu device virtual address
++ *
++ * Find the existing iovma starting at @da
++ */
++struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
++{
++ struct iovm_struct *area;
++
++ mutex_lock(&obj->mmap_lock);
++ area = __find_iovm_area(obj, da);
++ mutex_unlock(&obj->mmap_lock);
++
++ return area;
++}
++EXPORT_SYMBOL_GPL(find_iovm_area);
++
++/*
++ * This finds the hole(area) which fits the requested address and len
++ * in iovmas mmap, and returns the new allocated iovma.
++ */
++static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
++ size_t bytes, u32 flags)
++{
++ struct iovm_struct *new, *tmp;
++ u32 start, prev_end, alignement;
++
++ if (!obj || !bytes)
++ return ERR_PTR(-EINVAL);
++
++ start = da;
++ alignement = PAGE_SIZE;
++
++ if (flags & IOVMF_DA_ANON) {
++ /*
++ * Reserve the first page for NULL
++ */
++ start = PAGE_SIZE;
++ if (flags & IOVMF_LINEAR)
++ alignement = iopgsz_max(bytes);
++ start = roundup(start, alignement);
++ }
++
++ tmp = NULL;
++ if (list_empty(&obj->mmap))
++ goto found;
++
++ prev_end = 0;
++ list_for_each_entry(tmp, &obj->mmap, list) {
++
++ if ((prev_end <= start) && (start + bytes < tmp->da_start))
++ goto found;
++
++ if (flags & IOVMF_DA_ANON)
++ start = roundup(tmp->da_end, alignement);
++
++ prev_end = tmp->da_end;
++ }
++
++ if ((start >= prev_end) && (ULONG_MAX - start >= bytes))
++ goto found;
++
++ dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
++ __func__, da, bytes, flags);
++
++ return ERR_PTR(-EINVAL);
++
++found:
++ new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
++ if (!new)
++ return ERR_PTR(-ENOMEM);
++
++ new->iommu = obj;
++ new->da_start = start;
++ new->da_end = start + bytes;
++ new->flags = flags;
++
++ /*
++ * keep ascending order of iovmas
++ */
++ if (tmp)
++ list_add_tail(&new->list, &tmp->list);
++ else
++ list_add(&new->list, &obj->mmap);
++
++ dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
++ __func__, new->da_start, start, new->da_end, bytes, flags);
++
++ return new;
++}
++
++static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
++{
++ size_t bytes;
++
++ BUG_ON(!obj || !area);
++
++ bytes = area->da_end - area->da_start;
++
++ dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
++ __func__, area->da_start, area->da_end, bytes, area->flags);
++
++ list_del(&area->list);
++ kmem_cache_free(iovm_area_cachep, area);
++}
++
++/**
++ * da_to_va - convert (d) to (v)
++ * @obj: objective iommu
++ * @da: iommu device virtual address
++ * @va: mpu virtual address
++ *
++ * Returns mpu virtual addr which corresponds to a given device virtual addr
++ */
++void *da_to_va(struct iommu *obj, u32 da)
++{
++ void *va = NULL;
++ struct iovm_struct *area;
++
++ mutex_lock(&obj->mmap_lock);
++
++ area = __find_iovm_area(obj, da);
++ if (!area) {
++ dev_warn(obj->dev, "%s: no da area(%08x)\n", __func__, da);
++ goto out;
++ }
++ va = area->va;
++ mutex_unlock(&obj->mmap_lock);
++out:
++ return va;
++}
++EXPORT_SYMBOL_GPL(da_to_va);
++
++static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
++{
++ unsigned int i;
++ struct scatterlist *sg;
++ void *va = _va;
++ void *va_end;
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ struct page *pg;
++ const size_t bytes = PAGE_SIZE;
++
++ /*
++ * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
++ */
++ pg = vmalloc_to_page(va);
++ BUG_ON(!pg);
++ sg_set_page(sg, pg, bytes, 0);
++
++ va += bytes;
++ }
++
++ va_end = _va + PAGE_SIZE * i;
++ flush_cache_vmap(_va, va_end);
++}
++
++static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
++{
++ /*
++ * Actually this is not necessary at all, just exists for
++ * consistency of the code readibility.
++ */
++ BUG_ON(!sgt);
++}
++
++static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
++{
++ unsigned int i;
++ struct scatterlist *sg;
++ void *va;
++
++ va = phys_to_virt(pa);
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ size_t bytes;
++
++ bytes = iopgsz_max(len);
++
++ BUG_ON(!iopgsz_ok(bytes));
++
++ sg_set_buf(sg, phys_to_virt(pa), bytes);
++ /*
++ * 'pa' is cotinuous(linear).
++ */
++ pa += bytes;
++ len -= bytes;
++ }
++ BUG_ON(len);
++
++ clean_dcache_area(va, len);
++}
++
++static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
++{
++ /*
++ * Actually this is not necessary at all, just exists for
++ * consistency of the code readibility
++ */
++ BUG_ON(!sgt);
++}
++
++/* create 'da' <-> 'pa' mapping from 'sgt' */
++static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
++ const struct sg_table *sgt, u32 flags)
++{
++ int err;
++ unsigned int i, j;
++ struct scatterlist *sg;
++ u32 da = new->da_start;
++
++ if (!obj || !new || !sgt)
++ return -EINVAL;
++
++ BUG_ON(!sgtable_ok(sgt));
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ u32 pa;
++ int pgsz;
++ size_t bytes;
++ struct iotlb_entry e;
++
++ pa = sg_phys(sg);
++ bytes = sg_dma_len(sg);
++
++ flags &= ~IOVMF_PGSZ_MASK;
++ pgsz = bytes_to_iopgsz(bytes);
++ if (pgsz < 0)
++ goto err_out;
++ flags |= pgsz;
++
++ pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
++ i, da, pa, bytes);
++
++ iotlb_init_entry(&e, da, pa, flags);
++ err = iopgtable_store_entry(obj, &e);
++ if (err)
++ goto err_out;
++
++ da += bytes;
++ }
++ return 0;
++
++err_out:
++ da = new->da_start;
++
++ for_each_sg(sgt->sgl, sg, i, j) {
++ size_t bytes;
++
++ bytes = iopgtable_clear_entry(obj, da);
++
++ BUG_ON(!iopgsz_ok(bytes));
++
++ da += bytes;
++ }
++ return err;
++}
++
++/* release 'da' <-> 'pa' mapping */
++static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
++{
++ u32 start;
++ size_t total = area->da_end - area->da_start;
++
++ BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
++
++ start = area->da_start;
++ while (total > 0) {
++ size_t bytes;
++
++ bytes = iopgtable_clear_entry(obj, start);
++ if (bytes == 0)
++ bytes = PAGE_SIZE;
++ else
++ dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
++ __func__, start, bytes, area->flags);
++
++ BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
++
++ total -= bytes;
++ start += bytes;
++ }
++ BUG_ON(total);
++}
++
++/* template function for all unmapping */
++static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
++ void (*fn)(const void *), u32 flags)
++{
++ struct sg_table *sgt = NULL;
++ struct iovm_struct *area;
++
++ BUG_ON(in_interrupt());
++
++ if (!IS_ALIGNED(da, PAGE_SIZE)) {
++ dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
++ return NULL;
++ }
++
++ mutex_lock(&obj->mmap_lock);
++
++ area = __find_iovm_area(obj, da);
++ if (!area) {
++ dev_err(obj->dev, "%s: no da area(%08x)\n", __func__, da);
++ goto out;
++ }
++
++ if ((area->flags & flags) != flags) {
++ dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
++ area->flags);
++ goto out;
++ }
++ sgt = (struct sg_table *)area->sgt;
++
++ unmap_iovm_area(obj, area);
++
++ fn(area->va);
++
++ dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
++ area->da_start, da, area->da_end,
++ area->da_end - area->da_start, area->flags);
++
++ free_iovm_area(obj, area);
++out:
++ mutex_unlock(&obj->mmap_lock);
++
++ return sgt;
++}
++
++static u32 map_iommu_region(struct iommu *obj, u32 da,
++ const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
++{
++ int err = -ENOMEM;
++ struct iovm_struct *new;
++
++ mutex_lock(&obj->mmap_lock);
++
++ new = alloc_iovm_area(obj, da, bytes, flags);
++ if (IS_ERR(new)) {
++ err = PTR_ERR(new);
++ goto err_alloc_iovma;
++ }
++ new->va = va;
++ new->sgt = sgt;
++
++ if (map_iovm_area(obj, new, sgt, new->flags))
++ goto err_map;
++
++ mutex_unlock(&obj->mmap_lock);
++
++ dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
++ __func__, new->da_start, bytes, new->flags, va);
++
++ return new->da_start;
++
++err_map:
++ free_iovm_area(obj, new);
++err_alloc_iovma:
++ mutex_unlock(&obj->mmap_lock);
++ return err;
++}
++
++static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
++ const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
++{
++ return map_iommu_region(obj, da, sgt, va, bytes, flags);
++}
++
++/**
++ * iommu_vmap - (d)-(p)-(v) address mapper
++ * @obj: objective iommu
++ * @sgt: address of scatter gather table
++ * @flags: iovma and page property
++ *
++ * Creates 1-n-1 mapping with given @sgt and returns @da.
++ * All @sgt element must be io page size aligned.
++ */
++u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
++ u32 flags)
++{
++ size_t bytes;
++ void *va;
++
++ if (!obj || !obj->dev || !sgt)
++ return -EINVAL;
++
++ bytes = sgtable_len(sgt);
++ if (!bytes)
++ return -EINVAL;
++ bytes = PAGE_ALIGN(bytes);
++
++ va = vmap_sg(sgt);
++ if (IS_ERR(va))
++ return PTR_ERR(va);
++
++ flags &= IOVMF_HW_MASK;
++ flags |= IOVMF_DISCONT;
++ flags |= IOVMF_MMIO;
++ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
++
++ da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
++ if (IS_ERR_VALUE(da))
++ vunmap_sg(va);
++
++ return da;
++}
++EXPORT_SYMBOL_GPL(iommu_vmap);
++
++/**
++ * iommu_vunmap - release virtual mapping obtained by 'iommu_vmap()'
++ * @obj: objective iommu
++ * @da: iommu device virtual address
++ *
++ * Free the iommu virtually contiguous memory area starting at
++ * @da, which was returned by 'iommu_vmap()'.
++ */
++struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
++{
++ struct sg_table *sgt;
++ /*
++ * 'sgt' is allocated before 'iommu_vmalloc()' is called.
++ * Just returns 'sgt' to the caller to free
++ */
++ sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
++ if (!sgt)
++ dev_err(obj->dev, "%s: No sgt\n", __func__);
++ return sgt;
++}
++EXPORT_SYMBOL_GPL(iommu_vunmap);
++
++/**
++ * iommu_vmalloc - (d)-(p)-(v) address allocator and mapper
++ * @obj: objective iommu
++ * @da: contiguous iommu virtual memory
++ * @bytes: allocation size
++ * @flags: iovma and page property
++ *
++ * Allocate @bytes linearly and creates 1-n-1 mapping and returns
++ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
++ */
++u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
++{
++ void *va;
++ struct sg_table *sgt;
++
++ if (!obj || !obj->dev || !bytes)
++ return -EINVAL;
++
++ bytes = PAGE_ALIGN(bytes);
++
++ va = vmalloc(bytes);
++ if (!va)
++ return -ENOMEM;
++
++ sgt = sgtable_alloc(bytes, flags);
++ if (IS_ERR(sgt)) {
++ da = PTR_ERR(sgt);
++ goto err_sgt_alloc;
++ }
++ sgtable_fill_vmalloc(sgt, va);
++
++ flags &= IOVMF_HW_MASK;
++ flags |= IOVMF_DISCONT;
++ flags |= IOVMF_ALLOC;
++ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
++
++ da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
++ if (IS_ERR_VALUE(da))
++ goto err_iommu_vmap;
++
++ return da;
++
++err_iommu_vmap:
++ sgtable_drain_vmalloc(sgt);
++ sgtable_free(sgt);
++err_sgt_alloc:
++ vfree(va);
++ return da;
++}
++EXPORT_SYMBOL_GPL(iommu_vmalloc);
++
++/**
++ * iommu_vfree - release memory allocated by 'iommu_vmalloc()'
++ * @obj: objective iommu
++ * @da: iommu device virtual address
++ *
++ * Frees the iommu virtually continuous memory area starting at
++ * @da, as obtained from 'iommu_vmalloc()'.
++ */
++void iommu_vfree(struct iommu *obj, const u32 da)
++{
++ struct sg_table *sgt;
++
++ sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
++ if (!sgt)
++ dev_err(obj->dev, "%s: No sgt\n", __func__);
++ sgtable_free(sgt);
++}
++EXPORT_SYMBOL_GPL(iommu_vfree);
++
++static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
++ size_t bytes, u32 flags)
++{
++ struct sg_table *sgt;
++
++ sgt = sgtable_alloc(bytes, flags);
++ if (IS_ERR(sgt))
++ return PTR_ERR(sgt);
++
++ sgtable_fill_kmalloc(sgt, pa, bytes);
++
++ da = map_iommu_region(obj, da, sgt, va, bytes, flags);
++ if (IS_ERR_VALUE(da)) {
++ sgtable_drain_kmalloc(sgt);
++ sgtable_free(sgt);
++ }
++
++ return da;
++}
++
++/**
++ * iommu_kmap - (d)-(p)-(v) address mapper
++ * @obj: objective iommu
++ * @da: contiguous iommu virtual memory
++ * @pa: contiguous physical memory
++ * @flags: iovma and page property
++ *
++ * Creates 1-1-1 mapping and returns @da again, which can be
++ * adjusted if 'IOVMF_DA_ANON' is set.
++ */
++u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
++ u32 flags)
++{
++ void *va;
++
++ if (!obj || !obj->dev || !bytes)
++ return -EINVAL;
++
++ bytes = PAGE_ALIGN(bytes);
++
++ va = ioremap(pa, bytes);
++ if (!va)
++ return -ENOMEM;
++
++ flags &= IOVMF_HW_MASK;
++ flags |= IOVMF_LINEAR;
++ flags |= IOVMF_MMIO;
++ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
++
++ da = __iommu_kmap(obj, da, pa, va, bytes, flags);
++ if (IS_ERR_VALUE(da))
++ iounmap(va);
++
++ return da;
++}
++EXPORT_SYMBOL_GPL(iommu_kmap);
++
++/**
++ * iommu_kunmap - release virtual mapping obtained by 'iommu_kmap()'
++ * @obj: objective iommu
++ * @da: iommu device virtual address
++ *
++ * Frees the iommu virtually contiguous memory area starting at
++ * @da, which was passed to and was returned by'iommu_kmap()'.
++ */
++void iommu_kunmap(struct iommu *obj, u32 da)
++{
++ struct sg_table *sgt;
++
++ sgt = unmap_vm_area(obj, da, __iounmap, IOVMF_LINEAR | IOVMF_MMIO);
++ if (!sgt)
++ dev_err(obj->dev, "%s: No sgt\n", __func__);
++ sgtable_free(sgt);
++}
++EXPORT_SYMBOL_GPL(iommu_kunmap);
++
++/**
++ * iommu_kmalloc - (d)-(p)-(v) address allocator and mapper
++ * @obj: objective iommu
++ * @da: contiguous iommu virtual memory
++ * @bytes: bytes for allocation
++ * @flags: iovma and page property
++ *
++ * Allocate @bytes linearly and creates 1-1-1 mapping and returns
++ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
++ */
++u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
++{
++ void *va;
++ u32 pa;
++
++ if (!obj || !obj->dev || !bytes)
++ return -EINVAL;
++
++ bytes = PAGE_ALIGN(bytes);
++
++ va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
++ if (!va)
++ return -ENOMEM;
++ pa = virt_to_phys(va);
++
++ flags &= IOVMF_HW_MASK;
++ flags |= IOVMF_LINEAR;
++ flags |= IOVMF_ALLOC;
++ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
++
++ da = __iommu_kmap(obj, da, pa, va, bytes, flags);
++ if (IS_ERR_VALUE(da))
++ kfree(va);
++
++ return da;
++}
++EXPORT_SYMBOL_GPL(iommu_kmalloc);
++
++/**
++ * iommu_kfree - release virtual mapping obtained by 'iommu_kmalloc()'
++ * @obj: objective iommu
++ * @da: iommu device virtual address
++ *
++ * Frees the iommu virtually contiguous memory area starting at
++ * @da, which was passed to and was returned by'iommu_kmalloc()'.
++ */
++void iommu_kfree(struct iommu *obj, u32 da)
++{
++ struct sg_table *sgt;
++
++ sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
++ if (!sgt)
++ dev_err(obj->dev, "%s: No sgt\n", __func__);
++ sgtable_free(sgt);
++}
++EXPORT_SYMBOL_GPL(iommu_kfree);
++
++
++static int __init iovmm_init(void)
++{
++ const unsigned long flags = SLAB_HWCACHE_ALIGN;
++ struct kmem_cache *p;
++
++ p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
++ flags, NULL);
++ if (!p)
++ return -ENOMEM;
++ iovm_area_cachep = p;
++
++ return 0;
++}
++module_init(iovmm_init);
++
++static void __exit iovmm_exit(void)
++{
++ kmem_cache_destroy(iovm_area_cachep);
++}
++module_exit(iovmm_exit);
++
++MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
++MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
++MODULE_LICENSE("GPL v2");
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000000..c0f9e4d9ac
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch
@@ -0,0 +1,45 @@
+From 7de046a6a8446358001c38ad1d0b2b829ca0c98c Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Wed, 28 Jan 2009 21:32:08 +0200
+Subject: [PATCH] omap iommu: entries for Kconfig and Makefile
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/plat-omap/Kconfig | 8 ++++++++
+ arch/arm/plat-omap/Makefile | 1 +
+ 2 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index b16ae76..2090bb5 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -176,6 +176,14 @@ config OMAP_MBOX_FWK
+ Say Y here if you want to use OMAP Mailbox framework support for
+ DSP, IVA1.0 and IVA2 in OMAP1/2/3.
+
++config OMAP_IOMMU
++ tristate "IOMMU support"
++ depends on ARCH_OMAP
++ default n
++ help
++ Say Y here if you want to use OMAP IOMMU support for IVA2 and
++ Camera in OMAP3.
++
+ choice
+ prompt "System timer"
+ default OMAP_MPU_TIMER
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 3ebc09e..aa8f6df 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -13,6 +13,7 @@ obj- :=
+ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
+
+ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
++obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
+
+ obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
+ obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch
new file mode 100644
index 0000000000..54a7abfe85
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch
@@ -0,0 +1,26 @@
+From b03f695e25bbdaa95a2cc87e15ee8592e7ca128d Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Feb 2009 18:01:29 +0200
+Subject: [PATCH] omap iommu: Don't try BUG_ON(in_interrupt())
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ arch/arm/plat-omap/iovmm.c | 2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
+index 6726d10..bdfbb09 100644
+--- a/arch/arm/plat-omap/iovmm.c
++++ b/arch/arm/plat-omap/iovmm.c
+@@ -523,8 +523,6 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
+ struct sg_table *sgt = NULL;
+ struct iovm_struct *area;
+
+- BUG_ON(in_interrupt());
+-
+ if (!IS_ALIGNED(da, PAGE_SIZE)) {
+ dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
+ return NULL;
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch
new file mode 100644
index 0000000000..d8ad0eb0b7
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch
@@ -0,0 +1,24 @@
+From 24f984f784cae1a4515fe1be8db1ac24cdf51e84 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Feb 2009 18:37:41 +0200
+Subject: [PATCH] omap iommu: We support chained scatterlists, probably. :)
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ arch/arm/include/asm/scatterlist.h | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
+index ca0a37d..393f8b8 100644
+--- a/arch/arm/include/asm/scatterlist.h
++++ b/arch/arm/include/asm/scatterlist.h
+@@ -24,4 +24,6 @@ struct scatterlist {
+ #define sg_dma_address(sg) ((sg)->dma_address)
+ #define sg_dma_len(sg) ((sg)->length)
+
++#define ARCH_HAS_SG_CHAIN
++
+ #endif /* _ASMARM_SCATTERLIST_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000000..298e797c37
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch
@@ -0,0 +1,29 @@
+From 3c65ff4a684d3e0f4d9c59e731975408452c3743 Mon Sep 17 00:00:00 2001
+From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+Date: Wed, 28 Jan 2009 21:32:09 +0200
+Subject: [PATCH] omap2 iommu: entries for Kconfig and Makefile
+
+Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+---
+ arch/arm/mach-omap2/Makefile | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index b44bb78..33b5aa8 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -38,6 +38,11 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+ mailbox_mach-objs := mailbox.o
+
++iommu-y += iommu2.o
++iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o
++
++obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)
++
+ # Specific board support
+ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o board-h4-mmc.o
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch
new file mode 100644
index 0000000000..e6e07d8afc
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch
@@ -0,0 +1,4625 @@
+From 77c99cd863b906c803c3dec08753c19bf9b67882 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add ISP main driver and register definitions
+
+TODO:
+
+- Release resoures in isp_probe() if something fails.
+
+- Implement a sensible generic interface so that the ISP can offer a
+ v4l2_subdev (like the v4l2-int-device slaves) interface towards the
+ camera driver.
+
+- Handle CSI1 and CSI2 error cases (currently unhandled?).
+
+- Fix H3A / HIST interrupt enabling / disabling.
+
+- Clean up the private ioctls.
+
+- Handle SBL overflows somehow.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/Makefile | 2 +
+ drivers/media/video/isp/Makefile | 12 +
+ drivers/media/video/isp/isp.c | 2547 ++++++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/isp.h | 318 +++++
+ drivers/media/video/isp/ispreg.h | 1674 +++++++++++++++++++++++++
+ 5 files changed, 4553 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/Makefile
+ create mode 100644 drivers/media/video/isp/isp.c
+ create mode 100644 drivers/media/video/isp/isp.h
+ create mode 100644 drivers/media/video/isp/ispreg.h
+
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index 72f6d03..e654270 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -106,6 +106,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
+ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+
++obj-y += isp/
++
+ obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+
+ obj-$(CONFIG_USB_DABUSB) += dabusb.o
+diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
+new file mode 100644
+index 0000000..f14d617
+--- /dev/null
++++ b/drivers/media/video/isp/Makefile
+@@ -0,0 +1,12 @@
++# Makefile for OMAP3 ISP driver
++
++ifdef CONFIG_ARCH_OMAP3410
++isp-mod-objs += \
++ isp.o ispccdc.o
++else
++isp-mod-objs += \
++ isp.o ispccdc.o ispmmu.o \
++ isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
++endif
++
++obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
+diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
+new file mode 100644
+index 0000000..54c839b
+--- /dev/null
++++ b/drivers/media/video/isp/isp.c
+@@ -0,0 +1,2547 @@
++/*
++ * isp.c
++ *
++ * Driver Library for ISP Control module in TI's OMAP3 Camera ISP
++ * ISP interface and IRQ related APIs are defined here.
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ * Copyright (C) 2009 Nokia.
++ *
++ * Contributors:
++ * Sameer Venkatraman <sameerv@ti.com>
++ * Mohit Jalori <mjalori@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ * Toni Leinonen <toni.leinonen@nokia.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <asm/cacheflush.h>
++
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/platform_device.h>
++
++#include "isp.h"
++#include "ispmmu.h"
++#include "ispreg.h"
++#include "ispccdc.h"
++#include "isph3a.h"
++#include "isphist.h"
++#include "isp_af.h"
++#include "isppreview.h"
++#include "ispresizer.h"
++#include "ispcsi2.h"
++
++static struct isp_device *omap3isp;
++
++static int isp_try_size(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output);
++
++static void isp_save_ctx(void);
++
++static void isp_restore_ctx(void);
++
++static void isp_buf_init(void);
++
++/* List of image formats supported via OMAP ISP */
++const static struct v4l2_fmtdesc isp_formats[] = {
++ {
++ .description = "UYVY, packed",
++ .pixelformat = V4L2_PIX_FMT_UYVY,
++ },
++ {
++ .description = "YUYV (YUV 4:2:2), packed",
++ .pixelformat = V4L2_PIX_FMT_YUYV,
++ },
++ {
++ .description = "Bayer10 (GrR/BGb)",
++ .pixelformat = V4L2_PIX_FMT_SGRBG10,
++ },
++};
++
++/* ISP Crop capabilities */
++static struct v4l2_rect ispcroprect;
++static struct v4l2_rect cur_rect;
++
++/**
++ * struct vcontrol - Video control structure.
++ * @qc: V4L2 Query control structure.
++ * @current_value: Current value of the control.
++ */
++static struct vcontrol {
++ struct v4l2_queryctrl qc;
++ int current_value;
++} video_control[] = {
++ {
++ {
++ .id = V4L2_CID_BRIGHTNESS,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Brightness",
++ .minimum = ISPPRV_BRIGHT_LOW,
++ .maximum = ISPPRV_BRIGHT_HIGH,
++ .step = ISPPRV_BRIGHT_STEP,
++ .default_value = ISPPRV_BRIGHT_DEF,
++ },
++ .current_value = ISPPRV_BRIGHT_DEF,
++ },
++ {
++ {
++ .id = V4L2_CID_CONTRAST,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Contrast",
++ .minimum = ISPPRV_CONTRAST_LOW,
++ .maximum = ISPPRV_CONTRAST_HIGH,
++ .step = ISPPRV_CONTRAST_STEP,
++ .default_value = ISPPRV_CONTRAST_DEF,
++ },
++ .current_value = ISPPRV_CONTRAST_DEF,
++ },
++ {
++ {
++ .id = V4L2_CID_COLORFX,
++ .type = V4L2_CTRL_TYPE_MENU,
++ .name = "Color Effects",
++ .minimum = V4L2_COLORFX_NONE,
++ .maximum = V4L2_COLORFX_SEPIA,
++ .step = 1,
++ .default_value = V4L2_COLORFX_NONE,
++ },
++ .current_value = V4L2_COLORFX_NONE,
++ }
++};
++
++static struct v4l2_querymenu video_menu[] = {
++ {
++ .id = V4L2_CID_COLORFX,
++ .index = 0,
++ .name = "None",
++ },
++ {
++ .id = V4L2_CID_COLORFX,
++ .index = 1,
++ .name = "B&W",
++ },
++ {
++ .id = V4L2_CID_COLORFX,
++ .index = 2,
++ .name = "Sepia",
++ },
++};
++
++struct isp_buf {
++ dma_addr_t isp_addr;
++ void (*complete)(struct videobuf_buffer *vb, void *priv);
++ struct videobuf_buffer *vb;
++ void *priv;
++ u32 vb_state;
++};
++
++#define ISP_BUFS_IS_FULL(bufs) \
++ (((bufs)->queue + 1) % NUM_BUFS == (bufs)->done)
++#define ISP_BUFS_IS_EMPTY(bufs) ((bufs)->queue == (bufs)->done)
++#define ISP_BUFS_IS_LAST(bufs) \
++ ((bufs)->queue == ((bufs)->done + 1) % NUM_BUFS)
++#define ISP_BUFS_QUEUED(bufs) \
++ ((((bufs)->done - (bufs)->queue + NUM_BUFS)) % NUM_BUFS)
++#define ISP_BUF_DONE(bufs) ((bufs)->buf + (bufs)->done)
++#define ISP_BUF_NEXT_DONE(bufs) \
++ ((bufs)->buf + ((bufs)->done + 1) % NUM_BUFS)
++#define ISP_BUF_QUEUE(bufs) ((bufs)->buf + (bufs)->queue)
++#define ISP_BUF_MARK_DONE(bufs) \
++ (bufs)->done = ((bufs)->done + 1) % NUM_BUFS;
++#define ISP_BUF_MARK_QUEUED(bufs) \
++ (bufs)->queue = ((bufs)->queue + 1) % NUM_BUFS;
++
++struct isp_bufs {
++ dma_addr_t isp_addr_capture[VIDEO_MAX_FRAME];
++ spinlock_t lock; /* For handling current buffer */
++ /* queue full: (ispsg.queue + 1) % NUM_BUFS == ispsg.done
++ queue empty: ispsg.queue == ispsg.done */
++ struct isp_buf buf[NUM_BUFS];
++ /* Next slot to queue a buffer. */
++ int queue;
++ /* Buffer that is being processed. */
++ int done;
++ /* Wait for this many hs_vs before anything else. */
++ int wait_hs_vs;
++};
++
++/**
++ * struct ispirq - Structure for containing callbacks to be called in ISP ISR.
++ * @isp_callbk: Array which stores callback functions, indexed by the type of
++ * callback (8 possible types).
++ * @isp_callbk_arg1: Pointer to array containing pointers to the first argument
++ * to be passed to the requested callback function.
++ * @isp_callbk_arg2: Pointer to array containing pointers to the second
++ * argument to be passed to the requested callback function.
++ *
++ * This structure is used to contain all the callback functions related for
++ * each callback type (CBK_CCDC_VD0, CBK_CCDC_VD1, CBK_PREV_DONE,
++ * CBK_RESZ_DONE, CBK_MMU_ERR, CBK_H3A_AWB_DONE, CBK_HIST_DONE, CBK_HS_VS,
++ * CBK_LSC_ISR).
++ */
++struct isp_irq {
++ isp_callback_t isp_callbk[CBK_END];
++ isp_vbq_callback_ptr isp_callbk_arg1[CBK_END];
++ void *isp_callbk_arg2[CBK_END];
++};
++
++/**
++ * struct ispmodule - Structure for storing ISP sub-module information.
++ * @isp_pipeline: Bit mask for submodules enabled within the ISP.
++ * @applyCrop: Flag to do a crop operation when video buffer queue ISR is done
++ * @pix: Structure containing the format and layout of the output image.
++ * @ccdc_input_width: ISP CCDC module input image width.
++ * @ccdc_input_height: ISP CCDC module input image height.
++ * @ccdc_output_width: ISP CCDC module output image width.
++ * @ccdc_output_height: ISP CCDC module output image height.
++ * @preview_input_width: ISP Preview module input image width.
++ * @preview_input_height: ISP Preview module input image height.
++ * @preview_output_width: ISP Preview module output image width.
++ * @preview_output_height: ISP Preview module output image height.
++ * @resizer_input_width: ISP Resizer module input image width.
++ * @resizer_input_height: ISP Resizer module input image height.
++ * @resizer_output_width: ISP Resizer module output image width.
++ * @resizer_output_height: ISP Resizer module output image height.
++ */
++struct isp_module {
++ unsigned int isp_pipeline;
++ int applyCrop;
++ struct v4l2_pix_format pix;
++ unsigned int ccdc_input_width;
++ unsigned int ccdc_input_height;
++ unsigned int ccdc_output_width;
++ unsigned int ccdc_output_height;
++ unsigned int preview_input_width;
++ unsigned int preview_input_height;
++ unsigned int preview_output_width;
++ unsigned int preview_output_height;
++ unsigned int resizer_input_width;
++ unsigned int resizer_input_height;
++ unsigned int resizer_output_width;
++ unsigned int resizer_output_height;
++};
++
++#define RAW_CAPTURE(isp) \
++ (!((isp)->module.isp_pipeline & OMAP_ISP_PREVIEW))
++
++/**
++ * struct isp - Structure for storing ISP Control module information
++ * @lock: Spinlock to sync between isr and processes.
++ * @isp_mutex: Semaphore used to get access to the ISP.
++ * @ref_count: Reference counter.
++ * @cam_ick: Pointer to ISP Interface clock.
++ * @cam_fck: Pointer to ISP Functional clock.
++ *
++ * This structure is used to store the OMAP ISP Control Information.
++ */
++static struct isp {
++ spinlock_t lock; /* For handling registered ISP callbacks */
++ struct mutex isp_mutex; /* For handling ref_count field */
++ int ref_count;
++ struct clk *cam_ick;
++ struct clk *cam_mclk;
++ struct clk *csi2_fck;
++ struct isp_interface_config *config;
++ dma_addr_t tmp_buf;
++ size_t tmp_buf_size;
++ unsigned long tmp_buf_offset;
++ struct isp_bufs bufs;
++ struct isp_irq irq;
++ struct isp_module module;
++} isp_obj;
++
++/* Structure for saving/restoring ISP module registers */
++static struct isp_reg isp_reg_list[] = {
++ {OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_GRESET_LENGTH, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_REPLAY, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_FRAME, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_DELAY, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_DELAY, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_DELAY, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_LENGTH, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_LENGTH, 0},
++ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_LENGTH, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_SYSCONFIG, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_IRQENABLE, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_CTRL, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_CTRL, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_START, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_START, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_END, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_END, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_WINDOWSIZE, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_WINDOWSIZE, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_THRESHOLD, 0},
++ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_THRESHOLD, 0},
++ {0, ISP_TOK_TERM, 0}
++};
++
++u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset)
++{
++ return __raw_readl(omap3isp->mmio_base[isp_mmio_range] + reg_offset);
++}
++EXPORT_SYMBOL(isp_reg_readl);
++
++void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
++ u32 reg_offset)
++{
++ __raw_writel(reg_value,
++ omap3isp->mmio_base[isp_mmio_range] + reg_offset);
++}
++EXPORT_SYMBOL(isp_reg_writel);
++
++/*
++ *
++ * V4L2 Handling
++ *
++ */
++
++/**
++ * find_vctrl - Returns the index of the ctrl array of the requested ctrl ID.
++ * @id: Requested control ID.
++ *
++ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
++ * domain.
++ **/
++static int find_vctrl(int id)
++{
++ int i;
++
++ if (id < V4L2_CID_BASE)
++ return -EDOM;
++
++ for (i = (ARRAY_SIZE(video_control) - 1); i >= 0; i--)
++ if (video_control[i].qc.id == id)
++ break;
++
++ if (i < 0)
++ i = -EINVAL;
++
++ return i;
++}
++
++static int find_next_vctrl(int id)
++{
++ int i;
++ u32 best = (u32)-1;
++
++ for (i = 0; i < ARRAY_SIZE(video_control); i++) {
++ if (video_control[i].qc.id > id &&
++ (best == (u32)-1 ||
++ video_control[i].qc.id <
++ video_control[best].qc.id)) {
++ best = i;
++ }
++ }
++
++ if (best == (u32)-1)
++ return -EINVAL;
++
++ return best;
++}
++
++/**
++ * find_vmenu - Returns index of the menu array of the requested ctrl option.
++ * @id: Requested control ID.
++ * @index: Requested menu option index.
++ *
++ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
++ * domain.
++ **/
++static int find_vmenu(int id, int index)
++{
++ int i;
++
++ if (id < V4L2_CID_BASE)
++ return -EDOM;
++
++ for (i = (ARRAY_SIZE(video_menu) - 1); i >= 0; i--) {
++ if (video_menu[i].id != id || video_menu[i].index != index)
++ continue;
++ return i;
++ }
++
++ return -EINVAL;
++}
++
++/**
++ * isp_release_resources - Free ISP submodules
++ **/
++static void isp_release_resources(void)
++{
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
++ ispccdc_free();
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW)
++ isppreview_free();
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER)
++ ispresizer_free();
++ return;
++}
++
++static int isp_wait(int (*busy)(void), int wait_for_busy, int max_wait)
++{
++ int wait = 0;
++
++ if (max_wait == 0)
++ max_wait = 10000; /* 10 ms */
++
++ while ((wait_for_busy && !busy())
++ || (!wait_for_busy && busy())) {
++ rmb();
++ udelay(1);
++ wait++;
++ if (wait > max_wait) {
++ printk(KERN_ALERT "%s: wait is too much\n", __func__);
++ return -EBUSY;
++ }
++ }
++ DPRINTK_ISPCTRL(KERN_ALERT "%s: wait %d\n", __func__, wait);
++
++ return 0;
++}
++
++static int ispccdc_sbl_wait_idle(int max_wait)
++{
++ return isp_wait(ispccdc_sbl_busy, 0, max_wait);
++}
++
++static void isp_enable_interrupts(int is_raw)
++{
++ isp_reg_writel(-1, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
++ IRQ0ENABLE_HS_VS_IRQ |
++ IRQ0ENABLE_CCDC_VD0_IRQ |
++ IRQ0ENABLE_CCDC_VD1_IRQ);
++
++ if (is_raw)
++ return;
++
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_PRV_DONE_IRQ |
++ IRQ0ENABLE_RSZ_DONE_IRQ);
++
++ return;
++}
++
++static void isp_disable_interrupts(void)
++{
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~(IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
++ IRQ0ENABLE_HS_VS_IRQ |
++ IRQ0ENABLE_CCDC_VD0_IRQ |
++ IRQ0ENABLE_CCDC_VD1_IRQ |
++ IRQ0ENABLE_PRV_DONE_IRQ |
++ IRQ0ENABLE_RSZ_DONE_IRQ));
++}
++
++/**
++ * isp_set_callback - Sets the callback for the ISP module done events.
++ * @type: Type of the event for which callback is requested.
++ * @callback: Method to be called as callback in the ISR context.
++ * @arg1: First argument to be passed when callback is called in ISR.
++ * @arg2: Second argument to be passed when callback is called in ISR.
++ *
++ * This function sets a callback function for a done event in the ISP
++ * module, and enables the corresponding interrupt.
++ **/
++int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
++ isp_vbq_callback_ptr arg1,
++ void *arg2)
++{
++ unsigned long irqflags = 0;
++
++ if (callback == NULL) {
++ DPRINTK_ISPCTRL("ISP_ERR : Null Callback\n");
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&isp_obj.lock, irqflags);
++ isp_obj.irq.isp_callbk[type] = callback;
++ isp_obj.irq.isp_callbk_arg1[type] = arg1;
++ isp_obj.irq.isp_callbk_arg2[type] = arg2;
++ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
++
++ switch (type) {
++ case CBK_H3A_AWB_DONE:
++ isp_reg_writel(IRQ0ENABLE_H3A_AWB_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_H3A_AWB_DONE_IRQ);
++ break;
++ case CBK_H3A_AF_DONE:
++ isp_reg_writel(IRQ0ENABLE_H3A_AF_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_H3A_AF_DONE_IRQ);
++ break;
++ case CBK_HIST_DONE:
++ isp_reg_writel(IRQ0ENABLE_HIST_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_HIST_DONE_IRQ);
++ break;
++ case CBK_PREV_DONE:
++ isp_reg_writel(IRQ0ENABLE_PRV_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_PRV_DONE_IRQ);
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_set_callback);
++
++/**
++ * isp_unset_callback - Clears the callback for the ISP module done events.
++ * @type: Type of the event for which callback to be cleared.
++ *
++ * This function clears a callback function for a done event in the ISP
++ * module, and disables the corresponding interrupt.
++ **/
++int isp_unset_callback(enum isp_callback_type type)
++{
++ unsigned long irqflags = 0;
++
++ spin_lock_irqsave(&isp_obj.lock, irqflags);
++ isp_obj.irq.isp_callbk[type] = NULL;
++ isp_obj.irq.isp_callbk_arg1[type] = NULL;
++ isp_obj.irq.isp_callbk_arg2[type] = NULL;
++ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
++
++ switch (type) {
++ case CBK_H3A_AWB_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_H3A_AWB_DONE_IRQ);
++ break;
++ case CBK_H3A_AF_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_H3A_AF_DONE_IRQ);
++ break;
++ case CBK_HIST_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_HIST_DONE_IRQ);
++ break;
++ case CBK_CSIA:
++ isp_csi2_irq_set(0);
++ break;
++ case CBK_CSIB:
++ isp_reg_writel(IRQ0ENABLE_CSIB_IRQ, OMAP3_ISP_IOMEM_MAIN,
++ ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_CSIB_IRQ);
++ break;
++ case CBK_PREV_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_PRV_DONE_IRQ);
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_unset_callback);
++
++/**
++ * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
++ * @xclk: Desired frequency of the clock in Hz.
++ * @xclksel: XCLK to configure (0 = A, 1 = B).
++ *
++ * Configures the specified MCLK divisor in the ISP timing control register
++ * (TCTRL_CTRL) to generate the desired xclk clock value.
++ *
++ * Divisor = CM_CAM_MCLK_HZ / xclk
++ *
++ * Returns the final frequency that is actually being generated
++ **/
++u32 isp_set_xclk(u32 xclk, u8 xclksel)
++{
++ u32 divisor;
++ u32 currentxclk;
++
++ if (xclk >= CM_CAM_MCLK_HZ) {
++ divisor = ISPTCTRL_CTRL_DIV_BYPASS;
++ currentxclk = CM_CAM_MCLK_HZ;
++ } else if (xclk >= 2) {
++ divisor = CM_CAM_MCLK_HZ / xclk;
++ if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
++ divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
++ currentxclk = CM_CAM_MCLK_HZ / divisor;
++ } else {
++ divisor = xclk;
++ currentxclk = 0;
++ }
++
++ switch (xclksel) {
++ case 0:
++ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
++ ~ISPTCTRL_CTRL_DIVA_MASK,
++ divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
++ DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclka set to %d Hz\n",
++ currentxclk);
++ break;
++ case 1:
++ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
++ ~ISPTCTRL_CTRL_DIVB_MASK,
++ divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
++ DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclkb set to %d Hz\n",
++ currentxclk);
++ break;
++ default:
++ DPRINTK_ISPCTRL("ISP_ERR: isp_set_xclk(): Invalid requested "
++ "xclk. Must be 0 (A) or 1 (B)."
++ "\n");
++ return -EINVAL;
++ }
++
++ return currentxclk;
++}
++EXPORT_SYMBOL(isp_set_xclk);
++
++/**
++ * isp_power_settings - Sysconfig settings, for Power Management.
++ * @isp_sysconfig: Structure containing the power settings for ISP to configure
++ *
++ * Sets the power settings for the ISP, and SBL bus.
++ **/
++static void isp_power_settings(int idle)
++{
++ if (idle) {
++ isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
++ (ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY <<
++ ISP_SYSCONFIG_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_MAIN,
++ ISP_SYSCONFIG);
++ if (omap_rev() == OMAP3430_REV_ES1_0) {
++ isp_reg_writel(ISPCSI1_AUTOIDLE |
++ (ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
++ ISPCSI1_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_CSI2A,
++ ISP_CSIA_SYSCONFIG);
++ isp_reg_writel(ISPCSI1_AUTOIDLE |
++ (ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
++ ISPCSI1_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_CCP2,
++ ISP_CSIB_SYSCONFIG);
++ }
++ isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
++ ISP_CTRL);
++
++ } else {
++ isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
++ (ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY <<
++ ISP_SYSCONFIG_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_MAIN,
++ ISP_SYSCONFIG);
++ if (omap_rev() == OMAP3430_REV_ES1_0) {
++ isp_reg_writel(ISPCSI1_AUTOIDLE |
++ (ISPCSI1_MIDLEMODE_FORCESTANDBY <<
++ ISPCSI1_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_CSI2A,
++ ISP_CSIA_SYSCONFIG);
++
++ isp_reg_writel(ISPCSI1_AUTOIDLE |
++ (ISPCSI1_MIDLEMODE_FORCESTANDBY <<
++ ISPCSI1_MIDLEMODE_SHIFT),
++ OMAP3_ISP_IOMEM_CCP2,
++ ISP_CSIB_SYSCONFIG);
++ }
++
++ isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
++ ISP_CTRL);
++ }
++}
++
++#define BIT_SET(var, shift, mask, val) \
++ do { \
++ var = (var & ~(mask << shift)) \
++ | (val << shift); \
++ } while (0)
++
++static int isp_init_csi(struct isp_interface_config *config)
++{
++ u32 i = 0, val, reg;
++ int format;
++
++ switch (config->u.csi.format) {
++ case V4L2_PIX_FMT_SGRBG10:
++ format = 0x16; /* RAW10+VP */
++ break;
++ case V4L2_PIX_FMT_SGRBG10DPCM8:
++ format = 0x12; /* RAW8+DPCM10+VP */
++ break;
++ default:
++ printk(KERN_ERR "isp_init_csi: bad csi format\n");
++ return -EINVAL;
++ }
++
++ /* Reset the CSI and wait for reset to complete */
++ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSCONFIG) |
++ BIT(1),
++ OMAP3_ISP_IOMEM_CCP2,
++ ISPCSI1_SYSCONFIG);
++ while (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
++ BIT(0))) {
++ udelay(10);
++ if (i++ > 10)
++ break;
++ }
++ if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
++ BIT(0))) {
++ printk(KERN_WARNING
++ "omap3_isp: timeout waiting for csi reset\n");
++ }
++
++ /* ISPCSI1_CTRL */
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
++ val &= ~BIT(11); /* Enable VP only off ->
++ extract embedded data to interconnect */
++ BIT_SET(val, 8, 0x3, config->u.csi.vpclk); /* Video port clock */
++/* val |= BIT(3); */ /* Wait for FEC before disabling interface */
++ val |= BIT(2); /* I/O cell output is parallel
++ (no effect, but errata says should be enabled
++ for class 1/2) */
++ val |= BIT(12); /* VP clock polarity to falling edge
++ (needed or bad picture!) */
++
++ /* Data/strobe physical layer */
++ BIT_SET(val, 1, 1, config->u.csi.signalling);
++ BIT_SET(val, 10, 1, config->u.csi.strobe_clock_inv);
++ val |= BIT(4); /* Magic bit to enable CSI1 and strobe mode */
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
++
++ /* ISPCSI1_LCx_CTRL logical channel #0 */
++ reg = ISPCSI1_LCx_CTRL(0); /* reg = ISPCSI1_CTRL1; */
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
++ /* Format = RAW10+VP or RAW8+DPCM10+VP*/
++ BIT_SET(val, 3, 0x1f, format);
++ /* Enable setting of frame regions of interest */
++ BIT_SET(val, 1, 1, 1);
++ BIT_SET(val, 2, 1, config->u.csi.crc);
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
++
++ /* ISPCSI1_DAT_START for logical channel #0 */
++ reg = ISPCSI1_LCx_DAT_START(0); /* reg = ISPCSI1_DAT_START; */
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
++ BIT_SET(val, 16, 0xfff, config->u.csi.data_start);
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
++
++ /* ISPCSI1_DAT_SIZE for logical channel #0 */
++ reg = ISPCSI1_LCx_DAT_SIZE(0); /* reg = ISPCSI1_DAT_SIZE; */
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
++ BIT_SET(val, 16, 0xfff, config->u.csi.data_size);
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
++
++ /* Clear status bits for logical channel #0 */
++ isp_reg_writel(0xFFF & ~BIT(6), OMAP3_ISP_IOMEM_CCP2,
++ ISPCSI1_LC01_IRQSTATUS);
++
++ /* Enable CSI1 */
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
++ val |= BIT(0) | BIT(4);
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
++
++ if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL) & BIT(4))) {
++ printk(KERN_WARNING "OMAP3 CSI1 bus not available\n");
++ if (config->u.csi.signalling) /* Strobe mode requires CSI1 */
++ return -EIO;
++ }
++
++ return 0;
++}
++
++/**
++ * isp_configure_interface - Configures ISP Control I/F related parameters.
++ * @config: Pointer to structure containing the desired configuration for the
++ * ISP.
++ *
++ * Configures ISP control register (ISP_CTRL) with the values specified inside
++ * the config structure. Controls:
++ * - Selection of parallel or serial input to the preview hardware.
++ * - Data lane shifter.
++ * - Pixel clock polarity.
++ * - 8 to 16-bit bridge at the input of CCDC module.
++ * - HS or VS synchronization signal detection
++ **/
++int isp_configure_interface(struct isp_interface_config *config)
++{
++ u32 ispctrl_val = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
++ int r;
++
++ isp_obj.config = config;
++
++ ispctrl_val &= ISPCTRL_SHIFT_MASK;
++ ispctrl_val |= config->dataline_shift << ISPCTRL_SHIFT_SHIFT;
++ ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
++
++ ispctrl_val &= ISPCTRL_PAR_SER_CLK_SEL_MASK;
++
++ isp_buf_init();
++
++ switch (config->ccdc_par_ser) {
++ case ISP_PARLL:
++ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
++ ispctrl_val |= config->u.par.par_clk_pol
++ << ISPCTRL_PAR_CLK_POL_SHIFT;
++ ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
++ ispctrl_val |= config->u.par.par_bridge
++ << ISPCTRL_PAR_BRIDGE_SHIFT;
++ break;
++ case ISP_CSIA:
++ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
++ ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
++
++ isp_csi2_ctx_config_format(0, config->u.csi.format);
++ isp_csi2_ctx_update(0, false);
++
++ if (config->u.csi.crc)
++ isp_csi2_ctrl_config_ecc_enable(true);
++
++ isp_csi2_ctrl_config_vp_out_ctrl(config->u.csi.vpclk);
++ isp_csi2_ctrl_config_vp_only_enable(true);
++ isp_csi2_ctrl_config_vp_clk_enable(true);
++ isp_csi2_ctrl_update(false);
++
++ isp_csi2_irq_complexio1_set(1);
++ isp_csi2_irq_status_set(1);
++ isp_csi2_irq_set(1);
++
++ isp_csi2_enable(1);
++ mdelay(3);
++ break;
++ case ISP_CSIB:
++ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
++ r = isp_init_csi(config);
++ if (r)
++ return r;
++ break;
++ case ISP_NONE:
++ return 0;
++ default:
++ return -EINVAL;
++ }
++
++ ispctrl_val &= ~ISPCTRL_SYNC_DETECT_VSRISE;
++ ispctrl_val |= config->hsvs_syncdetect;
++
++ isp_reg_writel(ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
++
++ /* Set sensor specific fields in CCDC and Previewer module.*/
++ isppreview_set_skip(config->prev_sph, config->prev_slv);
++ ispccdc_set_wenlog(config->wenlog);
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_configure_interface);
++
++static int isp_buf_process(struct isp_bufs *bufs);
++
++/**
++ * omap34xx_isp_isr - Interrupt Service Routine for Camera ISP module.
++ * @irq: Not used currently.
++ * @ispirq_disp: Pointer to the object that is passed while request_irq is
++ * called. This is the isp_obj.irq object containing info on the
++ * callback.
++ *
++ * Handles the corresponding callback if plugged in.
++ *
++ * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
++ * IRQ wasn't handled.
++ **/
++static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
++{
++ struct isp *isp = _isp;
++ struct isp_irq *irqdis = &isp->irq;
++ struct isp_bufs *bufs = &isp->bufs;
++ unsigned long flags;
++ u32 irqstatus = 0;
++ unsigned long irqflags = 0;
++ int wait_hs_vs = 0;
++
++ irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_writel(irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++
++ spin_lock_irqsave(&bufs->lock, flags);
++ wait_hs_vs = bufs->wait_hs_vs;
++ if (irqstatus & HS_VS && bufs->wait_hs_vs)
++ bufs->wait_hs_vs--;
++ spin_unlock_irqrestore(&bufs->lock, flags);
++
++ spin_lock_irqsave(&isp_obj.lock, irqflags);
++ /*
++ * We need to wait for the first HS_VS interrupt from CCDC.
++ * Otherwise our frame (and everything else) might be bad.
++ */
++ if (wait_hs_vs)
++ goto out_ignore_buff;
++
++ if (irqstatus & CCDC_VD0) {
++ if (RAW_CAPTURE(&isp_obj))
++ isp_buf_process(bufs);
++ if (!ispccdc_busy())
++ ispccdc_config_shadow_registers();
++ }
++
++ if (irqstatus & PREV_DONE) {
++ if (irqdis->isp_callbk[CBK_PREV_DONE])
++ irqdis->isp_callbk[CBK_PREV_DONE](
++ PREV_DONE,
++ irqdis->isp_callbk_arg1[CBK_PREV_DONE],
++ irqdis->isp_callbk_arg2[CBK_PREV_DONE]);
++ else if (!RAW_CAPTURE(&isp_obj) && !ispresizer_busy()) {
++ if (isp_obj.module.applyCrop) {
++ ispresizer_applycrop();
++ if (!ispresizer_busy())
++ isp_obj.module.applyCrop = 0;
++ }
++ if (!isppreview_busy()) {
++ ispresizer_enable(1);
++ if (isppreview_busy()) {
++ /* FIXME: locking! */
++ ISP_BUF_DONE(bufs)->vb_state =
++ VIDEOBUF_ERROR;
++ printk(KERN_ERR "%s: can't stop"
++ " preview\n", __func__);
++ }
++ }
++ if (!isppreview_busy())
++ isppreview_config_shadow_registers();
++ if (!isppreview_busy())
++ isph3a_update_wb();
++ }
++ }
++
++ if (irqstatus & RESZ_DONE) {
++ if (!RAW_CAPTURE(&isp_obj)) {
++ if (!ispresizer_busy())
++ ispresizer_config_shadow_registers();
++ isp_buf_process(bufs);
++ }
++ }
++
++ if (irqstatus & H3A_AWB_DONE) {
++ if (irqdis->isp_callbk[CBK_H3A_AWB_DONE])
++ irqdis->isp_callbk[CBK_H3A_AWB_DONE](
++ H3A_AWB_DONE,
++ irqdis->isp_callbk_arg1[CBK_H3A_AWB_DONE],
++ irqdis->isp_callbk_arg2[CBK_H3A_AWB_DONE]);
++ }
++
++ if (irqstatus & HIST_DONE) {
++ if (irqdis->isp_callbk[CBK_HIST_DONE])
++ irqdis->isp_callbk[CBK_HIST_DONE](
++ HIST_DONE,
++ irqdis->isp_callbk_arg1[CBK_HIST_DONE],
++ irqdis->isp_callbk_arg2[CBK_HIST_DONE]);
++ }
++
++ if (irqstatus & H3A_AF_DONE) {
++ if (irqdis->isp_callbk[CBK_H3A_AF_DONE])
++ irqdis->isp_callbk[CBK_H3A_AF_DONE](
++ H3A_AF_DONE,
++ irqdis->isp_callbk_arg1[CBK_H3A_AF_DONE],
++ irqdis->isp_callbk_arg2[CBK_H3A_AF_DONE]);
++ }
++
++
++out_ignore_buff:
++ if (irqstatus & LSC_PRE_ERR) {
++ struct isp_buf *buf = ISP_BUF_DONE(bufs);
++ /* Mark buffer faulty. */
++ buf->vb_state = VIDEOBUF_ERROR;
++ ispccdc_lsc_error_handler();
++ printk(KERN_ERR "%s: lsc prefetch error\n", __func__);
++ }
++
++ if (irqstatus & CSIA) {
++ struct isp_buf *buf = ISP_BUF_DONE(bufs);
++ isp_csi2_isr();
++ buf->vb_state = VIDEOBUF_ERROR;
++ }
++
++ if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
++ u32 ispcsi1_irqstatus;
++
++ ispcsi1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2,
++ ISPCSI1_LC01_IRQSTATUS);
++ DPRINTK_ISPCTRL("%x\n", ispcsi1_irqstatus);
++ }
++
++ if (irqdis->isp_callbk[CBK_CATCHALL]) {
++ irqdis->isp_callbk[CBK_CATCHALL](
++ irqstatus,
++ irqdis->isp_callbk_arg1[CBK_CATCHALL],
++ irqdis->isp_callbk_arg2[CBK_CATCHALL]);
++ }
++
++ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
++
++#if 1
++ {
++ static const struct {
++ int num;
++ char *name;
++ } bits[] = {
++ { 31, "HS_VS_IRQ" },
++ { 30, "SEC_ERR_IRQ" },
++ { 29, "OCP_ERR_IRQ" },
++ { 28, "MMU_ERR_IRQ" },
++ { 27, "res27" },
++ { 26, "res26" },
++ { 25, "OVF_IRQ" },
++ { 24, "RSZ_DONE_IRQ" },
++ { 23, "res23" },
++ { 22, "res22" },
++ { 21, "CBUFF_IRQ" },
++ { 20, "PRV_DONE_IRQ" },
++ { 19, "CCDC_LSC_PREFETCH_ERROR" },
++ { 18, "CCDC_LSC_PREFETCH_COMPLETED" },
++ { 17, "CCDC_LSC_DONE" },
++ { 16, "HIST_DONE_IRQ" },
++ { 15, "res15" },
++ { 14, "res14" },
++ { 13, "H3A_AWB_DONE_IRQ" },
++ { 12, "H3A_AF_DONE_IRQ" },
++ { 11, "CCDC_ERR_IRQ" },
++ { 10, "CCDC_VD2_IRQ" },
++ { 9, "CCDC_VD1_IRQ" },
++ { 8, "CCDC_VD0_IRQ" },
++ { 7, "res7" },
++ { 6, "res6" },
++ { 5, "res5" },
++ { 4, "CSIB_IRQ" },
++ { 3, "CSIB_LCM_IRQ" },
++ { 2, "res2" },
++ { 1, "res1" },
++ { 0, "CSIA_IRQ" },
++ };
++ int i;
++ for (i = 0; i < ARRAY_SIZE(bits); i++) {
++ if ((1 << bits[i].num) & irqstatus)
++ DPRINTK_ISPCTRL("%s ", bits[i].name);
++ }
++ DPRINTK_ISPCTRL("\n");
++ }
++#endif
++
++ return IRQ_HANDLED;
++}
++
++/* Device name, needed for resource tracking layer */
++struct device_driver camera_drv = {
++ .name = "camera"
++};
++
++struct device camera_dev = {
++ .driver = &camera_drv,
++};
++
++/**
++ * isp_tmp_buf_free - To free allocated 10MB memory
++ *
++ **/
++static void isp_tmp_buf_free(void)
++{
++ if (isp_obj.tmp_buf) {
++ ispmmu_vfree(isp_obj.tmp_buf);
++ isp_obj.tmp_buf = 0;
++ isp_obj.tmp_buf_size = 0;
++ }
++}
++
++/**
++ * isp_tmp_buf_alloc - To allocate a 10MB memory
++ *
++ **/
++static u32 isp_tmp_buf_alloc(size_t size)
++{
++ isp_tmp_buf_free();
++
++ printk(KERN_INFO "%s: allocating %d bytes\n", __func__, size);
++
++ isp_obj.tmp_buf = ispmmu_vmalloc(size);
++ if (IS_ERR((void *)isp_obj.tmp_buf)) {
++ printk(KERN_ERR "ispmmu_vmap mapping failed ");
++ return -ENOMEM;
++ }
++ isp_obj.tmp_buf_size = size;
++
++ isppreview_set_outaddr(isp_obj.tmp_buf);
++ ispresizer_set_inaddr(isp_obj.tmp_buf);
++
++ return 0;
++}
++
++/**
++ * isp_start - Starts ISP submodule
++ *
++ * Start the needed isp components assuming these components
++ * are configured correctly.
++ **/
++void isp_start(void)
++{
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
++ && is_isppreview_enabled())
++ isppreview_enable(1);
++
++ return;
++}
++EXPORT_SYMBOL(isp_start);
++
++#define ISP_STATISTICS_BUSY \
++ ()
++#define ISP_STOP_TIMEOUT msecs_to_jiffies(1000)
++static int __isp_disable_modules(int suspend)
++{
++ unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
++ int reset = 0;
++
++ /*
++ * We need to stop all the modules after CCDC first or they'll
++ * never stop since they may not get a full frame from CCDC.
++ */
++ if (suspend) {
++ isp_af_suspend();
++ isph3a_aewb_suspend();
++ isp_hist_suspend();
++ isppreview_suspend();
++ ispresizer_suspend();
++ } else {
++ isp_af_enable(0);
++ isph3a_aewb_enable(0);
++ isp_hist_enable(0);
++ isppreview_enable(0);
++ ispresizer_enable(0);
++ }
++
++ timeout = jiffies + ISP_STOP_TIMEOUT;
++ while (isp_af_busy()
++ || isph3a_aewb_busy()
++ || isp_hist_busy()
++ || isppreview_busy()
++ || ispresizer_busy()) {
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "%s: can't stop non-ccdc modules\n",
++ __func__);
++ reset = 1;
++ break;
++ }
++ msleep(1);
++ }
++
++ /* Let's stop CCDC now. */
++ if (suspend)
++ /* This function supends lsc too */
++ ispccdc_suspend();
++ else {
++ ispccdc_enable_lsc(0);
++ ispccdc_enable(0);
++ }
++
++ timeout = jiffies + ISP_STOP_TIMEOUT;
++ while (ispccdc_busy()) {
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "%s: can't stop ccdc\n", __func__);
++ reset = 1;
++ break;
++ }
++ msleep(1);
++ }
++
++ return reset;
++}
++
++static int isp_stop_modules(void)
++{
++ return __isp_disable_modules(0);
++}
++
++static int isp_suspend_modules(void)
++{
++ return __isp_disable_modules(1);
++}
++
++static void isp_resume_modules(void)
++{
++ ispresizer_resume();
++ isppreview_resume();
++ isp_hist_resume();
++ isph3a_aewb_resume();
++ isp_af_resume();
++ ispccdc_resume();
++}
++
++static void isp_reset(void)
++{
++ unsigned long timeout = 0;
++
++ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
++ | ISP_SYSCONFIG_SOFTRESET,
++ OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
++ while (!(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS) & 0x1)) {
++ if (timeout++ > 10000) {
++ printk(KERN_ALERT "%s: cannot reset ISP\n", __func__);
++ break;
++ }
++ udelay(1);
++ }
++}
++
++/**
++ * isp_stop - Stops isp submodules
++ **/
++void isp_stop()
++{
++ int reset;
++
++ isp_disable_interrupts();
++ reset = isp_stop_modules();
++ isp_buf_init();
++ if (!reset)
++ return;
++
++ isp_save_ctx();
++ isp_reset();
++ isp_restore_ctx();
++}
++EXPORT_SYMBOL(isp_stop);
++
++static void isp_set_buf(struct isp_buf *buf)
++{
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER
++ && is_ispresizer_enabled())
++ ispresizer_set_outaddr(buf->isp_addr);
++ else if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
++ ispccdc_set_outaddr(buf->isp_addr);
++
++}
++
++/**
++ * isp_calc_pipeline - Sets pipeline depending of input and output pixel format
++ * @pix_input: Pointer to V4L2 pixel format structure for input image.
++ * @pix_output: Pointer to V4L2 pixel format structure for output image.
++ **/
++static u32 isp_calc_pipeline(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ isp_release_resources();
++ if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
++ || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
++ && pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10) {
++ isp_obj.module.isp_pipeline =
++ OMAP_ISP_CCDC | OMAP_ISP_PREVIEW | OMAP_ISP_RESIZER;
++ ispccdc_request();
++ isppreview_request();
++ ispresizer_request();
++ ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
++ isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_MEM);
++ ispresizer_config_datapath(RSZ_MEM_YUV);
++ } else {
++ isp_obj.module.isp_pipeline = OMAP_ISP_CCDC;
++ ispccdc_request();
++ if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
++ || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
++ ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP_MEM);
++ else
++ ispccdc_config_datapath(CCDC_YUV_SYNC,
++ CCDC_OTHERS_MEM);
++ }
++ return 0;
++}
++
++/**
++ * isp_config_pipeline - Configures the image size and ycpos for ISP submodules
++ * @pix_input: Pointer to V4L2 pixel format structure for input image.
++ * @pix_output: Pointer to V4L2 pixel format structure for output image.
++ *
++ * The configuration of ycpos depends on the output pixel format for both the
++ * Preview and Resizer submodules.
++ **/
++static void isp_config_pipeline(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ ispccdc_config_size(isp_obj.module.ccdc_input_width,
++ isp_obj.module.ccdc_input_height,
++ isp_obj.module.ccdc_output_width,
++ isp_obj.module.ccdc_output_height);
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
++ isppreview_config_size(isp_obj.module.preview_input_width,
++ isp_obj.module.preview_input_height,
++ isp_obj.module.preview_output_width,
++ isp_obj.module.preview_output_height);
++ }
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
++ ispresizer_config_size(isp_obj.module.resizer_input_width,
++ isp_obj.module.resizer_input_height,
++ isp_obj.module.resizer_output_width,
++ isp_obj.module.resizer_output_height);
++ }
++
++ if (pix_output->pixelformat == V4L2_PIX_FMT_UYVY) {
++ isppreview_config_ycpos(YCPOS_YCrYCb);
++ if (is_ispresizer_enabled())
++ ispresizer_config_ycpos(0);
++ } else {
++ isppreview_config_ycpos(YCPOS_CrYCbY);
++ if (is_ispresizer_enabled())
++ ispresizer_config_ycpos(1);
++ }
++
++ return;
++}
++
++static void isp_buf_init(void)
++{
++ struct isp_bufs *bufs = &isp_obj.bufs;
++ int sg;
++
++ bufs->queue = 0;
++ bufs->done = 0;
++ bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
++ for (sg = 0; sg < NUM_BUFS; sg++) {
++ bufs->buf[sg].complete = NULL;
++ bufs->buf[sg].vb = NULL;
++ bufs->buf[sg].priv = NULL;
++ }
++}
++
++/**
++ * isp_vbq_sync - Walks the pages table and flushes the cache for
++ * each page.
++ **/
++static int isp_vbq_sync(struct videobuf_buffer *vb, int when)
++{
++ flush_cache_all();
++
++ return 0;
++}
++
++static int isp_buf_process(struct isp_bufs *bufs)
++{
++ struct isp_buf *buf = NULL;
++ unsigned long flags;
++ int last;
++
++ spin_lock_irqsave(&bufs->lock, flags);
++
++ if (ISP_BUFS_IS_EMPTY(bufs))
++ goto out;
++
++ if (RAW_CAPTURE(&isp_obj) && ispccdc_sbl_wait_idle(1000)) {
++ printk(KERN_ERR "ccdc %d won't become idle!\n",
++ RAW_CAPTURE(&isp_obj));
++ goto out;
++ }
++
++ /* We had at least one buffer in queue. */
++ buf = ISP_BUF_DONE(bufs);
++ last = ISP_BUFS_IS_LAST(bufs);
++
++ if (!last) {
++ /* Set new buffer address. */
++ isp_set_buf(ISP_BUF_NEXT_DONE(bufs));
++ } else {
++ /* Tell ISP not to write any of our buffers. */
++ isp_disable_interrupts();
++ if (RAW_CAPTURE(&isp_obj))
++ ispccdc_enable(0);
++ else
++ ispresizer_enable(0);
++ /*
++ * We must wait for the HS_VS since before that the
++ * CCDC may trigger interrupts even if it's not
++ * receiving a frame.
++ */
++ bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
++ }
++ if ((RAW_CAPTURE(&isp_obj) && ispccdc_busy())
++ || (!RAW_CAPTURE(&isp_obj) && ispresizer_busy())) {
++ /*
++ * Next buffer available: for the transfer to succeed, the
++ * CCDC (RAW capture) or resizer (YUV capture) must be idle
++ * for the duration of transfer setup. Bad things happen
++ * otherwise!
++ *
++ * Next buffer not available: if we fail to stop the
++ * ISP the buffer is probably going to be bad.
++ */
++ /* Mark this buffer faulty. */
++ buf->vb_state = VIDEOBUF_ERROR;
++ /* Mark next faulty, too, in case we have one. */
++ if (!last) {
++ ISP_BUF_NEXT_DONE(bufs)->vb_state =
++ VIDEOBUF_ERROR;
++ printk(KERN_ALERT "OUCH!!!\n");
++ } else {
++ printk(KERN_ALERT "Ouch!\n");
++ }
++ }
++
++ /* Mark the current buffer as done. */
++ ISP_BUF_MARK_DONE(bufs);
++
++ DPRINTK_ISPCTRL(KERN_ALERT "%s: finish %d mmu %p\n", __func__,
++ (bufs->done - 1 + NUM_BUFS) % NUM_BUFS,
++ (bufs->buf+((bufs->done - 1 + NUM_BUFS)
++ % NUM_BUFS))->isp_addr);
++
++out:
++ spin_unlock_irqrestore(&bufs->lock, flags);
++
++ if (buf != NULL) {
++ /*
++ * We want to dequeue a buffer from the video buffer
++ * queue. Let's do it!
++ */
++ isp_vbq_sync(buf->vb, DMA_FROM_DEVICE);
++ buf->vb->state = buf->vb_state;
++ buf->complete(buf->vb, buf->priv);
++ }
++
++ return 0;
++}
++
++int isp_buf_queue(struct videobuf_buffer *vb,
++ void (*complete)(struct videobuf_buffer *vb, void *priv),
++ void *priv)
++{
++ unsigned long flags;
++ struct isp_buf *buf;
++ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
++ const struct scatterlist *sglist = dma->sglist;
++ struct isp_bufs *bufs = &isp_obj.bufs;
++ int sglen = dma->sglen;
++
++ BUG_ON(sglen < 0 || !sglist);
++
++ isp_vbq_sync(vb, DMA_TO_DEVICE);
++
++ spin_lock_irqsave(&bufs->lock, flags);
++
++ BUG_ON(ISP_BUFS_IS_FULL(bufs));
++
++ buf = ISP_BUF_QUEUE(bufs);
++
++ buf->isp_addr = bufs->isp_addr_capture[vb->i];
++ buf->complete = complete;
++ buf->vb = vb;
++ buf->priv = priv;
++ buf->vb_state = VIDEOBUF_DONE;
++
++ if (ISP_BUFS_IS_EMPTY(bufs)) {
++ isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
++ isp_set_buf(buf);
++ ispccdc_enable(1);
++ isp_start();
++ }
++
++ ISP_BUF_MARK_QUEUED(bufs);
++
++ spin_unlock_irqrestore(&bufs->lock, flags);
++
++ DPRINTK_ISPCTRL(KERN_ALERT "%s: queue %d vb %d, mmu %p\n", __func__,
++ (bufs->queue - 1 + NUM_BUFS) % NUM_BUFS, vb->i,
++ buf->isp_addr);
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_buf_queue);
++
++int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
++ unsigned int *size)
++{
++ int rval = 0;
++ size_t tmp_size = PAGE_ALIGN(isp_obj.module.preview_output_width
++ * isp_obj.module.preview_output_height
++ * ISP_BYTES_PER_PIXEL);
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
++ && isp_obj.tmp_buf_size < tmp_size)
++ rval = isp_tmp_buf_alloc(tmp_size);
++
++ return rval;
++}
++EXPORT_SYMBOL(isp_vbq_setup);
++
++/**
++ * isp_vbq_prepare - Videobuffer queue prepare.
++ * @vbq: Pointer to videobuf_queue structure.
++ * @vb: Pointer to videobuf_buffer structure.
++ * @field: Requested Field order for the videobuffer.
++ *
++ * Returns 0 if successful, or -EIO if the ispmmu was unable to map a
++ * scatter-gather linked list data space.
++ **/
++int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ unsigned int isp_addr;
++ struct videobuf_dmabuf *vdma;
++ struct isp_bufs *bufs = &isp_obj.bufs;
++
++ int err = 0;
++
++ vdma = videobuf_to_dma(vb);
++
++ isp_addr = ispmmu_vmap(vdma->sglist, vdma->sglen);
++
++ if (IS_ERR_VALUE(isp_addr))
++ err = -EIO;
++ else
++ bufs->isp_addr_capture[vb->i] = isp_addr;
++
++ return err;
++}
++EXPORT_SYMBOL(isp_vbq_prepare);
++
++/**
++ * isp_vbq_release - Videobuffer queue release.
++ * @vbq: Pointer to videobuf_queue structure.
++ * @vb: Pointer to videobuf_buffer structure.
++ **/
++void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb)
++{
++ struct isp_bufs *bufs = &isp_obj.bufs;
++
++ ispmmu_vunmap(bufs->isp_addr_capture[vb->i]);
++ bufs->isp_addr_capture[vb->i] = (dma_addr_t)NULL;
++ return;
++}
++EXPORT_SYMBOL(isp_vbq_release);
++
++/**
++ * isp_queryctrl - Query V4L2 control from existing controls in ISP.
++ * @a: Pointer to v4l2_queryctrl structure. It only needs the id field filled.
++ *
++ * Returns 0 if successful, or -EINVAL if not found in ISP.
++ **/
++int isp_queryctrl(struct v4l2_queryctrl *a)
++{
++ int i;
++
++ if (a->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
++ a->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
++ i = find_next_vctrl(a->id);
++ } else {
++ i = find_vctrl(a->id);
++ }
++
++ if (i < 0)
++ return -EINVAL;
++
++ *a = video_control[i].qc;
++ return 0;
++}
++EXPORT_SYMBOL(isp_queryctrl);
++
++/**
++ * isp_queryctrl - Query V4L2 control from existing controls in ISP.
++ * @a: Pointer to v4l2_queryctrl structure. It only needs the id field filled.
++ *
++ * Returns 0 if successful, or -EINVAL if not found in ISP.
++ **/
++int isp_querymenu(struct v4l2_querymenu *a)
++{
++ int i;
++
++ i = find_vmenu(a->id, a->index);
++
++ if (i < 0)
++ return -EINVAL;
++
++ *a = video_menu[i];
++ return 0;
++}
++EXPORT_SYMBOL(isp_querymenu);
++
++/**
++ * isp_g_ctrl - Gets value of the desired V4L2 control.
++ * @a: V4L2 control to read actual value from.
++ *
++ * Return 0 if successful, or -EINVAL if chosen control is not found.
++ **/
++int isp_g_ctrl(struct v4l2_control *a)
++{
++ u8 current_value;
++ int rval = 0;
++
++ if (!isp_obj.ref_count)
++ return -EINVAL;
++
++ switch (a->id) {
++ case V4L2_CID_BRIGHTNESS:
++ isppreview_query_brightness(&current_value);
++ a->value = current_value / ISPPRV_BRIGHT_UNITS;
++ break;
++ case V4L2_CID_CONTRAST:
++ isppreview_query_contrast(&current_value);
++ a->value = current_value / ISPPRV_CONTRAST_UNITS;
++ break;
++ case V4L2_CID_COLORFX:
++ isppreview_get_color(&current_value);
++ a->value = current_value;
++ break;
++ default:
++ rval = -EINVAL;
++ break;
++ }
++
++ return rval;
++}
++EXPORT_SYMBOL(isp_g_ctrl);
++
++/**
++ * isp_s_ctrl - Sets value of the desired V4L2 control.
++ * @a: V4L2 control to read actual value from.
++ *
++ * Return 0 if successful, -EINVAL if chosen control is not found or value
++ * is out of bounds, -EFAULT if copy_from_user or copy_to_user operation fails
++ * from camera abstraction layer related controls or the transfered user space
++ * pointer via the value field is not set properly.
++ **/
++int isp_s_ctrl(struct v4l2_control *a)
++{
++ int rval = 0;
++ u8 new_value = a->value;
++
++ if (!isp_obj.ref_count)
++ return -EINVAL;
++
++ switch (a->id) {
++ case V4L2_CID_BRIGHTNESS:
++ if (new_value > ISPPRV_BRIGHT_HIGH)
++ rval = -EINVAL;
++ else
++ isppreview_update_brightness(&new_value);
++ break;
++ case V4L2_CID_CONTRAST:
++ if (new_value > ISPPRV_CONTRAST_HIGH)
++ rval = -EINVAL;
++ else
++ isppreview_update_contrast(&new_value);
++ break;
++ case V4L2_CID_COLORFX:
++ if (new_value > V4L2_COLORFX_SEPIA)
++ rval = -EINVAL;
++ else
++ isppreview_set_color(&new_value);
++ break;
++ default:
++ rval = -EINVAL;
++ break;
++ }
++
++ return rval;
++}
++EXPORT_SYMBOL(isp_s_ctrl);
++
++/**
++ * isp_handle_private - Handle all private ioctls for isp module.
++ * @cmd: ioctl cmd value
++ * @arg: ioctl arg value
++ *
++ * Return 0 if successful, -EINVAL if chosen cmd value is not handled or value
++ * is out of bounds, -EFAULT if ioctl arg value is not valid.
++ * Function simply routes the input ioctl cmd id to the appropriate handler in
++ * the isp module.
++ **/
++int isp_handle_private(int cmd, void *arg)
++{
++ int rval = 0;
++
++ if (!isp_obj.ref_count)
++ return -EINVAL;
++
++ switch (cmd) {
++ case VIDIOC_PRIVATE_ISP_CCDC_CFG:
++ rval = omap34xx_isp_ccdc_config(arg);
++ break;
++ case VIDIOC_PRIVATE_ISP_PRV_CFG:
++ rval = omap34xx_isp_preview_config(arg);
++ break;
++ case VIDIOC_PRIVATE_ISP_AEWB_CFG: {
++ struct isph3a_aewb_config *params;
++ params = (struct isph3a_aewb_config *)arg;
++ rval = isph3a_aewb_configure(params);
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_AEWB_REQ: {
++ struct isph3a_aewb_data *data;
++ data = (struct isph3a_aewb_data *)arg;
++ rval = isph3a_aewb_request_statistics(data);
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_HIST_CFG: {
++ struct isp_hist_config *params;
++ params = (struct isp_hist_config *)arg;
++ rval = isp_hist_configure(params);
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_HIST_REQ: {
++ struct isp_hist_data *data;
++ data = (struct isp_hist_data *)arg;
++ rval = isp_hist_request_statistics(data);
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_AF_CFG: {
++ struct af_configuration *params;
++ params = (struct af_configuration *)arg;
++ rval = isp_af_configure(params);
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_AF_REQ: {
++ struct isp_af_data *data;
++ data = (struct isp_af_data *)arg;
++ rval = isp_af_request_statistics(data);
++ }
++ break;
++ default:
++ rval = -EINVAL;
++ break;
++ }
++ return rval;
++}
++EXPORT_SYMBOL(isp_handle_private);
++
++/**
++ * isp_enum_fmt_cap - Gets more information of chosen format index and type
++ * @f: Pointer to structure containing index and type of format to read from.
++ *
++ * Returns 0 if successful, or -EINVAL if format index or format type is
++ * invalid.
++ **/
++int isp_enum_fmt_cap(struct v4l2_fmtdesc *f)
++{
++ int index = f->index;
++ enum v4l2_buf_type type = f->type;
++ int rval = -EINVAL;
++
++ if (index >= NUM_ISP_CAPTURE_FORMATS)
++ goto err;
++
++ memset(f, 0, sizeof(*f));
++ f->index = index;
++ f->type = type;
++
++ switch (f->type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ rval = 0;
++ break;
++ default:
++ goto err;
++ }
++
++ f->flags = isp_formats[index].flags;
++ strncpy(f->description, isp_formats[index].description,
++ sizeof(f->description));
++ f->pixelformat = isp_formats[index].pixelformat;
++err:
++ return rval;
++}
++EXPORT_SYMBOL(isp_enum_fmt_cap);
++
++/**
++ * isp_g_fmt_cap - Gets current output image format.
++ * @f: Pointer to V4L2 format structure to be filled with current output format
++ **/
++void isp_g_fmt_cap(struct v4l2_pix_format *pix)
++{
++ *pix = isp_obj.module.pix;
++ return;
++}
++EXPORT_SYMBOL(isp_g_fmt_cap);
++
++/**
++ * isp_s_fmt_cap - Sets I/O formats and crop and configures pipeline in ISP
++ * @f: Pointer to V4L2 format structure to be filled with current output format
++ *
++ * Returns 0 if successful, or return value of either isp_try_size or
++ * isp_try_fmt if there is an error.
++ **/
++int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ int crop_scaling_w = 0, crop_scaling_h = 0;
++ int rval = 0;
++
++ if (!isp_obj.ref_count)
++ return -EINVAL;
++
++ rval = isp_calc_pipeline(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++ rval = isp_try_size(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++ rval = isp_try_fmt(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++ if (ispcroprect.width != pix_output->width) {
++ crop_scaling_w = 1;
++ ispcroprect.left = 0;
++ ispcroprect.width = pix_output->width;
++ }
++
++ if (ispcroprect.height != pix_output->height) {
++ crop_scaling_h = 1;
++ ispcroprect.top = 0;
++ ispcroprect.height = pix_output->height;
++ }
++
++ isp_config_pipeline(pix_input, pix_output);
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER
++ && (crop_scaling_h || crop_scaling_w))
++ isp_config_crop(pix_output);
++
++out:
++ return rval;
++}
++EXPORT_SYMBOL(isp_s_fmt_cap);
++
++/**
++ * isp_config_crop - Configures crop parameters in isp resizer.
++ * @croppix: Pointer to V4L2 pixel format structure containing crop parameters
++ **/
++void isp_config_crop(struct v4l2_pix_format *croppix)
++{
++ u8 crop_scaling_w;
++ u8 crop_scaling_h;
++ unsigned long org_left, num_pix, new_top;
++
++ struct v4l2_pix_format *pix = croppix;
++
++ crop_scaling_w = (isp_obj.module.preview_output_width * 10) /
++ pix->width;
++ crop_scaling_h = (isp_obj.module.preview_output_height * 10) /
++ pix->height;
++
++ cur_rect.left = (ispcroprect.left * crop_scaling_w) / 10;
++ cur_rect.top = (ispcroprect.top * crop_scaling_h) / 10;
++ cur_rect.width = (ispcroprect.width * crop_scaling_w) / 10;
++ cur_rect.height = (ispcroprect.height * crop_scaling_h) / 10;
++
++ org_left = cur_rect.left;
++ while (((int)cur_rect.left & 0xFFFFFFF0) != (int)cur_rect.left)
++ (int)cur_rect.left--;
++
++ num_pix = org_left - cur_rect.left;
++ new_top = (int)(num_pix * 3) / 4;
++ cur_rect.top = cur_rect.top - new_top;
++ cur_rect.height = (2 * new_top) + cur_rect.height;
++
++ cur_rect.width = cur_rect.width + (2 * num_pix);
++ while (((int)cur_rect.width & 0xFFFFFFF0) != (int)cur_rect.width)
++ (int)cur_rect.width--;
++
++ isp_obj.tmp_buf_offset =
++ cur_rect.left * 2 +
++ isp_obj.module.preview_output_width * 2 * cur_rect.top;
++
++ ispresizer_trycrop(cur_rect.left, cur_rect.top, cur_rect.width,
++ cur_rect.height,
++ isp_obj.module.resizer_output_width,
++ isp_obj.module.resizer_output_height);
++
++ return;
++}
++EXPORT_SYMBOL(isp_config_crop);
++
++/**
++ * isp_g_crop - Gets crop rectangle size and position.
++ * @a: Pointer to V4L2 crop structure to be filled.
++ *
++ * Always returns 0.
++ **/
++int isp_g_crop(struct v4l2_crop *a)
++{
++ struct v4l2_crop *crop = a;
++
++ crop->c = ispcroprect;
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_g_crop);
++
++/**
++ * isp_s_crop - Sets crop rectangle size and position and queues crop operation
++ * @a: Pointer to V4L2 crop structure with desired parameters.
++ * @pix: Pointer to V4L2 pixel format structure with desired parameters.
++ *
++ * Returns 0 if successful, or -EINVAL if crop parameters are out of bounds.
++ **/
++int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix)
++{
++ struct v4l2_crop *crop = a;
++ int rval = 0;
++
++ if (!isp_obj.ref_count)
++ return -EINVAL;
++
++ if (crop->c.left < 0)
++ crop->c.left = 0;
++ if (crop->c.width < 0)
++ crop->c.width = 0;
++ if (crop->c.top < 0)
++ crop->c.top = 0;
++ if (crop->c.height < 0)
++ crop->c.height = 0;
++
++ if (crop->c.left >= pix->width)
++ crop->c.left = pix->width - 1;
++ if (crop->c.top >= pix->height)
++ crop->c.top = pix->height - 1;
++
++ if (crop->c.left + crop->c.width > pix->width)
++ crop->c.width = pix->width - crop->c.left;
++ if (crop->c.top + crop->c.height > pix->height)
++ crop->c.height = pix->height - crop->c.top;
++
++ ispcroprect.left = crop->c.left;
++ ispcroprect.top = crop->c.top;
++ ispcroprect.width = crop->c.width;
++ ispcroprect.height = crop->c.height;
++
++ isp_config_crop(pix);
++
++ isp_obj.module.applyCrop = 1;
++
++ return rval;
++}
++EXPORT_SYMBOL(isp_s_crop);
++
++/**
++ * isp_try_fmt_cap - Tries desired input/output image formats
++ * @pix_input: Pointer to V4L2 pixel format structure for input image.
++ * @pix_output: Pointer to V4L2 pixel format structure for output image.
++ *
++ * Returns 0 if successful, or return value of either isp_try_size or
++ * isp_try_fmt if there is an error.
++ **/
++int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ int rval = 0;
++
++ rval = isp_calc_pipeline(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++ rval = isp_try_size(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++ rval = isp_try_fmt(pix_input, pix_output);
++ if (rval)
++ goto out;
++
++out:
++ return rval;
++}
++EXPORT_SYMBOL(isp_try_fmt_cap);
++
++/**
++ * isp_try_size - Tries size configuration for I/O images of each ISP submodule
++ * @pix_input: Pointer to V4L2 pixel format structure for input image.
++ * @pix_output: Pointer to V4L2 pixel format structure for output image.
++ *
++ * Returns 0 if successful, or return value of ispccdc_try_size,
++ * isppreview_try_size, or ispresizer_try_size (depending on the pipeline
++ * configuration) if there is an error.
++ **/
++static int isp_try_size(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ int rval = 0;
++
++ if (pix_output->width <= ISPRSZ_MIN_OUTPUT
++ || pix_output->height <= ISPRSZ_MIN_OUTPUT)
++ return -EINVAL;
++
++ if (pix_output->width >= ISPRSZ_MAX_OUTPUT
++ || pix_output->height > ISPRSZ_MAX_OUTPUT)
++ return -EINVAL;
++
++ isp_obj.module.ccdc_input_width = pix_input->width;
++ isp_obj.module.ccdc_input_height = pix_input->height;
++ isp_obj.module.resizer_output_width = pix_output->width;
++ isp_obj.module.resizer_output_height = pix_output->height;
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC) {
++ rval = ispccdc_try_size(isp_obj.module.ccdc_input_width,
++ isp_obj.module.ccdc_input_height,
++ &isp_obj.module.ccdc_output_width,
++ &isp_obj.module.ccdc_output_height);
++ if (rval) {
++ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
++ " supported\n", pix_input->width,
++ pix_input->height);
++ return rval;
++ }
++ pix_output->width = isp_obj.module.ccdc_output_width;
++ pix_output->height = isp_obj.module.ccdc_output_height;
++ }
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
++ isp_obj.module.preview_input_width =
++ isp_obj.module.ccdc_output_width;
++ isp_obj.module.preview_input_height =
++ isp_obj.module.ccdc_output_height;
++ rval = isppreview_try_size(
++ isp_obj.module.preview_input_width,
++ isp_obj.module.preview_input_height,
++ &isp_obj.module.preview_output_width,
++ &isp_obj.module.preview_output_height);
++ if (rval) {
++ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
++ " supported\n", pix_input->width,
++ pix_input->height);
++ return rval;
++ }
++ pix_output->width = isp_obj.module.preview_output_width;
++ pix_output->height = isp_obj.module.preview_output_height;
++ }
++
++ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
++ isp_obj.module.resizer_input_width =
++ isp_obj.module.preview_output_width;
++ isp_obj.module.resizer_input_height =
++ isp_obj.module.preview_output_height;
++ rval = ispresizer_try_size(
++ &isp_obj.module.resizer_input_width,
++ &isp_obj.module.resizer_input_height,
++ &isp_obj.module.resizer_output_width,
++ &isp_obj.module.resizer_output_height);
++ if (rval) {
++ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
++ " supported\n", pix_input->width,
++ pix_input->height);
++ return rval;
++ }
++ pix_output->width = isp_obj.module.resizer_output_width;
++ pix_output->height = isp_obj.module.resizer_output_height;
++ }
++
++ return rval;
++}
++
++/**
++ * isp_try_fmt - Validates input/output format parameters.
++ * @pix_input: Pointer to V4L2 pixel format structure for input image.
++ * @pix_output: Pointer to V4L2 pixel format structure for output image.
++ *
++ * Always returns 0.
++ **/
++int isp_try_fmt(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output)
++{
++ int ifmt;
++
++ for (ifmt = 0; ifmt < NUM_ISP_CAPTURE_FORMATS; ifmt++) {
++ if (pix_output->pixelformat == isp_formats[ifmt].pixelformat)
++ break;
++ }
++ if (ifmt == NUM_ISP_CAPTURE_FORMATS)
++ ifmt = 1;
++ pix_output->pixelformat = isp_formats[ifmt].pixelformat;
++ pix_output->field = V4L2_FIELD_NONE;
++ pix_output->bytesperline = pix_output->width * ISP_BYTES_PER_PIXEL;
++ pix_output->sizeimage =
++ PAGE_ALIGN(pix_output->bytesperline * pix_output->height);
++ pix_output->priv = 0;
++ switch (pix_output->pixelformat) {
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_UYVY:
++ pix_output->colorspace = V4L2_COLORSPACE_JPEG;
++ break;
++ default:
++ pix_output->colorspace = V4L2_COLORSPACE_SRGB;
++ }
++
++ isp_obj.module.pix.pixelformat = pix_output->pixelformat;
++ isp_obj.module.pix.width = pix_output->width;
++ isp_obj.module.pix.height = pix_output->height;
++ isp_obj.module.pix.field = pix_output->field;
++ isp_obj.module.pix.bytesperline = pix_output->bytesperline;
++ isp_obj.module.pix.sizeimage = pix_output->sizeimage;
++ isp_obj.module.pix.priv = pix_output->priv;
++ isp_obj.module.pix.colorspace = pix_output->colorspace;
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_try_fmt);
++
++/**
++ * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
++ *
++ * Routine for saving the context of each module in the ISP.
++ * CCDC, HIST, H3A, PREV, RESZ and MMU.
++ **/
++static void isp_save_ctx(void)
++{
++ isp_save_context(isp_reg_list);
++ ispccdc_save_context();
++ ispmmu_save_context();
++ isphist_save_context();
++ isph3a_save_context();
++ isppreview_save_context();
++ ispresizer_save_context();
++}
++
++/**
++ * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
++ *
++ * Routine for restoring the context of each module in the ISP.
++ * CCDC, HIST, H3A, PREV, RESZ and MMU.
++ **/
++static void isp_restore_ctx(void)
++{
++ isp_restore_context(isp_reg_list);
++ ispccdc_restore_context();
++ ispmmu_restore_context();
++ isphist_restore_context();
++ isph3a_restore_context();
++ isppreview_restore_context();
++ ispresizer_restore_context();
++}
++
++static int isp_enable_clocks(void)
++{
++ int r;
++
++ r = clk_enable(isp_obj.cam_ick);
++ if (r) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_en for ick failed\n");
++ goto out_clk_enable_ick;
++ }
++ r = clk_enable(isp_obj.cam_mclk);
++ if (r) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_en for mclk failed\n");
++ goto out_clk_enable_mclk;
++ }
++ r = clk_enable(isp_obj.csi2_fck);
++ if (r) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_en for csi2_fclk"
++ " failed\n");
++ goto out_clk_enable_csi2_fclk;
++ }
++ return 0;
++
++out_clk_enable_csi2_fclk:
++ clk_disable(isp_obj.cam_mclk);
++out_clk_enable_mclk:
++ clk_disable(isp_obj.cam_ick);
++out_clk_enable_ick:
++ return r;
++}
++
++static void isp_disable_clocks(void)
++{
++ clk_disable(isp_obj.cam_ick);
++ clk_disable(isp_obj.cam_mclk);
++ clk_disable(isp_obj.csi2_fck);
++}
++
++/**
++ * isp_get - Adquires the ISP resource.
++ *
++ * Initializes the clocks for the first acquire.
++ **/
++int isp_get(void)
++{
++ static int has_context;
++ int ret_err = 0;
++
++ if (omap3isp == NULL)
++ return -EBUSY;
++
++ DPRINTK_ISPCTRL("isp_get: old %d\n", isp_obj.ref_count);
++ mutex_lock(&(isp_obj.isp_mutex));
++ if (isp_obj.ref_count == 0) {
++ ret_err = isp_enable_clocks();
++ if (ret_err)
++ goto out_err;
++ /* We don't want to restore context before saving it! */
++ if (has_context)
++ isp_restore_ctx();
++ else
++ has_context = 1;
++ } else {
++ mutex_unlock(&isp_obj.isp_mutex);
++ return -EBUSY;
++ }
++ isp_obj.ref_count++;
++ mutex_unlock(&(isp_obj.isp_mutex));
++
++ DPRINTK_ISPCTRL("isp_get: new %d\n", isp_obj.ref_count);
++ return isp_obj.ref_count;
++
++out_err:
++ mutex_unlock(&(isp_obj.isp_mutex));
++ return ret_err;
++}
++EXPORT_SYMBOL(isp_get);
++
++/**
++ * isp_put - Releases the ISP resource.
++ *
++ * Releases the clocks also for the last release.
++ **/
++int isp_put(void)
++{
++ if (omap3isp == NULL)
++ return -EBUSY;
++
++ DPRINTK_ISPCTRL("isp_put: old %d\n", isp_obj.ref_count);
++ mutex_lock(&(isp_obj.isp_mutex));
++ if (isp_obj.ref_count) {
++ if (--isp_obj.ref_count == 0) {
++ isp_save_ctx();
++ isp_tmp_buf_free();
++ isp_release_resources();
++ isp_obj.module.isp_pipeline = 0;
++ isp_disable_clocks();
++ memset(&ispcroprect, 0, sizeof(ispcroprect));
++ memset(&cur_rect, 0, sizeof(cur_rect));
++ }
++ }
++ mutex_unlock(&(isp_obj.isp_mutex));
++ DPRINTK_ISPCTRL("isp_put: new %d\n", isp_obj.ref_count);
++ return isp_obj.ref_count;
++}
++EXPORT_SYMBOL(isp_put);
++
++/**
++ * isp_save_context - Saves the values of the ISP module registers.
++ * @reg_list: Structure containing pairs of register address and value to
++ * modify on OMAP.
++ **/
++void isp_save_context(struct isp_reg *reg_list)
++{
++ struct isp_reg *next = reg_list;
++
++ for (; next->reg != ISP_TOK_TERM; next++)
++ next->val = isp_reg_readl(next->mmio_range, next->reg);
++}
++EXPORT_SYMBOL(isp_save_context);
++
++/**
++ * isp_restore_context - Restores the values of the ISP module registers.
++ * @reg_list: Structure containing pairs of register address and value to
++ * modify on OMAP.
++ **/
++void isp_restore_context(struct isp_reg *reg_list)
++{
++ struct isp_reg *next = reg_list;
++
++ for (; next->reg != ISP_TOK_TERM; next++)
++ isp_reg_writel(next->val, next->mmio_range, next->reg);
++}
++EXPORT_SYMBOL(isp_restore_context);
++
++static int isp_remove(struct platform_device *pdev)
++{
++ struct isp_device *isp = platform_get_drvdata(pdev);
++ int i;
++
++ isp_csi2_cleanup();
++ isp_af_exit();
++ isp_resizer_cleanup();
++ isp_preview_cleanup();
++ ispmmu_cleanup();
++ isph3a_aewb_cleanup();
++ isp_hist_cleanup();
++ isp_ccdc_cleanup();
++
++ if (!isp)
++ return 0;
++
++ clk_put(isp_obj.cam_ick);
++ clk_put(isp_obj.cam_mclk);
++ clk_put(isp_obj.csi2_fck);
++
++ free_irq(isp->irq, &isp_obj);
++
++ for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
++ if (isp->mmio_base[i]) {
++ iounmap((void *)isp->mmio_base[i]);
++ isp->mmio_base[i] = 0;
++ }
++
++ if (isp->mmio_base_phys[i]) {
++ release_mem_region(isp->mmio_base_phys[i],
++ isp->mmio_size[i]);
++ isp->mmio_base_phys[i] = 0;
++ }
++ }
++
++ omap3isp = NULL;
++
++ kfree(isp);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++
++static int isp_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ int reset;
++
++ mutex_lock(&(isp_obj.isp_mutex));
++ DPRINTK_ISPCTRL("isp_suspend: starting\n");
++ if (isp_obj.ref_count == 0)
++ goto out;
++
++ isp_disable_interrupts();
++ reset = isp_suspend_modules();
++ isp_save_ctx();
++ if (reset)
++ isp_reset();
++
++ isp_disable_clocks();
++
++out:
++ DPRINTK_ISPCTRL("isp_suspend: done\n");
++ mutex_unlock(&(isp_obj.isp_mutex));
++ return 0;
++}
++
++static int isp_resume(struct platform_device *pdev)
++{
++ int ret_err = 0;
++
++ DPRINTK_ISPCTRL("isp_resume: starting\n");
++
++ if (omap3isp == NULL)
++ goto out;
++
++ if (isp_obj.ref_count >= 0) {
++ ret_err = isp_enable_clocks();
++ if (ret_err)
++ goto out;
++ isp_restore_ctx();
++ isp_resume_modules();
++ isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
++ isp_start();
++ }
++
++out:
++ DPRINTK_ISPCTRL("isp_resume: done \n");
++ return ret_err;
++}
++
++#else
++
++#define isp_suspend NULL
++#define isp_resume NULL
++
++#endif /* CONFIG_PM */
++
++
++static int isp_probe(struct platform_device *pdev)
++{
++ struct isp_device *isp;
++ int ret_err = 0;
++ int i;
++
++ isp = kzalloc(sizeof(*isp), GFP_KERNEL);
++ if (!isp) {
++ dev_err(&pdev->dev, "could not allocate memory\n");
++ return -ENOMEM;
++ }
++
++ platform_set_drvdata(pdev, isp);
++
++ isp->dev = &pdev->dev;
++
++ for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
++ struct resource *mem;
++ /* request the mem region for the camera registers */
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ if (!mem) {
++ dev_err(isp->dev, "no mem resource?\n");
++ return -ENODEV;
++ }
++
++ if (!request_mem_region(mem->start, mem->end - mem->start + 1,
++ pdev->name)) {
++ dev_err(isp->dev,
++ "cannot reserve camera register I/O region\n");
++ return -ENODEV;
++
++ }
++ isp->mmio_base_phys[i] = mem->start;
++ isp->mmio_size[i] = mem->end - mem->start + 1;
++
++ /* map the region */
++ isp->mmio_base[i] = (unsigned long)
++ ioremap_nocache(isp->mmio_base_phys[i],
++ isp->mmio_size[i]);
++ if (!isp->mmio_base[i]) {
++ dev_err(isp->dev,
++ "cannot map camera register I/O region\n");
++ return -ENODEV;
++ }
++ }
++
++ isp->irq = platform_get_irq(pdev, 0);
++ if (isp->irq <= 0) {
++ dev_err(isp->dev, "no irq for camera?\n");
++ return -ENODEV;
++ }
++
++ isp_obj.cam_ick = clk_get(&camera_dev, "cam_ick");
++ if (IS_ERR(isp_obj.cam_ick)) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
++ "cam_ick failed\n");
++ return PTR_ERR(isp_obj.cam_ick);
++ }
++ isp_obj.cam_mclk = clk_get(&camera_dev, "cam_mclk");
++ if (IS_ERR(isp_obj.cam_mclk)) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
++ "cam_mclk failed\n");
++ ret_err = PTR_ERR(isp_obj.cam_mclk);
++ goto out_clk_get_mclk;
++ }
++ isp_obj.csi2_fck = clk_get(&camera_dev, "csi2_96m_fck");
++ if (IS_ERR(isp_obj.csi2_fck)) {
++ DPRINTK_ISPCTRL("ISP_ERR: clk_get for csi2_fclk"
++ " failed\n");
++ ret_err = PTR_ERR(isp_obj.csi2_fck);
++ goto out_clk_get_csi2_fclk;
++ }
++
++ if (request_irq(isp->irq, omap34xx_isp_isr, IRQF_SHARED,
++ "Omap 3 Camera ISP", &isp_obj)) {
++ DPRINTK_ISPCTRL("Could not install ISR\n");
++ ret_err = -EINVAL;
++ goto out_request_irq;
++ }
++
++ isp_obj.ref_count = 0;
++
++ mutex_init(&(isp_obj.isp_mutex));
++ spin_lock_init(&isp_obj.lock);
++ spin_lock_init(&isp_obj.bufs.lock);
++
++ omap3isp = isp;
++
++ ret_err = ispmmu_init();
++ if (ret_err)
++ goto out_ispmmu_init;
++
++ isp_ccdc_init();
++ isp_hist_init();
++ isph3a_aewb_init();
++ isp_preview_init();
++ isp_resizer_init();
++ isp_af_init();
++ isp_csi2_init();
++
++ isp_get();
++ isp_power_settings(1);
++ isp_put();
++
++ isph3a_notify(1);
++ isp_af_notify(1);
++
++ return 0;
++
++out_ispmmu_init:
++ omap3isp = NULL;
++ free_irq(isp->irq, &isp_obj);
++out_request_irq:
++ clk_put(isp_obj.csi2_fck);
++out_clk_get_csi2_fclk:
++ clk_put(isp_obj.cam_mclk);
++out_clk_get_mclk:
++ clk_put(isp_obj.cam_ick);
++
++ return ret_err;
++}
++
++static struct platform_driver omap3isp_driver = {
++ .probe = isp_probe,
++ .remove = isp_remove,
++ .suspend = isp_suspend,
++ .resume = isp_resume,
++ .driver = {
++ .name = "omap3isp",
++ },
++};
++
++/**
++ * isp_init - ISP module initialization.
++ **/
++static int __init isp_init(void)
++{
++ return platform_driver_register(&omap3isp_driver);
++}
++
++/**
++ * isp_cleanup - ISP module cleanup.
++ **/
++static void __exit isp_cleanup(void)
++{
++ platform_driver_unregister(&omap3isp_driver);
++}
++
++/**
++ * isp_print_status - Prints the values of the ISP Control Module registers
++ *
++ * Also prints other debug information stored in the ISP module structure.
++ **/
++void isp_print_status(void)
++{
++ if (!is_ispctrl_debug_enabled())
++ return;
++
++ DPRINTK_ISPCTRL("###ISP_CTRL=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ DPRINTK_ISPCTRL("###ISP_TCTRL_CTRL=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
++ DPRINTK_ISPCTRL("###ISP_SYSCONFIG=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG));
++ DPRINTK_ISPCTRL("###ISP_SYSSTATUS=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS));
++ DPRINTK_ISPCTRL("###ISP_IRQ0ENABLE=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
++ DPRINTK_ISPCTRL("###ISP_IRQ0STATUS=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
++}
++EXPORT_SYMBOL(isp_print_status);
++
++module_init(isp_init);
++module_exit(isp_cleanup);
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_DESCRIPTION("ISP Control Module Library");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h
+new file mode 100644
+index 0000000..55c98a9
+--- /dev/null
++++ b/drivers/media/video/isp/isp.h
+@@ -0,0 +1,318 @@
++/*
++ * isp.h
++ *
++ * Top level public header file for ISP Control module in
++ * TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ * Copyright (C) 2009 Nokia.
++ *
++ * Contributors:
++ * Sameer Venkatraman <sameerv@ti.com>
++ * Mohit Jalori <mjalori@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_TOP_H
++#define OMAP_ISP_TOP_H
++#include <mach/cpu.h>
++#include <media/videobuf-dma-sg.h>
++#include <linux/videodev2.h>
++#define OMAP_ISP_CCDC (1 << 0)
++#define OMAP_ISP_PREVIEW (1 << 1)
++#define OMAP_ISP_RESIZER (1 << 2)
++#define OMAP_ISP_AEWB (1 << 3)
++#define OMAP_ISP_AF (1 << 4)
++#define OMAP_ISP_HIST (1 << 5)
++
++#define ISP_TOK_TERM 0xFFFFFFFF /*
++ * terminating token for ISP
++ * modules reg list
++ */
++#define NUM_BUFS VIDEO_MAX_FRAME
++
++#ifndef CONFIG_ARCH_OMAP3410
++#define USE_ISP_PREVIEW
++#define USE_ISP_RESZ
++#define is_isppreview_enabled() 1
++#define is_ispresizer_enabled() 1
++#else
++#define is_isppreview_enabled() 0
++#define is_ispresizer_enabled() 0
++#endif
++
++#define ISP_BYTES_PER_PIXEL 2
++#define NUM_ISP_CAPTURE_FORMATS (sizeof(isp_formats) / \
++ sizeof(isp_formats[0]))
++typedef int (*isp_vbq_callback_ptr) (struct videobuf_buffer *vb);
++typedef void (*isp_callback_t) (unsigned long status,
++ isp_vbq_callback_ptr arg1, void *arg2);
++
++enum isp_mem_resources {
++ OMAP3_ISP_IOMEM_MAIN,
++ OMAP3_ISP_IOMEM_CBUFF,
++ OMAP3_ISP_IOMEM_CCP2,
++ OMAP3_ISP_IOMEM_CCDC,
++ OMAP3_ISP_IOMEM_HIST,
++ OMAP3_ISP_IOMEM_H3A,
++ OMAP3_ISP_IOMEM_PREV,
++ OMAP3_ISP_IOMEM_RESZ,
++ OMAP3_ISP_IOMEM_SBL,
++ OMAP3_ISP_IOMEM_CSI2A,
++ OMAP3_ISP_IOMEM_CSI2PHY
++};
++
++struct isp_device {
++ struct device *dev;
++
++ /*** platform HW resources ***/
++ unsigned int irq;
++
++#define mmio_base_main mmio_base[OMAP3_ISP_IOMEM_MAIN]
++#define mmio_cbuff_main mmio_base[OMAP3_ISP_IOMEM_CBUFF]
++#define mmio_ccp2_main mmio_base[OMAP3_ISP_IOMEM_CCP2]
++#define mmio_ccdc_main mmio_base[OMAP3_ISP_IOMEM_CCDC]
++#define mmio_hist_main mmio_base[OMAP3_ISP_IOMEM_HIST]
++#define mmio_h3a_main mmio_base[OMAP3_ISP_IOMEM_H3A]
++#define mmio_prev_main mmio_base[OMAP3_ISP_IOMEM_PREV]
++#define mmio_resz_main mmio_base[OMAP3_ISP_IOMEM_RESZ]
++#define mmio_sbl_main mmio_base[OMAP3_ISP_IOMEM_SBL]
++#define mmio_csi2_main mmio_base[OMAP3_ISP_IOMEM_CSI2A]
++#define mmio_csi2phy_main mmio_base[OMAP3_ISP_IOMEM_CSI2PHY]
++ unsigned long mmio_base[OMAP3_ISP_IOMEM_CSI2PHY + 1];
++ unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_CSI2PHY + 1];
++ unsigned long mmio_size[OMAP3_ISP_IOMEM_CSI2PHY + 1];
++};
++
++enum isp_interface_type {
++ ISP_PARLL = 1,
++ ISP_CSIA = 2,
++ ISP_CSIB = 4,
++ ISP_NONE = 8 /* memory input to preview / resizer */
++};
++
++enum isp_irqevents {
++ CSIA = 0x01,
++ CSIB = 0x10,
++ CCDC_VD0 = 0x100,
++ CCDC_VD1 = 0x200,
++ CCDC_VD2 = 0x400,
++ CCDC_ERR = 0x800,
++ H3A_AWB_DONE = 0x2000,
++ H3A_AF_DONE = 0x1000,
++ HIST_DONE = 0x10000,
++ PREV_DONE = 0x100000,
++ LSC_DONE = 0x20000,
++ LSC_PRE_COMP = 0x40000,
++ LSC_PRE_ERR = 0x80000,
++ RESZ_DONE = 0x1000000,
++ SBL_OVF = 0x2000000,
++ MMU_ERR = 0x10000000,
++ OCP_ERR = 0x20000000,
++ HS_VS = 0x80000000
++};
++
++enum isp_callback_type {
++ CBK_CCDC_VD0,
++ CBK_CCDC_VD1,
++ CBK_PREV_DONE,
++ CBK_RESZ_DONE,
++ CBK_MMU_ERR,
++ CBK_H3A_AWB_DONE,
++ CBK_HIST_DONE,
++ CBK_HS_VS,
++ CBK_LSC_ISR,
++ CBK_H3A_AF_DONE,
++ CBK_CATCHALL,
++ CBK_CSIA,
++ CBK_CSIB,
++ CBK_END,
++};
++
++/**
++ * struct isp_reg - Structure for ISP register values.
++ * @reg: 32-bit Register address.
++ * @val: 32-bit Register value.
++ */
++struct isp_reg {
++ enum isp_mem_resources mmio_range;
++ u32 reg;
++ u32 val;
++};
++
++/**
++ * struct isp_interface_config - ISP interface configuration.
++ * @ccdc_par_ser: ISP interface type. 0 - Parallel, 1 - CSIA, 2 - CSIB to CCDC.
++ * @par_bridge: CCDC Bridge input control. Parallel interface.
++ * 0 - Disable, 1 - Enable, first byte->cam_d(bits 7 to 0)
++ * 2 - Enable, first byte -> cam_d(bits 15 to 8)
++ * @par_clk_pol: Pixel clock polarity on the parallel interface.
++ * 0 - Non Inverted, 1 - Inverted
++ * @dataline_shift: Data lane shifter.
++ * 0 - No Shift, 1 - CAMEXT[13 to 2]->CAM[11 to 0]
++ * 2 - CAMEXT[13 to 4]->CAM[9 to 0]
++ * 3 - CAMEXT[13 to 6]->CAM[7 to 0]
++ * @hsvs_syncdetect: HS or VS synchronization signal detection.
++ * 0 - HS Falling, 1 - HS rising
++ * 2 - VS falling, 3 - VS rising
++ * @strobe: Strobe related parameter.
++ * @prestrobe: PreStrobe related parameter.
++ * @shutter: Shutter related parameter.
++ * @hskip: Horizontal Start Pixel performed in Preview module.
++ * @vskip: Vertical Start Line performed in Preview module.
++ * @wenlog: Store the value for the sensor specific wenlog field.
++ * @wait_hs_vs: Wait for this many hs_vs before anything else in the beginning.
++ */
++struct isp_interface_config {
++ enum isp_interface_type ccdc_par_ser;
++ u8 dataline_shift;
++ u32 hsvs_syncdetect;
++ int strobe;
++ int prestrobe;
++ int shutter;
++ u32 prev_sph;
++ u32 prev_slv;
++ u32 wenlog;
++ int wait_hs_vs;
++ union {
++ struct par {
++ unsigned par_bridge:2;
++ unsigned par_clk_pol:1;
++ } par;
++ struct csi {
++ unsigned crc:1;
++ unsigned mode:1;
++ unsigned edge:1;
++ unsigned signalling:1;
++ unsigned strobe_clock_inv:1;
++ unsigned vs_edge:1;
++ unsigned channel:3;
++ unsigned vpclk:2; /* Video port output clock */
++ unsigned int data_start;
++ unsigned int data_size;
++ u32 format; /* V4L2_PIX_FMT_* */
++ } csi;
++ } u;
++};
++
++u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset);
++
++void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
++ u32 reg_offset);
++
++static inline void isp_reg_and(enum isp_mem_resources mmio_range, u32 reg,
++ u32 and_bits)
++{
++ u32 v = isp_reg_readl(mmio_range, reg);
++
++ isp_reg_writel(v & and_bits, mmio_range, reg);
++}
++
++static inline void isp_reg_or(enum isp_mem_resources mmio_range, u32 reg,
++ u32 or_bits)
++{
++ u32 v = isp_reg_readl(mmio_range, reg);
++
++ isp_reg_writel(v | or_bits, mmio_range, reg);
++}
++
++static inline void isp_reg_and_or(enum isp_mem_resources mmio_range, u32 reg,
++ u32 and_bits, u32 or_bits)
++{
++ u32 v = isp_reg_readl(mmio_range, reg);
++
++ isp_reg_writel((v & and_bits) | or_bits, mmio_range, reg);
++}
++
++void isp_start(void);
++
++void isp_stop(void);
++
++int isp_buf_queue(struct videobuf_buffer *vb,
++ void (*complete)(struct videobuf_buffer *vb, void *priv),
++ void *priv);
++
++int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
++ unsigned int *size);
++
++int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
++ enum v4l2_field field);
++
++void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb);
++
++int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
++ isp_vbq_callback_ptr arg1, void *arg2);
++
++int isp_unset_callback(enum isp_callback_type type);
++
++u32 isp_set_xclk(u32 xclk, u8 xclksel);
++
++int isp_configure_interface(struct isp_interface_config *config);
++
++int isp_get(void);
++
++int isp_put(void);
++
++int isp_queryctrl(struct v4l2_queryctrl *a);
++
++int isp_querymenu(struct v4l2_querymenu *a);
++
++int isp_g_ctrl(struct v4l2_control *a);
++
++int isp_s_ctrl(struct v4l2_control *a);
++
++int isp_enum_fmt_cap(struct v4l2_fmtdesc *f);
++
++int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output);
++
++void isp_g_fmt_cap(struct v4l2_pix_format *pix);
++
++int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output);
++
++int isp_g_crop(struct v4l2_crop *a);
++
++int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix);
++
++void isp_config_crop(struct v4l2_pix_format *pix);
++
++int isp_try_fmt(struct v4l2_pix_format *pix_input,
++ struct v4l2_pix_format *pix_output);
++
++int isp_handle_private(int cmd, void *arg);
++
++void isp_save_context(struct isp_reg *);
++
++void isp_restore_context(struct isp_reg *);
++
++void isp_print_status(void);
++
++int __init isp_ccdc_init(void);
++int __init isp_hist_init(void);
++int __init isph3a_aewb_init(void);
++int __init isp_preview_init(void);
++int __init isp_resizer_init(void);
++int __init isp_af_init(void);
++int __init isp_csi2_init(void);
++
++void isp_ccdc_cleanup(void);
++void isp_hist_cleanup(void);
++void isph3a_aewb_cleanup(void);
++void isp_preview_cleanup(void);
++void isp_hist_cleanup(void);
++void isp_resizer_cleanup(void);
++void isp_af_exit(void);
++void isp_csi2_cleanup(void);
++
++#endif /* OMAP_ISP_TOP_H */
+diff --git a/drivers/media/video/isp/ispreg.h b/drivers/media/video/isp/ispreg.h
+new file mode 100644
+index 0000000..4f8e1ef
+--- /dev/null
++++ b/drivers/media/video/isp/ispreg.h
+@@ -0,0 +1,1674 @@
++/*
++ * ispreg.h
++ *
++ * Header file for all the ISP module in TI's OMAP3 Camera ISP.
++ * It has the OMAP HW register definitions.
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ * Copyright (C) 2009 Nokia.
++ *
++ * Contributors:
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ * Thara Gopinath <thara@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef __ISPREG_H__
++#define __ISPREG_H__
++
++#include <mach/omap34xx.h>
++
++/* Note: Uncomment below defines as needed for enabling module specific debug
++ * messages
++ */
++
++/*
++ #define OMAP_ISPCTRL_DEBUG
++ #define OMAP_ISPCCDC_DEBUG
++ #define OMAP_ISPPREV_DEBUG
++ #define OMAP_ISPRESZ_DEBUG
++ #define OMAP_ISPMMU_DEBUG
++ #define OMAP_ISPH3A_DEBUG
++ #define OMAP_ISP_AF_DEBUG
++ #define OMAP_ISPHIST_DEBUG
++*/
++
++#ifdef OMAP_ISPCTRL_DEBUG
++#define DPRINTK_ISPCTRL(format, ...) \
++ printk(KERN_INFO "ISPCTRL: " format, ## __VA_ARGS__)
++#define is_ispctrl_debug_enabled() 1
++#else
++#define DPRINTK_ISPCTRL(format, ...)
++#define is_ispctrl_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPCCDC_DEBUG
++#define DPRINTK_ISPCCDC(format, ...) \
++ printk(KERN_INFO "ISPCCDC: " format, ## __VA_ARGS__)
++#define is_ispccdc_debug_enabled() 1
++#else
++#define DPRINTK_ISPCCDC(format, ...)
++#define is_ispccdc_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPPREV_DEBUG
++#define DPRINTK_ISPPREV(format, ...) \
++ printk(KERN_INFO "ISPPREV: " format, ## __VA_ARGS__)
++#define is_ispprev_debug_enabled() 1
++#else
++#define DPRINTK_ISPPREV(format, ...)
++#define is_ispprev_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPRESZ_DEBUG
++#define DPRINTK_ISPRESZ(format, ...) \
++ printk(KERN_INFO "ISPRESZ: " format, ## __VA_ARGS__)
++#define is_ispresz_debug_enabled() 1
++#else
++#define DPRINTK_ISPRESZ(format, ...)
++#define is_ispresz_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPMMU_DEBUG
++#define DPRINTK_ISPMMU(format, ...) \
++ printk(KERN_INFO "ISPMMU: " format, ## __VA_ARGS__)
++#define is_ispmmu_debug_enabled() 1
++#else
++#define DPRINTK_ISPMMU(format, ...)
++#define is_ispmmu_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPH3A_DEBUG
++#define DPRINTK_ISPH3A(format, ...) \
++ printk(KERN_INFO "ISPH3A: " format, ## __VA_ARGS__)
++#define is_isph3a_debug_enabled() 1
++#else
++#define DPRINTK_ISPH3A(format, ...)
++#define is_isph3a_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISP_AF_DEBUG
++#define DPRINTK_ISP_AF(format, ...) \
++ printk(KERN_INFO "ISP_AF: " format, ## __VA_ARGS__)
++#define is_isp_af_debug_enabled() 1
++#else
++#define DPRINTK_ISP_AF(format, ...)
++#define is_isp_af_debug_enabled() 0
++#endif
++
++#ifdef OMAP_ISPHIST_DEBUG
++#define DPRINTK_ISPHIST(format, ...) \
++ printk(KERN_INFO "ISPHIST: " format, ## __VA_ARGS__)
++#define is_isphist_debug_enabled() 1
++#else
++#define DPRINTK_ISPHIST(format, ...)
++#define is_isphist_debug_enabled() 0
++#endif
++
++#define ISP_32B_BOUNDARY_BUF 0xFFFFFFE0
++#define ISP_32B_BOUNDARY_OFFSET 0x0000FFE0
++
++#define CM_CAM_MCLK_HZ 216000000
++
++/* ISP Submodules offset */
++
++#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
++#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
++
++#define OMAP3ISP_CBUFF_REG_OFFSET 0x0100
++#define OMAP3ISP_CBUFF_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_CBUFF_REG_OFFSET)
++#define OMAP3ISP_CBUFF_REG(offset) (OMAP3ISP_CBUFF_REG_BASE + (offset))
++
++#define OMAP3ISP_CCP2_REG_OFFSET 0x0400
++#define OMAP3ISP_CCP2_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_CCP2_REG_OFFSET)
++#define OMAP3ISP_CCP2_REG(offset) (OMAP3ISP_CCP2_REG_BASE + (offset))
++
++#define OMAP3ISP_CCDC_REG_OFFSET 0x0600
++#define OMAP3ISP_CCDC_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_CCDC_REG_OFFSET)
++#define OMAP3ISP_CCDC_REG(offset) (OMAP3ISP_CCDC_REG_BASE + (offset))
++
++#define OMAP3ISP_HIST_REG_OFFSET 0x0A00
++#define OMAP3ISP_HIST_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_HIST_REG_OFFSET)
++#define OMAP3ISP_HIST_REG(offset) (OMAP3ISP_HIST_REG_BASE + (offset))
++
++#define OMAP3ISP_H3A_REG_OFFSET 0x0C00
++#define OMAP3ISP_H3A_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_H3A_REG_OFFSET)
++#define OMAP3ISP_H3A_REG(offset) (OMAP3ISP_H3A_REG_BASE + (offset))
++
++#define OMAP3ISP_PREV_REG_OFFSET 0x0E00
++#define OMAP3ISP_PREV_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_PREV_REG_OFFSET)
++#define OMAP3ISP_PREV_REG(offset) (OMAP3ISP_PREV_REG_BASE + (offset))
++
++#define OMAP3ISP_RESZ_REG_OFFSET 0x1000
++#define OMAP3ISP_RESZ_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_RESZ_REG_OFFSET)
++#define OMAP3ISP_RESZ_REG(offset) (OMAP3ISP_RESZ_REG_BASE + (offset))
++
++#define OMAP3ISP_SBL_REG_OFFSET 0x1200
++#define OMAP3ISP_SBL_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_SBL_REG_OFFSET)
++#define OMAP3ISP_SBL_REG(offset) (OMAP3ISP_SBL_REG_BASE + (offset))
++
++#define OMAP3ISP_MMU_REG_OFFSET 0x1400
++#define OMAP3ISP_MMU_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_MMU_REG_OFFSET)
++#define OMAP3ISP_MMU_REG(offset) (OMAP3ISP_MMU_REG_BASE + (offset))
++
++#define OMAP3ISP_CSI2A_REG_OFFSET 0x1800
++#define OMAP3ISP_CSI2A_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_CSI2A_REG_OFFSET)
++#define OMAP3ISP_CSI2A_REG(offset) (OMAP3ISP_CSI2A_REG_BASE + (offset))
++
++#define OMAP3ISP_CSI2PHY_REG_OFFSET 0x1970
++#define OMAP3ISP_CSI2PHY_REG_BASE (OMAP3ISP_REG_BASE + \
++ OMAP3ISP_CSI2PHY_REG_OFFSET)
++#define OMAP3ISP_CSI2PHY_REG(offset) (OMAP3ISP_CSI2PHY_REG_BASE + (offset))
++
++/* ISP module register offset */
++
++#define ISP_REVISION (0x000)
++#define ISP_SYSCONFIG (0x004)
++#define ISP_SYSSTATUS (0x008)
++#define ISP_IRQ0ENABLE (0x00C)
++#define ISP_IRQ0STATUS (0x010)
++#define ISP_IRQ1ENABLE (0x014)
++#define ISP_IRQ1STATUS (0x018)
++#define ISP_TCTRL_GRESET_LENGTH (0x030)
++#define ISP_TCTRL_PSTRB_REPLAY (0x034)
++#define ISP_CTRL (0x040)
++#define ISP_SECURE (0x044)
++#define ISP_TCTRL_CTRL (0x050)
++#define ISP_TCTRL_FRAME (0x054)
++#define ISP_TCTRL_PSTRB_DELAY (0x058)
++#define ISP_TCTRL_STRB_DELAY (0x05C)
++#define ISP_TCTRL_SHUT_DELAY (0x060)
++#define ISP_TCTRL_PSTRB_LENGTH (0x064)
++#define ISP_TCTRL_STRB_LENGTH (0x068)
++#define ISP_TCTRL_SHUT_LENGTH (0x06C)
++#define ISP_PING_PONG_ADDR (0x070)
++#define ISP_PING_PONG_MEM_RANGE (0x074)
++#define ISP_PING_PONG_BUF_SIZE (0x078)
++
++/* CSI1 receiver registers (ES2.0) */
++#define ISPCSI1_REVISION (0x000)
++#define ISPCSI1_SYSCONFIG (0x004)
++#define ISPCSI1_SYSSTATUS (0x008)
++#define ISPCSI1_LC01_IRQENABLE (0x00C)
++#define ISPCSI1_LC01_IRQSTATUS (0x010)
++#define ISPCSI1_LC23_IRQENABLE (0x014)
++#define ISPCSI1_LC23_IRQSTATUS (0x018)
++#define ISPCSI1_LCM_IRQENABLE (0x02C)
++#define ISPCSI1_LCM_IRQSTATUS (0x030)
++#define ISPCSI1_CTRL (0x040)
++#define ISPCSI1_DBG (0x044)
++#define ISPCSI1_GNQ (0x048)
++#define ISPCSI1_LCx_CTRL(x) ((0x050)+0x30*(x))
++#define ISPCSI1_LCx_CODE(x) ((0x054)+0x30*(x))
++#define ISPCSI1_LCx_STAT_START(x) ((0x058)+0x30*(x))
++#define ISPCSI1_LCx_STAT_SIZE(x) ((0x05C)+0x30*(x))
++#define ISPCSI1_LCx_SOF_ADDR(x) ((0x060)+0x30*(x))
++#define ISPCSI1_LCx_EOF_ADDR(x) ((0x064)+0x30*(x))
++#define ISPCSI1_LCx_DAT_START(x) ((0x068)+0x30*(x))
++#define ISPCSI1_LCx_DAT_SIZE(x) ((0x06C)+0x30*(x))
++#define ISPCSI1_LCx_DAT_PING_ADDR(x) ((0x070)+0x30*(x))
++#define ISPCSI1_LCx_DAT_PONG_ADDR(x) ((0x074)+0x30*(x))
++#define ISPCSI1_LCx_DAT_OFST(x) ((0x078)+0x30*(x))
++#define ISPCSI1_LCM_CTRL (0x1D0)
++#define ISPCSI1_LCM_VSIZE (0x1D4)
++#define ISPCSI1_LCM_HSIZE (0x1D8)
++#define ISPCSI1_LCM_PREFETCH (0x1DC)
++#define ISPCSI1_LCM_SRC_ADDR (0x1E0)
++#define ISPCSI1_LCM_SRC_OFST (0x1E4)
++#define ISPCSI1_LCM_DST_ADDR (0x1E8)
++#define ISPCSI1_LCM_DST_OFST (0x1EC)
++#define ISP_CSIB_SYSCONFIG ISPCSI1_SYSCONFIG
++#define ISP_CSIA_SYSCONFIG ISPCSI2_SYSCONFIG
++
++/* ISP_CBUFF Registers */
++
++#define ISP_CBUFF_SYSCONFIG (0x010)
++#define ISP_CBUFF_IRQENABLE (0x01C)
++
++#define ISP_CBUFF0_CTRL (0x020)
++#define ISP_CBUFF1_CTRL (0x024)
++
++#define ISP_CBUFF0_START (0x040)
++#define ISP_CBUFF1_START (0x044)
++
++#define ISP_CBUFF0_END (0x050)
++#define ISP_CBUFF1_END (0x054)
++
++#define ISP_CBUFF0_WINDOWSIZE (0x060)
++#define ISP_CBUFF1_WINDOWSIZE (0x064)
++
++#define ISP_CBUFF0_THRESHOLD (0x070)
++#define ISP_CBUFF1_THRESHOLD (0x074)
++
++/* CCDC module register offset */
++
++#define ISPCCDC_PID (0x000)
++#define ISPCCDC_PCR (0x004)
++#define ISPCCDC_SYN_MODE (0x008)
++#define ISPCCDC_HD_VD_WID (0x00C)
++#define ISPCCDC_PIX_LINES (0x010)
++#define ISPCCDC_HORZ_INFO (0x014)
++#define ISPCCDC_VERT_START (0x018)
++#define ISPCCDC_VERT_LINES (0x01C)
++#define ISPCCDC_CULLING (0x020)
++#define ISPCCDC_HSIZE_OFF (0x024)
++#define ISPCCDC_SDOFST (0x028)
++#define ISPCCDC_SDR_ADDR (0x02C)
++#define ISPCCDC_CLAMP (0x030)
++#define ISPCCDC_DCSUB (0x034)
++#define ISPCCDC_COLPTN (0x038)
++#define ISPCCDC_BLKCMP (0x03C)
++#define ISPCCDC_FPC (0x040)
++#define ISPCCDC_FPC_ADDR (0x044)
++#define ISPCCDC_VDINT (0x048)
++#define ISPCCDC_ALAW (0x04C)
++#define ISPCCDC_REC656IF (0x050)
++#define ISPCCDC_CFG (0x054)
++#define ISPCCDC_FMTCFG (0x058)
++#define ISPCCDC_FMT_HORZ (0x05C)
++#define ISPCCDC_FMT_VERT (0x060)
++#define ISPCCDC_FMT_ADDR0 (0x064)
++#define ISPCCDC_FMT_ADDR1 (0x068)
++#define ISPCCDC_FMT_ADDR2 (0x06C)
++#define ISPCCDC_FMT_ADDR3 (0x070)
++#define ISPCCDC_FMT_ADDR4 (0x074)
++#define ISPCCDC_FMT_ADDR5 (0x078)
++#define ISPCCDC_FMT_ADDR6 (0x07C)
++#define ISPCCDC_FMT_ADDR7 (0x080)
++#define ISPCCDC_PRGEVEN0 (0x084)
++#define ISPCCDC_PRGEVEN1 (0x088)
++#define ISPCCDC_PRGODD0 (0x08C)
++#define ISPCCDC_PRGODD1 (0x090)
++#define ISPCCDC_VP_OUT (0x094)
++
++#define ISPCCDC_LSC_CONFIG (0x098)
++#define ISPCCDC_LSC_INITIAL (0x09C)
++#define ISPCCDC_LSC_TABLE_BASE (0x0A0)
++#define ISPCCDC_LSC_TABLE_OFFSET (0x0A4)
++
++/* SBL */
++#define ISPSBL_CCDC_WR_0 (0x028)
++#define ISPSBL_CCDC_WR_0_DATA_READY (1 << 21)
++#define ISPSBL_CCDC_WR_1 (0x02C)
++#define ISPSBL_CCDC_WR_2 (0x030)
++#define ISPSBL_CCDC_WR_3 (0x034)
++
++/* Histogram registers */
++#define ISPHIST_PID (0x000)
++#define ISPHIST_PCR (0x004)
++#define ISPHIST_CNT (0x008)
++#define ISPHIST_WB_GAIN (0x00C)
++#define ISPHIST_R0_HORZ (0x010)
++#define ISPHIST_R0_VERT (0x014)
++#define ISPHIST_R1_HORZ (0x018)
++#define ISPHIST_R1_VERT (0x01C)
++#define ISPHIST_R2_HORZ (0x020)
++#define ISPHIST_R2_VERT (0x024)
++#define ISPHIST_R3_HORZ (0x028)
++#define ISPHIST_R3_VERT (0x02C)
++#define ISPHIST_ADDR (0x030)
++#define ISPHIST_DATA (0x034)
++#define ISPHIST_RADD (0x038)
++#define ISPHIST_RADD_OFF (0x03C)
++#define ISPHIST_H_V_INFO (0x040)
++
++/* H3A module registers */
++#define ISPH3A_PID (0x000)
++#define ISPH3A_PCR (0x004)
++#define ISPH3A_AEWWIN1 (0x04C)
++#define ISPH3A_AEWINSTART (0x050)
++#define ISPH3A_AEWINBLK (0x054)
++#define ISPH3A_AEWSUBWIN (0x058)
++#define ISPH3A_AEWBUFST (0x05C)
++#define ISPH3A_AFPAX1 (0x008)
++#define ISPH3A_AFPAX2 (0x00C)
++#define ISPH3A_AFPAXSTART (0x010)
++#define ISPH3A_AFIIRSH (0x014)
++#define ISPH3A_AFBUFST (0x018)
++#define ISPH3A_AFCOEF010 (0x01C)
++#define ISPH3A_AFCOEF032 (0x020)
++#define ISPH3A_AFCOEF054 (0x024)
++#define ISPH3A_AFCOEF076 (0x028)
++#define ISPH3A_AFCOEF098 (0x02C)
++#define ISPH3A_AFCOEF0010 (0x030)
++#define ISPH3A_AFCOEF110 (0x034)
++#define ISPH3A_AFCOEF132 (0x038)
++#define ISPH3A_AFCOEF154 (0x03C)
++#define ISPH3A_AFCOEF176 (0x040)
++#define ISPH3A_AFCOEF198 (0x044)
++#define ISPH3A_AFCOEF1010 (0x048)
++
++#define ISPPRV_PCR (0x004)
++#define ISPPRV_HORZ_INFO (0x008)
++#define ISPPRV_VERT_INFO (0x00C)
++#define ISPPRV_RSDR_ADDR (0x010)
++#define ISPPRV_RADR_OFFSET (0x014)
++#define ISPPRV_DSDR_ADDR (0x018)
++#define ISPPRV_DRKF_OFFSET (0x01C)
++#define ISPPRV_WSDR_ADDR (0x020)
++#define ISPPRV_WADD_OFFSET (0x024)
++#define ISPPRV_AVE (0x028)
++#define ISPPRV_HMED (0x02C)
++#define ISPPRV_NF (0x030)
++#define ISPPRV_WB_DGAIN (0x034)
++#define ISPPRV_WBGAIN (0x038)
++#define ISPPRV_WBSEL (0x03C)
++#define ISPPRV_CFA (0x040)
++#define ISPPRV_BLKADJOFF (0x044)
++#define ISPPRV_RGB_MAT1 (0x048)
++#define ISPPRV_RGB_MAT2 (0x04C)
++#define ISPPRV_RGB_MAT3 (0x050)
++#define ISPPRV_RGB_MAT4 (0x054)
++#define ISPPRV_RGB_MAT5 (0x058)
++#define ISPPRV_RGB_OFF1 (0x05C)
++#define ISPPRV_RGB_OFF2 (0x060)
++#define ISPPRV_CSC0 (0x064)
++#define ISPPRV_CSC1 (0x068)
++#define ISPPRV_CSC2 (0x06C)
++#define ISPPRV_CSC_OFFSET (0x070)
++#define ISPPRV_CNT_BRT (0x074)
++#define ISPPRV_CSUP (0x078)
++#define ISPPRV_SETUP_YC (0x07C)
++#define ISPPRV_SET_TBL_ADDR (0x080)
++#define ISPPRV_SET_TBL_DATA (0x084)
++#define ISPPRV_CDC_THR0 (0x090)
++#define ISPPRV_CDC_THR1 (ISPPRV_CDC_THR0 + (0x4))
++#define ISPPRV_CDC_THR2 (ISPPRV_CDC_THR0 + (0x4) * 2)
++#define ISPPRV_CDC_THR3 (ISPPRV_CDC_THR0 + (0x4) * 3)
++
++#define ISPPRV_REDGAMMA_TABLE_ADDR 0x0000
++#define ISPPRV_GREENGAMMA_TABLE_ADDR 0x0400
++#define ISPPRV_BLUEGAMMA_TABLE_ADDR 0x0800
++#define ISPPRV_NF_TABLE_ADDR 0x0C00
++#define ISPPRV_YENH_TABLE_ADDR 0x1000
++#define ISPPRV_CFA_TABLE_ADDR 0x1400
++
++#define ISPPRV_MAXOUTPUT_WIDTH 1280
++#define ISPPRV_MAXOUTPUT_WIDTH_ES2 3300
++#define ISPRSZ_MIN_OUTPUT 64
++#define ISPRSZ_MAX_OUTPUT 3312
++
++/* Resizer module register offset */
++#define ISPRSZ_PID (0x000)
++#define ISPRSZ_PCR (0x004)
++#define ISPRSZ_CNT (0x008)
++#define ISPRSZ_OUT_SIZE (0x00C)
++#define ISPRSZ_IN_START (0x010)
++#define ISPRSZ_IN_SIZE (0x014)
++#define ISPRSZ_SDR_INADD (0x018)
++#define ISPRSZ_SDR_INOFF (0x01C)
++#define ISPRSZ_SDR_OUTADD (0x020)
++#define ISPRSZ_SDR_OUTOFF (0x024)
++#define ISPRSZ_HFILT10 (0x028)
++#define ISPRSZ_HFILT32 (0x02C)
++#define ISPRSZ_HFILT54 (0x030)
++#define ISPRSZ_HFILT76 (0x034)
++#define ISPRSZ_HFILT98 (0x038)
++#define ISPRSZ_HFILT1110 (0x03C)
++#define ISPRSZ_HFILT1312 (0x040)
++#define ISPRSZ_HFILT1514 (0x044)
++#define ISPRSZ_HFILT1716 (0x048)
++#define ISPRSZ_HFILT1918 (0x04C)
++#define ISPRSZ_HFILT2120 (0x050)
++#define ISPRSZ_HFILT2322 (0x054)
++#define ISPRSZ_HFILT2524 (0x058)
++#define ISPRSZ_HFILT2726 (0x05C)
++#define ISPRSZ_HFILT2928 (0x060)
++#define ISPRSZ_HFILT3130 (0x064)
++#define ISPRSZ_VFILT10 (0x068)
++#define ISPRSZ_VFILT32 (0x06C)
++#define ISPRSZ_VFILT54 (0x070)
++#define ISPRSZ_VFILT76 (0x074)
++#define ISPRSZ_VFILT98 (0x078)
++#define ISPRSZ_VFILT1110 (0x07C)
++#define ISPRSZ_VFILT1312 (0x080)
++#define ISPRSZ_VFILT1514 (0x084)
++#define ISPRSZ_VFILT1716 (0x088)
++#define ISPRSZ_VFILT1918 (0x08C)
++#define ISPRSZ_VFILT2120 (0x090)
++#define ISPRSZ_VFILT2322 (0x094)
++#define ISPRSZ_VFILT2524 (0x098)
++#define ISPRSZ_VFILT2726 (0x09C)
++#define ISPRSZ_VFILT2928 (0x0A0)
++#define ISPRSZ_VFILT3130 (0x0A4)
++#define ISPRSZ_YENH (0x0A8)
++
++/* MMU module registers */
++#define ISPMMU_REVISION (0x000)
++#define ISPMMU_SYSCONFIG (0x010)
++#define ISPMMU_SYSSTATUS (0x014)
++#define ISPMMU_IRQSTATUS (0x018)
++#define ISPMMU_IRQENABLE (0x01C)
++#define ISPMMU_WALKING_ST (0x040)
++#define ISPMMU_CNTL (0x044)
++#define ISPMMU_FAULT_AD (0x048)
++#define ISPMMU_TTB (0x04C)
++#define ISPMMU_LOCK (0x050)
++#define ISPMMU_LD_TLB (0x054)
++#define ISPMMU_CAM (0x058)
++#define ISPMMU_RAM (0x05C)
++#define ISPMMU_GFLUSH (0x060)
++#define ISPMMU_FLUSH_ENTRY (0x064)
++#define ISPMMU_READ_CAM (0x068)
++#define ISPMMU_READ_RAM (0x06c)
++#define ISPMMU_EMU_FAULT_AD (0x070)
++
++#define ISP_INT_CLR 0xFF113F11
++#define ISPPRV_PCR_EN 1
++#define ISPPRV_PCR_BUSY (1 << 1)
++#define ISPPRV_PCR_SOURCE (1 << 2)
++#define ISPPRV_PCR_ONESHOT (1 << 3)
++#define ISPPRV_PCR_WIDTH (1 << 4)
++#define ISPPRV_PCR_INVALAW (1 << 5)
++#define ISPPRV_PCR_DRKFEN (1 << 6)
++#define ISPPRV_PCR_DRKFCAP (1 << 7)
++#define ISPPRV_PCR_HMEDEN (1 << 8)
++#define ISPPRV_PCR_NFEN (1 << 9)
++#define ISPPRV_PCR_CFAEN (1 << 10)
++#define ISPPRV_PCR_CFAFMT_SHIFT 11
++#define ISPPRV_PCR_CFAFMT_MASK 0x7800
++#define ISPPRV_PCR_CFAFMT_BAYER (0 << 11)
++#define ISPPRV_PCR_CFAFMT_SONYVGA (1 << 11)
++#define ISPPRV_PCR_CFAFMT_RGBFOVEON (2 << 11)
++#define ISPPRV_PCR_CFAFMT_DNSPL (3 << 11)
++#define ISPPRV_PCR_CFAFMT_HONEYCOMB (4 << 11)
++#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON (5 << 11)
++#define ISPPRV_PCR_YNENHEN (1 << 15)
++#define ISPPRV_PCR_SUPEN (1 << 16)
++#define ISPPRV_PCR_YCPOS_SHIFT 17
++#define ISPPRV_PCR_YCPOS_YCrYCb (0 << 17)
++#define ISPPRV_PCR_YCPOS_YCbYCr (1 << 17)
++#define ISPPRV_PCR_YCPOS_CbYCrY (2 << 17)
++#define ISPPRV_PCR_YCPOS_CrYCbY (3 << 17)
++#define ISPPRV_PCR_RSZPORT (1 << 19)
++#define ISPPRV_PCR_SDRPORT (1 << 20)
++#define ISPPRV_PCR_SCOMP_EN (1 << 21)
++#define ISPPRV_PCR_SCOMP_SFT_SHIFT (22)
++#define ISPPRV_PCR_SCOMP_SFT_MASK (~(7 << 22))
++#define ISPPRV_PCR_GAMMA_BYPASS (1 << 26)
++#define ISPPRV_PCR_DCOREN (1 << 27)
++#define ISPPRV_PCR_DCCOUP (1 << 28)
++#define ISPPRV_PCR_DRK_FAIL (1 << 31)
++
++#define ISPPRV_HORZ_INFO_EPH_SHIFT 0
++#define ISPPRV_HORZ_INFO_EPH_MASK 0x3fff
++#define ISPPRV_HORZ_INFO_SPH_SHIFT 16
++#define ISPPRV_HORZ_INFO_SPH_MASK 0x3fff0
++
++#define ISPPRV_VERT_INFO_ELV_SHIFT 0
++#define ISPPRV_VERT_INFO_ELV_MASK 0x3fff
++#define ISPPRV_VERT_INFO_SLV_SHIFT 16
++#define ISPPRV_VERT_INFO_SLV_MASK 0x3fff0
++
++#define ISPPRV_AVE_EVENDIST_SHIFT 2
++#define ISPPRV_AVE_EVENDIST_1 0x0
++#define ISPPRV_AVE_EVENDIST_2 0x1
++#define ISPPRV_AVE_EVENDIST_3 0x2
++#define ISPPRV_AVE_EVENDIST_4 0x3
++#define ISPPRV_AVE_ODDDIST_SHIFT 4
++#define ISPPRV_AVE_ODDDIST_1 0x0
++#define ISPPRV_AVE_ODDDIST_2 0x1
++#define ISPPRV_AVE_ODDDIST_3 0x2
++#define ISPPRV_AVE_ODDDIST_4 0x3
++
++#define ISPPRV_HMED_THRESHOLD_SHIFT 0
++#define ISPPRV_HMED_EVENDIST (1 << 8)
++#define ISPPRV_HMED_ODDDIST (1 << 9)
++
++#define ISPPRV_WBGAIN_COEF0_SHIFT 0
++#define ISPPRV_WBGAIN_COEF1_SHIFT 8
++#define ISPPRV_WBGAIN_COEF2_SHIFT 16
++#define ISPPRV_WBGAIN_COEF3_SHIFT 24
++
++#define ISPPRV_WBSEL_COEF0 0x0
++#define ISPPRV_WBSEL_COEF1 0x1
++#define ISPPRV_WBSEL_COEF2 0x2
++#define ISPPRV_WBSEL_COEF3 0x3
++
++#define ISPPRV_WBSEL_N0_0_SHIFT 0
++#define ISPPRV_WBSEL_N0_1_SHIFT 2
++#define ISPPRV_WBSEL_N0_2_SHIFT 4
++#define ISPPRV_WBSEL_N0_3_SHIFT 6
++#define ISPPRV_WBSEL_N1_0_SHIFT 8
++#define ISPPRV_WBSEL_N1_1_SHIFT 10
++#define ISPPRV_WBSEL_N1_2_SHIFT 12
++#define ISPPRV_WBSEL_N1_3_SHIFT 14
++#define ISPPRV_WBSEL_N2_0_SHIFT 16
++#define ISPPRV_WBSEL_N2_1_SHIFT 18
++#define ISPPRV_WBSEL_N2_2_SHIFT 20
++#define ISPPRV_WBSEL_N2_3_SHIFT 22
++#define ISPPRV_WBSEL_N3_0_SHIFT 24
++#define ISPPRV_WBSEL_N3_1_SHIFT 26
++#define ISPPRV_WBSEL_N3_2_SHIFT 28
++#define ISPPRV_WBSEL_N3_3_SHIFT 30
++
++#define ISPPRV_CFA_GRADTH_HOR_SHIFT 0
++#define ISPPRV_CFA_GRADTH_VER_SHIFT 8
++
++#define ISPPRV_BLKADJOFF_B_SHIFT 0
++#define ISPPRV_BLKADJOFF_G_SHIFT 8
++#define ISPPRV_BLKADJOFF_R_SHIFT 16
++
++#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT 0
++#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT 16
++
++#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT 0
++#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT 16
++
++#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT 0
++#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT 16
++
++#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT 0
++#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT 16
++
++#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT 0
++
++#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT 0
++#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT 16
++
++#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT 0
++
++#define ISPPRV_CSC0_RY_SHIFT 0
++#define ISPPRV_CSC0_GY_SHIFT 10
++#define ISPPRV_CSC0_BY_SHIFT 20
++
++#define ISPPRV_CSC1_RCB_SHIFT 0
++#define ISPPRV_CSC1_GCB_SHIFT 10
++#define ISPPRV_CSC1_BCB_SHIFT 20
++
++#define ISPPRV_CSC2_RCR_SHIFT 0
++#define ISPPRV_CSC2_GCR_SHIFT 10
++#define ISPPRV_CSC2_BCR_SHIFT 20
++
++#define ISPPRV_CSC_OFFSET_CR_SHIFT 0
++#define ISPPRV_CSC_OFFSET_CB_SHIFT 8
++#define ISPPRV_CSC_OFFSET_Y_SHIFT 16
++
++#define ISPPRV_CNT_BRT_BRT_SHIFT 0
++#define ISPPRV_CNT_BRT_CNT_SHIFT 8
++
++#define ISPPRV_CONTRAST_MAX 0x10
++#define ISPPRV_CONTRAST_MIN 0xFF
++#define ISPPRV_BRIGHT_MIN 0x00
++#define ISPPRV_BRIGHT_MAX 0xFF
++
++#define ISPPRV_CSUP_CSUPG_SHIFT 0
++#define ISPPRV_CSUP_THRES_SHIFT 8
++#define ISPPRV_CSUP_HPYF_SHIFT 16
++
++#define ISPPRV_SETUP_YC_MINC_SHIFT 0
++#define ISPPRV_SETUP_YC_MAXC_SHIFT 8
++#define ISPPRV_SETUP_YC_MINY_SHIFT 16
++#define ISPPRV_SETUP_YC_MAXY_SHIFT 24
++#define ISPPRV_YC_MAX 0xFF
++#define ISPPRV_YC_MIN 0x0
++
++/* Define bit fields within selected registers */
++#define ISP_REVISION_SHIFT 0
++
++#define ISP_SYSCONFIG_AUTOIDLE 0
++#define ISP_SYSCONFIG_SOFTRESET (1 << 1)
++#define ISP_SYSCONFIG_MIDLEMODE_SHIFT 12
++#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY 0x0
++#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY 0x1
++#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x2
++
++#define ISP_SYSSTATUS_RESETDONE 0
++
++#define IRQ0ENABLE_CSIA_IRQ 1
++#define IRQ0ENABLE_CSIA_LC1_IRQ (1 << 1)
++#define IRQ0ENABLE_CSIA_LC2_IRQ (1 << 2)
++#define IRQ0ENABLE_CSIA_LC3_IRQ (1 << 3)
++#define IRQ0ENABLE_CSIB_IRQ (1 << 4)
++#define IRQ0ENABLE_CSIB_LC1_IRQ (1 << 5)
++#define IRQ0ENABLE_CSIB_LC2_IRQ (1 << 6)
++#define IRQ0ENABLE_CSIB_LC3_IRQ (1 << 7)
++#define IRQ0ENABLE_CCDC_VD0_IRQ (1 << 8)
++#define IRQ0ENABLE_CCDC_VD1_IRQ (1 << 9)
++#define IRQ0ENABLE_CCDC_VD2_IRQ (1 << 10)
++#define IRQ0ENABLE_CCDC_ERR_IRQ (1 << 11)
++#define IRQ0ENABLE_H3A_AF_DONE_IRQ (1 << 12)
++#define IRQ0ENABLE_H3A_AWB_DONE_IRQ (1 << 13)
++#define IRQ0ENABLE_HIST_DONE_IRQ (1 << 16)
++#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ (1 << 17)
++#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
++#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
++#define IRQ0ENABLE_PRV_DONE_IRQ (1 << 20)
++#define IRQ0ENABLE_RSZ_DONE_IRQ (1 << 24)
++#define IRQ0ENABLE_OVF_IRQ (1 << 25)
++#define IRQ0ENABLE_PING_IRQ (1 << 26)
++#define IRQ0ENABLE_PONG_IRQ (1 << 27)
++#define IRQ0ENABLE_MMU_ERR_IRQ (1 << 28)
++#define IRQ0ENABLE_OCP_ERR_IRQ (1 << 29)
++#define IRQ0ENABLE_SEC_ERR_IRQ (1 << 30)
++#define IRQ0ENABLE_HS_VS_IRQ (1 << 31)
++
++#define IRQ0STATUS_CSIA_IRQ 1
++#define IRQ0STATUS_CSIA_LC1_IRQ (1 << 1)
++#define IRQ0STATUS_CSIA_LC2_IRQ (1 << 2)
++#define IRQ0STATUS_CSIA_LC3_IRQ (1 << 3)
++#define IRQ0STATUS_CSIB_IRQ (1 << 4)
++#define IRQ0STATUS_CSIB_LC1_IRQ (1 << 5)
++#define IRQ0STATUS_CSIB_LC2_IRQ (1 << 6)
++#define IRQ0STATUS_CSIB_LC3_IRQ (1 << 7)
++#define IRQ0STATUS_CCDC_VD0_IRQ (1 << 8)
++#define IRQ0STATUS_CCDC_VD1_IRQ (1 << 9)
++#define IRQ0STATUS_CCDC_VD2_IRQ (1 << 10)
++#define IRQ0STATUS_CCDC_ERR_IRQ (1 << 11)
++#define IRQ0STATUS_H3A_AF_DONE_IRQ (1 << 12)
++#define IRQ0STATUS_H3A_AWB_DONE_IRQ (1 << 13)
++#define IRQ0STATUS_HIST_DONE_IRQ (1 << 16)
++#define IRQ0STATUS_PRV_DONE_IRQ (1 << 20)
++#define IRQ0STATUS_RSZ_DONE_IRQ (1 << 24)
++#define IRQ0STATUS_OVF_IRQ (1 << 25)
++#define IRQ0STATUS_PING_IRQ (1 << 26)
++#define IRQ0STATUS_PONG_IRQ (1 << 27)
++#define IRQ0STATUS_MMU_ERR_IRQ (1 << 28)
++#define IRQ0STATUS_OCP_ERR_IRQ (1 << 29)
++#define IRQ0STATUS_SEC_ERR_IRQ (1 << 30)
++#define IRQ0STATUS_HS_VS_IRQ (1 << 31)
++
++#define TCTRL_GRESET_LEN 0
++
++#define TCTRL_PSTRB_REPLAY_DELAY 0
++#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT 25
++
++#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL 0x0
++#define ISPCTRL_PAR_SER_CLK_SEL_CSIA 0x1
++#define ISPCTRL_PAR_SER_CLK_SEL_CSIB 0x2
++#define ISPCTRL_PAR_SER_CLK_SEL_MASK 0xFFFFFFFC
++
++#define ISPCTRL_PAR_BRIDGE_SHIFT 2
++#define ISPCTRL_PAR_BRIDGE_DISABLE (0x0 << 2)
++#define ISPCTRL_PAR_BRIDGE_LENDIAN (0x2 << 2)
++#define ISPCTRL_PAR_BRIDGE_BENDIAN (0x3 << 2)
++
++#define ISPCTRL_PAR_CLK_POL_SHIFT 4
++#define ISPCTRL_PAR_CLK_POL_INV (1 << 4)
++#define ISPCTRL_PING_PONG_EN (1 << 5)
++#define ISPCTRL_SHIFT_SHIFT 6
++#define ISPCTRL_SHIFT_0 (0x0 << 6)
++#define ISPCTRL_SHIFT_2 (0x1 << 6)
++#define ISPCTRL_SHIFT_4 (0x2 << 6)
++#define ISPCTRL_SHIFT_MASK (~(0x3 << 6))
++
++#define ISPCTRL_CCDC_CLK_EN (1 << 8)
++#define ISPCTRL_SCMP_CLK_EN (1 << 9)
++#define ISPCTRL_H3A_CLK_EN (1 << 10)
++#define ISPCTRL_HIST_CLK_EN (1 << 11)
++#define ISPCTRL_PREV_CLK_EN (1 << 12)
++#define ISPCTRL_RSZ_CLK_EN (1 << 13)
++#define ISPCTRL_SYNC_DETECT_SHIFT 14
++#define ISPCTRL_SYNC_DETECT_HSFALL (0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
++#define ISPCTRL_SYNC_DETECT_HSRISE (0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
++#define ISPCTRL_SYNC_DETECT_VSFALL (0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
++#define ISPCTRL_SYNC_DETECT_VSRISE (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
++#define ISPCTRL_SYNC_DETECT_MASK (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
++
++#define ISPCTRL_CCDC_RAM_EN (1 << 16)
++#define ISPCTRL_PREV_RAM_EN (1 << 17)
++#define ISPCTRL_SBL_RD_RAM_EN (1 << 18)
++#define ISPCTRL_SBL_WR1_RAM_EN (1 << 19)
++#define ISPCTRL_SBL_WR0_RAM_EN (1 << 20)
++#define ISPCTRL_SBL_AUTOIDLE (1 << 21)
++#define ISPCTRL_SBL_SHARED_RPORTB (1 << 28)
++#define ISPCTRL_JPEG_FLUSH (1 << 30)
++#define ISPCTRL_CCDC_FLUSH (1 << 31)
++
++#define ISPSECURE_SECUREMODE 0
++
++#define ISPTCTRL_CTRL_DIV_LOW 0x0
++#define ISPTCTRL_CTRL_DIV_HIGH 0x1
++#define ISPTCTRL_CTRL_DIV_BYPASS 0x1F
++
++#define ISPTCTRL_CTRL_DIVA_SHIFT 0
++#define ISPTCTRL_CTRL_DIVA_MASK (0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
++
++#define ISPTCTRL_CTRL_DIVB_SHIFT 5
++#define ISPTCTRL_CTRL_DIVB_MASK (0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
++
++#define ISPTCTRL_CTRL_DIVC_SHIFT 10
++#define ISPTCTRL_CTRL_DIVC_NOCLOCK (0x0 << 10)
++
++#define ISPTCTRL_CTRL_SHUTEN (1 << 21)
++#define ISPTCTRL_CTRL_PSTRBEN (1 << 22)
++#define ISPTCTRL_CTRL_STRBEN (1 << 23)
++#define ISPTCTRL_CTRL_SHUTPOL (1 << 24)
++#define ISPTCTRL_CTRL_STRBPSTRBPOL (1 << 26)
++
++#define ISPTCTRL_CTRL_INSEL_SHIFT 27
++#define ISPTCTRL_CTRL_INSEL_PARALLEL (0x0 << 27)
++#define ISPTCTRL_CTRL_INSEL_CSIA (0x1 << 27)
++#define ISPTCTRL_CTRL_INSEL_CSIB (0x2 << 27)
++
++#define ISPTCTRL_CTRL_GRESETEn (1 << 29)
++#define ISPTCTRL_CTRL_GRESETPOL (1 << 30)
++#define ISPTCTRL_CTRL_GRESETDIR (1 << 31)
++
++#define ISPTCTRL_FRAME_SHUT_SHIFT 0
++#define ISPTCTRL_FRAME_PSTRB_SHIFT 6
++#define ISPTCTRL_FRAME_STRB_SHIFT 12
++
++#define ISPCCDC_PID_PREV_SHIFT 0
++#define ISPCCDC_PID_CID_SHIFT 8
++#define ISPCCDC_PID_TID_SHIFT 16
++
++#define ISPCCDC_PCR_EN 1
++#define ISPCCDC_PCR_BUSY (1 << 1)
++
++#define ISPCCDC_SYN_MODE_VDHDOUT 0x1
++#define ISPCCDC_SYN_MODE_FLDOUT (1 << 1)
++#define ISPCCDC_SYN_MODE_VDPOL (1 << 2)
++#define ISPCCDC_SYN_MODE_HDPOL (1 << 3)
++#define ISPCCDC_SYN_MODE_FLDPOL (1 << 4)
++#define ISPCCDC_SYN_MODE_EXWEN (1 << 5)
++#define ISPCCDC_SYN_MODE_DATAPOL (1 << 6)
++#define ISPCCDC_SYN_MODE_FLDMODE (1 << 7)
++#define ISPCCDC_SYN_MODE_DATSIZ_MASK 0xFFFFF8FF
++#define ISPCCDC_SYN_MODE_DATSIZ_8_16 (0x0 << 8)
++#define ISPCCDC_SYN_MODE_DATSIZ_12 (0x4 << 8)
++#define ISPCCDC_SYN_MODE_DATSIZ_11 (0x5 << 8)
++#define ISPCCDC_SYN_MODE_DATSIZ_10 (0x6 << 8)
++#define ISPCCDC_SYN_MODE_DATSIZ_8 (0x7 << 8)
++#define ISPCCDC_SYN_MODE_PACK8 (1 << 11)
++#define ISPCCDC_SYN_MODE_INPMOD_MASK 0xFFFFCFFF
++#define ISPCCDC_SYN_MODE_INPMOD_RAW (0 << 12)
++#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16 (1 << 12)
++#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8 (2 << 12)
++#define ISPCCDC_SYN_MODE_LPF (1 << 14)
++#define ISPCCDC_SYN_MODE_FLDSTAT (1 << 15)
++#define ISPCCDC_SYN_MODE_VDHDEN (1 << 16)
++#define ISPCCDC_SYN_MODE_WEN (1 << 17)
++#define ISPCCDC_SYN_MODE_VP2SDR (1 << 18)
++#define ISPCCDC_SYN_MODE_SDR2RSZ (1 << 19)
++
++#define ISPCCDC_HD_VD_WID_VDW_SHIFT 0
++#define ISPCCDC_HD_VD_WID_HDW_SHIFT 16
++
++#define ISPCCDC_PIX_LINES_HLPRF_SHIFT 0
++#define ISPCCDC_PIX_LINES_PPLN_SHIFT 16
++
++#define ISPCCDC_HORZ_INFO_NPH_SHIFT 0
++#define ISPCCDC_HORZ_INFO_NPH_MASK 0xFFFF8000
++#define ISPCCDC_HORZ_INFO_SPH_MASK 0x1000FFFF
++#define ISPCCDC_HORZ_INFO_SPH_SHIFT 16
++
++#define ISPCCDC_VERT_START_SLV0_SHIFT 16
++#define ISPCCDC_VERT_START_SLV0_MASK 0x1000FFFF
++#define ISPCCDC_VERT_START_SLV1_SHIFT 0
++
++#define ISPCCDC_VERT_LINES_NLV_MASK 0xFFFF8000
++#define ISPCCDC_VERT_LINES_NLV_SHIFT 0
++
++#define ISPCCDC_CULLING_CULV_SHIFT 0
++#define ISPCCDC_CULLING_CULHODD_SHIFT 16
++#define ISPCCDC_CULLING_CULHEVN_SHIFT 24
++
++#define ISPCCDC_HSIZE_OFF_SHIFT 0
++
++#define ISPCCDC_SDOFST_FINV (1 << 14)
++#define ISPCCDC_SDOFST_FOFST_1L 0
++#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
++#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
++#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
++#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
++#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
++#define EVENEVEN 1
++#define ODDEVEN 2
++#define EVENODD 3
++#define ODDODD 4
++
++#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
++#define ISPCCDC_CLAMP_OBST_SHIFT 10
++#define ISPCCDC_CLAMP_OBSLN_SHIFT 25
++#define ISPCCDC_CLAMP_OBSLEN_SHIFT 28
++#define ISPCCDC_CLAMP_CLAMPEN (1 << 31)
++
++#define ISPCCDC_COLPTN_R_Ye 0x0
++#define ISPCCDC_COLPTN_Gr_Cy 0x1
++#define ISPCCDC_COLPTN_Gb_G 0x2
++#define ISPCCDC_COLPTN_B_Mg 0x3
++#define ISPCCDC_COLPTN_CP0PLC0_SHIFT 0
++#define ISPCCDC_COLPTN_CP0PLC1_SHIFT 2
++#define ISPCCDC_COLPTN_CP0PLC2_SHIFT 4
++#define ISPCCDC_COLPTN_CP0PLC3_SHIFT 6
++#define ISPCCDC_COLPTN_CP1PLC0_SHIFT 8
++#define ISPCCDC_COLPTN_CP1PLC1_SHIFT 10
++#define ISPCCDC_COLPTN_CP1PLC2_SHIFT 12
++#define ISPCCDC_COLPTN_CP1PLC3_SHIFT 14
++#define ISPCCDC_COLPTN_CP2PLC0_SHIFT 16
++#define ISPCCDC_COLPTN_CP2PLC1_SHIFT 18
++#define ISPCCDC_COLPTN_CP2PLC2_SHIFT 20
++#define ISPCCDC_COLPTN_CP2PLC3_SHIFT 22
++#define ISPCCDC_COLPTN_CP3PLC0_SHIFT 24
++#define ISPCCDC_COLPTN_CP3PLC1_SHIFT 26
++#define ISPCCDC_COLPTN_CP3PLC2_SHIFT 28
++#define ISPCCDC_COLPTN_CP3PLC3_SHIFT 30
++
++#define ISPCCDC_BLKCMP_B_MG_SHIFT 0
++#define ISPCCDC_BLKCMP_GB_G_SHIFT 8
++#define ISPCCDC_BLKCMP_GR_CY_SHIFT 16
++#define ISPCCDC_BLKCMP_R_YE_SHIFT 24
++
++#define ISPCCDC_FPC_FPNUM_SHIFT 0
++#define ISPCCDC_FPC_FPCEN (1 << 15)
++#define ISPCCDC_FPC_FPERR (1 << 16)
++
++#define ISPCCDC_VDINT_1_SHIFT 0
++#define ISPCCDC_VDINT_0_SHIFT 16
++#define ISPCCDC_VDINT_0_MASK 0x7FFF
++#define ISPCCDC_VDINT_1_MASK 0x7FFF
++
++#define ISPCCDC_ALAW_GWDI_SHIFT 0
++#define ISPCCDC_ALAW_CCDTBL (1 << 3)
++
++#define ISPCCDC_REC656IF_R656ON 1
++#define ISPCCDC_REC656IF_ECCFVH (1 << 1)
++
++#define ISPCCDC_CFG_BW656 (1 << 5)
++#define ISPCCDC_CFG_FIDMD_SHIFT 6
++#define ISPCCDC_CFG_WENLOG (1 << 8)
++#define ISPCCDC_CFG_WENLOG_AND (0 << 8)
++#define ISPCCDC_CFG_WENLOG_OR (1 << 8)
++#define ISPCCDC_CFG_Y8POS (1 << 11)
++#define ISPCCDC_CFG_BSWD (1 << 12)
++#define ISPCCDC_CFG_MSBINVI (1 << 13)
++#define ISPCCDC_CFG_VDLC (1 << 15)
++
++#define ISPCCDC_FMTCFG_FMTEN 0x1
++#define ISPCCDC_FMTCFG_LNALT (1 << 1)
++#define ISPCCDC_FMTCFG_LNUM_SHIFT 2
++#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT 4
++#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT 8
++#define ISPCCDC_FMTCFG_VPIN_MASK 0xFFFF8000
++#define ISPCCDC_FMTCFG_VPIN_12_3 (0x3 << 12)
++#define ISPCCDC_FMTCFG_VPIN_11_2 (0x4 << 12)
++#define ISPCCDC_FMTCFG_VPIN_10_1 (0x5 << 12)
++#define ISPCCDC_FMTCFG_VPIN_9_0 (0x6 << 12)
++#define ISPCCDC_FMTCFG_VPEN (1 << 15)
++
++#define ISPCCDC_FMTCF_VPIF_FRQ_MASK 0xFFF8FFFF
++#define ISPCCDC_FMTCF_VPIF_FRQ_BY2 (0x0 << 16)
++#define ISPCCDC_FMTCF_VPIF_FRQ_BY3 (0x1 << 16)
++#define ISPCCDC_FMTCF_VPIF_FRQ_BY4 (0x2 << 16)
++#define ISPCCDC_FMTCF_VPIF_FRQ_BY5 (0x3 << 16)
++#define ISPCCDC_FMTCF_VPIF_FRQ_BY6 (0x4 << 16)
++
++#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT 0
++#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT 16
++
++#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT 0
++#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT 16
++
++#define ISPCCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF0000
++#define ISPCCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
++
++#define ISPCCDC_FMT_VERT_FMTSLV_MASK 0x1FFF0000
++#define ISPCCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
++
++#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT 0
++#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT 4
++#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT 17
++
++#define ISPRSZ_PID_PREV_SHIFT 0
++#define ISPRSZ_PID_CID_SHIFT 8
++#define ISPRSZ_PID_TID_SHIFT 16
++
++#define ISPRSZ_PCR_ENABLE 0x5
++#define ISPRSZ_PCR_BUSY (1 << 1)
++
++#define ISPRSZ_CNT_HRSZ_SHIFT 0
++#define ISPRSZ_CNT_HRSZ_MASK 0x3FF
++#define ISPRSZ_CNT_VRSZ_SHIFT 10
++#define ISPRSZ_CNT_VRSZ_MASK 0xFFC00
++#define ISPRSZ_CNT_HSTPH_SHIFT 20
++#define ISPRSZ_CNT_HSTPH_MASK 0x700000
++#define ISPRSZ_CNT_VSTPH_SHIFT 23
++#define ISPRSZ_CNT_VSTPH_MASK 0x3800000
++#define ISPRSZ_CNT_CBILIN_MASK 0x20000000
++#define ISPRSZ_CNT_INPTYP_MASK 0x08000000
++#define ISPRSZ_CNT_PIXFMT_MASK 0x04000000
++#define ISPRSZ_CNT_YCPOS (1 << 26)
++#define ISPRSZ_CNT_INPTYP (1 << 27)
++#define ISPRSZ_CNT_INPSRC (1 << 28)
++#define ISPRSZ_CNT_CBILIN (1 << 29)
++
++#define ISPRSZ_OUT_SIZE_HORZ_SHIFT 0
++#define ISPRSZ_OUT_SIZE_HORZ_MASK 0x7FF
++#define ISPRSZ_OUT_SIZE_VERT_SHIFT 16
++#define ISPRSZ_OUT_SIZE_VERT_MASK 0x7FF0000
++
++
++#define ISPRSZ_IN_START_HORZ_ST_SHIFT 0
++#define ISPRSZ_IN_START_HORZ_ST_MASK 0x1FFF
++#define ISPRSZ_IN_START_VERT_ST_SHIFT 16
++#define ISPRSZ_IN_START_VERT_ST_MASK 0x1FFF0000
++
++
++#define ISPRSZ_IN_SIZE_HORZ_SHIFT 0
++#define ISPRSZ_IN_SIZE_HORZ_MASK 0x1FFF
++#define ISPRSZ_IN_SIZE_VERT_SHIFT 16
++#define ISPRSZ_IN_SIZE_VERT_MASK 0x1FFF0000
++
++#define ISPRSZ_SDR_INADD_ADDR_SHIFT 0
++#define ISPRSZ_SDR_INADD_ADDR_MASK 0xFFFFFFFF
++
++#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT 0
++#define ISPRSZ_SDR_INOFF_OFFSET_MASK 0xFFFF
++
++#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT 0
++#define ISPRSZ_SDR_OUTADD_ADDR_MASK 0xFFFFFFFF
++
++
++#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT 0
++#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK 0xFFFF
++
++#define ISPRSZ_HFILT10_COEF0_SHIFT 0
++#define ISPRSZ_HFILT10_COEF0_MASK 0x3FF
++#define ISPRSZ_HFILT10_COEF1_SHIFT 16
++#define ISPRSZ_HFILT10_COEF1_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT32_COEF2_SHIFT 0
++#define ISPRSZ_HFILT32_COEF2_MASK 0x3FF
++#define ISPRSZ_HFILT32_COEF3_SHIFT 16
++#define ISPRSZ_HFILT32_COEF3_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT54_COEF4_SHIFT 0
++#define ISPRSZ_HFILT54_COEF4_MASK 0x3FF
++#define ISPRSZ_HFILT54_COEF5_SHIFT 16
++#define ISPRSZ_HFILT54_COEF5_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT76_COEFF6_SHIFT 0
++#define ISPRSZ_HFILT76_COEFF6_MASK 0x3FF
++#define ISPRSZ_HFILT76_COEFF7_SHIFT 16
++#define ISPRSZ_HFILT76_COEFF7_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT98_COEFF8_SHIFT 0
++#define ISPRSZ_HFILT98_COEFF8_MASK 0x3FF
++#define ISPRSZ_HFILT98_COEFF9_SHIFT 16
++#define ISPRSZ_HFILT98_COEFF9_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT1110_COEF10_SHIFT 0
++#define ISPRSZ_HFILT1110_COEF10_MASK 0x3FF
++#define ISPRSZ_HFILT1110_COEF11_SHIFT 16
++#define ISPRSZ_HFILT1110_COEF11_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT1312_COEFF12_SHIFT 0
++#define ISPRSZ_HFILT1312_COEFF12_MASK 0x3FF
++#define ISPRSZ_HFILT1312_COEFF13_SHIFT 16
++#define ISPRSZ_HFILT1312_COEFF13_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT1514_COEFF14_SHIFT 0
++#define ISPRSZ_HFILT1514_COEFF14_MASK 0x3FF
++#define ISPRSZ_HFILT1514_COEFF15_SHIFT 16
++#define ISPRSZ_HFILT1514_COEFF15_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT1716_COEF16_SHIFT 0
++#define ISPRSZ_HFILT1716_COEF16_MASK 0x3FF
++#define ISPRSZ_HFILT1716_COEF17_SHIFT 16
++#define ISPRSZ_HFILT1716_COEF17_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT1918_COEF18_SHIFT 0
++#define ISPRSZ_HFILT1918_COEF18_MASK 0x3FF
++#define ISPRSZ_HFILT1918_COEF19_SHIFT 16
++#define ISPRSZ_HFILT1918_COEF19_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT2120_COEF20_SHIFT 0
++#define ISPRSZ_HFILT2120_COEF20_MASK 0x3FF
++#define ISPRSZ_HFILT2120_COEF21_SHIFT 16
++#define ISPRSZ_HFILT2120_COEF21_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT2322_COEF22_SHIFT 0
++#define ISPRSZ_HFILT2322_COEF22_MASK 0x3FF
++#define ISPRSZ_HFILT2322_COEF23_SHIFT 16
++#define ISPRSZ_HFILT2322_COEF23_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT2524_COEF24_SHIFT 0
++#define ISPRSZ_HFILT2524_COEF24_MASK 0x3FF
++#define ISPRSZ_HFILT2524_COEF25_SHIFT 16
++#define ISPRSZ_HFILT2524_COEF25_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT2726_COEF26_SHIFT 0
++#define ISPRSZ_HFILT2726_COEF26_MASK 0x3FF
++#define ISPRSZ_HFILT2726_COEF27_SHIFT 16
++#define ISPRSZ_HFILT2726_COEF27_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT2928_COEF28_SHIFT 0
++#define ISPRSZ_HFILT2928_COEF28_MASK 0x3FF
++#define ISPRSZ_HFILT2928_COEF29_SHIFT 16
++#define ISPRSZ_HFILT2928_COEF29_MASK 0x3FF0000
++
++#define ISPRSZ_HFILT3130_COEF30_SHIFT 0
++#define ISPRSZ_HFILT3130_COEF30_MASK 0x3FF
++#define ISPRSZ_HFILT3130_COEF31_SHIFT 16
++#define ISPRSZ_HFILT3130_COEF31_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT10_COEF0_SHIFT 0
++#define ISPRSZ_VFILT10_COEF0_MASK 0x3FF
++#define ISPRSZ_VFILT10_COEF1_SHIFT 16
++#define ISPRSZ_VFILT10_COEF1_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT32_COEF2_SHIFT 0
++#define ISPRSZ_VFILT32_COEF2_MASK 0x3FF
++#define ISPRSZ_VFILT32_COEF3_SHIFT 16
++#define ISPRSZ_VFILT32_COEF3_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT54_COEF4_SHIFT 0
++#define ISPRSZ_VFILT54_COEF4_MASK 0x3FF
++#define ISPRSZ_VFILT54_COEF5_SHIFT 16
++#define ISPRSZ_VFILT54_COEF5_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT76_COEFF6_SHIFT 0
++#define ISPRSZ_VFILT76_COEFF6_MASK 0x3FF
++#define ISPRSZ_VFILT76_COEFF7_SHIFT 16
++#define ISPRSZ_VFILT76_COEFF7_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT98_COEFF8_SHIFT 0
++#define ISPRSZ_VFILT98_COEFF8_MASK 0x3FF
++#define ISPRSZ_VFILT98_COEFF9_SHIFT 16
++#define ISPRSZ_VFILT98_COEFF9_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT1110_COEF10_SHIFT 0
++#define ISPRSZ_VFILT1110_COEF10_MASK 0x3FF
++#define ISPRSZ_VFILT1110_COEF11_SHIFT 16
++#define ISPRSZ_VFILT1110_COEF11_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT1312_COEFF12_SHIFT 0
++#define ISPRSZ_VFILT1312_COEFF12_MASK 0x3FF
++#define ISPRSZ_VFILT1312_COEFF13_SHIFT 16
++#define ISPRSZ_VFILT1312_COEFF13_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT1514_COEFF14_SHIFT 0
++#define ISPRSZ_VFILT1514_COEFF14_MASK 0x3FF
++#define ISPRSZ_VFILT1514_COEFF15_SHIFT 16
++#define ISPRSZ_VFILT1514_COEFF15_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT1716_COEF16_SHIFT 0
++#define ISPRSZ_VFILT1716_COEF16_MASK 0x3FF
++#define ISPRSZ_VFILT1716_COEF17_SHIFT 16
++#define ISPRSZ_VFILT1716_COEF17_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT1918_COEF18_SHIFT 0
++#define ISPRSZ_VFILT1918_COEF18_MASK 0x3FF
++#define ISPRSZ_VFILT1918_COEF19_SHIFT 16
++#define ISPRSZ_VFILT1918_COEF19_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT2120_COEF20_SHIFT 0
++#define ISPRSZ_VFILT2120_COEF20_MASK 0x3FF
++#define ISPRSZ_VFILT2120_COEF21_SHIFT 16
++#define ISPRSZ_VFILT2120_COEF21_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT2322_COEF22_SHIFT 0
++#define ISPRSZ_VFILT2322_COEF22_MASK 0x3FF
++#define ISPRSZ_VFILT2322_COEF23_SHIFT 16
++#define ISPRSZ_VFILT2322_COEF23_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT2524_COEF24_SHIFT 0
++#define ISPRSZ_VFILT2524_COEF24_MASK 0x3FF
++#define ISPRSZ_VFILT2524_COEF25_SHIFT 16
++#define ISPRSZ_VFILT2524_COEF25_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT2726_COEF26_SHIFT 0
++#define ISPRSZ_VFILT2726_COEF26_MASK 0x3FF
++#define ISPRSZ_VFILT2726_COEF27_SHIFT 16
++#define ISPRSZ_VFILT2726_COEF27_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT2928_COEF28_SHIFT 0
++#define ISPRSZ_VFILT2928_COEF28_MASK 0x3FF
++#define ISPRSZ_VFILT2928_COEF29_SHIFT 16
++#define ISPRSZ_VFILT2928_COEF29_MASK 0x3FF0000
++
++#define ISPRSZ_VFILT3130_COEF30_SHIFT 0
++#define ISPRSZ_VFILT3130_COEF30_MASK 0x3FF
++#define ISPRSZ_VFILT3130_COEF31_SHIFT 16
++#define ISPRSZ_VFILT3130_COEF31_MASK 0x3FF0000
++
++#define ISPRSZ_YENH_CORE_SHIFT 0
++#define ISPRSZ_YENH_CORE_MASK 0xFF
++#define ISPRSZ_YENH_SLOP_SHIFT 8
++#define ISPRSZ_YENH_SLOP_MASK 0xF00
++#define ISPRSZ_YENH_GAIN_SHIFT 12
++#define ISPRSZ_YENH_GAIN_MASK 0xF000
++#define ISPRSZ_YENH_ALGO_SHIFT 16
++#define ISPRSZ_YENH_ALGO_MASK 0x30000
++
++#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT 1
++#define ISPH3A_PCR_AF_MED_TH_SHIFT 3
++#define ISPH3A_PCR_AF_RGBPOS_SHIFT 11
++#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT 22
++#define ISPH3A_PCR_AEW_AVE2LMT_MASK 0xFFC00000
++#define ISPH3A_PCR_BUSYAF (1 << 15)
++#define ISPH3A_PCR_BUSYAEAWB (1 << 18)
++
++#define ISPH3A_AEWWIN1_WINHC_SHIFT 0
++#define ISPH3A_AEWWIN1_WINHC_MASK 0x3F
++#define ISPH3A_AEWWIN1_WINVC_SHIFT 6
++#define ISPH3A_AEWWIN1_WINVC_MASK 0x1FC0
++#define ISPH3A_AEWWIN1_WINW_SHIFT 13
++#define ISPH3A_AEWWIN1_WINW_MASK 0xFE000
++#define ISPH3A_AEWWIN1_WINH_SHIFT 24
++#define ISPH3A_AEWWIN1_WINH_MASK 0x7F000000
++
++#define ISPH3A_AEWINSTART_WINSH_SHIFT 0
++#define ISPH3A_AEWINSTART_WINSH_MASK 0x0FFF
++#define ISPH3A_AEWINSTART_WINSV_SHIFT 16
++#define ISPH3A_AEWINSTART_WINSV_MASK 0x0FFF0000
++
++#define ISPH3A_AEWINBLK_WINH_SHIFT 0
++#define ISPH3A_AEWINBLK_WINH_MASK 0x7F
++#define ISPH3A_AEWINBLK_WINSV_SHIFT 16
++#define ISPH3A_AEWINBLK_WINSV_MASK 0x0FFF0000
++
++#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT 0
++#define ISPH3A_AEWSUBWIN_AEWINCH_MASK 0x0F
++#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT 8
++#define ISPH3A_AEWSUBWIN_AEWINCV_MASK 0x0F00
++
++#define ISPHIST_PCR_ENABLE_SHIFT 0
++#define ISPHIST_PCR_ENABLE_MASK 0x01
++#define ISPHIST_PCR_BUSY 0x02
++
++#define ISPHIST_CNT_DATASIZE_SHIFT 8
++#define ISPHIST_CNT_DATASIZE_MASK 0x0100
++#define ISPHIST_CNT_CLEAR_SHIFT 7
++#define ISPHIST_CNT_CLEAR_MASK 0x080
++#define ISPHIST_CNT_CFA_SHIFT 6
++#define ISPHIST_CNT_CFA_MASK 0x040
++#define ISPHIST_CNT_BINS_SHIFT 4
++#define ISPHIST_CNT_BINS_MASK 0x030
++#define ISPHIST_CNT_SOURCE_SHIFT 3
++#define ISPHIST_CNT_SOURCE_MASK 0x08
++#define ISPHIST_CNT_SHIFT_SHIFT 0
++#define ISPHIST_CNT_SHIFT_MASK 0x07
++
++#define ISPHIST_WB_GAIN_WG00_SHIFT 24
++#define ISPHIST_WB_GAIN_WG00_MASK 0xFF000000
++#define ISPHIST_WB_GAIN_WG01_SHIFT 16
++#define ISPHIST_WB_GAIN_WG01_MASK 0xFF0000
++#define ISPHIST_WB_GAIN_WG02_SHIFT 8
++#define ISPHIST_WB_GAIN_WG02_MASK 0xFF00
++#define ISPHIST_WB_GAIN_WG03_SHIFT 0
++#define ISPHIST_WB_GAIN_WG03_MASK 0xFF
++
++#define ISPHIST_REGHORIZ_HSTART_SHIFT 16 /*
++ * REGION 0 to 3 HORZ
++ * and VERT
++ */
++#define ISPHIST_REGHORIZ_HSTART_MASK 0x3FFF0000
++#define ISPHIST_REGHORIZ_HEND_SHIFT 0
++#define ISPHIST_REGHORIZ_HEND_MASK 0x3FFF
++#define ISPHIST_REGVERT_VSTART_SHIFT 16
++#define ISPHIST_REGVERT_VSTART_MASK 0x3FFF0000
++#define ISPHIST_REGVERT_VEND_SHIFT 0
++#define ISPHIST_REGVERT_VEND_MASK 0x3FFF
++
++#define ISPHIST_REGHORIZ_MASK 0x3FFF3FFF
++#define ISPHIST_REGVERT_MASK 0x3FFF3FFF
++
++#define ISPHIST_ADDR_SHIFT 0
++#define ISPHIST_ADDR_MASK 0x3FF
++
++#define ISPHIST_DATA_SHIFT 0
++#define ISPHIST_DATA_MASK 0xFFFFF
++
++#define ISPHIST_RADD_SHIFT 0
++#define ISPHIST_RADD_MASK 0xFFFFFFFF
++
++#define ISPHIST_RADD_OFF_SHIFT 0
++#define ISPHIST_RADD_OFF_MASK 0xFFFF
++
++#define ISPHIST_HV_INFO_HSIZE_SHIFT 16
++#define ISPHIST_HV_INFO_HSIZE_MASK 0x3FFF0000
++#define ISPHIST_HV_INFO_VSIZE_SHIFT 0
++#define ISPHIST_HV_INFO_VSIZE_MASK 0x3FFF
++
++#define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
++
++#define ISPCCDC_LSC_GAIN_MODE_N_MASK 0x700
++#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT 8
++#define ISPCCDC_LSC_GAIN_MODE_M_MASK 0x3800
++#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT 12
++#define ISPCCDC_LSC_GAIN_FORMAT_MASK 0xE
++#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT 1
++#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK (1<<6)
++
++#define ISPCCDC_LSC_INITIAL_X_MASK 0x3F
++#define ISPCCDC_LSC_INITIAL_X_SHIFT 0
++#define ISPCCDC_LSC_INITIAL_Y_MASK 0x3F0000
++#define ISPCCDC_LSC_INITIAL_Y_SHIFT 16
++
++#define ISPMMU_REVISION_REV_MINOR_MASK 0xF
++#define ISPMMU_REVISION_REV_MAJOR_SHIFT 0x4
++
++#define IRQENABLE_MULTIHITFAULT (1<<4)
++#define IRQENABLE_TWFAULT (1<<3)
++#define IRQENABLE_EMUMISS (1<<2)
++#define IRQENABLE_TRANSLNFAULT (1<<1)
++#define IRQENABLE_TLBMISS (1)
++
++#define ISPMMU_MMUCNTL_MMU_EN (1<<1)
++#define ISPMMU_MMUCNTL_TWL_EN (1<<2)
++#define ISPMMU_MMUCNTL_EMUTLBUPDATE (1<<3)
++#define ISPMMU_AUTOIDLE 0x1
++#define ISPMMU_SIDLEMODE_FORCEIDLE 0
++#define ISPMMU_SIDLEMODE_NOIDLE 1
++#define ISPMMU_SIDLEMODE_SMARTIDLE 2
++#define ISPMMU_SIDLEMODE_SHIFT 3
++
++#define ISPCSI1_AUTOIDLE 0x1
++#define ISPCSI1_MIDLEMODE_SHIFT 12
++#define ISPCSI1_MIDLEMODE_FORCESTANDBY 0x0
++#define ISPCSI1_MIDLEMODE_NOSTANDBY 0x1
++#define ISPCSI1_MIDLEMODE_SMARTSTANDBY 0x2
++
++/* CSI2 receiver registers (ES2.0) */
++#define ISPCSI2_REVISION (0x000)
++#define ISPCSI2_SYSCONFIG (0x010)
++#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
++#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
++ (0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
++#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
++ (0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
++#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
++ (0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
++#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
++ (0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
++#define ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT 1
++#define ISPCSI2_SYSCONFIG_SOFT_RESET_MASK \
++ (0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
++#define ISPCSI2_SYSCONFIG_SOFT_RESET_NORMAL \
++ (0x0 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
++#define ISPCSI2_SYSCONFIG_SOFT_RESET_RESET \
++ (0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
++#define ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT 0
++#define ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK \
++ (0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
++#define ISPCSI2_SYSCONFIG_AUTO_IDLE_FREE \
++ (0x0 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
++#define ISPCSI2_SYSCONFIG_AUTO_IDLE_AUTO \
++ (0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
++#define ISPCSI2_SYSSTATUS (0x014)
++#define ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT 0
++#define ISPCSI2_SYSSTATUS_RESET_DONE_MASK \
++ (0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
++#define ISPCSI2_SYSSTATUS_RESET_DONE_ONGOING \
++ (0x0 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
++#define ISPCSI2_SYSSTATUS_RESET_DONE_DONE \
++ (0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
++#define ISPCSI2_IRQSTATUS (0x018)
++#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ (1 << 14)
++#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ (1 << 13)
++#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 12)
++#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ (1 << 11)
++#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ (1 << 10)
++#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ (1 << 9)
++#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ (1 << 8)
++#define ISPCSI2_IRQSTATUS_CONTEXT(n) (1 << (n))
++
++#define ISPCSI2_IRQENABLE (0x01C)
++#define ISPCSI2_CTRL (0x040)
++#define ISPCSI2_CTRL_VP_CLK_EN_SHIFT 15
++#define ISPCSI2_CTRL_VP_CLK_EN_MASK (0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
++#define ISPCSI2_CTRL_VP_CLK_EN_DISABLE (0x0 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
++#define ISPCSI2_CTRL_VP_CLK_EN_ENABLE (0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
++
++#define ISPCSI2_CTRL_VP_ONLY_EN_SHIFT 11
++#define ISPCSI2_CTRL_VP_ONLY_EN_MASK (0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
++#define ISPCSI2_CTRL_VP_ONLY_EN_DISABLE (0x0 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
++#define ISPCSI2_CTRL_VP_ONLY_EN_ENABLE (0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
++
++#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT 8
++#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK (0x3 << \
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
++#define ISPCSI2_CTRL_VP_OUT_CTRL_DISABLE (0x0 << \
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
++#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV2 (0x1 << \
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
++#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV3 (0x2 << \
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
++#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV4 (0x3 << \
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
++
++#define ISPCSI2_CTRL_DBG_EN_SHIFT 7
++#define ISPCSI2_CTRL_DBG_EN_MASK (0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
++#define ISPCSI2_CTRL_DBG_EN_DISABLE (0x0 << ISPCSI2_CTRL_DBG_EN_SHIFT)
++#define ISPCSI2_CTRL_DBG_EN_ENABLE (0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
++
++#define ISPCSI2_CTRL_BURST_SIZE_SHIFT 5
++#define ISPCSI2_CTRL_BURST_SIZE_MASK (0x3 << \
++ ISPCSI2_CTRL_BURST_SIZE_SHIFT)
++#define ISPCSI2_CTRL_BURST_SIZE_MYSTERY_VAL (0x2 << \
++ ISPCSI2_CTRL_BURST_SIZE_SHIFT)
++
++#define ISPCSI2_CTRL_FRAME_SHIFT 3
++#define ISPCSI2_CTRL_FRAME_MASK (0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
++#define ISPCSI2_CTRL_FRAME_DISABLE_IMM (0x0 << ISPCSI2_CTRL_FRAME_SHIFT)
++#define ISPCSI2_CTRL_FRAME_DISABLE_FEC (0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
++
++#define ISPCSI2_CTRL_ECC_EN_SHIFT 2
++#define ISPCSI2_CTRL_ECC_EN_MASK (0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
++#define ISPCSI2_CTRL_ECC_EN_DISABLE (0x0 << ISPCSI2_CTRL_ECC_EN_SHIFT)
++#define ISPCSI2_CTRL_ECC_EN_ENABLE (0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
++
++#define ISPCSI2_CTRL_SECURE_SHIFT 1
++#define ISPCSI2_CTRL_SECURE_MASK (0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
++#define ISPCSI2_CTRL_SECURE_DISABLE (0x0 << ISPCSI2_CTRL_SECURE_SHIFT)
++#define ISPCSI2_CTRL_SECURE_ENABLE (0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
++
++#define ISPCSI2_CTRL_IF_EN_SHIFT 0
++#define ISPCSI2_CTRL_IF_EN_MASK (0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
++#define ISPCSI2_CTRL_IF_EN_DISABLE (0x0 << ISPCSI2_CTRL_IF_EN_SHIFT)
++#define ISPCSI2_CTRL_IF_EN_ENABLE (0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
++
++#define ISPCSI2_DBG_H (0x044)
++#define ISPCSI2_GNQ (0x048)
++#define ISPCSI2_COMPLEXIO_CFG1 (0x050)
++#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT 29
++#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_MASK \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_ONGOING \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_DONE \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT 27
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK \
++ (0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW \
++ (0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT 25
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK \
++ (0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW \
++ (0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT 24
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
++
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n) (3 + ((n) * 4))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(n) \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_PN(n) \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_NP(n) \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
++
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n) ((n) * 4)
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(n) \
++ (0x7 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_NC(n) \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_1(n) \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_2(n) \
++ (0x2 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_3(n) \
++ (0x3 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_4(n) \
++ (0x4 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_5(n) \
++ (0x5 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
++
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT 3
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_PN \
++ (0x0 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_NP \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
++
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT 0
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK \
++ (0x7 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_1 \
++ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_2 \
++ (0x2 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_3 \
++ (0x3 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_4 \
++ (0x4 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_5 \
++ (0x5 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
++
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS (0x054)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMEXIT (1 << 26)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMENTER (1 << 25)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM5 (1 << 24)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM4 (1 << 23)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM3 (1 << 22)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM2 (1 << 21)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM1 (1 << 20)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL5 (1 << 19)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL4 (1 << 18)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL3 (1 << 17)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL2 (1 << 16)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL1 (1 << 15)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC5 (1 << 14)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC4 (1 << 13)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC3 (1 << 12)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC2 (1 << 11)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC1 (1 << 10)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS5 (1 << 9)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS4 (1 << 8)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS3 (1 << 7)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS2 (1 << 6)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS1 (1 << 5)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS5 (1 << 4)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS4 (1 << 3)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS3 (1 << 2)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS2 (1 << 1)
++#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS1 1
++
++#define ISPCSI2_SHORT_PACKET (0x05C)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE (0x060)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT (1 << 26)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER (1 << 25)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 (1 << 24)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 (1 << 23)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 (1 << 22)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 (1 << 21)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 (1 << 20)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 (1 << 19)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 (1 << 18)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 (1 << 17)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 (1 << 16)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 (1 << 15)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 (1 << 14)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 (1 << 13)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 (1 << 12)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 (1 << 11)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 (1 << 10)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 (1 << 9)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 (1 << 8)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 (1 << 7)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 (1 << 6)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 (1 << 5)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 (1 << 4)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 (1 << 3)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 (1 << 2)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 (1 << 1)
++#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1 1
++#define ISPCSI2_DBG_P (0x068)
++#define ISPCSI2_TIMING (0x06C)
++
++
++#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n) \
++ ((16 * ((n) - 1)) + 15)
++#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(n) \
++ (0x1 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
++#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE(n) \
++ (0x0 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
++#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(n) \
++ (0x1 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n) ((16 * ((n) - 1)) + 14)
++#define ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(n) \
++ (0x1 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE(n) \
++ (0x0 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(n) \
++ (0x1 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n) ((16 * ((n) - 1)) + 13)
++#define ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(n) \
++ (0x1 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE(n) \
++ (0x0 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(n) \
++ (0x1 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
++#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n) (16 * ((n) - 1))
++#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n) \
++ (0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
++
++#define ISPCSI2_CTX_CTRL1(n) ((0x070) + 0x20 * (n))
++#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT 8
++#define ISPCSI2_CTX_CTRL1_COUNT_MASK (0xFF << \
++ ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT 7
++#define ISPCSI2_CTX_CTRL1_EOF_EN_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE \
++ (0x0 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE \
++ (0x1 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT 6
++#define ISPCSI2_CTX_CTRL1_EOL_EN_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE \
++ (0x0 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE \
++ (0x1 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CS_EN_SHIFT 5
++#define ISPCSI2_CTX_CTRL1_CS_EN_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CS_EN_DISABLE \
++ (0x0 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CS_EN_ENABLE \
++ (0x1 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT 4
++#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_DISABLE \
++ (0x0 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_ENABLE \
++ (0x1 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT 3
++#define ISPCSI2_CTX_CTRL1_PING_PONG_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT 0
++#define ISPCSI2_CTX_CTRL1_CTX_EN_MASK \
++ (0x1 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE \
++ (0x0 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
++#define ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE \
++ (0x1 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
++
++#define ISPCSI2_CTX_CTRL2(n) ((0x074) + 0x20 * (n))
++#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
++#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK \
++ (0x3 << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
++#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT 0
++#define ISPCSI2_CTX_CTRL2_FORMAT_MASK (0x3FF << \
++ ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
++
++#define ISPCSI2_CTX_DAT_OFST(n) ((0x078) + 0x20 * (n))
++#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT 5
++#define ISPCSI2_CTX_DAT_OFST_OFST_MASK (0x7FF << \
++ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
++
++#define ISPCSI2_CTX_DAT_PING_ADDR(n) ((0x07C) + 0x20 * (n))
++#define ISPCSI2_CTX_DAT_PONG_ADDR(n) ((0x080) + 0x20 * (n))
++#define ISPCSI2_CTX_IRQENABLE(n) ((0x084) + 0x20 * (n))
++#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ (1 << 8)
++#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ (1 << 7)
++#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ (1 << 6)
++#define ISPCSI2_CTX_IRQENABLE_CS_IRQ (1 << 5)
++#define ISPCSI2_CTX_IRQENABLE_LE_IRQ (1 << 3)
++#define ISPCSI2_CTX_IRQENABLE_LS_IRQ (1 << 2)
++#define ISPCSI2_CTX_IRQENABLE_FE_IRQ (1 << 1)
++#define ISPCSI2_CTX_IRQENABLE_FS_IRQ 1
++#define ISPCSI2_CTX_IRQSTATUS(n) ((0x088) + 0x20 * (n))
++#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 8)
++#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ (1 << 7)
++#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ (1 << 6)
++#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ (1 << 5)
++#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ (1 << 3)
++#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ (1 << 2)
++#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ (1 << 1)
++#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ 1
++
++#define ISPCSI2_CTX_CTRL3(n) ((0x08C) + 0x20 * (n))
++#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT 5
++#define ISPCSI2_CTX_CTRL3_ALPHA_MASK (0x3FFF << \
++ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
++
++#define ISPCSI2PHY_CFG0 (0x000)
++#define ISPCSI2PHY_CFG0_THS_TERM_SHIFT 8
++#define ISPCSI2PHY_CFG0_THS_TERM_MASK \
++ (0xFF << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
++#define ISPCSI2PHY_CFG0_THS_TERM_RESETVAL \
++ (0x04 << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
++#define ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT 0
++#define ISPCSI2PHY_CFG0_THS_SETTLE_MASK \
++ (0xFF << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
++#define ISPCSI2PHY_CFG0_THS_SETTLE_RESETVAL \
++ (0x27 << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
++#define ISPCSI2PHY_CFG1 (0x004)
++#define ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT 18
++#define ISPCSI2PHY_CFG1_TCLK_TERM_MASK \
++ (0x7F << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
++#define ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL \
++ (0x00 << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
++#define ISPCSI2PHY_CFG1_RESERVED1_SHIFT 10
++#define ISPCSI2PHY_CFG1_RESERVED1_MASK \
++ (0xFF << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
++#define ISPCSI2PHY_CFG1_RESERVED1__RESETVAL \
++ (0xB8 << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
++#define ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT 8
++#define ISPCSI2PHY_CFG1_TCLK_MISS_MASK \
++ (0x3 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
++#define ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL \
++ (0x1 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
++#define ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT 0
++#define ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK \
++ (0xFF << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
++#define ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL \
++ (0x0E << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
++#define ISPCSI2PHY_CFG1__RESETVAL (ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL | \
++ ISPCSI2PHY_CFG1_RESERVED1__RESETVAL | \
++ ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL | \
++ ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL)
++#define ISPCSI2PHY_CFG1__EDITABLE_MASK (ISPCSI2PHY_CFG1_TCLK_TERM_MASK | \
++ ISPCSI2PHY_CFG1_RESERVED1_MASK | \
++ ISPCSI2PHY_CFG1_TCLK_MISS_MASK | \
++ ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK)
++
++#endif /* __ISPREG_H__ */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch
new file mode 100644
index 0000000000..cfca26723a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch
@@ -0,0 +1,209 @@
+From 731527a7dc26533a878c7c5f36fc148fdcaa21b8 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add ISP MMU wrapper
+
+TODO:
+
+- The ISP driver should start using the IOMMU directly without this wrapper.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/ispmmu.c | 141 ++++++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/ispmmu.h | 36 ++++++++++
+ 2 files changed, 177 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/ispmmu.c
+ create mode 100644 drivers/media/video/isp/ispmmu.h
+
+diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
+new file mode 100644
+index 0000000..f872c71
+--- /dev/null
++++ b/drivers/media/video/isp/ispmmu.c
+@@ -0,0 +1,141 @@
++/*
++ * omap iommu wrapper for TI's OMAP3430 Camera ISP
++ *
++ * Copyright (C) 2008--2009 Nokia.
++ *
++ * Contributors:
++ * Hiroshi Doyu <hiroshi.doyu@nokia.com>
++ * Sakari Ailus <sakari.ailus@nokia.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/module.h>
++
++#include "ispmmu.h"
++#include "isp.h"
++
++#include <mach/iommu.h>
++#include <mach/iovmm.h>
++
++#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
++
++static struct iommu *isp_iommu;
++
++dma_addr_t ispmmu_vmalloc(size_t bytes)
++{
++ return (dma_addr_t)iommu_vmalloc(isp_iommu, 0, bytes, IOMMU_FLAG);
++}
++
++void ispmmu_vfree(const dma_addr_t da)
++{
++ iommu_vfree(isp_iommu, (u32)da);
++}
++
++dma_addr_t ispmmu_kmap(u32 pa, int size)
++{
++ void *da;
++
++ da = (void *)iommu_kmap(isp_iommu, 0, pa, size, IOMMU_FLAG);
++ if (IS_ERR(da))
++ return PTR_ERR(da);
++
++ return (dma_addr_t)da;
++}
++
++void ispmmu_kunmap(dma_addr_t da)
++{
++ iommu_kunmap(isp_iommu, (u32)da);
++}
++
++dma_addr_t ispmmu_vmap(const struct scatterlist *sglist,
++ int sglen)
++{
++ int err;
++ void *da;
++ struct sg_table *sgt;
++ unsigned int i;
++ struct scatterlist *sg, *src = (struct scatterlist *)sglist;
++
++ /*
++ * convert isp sglist to iommu sgt
++ * FIXME: should be fixed in the upper layer?
++ */
++ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
++ if (!sgt)
++ return -ENOMEM;
++ err = sg_alloc_table(sgt, sglen, GFP_KERNEL);
++ if (err)
++ goto err_sg_alloc;
++
++ for_each_sg(sgt->sgl, sg, sgt->nents, i)
++ sg_set_buf(sg, phys_to_virt(sg_dma_address(src + i)),
++ sg_dma_len(src + i));
++
++ da = (void *)iommu_vmap(isp_iommu, 0, sgt, IOMMU_FLAG);
++ if (IS_ERR(da))
++ goto err_vmap;
++
++ return (dma_addr_t)da;
++
++err_vmap:
++ sg_free_table(sgt);
++err_sg_alloc:
++ kfree(sgt);
++ return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(ispmmu_vmap);
++
++void ispmmu_vunmap(dma_addr_t da)
++{
++ struct sg_table *sgt;
++
++ sgt = iommu_vunmap(isp_iommu, (u32)da);
++ if (!sgt)
++ return;
++ sg_free_table(sgt);
++ kfree(sgt);
++}
++EXPORT_SYMBOL_GPL(ispmmu_vunmap);
++
++void ispmmu_save_context(void)
++{
++ if (isp_iommu)
++ iommu_save_ctx(isp_iommu);
++}
++
++void ispmmu_restore_context(void)
++{
++ if (isp_iommu)
++ iommu_restore_ctx(isp_iommu);
++}
++
++int __init ispmmu_init(void)
++{
++ int err = 0;
++
++ isp_get();
++ isp_iommu = iommu_get("isp");
++ if (IS_ERR(isp_iommu)) {
++ err = PTR_ERR(isp_iommu);
++ isp_iommu = NULL;
++ }
++ isp_put();
++
++ return err;
++}
++
++void ispmmu_cleanup(void)
++{
++ isp_get();
++ if (isp_iommu)
++ iommu_put(isp_iommu);
++ isp_put();
++ isp_iommu = NULL;
++}
+diff --git a/drivers/media/video/isp/ispmmu.h b/drivers/media/video/isp/ispmmu.h
+new file mode 100644
+index 0000000..0bc5bcb
+--- /dev/null
++++ b/drivers/media/video/isp/ispmmu.h
+@@ -0,0 +1,36 @@
++/*
++ * omap iommu wrapper for TI's OMAP3430 Camera ISP
++ *
++ * Copyright (C) 2008--2009 Nokia.
++ *
++ * Contributors:
++ * Hiroshi Doyu <hiroshi.doyu@nokia.com>
++ * Sakari Ailus <sakari.ailus@nokia.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_MMU_H
++#define OMAP_ISP_MMU_H
++
++#include <linux/err.h>
++#include <linux/scatterlist.h>
++
++dma_addr_t ispmmu_vmalloc(size_t bytes);
++void ispmmu_vfree(const dma_addr_t da);
++dma_addr_t ispmmu_kmap(u32 pa, int size);
++void ispmmu_kunmap(dma_addr_t da);
++dma_addr_t ispmmu_vmap(const struct scatterlist *sglist, int sglen);
++void ispmmu_vunmap(dma_addr_t da);
++void ispmmu_save_context(void);
++void ispmmu_restore_context(void);
++int ispmmu_init(void);
++void ispmmu_cleanup(void);
++
++#endif /* OMAP_ISP_MMU_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch
new file mode 100644
index 0000000000..66c171f544
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch
@@ -0,0 +1,696 @@
+From 98ca1ef8c6e2561989aeef981131cf5077eab1d1 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add userspace header
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ arch/arm/plat-omap/include/mach/isp_user.h | 676 ++++++++++++++++++++++++++++
+ 1 files changed, 676 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/plat-omap/include/mach/isp_user.h
+
+diff --git a/arch/arm/plat-omap/include/mach/isp_user.h b/arch/arm/plat-omap/include/mach/isp_user.h
+new file mode 100644
+index 0000000..b819e26
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/isp_user.h
+@@ -0,0 +1,676 @@
++/*
++ * isp_user.h
++ *
++ * Include file for OMAP ISP module in TI's OMAP3.
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Mohit Jalori <mjalori@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_USER_H
++#define OMAP_ISP_USER_H
++
++/* ISP Private IOCTLs */
++#define VIDIOC_PRIVATE_ISP_CCDC_CFG \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct ispccdc_update_config)
++#define VIDIOC_PRIVATE_ISP_PRV_CFG \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct ispprv_update_config)
++#define VIDIOC_PRIVATE_ISP_AEWB_CFG \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct isph3a_aewb_config)
++#define VIDIOC_PRIVATE_ISP_AEWB_REQ \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct isph3a_aewb_data)
++#define VIDIOC_PRIVATE_ISP_HIST_CFG \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct isp_hist_config)
++#define VIDIOC_PRIVATE_ISP_HIST_REQ \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct isp_hist_data)
++#define VIDIOC_PRIVATE_ISP_AF_CFG \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct af_configuration)
++#define VIDIOC_PRIVATE_ISP_AF_REQ \
++ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct isp_af_data)
++
++/* AE/AWB related structures and flags*/
++
++/* Flags for update field */
++#define REQUEST_STATISTICS (1 << 0)
++#define SET_COLOR_GAINS (1 << 1)
++#define SET_DIGITAL_GAIN (1 << 2)
++#define SET_EXPOSURE (1 << 3)
++#define SET_ANALOG_GAIN (1 << 4)
++
++#define MAX_FRAME_COUNT 0x0FFF
++#define MAX_FUTURE_FRAMES 10
++
++#define MAX_SATURATION_LIM 1023
++#define MIN_WIN_H 2
++#define MAX_WIN_H 256
++#define MIN_WIN_W 6
++#define MAX_WIN_W 256
++#define MAX_WINVC 128
++#define MAX_WINHC 36
++#define MAX_WINSTART 4095
++#define MIN_SUB_INC 2
++#define MAX_SUB_INC 32
++
++/* Range Constants */
++#define AF_IIRSH_MIN 0
++#define AF_IIRSH_MAX 4094
++#define AF_PAXEL_HORIZONTAL_COUNT_MIN 0
++#define AF_PAXEL_HORIZONTAL_COUNT_MAX 35
++#define AF_PAXEL_VERTICAL_COUNT_MIN 0
++#define AF_PAXEL_VERTICAL_COUNT_MAX 127
++#define AF_PAXEL_INCREMENT_MIN 0
++#define AF_PAXEL_INCREMENT_MAX 14
++#define AF_PAXEL_HEIGHT_MIN 0
++#define AF_PAXEL_HEIGHT_MAX 127
++#define AF_PAXEL_WIDTH_MIN 0
++#define AF_PAXEL_WIDTH_MAX 127
++#define AF_PAXEL_HZSTART_MIN 2
++#define AF_PAXEL_HZSTART_MAX 4094
++
++#define AF_PAXEL_VTSTART_MIN 0
++#define AF_PAXEL_VTSTART_MAX 4095
++#define AF_THRESHOLD_MAX 255
++#define AF_COEF_MAX 4095
++#define AF_PAXEL_SIZE 48
++
++/**
++ * struct isph3a_aewb_config - AE AWB configuration reset values.
++ * saturation_limit: Saturation limit.
++ * @win_height: Window Height. Range 2 - 256, even values only.
++ * @win_width: Window Width. Range 6 - 256, even values only.
++ * @ver_win_count: Vertical Window Count. Range 1 - 128.
++ * @hor_win_count: Horizontal Window Count. Range 1 - 36.
++ * @ver_win_start: Vertical Window Start. Range 0 - 4095.
++ * @hor_win_start: Horizontal Window Start. Range 0 - 4095.
++ * @blk_ver_win_start: Black Vertical Windows Start. Range 0 - 4095.
++ * @blk_win_height: Black Window Height. Range 2 - 256, even values only.
++ * @subsample_ver_inc: Subsample Vertical points increment Range 2 - 32, even
++ * values only.
++ * @subsample_hor_inc: Subsample Horizontal points increment Range 2 - 32, even
++ * values only.
++ * @alaw_enable: AEW ALAW EN flag.
++ * @aewb_enable: AE AWB stats generation EN flag.
++ */
++struct isph3a_aewb_config {
++ __u16 saturation_limit;
++ __u16 win_height;
++ __u16 win_width;
++ __u16 ver_win_count;
++ __u16 hor_win_count;
++ __u16 ver_win_start;
++ __u16 hor_win_start;
++ __u16 blk_ver_win_start;
++ __u16 blk_win_height;
++ __u16 subsample_ver_inc;
++ __u16 subsample_hor_inc;
++ __u8 alaw_enable;
++ __u8 aewb_enable;
++};
++
++/**
++ * struct isph3a_aewb_data - Structure of data sent to or received from user
++ * @h3a_aewb_statistics_buf: Pointer to pass to user.
++ * @shutter: Shutter speed.
++ * @gain: Sensor analog Gain.
++ * @shutter_cap: Shutter speed for capture.
++ * @gain_cap: Sensor Gain for capture.
++ * @dgain: White balance digital gain.
++ * @wb_gain_b: White balance color gain blue.
++ * @wb_gain_r: White balance color gain red.
++ * @wb_gain_gb: White balance color gain green blue.
++ * @wb_gain_gr: White balance color gain green red.
++ * @frame_number: Frame number of requested stats.
++ * @curr_frame: Current frame number being processed.
++ * @update: Bitwise flags to update parameters.
++ * @ts: Timestamp of returned framestats.
++ * @field_count: Sequence number of returned framestats.
++ */
++struct isph3a_aewb_data {
++ void *h3a_aewb_statistics_buf;
++ __u32 shutter;
++ __u16 gain;
++ __u32 shutter_cap;
++ __u16 gain_cap;
++ __u16 dgain;
++ __u16 wb_gain_b;
++ __u16 wb_gain_r;
++ __u16 wb_gain_gb;
++ __u16 wb_gain_gr;
++ __u16 frame_number;
++ __u16 curr_frame;
++ __u8 update;
++ struct timeval ts;
++ __u32 config_counter;
++ unsigned long field_count;
++};
++
++
++/* Histogram related structs */
++/* Flags for number of bins */
++#define BINS_32 0x0
++#define BINS_64 0x1
++#define BINS_128 0x2
++#define BINS_256 0x3
++
++struct isp_hist_config {
++ __u8 hist_source; /* CCDC or Memory */
++ __u8 input_bit_width; /* Needed o know the size per pixel */
++ __u8 hist_frames; /* Num of frames to be processed and
++ * accumulated
++ */
++ __u8 hist_h_v_info; /* frame-input width and height if source is
++ * memory
++ */
++ __u16 hist_radd; /* frame-input address in memory */
++ __u16 hist_radd_off; /* line-offset for frame-input */
++ __u16 hist_bins; /* number of bins: 32, 64, 128, or 256 */
++ __u16 wb_gain_R; /* White Balance Field-to-Pattern Assignments */
++ __u16 wb_gain_RG; /* White Balance Field-to-Pattern Assignments */
++ __u16 wb_gain_B; /* White Balance Field-to-Pattern Assignments */
++ __u16 wb_gain_BG; /* White Balance Field-to-Pattern Assignments */
++ __u8 num_regions; /* number of regions to be configured */
++ __u16 reg0_hor; /* Region 0 size and position */
++ __u16 reg0_ver; /* Region 0 size and position */
++ __u16 reg1_hor; /* Region 1 size and position */
++ __u16 reg1_ver; /* Region 1 size and position */
++ __u16 reg2_hor; /* Region 2 size and position */
++ __u16 reg2_ver; /* Region 2 size and position */
++ __u16 reg3_hor; /* Region 3 size and position */
++ __u16 reg3_ver; /* Region 3 size and position */
++};
++
++struct isp_hist_data {
++ __u32 *hist_statistics_buf; /* Pointer to pass to user */
++};
++
++/* Auto Focus related structs */
++
++#define AF_NUMBER_OF_COEF 11
++
++/* Flags for update field */
++#define REQUEST_STATISTICS (1 << 0)
++#define LENS_DESIRED_POSITION (1 << 1)
++#define LENS_CURRENT_POSITION (1 << 2)
++
++/**
++ * struct isp_af_xtrastats - Extra statistics related to AF generated stats.
++ * @ts: Timestamp when the frame gets delivered to the user.
++ * @field_count: Field count of the frame delivered to the user.
++ * @lens_position: Lens position when the stats are being generated.
++ */
++struct isp_af_xtrastats {
++ struct timeval ts;
++ unsigned long field_count;
++ __u16 lens_position; /* deprecated */
++};
++
++/**
++ * struct isp_af_data - AF statistics data to transfer between driver and user.
++ * @af_statistics_buf: Pointer to pass to user.
++ * @lens_current_position: Read value of lens absolute position.
++ * @desired_lens_direction: Lens desired location.
++ * @update: Bitwise flags to update parameters.
++ * @frame_number: Data for which frame is desired/given.
++ * @curr_frame: Current frame number being processed by AF module.
++ * @xtrastats: Extra statistics structure.
++ */
++struct isp_af_data {
++ void *af_statistics_buf;
++ __u16 lens_current_position; /* deprecated */
++ __u16 desired_lens_direction; /* deprecated */
++ __u16 update;
++ __u16 frame_number;
++ __u16 curr_frame;
++ __u32 config_counter;
++ struct isp_af_xtrastats xtrastats;
++};
++
++/* enum used for status of specific feature */
++enum af_alaw_enable {
++ H3A_AF_ALAW_DISABLE = 0,
++ H3A_AF_ALAW_ENABLE = 1
++};
++
++enum af_hmf_enable {
++ H3A_AF_HMF_DISABLE = 0,
++ H3A_AF_HMF_ENABLE = 1
++};
++
++enum af_config_flag {
++ H3A_AF_CFG_DISABLE = 0,
++ H3A_AF_CFG_ENABLE = 1
++};
++
++enum af_mode {
++ ACCUMULATOR_SUMMED = 0,
++ ACCUMULATOR_PEAK = 1
++};
++
++/* Red, Green, and blue pixel location in the AF windows */
++enum rgbpos {
++ GR_GB_BAYER = 0, /* GR and GB as Bayer pattern */
++ RG_GB_BAYER = 1, /* RG and GB as Bayer pattern */
++ GR_BG_BAYER = 2, /* GR and BG as Bayer pattern */
++ RG_BG_BAYER = 3, /* RG and BG as Bayer pattern */
++ GG_RB_CUSTOM = 4, /* GG and RB as custom pattern */
++ RB_GG_CUSTOM = 5 /* RB and GG as custom pattern */
++};
++
++/* Contains the information regarding the Horizontal Median Filter */
++struct af_hmf {
++ enum af_hmf_enable enable; /* Status of Horizontal Median Filter */
++ unsigned int threshold; /* Threshhold Value for Horizontal Median
++ * Filter
++ */
++};
++
++/* Contains the information regarding the IIR Filters */
++struct af_iir {
++ unsigned int hz_start_pos; /* IIR Start Register Value */
++ int coeff_set0[AF_NUMBER_OF_COEF]; /*
++ * IIR Filter Coefficient for
++ * Set 0
++ */
++ int coeff_set1[AF_NUMBER_OF_COEF]; /*
++ * IIR Filter Coefficient for
++ * Set 1
++ */
++};
++
++/* Contains the information regarding the Paxels Structure in AF Engine */
++struct af_paxel {
++ unsigned int width; /* Width of the Paxel */
++ unsigned int height; /* Height of the Paxel */
++ unsigned int hz_start; /* Horizontal Start Position */
++ unsigned int vt_start; /* Vertical Start Position */
++ unsigned int hz_cnt; /* Horizontal Count */
++ unsigned int vt_cnt; /* vertical Count */
++ unsigned int line_incr; /* Line Increment */
++};
++/* Contains the parameters required for hardware set up of AF Engine */
++struct af_configuration {
++ enum af_alaw_enable alaw_enable; /*ALWAW status */
++ struct af_hmf hmf_config; /*HMF configurations */
++ enum rgbpos rgb_pos; /*RGB Positions */
++ struct af_iir iir_config; /*IIR filter configurations */
++ struct af_paxel paxel_config; /*Paxel parameters */
++ enum af_mode mode; /*Accumulator mode */
++ enum af_config_flag af_config; /*Flag indicates Engine is configured */
++};
++
++/* ISP CCDC structs */
++
++/* Abstraction layer CCDC configurations */
++#define ISP_ABS_CCDC_ALAW (1 << 0)
++#define ISP_ABS_CCDC_LPF (1 << 1)
++#define ISP_ABS_CCDC_BLCLAMP (1 << 2)
++#define ISP_ABS_CCDC_BCOMP (1 << 3)
++#define ISP_ABS_CCDC_FPC (1 << 4)
++#define ISP_ABS_CCDC_CULL (1 << 5)
++#define ISP_ABS_CCDC_COLPTN (1 << 6)
++#define ISP_ABS_CCDC_CONFIG_LSC (1 << 7)
++#define ISP_ABS_TBL_LSC (1 << 8)
++
++#define RGB_MAX 3
++
++/* Enumeration constants for Alaw input width */
++enum alaw_ipwidth {
++ ALAW_BIT12_3 = 0x3,
++ ALAW_BIT11_2 = 0x4,
++ ALAW_BIT10_1 = 0x5,
++ ALAW_BIT9_0 = 0x6
++};
++
++/* Enumeration constants for Video Port */
++enum vpin {
++ BIT12_3 = 3,
++ BIT11_2 = 4,
++ BIT10_1 = 5,
++ BIT9_0 = 6
++};
++
++enum vpif_freq {
++ PIXCLKBY2,
++ PIXCLKBY3_5,
++ PIXCLKBY4_5,
++ PIXCLKBY5_5,
++ PIXCLKBY6_5
++};
++
++/**
++ * struct ispccdc_lsc_config - Structure for LSC configuration.
++ * @offset: Table Offset of the gain table.
++ * @gain_mode_n: Vertical dimension of a paxel in LSC configuration.
++ * @gain_mode_m: Horizontal dimension of a paxel in LSC configuration.
++ * @gain_format: Gain table format.
++ * @fmtsph: Start pixel horizontal from start of the HS sync pulse.
++ * @fmtlnh: Number of pixels in horizontal direction to use for the data
++ * reformatter.
++ * @fmtslv: Start line from start of VS sync pulse for the data reformatter.
++ * @fmtlnv: Number of lines in vertical direction for the data reformatter.
++ * @initial_x: X position, in pixels, of the first active pixel in reference
++ * to the first active paxel. Must be an even number.
++ * @initial_y: Y position, in pixels, of the first active pixel in reference
++ * to the first active paxel. Must be an even number.
++ * @size: Size of LSC gain table. Filled when loaded from userspace.
++ */
++struct ispccdc_lsc_config {
++ __u16 offset;
++ __u8 gain_mode_n;
++ __u8 gain_mode_m;
++ __u8 gain_format;
++ __u16 fmtsph;
++ __u16 fmtlnh;
++ __u16 fmtslv;
++ __u16 fmtlnv;
++ __u8 initial_x;
++ __u8 initial_y;
++ __u32 size;
++};
++
++/**
++ * struct ispccdc_bclamp - Structure for Optical & Digital black clamp subtract
++ * @obgain: Optical black average gain.
++ * @obstpixel: Start Pixel w.r.t. HS pulse in Optical black sample.
++ * @oblines: Optical Black Sample lines.
++ * @oblen: Optical Black Sample Length.
++ * @dcsubval: Digital Black Clamp subtract value.
++ */
++struct ispccdc_bclamp {
++ __u8 obgain;
++ __u8 obstpixel;
++ __u8 oblines;
++ __u8 oblen;
++ __u16 dcsubval;
++};
++
++/**
++ * ispccdc_fpc - Structure for FPC
++ * @fpnum: Number of faulty pixels to be corrected in the frame.
++ * @fpcaddr: Memory address of the FPC Table
++ */
++struct ispccdc_fpc {
++ __u16 fpnum;
++ __u32 fpcaddr;
++};
++
++/**
++ * ispccdc_blcomp - Structure for Black Level Compensation parameters.
++ * @b_mg: B/Mg pixels. 2's complement. -128 to +127.
++ * @gb_g: Gb/G pixels. 2's complement. -128 to +127.
++ * @gr_cy: Gr/Cy pixels. 2's complement. -128 to +127.
++ * @r_ye: R/Ye pixels. 2's complement. -128 to +127.
++ */
++struct ispccdc_blcomp {
++ __u8 b_mg;
++ __u8 gb_g;
++ __u8 gr_cy;
++ __u8 r_ye;
++};
++
++/**
++ * struct ispccdc_vp - Structure for Video Port parameters
++ * @bitshift_sel: Video port input select. 3 - bits 12-3, 4 - bits 11-2,
++ * 5 - bits 10-1, 6 - bits 9-0.
++ * @freq_sel: Video port data ready frequency. 1 - 1/3.5, 2 - 1/4.5,
++ * 3 - 1/5.5, 4 - 1/6.5.
++ */
++struct ispccdc_vp {
++ enum vpin bitshift_sel;
++ enum vpif_freq freq_sel;
++};
++
++/**
++ * ispccdc_culling - Structure for Culling parameters.
++ * @v_pattern: Vertical culling pattern.
++ * @h_odd: Horizontal Culling pattern for odd lines.
++ * @h_even: Horizontal Culling pattern for even lines.
++ */
++struct ispccdc_culling {
++ __u8 v_pattern;
++ __u16 h_odd;
++ __u16 h_even;
++};
++
++/**
++ * ispccdc_update_config - Structure for CCDC configuration.
++ * @update: Specifies which CCDC registers should be updated.
++ * @flag: Specifies which CCDC functions should be enabled.
++ * @alawip: Enable/Disable A-Law compression.
++ * @bclamp: Black clamp control register.
++ * @blcomp: Black level compensation value for RGrGbB Pixels. 2's complement.
++ * @fpc: Number of faulty pixels corrected in the frame, address of FPC table.
++ * @cull: Cull control register.
++ * @colptn: Color pattern of the sensor.
++ * @lsc: Pointer to LSC gain table.
++ */
++struct ispccdc_update_config {
++ __u16 update;
++ __u16 flag;
++ enum alaw_ipwidth alawip;
++ struct ispccdc_bclamp *bclamp;
++ struct ispccdc_blcomp *blcomp;
++ struct ispccdc_fpc *fpc;
++ struct ispccdc_lsc_config *lsc_cfg;
++ struct ispccdc_culling *cull;
++ __u32 colptn;
++ __u8 *lsc;
++};
++
++/* Preview configuration */
++
++/*Abstraction layer preview configurations*/
++#define ISP_ABS_PREV_LUMAENH (1 << 0)
++#define ISP_ABS_PREV_INVALAW (1 << 1)
++#define ISP_ABS_PREV_HRZ_MED (1 << 2)
++#define ISP_ABS_PREV_CFA (1 << 3)
++#define ISP_ABS_PREV_CHROMA_SUPP (1 << 4)
++#define ISP_ABS_PREV_WB (1 << 5)
++#define ISP_ABS_PREV_BLKADJ (1 << 6)
++#define ISP_ABS_PREV_RGB2RGB (1 << 7)
++#define ISP_ABS_PREV_COLOR_CONV (1 << 8)
++#define ISP_ABS_PREV_YC_LIMIT (1 << 9)
++#define ISP_ABS_PREV_DEFECT_COR (1 << 10)
++#define ISP_ABS_PREV_GAMMABYPASS (1 << 11)
++#define ISP_ABS_TBL_NF (1 << 12)
++#define ISP_ABS_TBL_REDGAMMA (1 << 13)
++#define ISP_ABS_TBL_GREENGAMMA (1 << 14)
++#define ISP_ABS_TBL_BLUEGAMMA (1 << 15)
++
++#define ISPPRV_NF_TBL_SIZE 64
++#define ISPPRV_CFA_TBL_SIZE 576
++#define ISPPRV_GAMMA_TBL_SIZE 1024
++#define ISPPRV_YENH_TBL_SIZE 128
++
++/**
++ * struct ispprev_hmed - Structure for Horizontal Median Filter.
++ * @odddist: Distance between consecutive pixels of same color in the odd line.
++ * @evendist: Distance between consecutive pixels of same color in the even
++ * line.
++ * @thres: Horizontal median filter threshold.
++ */
++struct ispprev_hmed {
++ __u8 odddist;
++ __u8 evendist;
++ __u8 thres;
++};
++
++/*
++ * Enumeration for CFA Formats supported by preview
++ */
++enum cfa_fmt {
++ CFAFMT_BAYER, CFAFMT_SONYVGA, CFAFMT_RGBFOVEON,
++ CFAFMT_DNSPL, CFAFMT_HONEYCOMB, CFAFMT_RRGGBBFOVEON
++};
++
++/**
++ * struct ispprev_cfa - Structure for CFA Inpterpolation.
++ * @cfafmt: CFA Format Enum value supported by preview.
++ * @cfa_gradthrs_vert: CFA Gradient Threshold - Vertical.
++ * @cfa_gradthrs_horz: CFA Gradient Threshold - Horizontal.
++ * @cfa_table: Pointer to the CFA table.
++ */
++struct ispprev_cfa {
++ enum cfa_fmt cfafmt;
++ __u8 cfa_gradthrs_vert;
++ __u8 cfa_gradthrs_horz;
++ __u32 *cfa_table;
++};
++
++/**
++ * struct ispprev_csup - Structure for Chrominance Suppression.
++ * @gain: Gain.
++ * @thres: Threshold.
++ * @hypf_en: Flag to enable/disable the High Pass Filter.
++ */
++struct ispprev_csup {
++ __u8 gain;
++ __u8 thres;
++ __u8 hypf_en;
++};
++
++/**
++ * struct ispprev_wbal - Structure for White Balance.
++ * @dgain: Digital gain (U10Q8).
++ * @coef3: White balance gain - COEF 3 (U8Q5).
++ * @coef2: White balance gain - COEF 2 (U8Q5).
++ * @coef1: White balance gain - COEF 1 (U8Q5).
++ * @coef0: White balance gain - COEF 0 (U8Q5).
++ */
++struct ispprev_wbal {
++ __u16 dgain;
++ __u8 coef3;
++ __u8 coef2;
++ __u8 coef1;
++ __u8 coef0;
++};
++
++/**
++ * struct ispprev_blkadj - Structure for Black Adjustment.
++ * @red: Black level offset adjustment for Red in 2's complement format
++ * @green: Black level offset adjustment for Green in 2's complement format
++ * @blue: Black level offset adjustment for Blue in 2's complement format
++ */
++struct ispprev_blkadj {
++ /*Black level offset adjustment for Red in 2's complement format */
++ __u8 red;
++ /*Black level offset adjustment for Green in 2's complement format */
++ __u8 green;
++ /* Black level offset adjustment for Blue in 2's complement format */
++ __u8 blue;
++};
++
++/**
++ * struct ispprev_rgbtorgb - Structure for RGB to RGB Blending.
++ * @matrix: Blending values(S12Q8 format)
++ * [RR] [GR] [BR]
++ * [RG] [GG] [BG]
++ * [RB] [GB] [BB]
++ * @offset: Blending offset value for R,G,B in 2's complement integer format.
++ */
++struct ispprev_rgbtorgb {
++ __u16 matrix[3][3];
++ __u16 offset[3];
++};
++
++/**
++ * struct ispprev_csc - Structure for Color Space Conversion from RGB-YCbYCr
++ * @matrix: Color space conversion coefficients(S10Q8)
++ * [CSCRY] [CSCGY] [CSCBY]
++ * [CSCRCB] [CSCGCB] [CSCBCB]
++ * [CSCRCR] [CSCGCR] [CSCBCR]
++ * @offset: CSC offset values for Y offset, CB offset and CR offset respectively
++ */
++struct ispprev_csc {
++ __u16 matrix[RGB_MAX][RGB_MAX];
++ __s16 offset[RGB_MAX];
++};
++
++/**
++ * struct ispprev_yclimit - Structure for Y, C Value Limit.
++ * @minC: Minimum C value
++ * @maxC: Maximum C value
++ * @minY: Minimum Y value
++ * @maxY: Maximum Y value
++ */
++struct ispprev_yclimit {
++ __u8 minC;
++ __u8 maxC;
++ __u8 minY;
++ __u8 maxY;
++};
++
++/**
++ * struct ispprev_dcor - Structure for Defect correction.
++ * @couplet_mode_en: Flag to enable or disable the couplet dc Correction in NF
++ * @detect_correct: Thresholds for correction bit 0:10 detect 16:25 correct
++ */
++struct ispprev_dcor {
++ __u8 couplet_mode_en;
++ __u32 detect_correct[4];
++};
++
++/**
++ * struct ispprev_nf - Structure for Noise Filter
++ * @spread: Spread value to be used in Noise Filter
++ * @table: Pointer to the Noise Filter table
++ */
++struct ispprev_nf {
++ __u8 spread;
++ __u32 table[ISPPRV_NF_TBL_SIZE];
++};
++
++/**
++ * struct ispprv_update_config - Structure for Preview Configuration (user).
++ * @update: Specifies which ISP Preview registers should be updated.
++ * @flag: Specifies which ISP Preview functions should be enabled.
++ * @yen: Pointer to luma enhancement table.
++ * @shading_shift: 3bit value of shift used in shading compensation.
++ * @prev_hmed: Pointer to structure containing the odd and even distance.
++ * between the pixels in the image along with the filter threshold.
++ * @prev_cfa: Pointer to structure containing the CFA interpolation table, CFA.
++ * format in the image, vertical and horizontal gradient threshold.
++ * @csup: Pointer to Structure for Chrominance Suppression coefficients.
++ * @prev_wbal: Pointer to structure for White Balance.
++ * @prev_blkadj: Pointer to structure for Black Adjustment.
++ * @rgb2rgb: Pointer to structure for RGB to RGB Blending.
++ * @prev_csc: Pointer to structure for Color Space Conversion from RGB-YCbYCr.
++ * @yclimit: Pointer to structure for Y, C Value Limit.
++ * @prev_dcor: Pointer to structure for defect correction.
++ * @prev_nf: Pointer to structure for Noise Filter
++ * @red_gamma: Pointer to red gamma correction table.
++ * @green_gamma: Pointer to green gamma correction table.
++ * @blue_gamma: Pointer to blue gamma correction table.
++ */
++struct ispprv_update_config {
++ __u16 update;
++ __u16 flag;
++ void *yen;
++ __u32 shading_shift;
++ struct ispprev_hmed *prev_hmed;
++ struct ispprev_cfa *prev_cfa;
++ struct ispprev_csup *csup;
++ struct ispprev_wbal *prev_wbal;
++ struct ispprev_blkadj *prev_blkadj;
++ struct ispprev_rgbtorgb *rgb2rgb;
++ struct ispprev_csc *prev_csc;
++ struct ispprev_yclimit *yclimit;
++ struct ispprev_dcor *prev_dcor;
++ struct ispprev_nf *prev_nf;
++ __u32 *red_gamma;
++ __u32 *green_gamma;
++ __u32 *blue_gamma;
++};
++
++#endif /* OMAP_ISP_USER_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
new file mode 100644
index 0000000000..4a161729fd
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
@@ -0,0 +1,1875 @@
+From 9ea796fe5383a6961125a6a18185a901fe8627d7 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add ISP frontend (CCDC)
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/ispccdc.c | 1638 +++++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/ispccdc.h | 209 +++++
+ 2 files changed, 1847 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/ispccdc.c
+ create mode 100644 drivers/media/video/isp/ispccdc.h
+
+diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
+new file mode 100644
+index 0000000..2574ea2
+--- /dev/null
++++ b/drivers/media/video/isp/ispccdc.c
+@@ -0,0 +1,1638 @@
++/*
++ * ispccdc.c
++ *
++ * Driver Library for CCDC module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Senthilvadivu Guruswamy <svadivu@ti.com>
++ * Pallavi Kulkarni <p-kulkarni@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/mutex.h>
++#include <linux/module.h>
++#include <linux/uaccess.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "ispccdc.h"
++#include "ispmmu.h"
++
++#define LSC_TABLE_INIT_SIZE 50052
++
++static u32 *fpc_table_add;
++static unsigned long fpc_table_add_m;
++
++/**
++ * struct isp_ccdc - Structure for the CCDC module to store its own information
++ * @ccdc_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
++ * @ccdcout_w: CCDC output width.
++ * @ccdcout_h: CCDC output height.
++ * @ccdcin_w: CCDC input width.
++ * @ccdcin_h: CCDC input height.
++ * @ccdcin_woffset: CCDC input horizontal offset.
++ * @ccdcin_hoffset: CCDC input vertical offset.
++ * @crop_w: Crop width.
++ * @crop_h: Crop weight.
++ * @ccdc_inpfmt: CCDC input format.
++ * @ccdc_outfmt: CCDC output format.
++ * @vpout_en: Video port output enable.
++ * @wen: Data write enable.
++ * @exwen: External data write enable.
++ * @refmt_en: Reformatter enable.
++ * @ccdcslave: CCDC slave mode enable.
++ * @syncif_ipmod: Image
++ * @obclamp_en: Data input format.
++ * @mutexlock: Mutex used to get access to the CCDC.
++ */
++static struct isp_ccdc {
++ u8 ccdc_inuse;
++ u32 ccdcout_w;
++ u32 ccdcout_h;
++ u32 ccdcin_w;
++ u32 ccdcin_h;
++ u32 ccdcin_woffset;
++ u32 ccdcin_hoffset;
++ u32 crop_w;
++ u32 crop_h;
++ u8 ccdc_inpfmt;
++ u8 ccdc_outfmt;
++ u8 vpout_en;
++ u8 wen;
++ u8 exwen;
++ u8 refmt_en;
++ u8 ccdcslave;
++ u8 syncif_ipmod;
++ u8 obclamp_en;
++ u8 pm_state;
++ u8 lsc_enable;
++ int lsc_state;
++ struct mutex mutexlock; /* For checking/modifying ccdc_inuse */
++ u32 wenlog;
++} ispccdc_obj;
++
++static struct ispccdc_lsc_config lsc_config;
++static u8 *lsc_gain_table;
++static unsigned long lsc_ispmmu_addr;
++static int lsc_initialized;
++static u8 *lsc_gain_table_tmp;
++
++/* Structure for saving/restoring CCDC module registers*/
++static struct isp_reg ispccdc_reg_list[] = {
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HD_VD_WID, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PIX_LINES, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE, 0},
++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET, 0},
++ {0, ISP_TOK_TERM, 0}
++};
++
++/**
++ * omap34xx_isp_ccdc_config - Sets CCDC configuration from userspace
++ * @userspace_add: Structure containing CCDC configuration sent from userspace.
++ *
++ * Returns 0 if successful, -EINVAL if the pointer to the configuration
++ * structure is null, or the copy_from_user function fails to copy user space
++ * memory to kernel space memory.
++ **/
++int omap34xx_isp_ccdc_config(void *userspace_add)
++{
++ struct ispccdc_bclamp bclamp_t;
++ struct ispccdc_blcomp blcomp_t;
++ struct ispccdc_fpc fpc_t;
++ struct ispccdc_culling cull_t;
++ struct ispccdc_update_config *ccdc_struct;
++
++ if (userspace_add == NULL)
++ return -EINVAL;
++
++ ccdc_struct = userspace_add;
++
++ if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
++ if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
++ ispccdc_config_alaw(ccdc_struct->alawip);
++ ispccdc_enable_alaw(1);
++ } else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
++ ispccdc_enable_alaw(0);
++
++ if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
++ ispccdc_enable_lpf(1);
++ else
++ ispccdc_enable_lpf(0);
++
++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
++ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
++ ccdc_struct->bclamp,
++ sizeof(struct ispccdc_bclamp)))
++ goto copy_from_user_err;
++
++ ispccdc_enable_black_clamp(1);
++ ispccdc_config_black_clamp(bclamp_t);
++ } else
++ ispccdc_enable_black_clamp(1);
++ } else {
++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
++ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
++ ccdc_struct->bclamp,
++ sizeof(struct ispccdc_bclamp)))
++ goto copy_from_user_err;
++
++ ispccdc_enable_black_clamp(0);
++ ispccdc_config_black_clamp(bclamp_t);
++ }
++ }
++
++ if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
++ if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *)
++ ccdc_struct->blcomp,
++ sizeof(blcomp_t)))
++ goto copy_from_user_err;
++
++ ispccdc_config_black_comp(blcomp_t);
++ }
++
++ if (ISP_ABS_CCDC_FPC & ccdc_struct->flag) {
++ if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
++ if (copy_from_user(&fpc_t, (struct ispccdc_fpc *)
++ ccdc_struct->fpc,
++ sizeof(fpc_t)))
++ goto copy_from_user_err;
++ fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4,
++ GFP_KERNEL | GFP_DMA);
++ if (!fpc_table_add) {
++ printk(KERN_ERR "Cannot allocate memory for"
++ " FPC table");
++ return -ENOMEM;
++ }
++ while (((unsigned long)fpc_table_add & 0xFFFFFFC0)
++ != (unsigned long)fpc_table_add)
++ fpc_table_add++;
++
++ fpc_table_add_m = ispmmu_kmap(virt_to_phys
++ (fpc_table_add),
++ fpc_t.fpnum * 4);
++
++ if (copy_from_user(fpc_table_add, (u32 *)fpc_t.fpcaddr,
++ fpc_t.fpnum * 4))
++ goto copy_from_user_err;
++
++ fpc_t.fpcaddr = fpc_table_add_m;
++ ispccdc_config_fpc(fpc_t);
++ }
++ ispccdc_enable_fpc(1);
++ } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update)
++ ispccdc_enable_fpc(0);
++
++ if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
++ if (copy_from_user(&cull_t, (struct ispccdc_culling *)
++ ccdc_struct->cull,
++ sizeof(cull_t)))
++ goto copy_from_user_err;
++ ispccdc_config_culling(cull_t);
++ }
++
++ if (is_isplsc_activated()) {
++ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
++ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
++ if (copy_from_user(
++ &lsc_config,
++ (struct ispccdc_lsc_config *)
++ ccdc_struct->lsc_cfg,
++ sizeof(struct ispccdc_lsc_config)))
++ goto copy_from_user_err;
++ ispccdc_config_lsc(&lsc_config);
++ }
++ ispccdc_enable_lsc(1);
++ } else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
++ ispccdc_enable_lsc(0);
++ }
++ if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
++ if (copy_from_user(lsc_gain_table,
++ ccdc_struct->lsc, lsc_config.size))
++ goto copy_from_user_err;
++ ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
++ }
++ }
++
++ if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
++ ispccdc_config_imgattr(ccdc_struct->colptn);
++
++ return 0;
++
++copy_from_user_err:
++ printk(KERN_ERR "CCDC Config:Copy From User Error");
++ return -EINVAL ;
++}
++EXPORT_SYMBOL(omap34xx_isp_ccdc_config);
++
++/**
++ * Set the value to be used for CCDC_CFG.WENLOG.
++ * w - Value of wenlog.
++ */
++void ispccdc_set_wenlog(u32 wenlog)
++{
++ ispccdc_obj.wenlog = wenlog;
++}
++EXPORT_SYMBOL(ispccdc_set_wenlog);
++
++/**
++ * ispccdc_request - Reserves the CCDC module.
++ *
++ * Reserves the CCDC module and assures that is used only once at a time.
++ *
++ * Returns 0 if successful, or -EBUSY if CCDC module is busy.
++ **/
++int ispccdc_request(void)
++{
++ mutex_lock(&ispccdc_obj.mutexlock);
++ if (ispccdc_obj.ccdc_inuse) {
++ mutex_unlock(&ispccdc_obj.mutexlock);
++ DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy\n");
++ return -EBUSY;
++ }
++
++ ispccdc_obj.ccdc_inuse = 1;
++ mutex_unlock(&ispccdc_obj.mutexlock);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_CCDC_RAM_EN |
++ ISPCTRL_CCDC_CLK_EN |
++ ISPCTRL_SBL_WR1_RAM_EN);
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_request);
++
++/**
++ * ispccdc_free - Frees the CCDC module.
++ *
++ * Frees the CCDC module so it can be used by another process.
++ *
++ * Returns 0 if successful, or -EINVAL if module has been already freed.
++ **/
++int ispccdc_free(void)
++{
++ mutex_lock(&ispccdc_obj.mutexlock);
++ if (!ispccdc_obj.ccdc_inuse) {
++ mutex_unlock(&ispccdc_obj.mutexlock);
++ DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n");
++ return -EINVAL;
++ }
++
++ ispccdc_obj.ccdc_inuse = 0;
++ mutex_unlock(&ispccdc_obj.mutexlock);
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
++ ~(ISPCTRL_CCDC_CLK_EN |
++ ISPCTRL_CCDC_RAM_EN |
++ ISPCTRL_SBL_WR1_RAM_EN));
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_free);
++
++/**
++ * ispccdc_free_lsc - Frees Lens Shading Compensation table
++ *
++ * Always returns 0.
++ **/
++static int ispccdc_free_lsc(void)
++{
++ if (!lsc_ispmmu_addr)
++ return 0;
++
++ ispccdc_enable_lsc(0);
++ lsc_initialized = 0;
++ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
++ ispmmu_kunmap(lsc_ispmmu_addr);
++ kfree(lsc_gain_table);
++ return 0;
++}
++
++/**
++ * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
++ * @table_size: LSC gain table size.
++ *
++ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
++ * table_size is zero.
++ **/
++static int ispccdc_allocate_lsc(u32 table_size)
++{
++ if (table_size == 0)
++ return -EINVAL;
++
++ if ((lsc_config.size >= table_size) && lsc_gain_table)
++ return 0;
++
++ ispccdc_free_lsc();
++
++ lsc_gain_table = kmalloc(table_size, GFP_KERNEL | GFP_DMA);
++
++ if (!lsc_gain_table) {
++ printk(KERN_ERR "Cannot allocate memory for gain tables \n");
++ return -ENOMEM;
++ }
++
++ lsc_ispmmu_addr = ispmmu_kmap(virt_to_phys(lsc_gain_table), table_size);
++ if (lsc_ispmmu_addr <= 0) {
++ printk(KERN_ERR "Cannot map memory for gain tables \n");
++ kfree(lsc_gain_table);
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++/**
++ * ispccdc_program_lsc - Program Lens Shading Compensation table.
++ * @table_size: LSC gain table size.
++ *
++ * Returns 0 if successful, or -EINVAL if there's no mapped address for the
++ * table yet.
++ **/
++static int ispccdc_program_lsc(void)
++{
++ if (!lsc_ispmmu_addr)
++ return -EINVAL;
++
++ if (lsc_initialized)
++ return 0;
++
++ isp_reg_writel(lsc_ispmmu_addr, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_TABLE_BASE);
++ lsc_initialized = 1;
++ return 0;
++}
++
++/**
++ * ispccdc_load_lsc - Load Lens Shading Compensation table.
++ * @table_addr: LSC gain table MMU Mapped address.
++ * @table_size: LSC gain table size.
++ *
++ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
++ * table_size is zero.
++ **/
++int ispccdc_load_lsc(u8 *table_addr, u32 table_size)
++{
++ int ret;
++
++ if (!is_isplsc_activated())
++ return 0;
++
++ if (!table_addr)
++ return -EINVAL;
++
++ ret = ispccdc_allocate_lsc(table_size);
++ if (ret)
++ return ret;
++
++ if (table_addr != lsc_gain_table)
++ memcpy(lsc_gain_table, table_addr, table_size);
++ ret = ispccdc_program_lsc();
++ if (ret)
++ return ret;
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_load_lsc);
++
++/**
++ * ispccdc_config_lsc - Configures the lens shading compensation module
++ * @lsc_cfg: LSC configuration structure
++ **/
++void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg)
++{
++ int reg;
++
++ if (!is_isplsc_activated())
++ return;
++
++ ispccdc_enable_lsc(0);
++ isp_reg_writel(lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_TABLE_OFFSET);
++
++ reg = 0;
++ reg |= lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
++ reg |= lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
++ reg |= lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
++
++ reg = 0;
++ reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
++ reg |= lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
++ reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
++ reg |= lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL);
++}
++EXPORT_SYMBOL(ispccdc_config_lsc);
++
++int __ispccdc_enable_lsc(u8 enable)
++{
++ if (!is_isplsc_activated())
++ return -ENODEV;
++
++ if (enable) {
++ if (!ispccdc_busy()) {
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
++ ISPCTRL_SBL_SHARED_RPORTB
++ | ISPCTRL_SBL_RD_RAM_EN);
++
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_CONFIG, 0x1);
++
++ ispccdc_obj.lsc_state = 1;
++ } else {
++ /* Postpone enabling LSC */
++ ispccdc_obj.lsc_enable = 1;
++ return -EBUSY;
++ }
++ } else {
++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0xFFFE);
++ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0;
++ }
++
++ return 0;
++}
++
++/**
++ * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
++ * @enable: 0 Disables LSC, 1 Enables LSC.
++ **/
++void ispccdc_enable_lsc(u8 enable)
++{
++ if (__ispccdc_enable_lsc(enable)) {
++ if (enable)
++ ispccdc_obj.lsc_state = 1;
++ else
++ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0;
++ }
++}
++EXPORT_SYMBOL(ispccdc_enable_lsc);
++
++void ispccdc_lsc_error_handler(void)
++{
++ int lsc_enable = ispccdc_obj.lsc_state;
++
++ ispccdc_enable_lsc(0);
++
++ ispccdc_obj.lsc_enable = lsc_enable;
++}
++
++/**
++ * ispccdc_config_crop - Configures crop parameters for the ISP CCDC.
++ * @left: Left offset of the crop area.
++ * @top: Top offset of the crop area.
++ * @height: Height of the crop area.
++ * @width: Width of the crop area.
++ *
++ * The following restrictions are applied for the crop settings. If incoming
++ * values do not follow these restrictions then we map the settings to the
++ * closest acceptable crop value.
++ * 1) Left offset is always odd. This can be avoided if we enable byte swap
++ * option for incoming data into CCDC.
++ * 2) Top offset is always even.
++ * 3) Crop height is always even.
++ * 4) Crop width is always a multiple of 16 pixels
++ **/
++void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width)
++{
++ ispccdc_obj.ccdcin_woffset = left + (left % 2);
++ ispccdc_obj.ccdcin_hoffset = top + (top % 2);
++
++ ispccdc_obj.crop_w = width - (width % 16);
++ ispccdc_obj.crop_h = height + (height % 2);
++
++ DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
++ ispccdc_obj.ccdcin_woffset,
++ ispccdc_obj.ccdcin_hoffset,
++ ispccdc_obj.crop_w,
++ ispccdc_obj.crop_h);
++}
++
++/**
++ * ispccdc_config_datapath - Specifies the input and output modules for CCDC.
++ * @input: Indicates the module that inputs the image to the CCDC.
++ * @output: Indicates the module to which the CCDC outputs the image.
++ *
++ * Configures the default configuration for the CCDC to work with.
++ *
++ * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
++ * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
++ *
++ * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1),
++ * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4).
++ *
++ * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
++ * or output values.
++ **/
++int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output)
++{
++ u32 syn_mode = 0;
++ struct ispccdc_vp vpcfg;
++ struct ispccdc_syncif syncif;
++ struct ispccdc_bclamp blkcfg;
++
++ u32 colptn = ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
++
++ /* CCDC does not convert the image format */
++ if ((input == CCDC_RAW || input == CCDC_OTHERS) &&
++ output == CCDC_YUV_RSZ) {
++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC I/O Combination\n");
++ return -EINVAL;
++ }
++
++ syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
++
++ switch (output) {
++ case CCDC_YUV_RSZ:
++ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
++ syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
++ break;
++
++ case CCDC_YUV_MEM_RSZ:
++ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
++ ispccdc_obj.wen = 1;
++ syn_mode |= ISPCCDC_SYN_MODE_WEN;
++ break;
++
++ case CCDC_OTHERS_VP:
++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
++ syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
++ vpcfg.bitshift_sel = BIT9_0;
++ vpcfg.freq_sel = PIXCLKBY2;
++ ispccdc_config_vp(vpcfg);
++ ispccdc_enable_vp(1);
++ break;
++
++ case CCDC_OTHERS_MEM:
++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
++ syn_mode |= ISPCCDC_SYN_MODE_WEN;
++ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
++ ~ISPCCDC_CFG_WENLOG);
++ vpcfg.bitshift_sel = BIT11_2;
++ vpcfg.freq_sel = PIXCLKBY2;
++ ispccdc_config_vp(vpcfg);
++ ispccdc_enable_vp(0);
++ break;
++
++ case CCDC_OTHERS_VP_MEM:
++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
++ syn_mode |= ISPCCDC_SYN_MODE_WEN;
++ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
++
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
++ ~ISPCCDC_CFG_WENLOG,
++ ispccdc_obj.wenlog);
++ vpcfg.bitshift_sel = BIT9_0;
++ vpcfg.freq_sel = PIXCLKBY2;
++ ispccdc_config_vp(vpcfg);
++ ispccdc_enable_vp(1);
++ break;
++ default:
++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
++ return -EINVAL;
++ };
++
++ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
++
++ switch (input) {
++ case CCDC_RAW:
++ syncif.ccdc_mastermode = 0;
++ syncif.datapol = 0;
++ syncif.datsz = DAT10;
++ syncif.fldmode = 0;
++ syncif.fldout = 0;
++ syncif.fldpol = 0;
++ syncif.fldstat = 0;
++ syncif.hdpol = 0;
++ syncif.ipmod = RAW;
++ syncif.vdpol = 0;
++ ispccdc_config_sync_if(syncif);
++ ispccdc_config_imgattr(colptn);
++ blkcfg.dcsubval = 64;
++ ispccdc_config_black_clamp(blkcfg);
++ if (is_isplsc_activated()) {
++ ispccdc_config_lsc(&lsc_config);
++ ispccdc_load_lsc(lsc_gain_table_tmp,
++ LSC_TABLE_INIT_SIZE);
++ }
++
++ break;
++ case CCDC_YUV_SYNC:
++ syncif.ccdc_mastermode = 0;
++ syncif.datapol = 0;
++ syncif.datsz = DAT8;
++ syncif.fldmode = 0;
++ syncif.fldout = 0;
++ syncif.fldpol = 0;
++ syncif.fldstat = 0;
++ syncif.hdpol = 0;
++ syncif.ipmod = YUV16;
++ syncif.vdpol = 1;
++ ispccdc_config_imgattr(0);
++ ispccdc_config_sync_if(syncif);
++ blkcfg.dcsubval = 0;
++ ispccdc_config_black_clamp(blkcfg);
++ break;
++ case CCDC_YUV_BT:
++ break;
++ case CCDC_OTHERS:
++ break;
++ default:
++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
++ return -EINVAL;
++ }
++
++ ispccdc_obj.ccdc_inpfmt = input;
++ ispccdc_obj.ccdc_outfmt = output;
++ ispccdc_print_status();
++ isp_print_status();
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_config_datapath);
++
++/**
++ * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
++ * @syncif: Structure containing the sync parameters like field state, CCDC in
++ * master/slave mode, raw/yuv data, polarity of data, field, hs, vs
++ * signals.
++ **/
++void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
++{
++ u32 syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
++
++ syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
++
++ if (syncif.fldstat)
++ syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
++
++ syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
++ ispccdc_obj.syncif_ipmod = syncif.ipmod;
++
++ switch (syncif.ipmod) {
++ case RAW:
++ break;
++ case YUV16:
++ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
++ break;
++ case YUV8:
++ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
++ break;
++ };
++
++ syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
++ switch (syncif.datsz) {
++ case DAT8:
++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
++ break;
++ case DAT10:
++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
++ break;
++ case DAT11:
++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
++ break;
++ case DAT12:
++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
++ break;
++ };
++
++ if (syncif.fldmode)
++ syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
++
++ if (syncif.datapol)
++ syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
++
++ if (syncif.fldpol)
++ syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
++
++ if (syncif.hdpol)
++ syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
++
++ if (syncif.vdpol)
++ syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
++ else
++ syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
++
++ if (syncif.ccdc_mastermode) {
++ syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
++ isp_reg_writel(syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
++ | syncif.vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_HD_VD_WID);
++
++ isp_reg_writel(syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
++ | syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_PIX_LINES);
++ } else
++ syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
++ ISPCCDC_SYN_MODE_VDHDOUT);
++
++ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
++
++ if (!(syncif.bt_r656_en)) {
++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
++ ~ISPCCDC_REC656IF_R656ON);
++ }
++}
++EXPORT_SYMBOL(ispccdc_config_sync_if);
++
++/**
++ * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
++ * @bclamp: Structure containing the optical black average gain, optical black
++ * sample length, sample lines, and the start pixel position of the
++ * samples w.r.t the HS pulse.
++ * Configures the clamp parameters in CCDC. Either if its being used the
++ * optical black clamp, or the digital clamp. If its a digital clamp, then
++ * assures to put a valid DC substraction level.
++ *
++ * Returns always 0 when completed.
++ **/
++int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp)
++{
++ u32 bclamp_val = 0;
++
++ if (ispccdc_obj.obclamp_en) {
++ bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
++ bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
++ bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
++ bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
++ isp_reg_writel(bclamp_val, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_CLAMP);
++ } else {
++ if (omap_rev() < OMAP3430_REV_ES2_0)
++ if (ispccdc_obj.syncif_ipmod == YUV16 ||
++ ispccdc_obj.syncif_ipmod == YUV8 ||
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_REC656IF) &
++ ISPCCDC_REC656IF_R656ON)
++ bclamp.dcsubval = 0;
++ isp_reg_writel(bclamp.dcsubval, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_DCSUB);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_config_black_clamp);
++
++/**
++ * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
++ * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
++ *
++ * Enables or disables the optical black clamp. When disabled, the digital
++ * clamp operates.
++ **/
++void ispccdc_enable_black_clamp(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
++ ~ISPCCDC_CLAMP_CLAMPEN,
++ enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
++ ispccdc_obj.obclamp_en = enable;
++}
++EXPORT_SYMBOL(ispccdc_enable_black_clamp);
++
++/**
++ * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
++ * @fpc: Structure containing the number of faulty pixels corrected in the
++ * frame, address of the FPC table.
++ *
++ * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
++ * boundary.
++ **/
++int ispccdc_config_fpc(struct ispccdc_fpc fpc)
++{
++ u32 fpc_val = 0;
++
++ fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
++
++ if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
++ isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN),
++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
++ isp_reg_writel(fpc.fpcaddr,
++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
++ } else {
++ DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_config_fpc);
++
++/**
++ * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
++ * @enable: 0 Disables FPC, 1 Enables FPC.
++ **/
++void ispccdc_enable_fpc(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
++ ~ISPCCDC_FPC_FPCEN,
++ enable ? ISPCCDC_FPC_FPCEN : 0);
++}
++EXPORT_SYMBOL(ispccdc_enable_fpc);
++
++/**
++ * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
++ * @blcomp: Structure containing the black level compensation value for RGrGbB
++ * pixels. in 2's complement.
++ **/
++void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp)
++{
++ u32 blcomp_val = 0;
++
++ blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
++ blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
++ blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
++ blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
++
++ isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
++}
++EXPORT_SYMBOL(ispccdc_config_black_comp);
++
++/**
++ * ispccdc_config_vp - Configures the Video Port Configuration parameters.
++ * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
++ * format.
++ **/
++void ispccdc_config_vp(struct ispccdc_vp vpcfg)
++{
++ u32 fmtcfg_vp = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
++
++ fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCF_VPIF_FRQ_MASK;
++
++ switch (vpcfg.bitshift_sel) {
++ case BIT9_0:
++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
++ break;
++ case BIT10_1:
++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
++ break;
++ case BIT11_2:
++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
++ break;
++ case BIT12_3:
++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
++ break;
++ };
++ switch (vpcfg.freq_sel) {
++ case PIXCLKBY2:
++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY2;
++ break;
++ case PIXCLKBY3_5:
++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY3;
++ break;
++ case PIXCLKBY4_5:
++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY4;
++ break;
++ case PIXCLKBY5_5:
++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY5;
++ break;
++ case PIXCLKBY6_5:
++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY6;
++ break;
++ };
++ isp_reg_writel(fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
++}
++EXPORT_SYMBOL(ispccdc_config_vp);
++
++/**
++ * ispccdc_enable_vp - Enables the Video Port.
++ * @enable: 0 Disables VP, 1 Enables VP
++ **/
++void ispccdc_enable_vp(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
++ ~ISPCCDC_FMTCFG_VPEN,
++ enable ? ISPCCDC_FMTCFG_VPEN : 0);
++}
++EXPORT_SYMBOL(ispccdc_enable_vp);
++
++/**
++ * ispccdc_config_reformatter - Configures the Reformatter.
++ * @refmt: Structure containing the memory address to format and the bit fields
++ * for the reformatter registers.
++ *
++ * Configures the Reformatter register values if line alternating is disabled.
++ * Else, just enabling line alternating is enough.
++ **/
++void ispccdc_config_reformatter(struct ispccdc_refmt refmt)
++{
++ u32 fmtcfg_val = 0;
++
++ fmtcfg_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
++
++ if (refmt.lnalt)
++ fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
++ else {
++ fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT;
++ fmtcfg_val &= 0xFFFFF003;
++ fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT;
++ fmtcfg_val |= refmt.plen_even <<
++ ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT;
++ fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT;
++
++ isp_reg_writel(refmt.prgeven0, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_PRGEVEN0);
++ isp_reg_writel(refmt.prgeven1, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_PRGEVEN1);
++ isp_reg_writel(refmt.prgodd0, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_PRGODD0);
++ isp_reg_writel(refmt.prgodd1, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_PRGODD1);
++ isp_reg_writel(refmt.fmtaddr0, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR0);
++ isp_reg_writel(refmt.fmtaddr1, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR1);
++ isp_reg_writel(refmt.fmtaddr2, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR2);
++ isp_reg_writel(refmt.fmtaddr3, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR3);
++ isp_reg_writel(refmt.fmtaddr4, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR4);
++ isp_reg_writel(refmt.fmtaddr5, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR5);
++ isp_reg_writel(refmt.fmtaddr6, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR6);
++ isp_reg_writel(refmt.fmtaddr7, OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_ADDR7);
++ }
++ isp_reg_writel(fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
++}
++EXPORT_SYMBOL(ispccdc_config_reformatter);
++
++/**
++ * ispccdc_enable_reformatter - Enables the Reformatter.
++ * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
++ **/
++void ispccdc_enable_reformatter(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
++ ~ISPCCDC_FMTCFG_FMTEN,
++ enable ? ISPCCDC_FMTCFG_FMTEN : 0);
++ ispccdc_obj.refmt_en = enable;
++}
++EXPORT_SYMBOL(ispccdc_enable_reformatter);
++
++/**
++ * ispccdc_config_culling - Configures the culling parameters.
++ * @cull: Structure containing the vertical culling pattern, and horizontal
++ * culling pattern for odd and even lines.
++ **/
++void ispccdc_config_culling(struct ispccdc_culling cull)
++{
++ u32 culling_val = 0;
++
++ culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
++ culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
++ culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
++
++ isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING);
++}
++EXPORT_SYMBOL(ispccdc_config_culling);
++
++/**
++ * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
++ * @enable: 0 Disables LPF, 1 Enables LPF
++ **/
++void ispccdc_enable_lpf(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
++ ~ISPCCDC_SYN_MODE_LPF,
++ enable ? ISPCCDC_SYN_MODE_LPF : 0);
++}
++EXPORT_SYMBOL(ispccdc_enable_lpf);
++
++/**
++ * ispccdc_config_alaw - Configures the input width for A-law.
++ * @ipwidth: Input width for A-law
++ **/
++void ispccdc_config_alaw(enum alaw_ipwidth ipwidth)
++{
++ isp_reg_writel(ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
++}
++EXPORT_SYMBOL(ispccdc_config_alaw);
++
++/**
++ * ispccdc_enable_alaw - Enables the A-law compression.
++ * @enable: 0 - Disables A-law, 1 - Enables A-law
++ **/
++void ispccdc_enable_alaw(u8 enable)
++{
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
++ ~ISPCCDC_ALAW_CCDTBL,
++ enable ? ISPCCDC_ALAW_CCDTBL : 0);
++}
++EXPORT_SYMBOL(ispccdc_enable_alaw);
++
++/**
++ * ispccdc_config_imgattr - Configures the sensor image specific attributes.
++ * @colptn: Color pattern of the sensor.
++ **/
++void ispccdc_config_imgattr(u32 colptn)
++{
++ isp_reg_writel(colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
++}
++EXPORT_SYMBOL(ispccdc_config_imgattr);
++
++void ispccdc_config_shadow_registers(void)
++{
++ if (ispccdc_obj.lsc_enable) {
++ ispccdc_enable_lsc(1);
++ ispccdc_obj.lsc_enable = 0;
++ }
++}
++
++/**
++ * ispccdc_try_size - Checks if requested Input/output dimensions are valid
++ * @input_w: input width for the CCDC in number of pixels per line
++ * @input_h: input height for the CCDC in number of lines
++ * @output_w: output width from the CCDC in number of pixels per line
++ * @output_h: output height for the CCDC in number of lines
++ *
++ * Calculates the number of pixels cropped if the reformater is disabled,
++ * Fills up the output width and height variables in the isp_ccdc structure.
++ *
++ * Returns 0 if successful, or -EINVAL if the input width is less than 2 pixels
++ **/
++int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
++{
++ if (input_w < 32 || input_h < 32) {
++ DPRINTK_ISPCCDC("ISP_ERR: CCDC cannot handle input width less"
++ " than 32 pixels or height less than 32\n");
++ return -EINVAL;
++ }
++
++ if (ispccdc_obj.crop_w)
++ *output_w = ispccdc_obj.crop_w;
++ else
++ *output_w = input_w;
++
++ if (ispccdc_obj.crop_h)
++ *output_h = ispccdc_obj.crop_h;
++ else
++ *output_h = input_h;
++
++ if (!ispccdc_obj.refmt_en
++ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_MEM
++ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_VP_MEM)
++ *output_h -= 1;
++
++ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM
++ || ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
++ if (*output_w % 16) {
++ *output_w -= (*output_w % 16);
++ *output_w += 16;
++ }
++ }
++
++ ispccdc_obj.ccdcout_w = *output_w;
++ ispccdc_obj.ccdcout_h = *output_h;
++ ispccdc_obj.ccdcin_w = input_w;
++ ispccdc_obj.ccdcin_h = input_h;
++
++ DPRINTK_ISPCCDC("try size: ccdcin_w=%u,ccdcin_h=%u,ccdcout_w=%u,"
++ " ccdcout_h=%u\n",
++ ispccdc_obj.ccdcin_w,
++ ispccdc_obj.ccdcin_h,
++ ispccdc_obj.ccdcout_w,
++ ispccdc_obj.ccdcout_h);
++
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_try_size);
++
++/**
++ * ispccdc_config_size - Configure the dimensions of the CCDC input/output
++ * @input_w: input width for the CCDC in number of pixels per line
++ * @input_h: input height for the CCDC in number of lines
++ * @output_w: output width from the CCDC in number of pixels per line
++ * @output_h: output height for the CCDC in number of lines
++ *
++ * Configures the appropriate values stored in the isp_ccdc structure to
++ * HORZ/VERT_INFO registers and the VP_OUT depending on whether the image
++ * is stored in memory or given to the another module in the ISP pipeline.
++ *
++ * Returns 0 if successful, or -EINVAL if try_size was not called before to
++ * validate the requested dimensions.
++ **/
++int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
++{
++ DPRINTK_ISPCCDC("config size: input_w=%u, input_h=%u, output_w=%u,"
++ " output_h=%u\n",
++ input_w, input_h,
++ output_w, output_h);
++ if (output_w != ispccdc_obj.ccdcout_w
++ || output_h != ispccdc_obj.ccdcout_h) {
++ DPRINTK_ISPCCDC("ISP_ERR : ispccdc_try_size should"
++ " be called before config size\n");
++ return -EINVAL;
++ }
++
++ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP) {
++ isp_reg_writel((ispccdc_obj.ccdcin_woffset <<
++ ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
++ (ispccdc_obj.ccdcin_w <<
++ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_HORZ);
++ isp_reg_writel((ispccdc_obj.ccdcin_hoffset <<
++ ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
++ (ispccdc_obj.ccdcin_h <<
++ ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_VERT);
++ isp_reg_writel((ispccdc_obj.ccdcout_w <<
++ ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
++ (ispccdc_obj.ccdcout_h - 1) <<
++ ISPCCDC_VP_OUT_VERT_NUM_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VP_OUT);
++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 25) &
++ ISPCCDC_VDINT_0_MASK) <<
++ ISPCCDC_VDINT_0_SHIFT) |
++ ((50 & ISPCCDC_VDINT_1_MASK) <<
++ ISPCCDC_VDINT_1_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VDINT);
++
++ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) {
++ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
++ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
++ | ((ispccdc_obj.ccdcout_w - 1)
++ << ISPCCDC_HORZ_INFO_NPH_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_HORZ_INFO);
++ } else {
++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
++ | ((ispccdc_obj.ccdcout_w - 1)
++ << ISPCCDC_HORZ_INFO_NPH_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_HORZ_INFO);
++ }
++ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_START);
++ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
++ ISPCCDC_VERT_LINES_NLV_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_LINES);
++
++ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
++ ISPCCDC_VDINT_0_MASK) <<
++ ISPCCDC_VDINT_0_SHIFT) |
++ ((100 & ISPCCDC_VDINT_1_MASK) <<
++ ISPCCDC_VDINT_1_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VDINT);
++ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
++ isp_reg_writel((0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
++ (ispccdc_obj.ccdcin_w <<
++ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_HORZ);
++ isp_reg_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
++ ((ispccdc_obj.ccdcin_h) <<
++ ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_FMT_VERT);
++ isp_reg_writel((ispccdc_obj.ccdcout_w
++ << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
++ ((ispccdc_obj.ccdcout_h - 1) <<
++ ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VP_OUT);
++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
++ ((ispccdc_obj.ccdcout_w - 1) <<
++ ISPCCDC_HORZ_INFO_NPH_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_HORZ_INFO);
++ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_START);
++ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
++ ISPCCDC_VERT_LINES_NLV_SHIFT,
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_LINES);
++ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
++ ISPCCDC_VDINT_0_MASK) <<
++ ISPCCDC_VDINT_0_SHIFT) |
++ ((100 & ISPCCDC_VDINT_1_MASK) <<
++ ISPCCDC_VDINT_1_SHIFT),
++ OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VDINT);
++ }
++
++ if (is_isplsc_activated()) {
++ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
++ ispccdc_config_lsc(&lsc_config);
++ ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
++ }
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_config_size);
++
++/**
++ * ispccdc_config_outlineoffset - Configures the output line offset
++ * @offset: Must be twice the Output width and aligned on 32 byte boundary
++ * @oddeven: Specifies the odd/even line pattern to be chosen to store the
++ * output.
++ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
++ *
++ * - Configures the output line offset when stored in memory
++ * - Sets the odd/even line pattern to store the output
++ * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
++ * - Configures the number of even and odd line fields in case of rearranging
++ * the lines.
++ *
++ * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
++ * boundary.
++ **/
++int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines)
++{
++ if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
++ isp_reg_writel((offset & 0xFFFF), OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_HSIZE_OFF);
++ } else {
++ DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
++ " boundary\n");
++ return -EINVAL;
++ }
++
++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ ~ISPCCDC_SDOFST_FINV);
++
++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ ~ISPCCDC_SDOFST_FOFST_4L);
++
++ switch (oddeven) {
++ case EVENEVEN:
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
++ break;
++ case ODDEVEN:
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
++ break;
++ case EVENODD:
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
++ break;
++ case ODDODD:
++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++EXPORT_SYMBOL(ispccdc_config_outlineoffset);
++
++/**
++ * ispccdc_set_outaddr - Sets the memory address where the output will be saved
++ * @addr: 32-bit memory address aligned on 32 byte boundary.
++ *
++ * Sets the memory address where the output will be saved.
++ *
++ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
++ * boundary.
++ **/
++int ispccdc_set_outaddr(u32 addr)
++{
++ if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
++ isp_reg_writel(addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
++ return 0;
++ } else {
++ DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
++ " boundary\n");
++ return -EINVAL;
++ }
++
++}
++EXPORT_SYMBOL(ispccdc_set_outaddr);
++
++void __ispccdc_enable(u8 enable)
++{
++ if (enable) {
++ if (ispccdc_obj.lsc_enable
++ && ispccdc_obj.ccdc_inpfmt == CCDC_RAW)
++ ispccdc_enable_lsc(1);
++
++ } else {
++ ispccdc_obj.lsc_enable = ispccdc_obj.lsc_state;
++ }
++
++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR, ~ISPCCDC_PCR_EN,
++ enable ? ISPCCDC_PCR_EN : 0);
++}
++
++/**
++ * ispccdc_enable - Enables the CCDC module.
++ * @enable: 0 Disables CCDC, 1 Enables CCDC
++ *
++ * Client should configure all the sub modules in CCDC before this.
++ **/
++void ispccdc_enable(u8 enable)
++{
++ __ispccdc_enable(enable);
++ ispccdc_obj.pm_state = enable;
++}
++EXPORT_SYMBOL(ispccdc_enable);
++
++/**
++ * ispccdc_suspend - Suspend the CCDC module.
++ **/
++void ispccdc_suspend(void)
++{
++ if (ispccdc_obj.pm_state) {
++ if (ispccdc_obj.lsc_state)
++ __ispccdc_enable_lsc(0);
++ else if (ispccdc_obj.lsc_enable) {
++ ispccdc_obj.lsc_state = 1;
++ ispccdc_obj.lsc_enable = 0;
++ }
++ __ispccdc_enable(0);
++ }
++}
++EXPORT_SYMBOL(ispccdc_suspend);
++
++/**
++ * ispccdc_resume - Resume the CCDC module.
++ **/
++void ispccdc_resume(void)
++{
++ if (ispccdc_obj.pm_state) {
++ if (ispccdc_obj.lsc_state)
++ __ispccdc_enable_lsc(1);
++ __ispccdc_enable(1);
++ }
++}
++EXPORT_SYMBOL(ispccdc_resume);
++
++/*
++ * Returns zero if the CCDC is idle and the image has been written to
++ * memory, too.
++ */
++int ispccdc_sbl_busy(void)
++{
++ return ispccdc_busy()
++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
++ ISPSBL_CCDC_WR_0_DATA_READY)
++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
++ ISPSBL_CCDC_WR_0_DATA_READY)
++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
++ ISPSBL_CCDC_WR_0_DATA_READY)
++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
++ ISPSBL_CCDC_WR_0_DATA_READY);
++}
++EXPORT_SYMBOL(ispccdc_sbl_busy);
++
++/**
++ * ispccdc_busy - Gets busy state of the CCDC.
++ **/
++int ispccdc_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
++ ISPCCDC_PCR_BUSY;
++}
++EXPORT_SYMBOL(ispccdc_busy);
++
++/**
++ * ispccdc_save_context - Saves the values of the CCDC module registers
++ **/
++void ispccdc_save_context(void)
++{
++ DPRINTK_ISPCCDC("Saving context\n");
++ isp_save_context(ispccdc_reg_list);
++}
++EXPORT_SYMBOL(ispccdc_save_context);
++
++/**
++ * ispccdc_restore_context - Restores the values of the CCDC module registers
++ **/
++void ispccdc_restore_context(void)
++{
++ DPRINTK_ISPCCDC("Restoring context\n");
++ isp_restore_context(ispccdc_reg_list);
++}
++EXPORT_SYMBOL(ispccdc_restore_context);
++
++/**
++ * ispccdc_print_status - Prints the values of the CCDC Module registers
++ *
++ * Also prints other debug information stored in the CCDC module.
++ **/
++void ispccdc_print_status(void)
++{
++ if (!is_ispccdc_debug_enabled())
++ return;
++
++ DPRINTK_ISPCCDC("Module in use =%d\n", ispccdc_obj.ccdc_inuse);
++ DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n",
++ ispccdc_obj.ccdcin_w,
++ ispccdc_obj.ccdcin_h);
++ DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n",
++ ispccdc_obj.ccdcout_w,
++ ispccdc_obj.ccdcout_h);
++ DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR));
++ DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ switch (ispccdc_obj.ccdc_inpfmt) {
++ case CCDC_RAW:
++ DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
++ break;
++ case CCDC_YUV_SYNC:
++ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
++ break;
++ case CCDC_YUV_BT:
++ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
++ break;
++ }
++
++ switch (ispccdc_obj.ccdc_outfmt) {
++ case CCDC_OTHERS_VP:
++ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
++ break;
++ case CCDC_OTHERS_MEM:
++ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
++ break;
++ case CCDC_YUV_RSZ:
++ DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
++ break;
++ }
++
++ DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
++ DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
++ DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
++ DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
++ DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_START));
++ DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_LINES));
++ DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING));
++ DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
++ DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST));
++ DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
++ DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP));
++ DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN));
++ DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
++ DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT));
++ DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
++ DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
++ DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ));
++ DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT));
++ DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_CONFIG));
++ DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_INITIAL));
++ DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_TABLE_BASE));
++ DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_LSC_TABLE_OFFSET));
++}
++EXPORT_SYMBOL(ispccdc_print_status);
++
++/**
++ * isp_ccdc_init - CCDC module initialization.
++ *
++ * Always returns 0
++ **/
++int __init isp_ccdc_init(void)
++{
++ ispccdc_obj.ccdc_inuse = 0;
++ ispccdc_config_crop(0, 0, 0, 0);
++ mutex_init(&ispccdc_obj.mutexlock);
++
++ if (is_isplsc_activated()) {
++ lsc_gain_table_tmp = kmalloc(LSC_TABLE_INIT_SIZE, GFP_KERNEL |
++ GFP_DMA);
++ memset(lsc_gain_table_tmp, 0x40, LSC_TABLE_INIT_SIZE);
++ lsc_config.initial_x = 0;
++ lsc_config.initial_y = 0;
++ lsc_config.gain_mode_n = 0x6;
++ lsc_config.gain_mode_m = 0x6;
++ lsc_config.gain_format = 0x4;
++ lsc_config.offset = 0x60;
++ lsc_config.size = LSC_TABLE_INIT_SIZE;
++ ispccdc_obj.lsc_enable = 1;
++ }
++
++ return 0;
++}
++
++/**
++ * isp_ccdc_cleanup - CCDC module cleanup.
++ **/
++void isp_ccdc_cleanup(void)
++{
++ if (is_isplsc_activated()) {
++ ispccdc_free_lsc();
++ kfree(lsc_gain_table_tmp);
++ }
++
++ if (fpc_table_add_m != 0) {
++ ispmmu_kunmap(fpc_table_add_m);
++ kfree(fpc_table_add);
++ }
++}
+diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h
+new file mode 100644
+index 0000000..4ef40a6
+--- /dev/null
++++ b/drivers/media/video/isp/ispccdc.h
+@@ -0,0 +1,209 @@
++/*
++ * ispccdc.h
++ *
++ * Driver header file for CCDC module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Senthilvadivu Guruswamy <svadivu@ti.com>
++ * Pallavi Kulkarni <p-kulkarni@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_CCDC_H
++#define OMAP_ISP_CCDC_H
++
++#include <mach/isp_user.h>
++
++#define is_isplsc_activated() 1
++
++/* Enumeration constants for CCDC input output format */
++enum ccdc_input {
++ CCDC_RAW,
++ CCDC_YUV_SYNC,
++ CCDC_YUV_BT,
++ CCDC_OTHERS
++};
++
++enum ccdc_output {
++ CCDC_YUV_RSZ,
++ CCDC_YUV_MEM_RSZ,
++ CCDC_OTHERS_VP,
++ CCDC_OTHERS_MEM,
++ CCDC_OTHERS_VP_MEM
++};
++
++/* Enumeration constants for the sync interface parameters */
++enum inpmode {
++ RAW,
++ YUV16,
++ YUV8
++};
++enum datasize {
++ DAT8,
++ DAT10,
++ DAT11,
++ DAT12
++};
++
++
++/**
++ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
++ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
++ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
++ * @ipmod: Input mode.
++ * @datsz: Data size.
++ * @fldmode: 0 - Progressive, 1 - Interlaced.
++ * @datapol: 0 - Positive, 1 - Negative.
++ * @fldpol: 0 - Positive, 1 - Negative.
++ * @hdpol: 0 - Positive, 1 - Negative.
++ * @vdpol: 0 - Positive, 1 - Negative.
++ * @fldout: 0 - Input, 1 - Output.
++ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
++ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
++ * @ppln: Number of pixels per line, used for HS/VS Output.
++ * @hlprf: Number of half lines per frame, used for HS/VS Output.
++ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
++ */
++struct ispccdc_syncif {
++ u8 ccdc_mastermode;
++ u8 fldstat;
++ enum inpmode ipmod;
++ enum datasize datsz;
++ u8 fldmode;
++ u8 datapol;
++ u8 fldpol;
++ u8 hdpol;
++ u8 vdpol;
++ u8 fldout;
++ u8 hs_width;
++ u8 vs_width;
++ u8 ppln;
++ u8 hlprf;
++ u8 bt_r656_en;
++};
++
++/**
++ * ispccdc_refmt - Structure for Reformatter parameters
++ * @lnalt: Line alternating mode enable. 0 - Enable, 1 - Disable.
++ * @lnum: Number of output lines from 1 input line. 1 to 4 lines.
++ * @plen_even: Number of program entries in even line minus 1.
++ * @plen_odd: Number of program entries in odd line minus 1.
++ * @prgeven0: Program entries 0-7 for even lines register
++ * @prgeven1: Program entries 8-15 for even lines register
++ * @prgodd0: Program entries 0-7 for odd lines register
++ * @prgodd1: Program entries 8-15 for odd lines register
++ * @fmtaddr0: Output line in which the original pixel is to be placed
++ * @fmtaddr1: Output line in which the original pixel is to be placed
++ * @fmtaddr2: Output line in which the original pixel is to be placed
++ * @fmtaddr3: Output line in which the original pixel is to be placed
++ * @fmtaddr4: Output line in which the original pixel is to be placed
++ * @fmtaddr5: Output line in which the original pixel is to be placed
++ * @fmtaddr6: Output line in which the original pixel is to be placed
++ * @fmtaddr7: Output line in which the original pixel is to be placed
++ */
++struct ispccdc_refmt {
++ u8 lnalt;
++ u8 lnum;
++ u8 plen_even;
++ u8 plen_odd;
++ u32 prgeven0;
++ u32 prgeven1;
++ u32 prgodd0;
++ u32 prgodd1;
++ u32 fmtaddr0;
++ u32 fmtaddr1;
++ u32 fmtaddr2;
++ u32 fmtaddr3;
++ u32 fmtaddr4;
++ u32 fmtaddr5;
++ u32 fmtaddr6;
++ u32 fmtaddr7;
++};
++
++int ispccdc_request(void);
++
++int ispccdc_free(void);
++
++int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output);
++
++void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width);
++
++void ispccdc_config_sync_if(struct ispccdc_syncif syncif);
++
++int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp);
++
++void ispccdc_enable_black_clamp(u8 enable);
++
++int ispccdc_config_fpc(struct ispccdc_fpc fpc);
++
++void ispccdc_enable_fpc(u8 enable);
++
++void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp);
++
++void ispccdc_config_vp(struct ispccdc_vp vp);
++
++void ispccdc_enable_vp(u8 enable);
++
++void ispccdc_config_reformatter(struct ispccdc_refmt refmt);
++
++void ispccdc_enable_reformatter(u8 enable);
++
++void ispccdc_config_culling(struct ispccdc_culling culling);
++
++void ispccdc_enable_lpf(u8 enable);
++
++void ispccdc_config_alaw(enum alaw_ipwidth ipwidth);
++
++void ispccdc_enable_alaw(u8 enable);
++
++int ispccdc_load_lsc(u8 *table_addr, u32 table_size);
++
++void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg);
++
++void ispccdc_enable_lsc(u8 enable);
++
++void ispccdc_lsc_error_handler(void);
++
++void ispccdc_config_imgattr(u32 colptn);
++
++void ispccdc_config_shadow_registers(void);
++
++int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h);
++
++int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h);
++
++int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines);
++
++int ispccdc_set_outaddr(u32 addr);
++
++void ispccdc_enable(u8 enable);
++
++void ispccdc_suspend(void);
++
++void ispccdc_resume(void);
++
++int ispccdc_sbl_busy(void);
++
++int ispccdc_busy(void);
++
++void ispccdc_save_context(void);
++
++void ispccdc_restore_context(void);
++
++void ispccdc_print_status(void);
++
++int omap34xx_isp_ccdc_config(void *userspace_add);
++
++void ispccdc_set_wenlog(u32 wenlog);
++
++#endif /* OMAP_ISP_CCDC_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch
new file mode 100644
index 0000000000..c549eadc88
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch
@@ -0,0 +1,3413 @@
+From 926b51afea146826c8076e5fb305eaa0332399b4 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add ISP backend (PRV and RSZ)
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/isppreview.c | 1929 ++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/isppreview.h | 354 +++++++
+ drivers/media/video/isp/ispresizer.c | 928 ++++++++++++++++
+ drivers/media/video/isp/ispresizer.h | 158 +++
+ 4 files changed, 3369 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/isppreview.c
+ create mode 100644 drivers/media/video/isp/isppreview.h
+ create mode 100644 drivers/media/video/isp/ispresizer.c
+ create mode 100644 drivers/media/video/isp/ispresizer.h
+
+diff --git a/drivers/media/video/isp/isppreview.c b/drivers/media/video/isp/isppreview.c
+new file mode 100644
+index 0000000..17f1abc
+--- /dev/null
++++ b/drivers/media/video/isp/isppreview.c
+@@ -0,0 +1,1929 @@
++/*
++ * isppreview.c
++ *
++ * Driver Library for Preview module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Senthilvadivu Guruswamy <svadivu@ti.com>
++ * Pallavi Kulkarni <p-kulkarni@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/mutex.h>
++#include <linux/module.h>
++#include <linux/uaccess.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "isppreview.h"
++
++static struct ispprev_nf prev_nf_t;
++static struct prev_params *params;
++static int rg_update, gg_update, bg_update, nf_enable, nf_update;
++
++/* Structure for saving/restoring preview module registers */
++static struct isp_reg ispprev_reg_list[] = {
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_DRKF_OFFSET, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_NF, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3, 0x0000},
++ {OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 0x0000},
++ {0, ISP_TOK_TERM, 0x0000}
++};
++
++
++/* Default values in Office Flourescent Light for RGBtoRGB Blending */
++static struct ispprev_rgbtorgb flr_rgb2rgb = {
++ { /* RGB-RGB Matrix */
++ {0x01E2, 0x0F30, 0x0FEE},
++ {0x0F9B, 0x01AC, 0x0FB9},
++ {0x0FE0, 0x0EC0, 0x0260}
++ }, /* RGB Offset */
++ {0x0000, 0x0000, 0x0000}
++};
++
++/* Default values in Office Flourescent Light for RGB to YUV Conversion*/
++static struct ispprev_csc flr_prev_csc[] = {
++ {
++ { /* CSC Coef Matrix */
++ {66, 129, 25},
++ {-38, -75, 112},
++ {112, -94 , -18}
++ }, /* CSC Offset */
++ {0x0, 0x0, 0x0}
++ },
++ {
++ { /* CSC Coef Matrix BW */
++ {66, 129, 25},
++ {0, 0, 0},
++ {0, 0, 0}
++ }, /* CSC Offset */
++ {0x0, 0x0, 0x0}
++ },
++ {
++ { /* CSC Coef Matrix Sepia */
++ {19, 38, 7},
++ {0, 0, 0},
++ {0, 0, 0}
++ }, /* CSC Offset */
++ {0x0, 0xE7, 0x14}
++ }
++};
++
++
++/* Default values in Office Flourescent Light for CFA Gradient*/
++#define FLR_CFA_GRADTHRS_HORZ 0x28
++#define FLR_CFA_GRADTHRS_VERT 0x28
++
++/* Default values in Office Flourescent Light for Chroma Suppression*/
++#define FLR_CSUP_GAIN 0x0D
++#define FLR_CSUP_THRES 0xEB
++
++/* Default values in Office Flourescent Light for Noise Filter*/
++#define FLR_NF_STRGTH 0x03
++
++/* Default values in Office Flourescent Light for White Balance*/
++#define FLR_WBAL_DGAIN 0x100
++#define FLR_WBAL_COEF0 0x20
++#define FLR_WBAL_COEF1 0x29
++#define FLR_WBAL_COEF2 0x2d
++#define FLR_WBAL_COEF3 0x20
++
++#define FLR_WBAL_COEF0_ES1 0x20
++#define FLR_WBAL_COEF1_ES1 0x23
++#define FLR_WBAL_COEF2_ES1 0x39
++#define FLR_WBAL_COEF3_ES1 0x20
++
++/* Default values in Office Flourescent Light for Black Adjustment*/
++#define FLR_BLKADJ_BLUE 0x0
++#define FLR_BLKADJ_GREEN 0x0
++#define FLR_BLKADJ_RED 0x0
++
++static int update_color_matrix;
++
++/**
++ * struct isp_prev - Structure for storing ISP Preview module information
++ * @prev_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
++ * @prevout_w: Preview output width.
++ * @prevout_h: Preview output height.
++ * @previn_w: Preview input width.
++ * @previn_h: Preview input height.
++ * @prev_inpfmt: Preview input format.
++ * @prev_outfmt: Preview output format.
++ * @hmed_en: Horizontal median filter enable.
++ * @nf_en: Noise filter enable.
++ * @dcor_en: Defect correction enable.
++ * @cfa_en: Color Filter Array (CFA) interpolation enable.
++ * @csup_en: Chrominance suppression enable.
++ * @yenh_en: Luma enhancement enable.
++ * @fmtavg: Number of horizontal pixels to average in input formatter. The
++ * input width should be a multiple of this number.
++ * @brightness: Brightness in preview module.
++ * @contrast: Contrast in preview module.
++ * @color: Color effect in preview module.
++ * @cfafmt: Color Filter Array (CFA) Format.
++ * @ispprev_mutex: Mutex for isp preview.
++ *
++ * This structure is used to store the OMAP ISP Preview module Information.
++ */
++static struct isp_prev {
++ int pm_state;
++ u8 prev_inuse;
++ u32 prevout_w;
++ u32 prevout_h;
++ u32 previn_w;
++ u32 previn_h;
++ enum preview_input prev_inpfmt;
++ enum preview_output prev_outfmt;
++ u8 hmed_en;
++ u8 nf_en;
++ u8 dcor_en;
++ u8 cfa_en;
++ u8 csup_en;
++ u8 yenh_en;
++ u8 fmtavg;
++ u8 brightness;
++ u8 contrast;
++ enum v4l2_colorfx color;
++ enum cfa_fmt cfafmt;
++ struct mutex ispprev_mutex; /* For checking/modifying prev_inuse */
++ u32 sph;
++ u32 slv;
++} ispprev_obj;
++
++/* Saved parameters */
++static struct prev_params *prev_config_params;
++
++/*
++ * Coeficient Tables for the submodules in Preview.
++ * Array is initialised with the values from.the tables text file.
++ */
++
++/*
++ * CFA Filter Coefficient Table
++ *
++ */
++static u32 cfa_coef_table[] = {
++#include "cfa_coef_table.h"
++};
++
++/*
++ * Gamma Correction Table - Red
++ */
++static u32 redgamma_table[] = {
++#include "redgamma_table.h"
++};
++
++/*
++ * Gamma Correction Table - Green
++ */
++static u32 greengamma_table[] = {
++#include "greengamma_table.h"
++};
++
++/*
++ * Gamma Correction Table - Blue
++ */
++static u32 bluegamma_table[] = {
++#include "bluegamma_table.h"
++};
++
++/*
++ * Noise Filter Threshold table
++ */
++static u32 noise_filter_table[] = {
++#include "noise_filter_table.h"
++};
++
++/*
++ * Luminance Enhancement Table
++ */
++static u32 luma_enhance_table[] = {
++#include "luma_enhance_table.h"
++};
++
++/**
++ * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
++ * @userspace_add: Pointer from Userspace to structure with flags and data to
++ * update.
++ **/
++int omap34xx_isp_preview_config(void *userspace_add)
++{
++ struct ispprev_hmed prev_hmed_t;
++ struct ispprev_cfa prev_cfa_t;
++ struct ispprev_csup csup_t;
++ struct ispprev_wbal prev_wbal_t;
++ struct ispprev_blkadj prev_blkadj_t;
++ struct ispprev_rgbtorgb rgb2rgb_t;
++ struct ispprev_csc prev_csc_t;
++ struct ispprev_yclimit yclimit_t;
++ struct ispprev_dcor prev_dcor_t;
++ struct ispprv_update_config *preview_struct;
++ struct isptables_update isp_table_update;
++ int yen_t[ISPPRV_YENH_TBL_SIZE];
++
++ if (userspace_add == NULL)
++ return -EINVAL;
++
++ preview_struct = userspace_add;
++
++ if (ISP_ABS_PREV_LUMAENH & preview_struct->flag) {
++ if (ISP_ABS_PREV_LUMAENH & preview_struct->update) {
++ if (copy_from_user(yen_t, preview_struct->yen,
++ sizeof(yen_t)))
++ goto err_copy_from_user;
++ isppreview_config_luma_enhancement(yen_t);
++ }
++ params->features |= PREV_LUMA_ENHANCE;
++ } else if (ISP_ABS_PREV_LUMAENH & preview_struct->update)
++ params->features &= ~PREV_LUMA_ENHANCE;
++
++ if (ISP_ABS_PREV_INVALAW & preview_struct->flag) {
++ isppreview_enable_invalaw(1);
++ params->features |= PREV_INVERSE_ALAW;
++ } else {
++ isppreview_enable_invalaw(0);
++ params->features &= ~PREV_INVERSE_ALAW;
++ }
++
++ if (ISP_ABS_PREV_HRZ_MED & preview_struct->flag) {
++ if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
++ if (copy_from_user(&prev_hmed_t,
++ (struct ispprev_hmed *)
++ preview_struct->prev_hmed,
++ sizeof(struct ispprev_hmed)))
++ goto err_copy_from_user;
++ isppreview_config_hmed(prev_hmed_t);
++ }
++ isppreview_enable_hmed(1);
++ params->features |= PREV_HORZ_MEDIAN_FILTER;
++ } else if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
++ isppreview_enable_hmed(0);
++ params->features &= ~PREV_HORZ_MEDIAN_FILTER;
++ }
++
++ if (ISP_ABS_PREV_CFA & preview_struct->flag) {
++ if (ISP_ABS_PREV_CFA & preview_struct->update) {
++ if (copy_from_user(&prev_cfa_t,
++ (struct ispprev_cfa *)
++ preview_struct->prev_cfa,
++ sizeof(struct ispprev_cfa)))
++ goto err_copy_from_user;
++
++ isppreview_config_cfa(prev_cfa_t);
++ }
++ isppreview_enable_cfa(1);
++ params->features |= PREV_CFA;
++ } else if (ISP_ABS_PREV_CFA & preview_struct->update) {
++ isppreview_enable_cfa(0);
++ params->features &= ~PREV_CFA;
++ }
++
++ if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->flag) {
++ if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
++ if (copy_from_user(&csup_t,
++ (struct ispprev_csup *)
++ preview_struct->csup,
++ sizeof(struct ispprev_csup)))
++ goto err_copy_from_user;
++ isppreview_config_chroma_suppression(csup_t);
++ }
++ isppreview_enable_chroma_suppression(1);
++ params->features |= PREV_CHROMA_SUPPRESS;
++ } else if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
++ isppreview_enable_chroma_suppression(0);
++ params->features &= ~PREV_CHROMA_SUPPRESS;
++ }
++
++ if (ISP_ABS_PREV_WB & preview_struct->update) {
++ if (copy_from_user(&prev_wbal_t, (struct ispprev_wbal *)
++ preview_struct->prev_wbal,
++ sizeof(struct ispprev_wbal)))
++ goto err_copy_from_user;
++ isppreview_config_whitebalance(prev_wbal_t);
++ }
++
++ if (ISP_ABS_PREV_BLKADJ & preview_struct->update) {
++ if (copy_from_user(&prev_blkadj_t, (struct ispprev_blkadjl *)
++ preview_struct->prev_blkadj,
++ sizeof(struct ispprev_blkadj)))
++ goto err_copy_from_user;
++ isppreview_config_blkadj(prev_blkadj_t);
++ }
++
++ if (ISP_ABS_PREV_RGB2RGB & preview_struct->update) {
++ if (copy_from_user(&rgb2rgb_t, (struct ispprev_rgbtorgb *)
++ preview_struct->rgb2rgb,
++ sizeof(struct ispprev_rgbtorgb)))
++ goto err_copy_from_user;
++ isppreview_config_rgb_blending(rgb2rgb_t);
++ }
++
++ if (ISP_ABS_PREV_COLOR_CONV & preview_struct->update) {
++ if (copy_from_user(&prev_csc_t, (struct ispprev_csc *)
++ preview_struct->prev_csc,
++ sizeof(struct ispprev_csc)))
++ goto err_copy_from_user;
++ isppreview_config_rgb_to_ycbcr(prev_csc_t);
++ }
++
++ if (ISP_ABS_PREV_YC_LIMIT & preview_struct->update) {
++ if (copy_from_user(&yclimit_t, (struct ispprev_yclimit *)
++ preview_struct->yclimit,
++ sizeof(struct ispprev_yclimit)))
++ goto err_copy_from_user;
++ isppreview_config_yc_range(yclimit_t);
++ }
++
++ if (ISP_ABS_PREV_DEFECT_COR & preview_struct->flag) {
++ if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
++ if (copy_from_user(&prev_dcor_t,
++ (struct ispprev_dcor *)
++ preview_struct->prev_dcor,
++ sizeof(struct ispprev_dcor)))
++ goto err_copy_from_user;
++ isppreview_config_dcor(prev_dcor_t);
++ }
++ isppreview_enable_dcor(1);
++ params->features |= PREV_DEFECT_COR;
++ } else if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
++ isppreview_enable_dcor(0);
++ params->features &= ~PREV_DEFECT_COR;
++ }
++
++ if (ISP_ABS_PREV_GAMMABYPASS & preview_struct->flag) {
++ isppreview_enable_gammabypass(1);
++ params->features |= PREV_GAMMA_BYPASS;
++ } else {
++ isppreview_enable_gammabypass(0);
++ params->features &= ~PREV_GAMMA_BYPASS;
++ }
++
++ isp_table_update.update = preview_struct->update;
++ isp_table_update.flag = preview_struct->flag;
++ isp_table_update.prev_nf = preview_struct->prev_nf;
++ isp_table_update.red_gamma = preview_struct->red_gamma;
++ isp_table_update.green_gamma = preview_struct->green_gamma;
++ isp_table_update.blue_gamma = preview_struct->blue_gamma;
++
++ if (omap34xx_isp_tables_update(&isp_table_update))
++ goto err_copy_from_user;
++
++ return 0;
++
++err_copy_from_user:
++ printk(KERN_ERR "Preview Config: Copy From User Error\n");
++ return -EFAULT;
++}
++EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
++
++/**
++ * omap34xx_isp_tables_update - Abstraction layer Tables update.
++ * @isptables_struct: Pointer from Userspace to structure with flags and table
++ * data to update.
++ **/
++int omap34xx_isp_tables_update(struct isptables_update *isptables_struct)
++{
++
++ if (ISP_ABS_TBL_NF & isptables_struct->flag) {
++ nf_enable = 1;
++ params->features |= PREV_NOISE_FILTER;
++ if (ISP_ABS_TBL_NF & isptables_struct->update) {
++ if (copy_from_user(&prev_nf_t, (struct ispprev_nf *)
++ isptables_struct->prev_nf,
++ sizeof(struct ispprev_nf)))
++ goto err_copy_from_user;
++
++ nf_update = 1;
++ } else
++ nf_update = 0;
++ } else {
++ nf_enable = 0;
++ params->features &= ~PREV_NOISE_FILTER;
++ if (ISP_ABS_TBL_NF & isptables_struct->update)
++ nf_update = 1;
++ else
++ nf_update = 0;
++ }
++
++ if (ISP_ABS_TBL_REDGAMMA & isptables_struct->update) {
++ if (copy_from_user(redgamma_table, isptables_struct->red_gamma,
++ sizeof(redgamma_table))) {
++ goto err_copy_from_user;
++ }
++ rg_update = 1;
++ } else
++ rg_update = 0;
++
++ if (ISP_ABS_TBL_GREENGAMMA & isptables_struct->update) {
++ if (copy_from_user(greengamma_table,
++ isptables_struct->green_gamma,
++ sizeof(greengamma_table)))
++ goto err_copy_from_user;
++ gg_update = 1;
++ } else
++ gg_update = 0;
++
++ if (ISP_ABS_TBL_BLUEGAMMA & isptables_struct->update) {
++ if (copy_from_user(bluegamma_table,
++ isptables_struct->blue_gamma,
++ sizeof(bluegamma_table))) {
++ goto err_copy_from_user;
++ }
++ bg_update = 1;
++ } else
++ bg_update = 0;
++
++ return 0;
++
++err_copy_from_user:
++ printk(KERN_ERR "Preview Tables:Copy From User Error\n");
++ return -EFAULT;
++}
++
++/**
++ * isppreview_config_shadow_registers - Program shadow registers for preview.
++ *
++ * Allows user to program shadow registers associated with preview module.
++ **/
++void isppreview_config_shadow_registers()
++{
++ u8 current_brightness_contrast;
++ int ctr, prv_disabled;
++
++ isppreview_query_brightness(&current_brightness_contrast);
++ if (current_brightness_contrast !=
++ (ispprev_obj.brightness * ISPPRV_BRIGHT_UNITS)) {
++ DPRINTK_ISPPREV(" Changing Brightness level to %d\n",
++ ispprev_obj.brightness);
++ isppreview_config_brightness(ispprev_obj.brightness *
++ ISPPRV_BRIGHT_UNITS);
++ }
++
++ isppreview_query_contrast(&current_brightness_contrast);
++ if (current_brightness_contrast !=
++ (ispprev_obj.contrast * ISPPRV_CONTRAST_UNITS)) {
++ DPRINTK_ISPPREV(" Changing Contrast level to %d\n",
++ ispprev_obj.contrast);
++ isppreview_config_contrast(ispprev_obj.contrast *
++ ISPPRV_CONTRAST_UNITS);
++ }
++ if (update_color_matrix) {
++ isppreview_config_rgb_to_ycbcr(flr_prev_csc[ispprev_obj.color]);
++ update_color_matrix = 0;
++ }
++ if (gg_update || rg_update || bg_update || nf_update) {
++ isppreview_enable(0);
++ prv_disabled = 1;
++ }
++
++ if (gg_update) {
++ isp_reg_writel(ISPPRV_TBL_ADDR_GREEN_G_START,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++
++ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
++ isp_reg_writel(greengamma_table[ctr],
++ OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_DATA);
++ }
++ gg_update = 0;
++ }
++
++ if (rg_update) {
++ isp_reg_writel(ISPPRV_TBL_ADDR_RED_G_START,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++
++ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
++ isp_reg_writel(redgamma_table[ctr],
++ OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_DATA);
++ }
++ rg_update = 0;
++ }
++
++ if (bg_update) {
++ isp_reg_writel(ISPPRV_TBL_ADDR_BLUE_G_START,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++
++ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
++ isp_reg_writel(bluegamma_table[ctr],
++ OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_DATA);
++ }
++ bg_update = 0;
++ }
++
++ if (nf_update && nf_enable) {
++ isp_reg_writel(0xC00,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++ isp_reg_writel(prev_nf_t.spread,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
++ for (ctr = 0; ctr < ISPPRV_NF_TBL_SIZE; ctr++) {
++ isp_reg_writel(prev_nf_t.table[ctr],
++ OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_DATA);
++ }
++ isppreview_enable_noisefilter(1);
++ nf_update = 0;
++ }
++
++ if (~nf_update && nf_enable)
++ isppreview_enable_noisefilter(1);
++
++ if (nf_update && ~nf_enable)
++ isppreview_enable_noisefilter(0);
++
++ if (prv_disabled) {
++ isppreview_enable(1);
++ prv_disabled = 0;
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_shadow_registers);
++
++/**
++ * isppreview_request - Reserves the preview module.
++ *
++ * Returns 0 if successful, or -EBUSY if the module was already reserved.
++ **/
++int isppreview_request()
++{
++ mutex_lock(&ispprev_obj.ispprev_mutex);
++ if (ispprev_obj.prev_inuse) {
++ mutex_unlock(&ispprev_obj.ispprev_mutex);
++ printk(KERN_ERR "ISP_ERR : Preview Module Busy\n");
++ return -EBUSY;
++ }
++ ispprev_obj.prev_inuse = 1;
++ mutex_unlock(&ispprev_obj.ispprev_mutex);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_PREV_RAM_EN |
++ ISPCTRL_PREV_CLK_EN |
++ ISPCTRL_SBL_WR1_RAM_EN);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_request);
++
++/**
++ * isppreview_free - Frees the preview module.
++ *
++ * Returns 0 if successful, or -EINVAL if the module was already freed.
++ **/
++int isppreview_free()
++{
++ mutex_lock(&ispprev_obj.ispprev_mutex);
++ if (ispprev_obj.prev_inuse) {
++ ispprev_obj.prev_inuse = 0;
++ mutex_unlock(&ispprev_obj.ispprev_mutex);
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
++ ~(ISPCTRL_PREV_CLK_EN |
++ ISPCTRL_PREV_RAM_EN |
++ ISPCTRL_SBL_WR1_RAM_EN));
++ return 0;
++ } else {
++ mutex_unlock(&ispprev_obj.ispprev_mutex);
++ DPRINTK_ISPPREV("ISP_ERR : Preview Module already freed\n");
++ return -EINVAL;
++ }
++
++}
++EXPORT_SYMBOL_GPL(isppreview_free);
++
++/** isppreview_config_datapath - Specifies input and output modules for Preview
++ * @input: Indicates the module that gives the image to preview.
++ * @output: Indicates the module to which the preview outputs to.
++ *
++ * Configures the default configuration for the CCDC to work with.
++ *
++ * The valid values for the input are PRV_RAW_CCDC (0), PRV_RAW_MEM (1),
++ * PRV_RGBBAYERCFA (2), PRV_COMPCFA (3), PRV_CCDC_DRKF (4), PRV_OTHERS (5).
++ *
++ * The valid values for the output are PREVIEW_RSZ (0), PREVIEW_MEM (1).
++ *
++ * Returns 0 if successful, or -EINVAL if wrong input or output values are
++ * specified.
++ **/
++int isppreview_config_datapath(enum preview_input input,
++ enum preview_output output)
++{
++ u32 pcr = 0;
++ u8 enable = 0;
++ struct prev_params *params = prev_config_params;
++ struct ispprev_yclimit yclimit;
++
++ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++
++ switch (input) {
++ case PRV_RAW_CCDC:
++ pcr &= ~ISPPRV_PCR_SOURCE;
++ pcr &= ~ISPPRV_PCR_ONESHOT;
++ ispprev_obj.prev_inpfmt = PRV_RAW_CCDC;
++ break;
++ case PRV_RAW_MEM:
++ pcr |= ISPPRV_PCR_SOURCE;
++ pcr |= ISPPRV_PCR_ONESHOT;
++ ispprev_obj.prev_inpfmt = PRV_RAW_MEM;
++ break;
++ case PRV_CCDC_DRKF:
++ pcr |= ISPPRV_PCR_DRKFCAP;
++ pcr |= ISPPRV_PCR_ONESHOT;
++ ispprev_obj.prev_inpfmt = PRV_CCDC_DRKF;
++ break;
++ case PRV_COMPCFA:
++ ispprev_obj.prev_inpfmt = PRV_COMPCFA;
++ break;
++ case PRV_OTHERS:
++ ispprev_obj.prev_inpfmt = PRV_OTHERS;
++ break;
++ case PRV_RGBBAYERCFA:
++ ispprev_obj.prev_inpfmt = PRV_RGBBAYERCFA;
++ break;
++ default:
++ printk(KERN_ERR "ISP_ERR : Wrong Input\n");
++ return -EINVAL;
++ };
++
++ switch (output) {
++ case PREVIEW_RSZ:
++ pcr |= ISPPRV_PCR_RSZPORT;
++ pcr &= ~ISPPRV_PCR_SDRPORT;
++ break;
++ case PREVIEW_MEM:
++ pcr &= ~ISPPRV_PCR_RSZPORT;
++ pcr |= ISPPRV_PCR_SDRPORT;
++ break;
++ default:
++ printk(KERN_ERR "ISP_ERR : Wrong Output\n");
++ return -EINVAL;
++ }
++ ispprev_obj.prev_outfmt = output;
++
++ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++
++ isppreview_config_ycpos(params->pix_fmt);
++
++ if (params->cfa.cfa_table != NULL)
++ isppreview_config_cfa(params->cfa);
++ if (params->csup.hypf_en == 1)
++ isppreview_config_chroma_suppression(params->csup);
++ if (params->ytable != NULL)
++ isppreview_config_luma_enhancement(params->ytable);
++
++ if (params->gtable.redtable != NULL)
++ isppreview_config_gammacorrn(params->gtable);
++
++ enable = (params->features & PREV_CFA) ? 1 : 0;
++ isppreview_enable_cfa(enable);
++
++ enable = (params->features & PREV_CHROMA_SUPPRESS) ? 1 : 0;
++ isppreview_enable_chroma_suppression(enable);
++
++ enable = (params->features & PREV_LUMA_ENHANCE) ? 1 : 0;
++ isppreview_enable_luma_enhancement(enable);
++
++ enable = (params->features & PREV_NOISE_FILTER) ? 1 : 0;
++ if (enable)
++ isppreview_config_noisefilter(params->nf);
++ isppreview_enable_noisefilter(enable);
++
++ enable = (params->features & PREV_DEFECT_COR) ? 1 : 0;
++ if (enable)
++ isppreview_config_dcor(params->dcor);
++ isppreview_enable_dcor(enable);
++
++ enable = (params->features & PREV_GAMMA_BYPASS) ? 1 : 0;
++ isppreview_enable_gammabypass(enable);
++
++ isppreview_config_whitebalance(params->wbal);
++ isppreview_config_blkadj(params->blk_adj);
++ isppreview_config_rgb_blending(params->rgb2rgb);
++ isppreview_config_rgb_to_ycbcr(params->rgb2ycbcr);
++
++ isppreview_config_contrast(params->contrast * ISPPRV_CONTRAST_UNITS);
++ isppreview_config_brightness(params->brightness * ISPPRV_BRIGHT_UNITS);
++
++ yclimit.minC = ISPPRV_YC_MIN;
++ yclimit.maxC = ISPPRV_YC_MAX;
++ yclimit.minY = ISPPRV_YC_MIN;
++ yclimit.maxY = ISPPRV_YC_MAX;
++ isppreview_config_yc_range(yclimit);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_config_datapath);
++
++/**
++ * isppreview_set_skip - Set the number of rows/columns that should be skipped.
++ * h - Start Pixel Horizontal.
++ * v - Start Line Vertical.
++ **/
++void isppreview_set_skip(u32 h, u32 v)
++{
++ ispprev_obj.sph = h;
++ ispprev_obj.slv = v;
++}
++EXPORT_SYMBOL_GPL(isppreview_set_skip);
++
++/**
++ * isppreview_config_ycpos - Configure byte layout of YUV image.
++ * @mode: Indicates the required byte layout.
++ **/
++void isppreview_config_ycpos(enum preview_ycpos_mode mode)
++{
++ u32 pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++ pcr &= ~ISPPRV_PCR_YCPOS_CrYCbY;
++ pcr |= (mode << ISPPRV_PCR_YCPOS_SHIFT);
++ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_ycpos);
++
++/**
++ * isppreview_config_averager - Enable / disable / configure averager
++ * @average: Average value to be configured.
++ **/
++void isppreview_config_averager(u8 average)
++{
++ int reg = 0;
++
++ reg = AVE_ODD_PIXEL_DIST | AVE_EVEN_PIXEL_DIST | average;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_averager);
++
++/**
++ * isppreview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
++ * @enable: 1 - Reverse the A-Law done in CCDC.
++ **/
++void isppreview_enable_invalaw(u8 enable)
++{
++ u32 pcr_val = 0;
++ pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++
++ if (enable) {
++ isp_reg_writel(pcr_val | ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++ } else {
++ isp_reg_writel(pcr_val &
++ ~(ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_invalaw);
++
++/**
++ * isppreview_enable_drkframe - Enable/Disable of the darkframe subtract.
++ * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
++ * subtracted with the pixels in the current frame.
++ *
++ * The proccess is applied for each captured frame.
++ **/
++void isppreview_enable_drkframe(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DRKFEN);
++ else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_DRKFEN);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_drkframe);
++
++/**
++ * isppreview_enable_shadcomp - Enables/Disables the shading compensation.
++ * @enable: 1 - Enables the shading compensation.
++ *
++ * If dark frame subtract won't be used, then enable this shading
++ * compensation.
++ **/
++void isppreview_enable_shadcomp(u8 enable)
++{
++
++ if (enable) {
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ISPPRV_PCR_SCOMP_EN);
++ isppreview_enable_drkframe(1);
++ } else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_SCOMP_EN);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_shadcomp);
++
++/**
++ * isppreview_config_drkf_shadcomp - Configures shift value in shading comp.
++ * @scomp_shtval: 3bit value of shift used in shading compensation.
++ **/
++void isppreview_config_drkf_shadcomp(u8 scomp_shtval)
++{
++ u32 pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++
++ pcr_val &= ISPPRV_PCR_SCOMP_SFT_MASK;
++ isp_reg_writel(pcr_val | (scomp_shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_drkf_shadcomp);
++
++/**
++ * isppreview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
++ * @enable: 1 - Enables Horizontal Median Filter.
++ **/
++void isppreview_enable_hmed(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_HMEDEN);
++ else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_HMEDEN);
++ }
++ ispprev_obj.hmed_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_hmed);
++
++/**
++ * isppreview_config_hmed - Configures the Horizontal Median Filter.
++ * @prev_hmed: Structure containing the odd and even distance between the
++ * pixels in the image along with the filter threshold.
++ **/
++void isppreview_config_hmed(struct ispprev_hmed prev_hmed)
++{
++
++ u32 odddist = 0;
++ u32 evendist = 0;
++
++ if (prev_hmed.odddist == 1)
++ odddist = ~ISPPRV_HMED_ODDDIST;
++ else
++ odddist = ISPPRV_HMED_ODDDIST;
++
++ if (prev_hmed.evendist == 1)
++ evendist = ~ISPPRV_HMED_EVENDIST;
++ else
++ evendist = ISPPRV_HMED_EVENDIST;
++
++ isp_reg_writel(odddist | evendist | (prev_hmed.thres <<
++ ISPPRV_HMED_THRESHOLD_SHIFT),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
++
++}
++EXPORT_SYMBOL_GPL(isppreview_config_hmed);
++
++/**
++ * isppreview_config_noisefilter - Configures the Noise Filter.
++ * @prev_nf: Structure containing the noisefilter table, strength to be used
++ * for the noise filter and the defect correction enable flag.
++ **/
++void isppreview_config_noisefilter(struct ispprev_nf prev_nf)
++{
++ int i = 0;
++
++ isp_reg_writel(prev_nf.spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
++ isp_reg_writel(ISPPRV_NF_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_ADDR);
++ for (i = 0; i < ISPPRV_NF_TBL_SIZE; i++) {
++ isp_reg_writel(prev_nf.table[i], OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_DATA);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_noisefilter);
++
++/**
++ * isppreview_config_dcor - Configures the defect correction
++ * @prev_nf: Structure containing the defect correction structure
++ **/
++void isppreview_config_dcor(struct ispprev_dcor prev_dcor)
++{
++ if (prev_dcor.couplet_mode_en) {
++ isp_reg_writel(prev_dcor.detect_correct[0],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
++ isp_reg_writel(prev_dcor.detect_correct[1],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
++ isp_reg_writel(prev_dcor.detect_correct[2],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
++ isp_reg_writel(prev_dcor.detect_correct[3],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCCOUP);
++ } else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_DCCOUP);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_dcor);
++
++/**
++ * isppreview_config_cfa - Configures the CFA Interpolation parameters.
++ * @prev_cfa: Structure containing the CFA interpolation table, CFA format
++ * in the image, vertical and horizontal gradient threshold.
++ **/
++void isppreview_config_cfa(struct ispprev_cfa prev_cfa)
++{
++ int i = 0;
++
++ ispprev_obj.cfafmt = prev_cfa.cfafmt;
++
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ (prev_cfa.cfafmt << ISPPRV_PCR_CFAFMT_SHIFT));
++
++ isp_reg_writel(
++ (prev_cfa.cfa_gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
++ (prev_cfa.cfa_gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
++
++ isp_reg_writel(ISPPRV_CFA_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_SET_TBL_ADDR);
++
++ for (i = 0; i < ISPPRV_CFA_TBL_SIZE; i++) {
++ isp_reg_writel(prev_cfa.cfa_table[i],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_cfa);
++
++/**
++ * isppreview_config_gammacorrn - Configures the Gamma Correction table values
++ * @gtable: Structure containing the table for red, blue, green gamma table.
++ **/
++void isppreview_config_gammacorrn(struct ispprev_gtable gtable)
++{
++ int i = 0;
++
++ isp_reg_writel(ISPPRV_REDGAMMA_TABLE_ADDR,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
++ isp_reg_writel(gtable.redtable[i],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
++ }
++
++ isp_reg_writel(ISPPRV_GREENGAMMA_TABLE_ADDR,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
++ isp_reg_writel(gtable.greentable[i],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
++ }
++
++ isp_reg_writel(ISPPRV_BLUEGAMMA_TABLE_ADDR,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
++ isp_reg_writel(gtable.bluetable[i],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_gammacorrn);
++
++/**
++ * isppreview_config_luma_enhancement - Sets the Luminance Enhancement table.
++ * @ytable: Structure containing the table for Luminance Enhancement table.
++ **/
++void isppreview_config_luma_enhancement(u32 *ytable)
++{
++ int i = 0;
++
++ isp_reg_writel(ISPPRV_YENH_TABLE_ADDR,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
++ for (i = 0; i < ISPPRV_YENH_TBL_SIZE; i++) {
++ isp_reg_writel(ytable[i],
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_config_luma_enhancement);
++
++/**
++ * isppreview_config_chroma_suppression - Configures the Chroma Suppression.
++ * @csup: Structure containing the threshold value for suppression
++ * and the hypass filter enable flag.
++ **/
++void isppreview_config_chroma_suppression(struct ispprev_csup csup)
++{
++ isp_reg_writel(csup.gain | (csup.thres << ISPPRV_CSUP_THRES_SHIFT) |
++ (csup.hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_chroma_suppression);
++
++/**
++ * isppreview_enable_noisefilter - Enables/Disables the Noise Filter.
++ * @enable: 1 - Enables the Noise Filter.
++ **/
++void isppreview_enable_noisefilter(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_NFEN);
++ else
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_NFEN);
++ ispprev_obj.nf_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_noisefilter);
++
++/**
++ * isppreview_enable_dcor - Enables/Disables the defect correction.
++ * @enable: 1 - Enables the defect correction.
++ **/
++void isppreview_enable_dcor(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCOREN);
++ else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_DCOREN);
++ }
++ ispprev_obj.dcor_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_dcor);
++
++/**
++ * isppreview_enable_cfa - Enable/Disable the CFA Interpolation.
++ * @enable: 1 - Enables the CFA.
++ **/
++void isppreview_enable_cfa(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
++ else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_CFAEN);
++ }
++ ispprev_obj.cfa_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_cfa);
++
++/**
++ * isppreview_enable_gammabypass - Enables/Disables the GammaByPass
++ * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
++ * 0 - Goes through Gamma Correction. input and output is 10bit.
++ **/
++void isppreview_enable_gammabypass(u8 enable)
++{
++ if (enable) {
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ISPPRV_PCR_GAMMA_BYPASS);
++ } else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_GAMMA_BYPASS);
++ }
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_gammabypass);
++
++/**
++ * isppreview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
++ * @enable: 1 - Enable the Luminance Enhancement.
++ **/
++void isppreview_enable_luma_enhancement(u8 enable)
++{
++ if (enable) {
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ISPPRV_PCR_YNENHEN);
++ } else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_YNENHEN);
++ }
++ ispprev_obj.yenh_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_luma_enhancement);
++
++/**
++ * isppreview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
++ * @enable: 1 - Enable the Chrominance Suppression.
++ **/
++void isppreview_enable_chroma_suppression(u8 enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_SUPEN);
++ else {
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
++ ~ISPPRV_PCR_SUPEN);
++ }
++ ispprev_obj.csup_en = enable ? 1 : 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable_chroma_suppression);
++
++/**
++ * isppreview_config_whitebalance - Configures the White Balance parameters.
++ * @prev_wbal: Structure containing the digital gain and white balance
++ * coefficient.
++ *
++ * Coefficient matrix always with default values.
++ **/
++void isppreview_config_whitebalance(struct ispprev_wbal prev_wbal)
++{
++ u32 val;
++
++ isp_reg_writel(prev_wbal.dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
++
++ val = prev_wbal.coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
++ val |= prev_wbal.coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
++ val |= prev_wbal.coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
++ val |= prev_wbal.coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
++
++ isp_reg_writel(ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
++ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
++ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
++ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
++ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
++ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
++ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
++ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
++ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
++ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
++ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
++ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
++ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
++ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
++ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
++ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_whitebalance);
++
++/**
++ * isppreview_config_whitebalance2 - Configures the White Balance parameters.
++ * @prev_wbal: Structure containing the digital gain and white balance
++ * coefficient.
++ *
++ * Coefficient matrix can be changed.
++ **/
++void isppreview_config_whitebalance2(struct prev_white_balance prev_wbal)
++{
++ isp_reg_writel(prev_wbal.wb_dgain,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
++ isp_reg_writel(prev_wbal.wb_gain[0] |
++ prev_wbal.wb_gain[1] << ISPPRV_WBGAIN_COEF1_SHIFT |
++ prev_wbal.wb_gain[2] << ISPPRV_WBGAIN_COEF2_SHIFT |
++ prev_wbal.wb_gain[3] << ISPPRV_WBGAIN_COEF3_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
++
++ isp_reg_writel(
++ prev_wbal.wb_coefmatrix[0][0] << ISPPRV_WBSEL_N0_0_SHIFT |
++ prev_wbal.wb_coefmatrix[0][1] << ISPPRV_WBSEL_N0_1_SHIFT |
++ prev_wbal.wb_coefmatrix[0][2] << ISPPRV_WBSEL_N0_2_SHIFT |
++ prev_wbal.wb_coefmatrix[0][3] << ISPPRV_WBSEL_N0_3_SHIFT |
++ prev_wbal.wb_coefmatrix[1][0] << ISPPRV_WBSEL_N1_0_SHIFT |
++ prev_wbal.wb_coefmatrix[1][1] << ISPPRV_WBSEL_N1_1_SHIFT |
++ prev_wbal.wb_coefmatrix[1][2] << ISPPRV_WBSEL_N1_2_SHIFT |
++ prev_wbal.wb_coefmatrix[1][3] << ISPPRV_WBSEL_N1_3_SHIFT |
++ prev_wbal.wb_coefmatrix[2][0] << ISPPRV_WBSEL_N2_0_SHIFT |
++ prev_wbal.wb_coefmatrix[2][1] << ISPPRV_WBSEL_N2_1_SHIFT |
++ prev_wbal.wb_coefmatrix[2][2] << ISPPRV_WBSEL_N2_2_SHIFT |
++ prev_wbal.wb_coefmatrix[2][3] << ISPPRV_WBSEL_N2_3_SHIFT |
++ prev_wbal.wb_coefmatrix[3][0] << ISPPRV_WBSEL_N3_0_SHIFT |
++ prev_wbal.wb_coefmatrix[3][1] << ISPPRV_WBSEL_N3_1_SHIFT |
++ prev_wbal.wb_coefmatrix[3][2] << ISPPRV_WBSEL_N3_2_SHIFT |
++ prev_wbal.wb_coefmatrix[3][3] << ISPPRV_WBSEL_N3_3_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_whitebalance2);
++
++/**
++ * isppreview_config_blkadj - Configures the Black Adjustment parameters.
++ * @prev_blkadj: Structure containing the black adjustment towards red, green,
++ * blue.
++ **/
++void isppreview_config_blkadj(struct ispprev_blkadj prev_blkadj)
++{
++ isp_reg_writel(prev_blkadj.blue |
++ (prev_blkadj.green << ISPPRV_BLKADJOFF_G_SHIFT) |
++ (prev_blkadj.red << ISPPRV_BLKADJOFF_R_SHIFT),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_blkadj);
++
++/**
++ * isppreview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
++ * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
++ * offset.
++ **/
++void isppreview_config_rgb_blending(struct ispprev_rgbtorgb rgb2rgb)
++{
++ u32 val = 0;
++
++ val = (rgb2rgb.matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
++ val |= (rgb2rgb.matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
++
++ val = (rgb2rgb.matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
++ val |= (rgb2rgb.matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
++
++ val = (rgb2rgb.matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
++ val |= (rgb2rgb.matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
++
++ val = (rgb2rgb.matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
++ val |= (rgb2rgb.matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
++
++ val = (rgb2rgb.matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
++
++ val = (rgb2rgb.offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
++ val |= (rgb2rgb.offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
++
++ val = (rgb2rgb.offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_rgb_blending);
++
++/**
++ * Configures the RGB-YCbYCr conversion matrix
++ * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
++ * YCbCr offset.
++ **/
++void isppreview_config_rgb_to_ycbcr(struct ispprev_csc prev_csc)
++{
++ u32 val = 0;
++
++ val = (prev_csc.matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
++ val |= (prev_csc.matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
++ val |= (prev_csc.matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
++
++ val = (prev_csc.matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
++ val |= (prev_csc.matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
++ val |= (prev_csc.matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
++
++ val = (prev_csc.matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
++ val |= (prev_csc.matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
++ val |= (prev_csc.matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
++
++ val = (prev_csc.offset[0] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
++ val |= (prev_csc.offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
++ val |= (prev_csc.offset[2] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_rgb_to_ycbcr);
++
++/**
++ * isppreview_query_contrast - Query the contrast.
++ * @contrast: Pointer to hold the current programmed contrast value.
++ **/
++void isppreview_query_contrast(u8 *contrast)
++{
++ u32 brt_cnt_val = 0;
++
++ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++ *contrast = (brt_cnt_val >> ISPPRV_CNT_BRT_CNT_SHIFT) & 0xff;
++ DPRINTK_ISPPREV(" Current brt cnt value in hw is %x\n", brt_cnt_val);
++}
++EXPORT_SYMBOL_GPL(isppreview_query_contrast);
++
++/**
++ * isppreview_update_contrast - Updates the contrast.
++ * @contrast: Pointer to hold the current programmed contrast value.
++ *
++ * Value should be programmed before enabling the module.
++ **/
++void isppreview_update_contrast(u8 *contrast)
++{
++ ispprev_obj.contrast = *contrast;
++}
++EXPORT_SYMBOL_GPL(isppreview_update_contrast);
++
++/**
++ * isppreview_config_contrast - Configures the Contrast.
++ * @contrast: 8 bit value in U8Q4 format.
++ *
++ * Value should be programmed before enabling the module.
++ **/
++void isppreview_config_contrast(u8 contrast)
++{
++ u32 brt_cnt_val = 0;
++
++ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++ brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_CNT_SHIFT);
++ contrast &= 0xff;
++ isp_reg_writel(brt_cnt_val | contrast << ISPPRV_CNT_BRT_CNT_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_contrast);
++
++/**
++ * isppreview_get_contrast_range - Gets the range contrast value.
++ * @min_contrast: Pointer to hold the minimum Contrast value.
++ * @max_contrast: Pointer to hold the maximum Contrast value.
++ **/
++void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast)
++{
++ *min_contrast = ISPPRV_CONTRAST_MIN;
++ *max_contrast = ISPPRV_CONTRAST_MAX;
++}
++EXPORT_SYMBOL_GPL(isppreview_get_contrast_range);
++
++/**
++ * isppreview_update_brightness - Updates the brightness in preview module.
++ * @brightness: Pointer to hold the current programmed brightness value.
++ *
++ **/
++void isppreview_update_brightness(u8 *brightness)
++{
++ ispprev_obj.brightness = *brightness;
++}
++EXPORT_SYMBOL_GPL(isppreview_update_brightness);
++
++/**
++ * isppreview_config_brightness - Configures the brightness.
++ * @contrast: 8bitvalue in U8Q0 format.
++ **/
++void isppreview_config_brightness(u8 brightness)
++{
++ u32 brt_cnt_val = 0;
++
++ DPRINTK_ISPPREV("\tConfiguring brightness in ISP: %d\n", brightness);
++ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++ brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_BRT_SHIFT);
++ brightness &= 0xff;
++ isp_reg_writel(brt_cnt_val | brightness << ISPPRV_CNT_BRT_BRT_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_brightness);
++
++/**
++ * isppreview_query_brightness - Query the brightness.
++ * @brightness: Pointer to hold the current programmed brightness value.
++ **/
++void isppreview_query_brightness(u8 *brightness)
++{
++ *brightness = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
++}
++EXPORT_SYMBOL_GPL(isppreview_query_brightness);
++
++/**
++ * isppreview_get_brightness_range - Gets the range brightness value
++ * @min_brightness: Pointer to hold the minimum brightness value
++ * @max_brightness: Pointer to hold the maximum brightness value
++ **/
++void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness)
++{
++ *min_brightness = ISPPRV_BRIGHT_MIN;
++ *max_brightness = ISPPRV_BRIGHT_MAX;
++}
++EXPORT_SYMBOL_GPL(isppreview_get_brightness_range);
++
++/**
++ * isppreview_set_color - Sets the color effect.
++ * @mode: Indicates the required color effect.
++ **/
++void isppreview_set_color(u8 *mode)
++{
++ ispprev_obj.color = *mode;
++ update_color_matrix = 1;
++}
++EXPORT_SYMBOL_GPL(isppreview_set_color);
++
++/**
++ * isppreview_get_color - Gets the current color effect.
++ * @mode: Indicates the current color effect.
++ **/
++void isppreview_get_color(u8 *mode)
++{
++ *mode = ispprev_obj.color;
++}
++EXPORT_SYMBOL_GPL(isppreview_get_color);
++
++/**
++ * isppreview_config_yc_range - Configures the max and min Y and C values.
++ * @yclimit: Structure containing the range of Y and C values.
++ **/
++void isppreview_config_yc_range(struct ispprev_yclimit yclimit)
++{
++ isp_reg_writel(yclimit.maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
++ yclimit.maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
++ yclimit.minC << ISPPRV_SETUP_YC_MINC_SHIFT |
++ yclimit.minY << ISPPRV_SETUP_YC_MINY_SHIFT,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
++}
++EXPORT_SYMBOL_GPL(isppreview_config_yc_range);
++
++/**
++ * isppreview_try_size - Calculates output dimensions with the modules enabled.
++ * @input_w: input width for the preview in number of pixels per line
++ * @input_h: input height for the preview in number of lines
++ * @output_w: output width from the preview in number of pixels per line
++ * @output_h: output height for the preview in number of lines
++ *
++ * Calculates the number of pixels cropped in the submodules that are enabled,
++ * Fills up the output width height variables in the isp_prev structure.
++ **/
++int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
++{
++ u32 prevout_w = input_w;
++ u32 prevout_h = input_h;
++ u32 div = 0;
++ int max_out;
++
++ ispprev_obj.previn_w = input_w;
++ ispprev_obj.previn_h = input_h;
++
++ if (input_w < 32 || input_h < 32) {
++ printk(KERN_ERR "ISP_ERR : preview does not support "
++ "width < 16 or height < 32 \n");
++ return -EINVAL;
++ }
++ if (omap_rev() == OMAP3430_REV_ES1_0)
++ max_out = ISPPRV_MAXOUTPUT_WIDTH;
++ else
++ max_out = ISPPRV_MAXOUTPUT_WIDTH_ES2;
++
++ ispprev_obj.fmtavg = 0;
++
++ if (input_w > max_out) {
++ div = (input_w/max_out);
++ if (div >= 2 && div < 4) {
++ ispprev_obj.fmtavg = 1;
++ prevout_w /= 2;
++ } else if (div >= 4 && div < 8) {
++ ispprev_obj.fmtavg = 2;
++ prevout_w /= 4;
++ } else if (div >= 8) {
++ ispprev_obj.fmtavg = 3;
++ prevout_w /= 8;
++ }
++ }
++
++ if (ispprev_obj.hmed_en)
++ prevout_w -= 4;
++ if (ispprev_obj.nf_en) {
++ prevout_w -= 4;
++ prevout_h -= 4;
++ }
++ if (ispprev_obj.cfa_en) {
++ switch (ispprev_obj.cfafmt) {
++ case CFAFMT_BAYER:
++ case CFAFMT_SONYVGA:
++ prevout_w -= 4;
++ prevout_h -= 4;
++ break;
++ case CFAFMT_RGBFOVEON:
++ case CFAFMT_RRGGBBFOVEON:
++ case CFAFMT_DNSPL:
++ case CFAFMT_HONEYCOMB:
++ prevout_h -= 2;
++ break;
++ };
++ }
++ if (ispprev_obj.yenh_en || ispprev_obj.csup_en)
++ prevout_w -= 2;
++
++ /* Start at the correct row/column by skipping
++ * a Sensor specific amount.
++ */
++ prevout_w -= ispprev_obj.sph;
++ prevout_h -= ispprev_obj.slv;
++
++
++ if (prevout_w % 2)
++ prevout_w -= 1;
++
++ if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
++ if (((prevout_w * 2) & ISP_32B_BOUNDARY_OFFSET) !=
++ (prevout_w * 2)) {
++ prevout_w = ((prevout_w * 2) &
++ ISP_32B_BOUNDARY_OFFSET) / 2;
++ }
++ }
++ *output_w = prevout_w;
++ ispprev_obj.prevout_w = prevout_w;
++ *output_h = prevout_h;
++ ispprev_obj.prevout_h = prevout_h;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_try_size);
++
++/**
++ * isppreview_config_size - Sets the size of ISP preview output.
++ * @input_w: input width for the preview in number of pixels per line
++ * @input_h: input height for the preview in number of lines
++ * @output_w: output width from the preview in number of pixels per line
++ * @output_h: output height for the preview in number of lines
++ *
++ * Configures the appropriate values stored in the isp_prev structure to
++ * HORZ/VERT_INFO. Configures PRV_AVE if needed for downsampling as calculated
++ * in trysize.
++ **/
++int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
++{
++ u32 prevsdroff;
++
++ if ((output_w != ispprev_obj.prevout_w) ||
++ (output_h != ispprev_obj.prevout_h)) {
++ printk(KERN_ERR "ISP_ERR : isppreview_try_size should "
++ "be called before config size\n");
++ return -EINVAL;
++ }
++
++ isp_reg_writel((ispprev_obj.sph << ISPPRV_HORZ_INFO_SPH_SHIFT) |
++ (ispprev_obj.previn_w - 1),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
++ isp_reg_writel((ispprev_obj.slv << ISPPRV_VERT_INFO_SLV_SHIFT) |
++ (ispprev_obj.previn_h - 2),
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
++
++ if (ispprev_obj.cfafmt == CFAFMT_BAYER)
++ isp_reg_writel(ISPPRV_AVE_EVENDIST_2 <<
++ ISPPRV_AVE_EVENDIST_SHIFT |
++ ISPPRV_AVE_ODDDIST_2 <<
++ ISPPRV_AVE_ODDDIST_SHIFT |
++ ispprev_obj.fmtavg,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
++
++ if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
++ prevsdroff = ispprev_obj.prevout_w * 2;
++ if ((prevsdroff & ISP_32B_BOUNDARY_OFFSET) != prevsdroff) {
++ DPRINTK_ISPPREV("ISP_WARN: Preview output buffer line"
++ " size is truncated"
++ " to 32byte boundary\n");
++ prevsdroff &= ISP_32B_BOUNDARY_BUF ;
++ }
++ isppreview_config_outlineoffset(prevsdroff);
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_config_size);
++
++/**
++ * isppreview_config_inlineoffset - Configures the Read address line offset.
++ * @offset: Line Offset for the input image.
++ **/
++int isppreview_config_inlineoffset(u32 offset)
++{
++ if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
++ isp_reg_writel(offset & 0xffff,
++ OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET);
++ } else {
++ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_config_inlineoffset);
++
++/**
++ * isppreview_set_inaddr - Sets memory address of input frame.
++ * @addr: 32bit memory address aligned on 32byte boundary.
++ *
++ * Configures the memory address from which the input frame is to be read.
++ **/
++int isppreview_set_inaddr(u32 addr)
++{
++ if ((addr & ISP_32B_BOUNDARY_BUF) == addr)
++ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
++ else {
++ printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_set_inaddr);
++
++/**
++ * isppreview_config_outlineoffset - Configures the Write address line offset.
++ * @offset: Line Offset for the preview output.
++ **/
++int isppreview_config_outlineoffset(u32 offset)
++{
++ if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
++ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_WADD_OFFSET);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_config_outlineoffset);
++
++/**
++ * isppreview_set_outaddr - Sets the memory address to store output frame
++ * @addr: 32bit memory address aligned on 32byte boundary.
++ *
++ * Configures the memory address to which the output frame is written.
++ **/
++int isppreview_set_outaddr(u32 addr)
++{
++ if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
++ printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_set_outaddr);
++
++/**
++ * isppreview_config_darklineoffset - Sets the Dark frame address line offset.
++ * @offset: Line Offset for the Darkframe.
++ **/
++int isppreview_config_darklineoffset(u32 offset)
++{
++ if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
++ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_DRKF_OFFSET);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_config_darklineoffset);
++
++/**
++ * isppreview_set_darkaddr - Sets the memory address to store Dark frame.
++ * @addr: 32bit memory address aligned on 32 bit boundary.
++ **/
++int isppreview_set_darkaddr(u32 addr)
++{
++ if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
++ printk(KERN_ERR "ISP_ERR : Address should be in 32 byte "
++ "boundary\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(isppreview_set_darkaddr);
++
++void __isppreview_enable(int enable)
++{
++ if (enable)
++ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_EN);
++ else
++ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_EN);
++}
++
++/**
++ * isppreview_enable - Enables the Preview module.
++ * @enable: 1 - Enables the preview module.
++ *
++ * Client should configure all the sub modules in Preview before this.
++ **/
++void isppreview_enable(int enable)
++{
++ __isppreview_enable(enable);
++ ispprev_obj.pm_state = enable;
++}
++EXPORT_SYMBOL_GPL(isppreview_enable);
++
++/**
++ * isppreview_suspend - Suspend Preview module.
++ **/
++void isppreview_suspend(void)
++{
++ if (ispprev_obj.pm_state)
++ __isppreview_enable(0);
++}
++EXPORT_SYMBOL_GPL(isppreview_suspend);
++
++/**
++ * isppreview_resume - Resume Preview module.
++ **/
++void isppreview_resume(void)
++{
++ if (ispprev_obj.pm_state)
++ __isppreview_enable(1);
++}
++EXPORT_SYMBOL_GPL(isppreview_resume);
++
++
++/**
++ * isppreview_busy - Gets busy state of preview module.
++ **/
++int isppreview_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR) &
++ ISPPRV_PCR_BUSY;
++}
++EXPORT_SYMBOL_GPL(isppreview_busy);
++
++/**
++ * isppreview_get_config - Gets parameters of preview module.
++ **/
++struct prev_params *isppreview_get_config(void)
++{
++ return prev_config_params;
++}
++EXPORT_SYMBOL_GPL(isppreview_get_config);
++
++/**
++ * isppreview_save_context - Saves the values of the preview module registers.
++ **/
++void isppreview_save_context(void)
++{
++ DPRINTK_ISPPREV("Saving context\n");
++ isp_save_context(ispprev_reg_list);
++}
++EXPORT_SYMBOL_GPL(isppreview_save_context);
++
++/**
++ * isppreview_restore_context - Restores the values of preview module registers
++ **/
++void isppreview_restore_context(void)
++{
++ DPRINTK_ISPPREV("Restoring context\n");
++ isp_restore_context(ispprev_reg_list);
++}
++EXPORT_SYMBOL_GPL(isppreview_restore_context);
++
++/**
++ * isppreview_print_status - Prints the values of the Preview Module registers.
++ *
++ * Also prints other debug information stored in the preview moduel.
++ **/
++void isppreview_print_status(void)
++{
++ DPRINTK_ISPPREV("Module in use =%d\n", ispprev_obj.prev_inuse);
++ DPRINTK_ISPPREV("Preview Input format =%d, Output Format =%d\n",
++ ispprev_obj.prev_inpfmt,
++ ispprev_obj.prev_outfmt);
++ DPRINTK_ISPPREV("Accepted Preview Input (width = %d,Height = %d)\n",
++ ispprev_obj.previn_w,
++ ispprev_obj.previn_h);
++ DPRINTK_ISPPREV("Accepted Preview Output (width = %d,Height = %d)\n",
++ ispprev_obj.prevout_w,
++ ispprev_obj.prevout_h);
++ DPRINTK_ISPPREV("###ISP_CTRL in preview =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ DPRINTK_ISPPREV("###ISP_IRQ0ENABLE in preview =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
++ DPRINTK_ISPPREV("###ISP_IRQ0STATUS in preview =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
++ DPRINTK_ISPPREV("###PRV PCR =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR));
++ DPRINTK_ISPPREV("###PRV HORZ_INFO =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO));
++ DPRINTK_ISPPREV("###PRV VERT_INFO =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO));
++ DPRINTK_ISPPREV("###PRV WSDR_ADDR =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR));
++ DPRINTK_ISPPREV("###PRV WADD_OFFSET =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_WADD_OFFSET));
++ DPRINTK_ISPPREV("###PRV AVE =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE));
++ DPRINTK_ISPPREV("###PRV HMED =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED));
++ DPRINTK_ISPPREV("###PRV NF =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_NF));
++ DPRINTK_ISPPREV("###PRV WB_DGAIN =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN));
++ DPRINTK_ISPPREV("###PRV WBGAIN =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN));
++ DPRINTK_ISPPREV("###PRV WBSEL =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL));
++ DPRINTK_ISPPREV("###PRV CFA =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA));
++ DPRINTK_ISPPREV("###PRV BLKADJOFF =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF));
++ DPRINTK_ISPPREV("###PRV RGB_MAT1 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1));
++ DPRINTK_ISPPREV("###PRV RGB_MAT2 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2));
++ DPRINTK_ISPPREV("###PRV RGB_MAT3 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3));
++ DPRINTK_ISPPREV("###PRV RGB_MAT4 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4));
++ DPRINTK_ISPPREV("###PRV RGB_MAT5 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5));
++ DPRINTK_ISPPREV("###PRV RGB_OFF1 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1));
++ DPRINTK_ISPPREV("###PRV RGB_OFF2 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2));
++ DPRINTK_ISPPREV("###PRV CSC0 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0));
++ DPRINTK_ISPPREV("###PRV CSC1 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1));
++ DPRINTK_ISPPREV("###PRV CSC2 =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2));
++ DPRINTK_ISPPREV("###PRV CSC_OFFSET =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET));
++ DPRINTK_ISPPREV("###PRV CNT_BRT =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT));
++ DPRINTK_ISPPREV("###PRV CSUP =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP));
++ DPRINTK_ISPPREV("###PRV SETUP_YC =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC));
++}
++EXPORT_SYMBOL_GPL(isppreview_print_status);
++
++/**
++ * isp_preview_init - Module Initialization.
++ **/
++int __init isp_preview_init(void)
++{
++ int i = 0;
++
++ prev_config_params = kmalloc(sizeof(*prev_config_params), GFP_KERNEL);
++ if (!prev_config_params) {
++ printk(KERN_ERR "Can't get memory for isp_preview params!\n");
++ return -ENOMEM;
++ }
++ params = prev_config_params;
++
++ ispprev_obj.prev_inuse = 0;
++ mutex_init(&ispprev_obj.ispprev_mutex);
++
++ /* Init values */
++ ispprev_obj.sph = 2;
++ ispprev_obj.slv = 0;
++ ispprev_obj.color = V4L2_COLORFX_NONE;
++ ispprev_obj.contrast = ISPPRV_CONTRAST_DEF;
++ params->contrast = ISPPRV_CONTRAST_DEF;
++ ispprev_obj.brightness = ISPPRV_BRIGHT_DEF;
++ params->brightness = ISPPRV_BRIGHT_DEF;
++ params->average = NO_AVE;
++ params->lens_shading_shift = 0;
++ params->pix_fmt = YCPOS_YCrYCb;
++ params->cfa.cfafmt = CFAFMT_BAYER;
++ params->cfa.cfa_table = cfa_coef_table;
++ params->cfa.cfa_gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
++ params->cfa.cfa_gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
++ params->csup.gain = FLR_CSUP_GAIN;
++ params->csup.thres = FLR_CSUP_THRES;
++ params->csup.hypf_en = 0;
++ params->ytable = luma_enhance_table;
++ params->nf.spread = FLR_NF_STRGTH;
++ memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
++ params->dcor.couplet_mode_en = 1;
++ for (i = 0; i < 4; i++)
++ params->dcor.detect_correct[i] = 0xE;
++ params->gtable.bluetable = bluegamma_table;
++ params->gtable.greentable = greengamma_table;
++ params->gtable.redtable = redgamma_table;
++ params->wbal.dgain = FLR_WBAL_DGAIN;
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ params->wbal.coef0 = FLR_WBAL_COEF0_ES1;
++ params->wbal.coef1 = FLR_WBAL_COEF1_ES1;
++ params->wbal.coef2 = FLR_WBAL_COEF2_ES1;
++ params->wbal.coef3 = FLR_WBAL_COEF3_ES1;
++ } else {
++ params->wbal.coef0 = FLR_WBAL_COEF0;
++ params->wbal.coef1 = FLR_WBAL_COEF1;
++ params->wbal.coef2 = FLR_WBAL_COEF2;
++ params->wbal.coef3 = FLR_WBAL_COEF3;
++ }
++ params->blk_adj.red = FLR_BLKADJ_RED;
++ params->blk_adj.green = FLR_BLKADJ_GREEN;
++ params->blk_adj.blue = FLR_BLKADJ_BLUE;
++ params->rgb2rgb = flr_rgb2rgb;
++ params->rgb2ycbcr = flr_prev_csc[ispprev_obj.color];
++
++ params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER;
++ params->features &= ~(PREV_AVERAGER | PREV_INVERSE_ALAW |
++ PREV_HORZ_MEDIAN_FILTER |
++ PREV_GAMMA_BYPASS |
++ PREV_DARK_FRAME_SUBTRACT |
++ PREV_LENS_SHADING |
++ PREV_DARK_FRAME_CAPTURE |
++ PREV_CHROMA_SUPPRESS |
++ PREV_LUMA_ENHANCE);
++ return 0;
++}
++
++/**
++ * isp_preview_cleanup - Module Cleanup.
++ **/
++void isp_preview_cleanup(void)
++{
++ kfree(prev_config_params);
++}
+diff --git a/drivers/media/video/isp/isppreview.h b/drivers/media/video/isp/isppreview.h
+new file mode 100644
+index 0000000..e88c329
+--- /dev/null
++++ b/drivers/media/video/isp/isppreview.h
+@@ -0,0 +1,354 @@
++/*
++ * isppreview.h
++ *
++ * Driver header file for Preview module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Senthilvadivu Guruswamy <svadivu@ti.com>
++ * Pallavi Kulkarni <p-kulkarni@ti.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_PREVIEW_H
++#define OMAP_ISP_PREVIEW_H
++
++#include <mach/isp_user.h>
++/* Isp query control structure */
++
++#define ISPPRV_BRIGHT_STEP 0x1
++#define ISPPRV_BRIGHT_DEF 0x0
++#define ISPPRV_BRIGHT_LOW 0x0
++#define ISPPRV_BRIGHT_HIGH 0xF
++#define ISPPRV_BRIGHT_UNITS 0x7
++
++#define ISPPRV_CONTRAST_STEP 0x1
++#define ISPPRV_CONTRAST_DEF 0x4
++#define ISPPRV_CONTRAST_LOW 0x0
++#define ISPPRV_CONTRAST_HIGH 0xF
++#define ISPPRV_CONTRAST_UNITS 0x4
++
++#define NO_AVE 0x0
++#define AVE_2_PIX 0x1
++#define AVE_4_PIX 0x2
++#define AVE_8_PIX 0x3
++#define AVE_ODD_PIXEL_DIST (1 << 4) /* For Bayer Sensors */
++#define AVE_EVEN_PIXEL_DIST (1 << 2)
++
++#define WB_GAIN_MAX 4
++
++/* Features list */
++#define PREV_AVERAGER (1 << 0)
++#define PREV_INVERSE_ALAW (1 << 1)
++#define PREV_HORZ_MEDIAN_FILTER (1 << 2)
++#define PREV_NOISE_FILTER (1 << 3)
++#define PREV_CFA (1 << 4)
++#define PREV_GAMMA_BYPASS (1 << 5)
++#define PREV_LUMA_ENHANCE (1 << 6)
++#define PREV_CHROMA_SUPPRESS (1 << 7)
++#define PREV_DARK_FRAME_SUBTRACT (1 << 8)
++#define PREV_LENS_SHADING (1 << 9)
++#define PREV_DARK_FRAME_CAPTURE (1 << 10)
++#define PREV_DEFECT_COR (1 << 11)
++
++
++#define ISP_NF_TABLE_SIZE (1 << 10)
++
++#define ISP_GAMMA_TABLE_SIZE (1 << 10)
++
++/* Table addresses */
++#define ISPPRV_TBL_ADDR_RED_G_START 0x00
++#define ISPPRV_TBL_ADDR_BLUE_G_START 0x800
++#define ISPPRV_TBL_ADDR_GREEN_G_START 0x400
++
++/*
++ *Enumeration Constants for input and output format
++ */
++enum preview_input {
++ PRV_RAW_CCDC,
++ PRV_RAW_MEM,
++ PRV_RGBBAYERCFA,
++ PRV_COMPCFA,
++ PRV_CCDC_DRKF,
++ PRV_OTHERS
++};
++enum preview_output {
++ PREVIEW_RSZ,
++ PREVIEW_MEM
++};
++/*
++ * Configure byte layout of YUV image
++ */
++enum preview_ycpos_mode {
++ YCPOS_YCrYCb = 0,
++ YCPOS_YCbYCr = 1,
++ YCPOS_CbYCrY = 2,
++ YCPOS_CrYCbY = 3
++};
++
++/**
++ * struct ispprev_gtable - Structure for Gamma Correction.
++ * @redtable: Pointer to the red gamma table.
++ * @greentable: Pointer to the green gamma table.
++ * @bluetable: Pointer to the blue gamma table.
++ */
++struct ispprev_gtable {
++ u32 *redtable;
++ u32 *greentable;
++ u32 *bluetable;
++};
++
++/**
++ * struct prev_white_balance - Structure for White Balance 2.
++ * @wb_dgain: White balance common gain.
++ * @wb_gain: Individual color gains.
++ * @wb_coefmatrix: Coefficient matrix
++ */
++struct prev_white_balance {
++ u16 wb_dgain; /* white balance common gain */
++ u8 wb_gain[WB_GAIN_MAX]; /* individual color gains */
++ u8 wb_coefmatrix[WB_GAIN_MAX][WB_GAIN_MAX];
++};
++
++/**
++ * struct prev_size_params - Structure for size parameters.
++ * @hstart: Starting pixel.
++ * @vstart: Starting line.
++ * @hsize: Width of input image.
++ * @vsize: Height of input image.
++ * @pixsize: Pixel size of the image in terms of bits.
++ * @in_pitch: Line offset of input image.
++ * @out_pitch: Line offset of output image.
++ */
++struct prev_size_params {
++ unsigned int hstart;
++ unsigned int vstart;
++ unsigned int hsize;
++ unsigned int vsize;
++ unsigned char pixsize;
++ unsigned short in_pitch;
++ unsigned short out_pitch;
++};
++
++/**
++ * struct prev_rgb2ycbcr_coeffs - Structure RGB2YCbCr parameters.
++ * @coeff: Color conversion gains in 3x3 matrix.
++ * @offset: Color conversion offsets.
++ */
++struct prev_rgb2ycbcr_coeffs {
++ short coeff[RGB_MAX][RGB_MAX];
++ short offset[RGB_MAX];
++};
++
++/**
++ * struct prev_darkfrm_params - Structure for Dark frame suppression.
++ * @addr: Memory start address.
++ * @offset: Line offset.
++ */
++struct prev_darkfrm_params {
++ u32 addr;
++ u32 offset;
++ };
++
++/**
++ * struct prev_params - Structure for all configuration
++ * @features: Set of features enabled.
++ * @pix_fmt: Output pixel format.
++ * @cfa: CFA coefficients.
++ * @csup: Chroma suppression coefficients.
++ * @ytable: Pointer to Luma enhancement coefficients.
++ * @nf: Noise filter coefficients.
++ * @dcor: Noise filter coefficients.
++ * @gtable: Gamma coefficients.
++ * @wbal: White Balance parameters.
++ * @blk_adj: Black adjustment parameters.
++ * @rgb2rgb: RGB blending parameters.
++ * @rgb2ycbcr: RGB to ycbcr parameters.
++ * @hmf_params: Horizontal median filter.
++ * @size_params: Size parameters.
++ * @drkf_params: Darkframe parameters.
++ * @lens_shading_shift:
++ * @average: Downsampling rate for averager.
++ * @contrast: Contrast.
++ * @brightness: Brightness.
++ */
++struct prev_params {
++ u16 features;
++ enum preview_ycpos_mode pix_fmt;
++ struct ispprev_cfa cfa;
++ struct ispprev_csup csup;
++ u32 *ytable;
++ struct ispprev_nf nf;
++ struct ispprev_dcor dcor;
++ struct ispprev_gtable gtable;
++ struct ispprev_wbal wbal;
++ struct ispprev_blkadj blk_adj;
++ struct ispprev_rgbtorgb rgb2rgb;
++ struct ispprev_csc rgb2ycbcr;
++ struct ispprev_hmed hmf_params;
++ struct prev_size_params size_params;
++ struct prev_darkfrm_params drkf_params;
++ u8 lens_shading_shift;
++ u8 average;
++ u8 contrast;
++ u8 brightness;
++};
++
++/**
++ * struct isptables_update - Structure for Table Configuration.
++ * @update: Specifies which tables should be updated.
++ * @flag: Specifies which tables should be enabled.
++ * @prev_nf: Pointer to structure for Noise Filter
++ * @lsc: Pointer to LSC gain table. (currently not used)
++ * @red_gamma: Pointer to red gamma correction table.
++ * @green_gamma: Pointer to green gamma correction table.
++ * @blue_gamma: Pointer to blue gamma correction table.
++ */
++struct isptables_update {
++ u16 update;
++ u16 flag;
++ struct ispprev_nf *prev_nf;
++ u32 *lsc;
++ u32 *red_gamma;
++ u32 *green_gamma;
++ u32 *blue_gamma;
++};
++
++void isppreview_config_shadow_registers(void);
++
++int isppreview_request(void);
++
++int isppreview_free(void);
++
++int isppreview_config_datapath(enum preview_input input,
++ enum preview_output output);
++
++void isppreview_config_ycpos(enum preview_ycpos_mode mode);
++
++void isppreview_config_averager(u8 average);
++
++void isppreview_enable_invalaw(u8 enable);
++
++void isppreview_enable_drkframe(u8 enable);
++
++void isppreview_enable_shadcomp(u8 enable);
++
++void isppreview_config_drkf_shadcomp(u8 scomp_shtval);
++
++void isppreview_enable_gammabypass(u8 enable);
++
++void isppreview_enable_hmed(u8 enable);
++
++void isppreview_config_hmed(struct ispprev_hmed);
++
++void isppreview_enable_noisefilter(u8 enable);
++
++void isppreview_config_noisefilter(struct ispprev_nf prev_nf);
++
++void isppreview_enable_dcor(u8 enable);
++
++void isppreview_config_dcor(struct ispprev_dcor prev_dcor);
++
++
++void isppreview_config_cfa(struct ispprev_cfa);
++
++void isppreview_config_gammacorrn(struct ispprev_gtable);
++
++void isppreview_config_chroma_suppression(struct ispprev_csup csup);
++
++void isppreview_enable_cfa(u8 enable);
++
++void isppreview_config_luma_enhancement(u32 *ytable);
++
++void isppreview_enable_luma_enhancement(u8 enable);
++
++void isppreview_enable_chroma_suppression(u8 enable);
++
++void isppreview_config_whitebalance(struct ispprev_wbal);
++
++void isppreview_config_blkadj(struct ispprev_blkadj);
++
++void isppreview_config_rgb_blending(struct ispprev_rgbtorgb);
++
++void isppreview_config_rgb_to_ycbcr(struct ispprev_csc);
++
++void isppreview_update_contrast(u8 *contrast);
++
++void isppreview_query_contrast(u8 *contrast);
++
++void isppreview_config_contrast(u8 contrast);
++
++void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast);
++
++void isppreview_update_brightness(u8 *brightness);
++
++void isppreview_config_brightness(u8 brightness);
++
++void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness);
++
++void isppreview_set_color(u8 *mode);
++
++void isppreview_get_color(u8 *mode);
++
++void isppreview_query_brightness(u8 *brightness);
++
++void isppreview_config_yc_range(struct ispprev_yclimit yclimit);
++
++int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w,
++ u32 *output_h);
++
++int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w,
++ u32 output_h);
++
++int isppreview_config_inlineoffset(u32 offset);
++
++int isppreview_set_inaddr(u32 addr);
++
++int isppreview_config_outlineoffset(u32 offset);
++
++int isppreview_set_outaddr(u32 addr);
++
++int isppreview_config_darklineoffset(u32 offset);
++
++int isppreview_set_darkaddr(u32 addr);
++
++void isppreview_enable(int enable);
++
++void isppreview_suspend(void);
++
++void isppreview_resume(void);
++
++int isppreview_busy(void);
++
++struct prev_params *isppreview_get_config(void);
++
++void isppreview_print_status(void);
++
++#ifndef CONFIG_ARCH_OMAP3410
++void isppreview_save_context(void);
++#else
++static inline void isppreview_save_context(void) {}
++#endif
++
++#ifndef CONFIG_ARCH_OMAP3410
++void isppreview_restore_context(void);
++#else
++static inline void isppreview_restore_context(void) {}
++#endif
++
++int omap34xx_isp_preview_config(void *userspace_add);
++
++int omap34xx_isp_tables_update(struct isptables_update *isptables_struct);
++
++void isppreview_set_skip(u32 h, u32 v);
++
++#endif/* OMAP_ISP_PREVIEW_H */
+diff --git a/drivers/media/video/isp/ispresizer.c b/drivers/media/video/isp/ispresizer.c
+new file mode 100644
+index 0000000..f78ddb3
+--- /dev/null
++++ b/drivers/media/video/isp/ispresizer.c
+@@ -0,0 +1,928 @@
++/*
++ * ispresizer.c
++ *
++ * Driver Library for Resizer module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C)2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sameer Venkatraman <sameerv@ti.com>
++ * Mohit Jalori
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/module.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "ispresizer.h"
++
++/* Default configuration of resizer,filter coefficients,yenh for camera isp */
++static struct isprsz_yenh ispreszdefaultyenh = {0, 0, 0, 0};
++static struct isprsz_coef ispreszdefcoef = {
++ {
++ 0x0027, 0x00B2, 0x00B2, 0x0027,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ 0x0027, 0x00B2, 0x0027, 0x00B2,
++ },
++ {
++ 0x0000, 0x0100, 0x0000, 0x0000,
++ 0x03FA, 0x00F6, 0x0010, 0x0000,
++ 0x03F9, 0x00DB, 0x002C, 0x0000,
++ 0x03FB, 0x00B3, 0x0053, 0x03FF,
++ 0x03FD, 0x0082, 0x0084, 0x03FD,
++ 0x03FF, 0x0053, 0x00B3, 0x03FB,
++ 0x0000, 0x002C, 0x00DB, 0x03F9,
++ 0x0000, 0x0010, 0x00F6, 0x03FA
++ },
++ {
++ 0x0004, 0x0023, 0x0023, 0x005A,
++ 0x005A, 0x0058, 0x0058, 0x0004,
++ 0x0023, 0x0023, 0x005A, 0x005A,
++ 0x0058, 0x0058, 0x0004, 0x0023,
++ 0x0023, 0x005A, 0x005A, 0x0058,
++ 0x0058, 0x0004, 0x0023, 0x0023,
++ 0x005A, 0x005A, 0x0058, 0x0058
++ },
++ {
++ 0x0004, 0x0023, 0x005A, 0x0058,
++ 0x0023, 0x0004, 0x0000, 0x0002,
++ 0x0018, 0x004d, 0x0060, 0x0031,
++ 0x0008, 0x0000, 0x0001, 0x000f,
++ 0x003f, 0x0062, 0x003f, 0x000f,
++ 0x0001, 0x0000, 0x0008, 0x0031,
++ 0x0060, 0x004d, 0x0018, 0x0002
++ }
++};
++
++/**
++ * struct isp_res - Structure for the resizer module to store its information.
++ * @res_inuse: Indicates if resizer module has been reserved. 1 - Reserved,
++ * 0 - Freed.
++ * @h_startphase: Horizontal starting phase.
++ * @v_startphase: Vertical starting phase.
++ * @h_resz: Horizontal resizing value.
++ * @v_resz: Vertical resizing value.
++ * @outputwidth: Output Image Width in pixels.
++ * @outputheight: Output Image Height in pixels.
++ * @inputwidth: Input Image Width in pixels.
++ * @inputheight: Input Image Height in pixels.
++ * @algo: Algorithm select. 0 - Disable, 1 - [-1 2 -1]/2 high-pass filter,
++ * 2 - [-1 -2 6 -2 -1]/4 high-pass filter.
++ * @ipht_crop: Vertical start line for cropping.
++ * @ipwd_crop: Horizontal start pixel for cropping.
++ * @cropwidth: Crop Width.
++ * @cropheight: Crop Height.
++ * @resinput: Resizer input.
++ * @coeflist: Register configuration for Resizer.
++ * @ispres_mutex: Mutex for isp resizer.
++ */
++static struct isp_res {
++ int pm_state;
++ u8 res_inuse;
++ u8 h_startphase;
++ u8 v_startphase;
++ u16 h_resz;
++ u16 v_resz;
++ u32 outputwidth;
++ u32 outputheight;
++ u32 inputwidth;
++ u32 inputheight;
++ u8 algo;
++ u32 ipht_crop;
++ u32 ipwd_crop;
++ u32 cropwidth;
++ u32 cropheight;
++ dma_addr_t tmp_buf;
++ enum ispresizer_input resinput;
++ struct isprsz_coef coeflist;
++ struct mutex ispres_mutex; /* For checking/modifying res_inuse */
++} ispres_obj;
++
++/* Structure for saving/restoring resizer module registers */
++static struct isp_reg isprsz_reg_list[] = {
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT32, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT54, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT76, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT98, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1110, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1312, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1514, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1716, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1918, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2120, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2322, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2524, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2726, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2928, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT3130, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT32, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT54, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT76, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT98, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1110, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1312, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1514, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1716, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1918, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2120, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2322, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2524, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2726, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2928, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT3130, 0x0000},
++ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH, 0x0000},
++ {0, ISP_TOK_TERM, 0x0000}
++};
++
++/**
++ * ispresizer_config_shadow_registers - Configure shadow registers.
++ **/
++void ispresizer_config_shadow_registers()
++{
++ return;
++}
++EXPORT_SYMBOL(ispresizer_config_shadow_registers);
++
++/**
++ * ispresizer_trycrop - Validate crop dimensions.
++ * @left: Left distance to start position of crop.
++ * @top: Top distance to start position of crop.
++ * @width: Width of input image.
++ * @height: Height of input image.
++ * @ow: Width of output image.
++ * @oh: Height of output image.
++ **/
++void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
++ u32 oh)
++{
++ ispres_obj.cropwidth = width + 6;
++ ispres_obj.cropheight = height + 6;
++ ispresizer_try_size(&ispres_obj.cropwidth, &ispres_obj.cropheight, &ow,
++ &oh);
++ ispres_obj.ipht_crop = top;
++ ispres_obj.ipwd_crop = left;
++}
++EXPORT_SYMBOL(ispresizer_trycrop);
++
++/**
++ * ispresizer_applycrop - Apply crop to input image.
++ **/
++void ispresizer_applycrop(void)
++{
++ ispresizer_config_size(ispres_obj.cropwidth, ispres_obj.cropheight,
++ ispres_obj.outputwidth,
++ ispres_obj.outputheight);
++ return;
++}
++EXPORT_SYMBOL(ispresizer_applycrop);
++
++/**
++ * ispresizer_request - Reserves the Resizer module.
++ *
++ * Allows only one user at a time.
++ *
++ * Returns 0 if successful, or -EBUSY if resizer module was already requested.
++ **/
++int ispresizer_request()
++{
++ mutex_lock(&ispres_obj.ispres_mutex);
++ if (!ispres_obj.res_inuse) {
++ ispres_obj.res_inuse = 1;
++ mutex_unlock(&ispres_obj.ispres_mutex);
++ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL) |
++ ISPCTRL_SBL_WR0_RAM_EN |
++ ISPCTRL_RSZ_CLK_EN,
++ OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
++ return 0;
++ } else {
++ mutex_unlock(&ispres_obj.ispres_mutex);
++ printk(KERN_ERR "ISP_ERR : Resizer Module Busy\n");
++ return -EBUSY;
++ }
++}
++EXPORT_SYMBOL(ispresizer_request);
++
++/**
++ * ispresizer_free - Makes Resizer module free.
++ *
++ * Returns 0 if successful, or -EINVAL if resizer module was already freed.
++ **/
++int ispresizer_free()
++{
++ mutex_lock(&ispres_obj.ispres_mutex);
++ if (ispres_obj.res_inuse) {
++ ispres_obj.res_inuse = 0;
++ mutex_unlock(&ispres_obj.ispres_mutex);
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
++ ~(ISPCTRL_RSZ_CLK_EN | ISPCTRL_SBL_WR0_RAM_EN));
++ return 0;
++ } else {
++ mutex_unlock(&ispres_obj.ispres_mutex);
++ DPRINTK_ISPRESZ("ISP_ERR : Resizer Module already freed\n");
++ return -EINVAL;
++ }
++}
++EXPORT_SYMBOL(ispresizer_free);
++
++/**
++ * ispresizer_config_datapath - Specifies which input to use in resizer module
++ * @input: Indicates the module that gives the image to resizer.
++ *
++ * Sets up the default resizer configuration according to the arguments.
++ *
++ * Returns 0 if successful, or -EINVAL if an unsupported input was requested.
++ **/
++int ispresizer_config_datapath(enum ispresizer_input input)
++{
++ u32 cnt = 0;
++ DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n");
++ ispres_obj.resinput = input;
++ switch (input) {
++ case RSZ_OTFLY_YUV:
++ cnt &= ~ISPRSZ_CNT_INPTYP;
++ cnt &= ~ISPRSZ_CNT_INPSRC;
++ ispresizer_set_inaddr(0);
++ ispresizer_config_inlineoffset(0);
++ break;
++ case RSZ_MEM_YUV:
++ cnt |= ISPRSZ_CNT_INPSRC;
++ cnt &= ~ISPRSZ_CNT_INPTYP;
++ break;
++ case RSZ_MEM_COL8:
++ cnt |= ISPRSZ_CNT_INPSRC;
++ cnt |= ISPRSZ_CNT_INPTYP;
++ break;
++ default:
++ printk(KERN_ERR "ISP_ERR : Wrong Input\n");
++ return -EINVAL;
++ }
++ isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt);
++ ispresizer_config_ycpos(0);
++ ispresizer_config_filter_coef(&ispreszdefcoef);
++ ispresizer_enable_cbilin(0);
++ ispresizer_config_luma_enhance(&ispreszdefaultyenh);
++ DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_config_datapath);
++
++/**
++ * ispresizer_try_size - Validates input and output images size.
++ * @input_w: input width for the resizer in number of pixels per line
++ * @input_h: input height for the resizer in number of lines
++ * @output_w: output width from the resizer in number of pixels per line
++ * resizer when writing to memory needs this to be multiple of 16.
++ * @output_h: output height for the resizer in number of lines, must be even.
++ *
++ * Calculates the horizontal and vertical resize ratio, number of pixels to
++ * be cropped in the resizer module and checks the validity of various
++ * parameters. Formula used for calculation is:-
++ *
++ * 8-phase 4-tap mode :-
++ * inputwidth = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
++ * inputheight = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
++ * endpahse for width = ((32 * sph + (ow - 1) * hrsz + 16) >> 5) % 8
++ * endphase for height = ((32 * sph + (oh - 1) * hrsz + 16) >> 5) % 8
++ *
++ * 4-phase 7-tap mode :-
++ * inputwidth = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
++ * inputheight = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
++ * endpahse for width = ((64 * sph + (ow - 1) * hrsz + 32) >> 6) % 4
++ * endphase for height = ((64 * sph + (oh - 1) * hrsz + 32) >> 6) % 4
++ *
++ * Where:
++ * sph = Start phase horizontal
++ * spv = Start phase vertical
++ * ow = Output width
++ * oh = Output height
++ * hrsz = Horizontal resize value
++ * vrsz = Vertical resize value
++ *
++ * Fills up the output/input widht/height, horizontal/vertical resize ratio,
++ * horizontal/vertical crop variables in the isp_res structure.
++ **/
++int ispresizer_try_size(u32 *input_width, u32 *input_height, u32 *output_w,
++ u32 *output_h)
++{
++ u32 rsz, rsz_7, rsz_4;
++ u32 sph;
++ u32 input_w, input_h;
++ int max_in_otf, max_out_7tap;
++
++ input_w = *input_width;
++ input_h = *input_height;
++
++ if (input_w < 32 || input_h < 32) {
++ DPRINTK_ISPCCDC("ISP_ERR: RESIZER cannot handle input width"
++ " less than 32 pixels or height less than"
++ " 32\n");
++ return -EINVAL;
++ }
++ input_w -= 6;
++ input_h -= 6;
++
++ if (input_h > MAX_IN_HEIGHT)
++ return -EINVAL;
++
++ if (*output_w < 16)
++ *output_w = 16;
++
++ if (*output_h < 2)
++ *output_h = 2;
++
++ if (omap_rev() == OMAP3430_REV_ES1_0) {
++ max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE;
++ max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH;
++ } else {
++ max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
++ max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH_ES2;
++ }
++
++ if (ispres_obj.resinput == RSZ_OTFLY_YUV) {
++ if (input_w > max_in_otf)
++ return -EINVAL;
++ } else {
++ if (input_w > MAX_IN_WIDTH_MEMORY_MODE)
++ return -EINVAL;
++ }
++
++ *output_h &= 0xfffffffe;
++ sph = DEFAULTSTPHASE;
++
++ rsz_7 = ((input_h - 7) * 256) / (*output_h - 1);
++ rsz_4 = ((input_h - 4) * 256) / (*output_h - 1);
++
++ rsz = (input_h * 256) / *output_h;
++
++ if (rsz <= MID_RESIZE_VALUE) {
++ rsz = rsz_4;
++ if (rsz < MINIMUM_RESIZE_VALUE) {
++ rsz = MINIMUM_RESIZE_VALUE;
++ *output_h = (((input_h - 4) * 256) / rsz) + 1;
++ printk(KERN_INFO "%s: using output_h %d instead\n",
++ __func__, *output_h);
++ }
++ } else {
++ rsz = rsz_7;
++ if (*output_w > max_out_7tap)
++ *output_w = max_out_7tap;
++ if (rsz > MAXIMUM_RESIZE_VALUE) {
++ rsz = MAXIMUM_RESIZE_VALUE;
++ *output_h = (((input_h - 7) * 256) / rsz) + 1;
++ printk(KERN_INFO "%s: using output_h %d instead\n",
++ __func__, *output_h);
++ }
++ }
++
++ if (rsz > MID_RESIZE_VALUE) {
++ input_h =
++ (((64 * sph) + ((*output_h - 1) * rsz) + 32) / 256) + 7;
++ } else {
++ input_h =
++ (((32 * sph) + ((*output_h - 1) * rsz) + 16) / 256) + 4;
++ }
++
++ ispres_obj.outputheight = *output_h;
++ ispres_obj.v_resz = rsz;
++ ispres_obj.inputheight = input_h;
++ ispres_obj.ipht_crop = DEFAULTSTPIXEL;
++ ispres_obj.v_startphase = sph;
++
++ *output_w &= 0xfffffff0;
++ sph = DEFAULTSTPHASE;
++
++ rsz_7 = ((input_w - 7) * 256) / (*output_w - 1);
++ rsz_4 = ((input_w - 4) * 256) / (*output_w - 1);
++
++ rsz = (input_w * 256) / *output_w;
++ if (rsz > MID_RESIZE_VALUE) {
++ rsz = rsz_7;
++ if (rsz > MAXIMUM_RESIZE_VALUE) {
++ rsz = MAXIMUM_RESIZE_VALUE;
++ *output_w = (((input_w - 7) * 256) / rsz) + 1;
++ *output_w = (*output_w + 0xf) & 0xfffffff0;
++ printk(KERN_INFO "%s: using output_w %d instead\n",
++ __func__, *output_w);
++ }
++ } else {
++ rsz = rsz_4;
++ if (rsz < MINIMUM_RESIZE_VALUE) {
++ rsz = MINIMUM_RESIZE_VALUE;
++ *output_w = (((input_w - 4) * 256) / rsz) + 1;
++ *output_w = (*output_w + 0xf) & 0xfffffff0;
++ printk(KERN_INFO "%s: using output_w %d instead\n",
++ __func__, *output_w);
++ }
++ }
++
++ /* Recalculate input based on TRM equations */
++ if (rsz > MID_RESIZE_VALUE) {
++ input_w =
++ (((64 * sph) + ((*output_w - 1) * rsz) + 32) / 256) + 7;
++ } else {
++ input_w =
++ (((32 * sph) + ((*output_w - 1) * rsz) + 16) / 256) + 7;
++ }
++
++ ispres_obj.outputwidth = *output_w;
++ ispres_obj.h_resz = rsz;
++ ispres_obj.inputwidth = input_w;
++ ispres_obj.ipwd_crop = DEFAULTSTPIXEL;
++ ispres_obj.h_startphase = sph;
++
++ *input_height = input_h;
++ *input_width = input_w;
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_try_size);
++
++/**
++ * ispresizer_config_size - Configures input and output image size.
++ * @input_w: input width for the resizer in number of pixels per line.
++ * @input_h: input height for the resizer in number of lines.
++ * @output_w: output width from the resizer in number of pixels per line.
++ * @output_h: output height for the resizer in number of lines.
++ *
++ * Configures the appropriate values stored in the isp_res structure in the
++ * resizer registers.
++ *
++ * Returns 0 if successful, or -EINVAL if passed values haven't been verified
++ * with ispresizer_try_size() previously.
++ **/
++int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
++ u32 output_h)
++{
++ int i, j;
++ u32 res;
++ DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h ="
++ " %d, output_w = %d, output_h"
++ " = %d,hresz = %d,vresz = %d,"
++ " hcrop = %d, vcrop = %d,"
++ " hstph = %d, vstph = %d\n",
++ ispres_obj.inputwidth,
++ ispres_obj.inputheight,
++ ispres_obj.outputwidth,
++ ispres_obj.outputheight,
++ ispres_obj.h_resz,
++ ispres_obj.v_resz,
++ ispres_obj.ipwd_crop,
++ ispres_obj.ipht_crop,
++ ispres_obj.h_startphase,
++ ispres_obj.v_startphase);
++ if ((output_w != ispres_obj.outputwidth)
++ || (output_h != ispres_obj.outputheight)) {
++ printk(KERN_ERR "Output parameters passed do not match the"
++ " values calculated by the"
++ " trysize passed w %d, h %d"
++ " \n", output_w , output_h);
++ return -EINVAL;
++ }
++
++ /* Set Resizer input address and offset adderss */
++ ispresizer_config_inlineoffset(isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
++ ISPPRV_WADD_OFFSET));
++
++ res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
++ ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
++ isp_reg_writel(res |
++ (ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) |
++ (ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_CNT);
++ /* Set start address for cropping */
++ isp_reg_writel(ispres_obj.tmp_buf + 2 *
++ (ispres_obj.ipht_crop * ispres_obj.inputwidth +
++ (ispres_obj.ipwd_crop & ~15)),
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
++
++ isp_reg_writel(
++ ((ispres_obj.ipwd_crop & 15) << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
++ (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
++
++ isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
++ (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_IN_START);
++
++ isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) |
++ (ispres_obj.inputheight <<
++ ISPRSZ_IN_SIZE_VERT_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_IN_SIZE);
++ if (!ispres_obj.algo) {
++ isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
++ (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_OUT_SIZE);
++ } else {
++ isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
++ (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_OUT_SIZE);
++ }
++
++ res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
++ ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
++ isp_reg_writel(res |
++ ((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) |
++ ((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_CNT);
++ if (ispres_obj.h_resz <= MID_RESIZE_VALUE) {
++ j = 0;
++ for (i = 0; i < 16; i++) {
++ isp_reg_writel(
++ (ispres_obj.coeflist.h_filter_coef_4tap[j]
++ << ISPRSZ_HFILT10_COEF0_SHIFT) |
++ (ispres_obj.coeflist.h_filter_coef_4tap[j + 1]
++ << ISPRSZ_HFILT10_COEF1_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_HFILT10 + (i * 0x04));
++ j += 2;
++ }
++ } else {
++ j = 0;
++ for (i = 0; i < 16; i++) {
++ if ((i + 1) % 4 == 0) {
++ isp_reg_writel((ispres_obj.coeflist.
++ h_filter_coef_7tap[j] <<
++ ISPRSZ_HFILT10_COEF0_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_HFILT10 + (i * 0x04));
++ j += 1;
++ } else {
++ isp_reg_writel((ispres_obj.coeflist.
++ h_filter_coef_7tap[j] <<
++ ISPRSZ_HFILT10_COEF0_SHIFT) |
++ (ispres_obj.coeflist.
++ h_filter_coef_7tap[j+1] <<
++ ISPRSZ_HFILT10_COEF1_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_HFILT10 + (i * 0x04));
++ j += 2;
++ }
++ }
++ }
++ if (ispres_obj.v_resz <= MID_RESIZE_VALUE) {
++ j = 0;
++ for (i = 0; i < 16; i++) {
++ isp_reg_writel((ispres_obj.coeflist.
++ v_filter_coef_4tap[j] <<
++ ISPRSZ_VFILT10_COEF0_SHIFT) |
++ (ispres_obj.coeflist.
++ v_filter_coef_4tap[j + 1] <<
++ ISPRSZ_VFILT10_COEF1_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_VFILT10 + (i * 0x04));
++ j += 2;
++ }
++ } else {
++ j = 0;
++ for (i = 0; i < 16; i++) {
++ if ((i + 1) % 4 == 0) {
++ isp_reg_writel((ispres_obj.coeflist.
++ v_filter_coef_7tap[j] <<
++ ISPRSZ_VFILT10_COEF0_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_VFILT10 + (i * 0x04));
++ j += 1;
++ } else {
++ isp_reg_writel((ispres_obj.coeflist.
++ v_filter_coef_7tap[j] <<
++ ISPRSZ_VFILT10_COEF0_SHIFT) |
++ (ispres_obj.coeflist.
++ v_filter_coef_7tap[j+1] <<
++ ISPRSZ_VFILT10_COEF1_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_VFILT10 + (i * 0x04));
++ j += 2;
++ }
++ }
++ }
++
++ ispresizer_config_outlineoffset(output_w*2);
++ DPRINTK_ISPRESZ("ispresizer_config_size()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_config_size);
++
++void __ispresizer_enable(int enable)
++{
++ int val;
++ DPRINTK_ISPRESZ("+ispresizer_enable()+\n");
++ if (enable) {
++ val = (isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & 0x2) |
++ ISPRSZ_PCR_ENABLE;
++ } else {
++ val = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
++ ~ISPRSZ_PCR_ENABLE;
++ }
++ isp_reg_writel(val, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR);
++ DPRINTK_ISPRESZ("+ispresizer_enable()-\n");
++}
++
++/**
++ * ispresizer_enable - Enables the resizer module.
++ * @enable: 1 - Enable, 0 - Disable
++ *
++ * Client should configure all the sub modules in resizer before this.
++ **/
++void ispresizer_enable(int enable)
++{
++ __ispresizer_enable(enable);
++ ispres_obj.pm_state = enable;
++}
++EXPORT_SYMBOL(ispresizer_enable);
++
++/**
++ * ispresizer_suspend - Suspend resizer module.
++ **/
++void ispresizer_suspend(void)
++{
++ if (ispres_obj.pm_state)
++ __ispresizer_enable(0);
++}
++EXPORT_SYMBOL(ispresizer_suspend);
++
++/**
++ * ispresizer_resume - Resume resizer module.
++ **/
++void ispresizer_resume(void)
++{
++ if (ispres_obj.pm_state)
++ __ispresizer_enable(1);
++}
++EXPORT_SYMBOL(ispresizer_resume);
++
++/**
++ * ispresizer_busy - Checks if ISP resizer is busy.
++ *
++ * Returns busy field from ISPRSZ_PCR register.
++ **/
++int ispresizer_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
++ ISPPRV_PCR_BUSY;
++}
++EXPORT_SYMBOL(ispresizer_busy);
++
++/**
++ * ispresizer_config_startphase - Sets the horizontal and vertical start phase.
++ * @hstartphase: horizontal start phase (0 - 7).
++ * @vstartphase: vertical startphase (0 - 7).
++ *
++ * This API just updates the isp_res struct. Actual register write happens in
++ * ispresizer_config_size.
++ **/
++void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase)
++{
++ DPRINTK_ISPRESZ("ispresizer_config_startphase()+\n");
++ ispres_obj.h_startphase = hstartphase;
++ ispres_obj.v_startphase = vstartphase;
++ DPRINTK_ISPRESZ("ispresizer_config_startphase()-\n");
++}
++EXPORT_SYMBOL(ispresizer_config_startphase);
++
++/**
++ * ispresizer_config_ycpos - Specifies if output should be in YC or CY format.
++ * @yc: 0 - YC format, 1 - CY format
++ **/
++void ispresizer_config_ycpos(u8 yc)
++{
++ DPRINTK_ISPRESZ("ispresizer_config_ycpos()+\n");
++ isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS,
++ (yc ? ISPRSZ_CNT_YCPOS : 0));
++ DPRINTK_ISPRESZ("ispresizer_config_ycpos()-\n");
++}
++EXPORT_SYMBOL(ispresizer_config_ycpos);
++
++/**
++ * Sets the chrominance algorithm
++ * @cbilin: 0 - chrominance uses same processing as luminance,
++ * 1 - bilinear interpolation processing
++ **/
++void ispresizer_enable_cbilin(u8 enable)
++{
++ DPRINTK_ISPRESZ("ispresizer_enable_cbilin()+\n");
++ isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN,
++ (enable ? ISPRSZ_CNT_CBILIN : 0));
++ DPRINTK_ISPRESZ("ispresizer_enable_cbilin()-\n");
++}
++EXPORT_SYMBOL(ispresizer_enable_cbilin);
++
++/**
++ * ispresizer_config_luma_enhance - Configures luminance enhancer parameters.
++ * @yenh: Pointer to structure containing desired values for core, slope, gain
++ * and algo parameters.
++ **/
++void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh)
++{
++ DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()+\n");
++ ispres_obj.algo = yenh->algo;
++ isp_reg_writel((yenh->algo << ISPRSZ_YENH_ALGO_SHIFT) |
++ (yenh->gain << ISPRSZ_YENH_GAIN_SHIFT) |
++ (yenh->slope << ISPRSZ_YENH_SLOP_SHIFT) |
++ (yenh->coreoffset << ISPRSZ_YENH_CORE_SHIFT),
++ OMAP3_ISP_IOMEM_RESZ,
++ ISPRSZ_YENH);
++ DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()-\n");
++}
++EXPORT_SYMBOL(ispresizer_config_luma_enhance);
++
++/**
++ * ispresizer_config_filter_coef - Sets filter coefficients for 4 & 7-tap mode.
++ * This API just updates the isp_res struct.Actual register write happens in
++ * ispresizer_config_size.
++ * @coef: Structure containing horizontal and vertical filter coefficients for
++ * both 4-tap and 7-tap mode.
++ **/
++void ispresizer_config_filter_coef(struct isprsz_coef *coef)
++{
++ int i;
++ DPRINTK_ISPRESZ("ispresizer_config_filter_coef()+\n");
++ for (i = 0; i < 32; i++) {
++ ispres_obj.coeflist.h_filter_coef_4tap[i] =
++ coef->h_filter_coef_4tap[i];
++ ispres_obj.coeflist.v_filter_coef_4tap[i] =
++ coef->v_filter_coef_4tap[i];
++ }
++ for (i = 0; i < 28; i++) {
++ ispres_obj.coeflist.h_filter_coef_7tap[i] =
++ coef->h_filter_coef_7tap[i];
++ ispres_obj.coeflist.v_filter_coef_7tap[i] =
++ coef->v_filter_coef_7tap[i];
++ }
++ DPRINTK_ISPRESZ("ispresizer_config_filter_coef()-\n");
++}
++EXPORT_SYMBOL(ispresizer_config_filter_coef);
++
++/**
++ * ispresizer_config_inlineoffset - Configures the read address line offset.
++ * @offset: Line Offset for the input image.
++ *
++ * Returns 0 if successful, or -EINVAL if offset is not 32 bits aligned.
++ **/
++int ispresizer_config_inlineoffset(u32 offset)
++{
++ DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()+\n");
++ if (offset % 32)
++ return -EINVAL;
++ isp_reg_writel(offset << ISPRSZ_SDR_INOFF_OFFSET_SHIFT,
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
++ DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_config_inlineoffset);
++
++/**
++ * ispresizer_set_inaddr - Sets the memory address of the input frame.
++ * @addr: 32bit memory address aligned on 32byte boundary.
++ *
++ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
++ **/
++int ispresizer_set_inaddr(u32 addr)
++{
++ DPRINTK_ISPRESZ("ispresizer_set_inaddr()+\n");
++ if (addr % 32)
++ return -EINVAL;
++ isp_reg_writel(addr << ISPRSZ_SDR_INADD_ADDR_SHIFT,
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
++ ispres_obj.tmp_buf = addr;
++ DPRINTK_ISPRESZ("ispresizer_set_inaddr()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_set_inaddr);
++
++/**
++ * ispresizer_config_outlineoffset - Configures the write address line offset.
++ * @offset: Line offset for the preview output.
++ *
++ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
++ **/
++int ispresizer_config_outlineoffset(u32 offset)
++{
++ DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()+\n");
++ if (offset % 32)
++ return -EINVAL;
++ isp_reg_writel(offset << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT,
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
++ DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_config_outlineoffset);
++
++/**
++ * Configures the memory address to which the output frame is written.
++ * @addr: 32bit memory address aligned on 32byte boundary.
++ **/
++int ispresizer_set_outaddr(u32 addr)
++{
++ DPRINTK_ISPRESZ("ispresizer_set_outaddr()+\n");
++ if (addr % 32)
++ return -EINVAL;
++ isp_reg_writel(addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
++ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
++ DPRINTK_ISPRESZ("ispresizer_set_outaddr()-\n");
++ return 0;
++}
++EXPORT_SYMBOL(ispresizer_set_outaddr);
++
++/**
++ * ispresizer_save_context - Saves the values of the resizer module registers.
++ **/
++void ispresizer_save_context(void)
++{
++ DPRINTK_ISPRESZ("Saving context\n");
++ isp_save_context(isprsz_reg_list);
++}
++EXPORT_SYMBOL(ispresizer_save_context);
++
++/**
++ * ispresizer_restore_context - Restores resizer module register values.
++ **/
++void ispresizer_restore_context(void)
++{
++ DPRINTK_ISPRESZ("Restoring context\n");
++ isp_restore_context(isprsz_reg_list);
++}
++EXPORT_SYMBOL(ispresizer_restore_context);
++
++/**
++ * ispresizer_print_status - Prints the values of the resizer module registers.
++ **/
++void ispresizer_print_status()
++{
++ if (!is_ispresz_debug_enabled())
++ return;
++ DPRINTK_ISPRESZ("###ISP_CTRL inresizer =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ DPRINTK_ISPRESZ("###ISP_IRQ0ENABLE in resizer =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
++ DPRINTK_ISPRESZ("###ISP_IRQ0STATUS in resizer =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
++ DPRINTK_ISPRESZ("###RSZ PCR =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR));
++ DPRINTK_ISPRESZ("###RSZ CNT =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT));
++ DPRINTK_ISPRESZ("###RSZ OUT SIZE =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE));
++ DPRINTK_ISPRESZ("###RSZ IN START =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START));
++ DPRINTK_ISPRESZ("###RSZ IN SIZE =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE));
++ DPRINTK_ISPRESZ("###RSZ SDR INADD =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD));
++ DPRINTK_ISPRESZ("###RSZ SDR INOFF =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF));
++ DPRINTK_ISPRESZ("###RSZ SDR OUTADD =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD));
++ DPRINTK_ISPRESZ("###RSZ SDR OTOFF =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF));
++ DPRINTK_ISPRESZ("###RSZ YENH =0x%x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH));
++}
++EXPORT_SYMBOL(ispresizer_print_status);
++
++/**
++ * isp_resizer_init - Module Initialisation.
++ *
++ * Always returns 0.
++ **/
++int __init isp_resizer_init(void)
++{
++ mutex_init(&ispres_obj.ispres_mutex);
++ ispres_obj.pm_state = 0;
++ return 0;
++}
++
++/**
++ * isp_resizer_cleanup - Module Cleanup.
++ **/
++void isp_resizer_cleanup(void)
++{
++}
+diff --git a/drivers/media/video/isp/ispresizer.h b/drivers/media/video/isp/ispresizer.h
+new file mode 100644
+index 0000000..4e92225
+--- /dev/null
++++ b/drivers/media/video/isp/ispresizer.h
+@@ -0,0 +1,158 @@
++/*
++ * ispresizer.h
++ *
++ * Driver header file for Resizer module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sameer Venkatraman <sameerv@ti.com>
++ * Mohit Jalori
++ * Sergio Aguirre <saaguirre@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_RESIZER_H
++#define OMAP_ISP_RESIZER_H
++
++/*
++ * Resizer Constants
++ */
++#define MAX_IN_WIDTH_MEMORY_MODE 4095
++
++#define MAX_IN_WIDTH_ONTHEFLY_MODE 1280
++#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2 4095
++#define MAX_IN_HEIGHT 4095
++#define MINIMUM_RESIZE_VALUE 64
++#define MAXIMUM_RESIZE_VALUE 1024
++#define MID_RESIZE_VALUE 512
++
++#define MAX_7TAP_HRSZ_OUTWIDTH 1280
++#define MAX_7TAP_VRSZ_OUTWIDTH 640
++
++#define MAX_7TAP_HRSZ_OUTWIDTH_ES2 3300
++#define MAX_7TAP_VRSZ_OUTWIDTH_ES2 1650
++
++#define DEFAULTSTPIXEL 0
++#define DEFAULTSTPHASE 1
++#define DEFAULTHSTPIXEL4TAPMODE 3
++#define FOURPHASE 4
++#define EIGHTPHASE 8
++#define RESIZECONSTANT 256
++#define SHIFTER4TAPMODE 0
++#define SHIFTER7TAPMODE 1
++#define DEFAULTOFFSET 7
++#define OFFSETVERT4TAPMODE 4
++#define OPWDALIGNCONSTANT 0xfffffff0
++
++/*
++ * The client is supposed to call resizer API in the following sequence:
++ * - request()
++ * - config_datatpath()
++ * - optionally config/enable sub modules
++ * - try/config size
++ * - setup callback
++ * - setup in/out memory offsets and ptrs
++ * - enable()
++ * ...
++ * - disable()
++ * - free()
++ */
++
++enum ispresizer_input {
++ RSZ_OTFLY_YUV,
++ RSZ_MEM_YUV,
++ RSZ_MEM_COL8
++};
++
++/**
++ * struct isprsz_coef - Structure for resizer filter coeffcients.
++ * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
++ * mode (.5x-4x)
++ * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
++ * mode (.5x-4x)
++ * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
++ * mode (.25x-.5x)
++ * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
++ * mode (.25x-.5x)
++ */
++struct isprsz_coef {
++ u16 h_filter_coef_4tap[32];
++ u16 v_filter_coef_4tap[32];
++ u16 h_filter_coef_7tap[28];
++ u16 v_filter_coef_7tap[28];
++};
++
++/**
++ * struct isprsz_yenh - Structure for resizer luminance enhancer parameters.
++ * @algo: Algorithm select.
++ * @gain: Maximum gain.
++ * @slope: Slope.
++ * @coreoffset: Coring offset.
++ */
++struct isprsz_yenh {
++ u8 algo;
++ u8 gain;
++ u8 slope;
++ u8 coreoffset;
++};
++
++void ispresizer_config_shadow_registers(void);
++
++int ispresizer_request(void);
++
++int ispresizer_free(void);
++
++int ispresizer_config_datapath(enum ispresizer_input input);
++
++void ispresizer_enable_cbilin(u8 enable);
++
++void ispresizer_config_ycpos(u8 yc);
++
++void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase);
++
++void ispresizer_config_filter_coef(struct isprsz_coef *coef);
++
++void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh);
++
++int ispresizer_try_size(u32 *input_w, u32 *input_h, u32 *output_w,
++ u32 *output_h);
++
++void ispresizer_applycrop(void);
++
++void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
++ u32 oh);
++
++int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
++ u32 output_h);
++
++int ispresizer_config_inlineoffset(u32 offset);
++
++int ispresizer_set_inaddr(u32 addr);
++
++int ispresizer_config_outlineoffset(u32 offset);
++
++int ispresizer_set_outaddr(u32 addr);
++
++void ispresizer_enable(int enable);
++
++void ispresizer_suspend(void);
++
++void ispresizer_resume(void);
++
++int ispresizer_busy(void);
++
++void ispresizer_save_context(void);
++
++void ispresizer_restore_context(void);
++
++void ispresizer_print_status(void);
++
++#endif /* OMAP_ISP_RESIZER_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
new file mode 100644
index 0000000000..876ce780f0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
@@ -0,0 +1,2741 @@
+From 9a39eab5ed1b70711c3b10de95cd90749293ef7a Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add statistics collection modules (H3A and HIST)
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/isp_af.c | 784 +++++++++++++++++++++++++++++++
+ drivers/media/video/isp/isp_af.h | 125 +++++
+ drivers/media/video/isp/isph3a.c | 932 +++++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/isph3a.h | 127 +++++
+ drivers/media/video/isp/isphist.c | 608 ++++++++++++++++++++++++
+ drivers/media/video/isp/isphist.h | 105 +++++
+ 6 files changed, 2681 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/isp_af.c
+ create mode 100644 drivers/media/video/isp/isp_af.h
+ create mode 100644 drivers/media/video/isp/isph3a.c
+ create mode 100644 drivers/media/video/isp/isph3a.h
+ create mode 100644 drivers/media/video/isp/isphist.c
+ create mode 100644 drivers/media/video/isp/isphist.h
+
+diff --git a/drivers/media/video/isp/isp_af.c b/drivers/media/video/isp/isp_af.c
+new file mode 100644
+index 0000000..a607b97
+--- /dev/null
++++ b/drivers/media/video/isp/isp_af.c
+@@ -0,0 +1,784 @@
++/*
++ * isp_af.c
++ *
++ * AF module for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/* Linux specific include files */
++#include <asm/cacheflush.h>
++
++#include <linux/uaccess.h>
++#include <linux/dma-mapping.h>
++#include <asm/atomic.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "isph3a.h"
++#include "isp_af.h"
++#include "ispmmu.h"
++
++/**
++ * struct isp_af_buffer - AF frame stats buffer.
++ * @virt_addr: Virtual address to mmap the buffer.
++ * @phy_addr: Physical address of the buffer.
++ * @addr_align: Virtual Address 32 bytes aligned.
++ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
++ * @mmap_addr: Mapped memory area of buffer. For userspace access.
++ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
++ * @frame_num: Frame number from which the statistics are taken.
++ * @lens_position: Lens position currently set in the DW9710 Coil motor driver.
++ * @next: Pointer to link next buffer.
++ */
++struct isp_af_buffer {
++ unsigned long virt_addr;
++ unsigned long phy_addr;
++ unsigned long addr_align;
++ unsigned long ispmmu_addr;
++ unsigned long mmap_addr;
++
++ u8 locked;
++ u16 frame_num;
++ u32 config_counter;
++ struct isp_af_xtrastats xtrastats;
++ struct isp_af_buffer *next;
++};
++
++/**
++ * struct isp_af_status - AF status.
++ * @initialized: 1 - Buffers initialized.
++ * @update: 1 - Update registers.
++ * @stats_req: 1 - Future stats requested.
++ * @stats_done: 1 - Stats ready for user.
++ * @frame_req: Number of frame requested for statistics.
++ * @af_buff: Array of statistics buffers to access.
++ * @stats_buf_size: Statistics buffer size.
++ * @curr_cfg_buf_size: Current user configured stats buff size.
++ * @min_buf_size: Minimum statisitics buffer size.
++ * @frame_count: Frame Count.
++ * @stats_wait: Wait primitive for locking/unlocking the stats request.
++ * @buffer_lock: Spinlock for statistics buffers access.
++ */
++static struct isp_af_status {
++ u8 initialized;
++ u8 update;
++ u8 stats_req;
++ u8 stats_done;
++ u16 frame_req;
++
++ struct isp_af_buffer af_buff[H3A_MAX_BUFF];
++ unsigned int stats_buf_size;
++ unsigned int min_buf_size;
++ unsigned int curr_cfg_buf_size;
++
++ int pm_state;
++ u32 frame_count;
++ wait_queue_head_t stats_wait;
++ atomic_t config_counter;
++ spinlock_t buffer_lock; /* For stats buffers read/write sync */
++} afstat;
++
++struct af_device *af_dev_configptr;
++static struct isp_af_buffer *active_buff;
++static int af_major = -1;
++static int camnotify;
++
++/**
++ * isp_af_setxtrastats - Receives extra statistics from prior frames.
++ * @xtrastats: Pointer to structure containing extra statistics fields like
++ * field count and timestamp of frame.
++ *
++ * Called from update_vbq in camera driver
++ **/
++void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag)
++{
++ int i, past_i;
++
++ if (active_buff == NULL)
++ return;
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if (afstat.af_buff[i].frame_num == active_buff->frame_num)
++ break;
++ }
++
++ if (i == H3A_MAX_BUFF)
++ return;
++
++ if (i == 0) {
++ if (afstat.af_buff[H3A_MAX_BUFF - 1].locked == 0)
++ past_i = H3A_MAX_BUFF - 1;
++ else
++ past_i = H3A_MAX_BUFF - 2;
++ } else if (i == 1) {
++ if (afstat.af_buff[0].locked == 0)
++ past_i = 0;
++ else
++ past_i = H3A_MAX_BUFF - 1;
++ } else {
++ if (afstat.af_buff[i - 1].locked == 0)
++ past_i = i - 1;
++ else
++ past_i = i - 2;
++ }
++
++ if (updateflag & AF_UPDATEXS_TS)
++ afstat.af_buff[past_i].xtrastats.ts = xtrastats->ts;
++
++ if (updateflag & AF_UPDATEXS_FIELDCOUNT)
++ afstat.af_buff[past_i].xtrastats.field_count =
++ xtrastats->field_count;
++}
++EXPORT_SYMBOL(isp_af_setxtrastats);
++
++/*
++ * Helper function to update buffer cache pages
++ */
++static void isp_af_update_req_buffer(struct isp_af_buffer *buffer)
++{
++ int size = afstat.stats_buf_size;
++
++ size = PAGE_ALIGN(size);
++ /* Update the kernel pages of the requested buffer */
++ dmac_inv_range((void *)buffer->addr_align, (void *)buffer->addr_align +
++ size);
++}
++
++#define IS_OUT_OF_BOUNDS(value, min, max) \
++ (((value) < (min)) || ((value) > (max)))
++
++/* Function to check paxel parameters */
++int isp_af_check_paxel(void)
++{
++ struct af_paxel *paxel_cfg = &af_dev_configptr->config->paxel_config;
++ struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
++
++ /* Check horizontal Count */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->hz_cnt, AF_PAXEL_HORIZONTAL_COUNT_MIN,
++ AF_PAXEL_HORIZONTAL_COUNT_MAX)) {
++ DPRINTK_ISP_AF("Error : Horizontal Count is incorrect");
++ return -AF_ERR_HZ_COUNT;
++ }
++
++ /*Check Vertical Count */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_cnt, AF_PAXEL_VERTICAL_COUNT_MIN,
++ AF_PAXEL_VERTICAL_COUNT_MAX)) {
++ DPRINTK_ISP_AF("Error : Vertical Count is incorrect");
++ return -AF_ERR_VT_COUNT;
++ }
++
++ /*Check Height */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->height, AF_PAXEL_HEIGHT_MIN,
++ AF_PAXEL_HEIGHT_MAX)) {
++ DPRINTK_ISP_AF("Error : Height is incorrect");
++ return -AF_ERR_HEIGHT;
++ }
++
++ /*Check width */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->width, AF_PAXEL_WIDTH_MIN,
++ AF_PAXEL_WIDTH_MAX)) {
++ DPRINTK_ISP_AF("Error : Width is incorrect");
++ return -AF_ERR_WIDTH;
++ }
++
++ /*Check Line Increment */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->line_incr, AF_PAXEL_INCREMENT_MIN,
++ AF_PAXEL_INCREMENT_MAX)) {
++ DPRINTK_ISP_AF("Error : Line Increment is incorrect");
++ return -AF_ERR_INCR;
++ }
++
++ /*Check Horizontal Start */
++ if ((paxel_cfg->hz_start % 2 != 0) ||
++ (paxel_cfg->hz_start < (iir_cfg->hz_start_pos + 2)) ||
++ IS_OUT_OF_BOUNDS(paxel_cfg->hz_start,
++ AF_PAXEL_HZSTART_MIN, AF_PAXEL_HZSTART_MAX)) {
++ DPRINTK_ISP_AF("Error : Horizontal Start is incorrect");
++ return -AF_ERR_HZ_START;
++ }
++
++ /*Check Vertical Start */
++ if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_start, AF_PAXEL_VTSTART_MIN,
++ AF_PAXEL_VTSTART_MAX)) {
++ DPRINTK_ISP_AF("Error : Vertical Start is incorrect");
++ return -AF_ERR_VT_START;
++ }
++ return 0;
++}
++
++/**
++ * isp_af_check_iir - Function to check IIR Coefficient.
++ **/
++int isp_af_check_iir(void)
++{
++ struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
++ int index;
++
++ for (index = 0; index < AF_NUMBER_OF_COEF; index++) {
++ if ((iir_cfg->coeff_set0[index]) > AF_COEF_MAX) {
++ DPRINTK_ISP_AF("Error : Coefficient for set 0 is "
++ "incorrect");
++ return -AF_ERR_IIR_COEF;
++ }
++
++ if ((iir_cfg->coeff_set1[index]) > AF_COEF_MAX) {
++ DPRINTK_ISP_AF("Error : Coefficient for set 1 is "
++ "incorrect");
++ return -AF_ERR_IIR_COEF;
++ }
++ }
++
++ if (IS_OUT_OF_BOUNDS(iir_cfg->hz_start_pos, AF_IIRSH_MIN,
++ AF_IIRSH_MAX)) {
++ DPRINTK_ISP_AF("Error : IIRSH is incorrect");
++ return -AF_ERR_IIRSH;
++ }
++
++ return 0;
++}
++/**
++ * isp_af_unlock_buffers - Helper function to unlock all buffers.
++ **/
++static void isp_af_unlock_buffers(void)
++{
++ int i;
++ unsigned long irqflags;
++
++ spin_lock_irqsave(&afstat.buffer_lock, irqflags);
++ for (i = 0; i < H3A_MAX_BUFF; i++)
++ afstat.af_buff[i].locked = 0;
++
++ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
++}
++
++/*
++ * Helper function to link allocated buffers
++ */
++static void isp_af_link_buffers(void)
++{
++ int i;
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if ((i + 1) < H3A_MAX_BUFF)
++ afstat.af_buff[i].next = &afstat.af_buff[i + 1];
++ else
++ afstat.af_buff[i].next = &afstat.af_buff[0];
++ }
++}
++
++/* Function to perform hardware set up */
++int isp_af_configure(struct af_configuration *afconfig)
++{
++ int result;
++ int buff_size, i;
++ unsigned int busyaf;
++ struct af_configuration *af_curr_cfg = af_dev_configptr->config;
++
++ if (NULL == afconfig) {
++ printk(KERN_ERR "Null argument in configuration. \n");
++ return -EINVAL;
++ }
++
++ memcpy(af_curr_cfg, afconfig, sizeof(struct af_configuration));
++ /* Get the value of PCR register */
++ busyaf = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++
++ if ((busyaf & AF_BUSYAF) == AF_BUSYAF) {
++ DPRINTK_ISP_AF("AF_register_setup_ERROR : Engine Busy");
++ DPRINTK_ISP_AF("\n Configuration cannot be done ");
++ return -AF_ERR_ENGINE_BUSY;
++ }
++
++ /* Check IIR Coefficient and start Values */
++ result = isp_af_check_iir();
++ if (result < 0)
++ return result;
++
++ /* Check Paxel Values */
++ result = isp_af_check_paxel();
++ if (result < 0)
++ return result;
++
++ /* Check HMF Threshold Values */
++ if (af_curr_cfg->hmf_config.threshold > AF_THRESHOLD_MAX) {
++ DPRINTK_ISP_AF("Error : HMF Threshold is incorrect");
++ return -AF_ERR_THRESHOLD;
++ }
++
++ /* Compute buffer size */
++ buff_size = (af_curr_cfg->paxel_config.hz_cnt + 1) *
++ (af_curr_cfg->paxel_config.vt_cnt + 1) * AF_PAXEL_SIZE;
++
++ afstat.curr_cfg_buf_size = buff_size;
++ /* Deallocate the previous buffers */
++ if (afstat.stats_buf_size && buff_size > afstat.stats_buf_size) {
++ isp_af_enable(0);
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
++ dma_free_coherent(
++ NULL, afstat.min_buf_size,
++ (void *)afstat.af_buff[i].virt_addr,
++ (dma_addr_t)afstat.af_buff[i].phy_addr);
++ afstat.af_buff[i].virt_addr = 0;
++ }
++ afstat.stats_buf_size = 0;
++ }
++
++ if (!afstat.af_buff[0].virt_addr) {
++ afstat.stats_buf_size = buff_size;
++ afstat.min_buf_size = PAGE_ALIGN(afstat.stats_buf_size);
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ afstat.af_buff[i].virt_addr =
++ (unsigned long)dma_alloc_coherent(
++ NULL,
++ afstat.min_buf_size,
++ (dma_addr_t *)
++ &afstat.af_buff[i].phy_addr,
++ GFP_KERNEL | GFP_DMA);
++ if (afstat.af_buff[i].virt_addr == 0) {
++ printk(KERN_ERR "Can't acquire memory for "
++ "buffer[%d]\n", i);
++ return -ENOMEM;
++ }
++ afstat.af_buff[i].addr_align =
++ afstat.af_buff[i].virt_addr;
++ while ((afstat.af_buff[i].addr_align & 0xFFFFFFC0) !=
++ afstat.af_buff[i].addr_align)
++ afstat.af_buff[i].addr_align++;
++ afstat.af_buff[i].ispmmu_addr =
++ ispmmu_kmap(afstat.af_buff[i].phy_addr,
++ afstat.min_buf_size);
++ }
++ isp_af_unlock_buffers();
++ isp_af_link_buffers();
++
++ /* First active buffer */
++ if (active_buff == NULL)
++ active_buff = &afstat.af_buff[0];
++ isp_af_set_address(active_buff->ispmmu_addr);
++ }
++
++ result = isp_af_register_setup(af_dev_configptr);
++ if (result < 0)
++ return result;
++ af_dev_configptr->size_paxel = buff_size;
++ atomic_inc(&afstat.config_counter);
++ afstat.initialized = 1;
++ afstat.frame_count = 1;
++ active_buff->frame_num = 1;
++ /* Set configuration flag to indicate HW setup done */
++ if (af_curr_cfg->af_config)
++ isp_af_enable(1);
++ else
++ isp_af_enable(0);
++
++ /* Success */
++ return 0;
++}
++EXPORT_SYMBOL(isp_af_configure);
++
++int isp_af_register_setup(struct af_device *af_dev)
++{
++ unsigned int pcr = 0, pax1 = 0, pax2 = 0, paxstart = 0;
++ unsigned int coef = 0;
++ unsigned int base_coef_set0 = 0;
++ unsigned int base_coef_set1 = 0;
++ int index;
++
++ /* Configure Hardware Registers */
++ /* Read PCR Register */
++ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++
++ /* Set Accumulator Mode */
++ if (af_dev->config->mode == ACCUMULATOR_PEAK)
++ pcr |= FVMODE;
++ else
++ pcr &= ~FVMODE;
++
++ /* Set A-law */
++ if (af_dev->config->alaw_enable == H3A_AF_ALAW_ENABLE)
++ pcr |= AF_ALAW_EN;
++ else
++ pcr &= ~AF_ALAW_EN;
++
++ /* Set RGB Position */
++ pcr &= ~RGBPOS;
++ pcr |= af_dev->config->rgb_pos << AF_RGBPOS_SHIFT;
++
++ /* HMF Configurations */
++ if (af_dev->config->hmf_config.enable == H3A_AF_HMF_ENABLE) {
++ pcr &= ~AF_MED_EN;
++ /* Enable HMF */
++ pcr |= AF_MED_EN;
++
++ /* Set Median Threshold */
++ pcr &= ~MED_TH;
++ pcr |= af_dev->config->hmf_config.threshold << AF_MED_TH_SHIFT;
++ } else
++ pcr &= ~AF_MED_EN;
++
++ /* Set PCR Register */
++ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++
++ pax1 &= ~PAXW;
++ pax1 |= af_dev->config->paxel_config.width << AF_PAXW_SHIFT;
++
++ /* Set height in AFPAX1 */
++ pax1 &= ~PAXH;
++ pax1 |= af_dev->config->paxel_config.height;
++
++ isp_reg_writel(pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
++
++ /* Configure AFPAX2 Register */
++ /* Set Line Increment in AFPAX2 Register */
++ pax2 &= ~AFINCV;
++ pax2 |= af_dev->config->paxel_config.line_incr << AF_LINE_INCR_SHIFT;
++ /* Set Vertical Count */
++ pax2 &= ~PAXVC;
++ pax2 |= af_dev->config->paxel_config.vt_cnt << AF_VT_COUNT_SHIFT;
++ /* Set Horizontal Count */
++ pax2 &= ~PAXHC;
++ pax2 |= af_dev->config->paxel_config.hz_cnt;
++ isp_reg_writel(pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
++
++ /* Configure PAXSTART Register */
++ /*Configure Horizontal Start */
++ paxstart &= ~PAXSH;
++ paxstart |= af_dev->config->paxel_config.hz_start << AF_HZ_START_SHIFT;
++ /* Configure Vertical Start */
++ paxstart &= ~PAXSV;
++ paxstart |= af_dev->config->paxel_config.vt_start;
++ isp_reg_writel(paxstart, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART);
++
++ /*SetIIRSH Register */
++ isp_reg_writel(af_dev->config->iir_config.hz_start_pos,
++ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
++
++ /*Set IIR Filter0 Coefficients */
++ base_coef_set0 = ISPH3A_AFCOEF010;
++ for (index = 0; index <= 8; index += 2) {
++ coef &= ~COEF_MASK0;
++ coef |= af_dev->config->iir_config.coeff_set0[index];
++ coef &= ~COEF_MASK1;
++ coef |= af_dev->config->iir_config.coeff_set0[index + 1] <<
++ AF_COEF_SHIFT;
++ isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set0);
++ base_coef_set0 = base_coef_set0 + AFCOEF_OFFSET;
++ }
++
++ /* set AFCOEF0010 Register */
++ isp_reg_writel(af_dev->config->iir_config.coeff_set0[10],
++ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010);
++
++ /*Set IIR Filter1 Coefficients */
++
++ base_coef_set1 = ISPH3A_AFCOEF110;
++ for (index = 0; index <= 8; index += 2) {
++ coef &= ~COEF_MASK0;
++ coef |= af_dev->config->iir_config.coeff_set1[index];
++ coef &= ~COEF_MASK1;
++ coef |= af_dev->config->iir_config.coeff_set1[index + 1] <<
++ AF_COEF_SHIFT;
++ isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set1);
++
++ base_coef_set1 = base_coef_set1 + AFCOEF_OFFSET;
++ }
++ isp_reg_writel(af_dev->config->iir_config.coeff_set1[10],
++ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
++
++ return 0;
++}
++
++/* Function to set address */
++void isp_af_set_address(unsigned long address)
++{
++ isp_reg_writel(address, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST);
++}
++
++static int isp_af_stats_available(struct isp_af_data *afdata)
++{
++ int i, ret;
++ unsigned long irqflags;
++
++ spin_lock_irqsave(&afstat.buffer_lock, irqflags);
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ DPRINTK_ISP_AF("Checking Stats buff[%d] (%d) for %d\n",
++ i, afstat.af_buff[i].frame_num,
++ afdata->frame_number);
++ if (afdata->frame_number == afstat.af_buff[i].frame_num
++ && afstat.af_buff[i].frame_num != active_buff->frame_num) {
++ afstat.af_buff[i].locked = 1;
++ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
++ isp_af_update_req_buffer(&afstat.af_buff[i]);
++ afstat.af_buff[i].frame_num = 0;
++ ret = copy_to_user((void *)afdata->af_statistics_buf,
++ (void *)afstat.af_buff[i].virt_addr,
++ afstat.curr_cfg_buf_size);
++ if (ret) {
++ printk(KERN_ERR "Failed copy_to_user for "
++ "H3A stats buff, %d\n", ret);
++ }
++ afdata->xtrastats.ts = afstat.af_buff[i].xtrastats.ts;
++ afdata->xtrastats.field_count =
++ afstat.af_buff[i].xtrastats.field_count;
++ return 0;
++ }
++ }
++ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
++ /* Stats unavailable */
++
++ return -1;
++}
++
++void isp_af_notify(int notify)
++{
++ camnotify = notify;
++ if (camnotify && afstat.initialized) {
++ printk(KERN_DEBUG "Warning Camera Off \n");
++ afstat.stats_req = 0;
++ afstat.stats_done = 1;
++ wake_up_interruptible(&afstat.stats_wait);
++ }
++}
++EXPORT_SYMBOL(isp_af_notify);
++/*
++ * This API allows the user to update White Balance gains, as well as
++ * exposure time and analog gain. It is also used to request frame
++ * statistics.
++ */
++int isp_af_request_statistics(struct isp_af_data *afdata)
++{
++ int ret = 0;
++ u16 frame_diff = 0;
++ u16 frame_cnt = afstat.frame_count;
++ wait_queue_t wqt;
++
++ if (!af_dev_configptr->config->af_config) {
++ printk(KERN_ERR "AF engine not enabled\n");
++ return -EINVAL;
++ }
++
++ if (!(afdata->update & REQUEST_STATISTICS)) {
++ afdata->af_statistics_buf = NULL;
++ goto out;
++ }
++
++ isp_af_unlock_buffers();
++ /* Stats available? */
++ DPRINTK_ISP_AF("Stats available?\n");
++ ret = isp_af_stats_available(afdata);
++ if (!ret)
++ goto out;
++
++ /* Stats in near future? */
++ DPRINTK_ISP_AF("Stats in near future?\n");
++ if (afdata->frame_number > frame_cnt)
++ frame_diff = afdata->frame_number - frame_cnt;
++ else if (afdata->frame_number < frame_cnt) {
++ if (frame_cnt > MAX_FRAME_COUNT - MAX_FUTURE_FRAMES
++ && afdata->frame_number < MAX_FRAME_COUNT) {
++ frame_diff = afdata->frame_number + MAX_FRAME_COUNT -
++ frame_cnt;
++ } else {
++ /* Frame unavailable */
++ frame_diff = MAX_FUTURE_FRAMES + 1;
++ }
++ }
++
++ if (frame_diff > MAX_FUTURE_FRAMES) {
++ printk(KERN_ERR "Invalid frame requested, returning current"
++ " frame stats\n");
++ afdata->frame_number = frame_cnt;
++ }
++ if (!camnotify) {
++ /* Block until frame in near future completes */
++ afstat.frame_req = afdata->frame_number;
++ afstat.stats_req = 1;
++ afstat.stats_done = 0;
++ init_waitqueue_entry(&wqt, current);
++ ret = wait_event_interruptible(afstat.stats_wait,
++ afstat.stats_done == 1);
++ if (ret < 0) {
++ afdata->af_statistics_buf = NULL;
++ return ret;
++ }
++ DPRINTK_ISP_AF("ISP AF request status interrupt raised\n");
++
++ /* Stats now available */
++ ret = isp_af_stats_available(afdata);
++ if (ret) {
++ printk(KERN_ERR "After waiting for stats, stats not"
++ " available!!\n");
++ afdata->af_statistics_buf = NULL;
++ }
++ }
++
++out:
++ afdata->curr_frame = afstat.frame_count;
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_af_request_statistics);
++
++/* This function will handle the H3A interrupt. */
++static void isp_af_isr(unsigned long status, isp_vbq_callback_ptr arg1,
++ void *arg2)
++{
++ u16 frame_align;
++
++ if ((H3A_AF_DONE & status) != H3A_AF_DONE)
++ return;
++
++ /* timestamp stats buffer */
++ do_gettimeofday(&active_buff->xtrastats.ts);
++ active_buff->config_counter = atomic_read(&afstat.config_counter);
++
++ /* Exchange buffers */
++ active_buff = active_buff->next;
++ if (active_buff->locked == 1)
++ active_buff = active_buff->next;
++ isp_af_set_address(active_buff->ispmmu_addr);
++
++ /* Update frame counter */
++ afstat.frame_count++;
++ frame_align = afstat.frame_count;
++ if (afstat.frame_count > MAX_FRAME_COUNT) {
++ afstat.frame_count = 1;
++ frame_align++;
++ }
++ active_buff->frame_num = afstat.frame_count;
++
++ /* Future Stats requested? */
++ if (afstat.stats_req) {
++ /* Is the frame we want already done? */
++ if (frame_align >= afstat.frame_req + 1) {
++ afstat.stats_req = 0;
++ afstat.stats_done = 1;
++ wake_up_interruptible(&afstat.stats_wait);
++ }
++ }
++}
++
++int __isp_af_enable(int enable)
++{
++ unsigned int pcr;
++
++ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++
++ /* Set AF_EN bit in PCR Register */
++ if (enable) {
++ if (isp_set_callback(CBK_H3A_AF_DONE, isp_af_isr,
++ (void *)NULL, (void *)NULL)) {
++ printk(KERN_ERR "No callback for AF\n");
++ return -EINVAL;
++ }
++
++ pcr |= AF_EN;
++ } else {
++ isp_unset_callback(CBK_H3A_AF_DONE);
++ pcr &= ~AF_EN;
++ }
++ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++ return 0;
++}
++
++/* Function to Enable/Disable AF Engine */
++int isp_af_enable(int enable)
++{
++ int rval;
++
++ rval = __isp_af_enable(enable);
++
++ if (!rval)
++ afstat.pm_state = enable;
++
++ return rval;
++}
++
++/* Function to Suspend AF Engine */
++void isp_af_suspend(void)
++{
++ if (afstat.pm_state)
++ __isp_af_enable(0);
++}
++
++/* Function to Resume AF Engine */
++void isp_af_resume(void)
++{
++ if (afstat.pm_state)
++ __isp_af_enable(1);
++}
++
++int isp_af_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
++ & ISPH3A_PCR_BUSYAF;
++}
++
++/* Function to register the AF character device driver. */
++int __init isp_af_init(void)
++{
++ /*allocate memory for device structure and initialize it with 0 */
++ af_dev_configptr = kzalloc(sizeof(struct af_device), GFP_KERNEL);
++ if (!af_dev_configptr)
++ goto err_nomem1;
++
++ active_buff = NULL;
++
++ af_dev_configptr->config = (struct af_configuration *)
++ kzalloc(sizeof(struct af_configuration), GFP_KERNEL);
++
++ if (af_dev_configptr->config == NULL)
++ goto err_nomem2;
++
++ memset(&afstat, 0, sizeof(afstat));
++
++ init_waitqueue_head(&afstat.stats_wait);
++ spin_lock_init(&afstat.buffer_lock);
++
++ return 0;
++
++err_nomem2:
++ kfree(af_dev_configptr);
++err_nomem1:
++ printk(KERN_ERR "Error: kmalloc fail");
++ return -ENOMEM;
++}
++
++void isp_af_exit(void)
++{
++ int i;
++
++ /* Free buffers */
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if (!afstat.af_buff[i].phy_addr)
++ continue;
++
++ ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
++
++ dma_free_coherent(NULL,
++ afstat.min_buf_size,
++ (void *)afstat.af_buff[i].virt_addr,
++ (dma_addr_t)afstat.af_buff[i].phy_addr);
++ }
++ kfree(af_dev_configptr->config);
++ kfree(af_dev_configptr);
++
++ memset(&afstat, 0, sizeof(afstat));
++
++ af_major = -1;
++}
+diff --git a/drivers/media/video/isp/isp_af.h b/drivers/media/video/isp/isp_af.h
+new file mode 100644
+index 0000000..ee2b89f
+--- /dev/null
++++ b/drivers/media/video/isp/isp_af.h
+@@ -0,0 +1,125 @@
++/*
++ * isp_af.h
++ *
++ * Include file for AF module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/* Device Constants */
++#ifndef OMAP_ISP_AF_H
++#define OMAP_ISP_AF_H
++
++#include <mach/isp_user.h>
++
++#define AF_MAJOR_NUMBER 0
++#define ISPAF_NAME "OMAPISP_AF"
++#define AF_NR_DEVS 1
++#define AF_TIMEOUT ((300 * HZ) / 1000)
++
++
++
++/* Print Macros */
++/*list of error code */
++#define AF_ERR_HZ_COUNT 800 /* Invalid Horizontal Count */
++#define AF_ERR_VT_COUNT 801 /* Invalid Vertical Count */
++#define AF_ERR_HEIGHT 802 /* Invalid Height */
++#define AF_ERR_WIDTH 803 /* Invalid width */
++#define AF_ERR_INCR 804 /* Invalid Increment */
++#define AF_ERR_HZ_START 805 /* Invalid horizontal Start */
++#define AF_ERR_VT_START 806 /* Invalud vertical Start */
++#define AF_ERR_IIRSH 807 /* Invalid IIRSH value */
++#define AF_ERR_IIR_COEF 808 /* Invalid Coefficient */
++#define AF_ERR_SETUP 809 /* Setup not done */
++#define AF_ERR_THRESHOLD 810 /* Invalid Threshold */
++#define AF_ERR_ENGINE_BUSY 811 /* Engine is busy */
++
++#define AFPID 0x0 /* Peripheral Revision
++ * and Class Information
++ */
++
++#define AFCOEF_OFFSET 0x00000004 /* COEFFICIENT BASE
++ * ADDRESS
++ */
++
++/*
++ * PCR fields
++ */
++#define AF_BUSYAF (1 << 15)
++#define FVMODE (1 << 14)
++#define RGBPOS (0x7 << 11)
++#define MED_TH (0xFF << 3)
++#define AF_MED_EN (1 << 2)
++#define AF_ALAW_EN (1 << 1)
++#define AF_EN (1 << 0)
++
++/*
++ * AFPAX1 fields
++ */
++#define PAXW (0x7F << 16)
++#define PAXH 0x7F
++
++/*
++ * AFPAX2 fields
++ */
++#define AFINCV (0xF << 13)
++#define PAXVC (0x7F << 6)
++#define PAXHC 0x3F
++
++/*
++ * AFPAXSTART fields
++ */
++#define PAXSH (0xFFF<<16)
++#define PAXSV 0xFFF
++
++/*
++ * COEFFICIENT MASK
++ */
++
++#define COEF_MASK0 0xFFF
++#define COEF_MASK1 (0xFFF<<16)
++
++/* BIT SHIFTS */
++#define AF_RGBPOS_SHIFT 11
++#define AF_MED_TH_SHIFT 3
++#define AF_PAXW_SHIFT 16
++#define AF_LINE_INCR_SHIFT 13
++#define AF_VT_COUNT_SHIFT 6
++#define AF_HZ_START_SHIFT 16
++#define AF_COEF_SHIFT 16
++
++#define AF_UPDATEXS_TS (1 << 0)
++#define AF_UPDATEXS_FIELDCOUNT (1 << 1)
++#define AF_UPDATEXS_LENSPOS (1 << 2)
++
++/* Structure for device of AF Engine */
++struct af_device {
++ struct af_configuration *config; /*Device configuration structure */
++ int size_paxel; /*Paxel size in bytes */
++};
++
++int isp_af_check_paxel(void);
++int isp_af_check_iir(void);
++int isp_af_register_setup(struct af_device *af_dev);
++int isp_af_enable(int);
++void isp_af_suspend(void);
++void isp_af_resume(void);
++int isp_af_busy(void);
++void isp_af_notify(int notify);
++int isp_af_request_statistics(struct isp_af_data *afdata);
++int isp_af_configure(struct af_configuration *afconfig);
++void isp_af_set_address(unsigned long);
++void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag);
++#endif /* OMAP_ISP_AF_H */
+diff --git a/drivers/media/video/isp/isph3a.c b/drivers/media/video/isp/isph3a.c
+new file mode 100644
+index 0000000..7ff1c5b
+--- /dev/null
++++ b/drivers/media/video/isp/isph3a.c
+@@ -0,0 +1,932 @@
++/*
++ * isph3a.c
++ *
++ * H3A module for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <asm/cacheflush.h>
++
++#include <linux/dma-mapping.h>
++#include <linux/uaccess.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "isph3a.h"
++#include "ispmmu.h"
++#include "isppreview.h"
++
++/**
++ * struct isph3a_aewb_buffer - AE, AWB frame stats buffer.
++ * @virt_addr: Virtual address to mmap the buffer.
++ * @phy_addr: Physical address of the buffer.
++ * @addr_align: Virtual Address 32 bytes aligned.
++ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
++ * @mmap_addr: Mapped memory area of buffer. For userspace access.
++ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
++ * @frame_num: Frame number from which the statistics are taken.
++ * @next: Pointer to link next buffer.
++ */
++struct isph3a_aewb_buffer {
++ unsigned long virt_addr;
++ unsigned long phy_addr;
++ unsigned long addr_align;
++ unsigned long ispmmu_addr;
++ unsigned long mmap_addr; /* For userspace */
++ struct timeval ts;
++ u32 config_counter;
++
++ u8 locked;
++ u16 frame_num;
++ struct isph3a_aewb_buffer *next;
++};
++
++/**
++ * struct isph3a_aewb_status - AE, AWB status.
++ * @initialized: 1 - Buffers initialized.
++ * @update: 1 - Update registers.
++ * @stats_req: 1 - Future stats requested.
++ * @stats_done: 1 - Stats ready for user.
++ * @frame_req: Number of frame requested for statistics.
++ * @h3a_buff: Array of statistics buffers to access.
++ * @stats_buf_size: Statistics buffer size.
++ * @min_buf_size: Minimum statisitics buffer size.
++ * @win_count: Window Count.
++ * @frame_count: Frame Count.
++ * @stats_wait: Wait primitive for locking/unlocking the stats request.
++ * @buffer_lock: Spinlock for statistics buffers access.
++ */
++static struct isph3a_aewb_status {
++ u8 initialized;
++ u8 update;
++ u8 stats_req;
++ u8 stats_done;
++ u16 frame_req;
++ int pm_state;
++
++ struct isph3a_aewb_buffer h3a_buff[H3A_MAX_BUFF];
++ unsigned int stats_buf_size;
++ unsigned int min_buf_size;
++ unsigned int curr_cfg_buf_size;
++
++ atomic_t config_counter;
++
++ u16 win_count;
++ u32 frame_count;
++ wait_queue_head_t stats_wait;
++ spinlock_t buffer_lock; /* For stats buffers read/write sync */
++} aewbstat;
++
++/**
++ * struct isph3a_aewb_regs - Current value of AE, AWB configuration registers.
++ * reg_pcr: Peripheral control register.
++ * reg_win1: Control register.
++ * reg_start: Start position register.
++ * reg_blk: Black line register.
++ * reg_subwin: Configuration register.
++ */
++static struct isph3a_aewb_regs {
++ u32 reg_pcr;
++ u32 reg_win1;
++ u32 reg_start;
++ u32 reg_blk;
++ u32 reg_subwin;
++} aewb_regs;
++
++static struct isph3a_aewb_config aewb_config_local = {
++ .saturation_limit = 0x3FF,
++ .win_height = 0,
++ .win_width = 0,
++ .ver_win_count = 0,
++ .hor_win_count = 0,
++ .ver_win_start = 0,
++ .hor_win_start = 0,
++ .blk_ver_win_start = 0,
++ .blk_win_height = 0,
++ .subsample_ver_inc = 0,
++ .subsample_hor_inc = 0,
++ .alaw_enable = 0,
++ .aewb_enable = 0,
++};
++
++/* Structure for saving/restoring h3a module registers */
++static struct isp_reg isph3a_reg_list[] = {
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, 0}, /* Should be the first one */
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF032, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF054, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF076, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF098, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF110, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF132, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF154, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF176, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF198, 0},
++ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010, 0},
++ {0, ISP_TOK_TERM, 0}
++};
++
++static struct ispprev_wbal h3awb_update;
++static struct isph3a_aewb_buffer *active_buff;
++static struct isph3a_aewb_xtrastats h3a_xtrastats[H3A_MAX_BUFF];
++static int camnotify;
++static int wb_update;
++static void isph3a_print_status(void);
++
++/**
++ * isph3a_aewb_setxtrastats - Receives extra statistics from prior frames.
++ * @xtrastats: Pointer to structure containing extra statistics fields like
++ * field count and timestamp of frame.
++ *
++ * Called from update_vbq in camera driver
++ **/
++void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats)
++{
++ int i;
++
++ if (active_buff == NULL)
++ return;
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if (aewbstat.h3a_buff[i].frame_num != active_buff->frame_num)
++ continue;
++
++ if (i == 0) {
++ if (aewbstat.h3a_buff[H3A_MAX_BUFF - 1].locked == 0) {
++ h3a_xtrastats[H3A_MAX_BUFF - 1] =
++ *xtrastats;
++ } else {
++ h3a_xtrastats[H3A_MAX_BUFF - 2] =
++ *xtrastats;
++ }
++ } else if (i == 1) {
++ if (aewbstat.h3a_buff[0].locked == 0)
++ h3a_xtrastats[0] = *xtrastats;
++ else {
++ h3a_xtrastats[H3A_MAX_BUFF - 1] =
++ *xtrastats;
++ }
++ } else {
++ if (aewbstat.h3a_buff[i - 1].locked == 0)
++ h3a_xtrastats[i - 1] = *xtrastats;
++ else
++ h3a_xtrastats[i - 2] = *xtrastats;
++ }
++ return;
++ }
++}
++EXPORT_SYMBOL(isph3a_aewb_setxtrastats);
++
++void __isph3a_aewb_enable(u8 enable)
++{
++ isp_reg_writel(IRQ0STATUS_H3A_AWB_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
++ ISP_IRQ0STATUS);
++
++ if (enable) {
++ aewb_regs.reg_pcr |= ISPH3A_PCR_AEW_EN;
++ DPRINTK_ISPH3A(" H3A enabled \n");
++ } else {
++ aewb_regs.reg_pcr &= ~ISPH3A_PCR_AEW_EN;
++ DPRINTK_ISPH3A(" H3A disabled \n");
++ }
++ isp_reg_and_or(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ~ISPH3A_PCR_AEW_EN,
++ (enable ? ISPH3A_PCR_AEW_EN : 0));
++ aewb_config_local.aewb_enable = enable;
++}
++
++/**
++ * isph3a_aewb_enable - Enables AE, AWB engine in the H3A module.
++ * @enable: 1 - Enables the AE & AWB engine.
++ *
++ * Client should configure all the AE & AWB registers in H3A before this.
++ **/
++void isph3a_aewb_enable(u8 enable)
++{
++ __isph3a_aewb_enable(enable);
++ aewbstat.pm_state = enable;
++}
++
++/**
++ * isph3a_aewb_suspend - Suspend AE, AWB engine in the H3A module.
++ **/
++void isph3a_aewb_suspend(void)
++{
++ if (aewbstat.pm_state)
++ __isph3a_aewb_enable(0);
++}
++
++/**
++ * isph3a_aewb_resume - Resume AE, AWB engine in the H3A module.
++ **/
++void isph3a_aewb_resume(void)
++{
++ if (aewbstat.pm_state)
++ __isph3a_aewb_enable(1);
++}
++
++int isph3a_aewb_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
++ & ISPH3A_PCR_BUSYAEAWB;
++}
++
++/**
++ * isph3a_update_wb - Updates WB parameters.
++ *
++ * Needs to be called when no ISP Preview processing is taking place.
++ **/
++void isph3a_update_wb(void)
++{
++ if (wb_update) {
++ isppreview_config_whitebalance(h3awb_update);
++ wb_update = 0;
++ }
++ return;
++}
++EXPORT_SYMBOL(isph3a_update_wb);
++
++/**
++ * isph3a_aewb_update_regs - Helper function to update h3a registers.
++ **/
++static void isph3a_aewb_update_regs(void)
++{
++ isp_reg_writel(aewb_regs.reg_pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
++ isp_reg_writel(aewb_regs.reg_win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
++ isp_reg_writel(aewb_regs.reg_start, OMAP3_ISP_IOMEM_H3A,
++ ISPH3A_AEWINSTART);
++ isp_reg_writel(aewb_regs.reg_blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
++ isp_reg_writel(aewb_regs.reg_subwin, OMAP3_ISP_IOMEM_H3A,
++ ISPH3A_AEWSUBWIN);
++
++ aewbstat.update = 0;
++ aewbstat.frame_count = 1;
++}
++
++/**
++ * isph3a_aewb_update_req_buffer - Helper function to update buffer cache pages
++ * @buffer: Pointer to structure
++ **/
++static void isph3a_aewb_update_req_buffer(struct isph3a_aewb_buffer *buffer)
++{
++ int size = aewbstat.stats_buf_size;
++
++ size = PAGE_ALIGN(size);
++ dmac_inv_range((void *)buffer->addr_align,
++ (void *)buffer->addr_align + size);
++}
++
++/**
++ * isph3a_aewb_stats_available - Check for stats available of specified frame.
++ * @aewbdata: Pointer to return AE AWB statistics data
++ *
++ * Returns 0 if successful, or -1 if statistics are unavailable.
++ **/
++static int isph3a_aewb_stats_available(struct isph3a_aewb_data *aewbdata)
++{
++ int i, ret;
++ unsigned long irqflags;
++
++ spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ DPRINTK_ISPH3A("Checking Stats buff[%d] (%d) for %d\n",
++ i, aewbstat.h3a_buff[i].frame_num,
++ aewbdata->frame_number);
++ if ((aewbdata->frame_number !=
++ aewbstat.h3a_buff[i].frame_num) ||
++ (aewbstat.h3a_buff[i].frame_num ==
++ active_buff->frame_num))
++ continue;
++ aewbstat.h3a_buff[i].locked = 1;
++ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
++ isph3a_aewb_update_req_buffer(&aewbstat.h3a_buff[i]);
++ aewbstat.h3a_buff[i].frame_num = 0;
++ ret = copy_to_user((void *)aewbdata->h3a_aewb_statistics_buf,
++ (void *)aewbstat.h3a_buff[i].virt_addr,
++ aewbstat.curr_cfg_buf_size);
++ if (ret) {
++ printk(KERN_ERR "Failed copy_to_user for "
++ "H3A stats buff, %d\n", ret);
++ }
++ aewbdata->ts = aewbstat.h3a_buff[i].ts;
++ aewbdata->config_counter = aewbstat.h3a_buff[i].config_counter;
++ aewbdata->field_count = h3a_xtrastats[i].field_count;
++ return 0;
++ }
++ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
++
++ return -1;
++}
++
++/**
++ * isph3a_aewb_link_buffers - Helper function to link allocated buffers.
++ **/
++static void isph3a_aewb_link_buffers(void)
++{
++ int i;
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if ((i + 1) < H3A_MAX_BUFF) {
++ aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[i + 1];
++ h3a_xtrastats[i].next = &h3a_xtrastats[i + 1];
++ } else {
++ aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[0];
++ h3a_xtrastats[i].next = &h3a_xtrastats[0];
++ }
++ }
++}
++
++/**
++ * isph3a_aewb_unlock_buffers - Helper function to unlock all buffers.
++ **/
++static void isph3a_aewb_unlock_buffers(void)
++{
++ int i;
++ unsigned long irqflags;
++
++ spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
++ for (i = 0; i < H3A_MAX_BUFF; i++)
++ aewbstat.h3a_buff[i].locked = 0;
++
++ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
++}
++
++/**
++ * isph3a_aewb_isr - Callback from ISP driver for H3A AEWB interrupt.
++ * @status: IRQ0STATUS in case of MMU error, 0 for H3A interrupt.
++ * @arg1: Not used as of now.
++ * @arg2: Not used as of now.
++ */
++static void isph3a_aewb_isr(unsigned long status, isp_vbq_callback_ptr arg1,
++ void *arg2)
++{
++ u16 frame_align;
++
++ if ((H3A_AWB_DONE & status) != H3A_AWB_DONE)
++ return;
++
++ do_gettimeofday(&active_buff->ts);
++ active_buff->config_counter = atomic_read(&aewbstat.config_counter);
++ active_buff = active_buff->next;
++ if (active_buff->locked == 1)
++ active_buff = active_buff->next;
++ isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
++ ISPH3A_AEWBUFST);
++
++ aewbstat.frame_count++;
++ frame_align = aewbstat.frame_count;
++ if (aewbstat.frame_count > MAX_FRAME_COUNT) {
++ aewbstat.frame_count = 1;
++ frame_align++;
++ }
++ active_buff->frame_num = aewbstat.frame_count;
++
++ if (aewbstat.stats_req) {
++ DPRINTK_ISPH3A("waiting for frame %d\n", aewbstat.frame_req);
++ if (frame_align >= aewbstat.frame_req + 1) {
++ aewbstat.stats_req = 0;
++ aewbstat.stats_done = 1;
++ wake_up_interruptible(&aewbstat.stats_wait);
++ }
++ }
++
++ if (aewbstat.update)
++ isph3a_aewb_update_regs();
++}
++
++/**
++ * isph3a_aewb_set_params - Helper function to check & store user given params.
++ * @user_cfg: Pointer to AE and AWB parameters struct.
++ *
++ * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
++ * program them during ISR.
++ *
++ * Returns 0 if successful, or -EINVAL if any of the parameters are invalid.
++ **/
++static int isph3a_aewb_set_params(struct isph3a_aewb_config *user_cfg)
++{
++ if (unlikely(user_cfg->saturation_limit > MAX_SATURATION_LIM)) {
++ printk(KERN_ERR "Invalid Saturation_limit: %d\n",
++ user_cfg->saturation_limit);
++ return -EINVAL;
++ }
++ if (aewb_config_local.saturation_limit != user_cfg->saturation_limit) {
++ WRITE_SAT_LIM(aewb_regs.reg_pcr, user_cfg->saturation_limit);
++ aewb_config_local.saturation_limit =
++ user_cfg->saturation_limit;
++ aewbstat.update = 1;
++ }
++
++ if (aewb_config_local.alaw_enable != user_cfg->alaw_enable) {
++ WRITE_ALAW(aewb_regs.reg_pcr, user_cfg->alaw_enable);
++ aewb_config_local.alaw_enable = user_cfg->alaw_enable;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->win_height < MIN_WIN_H ||
++ user_cfg->win_height > MAX_WIN_H ||
++ user_cfg->win_height & 0x01)) {
++ printk(KERN_ERR "Invalid window height: %d\n",
++ user_cfg->win_height);
++ return -EINVAL;
++ }
++ if (aewb_config_local.win_height != user_cfg->win_height) {
++ WRITE_WIN_H(aewb_regs.reg_win1, user_cfg->win_height);
++ aewb_config_local.win_height = user_cfg->win_height;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->win_width < MIN_WIN_W ||
++ user_cfg->win_width > MAX_WIN_W ||
++ user_cfg->win_width & 0x01)) {
++ printk(KERN_ERR "Invalid window width: %d\n",
++ user_cfg->win_width);
++ return -EINVAL;
++ }
++ if (aewb_config_local.win_width != user_cfg->win_width) {
++ WRITE_WIN_W(aewb_regs.reg_win1, user_cfg->win_width);
++ aewb_config_local.win_width = user_cfg->win_width;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->ver_win_count < 1 ||
++ user_cfg->ver_win_count > MAX_WINVC)) {
++ printk(KERN_ERR "Invalid vertical window count: %d\n",
++ user_cfg->ver_win_count);
++ return -EINVAL;
++ }
++ if (aewb_config_local.ver_win_count != user_cfg->ver_win_count) {
++ WRITE_VER_C(aewb_regs.reg_win1, user_cfg->ver_win_count);
++ aewb_config_local.ver_win_count = user_cfg->ver_win_count;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->hor_win_count < 1 ||
++ user_cfg->hor_win_count > MAX_WINHC)) {
++ printk(KERN_ERR "Invalid horizontal window count: %d\n",
++ user_cfg->hor_win_count);
++ return -EINVAL;
++ }
++ if (aewb_config_local.hor_win_count != user_cfg->hor_win_count) {
++ WRITE_HOR_C(aewb_regs.reg_win1, user_cfg->hor_win_count);
++ aewb_config_local.hor_win_count = user_cfg->hor_win_count;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->ver_win_start > MAX_WINSTART)) {
++ printk(KERN_ERR "Invalid vertical window start: %d\n",
++ user_cfg->ver_win_start);
++ return -EINVAL;
++ }
++ if (aewb_config_local.ver_win_start != user_cfg->ver_win_start) {
++ WRITE_VER_WIN_ST(aewb_regs.reg_start, user_cfg->ver_win_start);
++ aewb_config_local.ver_win_start = user_cfg->ver_win_start;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->hor_win_start > MAX_WINSTART)) {
++ printk(KERN_ERR "Invalid horizontal window start: %d\n",
++ user_cfg->hor_win_start);
++ return -EINVAL;
++ }
++ if (aewb_config_local.hor_win_start != user_cfg->hor_win_start) {
++ WRITE_HOR_WIN_ST(aewb_regs.reg_start, user_cfg->hor_win_start);
++ aewb_config_local.hor_win_start = user_cfg->hor_win_start;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->blk_ver_win_start > MAX_WINSTART)) {
++ printk(KERN_ERR "Invalid black vertical window start: %d\n",
++ user_cfg->blk_ver_win_start);
++ return -EINVAL;
++ }
++ if (aewb_config_local.blk_ver_win_start !=
++ user_cfg->blk_ver_win_start) {
++ WRITE_BLK_VER_WIN_ST(aewb_regs.reg_blk,
++ user_cfg->blk_ver_win_start);
++ aewb_config_local.blk_ver_win_start =
++ user_cfg->blk_ver_win_start;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->blk_win_height < MIN_WIN_H ||
++ user_cfg->blk_win_height > MAX_WIN_H ||
++ user_cfg->blk_win_height & 0x01)) {
++ printk(KERN_ERR "Invalid black window height: %d\n",
++ user_cfg->blk_win_height);
++ return -EINVAL;
++ }
++ if (aewb_config_local.blk_win_height != user_cfg->blk_win_height) {
++ WRITE_BLK_WIN_H(aewb_regs.reg_blk, user_cfg->blk_win_height);
++ aewb_config_local.blk_win_height = user_cfg->blk_win_height;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->subsample_ver_inc < MIN_SUB_INC ||
++ user_cfg->subsample_ver_inc > MAX_SUB_INC ||
++ user_cfg->subsample_ver_inc & 0x01)) {
++ printk(KERN_ERR "Invalid vertical subsample increment: %d\n",
++ user_cfg->subsample_ver_inc);
++ return -EINVAL;
++ }
++ if (aewb_config_local.subsample_ver_inc !=
++ user_cfg->subsample_ver_inc) {
++ WRITE_SUB_VER_INC(aewb_regs.reg_subwin,
++ user_cfg->subsample_ver_inc);
++ aewb_config_local.subsample_ver_inc =
++ user_cfg->subsample_ver_inc;
++ aewbstat.update = 1;
++ }
++
++ if (unlikely(user_cfg->subsample_hor_inc < MIN_SUB_INC ||
++ user_cfg->subsample_hor_inc > MAX_SUB_INC ||
++ user_cfg->subsample_hor_inc & 0x01)) {
++ printk(KERN_ERR "Invalid horizontal subsample increment: %d\n",
++ user_cfg->subsample_hor_inc);
++ return -EINVAL;
++ }
++ if (aewb_config_local.subsample_hor_inc !=
++ user_cfg->subsample_hor_inc) {
++ WRITE_SUB_HOR_INC(aewb_regs.reg_subwin,
++ user_cfg->subsample_hor_inc);
++ aewb_config_local.subsample_hor_inc =
++ user_cfg->subsample_hor_inc;
++ aewbstat.update = 1;
++ }
++
++ if (!aewbstat.initialized || !aewb_config_local.aewb_enable) {
++ isph3a_aewb_update_regs();
++ aewbstat.initialized = 1;
++ }
++ return 0;
++}
++
++/**
++ * isph3a_aewb_configure - Configure AEWB regs, enable/disable H3A engine.
++ * @aewbcfg: Pointer to AEWB config structure.
++ *
++ * Returns 0 if successful, -EINVAL if aewbcfg pointer is NULL, -ENOMEM if
++ * was unable to allocate memory for the buffer, of other errors if H3A
++ * callback is not set or the parameters for AEWB are invalid.
++ **/
++int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg)
++{
++ int ret = 0;
++ int i;
++ int win_count = 0;
++
++ if (NULL == aewbcfg) {
++ printk(KERN_ERR "Null argument in configuration. \n");
++ return -EINVAL;
++ }
++
++ if (!aewbstat.initialized) {
++ DPRINTK_ISPH3A("Setting callback for H3A\n");
++ ret = isp_set_callback(CBK_H3A_AWB_DONE, isph3a_aewb_isr,
++ (void *)NULL, (void *)NULL);
++ if (ret) {
++ printk(KERN_ERR "No callback for H3A\n");
++ return ret;
++ }
++ }
++
++ ret = isph3a_aewb_set_params(aewbcfg);
++ if (ret) {
++ printk(KERN_ERR "Invalid parameters! \n");
++ return ret;
++ }
++
++ win_count = aewbcfg->ver_win_count * aewbcfg->hor_win_count;
++ win_count += aewbcfg->hor_win_count;
++ ret = win_count / 8;
++ win_count += win_count % 8 ? 1 : 0;
++ win_count += ret;
++
++ aewbstat.win_count = win_count;
++ aewbstat.curr_cfg_buf_size = win_count * AEWB_PACKET_SIZE;
++
++ if (aewbstat.stats_buf_size
++ && win_count * AEWB_PACKET_SIZE > aewbstat.stats_buf_size) {
++ DPRINTK_ISPH3A("There was a previous buffer... "
++ "Freeing/unmapping current stat busffs\n");
++ isph3a_aewb_enable(0);
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
++ dma_free_coherent(
++ NULL,
++ aewbstat.min_buf_size,
++ (void *)aewbstat.h3a_buff[i].virt_addr,
++ (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
++ aewbstat.h3a_buff[i].virt_addr = 0;
++ }
++ aewbstat.stats_buf_size = 0;
++ }
++
++ if (!aewbstat.h3a_buff[0].virt_addr) {
++ aewbstat.stats_buf_size = win_count * AEWB_PACKET_SIZE;
++ aewbstat.min_buf_size = PAGE_ALIGN(aewbstat.stats_buf_size);
++
++ DPRINTK_ISPH3A("Allocating/mapping new stat buffs\n");
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ aewbstat.h3a_buff[i].virt_addr =
++ (unsigned long)dma_alloc_coherent(
++ NULL,
++ aewbstat.min_buf_size,
++ (dma_addr_t *)
++ &aewbstat.h3a_buff[i].phy_addr,
++ GFP_KERNEL | GFP_DMA);
++ if (aewbstat.h3a_buff[i].virt_addr == 0) {
++ printk(KERN_ERR "Can't acquire memory for "
++ "buffer[%d]\n", i);
++ return -ENOMEM;
++ }
++ aewbstat.h3a_buff[i].addr_align =
++ aewbstat.h3a_buff[i].virt_addr;
++ while ((aewbstat.h3a_buff[i].addr_align & 0xFFFFFFC0) !=
++ aewbstat.h3a_buff[i].addr_align)
++ aewbstat.h3a_buff[i].addr_align++;
++ aewbstat.h3a_buff[i].ispmmu_addr =
++ ispmmu_kmap(aewbstat.h3a_buff[i].phy_addr,
++ aewbstat.min_buf_size);
++ }
++ isph3a_aewb_unlock_buffers();
++ isph3a_aewb_link_buffers();
++
++ if (active_buff == NULL)
++ active_buff = &aewbstat.h3a_buff[0];
++
++ isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
++ ISPH3A_AEWBUFST);
++ }
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ DPRINTK_ISPH3A("buff[%d] addr is:\n virt 0x%lX\n"
++ " aligned 0x%lX\n"
++ " phys 0x%lX\n"
++ " ispmmu 0x%08lX\n"
++ " mmapped 0x%lX\n"
++ " frame_num %d\n", i,
++ aewbstat.h3a_buff[i].virt_addr,
++ aewbstat.h3a_buff[i].addr_align,
++ aewbstat.h3a_buff[i].phy_addr,
++ aewbstat.h3a_buff[i].ispmmu_addr,
++ aewbstat.h3a_buff[i].mmap_addr,
++ aewbstat.h3a_buff[i].frame_num);
++ }
++
++ active_buff->frame_num = 1;
++
++ atomic_inc(&aewbstat.config_counter);
++ isph3a_aewb_enable(aewbcfg->aewb_enable);
++ isph3a_print_status();
++
++ return 0;
++}
++EXPORT_SYMBOL(isph3a_aewb_configure);
++
++/**
++ * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB
++ * @aewbdata: Pointer to return AE AWB statistics data.
++ *
++ * This API allows the user to update White Balance gains, as well as
++ * exposure time and analog gain. It is also used to request frame
++ * statistics.
++ *
++ * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other
++ * errors when setting gains.
++ **/
++int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata)
++{
++ int ret = 0;
++ u16 frame_diff = 0;
++ u16 frame_cnt = aewbstat.frame_count;
++ wait_queue_t wqt;
++
++ if (!aewb_config_local.aewb_enable) {
++ printk(KERN_ERR "H3A engine not enabled\n");
++ return -EINVAL;
++ }
++
++ DPRINTK_ISPH3A("isph3a_aewb_request_statistics: Enter "
++ "(frame req. => %d, current frame => %d,"
++ "update => %d)\n",
++ aewbdata->frame_number, frame_cnt, aewbdata->update);
++ DPRINTK_ISPH3A("User data received: \n");
++ DPRINTK_ISPH3A("Digital gain = 0x%04x\n", aewbdata->dgain);
++ DPRINTK_ISPH3A("WB gain b *= 0x%04x\n", aewbdata->wb_gain_b);
++ DPRINTK_ISPH3A("WB gain r *= 0x%04x\n", aewbdata->wb_gain_r);
++ DPRINTK_ISPH3A("WB gain gb = 0x%04x\n", aewbdata->wb_gain_gb);
++ DPRINTK_ISPH3A("WB gain gr = 0x%04x\n", aewbdata->wb_gain_gr);
++
++ if (!aewbdata->update) {
++ aewbdata->h3a_aewb_statistics_buf = NULL;
++ goto out;
++ }
++ if (aewbdata->update & SET_DIGITAL_GAIN)
++ h3awb_update.dgain = (u16)aewbdata->dgain;
++ if (aewbdata->update & SET_COLOR_GAINS) {
++ h3awb_update.coef0 = (u8)aewbdata->wb_gain_gr;
++ h3awb_update.coef1 = (u8)aewbdata->wb_gain_r;
++ h3awb_update.coef2 = (u8)aewbdata->wb_gain_b;
++ h3awb_update.coef3 = (u8)aewbdata->wb_gain_gb;
++ }
++ if (aewbdata->update & (SET_COLOR_GAINS | SET_DIGITAL_GAIN))
++ wb_update = 1;
++
++ if (!(aewbdata->update & REQUEST_STATISTICS)) {
++ aewbdata->h3a_aewb_statistics_buf = NULL;
++ goto out;
++ }
++
++ if (aewbdata->frame_number < 1) {
++ printk(KERN_ERR "Illeagal frame number "
++ "requested (%d)\n",
++ aewbdata->frame_number);
++ return -EINVAL;
++ }
++
++ isph3a_aewb_unlock_buffers();
++
++ DPRINTK_ISPH3A("Stats available?\n");
++ ret = isph3a_aewb_stats_available(aewbdata);
++ if (!ret)
++ goto out;
++
++ DPRINTK_ISPH3A("Stats in near future?\n");
++ if (aewbdata->frame_number > frame_cnt)
++ frame_diff = aewbdata->frame_number - frame_cnt;
++ else if (aewbdata->frame_number < frame_cnt) {
++ if ((frame_cnt > (MAX_FRAME_COUNT - MAX_FUTURE_FRAMES)) &&
++ (aewbdata->frame_number < MAX_FRAME_COUNT)) {
++ frame_diff = aewbdata->frame_number + MAX_FRAME_COUNT -
++ frame_cnt;
++ } else
++ frame_diff = MAX_FUTURE_FRAMES + 1;
++ }
++
++ if (frame_diff > MAX_FUTURE_FRAMES) {
++ printk(KERN_ERR "Invalid frame requested, returning current"
++ " frame stats\n");
++ aewbdata->frame_number = frame_cnt;
++ }
++ if (camnotify) {
++ DPRINTK_ISPH3A("NOT Waiting on stats IRQ for frame %d "
++ "because camnotify set\n",
++ aewbdata->frame_number);
++ aewbdata->h3a_aewb_statistics_buf = NULL;
++ goto out;
++ }
++ DPRINTK_ISPH3A("Waiting on stats IRQ for frame %d\n",
++ aewbdata->frame_number);
++ aewbstat.frame_req = aewbdata->frame_number;
++ aewbstat.stats_req = 1;
++ aewbstat.stats_done = 0;
++ init_waitqueue_entry(&wqt, current);
++ ret = wait_event_interruptible(aewbstat.stats_wait,
++ aewbstat.stats_done == 1);
++ if (ret < 0) {
++ printk(KERN_ERR "isph3a_aewb_request_statistics"
++ " Error on wait event %d\n", ret);
++ aewbdata->h3a_aewb_statistics_buf = NULL;
++ return ret;
++ }
++
++ DPRINTK_ISPH3A("ISP AEWB request status interrupt raised\n");
++ ret = isph3a_aewb_stats_available(aewbdata);
++ if (ret) {
++ DPRINTK_ISPH3A("After waiting for stats,"
++ " stats not available!!\n");
++ aewbdata->h3a_aewb_statistics_buf = NULL;
++ }
++out:
++ DPRINTK_ISPH3A("isph3a_aewb_request_statistics: "
++ "aewbdata->h3a_aewb_statistics_buf => %p\n",
++ aewbdata->h3a_aewb_statistics_buf);
++ aewbdata->curr_frame = aewbstat.frame_count;
++
++ return 0;
++}
++EXPORT_SYMBOL(isph3a_aewb_request_statistics);
++
++/**
++ * isph3a_aewb_init - Module Initialisation.
++ *
++ * Always returns 0.
++ **/
++int __init isph3a_aewb_init(void)
++{
++ memset(&aewbstat, 0, sizeof(aewbstat));
++ memset(&aewb_regs, 0, sizeof(aewb_regs));
++
++ init_waitqueue_head(&aewbstat.stats_wait);
++ spin_lock_init(&aewbstat.buffer_lock);
++ return 0;
++}
++
++/**
++ * isph3a_aewb_cleanup - Module exit.
++ **/
++void isph3a_aewb_cleanup(void)
++{
++ int i;
++
++ for (i = 0; i < H3A_MAX_BUFF; i++) {
++ if (!aewbstat.h3a_buff[i].phy_addr)
++ continue;
++
++ ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
++ dma_free_coherent(NULL,
++ aewbstat.min_buf_size,
++ (void *)aewbstat.h3a_buff[i].virt_addr,
++ (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
++ }
++ memset(&aewbstat, 0, sizeof(aewbstat));
++ memset(&aewb_regs, 0, sizeof(aewb_regs));
++}
++
++/**
++ * isph3a_print_status - Debug print. Values of H3A related registers.
++ **/
++static void isph3a_print_status(void)
++{
++ DPRINTK_ISPH3A("ISPH3A_PCR = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR));
++ DPRINTK_ISPH3A("ISPH3A_AEWWIN1 = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1));
++ DPRINTK_ISPH3A("ISPH3A_AEWINSTART = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART));
++ DPRINTK_ISPH3A("ISPH3A_AEWINBLK = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK));
++ DPRINTK_ISPH3A("ISPH3A_AEWSUBWIN = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN));
++ DPRINTK_ISPH3A("ISPH3A_AEWBUFST = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST));
++ DPRINTK_ISPH3A("stats windows = %d\n", aewbstat.win_count);
++ DPRINTK_ISPH3A("stats buff size = %d\n", aewbstat.stats_buf_size);
++ DPRINTK_ISPH3A("currently configured stats buff size = %d\n",
++ aewbstat.curr_cfg_buf_size);
++}
++
++/**
++ * isph3a_notify - Unblocks user request for statistics when camera is off
++ * @notify: 1 - Camera is turned off
++ *
++ * Used when the user has requested statistics about a future frame, but the
++ * camera is turned off before it happens, and this function unblocks the
++ * request so the user can continue in its program.
++ **/
++void isph3a_notify(int notify)
++{
++ camnotify = notify;
++ if (camnotify && aewbstat.initialized) {
++ printk(KERN_DEBUG "Warning Camera Off \n");
++ aewbstat.stats_req = 0;
++ aewbstat.stats_done = 1;
++ wake_up_interruptible(&aewbstat.stats_wait);
++ }
++}
++EXPORT_SYMBOL(isph3a_notify);
++
++/**
++ * isph3a_save_context - Saves the values of the h3a module registers.
++ **/
++void isph3a_save_context(void)
++{
++ DPRINTK_ISPH3A(" Saving context\n");
++ isp_save_context(isph3a_reg_list);
++ /* Avoid enable during restore ctx */
++ isph3a_reg_list[0].val &= ~ISPH3A_PCR_AEW_EN;
++}
++EXPORT_SYMBOL(isph3a_save_context);
++
++/**
++ * isph3a_restore_context - Restores the values of the h3a module registers.
++ **/
++void isph3a_restore_context(void)
++{
++ DPRINTK_ISPH3A(" Restoring context\n");
++ isp_restore_context(isph3a_reg_list);
++}
++EXPORT_SYMBOL(isph3a_restore_context);
+diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
+new file mode 100644
+index 0000000..7d4c765
+--- /dev/null
++++ b/drivers/media/video/isp/isph3a.h
+@@ -0,0 +1,127 @@
++/*
++ * isph3a.h
++ *
++ * Include file for H3A module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_H3A_H
++#define OMAP_ISP_H3A_H
++
++#include <mach/isp_user.h>
++
++#define AEWB_PACKET_SIZE 16
++#define H3A_MAX_BUFF 5
++
++/* Flags for changed registers */
++#define PCR_CHNG (1 << 0)
++#define AEWWIN1_CHNG (1 << 1)
++#define AEWINSTART_CHNG (1 << 2)
++#define AEWINBLK_CHNG (1 << 3)
++#define AEWSUBWIN_CHNG (1 << 4)
++#define PRV_WBDGAIN_CHNG (1 << 5)
++#define PRV_WBGAIN_CHNG (1 << 6)
++
++/* ISPH3A REGISTERS bits */
++#define ISPH3A_PCR_AF_EN (1 << 0)
++#define ISPH3A_PCR_AF_ALAW_EN (1 << 1)
++#define ISPH3A_PCR_AF_MED_EN (1 << 2)
++#define ISPH3A_PCR_AF_BUSY (1 << 15)
++#define ISPH3A_PCR_AEW_EN (1 << 16)
++#define ISPH3A_PCR_AEW_ALAW_EN (1 << 17)
++#define ISPH3A_PCR_AEW_BUSY (1 << 18)
++
++#define WRITE_SAT_LIM(reg, sat_limit) \
++ (reg = (reg & (~(ISPH3A_PCR_AEW_AVE2LMT_MASK))) \
++ | (sat_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT))
++
++#define WRITE_ALAW(reg, alaw_en) \
++ (reg = (reg & (~(ISPH3A_PCR_AEW_ALAW_EN))) \
++ | ((alaw_en & ISPH3A_PCR_AF_ALAW_EN) \
++ << ISPH3A_PCR_AEW_ALAW_EN_SHIFT))
++
++#define WRITE_WIN_H(reg, height) \
++ (reg = (reg & (~(ISPH3A_AEWWIN1_WINH_MASK))) \
++ | (((height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT))
++
++#define WRITE_WIN_W(reg, width) \
++ (reg = (reg & (~(ISPH3A_AEWWIN1_WINW_MASK))) \
++ | (((width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT))
++
++#define WRITE_VER_C(reg, ver_count) \
++ (reg = (reg & ~(ISPH3A_AEWWIN1_WINVC_MASK)) \
++ | ((ver_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT))
++
++#define WRITE_HOR_C(reg, hor_count) \
++ (reg = (reg & ~(ISPH3A_AEWWIN1_WINHC_MASK)) \
++ | ((hor_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT))
++
++#define WRITE_VER_WIN_ST(reg, ver_win_st) \
++ (reg = (reg & ~(ISPH3A_AEWINSTART_WINSV_MASK)) \
++ | (ver_win_st << ISPH3A_AEWINSTART_WINSV_SHIFT))
++
++#define WRITE_HOR_WIN_ST(reg, hor_win_st) \
++ (reg = (reg & ~(ISPH3A_AEWINSTART_WINSH_MASK)) \
++ | (hor_win_st << ISPH3A_AEWINSTART_WINSH_SHIFT))
++
++#define WRITE_BLK_VER_WIN_ST(reg, blk_win_st) \
++ (reg = (reg & ~(ISPH3A_AEWINBLK_WINSV_MASK)) \
++ | (blk_win_st << ISPH3A_AEWINBLK_WINSV_SHIFT))
++
++#define WRITE_BLK_WIN_H(reg, height) \
++ (reg = (reg & ~(ISPH3A_AEWINBLK_WINH_MASK)) \
++ | (((height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT))
++
++#define WRITE_SUB_VER_INC(reg, sub_ver_inc) \
++ (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCV_MASK)) \
++ | (((sub_ver_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCV_SHIFT))
++
++#define WRITE_SUB_HOR_INC(reg, sub_hor_inc) \
++ (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCH_MASK)) \
++ | (((sub_hor_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCH_SHIFT))
++
++/**
++ * struct isph3a_aewb_xtrastats - Structure with extra statistics sent by cam.
++ * @field_count: Sequence number of returned framestats.
++ * @isph3a_aewb_xtrastats: Pointer to next buffer with extra stats.
++ */
++struct isph3a_aewb_xtrastats {
++ unsigned long field_count;
++ struct isph3a_aewb_xtrastats *next;
++};
++
++void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats);
++
++int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg);
++
++int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata);
++
++void isph3a_save_context(void);
++
++void isph3a_restore_context(void);
++
++void isph3a_aewb_enable(u8 enable);
++
++int isph3a_aewb_busy(void);
++
++void isph3a_aewb_suspend(void);
++
++void isph3a_aewb_resume(void);
++
++void isph3a_update_wb(void);
++
++void isph3a_notify(int notify);
++#endif /* OMAP_ISP_H3A_H */
+diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
+new file mode 100644
+index 0000000..c6f6a77
+--- /dev/null
++++ b/drivers/media/video/isp/isphist.c
+@@ -0,0 +1,608 @@
++/*
++ * isphist.c
++ *
++ * HISTOGRAM module for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <asm/cacheflush.h>
++
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/uaccess.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "isphist.h"
++#include "ispmmu.h"
++
++/**
++ * struct isp_hist_status - Histogram status.
++ * @hist_enable: Enables the histogram module.
++ * @initialized: Flag to indicate that the module is correctly initializated.
++ * @frame_cnt: Actual frame count.
++ * @frame_req: Frame requested by user.
++ * @completed: Flag to indicate if a frame request is completed.
++ */
++struct isp_hist_status {
++ u8 hist_enable;
++ u8 pm_state;
++ u8 initialized;
++ u8 frame_cnt;
++ u8 frame_req;
++ u8 completed;
++} histstat;
++
++/**
++ * struct isp_hist_buffer - Frame histogram buffer.
++ * @virt_addr: Virtual address to mmap the buffer.
++ * @phy_addr: Physical address of the buffer.
++ * @addr_align: Virtual Address 32 bytes aligned.
++ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
++ * @mmap_addr: Mapped memory area of buffer. For userspace access.
++ */
++struct isp_hist_buffer {
++ unsigned long virt_addr;
++ unsigned long phy_addr;
++ unsigned long addr_align;
++ unsigned long ispmmu_addr;
++ unsigned long mmap_addr;
++} hist_buff;
++
++/**
++ * struct isp_hist_regs - Current value of Histogram configuration registers.
++ * @reg_pcr: Peripheral control register.
++ * @reg_cnt: Histogram control register.
++ * @reg_wb_gain: Histogram white balance gain register.
++ * @reg_r0_h: Region 0 horizontal register.
++ * @reg_r0_v: Region 0 vertical register.
++ * @reg_r1_h: Region 1 horizontal register.
++ * @reg_r1_v: Region 1 vertical register.
++ * @reg_r2_h: Region 2 horizontal register.
++ * @reg_r2_v: Region 2 vertical register.
++ * @reg_r3_h: Region 3 horizontal register.
++ * @reg_r3_v: Region 3 vertical register.
++ * @reg_hist_addr: Histogram address register.
++ * @reg_hist_data: Histogram data.
++ * @reg_hist_radd: Address register. When input data comes from mem.
++ * @reg_hist_radd_off: Address offset register. When input data comes from mem.
++ * @reg_h_v_info: Image size register. When input data comes from mem.
++ */
++static struct isp_hist_regs {
++ u32 reg_pcr;
++ u32 reg_cnt;
++ u32 reg_wb_gain;
++ u32 reg_r0_h;
++ u32 reg_r0_v;
++ u32 reg_r1_h;
++ u32 reg_r1_v;
++ u32 reg_r2_h;
++ u32 reg_r2_v;
++ u32 reg_r3_h;
++ u32 reg_r3_v;
++ u32 reg_hist_addr;
++ u32 reg_hist_data;
++ u32 reg_hist_radd;
++ u32 reg_hist_radd_off;
++ u32 reg_h_v_info;
++} hist_regs;
++
++/* Structure for saving/restoring histogram module registers */
++struct isp_reg isphist_reg_list[] = {
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF, 0},
++ {OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO, 0},
++ {0, ISP_TOK_TERM, 0}
++};
++
++static void isp_hist_print_status(void);
++
++void __isp_hist_enable(u8 enable)
++{
++ if (enable)
++ DPRINTK_ISPHIST(" histogram enabled \n");
++ else
++ DPRINTK_ISPHIST(" histogram disabled \n");
++
++ isp_reg_and_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ~ISPHIST_PCR_EN,
++ (enable ? ISPHIST_PCR_EN : 0));
++ histstat.hist_enable = enable;
++}
++
++/**
++ * isp_hist_enable - Enables ISP Histogram submodule operation.
++ * @enable: 1 - Enables the histogram submodule.
++ *
++ * Client should configure all the Histogram registers before calling this
++ * function.
++ **/
++void isp_hist_enable(u8 enable)
++{
++ __isp_hist_enable(enable);
++ histstat.pm_state = enable;
++}
++
++/**
++ * isp_hist_suspend - Suspend ISP Histogram submodule.
++ **/
++void isp_hist_suspend(void)
++{
++ if (histstat.pm_state)
++ __isp_hist_enable(0);
++}
++
++/**
++ * isp_hist_resume - Resume ISP Histogram submodule.
++ **/
++void isp_hist_resume(void)
++{
++ if (histstat.pm_state)
++ __isp_hist_enable(1);
++}
++
++int isp_hist_busy(void)
++{
++ return isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR) &
++ ISPHIST_PCR_BUSY;
++}
++
++
++/**
++ * isp_hist_update_regs - Helper function to update Histogram registers.
++ **/
++static void isp_hist_update_regs(void)
++{
++ isp_reg_writel(hist_regs.reg_pcr, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR);
++ isp_reg_writel(hist_regs.reg_cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
++ isp_reg_writel(hist_regs.reg_wb_gain, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_WB_GAIN);
++ isp_reg_writel(hist_regs.reg_r0_h, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R0_HORZ);
++ isp_reg_writel(hist_regs.reg_r0_v, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R0_VERT);
++ isp_reg_writel(hist_regs.reg_r1_h, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R1_HORZ);
++ isp_reg_writel(hist_regs.reg_r1_v, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R1_VERT);
++ isp_reg_writel(hist_regs.reg_r2_h, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R2_HORZ);
++ isp_reg_writel(hist_regs.reg_r2_v, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R2_VERT);
++ isp_reg_writel(hist_regs.reg_r3_h, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R3_HORZ);
++ isp_reg_writel(hist_regs.reg_r3_v, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_R3_VERT);
++ isp_reg_writel(hist_regs.reg_hist_addr, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_ADDR);
++ isp_reg_writel(hist_regs.reg_hist_data, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_DATA);
++ isp_reg_writel(hist_regs.reg_hist_radd, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_RADD);
++ isp_reg_writel(hist_regs.reg_hist_radd_off, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_RADD_OFF);
++ isp_reg_writel(hist_regs.reg_h_v_info, OMAP3_ISP_IOMEM_HIST,
++ ISPHIST_H_V_INFO);
++}
++
++/**
++ * isp_hist_isr - Callback from ISP driver for HIST interrupt.
++ * @status: IRQ0STATUS in case of MMU error, 0 for hist interrupt.
++ * arg1 and arg2 Not used as of now.
++ **/
++static void isp_hist_isr(unsigned long status, isp_vbq_callback_ptr arg1,
++ void *arg2)
++{
++ isp_hist_enable(0);
++
++ if (!(status & HIST_DONE))
++ return;
++
++ if (!histstat.completed) {
++ if (histstat.frame_req == histstat.frame_cnt) {
++ histstat.frame_cnt = 0;
++ histstat.frame_req = 0;
++ histstat.completed = 1;
++ } else {
++ isp_hist_enable(1);
++ histstat.frame_cnt++;
++ }
++ }
++}
++
++/**
++ * isp_hist_reset_mem - clear Histogram memory before start stats engine.
++ *
++ * Returns 0 after histogram memory was cleared.
++ **/
++static int isp_hist_reset_mem(void)
++{
++ int i;
++
++ isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
++
++ for (i = 0; i < HIST_MEM_SIZE; i++)
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
++
++ isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ~ISPHIST_CNT_CLR_EN);
++
++ return 0;
++}
++
++/**
++ * isp_hist_set_params - Helper function to check and store user given params.
++ * @user_cfg: Pointer to user configuration structure.
++ *
++ * Returns 0 on success configuration.
++ **/
++static int isp_hist_set_params(struct isp_hist_config *user_cfg)
++{
++
++ int reg_num = 0;
++ int bit_shift = 0;
++
++
++ if (isp_hist_busy())
++ return -EINVAL;
++
++ if (user_cfg->input_bit_width > MIN_BIT_WIDTH)
++ WRITE_DATA_SIZE(hist_regs.reg_cnt, 0);
++ else
++ WRITE_DATA_SIZE(hist_regs.reg_cnt, 1);
++
++ WRITE_SOURCE(hist_regs.reg_cnt, user_cfg->hist_source);
++
++ if (user_cfg->hist_source) {
++ WRITE_HV_INFO(hist_regs.reg_h_v_info, user_cfg->hist_h_v_info);
++
++ if ((user_cfg->hist_radd & ISP_32B_BOUNDARY_BUF) ==
++ user_cfg->hist_radd) {
++ WRITE_RADD(hist_regs.reg_hist_radd,
++ user_cfg->hist_radd);
++ } else {
++ printk(KERN_ERR "Address should be in 32 byte boundary"
++ "\n");
++ return -EINVAL;
++ }
++
++ if ((user_cfg->hist_radd_off & ISP_32B_BOUNDARY_OFFSET) ==
++ user_cfg->hist_radd_off) {
++ WRITE_RADD_OFF(hist_regs.reg_hist_radd_off,
++ user_cfg->hist_radd_off);
++ } else {
++ printk(KERN_ERR "Offset should be in 32 byte boundary"
++ "\n");
++ return -EINVAL;
++ }
++
++ }
++
++ isp_hist_reset_mem();
++ DPRINTK_ISPHIST("ISPHIST: Memory Cleared\n");
++ histstat.frame_req = user_cfg->hist_frames;
++
++ if (unlikely(user_cfg->wb_gain_R > MAX_WB_GAIN ||
++ user_cfg->wb_gain_RG > MAX_WB_GAIN ||
++ user_cfg->wb_gain_B > MAX_WB_GAIN ||
++ user_cfg->wb_gain_BG > MAX_WB_GAIN)) {
++ printk(KERN_ERR "Invalid WB gain\n");
++ return -EINVAL;
++ } else {
++ WRITE_WB_R(hist_regs.reg_wb_gain, user_cfg->wb_gain_R);
++ WRITE_WB_RG(hist_regs.reg_wb_gain, user_cfg->wb_gain_RG);
++ WRITE_WB_B(hist_regs.reg_wb_gain, user_cfg->wb_gain_B);
++ WRITE_WB_BG(hist_regs.reg_wb_gain, user_cfg->wb_gain_BG);
++ }
++
++ /* Regions size and position */
++
++ if (user_cfg->num_regions > MAX_REGIONS)
++ return -EINVAL;
++
++ if (likely((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HEND_MASK) -
++ ((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HSTART_MASK) >>
++ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
++ WRITE_REG_HORIZ(hist_regs.reg_r0_h, user_cfg->reg0_hor);
++ reg_num++;
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++
++ if (likely((user_cfg->reg0_ver & ISPHIST_REGVERT_VEND_MASK) -
++ ((user_cfg->reg0_ver & ISPHIST_REGVERT_VSTART_MASK) >>
++ ISPHIST_REGVERT_VSTART_SHIFT))) {
++ WRITE_REG_VERT(hist_regs.reg_r0_v, user_cfg->reg0_ver);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++
++ if (user_cfg->num_regions >= 1) {
++ if (likely((user_cfg->reg1_hor & ISPHIST_REGHORIZ_HEND_MASK) -
++ ((user_cfg->reg1_hor &
++ ISPHIST_REGHORIZ_HSTART_MASK) >>
++ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
++ WRITE_REG_HORIZ(hist_regs.reg_r1_h, user_cfg->reg1_hor);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++
++ if (likely((user_cfg->reg1_ver & ISPHIST_REGVERT_VEND_MASK) -
++ ((user_cfg->reg1_ver &
++ ISPHIST_REGVERT_VSTART_MASK) >>
++ ISPHIST_REGVERT_VSTART_SHIFT))) {
++ WRITE_REG_VERT(hist_regs.reg_r1_v, user_cfg->reg1_ver);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++ }
++
++ if (user_cfg->num_regions >= 2) {
++ if (likely((user_cfg->reg2_hor & ISPHIST_REGHORIZ_HEND_MASK) -
++ ((user_cfg->reg2_hor &
++ ISPHIST_REGHORIZ_HSTART_MASK) >>
++ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
++ WRITE_REG_HORIZ(hist_regs.reg_r2_h, user_cfg->reg2_hor);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++
++ if (likely((user_cfg->reg2_ver & ISPHIST_REGVERT_VEND_MASK) -
++ ((user_cfg->reg2_ver &
++ ISPHIST_REGVERT_VSTART_MASK) >>
++ ISPHIST_REGVERT_VSTART_SHIFT))) {
++ WRITE_REG_VERT(hist_regs.reg_r2_v, user_cfg->reg2_ver);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++ }
++
++ if (user_cfg->num_regions >= 3) {
++ if (likely((user_cfg->reg3_hor & ISPHIST_REGHORIZ_HEND_MASK) -
++ ((user_cfg->reg3_hor &
++ ISPHIST_REGHORIZ_HSTART_MASK) >>
++ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
++ WRITE_REG_HORIZ(hist_regs.reg_r3_h, user_cfg->reg3_hor);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++
++ if (likely((user_cfg->reg3_ver & ISPHIST_REGVERT_VEND_MASK) -
++ ((user_cfg->reg3_ver &
++ ISPHIST_REGVERT_VSTART_MASK) >>
++ ISPHIST_REGVERT_VSTART_SHIFT))) {
++ WRITE_REG_VERT(hist_regs.reg_r3_v, user_cfg->reg3_ver);
++ } else {
++ printk(KERN_ERR "Invalid Region parameters\n");
++ return -EINVAL;
++ }
++ }
++ reg_num = user_cfg->num_regions;
++ if (unlikely(((user_cfg->hist_bins > BINS_256) &&
++ (user_cfg->hist_bins != BINS_32)) ||
++ ((user_cfg->hist_bins == BINS_256) &&
++ reg_num != 0) || ((user_cfg->hist_bins ==
++ BINS_128) && reg_num >= 2))) {
++ printk(KERN_ERR "Invalid Bins Number: %d\n",
++ user_cfg->hist_bins);
++ return -EINVAL;
++ } else {
++ WRITE_NUM_BINS(hist_regs.reg_cnt, user_cfg->hist_bins);
++ }
++
++ if (user_cfg->input_bit_width > MAX_BIT_WIDTH ||
++ user_cfg->input_bit_width < MIN_BIT_WIDTH) {
++ printk(KERN_ERR "Invalid Bit Width: %d\n",
++ user_cfg->input_bit_width);
++ return -EINVAL;
++ } else {
++ switch (user_cfg->hist_bins) {
++ case BINS_256:
++ bit_shift = user_cfg->input_bit_width - 8;
++ break;
++ case BINS_128:
++ bit_shift = user_cfg->input_bit_width - 7;
++ break;
++ case BINS_64:
++ bit_shift = user_cfg->input_bit_width - 6;
++ break;
++ case BINS_32:
++ bit_shift = user_cfg->input_bit_width - 5;
++ break;
++ default:
++ return -EINVAL;
++ }
++ WRITE_BIT_SHIFT(hist_regs.reg_cnt, bit_shift);
++ }
++
++ isp_hist_update_regs();
++ histstat.initialized = 1;
++
++ return 0;
++}
++
++/**
++ * isp_hist_configure - API to configure HIST registers.
++ * @histcfg: Pointer to user configuration structure.
++ *
++ * Returns 0 on success configuration.
++ **/
++int isp_hist_configure(struct isp_hist_config *histcfg)
++{
++
++ int ret = 0;
++
++ if (NULL == histcfg) {
++ printk(KERN_ERR "Null argument in configuration. \n");
++ return -EINVAL;
++ }
++
++ if (!histstat.initialized) {
++ DPRINTK_ISPHIST("Setting callback for HISTOGRAM\n");
++ ret = isp_set_callback(CBK_HIST_DONE, isp_hist_isr,
++ (void *)NULL, (void *)NULL);
++ if (ret) {
++ printk(KERN_ERR "No callback for HIST\n");
++ return ret;
++ }
++ }
++
++ ret = isp_hist_set_params(histcfg);
++ if (ret) {
++ printk(KERN_ERR "Invalid parameters! \n");
++ return ret;
++ }
++
++ histstat.frame_cnt = 0;
++ histstat.completed = 0;
++ isp_hist_enable(1);
++ isp_hist_print_status();
++
++ return 0;
++}
++EXPORT_SYMBOL(isp_hist_configure);
++
++/**
++ * isp_hist_request_statistics - Request statistics in Histogram.
++ * @histdata: Pointer to data structure.
++ *
++ * This API allows the user to request for histogram statistics.
++ *
++ * Returns 0 on successful request.
++ **/
++int isp_hist_request_statistics(struct isp_hist_data *histdata)
++{
++ int i, ret;
++ u32 curr;
++
++ if (isp_hist_busy())
++ return -EBUSY;
++
++ if (!histstat.completed && histstat.initialized)
++ return -EINVAL;
++
++ isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
++
++ for (i = 0; i < HIST_MEM_SIZE; i++) {
++ curr = isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
++ ret = put_user(curr, histdata->hist_statistics_buf + i);
++ if (ret) {
++ printk(KERN_ERR "Failed copy_to_user for "
++ "HIST stats buff, %d\n", ret);
++ }
++ }
++
++ isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
++ ~ISPHIST_CNT_CLR_EN);
++ histstat.completed = 0;
++ return 0;
++}
++EXPORT_SYMBOL(isp_hist_request_statistics);
++
++/**
++ * isp_hist_init - Module Initialization.
++ *
++ * Returns 0 if successful.
++ **/
++int __init isp_hist_init(void)
++{
++ memset(&histstat, 0, sizeof(histstat));
++ memset(&hist_regs, 0, sizeof(hist_regs));
++
++ return 0;
++}
++
++/**
++ * isp_hist_cleanup - Module cleanup.
++ **/
++void isp_hist_cleanup(void)
++{
++ memset(&histstat, 0, sizeof(histstat));
++ memset(&hist_regs, 0, sizeof(hist_regs));
++}
++
++/**
++ * isphist_save_context - Saves the values of the histogram module registers.
++ **/
++void isphist_save_context(void)
++{
++ DPRINTK_ISPHIST(" Saving context\n");
++ isp_save_context(isphist_reg_list);
++}
++EXPORT_SYMBOL(isphist_save_context);
++
++/**
++ * isphist_restore_context - Restores the values of the histogram module regs.
++ **/
++void isphist_restore_context(void)
++{
++ DPRINTK_ISPHIST(" Restoring context\n");
++ isp_restore_context(isphist_reg_list);
++}
++EXPORT_SYMBOL(isphist_restore_context);
++
++/**
++ * isp_hist_print_status - Debug print
++ **/
++static void isp_hist_print_status(void)
++{
++ DPRINTK_ISPHIST("ISPHIST_PCR = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR));
++ DPRINTK_ISPHIST("ISPHIST_CNT = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT));
++ DPRINTK_ISPHIST("ISPHIST_WB_GAIN = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN));
++ DPRINTK_ISPHIST("ISPHIST_R0_HORZ = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ));
++ DPRINTK_ISPHIST("ISPHIST_R0_VERT = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT));
++ DPRINTK_ISPHIST("ISPHIST_R1_HORZ = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ));
++ DPRINTK_ISPHIST("ISPHIST_R1_VERT = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT));
++ DPRINTK_ISPHIST("ISPHIST_R2_HORZ = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ));
++ DPRINTK_ISPHIST("ISPHIST_R2_VERT = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT));
++ DPRINTK_ISPHIST("ISPHIST_R3_HORZ = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ));
++ DPRINTK_ISPHIST("ISPHIST_R3_VERT = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT));
++ DPRINTK_ISPHIST("ISPHIST_ADDR = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR));
++ DPRINTK_ISPHIST("ISPHIST_RADD = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD));
++ DPRINTK_ISPHIST("ISPHIST_RADD_OFF = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF));
++ DPRINTK_ISPHIST("ISPHIST_H_V_INFO = 0x%08x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO));
++}
+diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
+new file mode 100644
+index 0000000..6b17c4e
+--- /dev/null
++++ b/drivers/media/video/isp/isphist.h
+@@ -0,0 +1,105 @@
++/*
++ * isphist.h
++ *
++ * Header file for HISTOGRAM module in TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_HIST_H
++#define OMAP_ISP_HIST_H
++
++#include <mach/isp_user.h>
++
++#define MAX_REGIONS 0x4
++#define MAX_WB_GAIN 255
++#define MIN_WB_GAIN 0x0
++#define MAX_BIT_WIDTH 14
++#define MIN_BIT_WIDTH 8
++
++#define ISPHIST_PCR_EN (1 << 0)
++#define HIST_MEM_SIZE 1024
++#define ISPHIST_CNT_CLR_EN (1 << 7)
++
++#define WRITE_SOURCE(reg, source) \
++ (reg = (reg & ~(ISPHIST_CNT_SOURCE_MASK)) \
++ | (source << ISPHIST_CNT_SOURCE_SHIFT))
++
++#define WRITE_HV_INFO(reg, hv_info) \
++ (reg = ((reg & ~(ISPHIST_HV_INFO_MASK)) \
++ | (hv_info & ISPHIST_HV_INFO_MASK)))
++
++#define WRITE_RADD(reg, radd) \
++ (reg = (reg & ~(ISPHIST_RADD_MASK)) \
++ | (radd << ISPHIST_RADD_SHIFT))
++
++#define WRITE_RADD_OFF(reg, radd_off) \
++ (reg = (reg & ~(ISPHIST_RADD_OFF_MASK)) \
++ | (radd_off << ISPHIST_RADD_OFF_SHIFT))
++
++#define WRITE_BIT_SHIFT(reg, bit_shift) \
++ (reg = (reg & ~(ISPHIST_CNT_SHIFT_MASK)) \
++ | (bit_shift << ISPHIST_CNT_SHIFT_SHIFT))
++
++#define WRITE_DATA_SIZE(reg, data_size) \
++ (reg = (reg & ~(ISPHIST_CNT_DATASIZE_MASK)) \
++ | (data_size << ISPHIST_CNT_DATASIZE_SHIFT))
++
++#define WRITE_NUM_BINS(reg, num_bins) \
++ (reg = (reg & ~(ISPHIST_CNT_BINS_MASK)) \
++ | (num_bins << ISPHIST_CNT_BINS_SHIFT))
++
++#define WRITE_WB_R(reg, reg_wb_gain) \
++ reg = ((reg & ~(ISPHIST_WB_GAIN_WG00_MASK)) \
++ | (reg_wb_gain << ISPHIST_WB_GAIN_WG00_SHIFT))
++
++#define WRITE_WB_RG(reg, reg_wb_gain) \
++ (reg = (reg & ~(ISPHIST_WB_GAIN_WG01_MASK)) \
++ | (reg_wb_gain << ISPHIST_WB_GAIN_WG01_SHIFT))
++
++#define WRITE_WB_B(reg, reg_wb_gain) \
++ (reg = (reg & ~(ISPHIST_WB_GAIN_WG02_MASK)) \
++ | (reg_wb_gain << ISPHIST_WB_GAIN_WG02_SHIFT))
++
++#define WRITE_WB_BG(reg, reg_wb_gain) \
++ (reg = (reg & ~(ISPHIST_WB_GAIN_WG03_MASK)) \
++ | (reg_wb_gain << ISPHIST_WB_GAIN_WG03_SHIFT))
++
++#define WRITE_REG_HORIZ(reg, reg_n_hor) \
++ (reg = ((reg & ~ISPHIST_REGHORIZ_MASK) \
++ | (reg_n_hor & ISPHIST_REGHORIZ_MASK)))
++
++#define WRITE_REG_VERT(reg, reg_n_vert) \
++ (reg = ((reg & ~ISPHIST_REGVERT_MASK) \
++ | (reg_n_vert & ISPHIST_REGVERT_MASK)))
++
++
++void isp_hist_enable(u8 enable);
++
++int isp_hist_busy(void);
++
++int isp_hist_configure(struct isp_hist_config *histcfg);
++
++int isp_hist_request_statistics(struct isp_hist_data *histdata);
++
++void isphist_save_context(void);
++
++void isp_hist_suspend(void);
++
++void isp_hist_resume(void);
++
++void isphist_restore_context(void);
++
++#endif /* OMAP_ISP_HIST */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
new file mode 100644
index 0000000000..842f395388
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
@@ -0,0 +1,2384 @@
+From 9fbe7b786427d981cac890a7407da09232f5d1e2 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add CSI2 interface support
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/ispcsi2.c | 2124 +++++++++++++++++++++++++++++++++++++
+ drivers/media/video/isp/ispcsi2.h | 232 ++++
+ 2 files changed, 2356 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/ispcsi2.c
+ create mode 100644 drivers/media/video/isp/ispcsi2.h
+
+diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
+new file mode 100644
+index 0000000..5141b5a
+--- /dev/null
++++ b/drivers/media/video/isp/ispcsi2.c
+@@ -0,0 +1,2124 @@
++/*
++ * ispcsi2.c
++ *
++ * Driver Library for ISP CSI Control module in TI's OMAP3 Camera ISP
++ * ISP CSI interface and IRQ related APIs are defined here.
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Dominic Curran <dcurran@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/delay.h>
++#include <media/v4l2-common.h>
++
++#include "isp.h"
++#include "ispreg.h"
++#include "ispcsi2.h"
++
++static struct isp_csi2_cfg current_csi2_cfg;
++static struct isp_csi2_cfg_update current_csi2_cfg_update;
++
++static bool update_complexio_cfg1;
++static bool update_phy_cfg0;
++static bool update_phy_cfg1;
++static bool update_ctx_ctrl1[8];
++static bool update_ctx_ctrl2[8];
++static bool update_ctx_ctrl3[8];
++static bool update_timing;
++static bool update_ctrl;
++static bool uses_videoport;
++
++/**
++ * isp_csi2_complexio_lanes_config - Configuration of CSI2 ComplexIO lanes.
++ * @reqcfg: Pointer to structure containing desired lane configuration
++ *
++ * Validates and saves to internal driver memory the passed configuration.
++ * Returns 0 if successful, or -EINVAL if null pointer is passed, invalid
++ * lane position or polarity is set, and if 2 lanes try to occupy the same
++ * position. To apply this settings, use the isp_csi2_complexio_lanes_update()
++ * function just after calling this function.
++ **/
++int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg)
++{
++ int i;
++ bool pos_occupied[5] = {false, false, false, false, false};
++ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
++ struct isp_csi2_lanes_cfg_update *currlanes_u =
++ &current_csi2_cfg_update.lanes;
++
++ /* Validating parameters sent by driver */
++ if (reqcfg == NULL) {
++ printk(KERN_ERR "Invalid Complex IO Configuration sent by"
++ " sensor\n");
++ goto err_einval;
++ }
++
++ /* Data lanes verification */
++ for (i = 0; i < 4; i++) {
++ if ((reqcfg->data[i].pol > 1) || (reqcfg->data[i].pos > 5)) {
++ printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
++ " parameters for data lane #%d\n", i);
++ goto err_einval;
++ }
++ if (pos_occupied[reqcfg->data[i].pos - 1] &&
++ reqcfg->data[i].pos > 0) {
++ printk(KERN_ERR "Lane #%d already occupied\n",
++ reqcfg->data[i].pos);
++ goto err_einval;
++ } else
++ pos_occupied[reqcfg->data[i].pos - 1] = true;
++ }
++
++ /* Clock lane verification */
++ if ((reqcfg->clk.pol > 1) || (reqcfg->clk.pos > 5) ||
++ (reqcfg->clk.pos == 0)) {
++ printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
++ " parameters for clock lane\n");
++ goto err_einval;
++ }
++ if (pos_occupied[reqcfg->clk.pos - 1]) {
++ printk(KERN_ERR "Lane #%d already occupied",
++ reqcfg->clk.pos);
++ goto err_einval;
++ } else
++ pos_occupied[reqcfg->clk.pos - 1] = true;
++
++ for (i = 0; i < 4; i++) {
++ if (currlanes->data[i].pos != reqcfg->data[i].pos) {
++ currlanes->data[i].pos = reqcfg->data[i].pos;
++ currlanes_u->data[i] = true;
++ update_complexio_cfg1 = true;
++ }
++ if (currlanes->data[i].pol != reqcfg->data[i].pol) {
++ currlanes->data[i].pol = reqcfg->data[i].pol;
++ currlanes_u->data[i] = true;
++ update_complexio_cfg1 = true;
++ }
++ }
++
++ if (currlanes->clk.pos != reqcfg->clk.pos) {
++ currlanes->clk.pos = reqcfg->clk.pos;
++ currlanes_u->clk = true;
++ update_complexio_cfg1 = true;
++ }
++ if (currlanes->clk.pol != reqcfg->clk.pol) {
++ currlanes->clk.pol = reqcfg->clk.pol;
++ currlanes_u->clk = true;
++ update_complexio_cfg1 = true;
++ }
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * isp_csi2_complexio_lanes_update - Applies CSI2 ComplexIO lanes configuration.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_complexio_lanes_config() function.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_complexio_lanes_config() function, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_complexio_lanes_update(bool force_update)
++{
++ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
++ struct isp_csi2_lanes_cfg_update *currlanes_u =
++ &current_csi2_cfg_update.lanes;
++ u32 reg;
++ int i;
++
++ if (!update_complexio_cfg1 && !force_update)
++ return 0;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++ for (i = 0; i < 4; i++) {
++ if (currlanes_u->data[i] || force_update) {
++ reg &= ~(ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1) |
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i +
++ 1));
++ reg |= (currlanes->data[i].pol <<
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1));
++ reg |= (currlanes->data[i].pos <<
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i +
++ 1));
++ currlanes_u->data[i] = false;
++ }
++ }
++
++ if (currlanes_u->clk || force_update) {
++ reg &= ~(ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK |
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK);
++ reg |= (currlanes->clk.pol <<
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT);
++ reg |= (currlanes->clk.pos <<
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT);
++ currlanes_u->clk = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++
++ update_complexio_cfg1 = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_complexio_lanes_get - Gets CSI2 ComplexIO lanes configuration.
++ *
++ * Gets settings from HW registers and fills in the internal driver memory
++ * Always returns 0.
++ **/
++int isp_csi2_complexio_lanes_get(void)
++{
++ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
++ struct isp_csi2_lanes_cfg_update *currlanes_u =
++ &current_csi2_cfg_update.lanes;
++ u32 reg;
++ int i;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++ for (i = 0; i < 4; i++) {
++ currlanes->data[i].pol = (reg &
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1)) >>
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1);
++ currlanes->data[i].pos = (reg &
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i + 1)) >>
++ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i + 1);
++ currlanes_u->data[i] = false;
++ }
++ currlanes->clk.pol = (reg & ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK) >>
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT;
++ currlanes->clk.pos = (reg &
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK) >>
++ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT;
++ currlanes_u->clk = false;
++
++ update_complexio_cfg1 = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_complexio_power_status - Gets CSI2 ComplexIO power status.
++ *
++ * Returns 3 possible valid states: ISP_CSI2_POWER_OFF, ISP_CSI2_POWER_ON,
++ * and ISP_CSI2_POWER_ULPW.
++ **/
++static enum isp_csi2_power_cmds isp_csi2_complexio_power_status(void)
++{
++ enum isp_csi2_power_cmds ret;
++ u32 reg;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
++ ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK;
++ switch (reg) {
++ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF:
++ ret = ISP_CSI2_POWER_OFF;
++ break;
++ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON:
++ ret = ISP_CSI2_POWER_ON;
++ break;
++ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW:
++ ret = ISP_CSI2_POWER_ULPW;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return ret;
++}
++
++/**
++ * isp_csi2_complexio_power_autoswitch - Sets CSI2 ComplexIO power autoswitch.
++ * @enable: Sets or clears the autoswitch function enable flag.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_complexio_power_autoswitch(bool enable)
++{
++ u32 reg;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++ reg &= ~ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK;
++
++ if (enable)
++ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE;
++ else
++ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE;
++
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++ return 0;
++}
++
++/**
++ * isp_csi2_complexio_power - Sets the desired power command for CSI2 ComplexIO.
++ * @power_cmd: Power command to be set.
++ *
++ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
++ **/
++int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd)
++{
++ enum isp_csi2_power_cmds current_state;
++ u32 reg;
++ u8 retry_count;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
++ ~ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK;
++ switch (power_cmd) {
++ case ISP_CSI2_POWER_OFF:
++ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF;
++ break;
++ case ISP_CSI2_POWER_ON:
++ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON;
++ break;
++ case ISP_CSI2_POWER_ULPW:
++ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW;
++ break;
++ default:
++ printk(KERN_ERR "CSI2: ERROR - Wrong Power command!\n");
++ return -EINVAL;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
++
++ retry_count = 0;
++ do {
++ udelay(50);
++ current_state = isp_csi2_complexio_power_status();
++
++ if (current_state != power_cmd) {
++ printk(KERN_DEBUG "CSI2: Complex IO power command not"
++ " yet taken.");
++ if (++retry_count < 100) {
++ printk(KERN_DEBUG " Retrying...\n");
++ udelay(50);
++ } else {
++ printk(KERN_DEBUG " Retry count exceeded!\n");
++ }
++ }
++ } while ((current_state != power_cmd) && (retry_count < 100));
++
++ if (retry_count == 100)
++ return -EBUSY;
++
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_frame_mode - Configure if_en behaviour for CSI2
++ * @frame_mode: Desired action for IF_EN switch off. 0 - disable IF immediately
++ * 1 - disable after all Frame end Code is received in all
++ * contexts.
++ *
++ * Validates and saves to internal driver memory the passed configuration.
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->frame_mode != frame_mode) {
++ currctrl->frame_mode = frame_mode;
++ currctrl_u->frame_mode = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_vp_clk_enable - Enables/disables CSI2 Videoport clock.
++ * @vp_clk_enable: Boolean value to specify the Videoport clock state.
++ *
++ * Validates and saves to internal driver memory the passed configuration.
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->vp_clk_enable != vp_clk_enable) {
++ currctrl->vp_clk_enable = vp_clk_enable;
++ currctrl_u->vp_clk_enable = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_vp_only_enable - Sets CSI2 Videoport clock as exclusive
++ * @vp_only_enable: Boolean value to specify if the Videoport clock is
++ * exclusive, setting the OCP port as disabled.
++ *
++ * Validates and saves to internal driver memory the passed configuration.
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->vp_only_enable != vp_only_enable) {
++ currctrl->vp_only_enable = vp_only_enable;
++ currctrl_u->vp_only_enable = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_vp_out_ctrl - Sets CSI2 Videoport clock divider
++ * @vp_out_ctrl: Divider value for setting videoport clock frequency based on
++ * OCP port frequency, valid dividers are between 1 and 4.
++ *
++ * Validates and saves to internal driver memory the passed configuration.
++ * Returns 0 if successful, or -EINVAL if wrong divider value is passed.
++ **/
++int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if ((vp_out_ctrl == 0) || (vp_out_ctrl > 4)) {
++ printk(KERN_ERR "CSI2: Wrong divisor value. Must be between"
++ " 1 and 4");
++ return -EINVAL;
++ }
++
++ if (currctrl->vp_out_ctrl != vp_out_ctrl) {
++ currctrl->vp_out_ctrl = vp_out_ctrl;
++ currctrl_u->vp_out_ctrl = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_debug_enable - Sets CSI2 debug
++ * @debug_enable: Boolean for setting debug configuration on CSI2.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_debug_enable(bool debug_enable)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->debug_enable != debug_enable) {
++ currctrl->debug_enable = debug_enable;
++ currctrl_u->debug_enable = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_burst_size - Sets CSI2 burst size.
++ * @burst_size: Burst size of the memory saving capability of receiver.
++ *
++ * Returns 0 if successful, or -EINVAL if burst size is wrong.
++ **/
++int isp_csi2_ctrl_config_burst_size(u8 burst_size)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++ if (burst_size > 3) {
++ printk(KERN_ERR "CSI2: Wrong burst size. Must be between"
++ " 0 and 3");
++ return -EINVAL;
++ }
++
++ if (currctrl->burst_size != burst_size) {
++ currctrl->burst_size = burst_size;
++ currctrl_u->burst_size = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
++ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->ecc_enable != ecc_enable) {
++ currctrl->ecc_enable = ecc_enable;
++ currctrl_u->ecc_enable = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
++ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_secure_mode(bool secure_mode)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->secure_mode != secure_mode) {
++ currctrl->secure_mode = secure_mode;
++ currctrl_u->secure_mode = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_config_if_enable - Enables CSI2 Receiver interface.
++ * @if_enable: Boolean to enable/disable the CSI2 receiver interface.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_config_if_enable(bool if_enable)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++
++ if (currctrl->if_enable != if_enable) {
++ currctrl->if_enable = if_enable;
++ currctrl_u->if_enable = true;
++ update_ctrl = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_update - Applies CSI2 control configuration.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_ctrl_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_ctrl_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_update(bool force_update)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++ u32 reg;
++
++ if (update_ctrl || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
++ if (currctrl_u->frame_mode || force_update) {
++ reg &= ~ISPCSI2_CTRL_FRAME_MASK;
++ if (currctrl->frame_mode)
++ reg |= ISPCSI2_CTRL_FRAME_DISABLE_FEC;
++ else
++ reg |= ISPCSI2_CTRL_FRAME_DISABLE_IMM;
++ currctrl_u->frame_mode = false;
++ }
++ if (currctrl_u->vp_clk_enable || force_update) {
++ reg &= ~ISPCSI2_CTRL_VP_CLK_EN_MASK;
++ if (currctrl->vp_clk_enable)
++ reg |= ISPCSI2_CTRL_VP_CLK_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_VP_CLK_EN_DISABLE;
++ currctrl_u->vp_clk_enable = false;
++ }
++ if (currctrl_u->vp_only_enable || force_update) {
++ reg &= ~ISPCSI2_CTRL_VP_ONLY_EN_MASK;
++ uses_videoport = currctrl->vp_only_enable;
++ if (currctrl->vp_only_enable)
++ reg |= ISPCSI2_CTRL_VP_ONLY_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_VP_ONLY_EN_DISABLE;
++ currctrl_u->vp_only_enable = false;
++ }
++ if (currctrl_u->vp_out_ctrl || force_update) {
++ reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
++ reg |= (currctrl->vp_out_ctrl - 1) <<
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
++ currctrl_u->vp_out_ctrl = false;
++ }
++ if (currctrl_u->debug_enable || force_update) {
++ reg &= ~ISPCSI2_CTRL_DBG_EN_MASK;
++ if (currctrl->debug_enable)
++ reg |= ISPCSI2_CTRL_DBG_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_DBG_EN_DISABLE;
++ currctrl_u->debug_enable = false;
++ }
++ if (currctrl_u->burst_size || force_update) {
++ reg &= ~ISPCSI2_CTRL_BURST_SIZE_MASK;
++ reg |= currctrl->burst_size <<
++ ISPCSI2_CTRL_BURST_SIZE_SHIFT;
++ currctrl_u->burst_size = false;
++ }
++ if (currctrl_u->ecc_enable || force_update) {
++ reg &= ~ISPCSI2_CTRL_ECC_EN_MASK;
++ if (currctrl->ecc_enable)
++ reg |= ISPCSI2_CTRL_ECC_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_ECC_EN_DISABLE;
++ currctrl_u->ecc_enable = false;
++ }
++ if (currctrl_u->secure_mode || force_update) {
++ reg &= ~ISPCSI2_CTRL_SECURE_MASK;
++ if (currctrl->secure_mode)
++ reg |= ISPCSI2_CTRL_SECURE_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_SECURE_DISABLE;
++ currctrl_u->secure_mode = false;
++ }
++ if (currctrl_u->if_enable || force_update) {
++ reg &= ~ISPCSI2_CTRL_IF_EN_MASK;
++ if (currctrl->if_enable)
++ reg |= ISPCSI2_CTRL_IF_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTRL_IF_EN_DISABLE;
++ currctrl_u->if_enable = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
++ update_ctrl = false;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctrl_get - Gets CSI2 control configuration
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctrl_get(void)
++{
++ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
++ struct isp_csi2_ctrl_cfg_update *currctrl_u =
++ &current_csi2_cfg_update.ctrl;
++ u32 reg;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
++ currctrl->frame_mode = (reg & ISPCSI2_CTRL_FRAME_MASK) >>
++ ISPCSI2_CTRL_FRAME_SHIFT;
++ currctrl_u->frame_mode = false;
++
++ if ((reg & ISPCSI2_CTRL_VP_CLK_EN_MASK) ==
++ ISPCSI2_CTRL_VP_CLK_EN_ENABLE)
++ currctrl->vp_clk_enable = true;
++ else
++ currctrl->vp_clk_enable = false;
++ currctrl_u->vp_clk_enable = false;
++
++ if ((reg & ISPCSI2_CTRL_VP_ONLY_EN_MASK) ==
++ ISPCSI2_CTRL_VP_ONLY_EN_ENABLE)
++ currctrl->vp_only_enable = true;
++ else
++ currctrl->vp_only_enable = false;
++ uses_videoport = currctrl->vp_only_enable;
++ currctrl_u->vp_only_enable = false;
++
++ currctrl->vp_out_ctrl = ((reg & ISPCSI2_CTRL_VP_OUT_CTRL_MASK) >>
++ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT) + 1;
++ currctrl_u->vp_out_ctrl = false;
++
++ if ((reg & ISPCSI2_CTRL_DBG_EN_MASK) == ISPCSI2_CTRL_DBG_EN_ENABLE)
++ currctrl->debug_enable = true;
++ else
++ currctrl->debug_enable = false;
++ currctrl_u->debug_enable = false;
++
++ currctrl->burst_size = (reg & ISPCSI2_CTRL_BURST_SIZE_MASK) >>
++ ISPCSI2_CTRL_BURST_SIZE_SHIFT;
++ currctrl_u->burst_size = false;
++
++ if ((reg & ISPCSI2_CTRL_ECC_EN_MASK) == ISPCSI2_CTRL_ECC_EN_ENABLE)
++ currctrl->ecc_enable = true;
++ else
++ currctrl->ecc_enable = false;
++ currctrl_u->ecc_enable = false;
++
++ if ((reg & ISPCSI2_CTRL_SECURE_MASK) == ISPCSI2_CTRL_SECURE_ENABLE)
++ currctrl->secure_mode = true;
++ else
++ currctrl->secure_mode = false;
++ currctrl_u->secure_mode = false;
++
++ if ((reg & ISPCSI2_CTRL_IF_EN_MASK) == ISPCSI2_CTRL_IF_EN_ENABLE)
++ currctrl->if_enable = true;
++ else
++ currctrl->if_enable = false;
++ currctrl_u->if_enable = false;
++
++ update_ctrl = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_validate - Validates the context number value
++ * @ctxnum: Pointer to variable containing context number.
++ *
++ * If the value is not in range (3 bits), it is being ANDed with 0x7 to force
++ * it to be on range.
++ **/
++static void isp_csi2_ctx_validate(u8 *ctxnum)
++{
++ if (*ctxnum > 7) {
++ printk(KERN_ERR "Invalid context number. Forcing valid"
++ " value...\n");
++ *ctxnum &= ~(0x7);
++ }
++}
++
++/**
++ * isp_csi2_ctx_config_virtual_id - Maps a virtual ID with a CSI2 Rx context
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @virtual_id: CSI2 Virtual ID to associate with specified context number.
++ *
++ * Returns 0 if successful, or -EINVAL if Virtual ID is not in range (0-3).
++ **/
++int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ if (virtual_id > 3) {
++ printk(KERN_ERR "Wrong requested virtual_id\n");
++ return -EINVAL;
++ }
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->virtual_id != virtual_id) {
++ selected_ctx->virtual_id = virtual_id;
++ selected_ctx_u->virtual_id = true;
++ update_ctx_ctrl2[ctxnum] = true;
++ }
++
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_frame_count - Sets frame count to be received in CSI2 Rx.
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @frame_count: Number of frames to acquire.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->frame_count != frame_count) {
++ selected_ctx->frame_count = frame_count;
++ selected_ctx_u->frame_count = true;
++ update_ctx_ctrl1[ctxnum] = true;
++ }
++
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_format - Maps a pixel format to a specified context.
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @pixformat: V4L2 structure for pixel format.
++ *
++ * Returns 0 if successful, or -EINVAL if the format is not supported by the
++ * receiver.
++ **/
++int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++ struct v4l2_pix_format pix;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ pix.pixelformat = pixformat;
++ switch (pix.pixelformat) {
++ case V4L2_PIX_FMT_RGB565:
++ case V4L2_PIX_FMT_RGB565X:
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_UYVY:
++ case V4L2_PIX_FMT_RGB555:
++ case V4L2_PIX_FMT_RGB555X:
++ case V4L2_PIX_FMT_SGRBG10:
++ break;
++ default:
++ printk(KERN_ERR "Context config pixel format unsupported\n");
++ return -EINVAL;
++ }
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ selected_ctx->format = pix;
++ selected_ctx_u->format = true;
++ update_ctx_ctrl2[ctxnum] = true;
++
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_alpha - Sets the alpha value for pixel format
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @alpha: Alpha value.
++ *
++ * Returns 0 if successful, or -EINVAL if the alpha value is bigger than 16383.
++ **/
++int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ if (alpha > 0x3FFF) {
++ printk(KERN_ERR "Wrong alpha value\n");
++ return -EINVAL;
++ }
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->alpha != alpha) {
++ selected_ctx->alpha = alpha;
++ selected_ctx_u->alpha = true;
++ update_ctx_ctrl3[ctxnum] = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_data_offset - Sets the offset between received lines
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @data_offset: Offset between first pixel of each 2 contiguous lines.
++ *
++ * Returns 0 if successful, or -EINVAL if the line offset is bigger than 1023.
++ **/
++int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ if (data_offset > 0x3FF) {
++ printk(KERN_ERR "Wrong line offset\n");
++ return -EINVAL;
++ }
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->data_offset != data_offset) {
++ selected_ctx->data_offset = data_offset;
++ selected_ctx_u->data_offset = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_ping_addr - Sets Ping address for CSI2 Rx. buffer saving
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @ping_addr: 32 bit ISP MMU mapped address.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ ping_addr &= ~(0x1F);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->ping_addr != ping_addr) {
++ selected_ctx->ping_addr = ping_addr;
++ selected_ctx_u->ping_addr = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_pong_addr - Sets Pong address for CSI2 Rx. buffer saving
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @pong_addr: 32 bit ISP MMU mapped address.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ pong_addr &= ~(0x1F);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->pong_addr != pong_addr) {
++ selected_ctx->pong_addr = pong_addr;
++ selected_ctx_u->pong_addr = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_eof_enabled - Enables EOF signal assertion
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @eof_enabled: Boolean to enable/disable EOF signal assertion on received
++ * packets.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->eof_enabled != eof_enabled) {
++ selected_ctx->eof_enabled = eof_enabled;
++ selected_ctx_u->eof_enabled = true;
++ update_ctx_ctrl1[ctxnum] = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_eol_enabled - Enables EOL signal assertion
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @eol_enabled: Boolean to enable/disable EOL signal assertion on received
++ * packets.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->eol_enabled != eol_enabled) {
++ selected_ctx->eol_enabled = eol_enabled;
++ selected_ctx_u->eol_enabled = true;
++ update_ctx_ctrl1[ctxnum] = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_checksum_enabled - Enables Checksum check in rcvd packets
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @checksum_enabled: Boolean to enable/disable Checksum check on received
++ * packets
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->checksum_enabled != checksum_enabled) {
++ selected_ctx->checksum_enabled = checksum_enabled;
++ selected_ctx_u->checksum_enabled = true;
++ update_ctx_ctrl1[ctxnum] = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_config_enabled - Enables specified CSI2 context
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @enabled: Boolean to enable/disable specified context.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (selected_ctx->enabled != enabled) {
++ selected_ctx->enabled = enabled;
++ selected_ctx_u->enabled = true;
++ update_ctx_ctrl1[ctxnum] = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_update - Applies CSI2 context configuration.
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_ctx_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_update(u8 ctxnum, bool force_update)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++ u32 reg;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ if (update_ctx_ctrl1[ctxnum] || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL1(ctxnum));
++ if (selected_ctx_u->frame_count || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL1_COUNT_MASK);
++ reg |= selected_ctx->frame_count <<
++ ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
++ selected_ctx_u->frame_count = false;
++ }
++ if (selected_ctx_u->eof_enabled || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL1_EOF_EN_MASK);
++ if (selected_ctx->eof_enabled)
++ reg |= ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE;
++ selected_ctx_u->eof_enabled = false;
++ }
++ if (selected_ctx_u->eol_enabled || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL1_EOL_EN_MASK);
++ if (selected_ctx->eol_enabled)
++ reg |= ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE;
++ selected_ctx_u->eol_enabled = false;
++ }
++ if (selected_ctx_u->checksum_enabled || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL1_CS_EN_MASK);
++ if (selected_ctx->checksum_enabled)
++ reg |= ISPCSI2_CTX_CTRL1_CS_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTX_CTRL1_CS_EN_DISABLE;
++ selected_ctx_u->checksum_enabled = false;
++ }
++ if (selected_ctx_u->enabled || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL1_CTX_EN_MASK);
++ if (selected_ctx->enabled)
++ reg |= ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE;
++ else
++ reg |= ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE;
++ selected_ctx_u->enabled = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL1(ctxnum));
++ update_ctx_ctrl1[ctxnum] = false;
++ }
++
++ if (update_ctx_ctrl2[ctxnum] || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL2(ctxnum));
++ if (selected_ctx_u->virtual_id || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
++ reg |= selected_ctx->virtual_id <<
++ ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
++ selected_ctx_u->virtual_id = false;
++ }
++
++ if (selected_ctx_u->format || force_update) {
++ struct v4l2_pix_format *pix;
++ u16 new_format = 0;
++
++ reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
++ pix = &selected_ctx->format;
++ switch (pix->pixelformat) {
++ case V4L2_PIX_FMT_RGB565:
++ case V4L2_PIX_FMT_RGB565X:
++ new_format = 0x22;
++ break;
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_UYVY:
++ if (uses_videoport)
++ new_format = 0x9E;
++ else
++ new_format = 0x1E;
++ break;
++ case V4L2_PIX_FMT_RGB555:
++ case V4L2_PIX_FMT_RGB555X:
++ new_format = 0xA1;
++ break;
++ case V4L2_PIX_FMT_SGRBG10:
++ if (uses_videoport)
++ new_format = 0x12F;
++ else
++ new_format = 0xAB;
++ break;
++ }
++ reg |= (new_format << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT);
++ selected_ctx_u->format = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL2(ctxnum));
++ update_ctx_ctrl2[ctxnum] = false;
++ }
++
++ if (update_ctx_ctrl3[ctxnum] || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL3(ctxnum));
++ if (selected_ctx_u->alpha || force_update) {
++ reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
++ reg |= (selected_ctx->alpha <<
++ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
++ selected_ctx_u->alpha = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL3(ctxnum));
++ update_ctx_ctrl3[ctxnum] = false;
++ }
++
++ if (selected_ctx_u->data_offset) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_OFST(ctxnum));
++ reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
++ reg |= selected_ctx->data_offset <<
++ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_OFST(ctxnum));
++ selected_ctx_u->data_offset = false;
++ }
++
++ if (selected_ctx_u->ping_addr) {
++ reg = selected_ctx->ping_addr;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
++ selected_ctx_u->ping_addr = false;
++ }
++
++ if (selected_ctx_u->pong_addr) {
++ reg = selected_ctx->pong_addr;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
++ selected_ctx_u->pong_addr = false;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_get - Gets specific CSI2 Context configuration
++ * @ctxnum: Context number, valid between 0 and 7 values.
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_get(u8 ctxnum)
++{
++ struct isp_csi2_ctx_cfg *selected_ctx;
++ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
++ u32 reg;
++
++ isp_csi2_ctx_validate(&ctxnum);
++
++ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
++ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL1(ctxnum));
++ selected_ctx->frame_count = (reg & ISPCSI2_CTX_CTRL1_COUNT_MASK) >>
++ ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
++ selected_ctx_u->frame_count = false;
++
++ if ((reg & ISPCSI2_CTX_CTRL1_EOF_EN_MASK) ==
++ ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE)
++ selected_ctx->eof_enabled = true;
++ else
++ selected_ctx->eof_enabled = false;
++ selected_ctx_u->eof_enabled = false;
++
++ if ((reg & ISPCSI2_CTX_CTRL1_EOL_EN_MASK) ==
++ ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE)
++ selected_ctx->eol_enabled = true;
++ else
++ selected_ctx->eol_enabled = false;
++ selected_ctx_u->eol_enabled = false;
++
++ if ((reg & ISPCSI2_CTX_CTRL1_CS_EN_MASK) ==
++ ISPCSI2_CTX_CTRL1_CS_EN_ENABLE)
++ selected_ctx->checksum_enabled = true;
++ else
++ selected_ctx->checksum_enabled = false;
++ selected_ctx_u->checksum_enabled = false;
++
++ if ((reg & ISPCSI2_CTX_CTRL1_CTX_EN_MASK) ==
++ ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE)
++ selected_ctx->enabled = true;
++ else
++ selected_ctx->enabled = false;
++ selected_ctx_u->enabled = false;
++ update_ctx_ctrl1[ctxnum] = false;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL2(ctxnum));
++
++ selected_ctx->virtual_id = (reg & ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK) >>
++ ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
++ selected_ctx_u->virtual_id = false;
++
++ switch ((reg & ISPCSI2_CTX_CTRL2_FORMAT_MASK) >>
++ ISPCSI2_CTX_CTRL2_FORMAT_SHIFT) {
++ case 0x22:
++ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB565;
++ break;
++ case 0x9E:
++ case 0x1E:
++ selected_ctx->format.pixelformat = V4L2_PIX_FMT_YUYV;
++ break;
++ case 0xA1:
++ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB555;
++ break;
++ case 0xAB:
++ case 0x12F:
++ selected_ctx->format.pixelformat = V4L2_PIX_FMT_SGRBG10;
++ break;
++ }
++ selected_ctx_u->format = false;
++ update_ctx_ctrl2[ctxnum] = false;
++
++ selected_ctx->alpha = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL3(ctxnum)) &
++ ISPCSI2_CTX_CTRL3_ALPHA_MASK) >>
++ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT;
++ selected_ctx_u->alpha = false;
++ update_ctx_ctrl3[ctxnum] = false;
++
++ selected_ctx->data_offset = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_OFST(ctxnum)) &
++ ISPCSI2_CTX_DAT_OFST_OFST_MASK) >>
++ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
++ selected_ctx_u->data_offset = false;
++
++ selected_ctx->ping_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
++ selected_ctx_u->ping_addr = false;
++
++ selected_ctx->pong_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
++ selected_ctx_u->pong_addr = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_update_all - Applies all CSI2 context configuration.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_ctx_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_update_all(bool force_update)
++{
++ u8 ctxnum;
++
++ for (ctxnum = 0; ctxnum < 8; ctxnum++)
++ isp_csi2_ctx_update(ctxnum, force_update);
++
++ return 0;
++}
++
++/**
++ * isp_csi2_ctx_get_all - Gets all CSI2 Context configurations
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_ctx_get_all(void)
++{
++ u8 ctxnum;
++
++ for (ctxnum = 0; ctxnum < 8; ctxnum++)
++ isp_csi2_ctx_get(ctxnum);
++
++ return 0;
++}
++
++int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig)
++{
++ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
++ struct isp_csi2_phy_cfg_update *currphy_u =
++ &current_csi2_cfg_update.phy;
++
++ if ((desiredphyconfig->tclk_term > 0x7f) ||
++ (desiredphyconfig->tclk_miss > 0x3)) {
++ printk(KERN_ERR "Invalid PHY configuration sent by the"
++ " driver\n");
++ return -EINVAL;
++ }
++
++ if (currphy->ths_term != desiredphyconfig->ths_term) {
++ currphy->ths_term = desiredphyconfig->ths_term;
++ currphy_u->ths_term = true;
++ update_phy_cfg0 = true;
++ }
++ if (currphy->ths_settle != desiredphyconfig->ths_settle) {
++ currphy->ths_settle = desiredphyconfig->ths_settle;
++ currphy_u->ths_settle = true;
++ update_phy_cfg0 = true;
++ }
++ if (currphy->tclk_term != desiredphyconfig->tclk_term) {
++ currphy->tclk_term = desiredphyconfig->tclk_term;
++ currphy_u->tclk_term = true;
++ update_phy_cfg1 = true;
++ }
++ if (currphy->tclk_miss != desiredphyconfig->tclk_miss) {
++ currphy->tclk_miss = desiredphyconfig->tclk_miss;
++ currphy_u->tclk_miss = true;
++ update_phy_cfg1 = true;
++ }
++ if (currphy->tclk_settle != desiredphyconfig->tclk_settle) {
++ currphy->tclk_settle = desiredphyconfig->tclk_settle;
++ currphy_u->tclk_settle = true;
++ update_phy_cfg1 = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_calc_phy_cfg0 - Calculates D-PHY config based on the MIPIClk speed.
++ * @mipiclk: MIPI clock frequency being used with CSI2 sensor.
++ * @lbound_hs_settle: Lower bound for CSI2 High Speed Settle transition.
++ * @ubound_hs_settle: Upper bound for CSI2 High Speed Settle transition.
++ *
++ * From TRM, we have the same calculation for HS Termination signal.
++ * THS_TERM = ceil( 12.5ns / DDRCLK period ) - 1
++ * But for Settle, we use the mid value between the two passed boundaries from
++ * sensor:
++ * THS_SETTLE = (Upper bound + Lower bound) / 2
++ *
++ * Always returns 0.
++ */
++int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
++ u32 ubound_hs_settle)
++{
++ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
++ struct isp_csi2_phy_cfg_update *currphy_u =
++ &current_csi2_cfg_update.phy;
++ u32 tmp, ddrclk = mipiclk >> 1;
++
++ /* Calculate THS_TERM */
++ tmp = ddrclk / 80000000;
++ if ((ddrclk % 80000000) > 0)
++ tmp++;
++ currphy->ths_term = tmp - 1;
++ currphy_u->ths_term = true;
++
++ /* Calculate THS_SETTLE */
++ currphy->ths_settle = (ubound_hs_settle + lbound_hs_settle) / 2;
++
++ currphy_u->ths_settle = true;
++ isp_csi2_phy_update(true);
++ return 0;
++}
++EXPORT_SYMBOL(isp_csi2_calc_phy_cfg0);
++
++/**
++ * isp_csi2_phy_update - Applies CSI2 D-PHY configuration.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_phy_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_phy_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_phy_update(bool force_update)
++{
++ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
++ struct isp_csi2_phy_cfg_update *currphy_u =
++ &current_csi2_cfg_update.phy;
++ u32 reg;
++
++ if (update_phy_cfg0 || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
++ if (currphy_u->ths_term || force_update) {
++ reg &= ~ISPCSI2PHY_CFG0_THS_TERM_MASK;
++ reg |= (currphy->ths_term <<
++ ISPCSI2PHY_CFG0_THS_TERM_SHIFT);
++ currphy_u->ths_term = false;
++ }
++ if (currphy_u->ths_settle || force_update) {
++ reg &= ~ISPCSI2PHY_CFG0_THS_SETTLE_MASK;
++ reg |= (currphy->ths_settle <<
++ ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT);
++ currphy_u->ths_settle = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
++ update_phy_cfg0 = false;
++ }
++
++ if (update_phy_cfg1 || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
++ if (currphy_u->tclk_term || force_update) {
++ reg &= ~ISPCSI2PHY_CFG1_TCLK_TERM_MASK;
++ reg |= (currphy->tclk_term <<
++ ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT);
++ currphy_u->tclk_term = false;
++ }
++ if (currphy_u->tclk_miss || force_update) {
++ reg &= ~ISPCSI2PHY_CFG1_TCLK_MISS_MASK;
++ reg |= (currphy->tclk_miss <<
++ ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT);
++ currphy_u->tclk_miss = false;
++ }
++ if (currphy_u->tclk_settle || force_update) {
++ reg &= ~ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK;
++ reg |= (currphy->tclk_settle <<
++ ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT);
++ currphy_u->tclk_settle = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
++ update_phy_cfg1 = false;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_phy_get - Gets CSI2 D-PHY configuration
++ *
++ * Gets settings from HW registers and fills in the internal driver memory
++ * Always returns 0.
++ **/
++int isp_csi2_phy_get(void)
++{
++ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
++ struct isp_csi2_phy_cfg_update *currphy_u =
++ &current_csi2_cfg_update.phy;
++ u32 reg;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
++ currphy->ths_term = (reg & ISPCSI2PHY_CFG0_THS_TERM_MASK) >>
++ ISPCSI2PHY_CFG0_THS_TERM_SHIFT;
++ currphy_u->ths_term = false;
++
++ currphy->ths_settle = (reg & ISPCSI2PHY_CFG0_THS_SETTLE_MASK) >>
++ ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT;
++ currphy_u->ths_settle = false;
++ update_phy_cfg0 = false;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
++
++ currphy->tclk_term = (reg & ISPCSI2PHY_CFG1_TCLK_TERM_MASK) >>
++ ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT;
++ currphy_u->tclk_term = false;
++
++ currphy->tclk_miss = (reg & ISPCSI2PHY_CFG1_TCLK_MISS_MASK) >>
++ ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT;
++ currphy_u->tclk_miss = false;
++
++ currphy->tclk_settle = (reg & ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK) >>
++ ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT;
++ currphy_u->tclk_settle = false;
++
++ update_phy_cfg1 = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_config_forcerxmode - Sets Force Rx mode on stop state count
++ * @force_rx_mode: Boolean to enable/disable forcing Rx mode in CSI2 receiver
++ *
++ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
++ **/
++int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++ if (currtimings->force_rx_mode != force_rx_mode) {
++ currtimings->force_rx_mode = force_rx_mode;
++ currtimings_u->force_rx_mode = true;
++ update_timing = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_config_stopstate_16x - Sets 16x factor for L3 cycles
++ * @stop_state_16x: Boolean to use or not use the 16x multiplier for stop count
++ *
++ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
++ **/
++int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++ if (currtimings->stop_state_16x != stop_state_16x) {
++ currtimings->stop_state_16x = stop_state_16x;
++ currtimings_u->stop_state_16x = true;
++ update_timing = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_config_stopstate_4x - Sets 4x factor for L3 cycles
++ * @stop_state_4x: Boolean to use or not use the 4x multiplier for stop count
++ *
++ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
++ **/
++int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++ if (currtimings->stop_state_4x != stop_state_4x) {
++ currtimings->stop_state_4x = stop_state_4x;
++ currtimings_u->stop_state_4x = true;
++ update_timing = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_config_stopstate_cnt - Sets L3 cycles
++ * @stop_state_counter: Stop state counter value for L3 cycles
++ *
++ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
++ **/
++int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++ if (currtimings->stop_state_counter != stop_state_counter) {
++ currtimings->stop_state_counter = (stop_state_counter & 0x1FFF);
++ currtimings_u->stop_state_counter = true;
++ update_timing = true;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_update - Applies specified CSI2 timing configuration.
++ * @io: IO number (1 or 2) which specifies which ComplexIO are we updating
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_timings_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_timings_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
++ **/
++int isp_csi2_timings_update(u8 io, bool force_update)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++ u32 reg;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++
++ if (update_timing || force_update) {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
++ if (currtimings_u->force_rx_mode || force_update) {
++ reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io);
++ if (currtimings->force_rx_mode)
++ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE
++ (io);
++ else
++ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE
++ (io);
++ currtimings_u->force_rx_mode = false;
++ }
++ if (currtimings_u->stop_state_16x || force_update) {
++ reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io);
++ if (currtimings->stop_state_16x)
++ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE
++ (io);
++ else
++ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE
++ (io);
++ currtimings_u->stop_state_16x = false;
++ }
++ if (currtimings_u->stop_state_4x || force_update) {
++ reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io);
++ if (currtimings->stop_state_4x) {
++ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE
++ (io);
++ } else {
++ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE
++ (io);
++ }
++ currtimings_u->stop_state_4x = false;
++ }
++ if (currtimings_u->stop_state_counter || force_update) {
++ reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io);
++ reg |= currtimings->stop_state_counter <<
++ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
++ currtimings_u->stop_state_counter = false;
++ }
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
++ update_timing = false;
++ }
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_get - Gets specific CSI2 ComplexIO timing configuration
++ * @io: IO number (1 or 2) which specifies which ComplexIO are we getting
++ *
++ * Gets settings from HW registers and fills in the internal driver memory
++ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
++ **/
++int isp_csi2_timings_get(u8 io)
++{
++ struct isp_csi2_timings_cfg *currtimings;
++ struct isp_csi2_timings_cfg_update *currtimings_u;
++ u32 reg;
++
++ if (io < 1 || io > 2) {
++ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
++ return -EINVAL;
++ }
++
++ currtimings = &current_csi2_cfg.timings[io - 1];
++ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
++ if ((reg & ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io)) ==
++ ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(io))
++ currtimings->force_rx_mode = true;
++ else
++ currtimings->force_rx_mode = false;
++ currtimings_u->force_rx_mode = false;
++
++ if ((reg & ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io)) ==
++ ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(io))
++ currtimings->stop_state_16x = true;
++ else
++ currtimings->stop_state_16x = false;
++ currtimings_u->stop_state_16x = false;
++
++ if ((reg & ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io)) ==
++ ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(io))
++ currtimings->stop_state_4x = true;
++ else
++ currtimings->stop_state_4x = false;
++ currtimings_u->stop_state_4x = false;
++
++ currtimings->stop_state_counter = (reg &
++ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io)) >>
++ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
++ currtimings_u->stop_state_counter = false;
++ update_timing = false;
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_update_all - Applies specified CSI2 timing configuration.
++ * @force_update: Flag to force rewrite of registers, even if they haven't been
++ * updated with the isp_csi2_timings_config_*() functions.
++ *
++ * It only saves settings when they were previously updated using the
++ * isp_csi2_timings_config_*() functions, unless the force_update flag is
++ * set to true.
++ * Always returns 0.
++ **/
++int isp_csi2_timings_update_all(bool force_update)
++{
++ int i;
++
++ for (i = 1; i < 3; i++)
++ isp_csi2_timings_update(i, force_update);
++ return 0;
++}
++
++/**
++ * isp_csi2_timings_get_all - Gets all CSI2 ComplexIO timing configurations
++ *
++ * Always returns 0.
++ **/
++int isp_csi2_timings_get_all(void)
++{
++ int i;
++
++ for (i = 1; i < 3; i++)
++ isp_csi2_timings_get(i);
++ return 0;
++}
++
++/**
++ * isp_csi2_isr - CSI2 interrupt handling.
++ **/
++void isp_csi2_isr(void)
++{
++ u32 csi2_irqstatus, cpxio1_irqstatus, ctxirqstatus;
++
++ csi2_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_IRQSTATUS);
++ isp_reg_writel(csi2_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_IRQSTATUS);
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
++ cpxio1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO1_IRQSTATUS);
++ isp_reg_writel(cpxio1_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO1_IRQSTATUS);
++ printk(KERN_ERR "CSI2: ComplexIO Error IRQ %x\n",
++ cpxio1_irqstatus);
++ }
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) {
++ ctxirqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQSTATUS(0));
++ isp_reg_writel(ctxirqstatus, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQSTATUS(0));
++ }
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_OCP_ERR_IRQ)
++ printk(KERN_ERR "CSI2: OCP Transmission Error\n");
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ)
++ printk(KERN_ERR "CSI2: Short packet receive error\n");
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
++ printk(KERN_DEBUG "CSI2: ECC correction done\n");
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ)
++ printk(KERN_ERR "CSI2: ECC correction failed\n");
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ)
++ printk(KERN_ERR "CSI2: ComplexIO #2 failed\n");
++
++ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)
++ printk(KERN_ERR "CSI2: FIFO overflow error\n");
++
++ return;
++}
++EXPORT_SYMBOL(isp_csi2_isr);
++
++/**
++ * isp_csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
++ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
++ **/
++void isp_csi2_irq_complexio1_set(int enable)
++{
++ u32 reg;
++ reg = ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 |
++ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO1_IRQSTATUS);
++ if (enable) {
++ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO1_IRQENABLE);
++ } else
++ reg = 0;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO1_IRQENABLE);
++}
++EXPORT_SYMBOL(isp_csi2_irq_complexio1_set);
++
++/**
++ * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
++ * @enable: Enable/disable CSI2 Context interrupts
++ **/
++void isp_csi2_irq_ctx_set(int enable)
++{
++ u32 reg;
++ int i;
++
++ reg = ISPCSI2_CTX_IRQSTATUS_FS_IRQ | ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
++ for (i = 0; i < 8; i++) {
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQSTATUS(i));
++ if (enable) {
++ isp_reg_or(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQENABLE(i), reg);
++ } else {
++ isp_reg_writel(0, OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQENABLE(i));
++ }
++ }
++
++}
++EXPORT_SYMBOL(isp_csi2_irq_ctx_set);
++
++/**
++ * isp_csi2_irq_status_set - Enables CSI2 Status IRQs.
++ * @enable: Enable/disable CSI2 Status interrupts
++ **/
++void isp_csi2_irq_status_set(int enable)
++{
++ u32 reg;
++ reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
++ ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
++ ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
++ ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
++ ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
++ ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
++ ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
++ ISPCSI2_IRQSTATUS_CONTEXT(0);
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQSTATUS);
++ if (enable)
++ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
++ else
++ reg = 0;
++
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
++}
++EXPORT_SYMBOL(isp_csi2_irq_status_set);
++
++/**
++ * isp_csi2_irq_status_set - Enables main CSI2 IRQ.
++ * @enable: Enable/disable main CSI2 interrupt
++ **/
++void isp_csi2_irq_set(int enable)
++{
++ isp_reg_writel(IRQ0STATUS_CSIA_IRQ, OMAP3_ISP_IOMEM_MAIN,
++ ISP_IRQ0STATUS);
++ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_CSIA_IRQ,
++ (enable ? IRQ0ENABLE_CSIA_IRQ : 0));
++}
++EXPORT_SYMBOL(isp_csi2_irq_set);
++
++/**
++ * isp_csi2_irq_all_set - Enable/disable CSI2 interrupts.
++ * @enable: 0-Disable, 1-Enable.
++ **/
++void isp_csi2_irq_all_set(int enable)
++{
++ if (enable) {
++ isp_csi2_irq_complexio1_set(enable);
++ isp_csi2_irq_ctx_set(enable);
++ isp_csi2_irq_status_set(enable);
++ isp_csi2_irq_set(enable);
++ } else {
++ isp_csi2_irq_set(enable);
++ isp_csi2_irq_status_set(enable);
++ isp_csi2_irq_ctx_set(enable);
++ isp_csi2_irq_complexio1_set(enable);
++ }
++ return;
++}
++EXPORT_SYMBOL(isp_csi2_irq_all_set);
++
++/**
++ * isp_csi2_reset - Resets the CSI2 module.
++ *
++ * Returns 0 if successful, or -EBUSY if power command didn't respond.
++ **/
++int isp_csi2_reset(void)
++{
++ u32 reg;
++ u8 soft_reset_retries = 0;
++ int i;
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
++ reg |= ISPCSI2_SYSCONFIG_SOFT_RESET_RESET;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
++
++ do {
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSSTATUS) &
++ ISPCSI2_SYSSTATUS_RESET_DONE_MASK;
++ if (reg == ISPCSI2_SYSSTATUS_RESET_DONE_DONE)
++ break;
++ soft_reset_retries++;
++ if (soft_reset_retries < 5)
++ udelay(100);
++ } while (soft_reset_retries < 5);
++
++ if (soft_reset_retries == 5) {
++ printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
++ return -EBUSY;
++ }
++
++ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
++ reg &= ~ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK;
++ reg |= ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO;
++ reg &= ~ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK;
++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
++
++ uses_videoport = false;
++ update_complexio_cfg1 = false;
++ update_phy_cfg0 = false;
++ update_phy_cfg1 = false;
++ for (i = 0; i < 8; i++) {
++ update_ctx_ctrl1[i] = false;
++ update_ctx_ctrl2[i] = false;
++ update_ctx_ctrl3[i] = false;
++ }
++ update_timing = false;
++ update_ctrl = false;
++
++ isp_csi2_complexio_lanes_get();
++ isp_csi2_ctrl_get();
++ isp_csi2_ctx_get_all();
++ isp_csi2_phy_get();
++ isp_csi2_timings_get_all();
++
++ isp_csi2_complexio_power_autoswitch(true);
++ isp_csi2_complexio_power(ISP_CSI2_POWER_ON);
++
++ isp_csi2_timings_config_forcerxmode(1, true);
++ isp_csi2_timings_config_stopstate_cnt(1, 0x1FF);
++ isp_csi2_timings_update_all(true);
++
++ return 0;
++}
++
++/**
++ * isp_csi2_enable - Enables the CSI2 module.
++ * @enable: Enables/disables the CSI2 module.
++ **/
++void isp_csi2_enable(int enable)
++{
++ if (enable) {
++ isp_csi2_ctx_config_enabled(0, true);
++ isp_csi2_ctx_config_eof_enabled(0, true);
++ isp_csi2_ctx_config_checksum_enabled(0, true);
++ isp_csi2_ctx_update(0, false);
++
++ isp_csi2_ctrl_config_ecc_enable(true);
++ isp_csi2_ctrl_config_if_enable(true);
++ isp_csi2_ctrl_update(false);
++ } else {
++ isp_csi2_ctx_config_enabled(0, false);
++ isp_csi2_ctx_config_eof_enabled(0, false);
++ isp_csi2_ctx_config_checksum_enabled(0, false);
++ isp_csi2_ctx_update(0, false);
++
++ isp_csi2_ctrl_config_ecc_enable(false);
++ isp_csi2_ctrl_config_if_enable(false);
++ isp_csi2_ctrl_update(false);
++ }
++}
++EXPORT_SYMBOL(isp_csi2_enable);
++
++/**
++ * isp_csi2_regdump - Prints CSI2 debug information.
++ **/
++void isp_csi2_regdump(void)
++{
++ printk(KERN_DEBUG "-------------Register dump-------------\n");
++
++ printk(KERN_DEBUG "ISP_CTRL: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
++ printk(KERN_DEBUG "ISP_TCTRL_CTRL: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
++
++ printk(KERN_DEBUG "ISPCCDC_SDR_ADDR: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
++ printk(KERN_DEBUG "ISPCCDC_SYN_MODE: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
++ printk(KERN_DEBUG "ISPCCDC_CFG: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
++ printk(KERN_DEBUG "ISPCCDC_FMTCFG: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
++ printk(KERN_DEBUG "ISPCCDC_HSIZE_OFF: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
++ printk(KERN_DEBUG "ISPCCDC_HORZ_INFO: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
++ printk(KERN_DEBUG "ISPCCDC_VERT_START: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_START));
++ printk(KERN_DEBUG "ISPCCDC_VERT_LINES: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
++ ISPCCDC_VERT_LINES));
++
++ printk(KERN_DEBUG "ISPCSI2_COMPLEXIO_CFG1: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_COMPLEXIO_CFG1));
++ printk(KERN_DEBUG "ISPCSI2_SYSSTATUS: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_SYSSTATUS));
++ printk(KERN_DEBUG "ISPCSI2_SYSCONFIG: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_SYSCONFIG));
++ printk(KERN_DEBUG "ISPCSI2_IRQENABLE: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_IRQENABLE));
++ printk(KERN_DEBUG "ISPCSI2_IRQSTATUS: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_IRQSTATUS));
++
++ printk(KERN_DEBUG "ISPCSI2_CTX_IRQENABLE(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQENABLE(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_IRQSTATUS(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_IRQSTATUS(0)));
++ printk(KERN_DEBUG "ISPCSI2_TIMING: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING));
++ printk(KERN_DEBUG "ISPCSI2PHY_CFG0: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
++ ISPCSI2PHY_CFG0));
++ printk(KERN_DEBUG "ISPCSI2PHY_CFG1: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
++ ISPCSI2PHY_CFG1));
++ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL1(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL1(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL2(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL2(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL3(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_CTRL3(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_OFST(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_OFST(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PING_ADDR(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PING_ADDR(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PONG_ADDR(0): %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
++ ISPCSI2_CTX_DAT_PONG_ADDR(0)));
++ printk(KERN_DEBUG "ISPCSI2_CTRL: %x\n",
++ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL));
++ printk(KERN_DEBUG "---------------------------------------\n");
++}
++
++/**
++ * isp_csi2_cleanup - Routine for module driver cleanup
++ **/
++void isp_csi2_cleanup(void)
++{
++ return;
++}
++
++/**
++ * isp_csi2_init - Routine for module driver init
++ **/
++int __init isp_csi2_init(void)
++{
++ int i;
++
++ update_complexio_cfg1 = false;
++ update_phy_cfg0 = false;
++ update_phy_cfg1 = false;
++ for (i = 0; i < 8; i++) {
++ update_ctx_ctrl1[i] = false;
++ update_ctx_ctrl2[i] = false;
++ update_ctx_ctrl3[i] = false;
++ }
++ update_timing = false;
++ update_ctrl = false;
++
++ memset(&current_csi2_cfg, 0, sizeof(current_csi2_cfg));
++ memset(&current_csi2_cfg_update, 0, sizeof(current_csi2_cfg_update));
++ return 0;
++}
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_DESCRIPTION("ISP CSI2 Receiver Module");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
+new file mode 100644
+index 0000000..4582c96
+--- /dev/null
++++ b/drivers/media/video/isp/ispcsi2.h
+@@ -0,0 +1,232 @@
++/*
++ * ispcsi2.h
++ *
++ * Copyright (C) 2009 Texas Instruments.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Dominic Curran <dcurran@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_ISP_CSI2_API_H
++#define OMAP_ISP_CSI2_API_H
++#include <linux/videodev2.h>
++
++enum isp_csi2_irqevents {
++ OCP_ERR_IRQ = 0x4000,
++ SHORT_PACKET_IRQ = 0x2000,
++ ECC_CORRECTION_IRQ = 0x1000,
++ ECC_NO_CORRECTION_IRQ = 0x800,
++ COMPLEXIO2_ERR_IRQ = 0x400,
++ COMPLEXIO1_ERR_IRQ = 0x200,
++ FIFO_OVF_IRQ = 0x100,
++ CONTEXT7 = 0x80,
++ CONTEXT6 = 0x40,
++ CONTEXT5 = 0x20,
++ CONTEXT4 = 0x10,
++ CONTEXT3 = 0x8,
++ CONTEXT2 = 0x4,
++ CONTEXT1 = 0x2,
++ CONTEXT0 = 0x1,
++};
++
++enum isp_csi2_ctx_irqevents {
++ CTX_ECC_CORRECTION = 0x100,
++ CTX_LINE_NUMBER = 0x80,
++ CTX_FRAME_NUMBER = 0x40,
++ CTX_CS = 0x20,
++ CTX_LE = 0x8,
++ CTX_LS = 0x4,
++ CTX_FE = 0x2,
++ CTX_FS = 0x1,
++};
++
++enum isp_csi2_power_cmds {
++ ISP_CSI2_POWER_OFF,
++ ISP_CSI2_POWER_ON,
++ ISP_CSI2_POWER_ULPW,
++};
++
++enum isp_csi2_frame_mode {
++ ISP_CSI2_FRAME_IMMEDIATE,
++ ISP_CSI2_FRAME_AFTERFEC,
++};
++
++struct csi2_lanecfg {
++ u8 pos;
++ u8 pol;
++};
++
++struct isp_csi2_lanes_cfg {
++ struct csi2_lanecfg data[4];
++ struct csi2_lanecfg clk;
++};
++
++struct isp_csi2_lanes_cfg_update {
++ bool data[4];
++ bool clk;
++};
++
++struct isp_csi2_phy_cfg {
++ u8 ths_term;
++ u8 ths_settle;
++ u8 tclk_term;
++ unsigned tclk_miss:1;
++ u8 tclk_settle;
++};
++
++struct isp_csi2_phy_cfg_update {
++ bool ths_term;
++ bool ths_settle;
++ bool tclk_term;
++ bool tclk_miss;
++ bool tclk_settle;
++};
++
++struct isp_csi2_ctx_cfg {
++ u8 virtual_id;
++ u8 frame_count;
++ struct v4l2_pix_format format;
++ u16 alpha;
++ u16 data_offset;
++ u32 ping_addr;
++ u32 pong_addr;
++ bool eof_enabled;
++ bool eol_enabled;
++ bool checksum_enabled;
++ bool enabled;
++};
++
++struct isp_csi2_ctx_cfg_update {
++ bool virtual_id;
++ bool frame_count;
++ bool format;
++ bool alpha;
++ bool data_offset;
++ bool ping_addr;
++ bool pong_addr;
++ bool eof_enabled;
++ bool eol_enabled;
++ bool checksum_enabled;
++ bool enabled;
++};
++
++struct isp_csi2_timings_cfg {
++ bool force_rx_mode;
++ bool stop_state_16x;
++ bool stop_state_4x;
++ u16 stop_state_counter;
++};
++
++struct isp_csi2_timings_cfg_update {
++ bool force_rx_mode;
++ bool stop_state_16x;
++ bool stop_state_4x;
++ bool stop_state_counter;
++};
++
++struct isp_csi2_ctrl_cfg {
++ bool vp_clk_enable;
++ bool vp_only_enable;
++ u8 vp_out_ctrl;
++ bool debug_enable;
++ u8 burst_size;
++ enum isp_csi2_frame_mode frame_mode;
++ bool ecc_enable;
++ bool secure_mode;
++ bool if_enable;
++};
++
++struct isp_csi2_ctrl_cfg_update {
++ bool vp_clk_enable;
++ bool vp_only_enable;
++ bool vp_out_ctrl;
++ bool debug_enable;
++ bool burst_size;
++ bool frame_mode;
++ bool ecc_enable;
++ bool secure_mode;
++ bool if_enable;
++};
++
++struct isp_csi2_cfg {
++ struct isp_csi2_lanes_cfg lanes;
++ struct isp_csi2_phy_cfg phy;
++ struct isp_csi2_ctx_cfg contexts[8];
++ struct isp_csi2_timings_cfg timings[2];
++ struct isp_csi2_ctrl_cfg ctrl;
++};
++
++struct isp_csi2_cfg_update {
++ struct isp_csi2_lanes_cfg_update lanes;
++ struct isp_csi2_phy_cfg_update phy;
++ struct isp_csi2_ctx_cfg_update contexts[8];
++ struct isp_csi2_timings_cfg_update timings[2];
++ struct isp_csi2_ctrl_cfg_update ctrl;
++};
++
++int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg);
++int isp_csi2_complexio_lanes_update(bool force_update);
++int isp_csi2_complexio_lanes_get(void);
++int isp_csi2_complexio_power_autoswitch(bool enable);
++int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd);
++int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode);
++int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable);
++int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable);
++int isp_csi2_ctrl_config_debug_enable(bool debug_enable);
++int isp_csi2_ctrl_config_burst_size(u8 burst_size);
++int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable);
++int isp_csi2_ctrl_config_secure_mode(bool secure_mode);
++int isp_csi2_ctrl_config_if_enable(bool if_enable);
++int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl);
++int isp_csi2_ctrl_update(bool force_update);
++int isp_csi2_ctrl_get(void);
++int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id);
++int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count);
++int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat);
++int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha);
++int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset);
++int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr);
++int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr);
++int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled);
++int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled);
++int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled);
++int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled);
++int isp_csi2_ctx_update(u8 ctxnum, bool force_update);
++int isp_csi2_ctx_get(u8 ctxnum);
++int isp_csi2_ctx_update_all(bool force_update);
++int isp_csi2_ctx_get_all(void);
++int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig);
++int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
++ u32 ubound_hs_settle);
++int isp_csi2_phy_update(bool force_update);
++int isp_csi2_phy_get(void);
++int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode);
++int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x);
++int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x);
++int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter);
++int isp_csi2_timings_update(u8 io, bool force_update);
++int isp_csi2_timings_get(u8 io);
++int isp_csi2_timings_update_all(bool force_update);
++int isp_csi2_timings_get_all(void);
++void isp_csi2_irq_complexio1_set(int enable);
++void isp_csi2_irq_ctx_set(int enable);
++void isp_csi2_irq_status_set(int enable);
++void isp_csi2_irq_set(int enable);
++void isp_csi2_irq_all_set(int enable);
++
++void isp_csi2_isr(void);
++int isp_csi2_reset(void);
++void isp_csi2_enable(int enable);
++void isp_csi2_regdump(void);
++
++#endif /* OMAP_ISP_CSI2_H */
++
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch
new file mode 100644
index 0000000000..db023e514d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch
@@ -0,0 +1,4018 @@
+From 5de7cb2cac5f7d76cb025ddc8fb09c99a1007e08 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:02 +0200
+Subject: [PATCH] omap3isp: Add ISP tables
+
+* Blue Gamma gain table
+* CFA gain table
+* Green Gamma gain table
+* Luma Enhancement gain table
+* Noise filter gain table
+* Red Gamma gain table
+
+TODO:
+
+- Get rid of this kind of tables. Either generate them at runtime or
+ use a user space program to fill defaults.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/isp/bluegamma_table.h | 1040 ++++++++++++++++++++++++++
+ drivers/media/video/isp/cfa_coef_table.h | 603 +++++++++++++++
+ drivers/media/video/isp/greengamma_table.h | 1040 ++++++++++++++++++++++++++
+ drivers/media/video/isp/luma_enhance_table.h | 144 ++++
+ drivers/media/video/isp/noise_filter_table.h | 79 ++
+ drivers/media/video/isp/redgamma_table.h | 1040 ++++++++++++++++++++++++++
+ 6 files changed, 3946 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/bluegamma_table.h
+ create mode 100644 drivers/media/video/isp/cfa_coef_table.h
+ create mode 100644 drivers/media/video/isp/greengamma_table.h
+ create mode 100644 drivers/media/video/isp/luma_enhance_table.h
+ create mode 100644 drivers/media/video/isp/noise_filter_table.h
+ create mode 100644 drivers/media/video/isp/redgamma_table.h
+
+diff --git a/drivers/media/video/isp/bluegamma_table.h b/drivers/media/video/isp/bluegamma_table.h
+new file mode 100644
+index 0000000..301382a
+--- /dev/null
++++ b/drivers/media/video/isp/bluegamma_table.h
+@@ -0,0 +1,1040 @@
++/*
++ * bluegamma_table.h
++ *
++ * Gamma Table values for BLUE for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++0,
++0,
++1,
++2,
++3,
++3,
++4,
++5,
++6,
++8,
++10,
++12,
++14,
++16,
++18,
++20,
++22,
++23,
++25,
++26,
++28,
++29,
++31,
++32,
++34,
++35,
++36,
++37,
++39,
++40,
++41,
++42,
++43,
++44,
++45,
++46,
++47,
++48,
++49,
++50,
++51,
++52,
++52,
++53,
++54,
++55,
++56,
++57,
++58,
++59,
++60,
++61,
++62,
++63,
++63,
++64,
++65,
++66,
++66,
++67,
++68,
++69,
++69,
++70,
++71,
++72,
++72,
++73,
++74,
++75,
++75,
++76,
++77,
++78,
++78,
++79,
++80,
++81,
++81,
++82,
++83,
++84,
++84,
++85,
++86,
++87,
++88,
++88,
++89,
++90,
++91,
++91,
++92,
++93,
++94,
++94,
++95,
++96,
++97,
++97,
++98,
++98,
++99,
++99,
++100,
++100,
++101,
++101,
++102,
++103,
++104,
++104,
++105,
++106,
++107,
++108,
++108,
++109,
++110,
++111,
++111,
++112,
++113,
++114,
++114,
++115,
++116,
++117,
++117,
++118,
++119,
++119,
++120,
++120,
++121,
++121,
++122,
++122,
++123,
++123,
++124,
++124,
++125,
++125,
++126,
++126,
++127,
++127,
++128,
++128,
++129,
++129,
++130,
++130,
++131,
++131,
++132,
++132,
++133,
++133,
++134,
++134,
++135,
++135,
++136,
++136,
++137,
++137,
++138,
++138,
++139,
++139,
++140,
++140,
++141,
++141,
++142,
++142,
++143,
++143,
++144,
++144,
++145,
++145,
++146,
++146,
++147,
++147,
++148,
++148,
++149,
++149,
++150,
++150,
++151,
++151,
++152,
++152,
++153,
++153,
++153,
++153,
++154,
++154,
++154,
++154,
++155,
++155,
++156,
++156,
++157,
++157,
++158,
++158,
++158,
++159,
++159,
++159,
++160,
++160,
++160,
++161,
++161,
++162,
++162,
++163,
++163,
++164,
++164,
++164,
++164,
++165,
++165,
++165,
++165,
++166,
++166,
++167,
++167,
++168,
++168,
++169,
++169,
++170,
++170,
++170,
++170,
++171,
++171,
++171,
++171,
++172,
++172,
++173,
++173,
++174,
++174,
++175,
++175,
++176,
++176,
++176,
++176,
++177,
++177,
++177,
++177,
++178,
++178,
++178,
++178,
++179,
++179,
++179,
++179,
++180,
++180,
++180,
++180,
++181,
++181,
++181,
++181,
++182,
++182,
++182,
++182,
++183,
++183,
++183,
++183,
++184,
++184,
++184,
++184,
++185,
++185,
++185,
++185,
++186,
++186,
++186,
++186,
++187,
++187,
++187,
++187,
++188,
++188,
++188,
++188,
++189,
++189,
++189,
++189,
++190,
++190,
++190,
++190,
++191,
++191,
++191,
++191,
++192,
++192,
++192,
++192,
++193,
++193,
++193,
++193,
++194,
++194,
++194,
++194,
++195,
++195,
++195,
++195,
++196,
++196,
++196,
++196,
++197,
++197,
++197,
++197,
++198,
++198,
++198,
++198,
++199,
++199,
++199,
++199,
++200,
++200,
++200,
++200,
++201,
++201,
++201,
++201,
++202,
++202,
++202,
++203,
++203,
++203,
++203,
++204,
++204,
++204,
++204,
++205,
++205,
++205,
++205,
++206,
++206,
++206,
++206,
++207,
++207,
++207,
++207,
++208,
++208,
++208,
++208,
++209,
++209,
++209,
++209,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++212,
++212,
++212,
++212,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++214,
++214,
++214,
++214,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++216,
++216,
++216,
++216,
++217,
++217,
++217,
++217,
++218,
++218,
++218,
++218,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++220,
++220,
++220,
++220,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++222,
++222,
++222,
++222,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++224,
++224,
++224,
++224,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++226,
++226,
++226,
++226,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++228,
++228,
++228,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++230,
++230,
++230,
++230,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++233,
++233,
++233,
++233,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++235,
++235,
++235,
++235,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++237,
++237,
++237,
++237,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++239,
++239,
++239,
++239,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++241,
++241,
++241,
++241,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++243,
++243,
++243,
++243,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++245,
++245,
++245,
++245,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++247,
++247,
++247,
++247,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++249,
++249,
++249,
++249,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++251,
++251,
++251,
++251,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++254,
++254,
++254,
++254,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255
+diff --git a/drivers/media/video/isp/cfa_coef_table.h b/drivers/media/video/isp/cfa_coef_table.h
+new file mode 100644
+index 0000000..8cafa1f
+--- /dev/null
++++ b/drivers/media/video/isp/cfa_coef_table.h
+@@ -0,0 +1,603 @@
++/*
++ * cfa_coef_table.h
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ *
++ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ *
++ * Written by Gjorgji Rosikopulos
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248,
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248,
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++4,
++250,
++12,
++244,
++250,
++0,
++27,
++0,
++12,
++27,
++36,
++247,
++244,
++0,
++247,
++0,
++0,
++0,
++0,
++248,
++0,
++0,
++40,
++0,
++0,
++247,
++0,
++244,
++247,
++36,
++27,
++12,
++0,
++27,
++0,
++250,
++244,
++12,
++250,
++4,
++0,
++40,
++0,
++0,
++248,
++0,
++0,
++0,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248,
++244,
++12,
++250,
++4,
++0,
++27,
++0,
++250,
++247,
++36,
++27,
++12,
++0,
++247,
++0,
++244,
++248,
++0,
++0,
++0,
++0,
++40,
++0,
++0,
++244,
++0,
++247,
++0,
++12,
++27,
++36,
++247,
++250,
++0,
++27,
++0,
++4,
++250,
++12,
++244,
++0,
++0,
++40,
++0,
++0,
++0,
++0,
++248
++
+diff --git a/drivers/media/video/isp/greengamma_table.h b/drivers/media/video/isp/greengamma_table.h
+new file mode 100644
+index 0000000..0f5c5e4
+--- /dev/null
++++ b/drivers/media/video/isp/greengamma_table.h
+@@ -0,0 +1,1040 @@
++/*
++ * greengamma_table.h
++ *
++ * Gamma Table values for GREEN for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++0,
++0,
++1,
++2,
++3,
++3,
++4,
++5,
++6,
++8,
++10,
++12,
++14,
++16,
++18,
++20,
++22,
++23,
++25,
++26,
++28,
++29,
++31,
++32,
++34,
++35,
++36,
++37,
++39,
++40,
++41,
++42,
++43,
++44,
++45,
++46,
++47,
++48,
++49,
++50,
++51,
++52,
++52,
++53,
++54,
++55,
++56,
++57,
++58,
++59,
++60,
++61,
++62,
++63,
++63,
++64,
++65,
++66,
++66,
++67,
++68,
++69,
++69,
++70,
++71,
++72,
++72,
++73,
++74,
++75,
++75,
++76,
++77,
++78,
++78,
++79,
++80,
++81,
++81,
++82,
++83,
++84,
++84,
++85,
++86,
++87,
++88,
++88,
++89,
++90,
++91,
++91,
++92,
++93,
++94,
++94,
++95,
++96,
++97,
++97,
++98,
++98,
++99,
++99,
++100,
++100,
++101,
++101,
++102,
++103,
++104,
++104,
++105,
++106,
++107,
++108,
++108,
++109,
++110,
++111,
++111,
++112,
++113,
++114,
++114,
++115,
++116,
++117,
++117,
++118,
++119,
++119,
++120,
++120,
++121,
++121,
++122,
++122,
++123,
++123,
++124,
++124,
++125,
++125,
++126,
++126,
++127,
++127,
++128,
++128,
++129,
++129,
++130,
++130,
++131,
++131,
++132,
++132,
++133,
++133,
++134,
++134,
++135,
++135,
++136,
++136,
++137,
++137,
++138,
++138,
++139,
++139,
++140,
++140,
++141,
++141,
++142,
++142,
++143,
++143,
++144,
++144,
++145,
++145,
++146,
++146,
++147,
++147,
++148,
++148,
++149,
++149,
++150,
++150,
++151,
++151,
++152,
++152,
++153,
++153,
++153,
++153,
++154,
++154,
++154,
++154,
++155,
++155,
++156,
++156,
++157,
++157,
++158,
++158,
++158,
++159,
++159,
++159,
++160,
++160,
++160,
++161,
++161,
++162,
++162,
++163,
++163,
++164,
++164,
++164,
++164,
++165,
++165,
++165,
++165,
++166,
++166,
++167,
++167,
++168,
++168,
++169,
++169,
++170,
++170,
++170,
++170,
++171,
++171,
++171,
++171,
++172,
++172,
++173,
++173,
++174,
++174,
++175,
++175,
++176,
++176,
++176,
++176,
++177,
++177,
++177,
++177,
++178,
++178,
++178,
++178,
++179,
++179,
++179,
++179,
++180,
++180,
++180,
++180,
++181,
++181,
++181,
++181,
++182,
++182,
++182,
++182,
++183,
++183,
++183,
++183,
++184,
++184,
++184,
++184,
++185,
++185,
++185,
++185,
++186,
++186,
++186,
++186,
++187,
++187,
++187,
++187,
++188,
++188,
++188,
++188,
++189,
++189,
++189,
++189,
++190,
++190,
++190,
++190,
++191,
++191,
++191,
++191,
++192,
++192,
++192,
++192,
++193,
++193,
++193,
++193,
++194,
++194,
++194,
++194,
++195,
++195,
++195,
++195,
++196,
++196,
++196,
++196,
++197,
++197,
++197,
++197,
++198,
++198,
++198,
++198,
++199,
++199,
++199,
++199,
++200,
++200,
++200,
++200,
++201,
++201,
++201,
++201,
++202,
++202,
++202,
++203,
++203,
++203,
++203,
++204,
++204,
++204,
++204,
++205,
++205,
++205,
++205,
++206,
++206,
++206,
++206,
++207,
++207,
++207,
++207,
++208,
++208,
++208,
++208,
++209,
++209,
++209,
++209,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++212,
++212,
++212,
++212,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++214,
++214,
++214,
++214,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++216,
++216,
++216,
++216,
++217,
++217,
++217,
++217,
++218,
++218,
++218,
++218,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++220,
++220,
++220,
++220,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++222,
++222,
++222,
++222,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++224,
++224,
++224,
++224,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++226,
++226,
++226,
++226,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++228,
++228,
++228,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++230,
++230,
++230,
++230,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++233,
++233,
++233,
++233,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++235,
++235,
++235,
++235,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++237,
++237,
++237,
++237,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++239,
++239,
++239,
++239,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++241,
++241,
++241,
++241,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++243,
++243,
++243,
++243,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++245,
++245,
++245,
++245,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++247,
++247,
++247,
++247,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++249,
++249,
++249,
++249,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++251,
++251,
++251,
++251,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++254,
++254,
++254,
++254,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255
+diff --git a/drivers/media/video/isp/luma_enhance_table.h b/drivers/media/video/isp/luma_enhance_table.h
+new file mode 100644
+index 0000000..99c8b05
+--- /dev/null
++++ b/drivers/media/video/isp/luma_enhance_table.h
+@@ -0,0 +1,144 @@
++/*
++ * luma_enhance_table.h
++ *
++ * Luminance Enhancement table values for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1047552,
++1048575,
++1047551,
++1046527,
++1045503,
++1044479,
++1043455,
++1042431,
++1041407,
++1040383,
++1039359,
++1038335,
++1037311,
++1036287,
++1035263,
++1034239,
++1033215,
++1032191,
++1031167,
++1030143,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028096,
++1028100,
++1032196,
++1036292,
++1040388,
++1044484,
++0,
++0,
++0,
++5,
++5125,
++10245,
++15365,
++20485,
++25605,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++30720,
++31743,
++30719,
++29695,
++28671,
++27647,
++26623,
++25599,
++24575,
++23551,
++22527,
++21503,
++20479,
++19455,
++18431,
++17407,
++16383,
++15359,
++14335,
++13311,
++12287,
++11263,
++10239,
++9215,
++8191,
++7167,
++6143,
++5119,
++4095,
++3071,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024,
++1024
+diff --git a/drivers/media/video/isp/noise_filter_table.h b/drivers/media/video/isp/noise_filter_table.h
+new file mode 100644
+index 0000000..7345f90
+--- /dev/null
++++ b/drivers/media/video/isp/noise_filter_table.h
+@@ -0,0 +1,79 @@
++/*
++ * noise_filter_table.h
++ *
++ * Noise Filter Table values for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++16,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31,
++31
+diff --git a/drivers/media/video/isp/redgamma_table.h b/drivers/media/video/isp/redgamma_table.h
+new file mode 100644
+index 0000000..ad0232a
+--- /dev/null
++++ b/drivers/media/video/isp/redgamma_table.h
+@@ -0,0 +1,1040 @@
++/*
++ * redgamma_table.h
++ *
++ * Gamma Table values for RED for TI's OMAP3 Camera ISP
++ *
++ * Copyright (C) 2009 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++0,
++0,
++1,
++2,
++3,
++3,
++4,
++5,
++6,
++8,
++10,
++12,
++14,
++16,
++18,
++20,
++22,
++23,
++25,
++26,
++28,
++29,
++31,
++32,
++34,
++35,
++36,
++37,
++39,
++40,
++41,
++42,
++43,
++44,
++45,
++46,
++47,
++48,
++49,
++50,
++51,
++52,
++52,
++53,
++54,
++55,
++56,
++57,
++58,
++59,
++60,
++61,
++62,
++63,
++63,
++64,
++65,
++66,
++66,
++67,
++68,
++69,
++69,
++70,
++71,
++72,
++72,
++73,
++74,
++75,
++75,
++76,
++77,
++78,
++78,
++79,
++80,
++81,
++81,
++82,
++83,
++84,
++84,
++85,
++86,
++87,
++88,
++88,
++89,
++90,
++91,
++91,
++92,
++93,
++94,
++94,
++95,
++96,
++97,
++97,
++98,
++98,
++99,
++99,
++100,
++100,
++101,
++101,
++102,
++103,
++104,
++104,
++105,
++106,
++107,
++108,
++108,
++109,
++110,
++111,
++111,
++112,
++113,
++114,
++114,
++115,
++116,
++117,
++117,
++118,
++119,
++119,
++120,
++120,
++121,
++121,
++122,
++122,
++123,
++123,
++124,
++124,
++125,
++125,
++126,
++126,
++127,
++127,
++128,
++128,
++129,
++129,
++130,
++130,
++131,
++131,
++132,
++132,
++133,
++133,
++134,
++134,
++135,
++135,
++136,
++136,
++137,
++137,
++138,
++138,
++139,
++139,
++140,
++140,
++141,
++141,
++142,
++142,
++143,
++143,
++144,
++144,
++145,
++145,
++146,
++146,
++147,
++147,
++148,
++148,
++149,
++149,
++150,
++150,
++151,
++151,
++152,
++152,
++153,
++153,
++153,
++153,
++154,
++154,
++154,
++154,
++155,
++155,
++156,
++156,
++157,
++157,
++158,
++158,
++158,
++159,
++159,
++159,
++160,
++160,
++160,
++161,
++161,
++162,
++162,
++163,
++163,
++164,
++164,
++164,
++164,
++165,
++165,
++165,
++165,
++166,
++166,
++167,
++167,
++168,
++168,
++169,
++169,
++170,
++170,
++170,
++170,
++171,
++171,
++171,
++171,
++172,
++172,
++173,
++173,
++174,
++174,
++175,
++175,
++176,
++176,
++176,
++176,
++177,
++177,
++177,
++177,
++178,
++178,
++178,
++178,
++179,
++179,
++179,
++179,
++180,
++180,
++180,
++180,
++181,
++181,
++181,
++181,
++182,
++182,
++182,
++182,
++183,
++183,
++183,
++183,
++184,
++184,
++184,
++184,
++185,
++185,
++185,
++185,
++186,
++186,
++186,
++186,
++187,
++187,
++187,
++187,
++188,
++188,
++188,
++188,
++189,
++189,
++189,
++189,
++190,
++190,
++190,
++190,
++191,
++191,
++191,
++191,
++192,
++192,
++192,
++192,
++193,
++193,
++193,
++193,
++194,
++194,
++194,
++194,
++195,
++195,
++195,
++195,
++196,
++196,
++196,
++196,
++197,
++197,
++197,
++197,
++198,
++198,
++198,
++198,
++199,
++199,
++199,
++199,
++200,
++200,
++200,
++200,
++201,
++201,
++201,
++201,
++202,
++202,
++202,
++203,
++203,
++203,
++203,
++204,
++204,
++204,
++204,
++205,
++205,
++205,
++205,
++206,
++206,
++206,
++206,
++207,
++207,
++207,
++207,
++208,
++208,
++208,
++208,
++209,
++209,
++209,
++209,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++210,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++211,
++212,
++212,
++212,
++212,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++213,
++214,
++214,
++214,
++214,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++215,
++216,
++216,
++216,
++216,
++217,
++217,
++217,
++217,
++218,
++218,
++218,
++218,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++219,
++220,
++220,
++220,
++220,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++221,
++222,
++222,
++222,
++222,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++223,
++224,
++224,
++224,
++224,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++225,
++226,
++226,
++226,
++226,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++227,
++228,
++228,
++228,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++229,
++230,
++230,
++230,
++230,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++231,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++232,
++233,
++233,
++233,
++233,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++234,
++235,
++235,
++235,
++235,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++236,
++237,
++237,
++237,
++237,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++238,
++239,
++239,
++239,
++239,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++240,
++241,
++241,
++241,
++241,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++242,
++243,
++243,
++243,
++243,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++244,
++245,
++245,
++245,
++245,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++246,
++247,
++247,
++247,
++247,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++248,
++249,
++249,
++249,
++249,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++250,
++251,
++251,
++251,
++251,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++252,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++253,
++254,
++254,
++254,
++254,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255,
++255
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
new file mode 100644
index 0000000000..22074be148
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
@@ -0,0 +1,2249 @@
+From 0edf5a50dc0164db5bc71b1a5d1aa8bb1838262c Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Tue, 10 Mar 2009 10:49:03 +0200
+Subject: [PATCH] omap34xxcam: Add camera driver
+
+This is the camera driver for the OMAP 3 camera ISP and v4l2-int-device
+sensors, lenses and (led) flashes. There are a few connections to OMAP
+3 left but after those have been broken this is hardware independent.
+Namely, the OMAP 3 ISP must offer a standard interface through
+v4l2_subdev (or v4l2-int-device) first.
+
+This driver has originated from the omap24xxcam camera driver written
+specifically for OMAP 2.
+
+TODO:
+
+- Convert to use v4l2_subdev instead of v4l2-int-device.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ drivers/media/video/Kconfig | 9 +
+ drivers/media/video/Makefile | 2 +
+ drivers/media/video/omap34xxcam.c | 1966 +++++++++++++++++++++++++++++++++++++
+ drivers/media/video/omap34xxcam.h | 207 ++++
+ 4 files changed, 2184 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/omap34xxcam.c
+ create mode 100644 drivers/media/video/omap34xxcam.h
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 19cf3b8..3cdb5a4 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -711,6 +711,15 @@ config VIDEO_CAFE_CCIC
+ CMOS camera controller. This is the controller found on first-
+ generation OLPC systems.
+
++config VIDEO_OMAP3
++ tristate "OMAP 3 Camera support"
++ select VIDEOBUF_GEN
++ select VIDEOBUF_DMA_SG
++ select OMAP_IOMMU
++ depends on VIDEO_V4L2 && ARCH_OMAP34XX
++ ---help---
++ Driver for an OMAP 3 camera controller.
++
+ config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index e654270..74a684e 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -108,6 +108,8 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+
+ obj-y += isp/
+
++obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o
++
+ obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+
+ obj-$(CONFIG_USB_DABUSB) += dabusb.o
+diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
+new file mode 100644
+index 0000000..00fdbf2
+--- /dev/null
++++ b/drivers/media/video/omap34xxcam.c
+@@ -0,0 +1,1966 @@
++/*
++ * omap34xxcam.c
++ *
++ * Copyright (C) 2006--2009 Nokia Corporation
++ * Copyright (C) 2007--2009 Texas Instruments
++ *
++ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ *
++ * Originally based on the OMAP 2 camera driver.
++ *
++ * Written by Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Mohit Jalori
++ * Sameer Venkatraman
++ * Leonides Martinez
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/pci.h> /* needed for videobufs */
++#include <linux/delay.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/videodev2.h>
++#include <linux/version.h>
++#include <linux/platform_device.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-ioctl.h>
++
++#include "omap34xxcam.h"
++#include "isp/isp.h"
++#include "isp/ispmmu.h"
++#include "isp/ispreg.h"
++#include "isp/ispccdc.h"
++#include "isp/isph3a.h"
++#include "isp/isp_af.h"
++#include "isp/isphist.h"
++#include "isp/isppreview.h"
++#include "isp/ispresizer.h"
++
++#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
++
++/* global variables */
++static struct omap34xxcam_device *omap34xxcam;
++
++/*
++ *
++ * Sensor handling.
++ *
++ */
++
++/**
++ * omap34xxcam_slave_power_set - set slave power state
++ * @vdev: per-video device data structure
++ * @power: new power state
++ */
++static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
++ enum v4l2_power power,
++ int mask)
++{
++ int rval = 0, i = 0;
++
++ BUG_ON(!mutex_is_locked(&vdev->mutex));
++
++#ifdef OMAP34XXCAM_POWEROFF_DELAY
++ vdev->power_state_wish = -1;
++#endif
++
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ if (vdev->slave[i] == v4l2_int_device_dummy())
++ continue;
++
++ if (!(mask & (1 << i))
++ || power == vdev->power_state[i])
++ continue;
++
++ rval = vidioc_int_s_power(vdev->slave[i], power);
++
++ if (rval && power != V4L2_POWER_OFF) {
++ power = V4L2_POWER_OFF;
++ goto out;
++ }
++
++ vdev->power_state[i] = power;
++ }
++
++ return 0;
++
++out:
++ for (i--; i >= 0; i--) {
++ if (vdev->slave[i] == v4l2_int_device_dummy())
++ continue;
++
++ if (!(mask & (1 << i)))
++ continue;
++
++ vidioc_int_s_power(vdev->slave[i], power);
++ vdev->power_state[i] = power;
++ }
++
++ return rval;
++}
++
++#ifdef OMAP34XXCAM_POWEROFF_DELAY
++static void omap34xxcam_slave_power_work(struct work_struct *work)
++{
++ struct omap34xxcam_videodev *vdev =
++ container_of(work, struct omap34xxcam_videodev, poweroff_work);
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->power_state_wish != -1)
++ omap34xxcam_slave_power_set(vdev, vdev->power_state_wish,
++ vdev->power_state_mask);
++
++ mutex_unlock(&vdev->mutex);
++}
++
++static void omap34xxcam_slave_power_timer(unsigned long ptr)
++{
++ struct omap34xxcam_videodev *vdev = (void *)ptr;
++
++ schedule_work(&vdev->poweroff_work);
++}
++
++/**
++ * omap34xxcam_slave_power_suggest - delayed power state change
++ *
++ * @vdev: per-video device data structure
++ * @power: new power state
++ */
++static void omap34xxcam_slave_power_suggest(struct omap34xxcam_videodev *vdev,
++ enum v4l2_power power,
++ int mask)
++{
++ BUG_ON(!mutex_is_locked(&vdev->mutex));
++
++ del_timer(&vdev->poweroff_timer);
++
++ vdev->power_state_wish = power;
++ vdev->power_state_mask = mask;
++
++ mod_timer(&vdev->poweroff_timer, jiffies + OMAP34XXCAM_POWEROFF_DELAY);
++}
++#else /* OMAP34XXCAM_POWEROFF_DELAY */
++#define omap34xxcam_slave_power_suggest(a, b, c) do {} while (0)
++#endif /* OMAP34XXCAM_POWEROFF_DELAY */
++
++/**
++ * omap34xxcam_update_vbq - Updates VBQ with completed input buffer
++ * @vb: ptr. to standard V4L2 video buffer structure
++ *
++ * Updates video buffer queue with completed buffer passed as
++ * input parameter. Also updates ISP H3A timestamp and field count
++ * statistics.
++ */
++void omap34xxcam_vbq_complete(struct videobuf_buffer *vb, void *priv)
++{
++ struct omap34xxcam_fh *fh = priv;
++
++ do_gettimeofday(&vb->ts);
++ vb->field_count = atomic_add_return(2, &fh->field_count);
++
++ wake_up(&vb->done);
++}
++
++/**
++ * omap34xxcam_vbq_setup - Calcs size and num of buffs allowed in queue
++ * @vbq: ptr. to standard V4L2 video buffer queue structure
++ * @cnt: ptr to location to hold the count of buffers to be in the queue
++ * @size: ptr to location to hold the size of a frame
++ *
++ * Calculates the number of buffers of current image size that can be
++ * supported by the available capture memory.
++ */
++static int omap34xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
++ unsigned int *size)
++{
++ struct omap34xxcam_fh *fh = vbq->priv_data;
++ struct omap34xxcam_videodev *vdev = fh->vdev;
++
++ if (*cnt <= 0)
++ *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */
++
++ if (*cnt > VIDEO_MAX_FRAME)
++ *cnt = VIDEO_MAX_FRAME;
++
++ *size = vdev->pix.sizeimage;
++
++ while (*size * *cnt > fh->vdev->vdev_sensor_config.capture_mem)
++ (*cnt)--;
++
++ return isp_vbq_setup(vbq, cnt, size);
++}
++
++/**
++ * omap34xxcam_vbq_release - Free resources for input VBQ and VB
++ * @vbq: ptr. to standard V4L2 video buffer queue structure
++ * @vb: ptr to standard V4L2 video buffer structure
++ *
++ * Unmap and free all memory associated with input VBQ and VB, also
++ * unmap the address in ISP MMU. Reset the VB state.
++ */
++static void omap34xxcam_vbq_release(struct videobuf_queue *vbq,
++ struct videobuf_buffer *vb)
++{
++ if (!vbq->streaming) {
++ isp_vbq_release(vbq, vb);
++ videobuf_dma_unmap(vbq, videobuf_to_dma(vb));
++ videobuf_dma_free(videobuf_to_dma(vb));
++ vb->state = VIDEOBUF_NEEDS_INIT;
++ }
++ return;
++}
++
++/**
++ * omap34xxcam_vbq_prepare - V4L2 video ops buf_prepare handler
++ * @vbq: ptr. to standard V4L2 video buffer queue structure
++ * @vb: ptr to standard V4L2 video buffer structure
++ * @field: standard V4L2 field enum
++ *
++ * Verifies there is sufficient locked memory for the requested
++ * buffer, or if there is not, allocates, locks and initializes
++ * it.
++ */
++static int omap34xxcam_vbq_prepare(struct videobuf_queue *vbq,
++ struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ struct omap34xxcam_fh *fh = vbq->priv_data;
++ struct omap34xxcam_videodev *vdev = fh->vdev;
++ int err = 0;
++
++ /*
++ * Accessing pix here is okay since it's constant while
++ * streaming is on (and we only get called then).
++ */
++ if (vb->baddr) {
++ /* This is a userspace buffer. */
++ if (vdev->pix.sizeimage > vb->bsize)
++ /* The buffer isn't big enough. */
++ return -EINVAL;
++ } else {
++ if (vb->state != VIDEOBUF_NEEDS_INIT
++ && vdev->pix.sizeimage > vb->bsize)
++ /*
++ * We have a kernel bounce buffer that has
++ * already been allocated.
++ */
++ omap34xxcam_vbq_release(vbq, vb);
++ }
++
++ vb->size = vdev->pix.bytesperline * vdev->pix.height;
++ vb->width = vdev->pix.width;
++ vb->height = vdev->pix.height;
++ vb->field = field;
++
++ if (vb->state == VIDEOBUF_NEEDS_INIT) {
++ err = videobuf_iolock(vbq, vb, NULL);
++ if (!err) {
++ /* isp_addr will be stored locally inside isp code */
++ err = isp_vbq_prepare(vbq, vb, field);
++ }
++ }
++
++ if (!err)
++ vb->state = VIDEOBUF_PREPARED;
++ else
++ omap34xxcam_vbq_release(vbq, vb);
++
++ return err;
++}
++
++/**
++ * omap34xxcam_vbq_queue - V4L2 video ops buf_queue handler
++ * @vbq: ptr. to standard V4L2 video buffer queue structure
++ * @vb: ptr to standard V4L2 video buffer structure
++ *
++ * Maps the video buffer to sgdma and through the isp, sets
++ * the isp buffer done callback and sets the video buffer state
++ * to active.
++ */
++static void omap34xxcam_vbq_queue(struct videobuf_queue *vbq,
++ struct videobuf_buffer *vb)
++{
++ struct omap34xxcam_fh *fh = vbq->priv_data;
++
++ vb->state = VIDEOBUF_ACTIVE;
++
++ isp_buf_queue(vb, omap34xxcam_vbq_complete, (void *)fh);
++}
++
++static struct videobuf_queue_ops omap34xxcam_vbq_ops = {
++ .buf_setup = omap34xxcam_vbq_setup,
++ .buf_prepare = omap34xxcam_vbq_prepare,
++ .buf_queue = omap34xxcam_vbq_queue,
++ .buf_release = omap34xxcam_vbq_release,
++};
++
++/*
++ *
++ * IOCTL interface.
++ *
++ */
++
++/**
++ * vidioc_querycap - V4L2 query capabilities IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @cap: ptr to standard V4L2 capability structure
++ *
++ * Fill in the V4L2 capabliity structure for the camera device
++ */
++static int vidioc_querycap(struct file *file, void *fh,
++ struct v4l2_capability *cap)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++
++ strlcpy(cap->driver, CAM_SHORT_NAME, sizeof(cap->driver));
++ strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
++ cap->version = OMAP34XXCAM_VERSION;
++ if (vdev->vdev_sensor != v4l2_int_device_dummy())
++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
++
++ return 0;
++}
++
++/**
++ * vidioc_enum_fmt_vid_cap - V4L2 enumerate format capabilities IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @f: ptr to standard V4L2 format description structure
++ *
++ * Fills in enumerate format capabilities information for sensor (if SOC
++ * sensor attached) or ISP (if raw sensor attached).
++ */
++static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
++ struct v4l2_fmtdesc *f)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ if (vdev->vdev_sensor_config.sensor_isp)
++ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, f);
++ else
++ rval = isp_enum_fmt_cap(f);
++
++ return rval;
++}
++
++/**
++ * vidioc_g_fmt_vid_cap - V4L2 get format capabilities IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @f: ptr to standard V4L2 format structure
++ *
++ * Fills in format capabilities for sensor (if SOC sensor attached) or ISP
++ * (if raw sensor attached).
++ */
++static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ f->fmt.pix = vdev->pix;
++ mutex_unlock(&vdev->mutex);
++
++ return 0;
++}
++
++static int try_pix_parm(struct omap34xxcam_videodev *vdev,
++ struct v4l2_pix_format *best_pix_in,
++ struct v4l2_pix_format *wanted_pix_out,
++ struct v4l2_fract *best_ival)
++{
++ int fps;
++ int fmtd_index;
++ int rval;
++ struct v4l2_pix_format best_pix_out;
++
++ if (best_ival->numerator == 0
++ || best_ival->denominator == 0)
++ *best_ival = vdev->vdev_sensor_config.ival_default;
++
++ fps = best_ival->denominator / best_ival->numerator;
++
++ best_ival->denominator = 0;
++ best_pix_out.height = INT_MAX >> 1;
++ best_pix_out.width = best_pix_out.height;
++
++ for (fmtd_index = 0; ; fmtd_index++) {
++ int size_index;
++ struct v4l2_fmtdesc fmtd;
++
++ fmtd.index = fmtd_index;
++ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, &fmtd);
++ if (rval)
++ break;
++ dev_info(&vdev->vfd->dev, "trying fmt %8.8x (%d)\n",
++ fmtd.pixelformat, fmtd_index);
++ /*
++ * Get supported resolutions.
++ */
++ for (size_index = 0; ; size_index++) {
++ struct v4l2_frmsizeenum frms;
++ struct v4l2_pix_format pix_tmp_in, pix_tmp_out;
++ int ival_index;
++
++ frms.index = size_index;
++ frms.pixel_format = fmtd.pixelformat;
++
++ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor,
++ &frms);
++ if (rval)
++ break;
++
++ pix_tmp_in.pixelformat = frms.pixel_format;
++ pix_tmp_in.width = frms.discrete.width;
++ pix_tmp_in.height = frms.discrete.height;
++ pix_tmp_out = *wanted_pix_out;
++ /* Don't do upscaling. */
++ if (pix_tmp_out.width > pix_tmp_in.width)
++ pix_tmp_out.width = pix_tmp_in.width;
++ if (pix_tmp_out.height > pix_tmp_in.height)
++ pix_tmp_out.height = pix_tmp_in.height;
++ rval = isp_try_fmt_cap(&pix_tmp_in, &pix_tmp_out);
++ if (rval)
++ return rval;
++
++ dev_info(&vdev->vfd->dev, "this w %d\th %d\tfmt %8.8x\t"
++ "-> w %d\th %d\t fmt %8.8x"
++ "\twanted w %d\th %d\t fmt %8.8x\n",
++ pix_tmp_in.width, pix_tmp_in.height,
++ pix_tmp_in.pixelformat,
++ pix_tmp_out.width, pix_tmp_out.height,
++ pix_tmp_out.pixelformat,
++ wanted_pix_out->width, wanted_pix_out->height,
++ wanted_pix_out->pixelformat);
++
++#define IS_SMALLER_OR_EQUAL(pix1, pix2) \
++ ((pix1)->width + (pix1)->height \
++ < (pix2)->width + (pix2)->height)
++#define SIZE_DIFF(pix1, pix2) \
++ (abs((pix1)->width - (pix2)->width) \
++ + abs((pix1)->height - (pix2)->height))
++
++ /*
++ * Don't use modes that are farther from wanted size
++ * that what we already got.
++ */
++ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
++ > SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
++ dev_info(&vdev->vfd->dev, "size diff bigger: "
++ "w %d\th %d\tw %d\th %d\n",
++ pix_tmp_out.width, pix_tmp_out.height,
++ best_pix_out.width,
++ best_pix_out.height);
++ continue;
++ }
++
++ /*
++ * There's an input mode that can provide output
++ * closer to wanted.
++ */
++ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
++ < SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
++ /* Force renegotation of fps etc. */
++ best_ival->denominator = 0;
++ dev_info(&vdev->vfd->dev, "renegotiate: "
++ "w %d\th %d\tw %d\th %d\n",
++ pix_tmp_out.width, pix_tmp_out.height,
++ best_pix_out.width,
++ best_pix_out.height);
++ }
++
++ for (ival_index = 0; ; ival_index++) {
++ struct v4l2_frmivalenum frmi;
++
++ frmi.index = ival_index;
++ frmi.pixel_format = frms.pixel_format;
++ frmi.width = frms.discrete.width;
++ frmi.height = frms.discrete.height;
++ /* FIXME: try to fix standard... */
++ frmi.reserved[0] = 0xdeafbeef;
++
++ rval = vidioc_int_enum_frameintervals(
++ vdev->vdev_sensor, &frmi);
++ if (rval)
++ break;
++
++ dev_info(&vdev->vfd->dev, "fps %d\n",
++ frmi.discrete.denominator
++ / frmi.discrete.numerator);
++
++ if (best_ival->denominator == 0)
++ goto do_it_now;
++
++ /*
++ * We aim to use maximum resolution
++ * from the sensor, provided that the
++ * fps is at least as close as on the
++ * current mode.
++ */
++#define FPS_ABS_DIFF(fps, ival) abs(fps - (ival).denominator / (ival).numerator)
++
++ /* Select mode with closest fps. */
++ if (FPS_ABS_DIFF(fps, frmi.discrete)
++ < FPS_ABS_DIFF(fps, *best_ival)) {
++ dev_info(&vdev->vfd->dev, "closer fps: "
++ "fps %d\t fps %d\n",
++ FPS_ABS_DIFF(fps,
++ frmi.discrete),
++ FPS_ABS_DIFF(fps, *best_ival));
++ goto do_it_now;
++ }
++
++ /*
++ * Select bigger resolution if it's available
++ * at same fps.
++ */
++ if (frmi.width + frmi.height
++ > best_pix_in->width + best_pix_in->height
++ && FPS_ABS_DIFF(fps, frmi.discrete)
++ <= FPS_ABS_DIFF(fps, *best_ival)) {
++ dev_info(&vdev->vfd->dev, "bigger res, "
++ "same fps: "
++ "w %d\th %d\tw %d\th %d\n",
++ frmi.width, frmi.height,
++ best_pix_in->width,
++ best_pix_in->height);
++ goto do_it_now;
++ }
++
++ dev_info(&vdev->vfd->dev, "falling through\n");
++
++ continue;
++
++do_it_now:
++ *best_ival = frmi.discrete;
++ best_pix_out = pix_tmp_out;
++ best_pix_in->width = frmi.width;
++ best_pix_in->height = frmi.height;
++ best_pix_in->pixelformat = frmi.pixel_format;
++
++ dev_info(&vdev->vfd->dev,
++ "best_pix_in: w %d\th %d\tfmt %8.8x"
++ "\tival %d/%d\n",
++ best_pix_in->width,
++ best_pix_in->height,
++ best_pix_in->pixelformat,
++ best_ival->numerator,
++ best_ival->denominator);
++ }
++ }
++ }
++
++ if (best_ival->denominator == 0)
++ return -EINVAL;
++
++ *wanted_pix_out = best_pix_out;
++
++ dev_info(&vdev->vfd->dev, "w %d, h %d, fmt %8.8x -> w %d, h %d\n",
++ best_pix_in->width, best_pix_in->height,
++ best_pix_in->pixelformat,
++ best_pix_out.width, best_pix_out.height);
++
++ return isp_try_fmt_cap(best_pix_in, wanted_pix_out);
++}
++
++static int s_pix_parm(struct omap34xxcam_videodev *vdev,
++ struct v4l2_pix_format *best_pix,
++ struct v4l2_pix_format *pix,
++ struct v4l2_fract *best_ival)
++{
++ struct v4l2_streamparm a;
++ struct v4l2_format fmt;
++ int rval;
++
++ rval = try_pix_parm(vdev, best_pix, pix, best_ival);
++ if (rval)
++ return rval;
++
++ rval = isp_s_fmt_cap(best_pix, pix);
++ if (rval)
++ return rval;
++
++ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ fmt.fmt.pix = *best_pix;
++ rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &fmt);
++ if (rval)
++ return rval;
++
++ a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ a.parm.capture.timeperframe = *best_ival;
++ rval = vidioc_int_s_parm(vdev->vdev_sensor, &a);
++
++ return rval;
++}
++
++/**
++ * vidioc_s_fmt_vid_cap - V4L2 set format capabilities IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @f: ptr to standard V4L2 format structure
++ *
++ * Attempts to set input format with the sensor driver (first) and then the
++ * ISP. Returns the return code from vidioc_g_fmt_vid_cap().
++ */
++static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct v4l2_pix_format pix_tmp;
++ struct v4l2_fract timeperframe;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming) {
++ rval = -EBUSY;
++ goto out;
++ }
++
++ vdev->want_pix = f->fmt.pix;
++
++ timeperframe = vdev->want_timeperframe;
++
++ rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
++ if (!rval)
++ vdev->pix = f->fmt.pix;
++
++out:
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_try_fmt_vid_cap - V4L2 try format capabilities IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @f: ptr to standard V4L2 format structure
++ *
++ * Checks if the given format is supported by the sensor driver and
++ * by the ISP.
++ */
++static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct v4l2_pix_format pix_tmp;
++ struct v4l2_fract timeperframe;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++
++ timeperframe = vdev->want_timeperframe;
++
++ rval = try_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_reqbufs - V4L2 request buffers IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @b: ptr to standard V4L2 request buffers structure
++ *
++ * Attempts to get a buffer from the buffer queue associated with the
++ * fh through the video buffer library API.
++ */
++static int vidioc_reqbufs(struct file *file, void *fh,
++ struct v4l2_requestbuffers *b)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming) {
++ mutex_unlock(&vdev->mutex);
++ return -EBUSY;
++ }
++
++ rval = videobuf_reqbufs(&ofh->vbq, b);
++
++ mutex_unlock(&vdev->mutex);
++
++ /*
++ * Either videobuf_reqbufs failed or the buffers are not
++ * memory-mapped (which would need special attention).
++ */
++ if (rval < 0 || b->memory != V4L2_MEMORY_MMAP)
++ goto out;
++
++out:
++ return rval;
++}
++
++/**
++ * vidioc_querybuf - V4L2 query buffer IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @b: ptr to standard V4L2 buffer structure
++ *
++ * Attempts to fill in the v4l2_buffer structure for the buffer queue
++ * associated with the fh through the video buffer library API.
++ */
++static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
++{
++ struct omap34xxcam_fh *ofh = fh;
++
++ return videobuf_querybuf(&ofh->vbq, b);
++}
++
++/**
++ * vidioc_qbuf - V4L2 queue buffer IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @b: ptr to standard V4L2 buffer structure
++ *
++ * Attempts to queue the v4l2_buffer on the buffer queue
++ * associated with the fh through the video buffer library API.
++ */
++static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
++{
++ struct omap34xxcam_fh *ofh = fh;
++
++ return videobuf_qbuf(&ofh->vbq, b);
++}
++
++/**
++ * vidioc_dqbuf - V4L2 dequeue buffer IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @b: ptr to standard V4L2 buffer structure
++ *
++ * Attempts to dequeue the v4l2_buffer from the buffer queue
++ * associated with the fh through the video buffer library API. If the
++ * buffer is a user space buffer, then this function will also requeue it,
++ * as user does not expect to do this.
++ */
++static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ int rval;
++
++videobuf_dqbuf_again:
++ rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
++
++ /*
++ * This is a hack. We don't want to show -EIO to the user
++ * space. Requeue the buffer and try again if we're not doing
++ * this in non-blocking mode.
++ */
++ if (rval == -EIO) {
++ videobuf_qbuf(&ofh->vbq, b);
++ if (!(file->f_flags & O_NONBLOCK))
++ goto videobuf_dqbuf_again;
++ /*
++ * We don't have a videobuf_buffer now --- maybe next
++ * time...
++ */
++ rval = -EAGAIN;
++ }
++
++ return rval;
++}
++
++/**
++ * vidioc_streamon - V4L2 streamon IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @i: V4L2 buffer type
++ *
++ * Attempts to start streaming by enabling the sensor interface and turning
++ * on video buffer streaming through the video buffer library API. Upon
++ * success the function returns 0, otherwise an error code is returned.
++ */
++static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming) {
++ rval = -EBUSY;
++ goto out;
++ }
++
++ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
++ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
++ if (rval) {
++ dev_dbg(&vdev->vfd->dev,
++ "omap34xxcam_slave_power_set failed\n");
++ goto out;
++ }
++
++ rval = videobuf_streamon(&ofh->vbq);
++ if (rval)
++ omap34xxcam_slave_power_set(
++ vdev, V4L2_POWER_OFF,
++ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
++ else
++ vdev->streaming = file;
++
++out:
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_streamoff - V4L2 streamoff IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @i: V4L2 buffer type
++ *
++ * Attempts to stop streaming by flushing all scheduled work, waiting on
++ * any queued buffers to complete and then stopping the ISP and turning
++ * off video buffer streaming through the video buffer library API. Upon
++ * success the function returns 0, otherwise an error code is returned.
++ */
++static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct videobuf_queue *q = &ofh->vbq;
++ int rval;
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->streaming == file)
++ isp_stop();
++
++ rval = videobuf_streamoff(q);
++ if (!rval) {
++ vdev->streaming = NULL;
++
++ omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_SENSOR);
++ omap34xxcam_slave_power_suggest(vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_LENS);
++ }
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_enum_input - V4L2 enumerate input IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @inp: V4L2 input type information structure
++ *
++ * Fills in v4l2_input structure. Returns 0.
++ */
++static int vidioc_enum_input(struct file *file, void *fh,
++ struct v4l2_input *inp)
++{
++ if (inp->index > 0)
++ return -EINVAL;
++
++ strlcpy(inp->name, "camera", sizeof(inp->name));
++ inp->type = V4L2_INPUT_TYPE_CAMERA;
++
++ return 0;
++}
++
++/**
++ * vidioc_g_input - V4L2 get input IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @i: address to hold index of input supported
++ *
++ * Sets index to 0.
++ */
++static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
++{
++ *i = 0;
++
++ return 0;
++}
++
++/**
++ * vidioc_s_input - V4L2 set input IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @i: index of input selected
++ *
++ * 0 is only index supported.
++ */
++static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
++{
++ if (i > 0)
++ return -EINVAL;
++
++ return 0;
++}
++
++/**
++ * vidioc_queryctrl - V4L2 query control IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 query control ioctl structure
++ *
++ * If the requested control is supported, returns the control information
++ * in the v4l2_queryctrl structure. Otherwise, returns -EINVAL if the
++ * control is not supported. If the sensor being used is a "smart sensor",
++ * this request is passed to the sensor driver, otherwise the ISP is
++ * queried and if it does not support the requested control, the request
++ * is forwarded to the "raw" sensor driver to see if it supports it.
++ */
++static int vidioc_queryctrl(struct file *file, void *fh,
++ struct v4l2_queryctrl *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct v4l2_queryctrl a_tmp;
++ int best_slave = -1;
++ u32 best_ctrl = (u32)-1;
++ int i;
++
++ if (vdev->vdev_sensor_config.sensor_isp)
++ return vidioc_int_queryctrl(vdev->vdev_sensor, a);
++
++ /* No next flags: try slaves directly. */
++ if (!(a->id & V4L2_CTRL_FLAG_NEXT_CTRL)) {
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ if (!vidioc_int_queryctrl(vdev->slave[i], a))
++ return 0;
++ }
++ return isp_queryctrl(a);
++ }
++
++ /* Find slave with smallest next control id. */
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ a_tmp = *a;
++
++ if (vidioc_int_queryctrl(vdev->slave[i], &a_tmp))
++ continue;
++
++ if (a_tmp.id < best_ctrl) {
++ best_slave = i;
++ best_ctrl = a_tmp.id;
++ }
++ }
++
++ a_tmp = *a;
++ if (!isp_queryctrl(&a_tmp)) {
++ if (a_tmp.id < best_ctrl) {
++ *a = a_tmp;
++
++ return 0;
++ }
++ }
++
++ if (best_slave == -1)
++ return -EINVAL;
++
++ a->id = best_ctrl;
++ return vidioc_int_queryctrl(vdev->slave[best_slave], a);
++}
++
++/**
++ * vidioc_querymenu - V4L2 query menu IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 query menu ioctl structure
++ *
++ * If the requested control is supported, returns the menu information
++ * in the v4l2_querymenu structure. Otherwise, returns -EINVAL if the
++ * control is not supported or is not a menu. If the sensor being used
++ * is a "smart sensor", this request is passed to the sensor driver,
++ * otherwise the ISP is queried and if it does not support the requested
++ * menu control, the request is forwarded to the "raw" sensor driver to
++ * see if it supports it.
++ */
++static int vidioc_querymenu(struct file *file, void *fh,
++ struct v4l2_querymenu *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int i;
++
++ if (vdev->vdev_sensor_config.sensor_isp)
++ return vidioc_int_querymenu(vdev->vdev_sensor, a);
++
++ /* Try slaves directly. */
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ if (!vidioc_int_querymenu(vdev->slave[i], a))
++ return 0;
++ }
++ return isp_querymenu(a);
++}
++
++static int vidioc_g_ext_ctrls(struct file *file, void *fh,
++ struct v4l2_ext_controls *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int i, ctrl_idx, rval = 0;
++
++ mutex_lock(&vdev->mutex);
++
++ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
++ struct v4l2_control ctrl;
++
++ ctrl.id = a->controls[ctrl_idx].id;
++
++ if (vdev->vdev_sensor_config.sensor_isp) {
++ rval = vidioc_int_g_ctrl(vdev->vdev_sensor, &ctrl);
++ } else {
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ rval = vidioc_int_g_ctrl(vdev->slave[i], &ctrl);
++ if (!rval)
++ break;
++ }
++ }
++
++ if (rval)
++ rval = isp_g_ctrl(&ctrl);
++
++ if (rval) {
++ a->error_idx = ctrl_idx;
++ break;
++ }
++
++ a->controls[ctrl_idx].value = ctrl.value;
++ }
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++static int vidioc_s_ext_ctrls(struct file *file, void *fh,
++ struct v4l2_ext_controls *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int i, ctrl_idx, rval = 0;
++
++ mutex_lock(&vdev->mutex);
++
++ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
++ struct v4l2_control ctrl;
++
++ ctrl.id = a->controls[ctrl_idx].id;
++ ctrl.value = a->controls[ctrl_idx].value;
++
++ if (vdev->vdev_sensor_config.sensor_isp) {
++ rval = vidioc_int_s_ctrl(vdev->vdev_sensor, &ctrl);
++ } else {
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ rval = vidioc_int_s_ctrl(vdev->slave[i], &ctrl);
++ if (!rval)
++ break;
++ }
++ }
++
++ if (rval)
++ rval = isp_s_ctrl(&ctrl);
++
++ if (rval) {
++ a->error_idx = ctrl_idx;
++ break;
++ }
++
++ a->controls[ctrl_idx].value = ctrl.value;
++ }
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_g_parm - V4L2 get parameters IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 stream parameters structure
++ *
++ * If request is for video capture buffer type, handles request by
++ * forwarding to sensor driver.
++ */
++static int vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval;
++
++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ rval = vidioc_int_g_parm(vdev->vdev_sensor, a);
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_s_parm - V4L2 set parameters IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 stream parameters structure
++ *
++ * If request is for video capture buffer type, handles request by
++ * first getting current stream parameters from sensor, then forwarding
++ * request to set new parameters to sensor driver. It then attempts to
++ * enable the sensor interface with the new parameters. If this fails, it
++ * reverts back to the previous parameters.
++ */
++static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct v4l2_pix_format pix_tmp_sensor, pix_tmp;
++ int rval;
++
++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming) {
++ rval = -EBUSY;
++ goto out;
++ }
++
++ vdev->want_timeperframe = a->parm.capture.timeperframe;
++
++ pix_tmp = vdev->want_pix;
++
++ rval = s_pix_parm(vdev, &pix_tmp_sensor, &pix_tmp,
++ &a->parm.capture.timeperframe);
++
++out:
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_cropcap - V4L2 crop capture IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 crop capture structure
++ *
++ * If using a "smart" sensor, just forwards request to the sensor driver,
++ * otherwise fills in the v4l2_cropcap values locally.
++ */
++static int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ struct v4l2_cropcap *cropcap = a;
++ int rval;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++
++ rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
++
++ if (rval && !vdev->vdev_sensor_config.sensor_isp) {
++ struct v4l2_format f;
++
++ /* cropcap failed, try to do this via g_fmt_cap */
++ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &f);
++ if (!rval) {
++ cropcap->bounds.top = 0;
++ cropcap->bounds.left = 0;
++ cropcap->bounds.width = f.fmt.pix.width;
++ cropcap->bounds.height = f.fmt.pix.height;
++ cropcap->defrect = cropcap->bounds;
++ cropcap->pixelaspect.numerator = 1;
++ cropcap->pixelaspect.denominator = 1;
++ }
++ }
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_g_crop - V4L2 get capture crop IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 crop structure
++ *
++ * If using a "smart" sensor, just forwards request to the sensor driver,
++ * otherwise calls the isp functions to fill in current crop values.
++ */
++static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval = 0;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->vdev_sensor_config.sensor_isp)
++ rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
++ else
++ rval = isp_g_crop(a);
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++/**
++ * vidioc_s_crop - V4L2 set capture crop IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @a: standard V4L2 crop structure
++ *
++ * If using a "smart" sensor, just forwards request to the sensor driver,
++ * otherwise calls the isp functions to set the current crop values.
++ */
++static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval = 0;
++
++ if (vdev->vdev_sensor == v4l2_int_device_dummy())
++ return -EINVAL;
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->vdev_sensor_config.sensor_isp)
++ rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
++ else
++ rval = isp_s_crop(a, &vdev->pix);
++
++ mutex_unlock(&vdev->mutex);
++
++ return rval;
++}
++
++static int vidioc_enum_framesizes(struct file *file, void *fh,
++ struct v4l2_frmsizeenum *frms)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ u32 pixel_format;
++ int rval;
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->vdev_sensor_config.sensor_isp) {
++ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
++ } else {
++ pixel_format = frms->pixel_format;
++ frms->pixel_format = -1; /* ISP does format conversion */
++ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
++ frms->pixel_format = pixel_format;
++ }
++
++ mutex_unlock(&vdev->mutex);
++ return rval;
++}
++
++static int vidioc_enum_frameintervals(struct file *file, void *fh,
++ struct v4l2_frmivalenum *frmi)
++{
++ struct omap34xxcam_fh *ofh = fh;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ u32 pixel_format;
++ int rval;
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->vdev_sensor_config.sensor_isp) {
++ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
++ } else {
++ pixel_format = frmi->pixel_format;
++ frmi->pixel_format = -1; /* ISP does format conversion */
++ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
++ frmi->pixel_format = pixel_format;
++ }
++
++ mutex_unlock(&vdev->mutex);
++ return rval;
++}
++
++/**
++ * vidioc_default - private IOCTL handler
++ * @file: ptr. to system file structure
++ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
++ * @cmd: ioctl cmd value
++ * @arg: ioctl arg value
++ *
++ * If the sensor being used is a "smart sensor", this request is returned to
++ * caller with -EINVAL err code. Otherwise if the control id is the private
++ * VIDIOC_PRIVATE_ISP_AEWB_REQ to update the analog gain or exposure,
++ * then this request is forwared directly to the sensor to incorporate the
++ * feedback. The request is then passed on to the ISP private IOCTL handler,
++ * isp_handle_private()
++ */
++static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
++{
++ struct omap34xxcam_fh *ofh = file->private_data;
++ struct omap34xxcam_videodev *vdev = ofh->vdev;
++ int rval;
++
++ if (vdev->vdev_sensor_config.sensor_isp) {
++ rval = -EINVAL;
++ } else {
++ switch (cmd) {
++ case VIDIOC_PRIVATE_ISP_AEWB_REQ:
++ {
++ /* Need to update sensor first */
++ struct isph3a_aewb_data *data;
++ struct v4l2_control vc;
++
++ data = (struct isph3a_aewb_data *) arg;
++ if (data->update & SET_EXPOSURE) {
++ dev_info(&vdev->vfd->dev, "using "
++ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
++ "exposure is deprecated!\n");
++ vc.id = V4L2_CID_EXPOSURE;
++ vc.value = data->shutter;
++ mutex_lock(&vdev->mutex);
++ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
++ &vc);
++ mutex_unlock(&vdev->mutex);
++ if (rval)
++ goto out;
++ }
++ if (data->update & SET_ANALOG_GAIN) {
++ dev_info(&vdev->vfd->dev, "using "
++ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
++ "gain is deprecated!\n");
++ vc.id = V4L2_CID_GAIN;
++ vc.value = data->gain;
++ mutex_lock(&vdev->mutex);
++ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
++ &vc);
++ mutex_unlock(&vdev->mutex);
++ if (rval)
++ goto out;
++ }
++ }
++ break;
++ case VIDIOC_PRIVATE_ISP_AF_REQ: {
++ /* Need to update lens first */
++ struct isp_af_data *data;
++ struct v4l2_control vc;
++
++ if (!vdev->vdev_lens) {
++ rval = -EINVAL;
++ goto out;
++ }
++ data = (struct isp_af_data *) arg;
++ if (data->update & LENS_DESIRED_POSITION) {
++ dev_info(&vdev->vfd->dev, "using "
++ "VIDIOC_PRIVATE_ISP_AF_REQ to set "
++ "lens position is deprecated!\n");
++ vc.id = V4L2_CID_FOCUS_ABSOLUTE;
++ vc.value = data->desired_lens_direction;
++ mutex_lock(&vdev->mutex);
++ rval = vidioc_int_s_ctrl(vdev->vdev_lens, &vc);
++ mutex_unlock(&vdev->mutex);
++ if (rval)
++ goto out;
++ }
++ }
++ break;
++ }
++
++ mutex_lock(&vdev->mutex);
++ rval = isp_handle_private(cmd, arg);
++ mutex_unlock(&vdev->mutex);
++ }
++out:
++ return rval;
++}
++
++/*
++ *
++ * File operations.
++ *
++ */
++
++/**
++ * omap34xxcam_poll - file operations poll handler
++ * @file: ptr. to system file structure
++ * @wait: system poll table structure
++ *
++ */
++static unsigned int omap34xxcam_poll(struct file *file,
++ struct poll_table_struct *wait)
++{
++ struct omap34xxcam_fh *fh = file->private_data;
++ struct omap34xxcam_videodev *vdev = fh->vdev;
++ struct videobuf_buffer *vb;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming != file) {
++ mutex_unlock(&vdev->mutex);
++ return POLLERR;
++ }
++ mutex_unlock(&vdev->mutex);
++
++ mutex_lock(&fh->vbq.vb_lock);
++ if (list_empty(&fh->vbq.stream)) {
++ mutex_unlock(&fh->vbq.vb_lock);
++ return POLLERR;
++ }
++ vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream);
++ mutex_unlock(&fh->vbq.vb_lock);
++
++ poll_wait(file, &vb->done, wait);
++
++ if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR)
++ return POLLIN | POLLRDNORM;
++
++ return 0;
++}
++
++/**
++ * omap34xxcam_mmap - file operations mmap handler
++ * @file: ptr. to system file structure
++ * @vma: system virt. mem. area structure
++ *
++ * Maps a virtual memory area via the video buffer API
++ */
++static int omap34xxcam_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct omap34xxcam_fh *fh = file->private_data;
++ return videobuf_mmap_mapper(&fh->vbq, vma);
++}
++
++/**
++ * omap34xxcam_open - file operations open handler
++ * @inode: ptr. to system inode structure
++ * @file: ptr. to system file structure
++ *
++ * Allocates and initializes the per-filehandle data (omap34xxcam_fh),
++ * enables the sensor, opens/initializes the ISP interface and the
++ * video buffer queue. Note that this function will allow multiple
++ * file handles to be open simultaneously, however only the first
++ * handle opened will initialize the ISP. It is the application
++ * responsibility to only use one handle for streaming and the others
++ * for control only.
++ * This function returns 0 upon success and -ENODEV upon error.
++ */
++static int omap34xxcam_open(struct file *file)
++{
++ int rval = 0;
++ struct omap34xxcam_videodev *vdev = NULL;
++ struct omap34xxcam_device *cam = omap34xxcam;
++ struct omap34xxcam_fh *fh;
++ struct v4l2_format format;
++ int i;
++
++ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
++ if (cam->vdevs[i].vfd
++ && cam->vdevs[i].vfd->minor ==
++ iminor(file->f_dentry->d_inode)) {
++ vdev = &cam->vdevs[i];
++ break;
++ }
++ }
++
++ if (!vdev || !vdev->vfd)
++ return -ENODEV;
++
++ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
++ if (fh == NULL)
++ return -ENOMEM;
++
++ mutex_lock(&vdev->mutex);
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ if (vdev->slave[i] != v4l2_int_device_dummy()
++ && !try_module_get(vdev->slave[i]->module)) {
++ mutex_unlock(&vdev->mutex);
++ dev_err(&vdev->vfd->dev, "can't try_module_get %s\n",
++ vdev->slave[i]->name);
++ rval = -ENODEV;
++ goto out_try_module_get;
++ }
++ }
++
++ if (atomic_inc_return(&vdev->users) == 1) {
++ rval = isp_get();
++ if (rval < 0) {
++ dev_err(&vdev->vfd->dev, "can't get isp\n");
++ goto out_isp_get;
++ }
++ if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
++ OMAP34XXCAM_SLAVE_POWER_ALL)) {
++ dev_err(&vdev->vfd->dev, "can't power up slaves\n");
++ rval = -EBUSY;
++ goto out_slave_power_set_standby;
++ }
++ omap34xxcam_slave_power_set(
++ vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_SENSOR);
++ omap34xxcam_slave_power_suggest(
++ vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_LENS);
++ }
++
++ fh->vdev = vdev;
++
++ if (!vdev->pix.width
++ && vdev->vdev_sensor != v4l2_int_device_dummy()) {
++ memset(&format, 0, sizeof(format));
++ if (vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format)) {
++ dev_err(&vdev->vfd->dev,
++ "can't get current pix from sensor!\n");
++ goto out_vidioc_int_g_fmt_cap;
++ }
++ if (!vdev->vdev_sensor_config.sensor_isp) {
++ struct v4l2_pix_format pix = format.fmt.pix;
++ if (isp_s_fmt_cap(&pix, &format.fmt.pix)) {
++ dev_err(&vdev->vfd->dev,
++ "isp doesn't like the sensor!\n");
++ goto out_isp_s_fmt_cap;
++ }
++ }
++ vdev->pix = format.fmt.pix;
++ }
++
++ mutex_unlock(&vdev->mutex);
++
++ file->private_data = fh;
++
++ spin_lock_init(&fh->vbq_lock);
++
++ videobuf_queue_sg_init(&fh->vbq, &omap34xxcam_vbq_ops, NULL,
++ &fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ V4L2_FIELD_NONE,
++ sizeof(struct videobuf_buffer), fh);
++
++ return 0;
++
++out_isp_s_fmt_cap:
++out_vidioc_int_g_fmt_cap:
++ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
++ OMAP34XXCAM_SLAVE_POWER_ALL);
++out_slave_power_set_standby:
++ isp_put();
++
++out_isp_get:
++ atomic_dec(&vdev->users);
++ mutex_unlock(&vdev->mutex);
++
++out_try_module_get:
++ for (i--; i >= 0; i--)
++ if (vdev->slave[i] != v4l2_int_device_dummy())
++ module_put(vdev->slave[i]->module);
++
++ kfree(fh);
++
++ return rval;
++}
++
++/**
++ * omap34xxcam_release - file operations release handler
++ * @inode: ptr. to system inode structure
++ * @file: ptr. to system file structure
++ *
++ * Complement of omap34xxcam_open. This function will flush any scheduled
++ * work, disable the sensor, close the ISP interface, stop the
++ * video buffer queue from streaming and free the per-filehandle data
++ * (omap34xxcam_fh). Note that because multiple open file handles
++ * are allowed, this function will only close the ISP and disable the
++ * sensor when the last open file handle (by count) is closed.
++ * This function returns 0.
++ */
++static int omap34xxcam_release(struct file *file)
++{
++ struct omap34xxcam_fh *fh = file->private_data;
++ struct omap34xxcam_videodev *vdev = fh->vdev;
++ int i;
++
++ mutex_lock(&vdev->mutex);
++ if (vdev->streaming == file) {
++ isp_stop();
++ videobuf_streamoff(&fh->vbq);
++ omap34xxcam_slave_power_set(
++ vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_SENSOR);
++ omap34xxcam_slave_power_suggest(
++ vdev, V4L2_POWER_STANDBY,
++ OMAP34XXCAM_SLAVE_POWER_LENS);
++ vdev->streaming = NULL;
++ }
++
++ if (atomic_dec_return(&vdev->users) == 0) {
++ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
++ OMAP34XXCAM_SLAVE_POWER_ALL);
++ isp_put();
++ }
++ mutex_unlock(&vdev->mutex);
++
++ file->private_data = NULL;
++
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
++ if (vdev->slave[i] != v4l2_int_device_dummy())
++ module_put(vdev->slave[i]->module);
++
++ kfree(fh);
++
++ return 0;
++}
++
++static struct v4l2_file_operations omap34xxcam_fops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = video_ioctl2,
++ .poll = omap34xxcam_poll,
++ .mmap = omap34xxcam_mmap,
++ .open = omap34xxcam_open,
++ .release = omap34xxcam_release,
++};
++
++static void omap34xxcam_vfd_name_update(struct omap34xxcam_videodev *vdev)
++{
++ struct video_device *vfd = vdev->vfd;
++ int i;
++
++ strlcpy(vfd->name, CAM_SHORT_NAME, sizeof(vfd->name));
++ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
++ strlcat(vfd->name, "/", sizeof(vfd->name));
++ if (vdev->slave[i] == v4l2_int_device_dummy())
++ continue;
++ strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
++ }
++ dev_info(&vdev->vfd->dev, "video%d is now %s\n", vfd->num, vfd->name);
++}
++
++/**
++ * omap34xxcam_device_unregister - V4L2 detach handler
++ * @s: ptr. to standard V4L2 device information structure
++ *
++ * Detach sensor and unregister and release the video device.
++ */
++static void omap34xxcam_device_unregister(struct v4l2_int_device *s)
++{
++ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
++ struct omap34xxcam_hw_config hwc;
++
++ BUG_ON(vidioc_int_g_priv(s, &hwc) < 0);
++
++ mutex_lock(&vdev->mutex);
++
++ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy()) {
++ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
++ vdev->slaves--;
++ omap34xxcam_vfd_name_update(vdev);
++ }
++
++ if (vdev->slaves == 0 && vdev->vfd) {
++ if (vdev->vfd->minor == -1) {
++ /*
++ * The device was never registered, so release the
++ * video_device struct directly.
++ */
++ video_device_release(vdev->vfd);
++ } else {
++ /*
++ * The unregister function will release the
++ * video_device struct as well as
++ * unregistering it.
++ */
++ video_unregister_device(vdev->vfd);
++ }
++ vdev->vfd = NULL;
++ }
++
++ mutex_unlock(&vdev->mutex);
++}
++
++static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
++ .vidioc_reqbufs = vidioc_reqbufs,
++ .vidioc_querybuf = vidioc_querybuf,
++ .vidioc_qbuf = vidioc_qbuf,
++ .vidioc_dqbuf = vidioc_dqbuf,
++ .vidioc_streamon = vidioc_streamon,
++ .vidioc_streamoff = vidioc_streamoff,
++ .vidioc_enum_input = vidioc_enum_input,
++ .vidioc_g_input = vidioc_g_input,
++ .vidioc_s_input = vidioc_s_input,
++ .vidioc_queryctrl = vidioc_queryctrl,
++ .vidioc_querymenu = vidioc_querymenu,
++ .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
++ .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
++ .vidioc_g_parm = vidioc_g_parm,
++ .vidioc_s_parm = vidioc_s_parm,
++ .vidioc_cropcap = vidioc_cropcap,
++ .vidioc_g_crop = vidioc_g_crop,
++ .vidioc_s_crop = vidioc_s_crop,
++ .vidioc_enum_framesizes = vidioc_enum_framesizes,
++ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
++ .vidioc_default = vidioc_default,
++};
++
++/**
++ * omap34xxcam_device_register - V4L2 attach handler
++ * @s: ptr. to standard V4L2 device information structure
++ *
++ * Allocates and initializes the V4L2 video_device structure, initializes
++ * the sensor, and finally
++ registers the device with V4L2 based on the
++ * video_device structure.
++ *
++ * Returns 0 on success, otherwise an appropriate error code on
++ * failure.
++ */
++static int omap34xxcam_device_register(struct v4l2_int_device *s)
++{
++ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
++ struct omap34xxcam_hw_config hwc;
++ int rval;
++
++ /* We need to check rval just once. The place is here. */
++ if (vidioc_int_g_priv(s, &hwc))
++ return -ENODEV;
++
++ if (vdev->index != hwc.dev_index)
++ return -ENODEV;
++
++ if (hwc.dev_type < 0 || hwc.dev_type > OMAP34XXCAM_SLAVE_FLASH)
++ return -EINVAL;
++
++ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy())
++ return -EBUSY;
++
++ mutex_lock(&vdev->mutex);
++ if (atomic_read(&vdev->users)) {
++ printk(KERN_ERR "%s: we're open (%d), can't register\n",
++ __func__, atomic_read(&vdev->users));
++ mutex_unlock(&vdev->mutex);
++ return -EBUSY;
++ }
++
++ vdev->slaves++;
++ vdev->slave[hwc.dev_type] = s;
++ vdev->slave_config[hwc.dev_type] = hwc;
++
++ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
++ rval = isp_get();
++ if (rval < 0) {
++ printk(KERN_ERR "%s: can't get ISP, "
++ "sensor init failed\n", __func__);
++ goto err;
++ }
++ }
++ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
++ 1 << hwc.dev_type);
++ if (rval)
++ goto err_omap34xxcam_slave_power_set;
++ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
++ struct v4l2_format format;
++
++ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
++ if (rval)
++ rval = -EBUSY;
++
++ vdev->want_pix = format.fmt.pix;
++ }
++ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF, 1 << hwc.dev_type);
++ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
++ isp_put();
++
++ if (rval)
++ goto err;
++
++ /* Are we the first slave? */
++ if (vdev->slaves == 1) {
++ /* initialize the video_device struct */
++ vdev->vfd = video_device_alloc();
++ if (!vdev->vfd) {
++ printk(KERN_ERR "%s: could not allocate "
++ "video device struct\n", __func__);
++ rval = -ENOMEM;
++ goto err;
++ }
++ vdev->vfd->release = video_device_release;
++ vdev->vfd->minor = -1;
++ vdev->vfd->fops = &omap34xxcam_fops;
++ vdev->vfd->ioctl_ops = &omap34xxcam_ioctl_ops;
++ video_set_drvdata(vdev->vfd, vdev);
++
++ if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
++ hwc.dev_minor) < 0) {
++ printk(KERN_ERR "%s: could not register V4L device\n",
++ __func__);
++ vdev->vfd->minor = -1;
++ rval = -EBUSY;
++ goto err;
++ }
++ }
++
++ omap34xxcam_vfd_name_update(vdev);
++
++ mutex_unlock(&vdev->mutex);
++
++ return 0;
++
++err_omap34xxcam_slave_power_set:
++ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
++ isp_put();
++
++err:
++ if (s == vdev->slave[hwc.dev_type]) {
++ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
++ vdev->slaves--;
++ }
++
++ mutex_unlock(&vdev->mutex);
++ omap34xxcam_device_unregister(s);
++
++ return rval;
++}
++
++static struct v4l2_int_master omap34xxcam_master = {
++ .attach = omap34xxcam_device_register,
++ .detach = omap34xxcam_device_unregister,
++};
++
++/*
++ *
++ * Module initialisation and deinitialisation
++ *
++ */
++
++static void omap34xxcam_exit(void)
++{
++ struct omap34xxcam_device *cam = omap34xxcam;
++ int i;
++
++ if (!cam)
++ return;
++
++ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
++ if (cam->vdevs[i].cam == NULL)
++ continue;
++
++ v4l2_int_device_unregister(&cam->vdevs[i].master);
++ cam->vdevs[i].cam = NULL;
++ }
++
++ omap34xxcam = NULL;
++
++ kfree(cam);
++}
++
++static int __init omap34xxcam_init(void)
++{
++ struct omap34xxcam_device *cam;
++ int i;
++
++ cam = kzalloc(sizeof(*cam), GFP_KERNEL);
++ if (!cam) {
++ printk(KERN_ERR "%s: could not allocate memory\n", __func__);
++ return -ENOMEM;
++ }
++
++ omap34xxcam = cam;
++
++ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
++ struct omap34xxcam_videodev *vdev = &cam->vdevs[i];
++ struct v4l2_int_device *m = &vdev->master;
++
++ m->module = THIS_MODULE;
++ strlcpy(m->name, CAM_NAME, sizeof(m->name));
++ m->type = v4l2_int_type_master;
++ m->u.master = &omap34xxcam_master;
++ m->priv = vdev;
++
++ mutex_init(&vdev->mutex);
++ vdev->index = i;
++ vdev->cam = cam;
++ vdev->vdev_sensor =
++ vdev->vdev_lens =
++ vdev->vdev_flash = v4l2_int_device_dummy();
++#ifdef OMAP34XXCAM_POWEROFF_DELAY
++ setup_timer(&vdev->poweroff_timer,
++ omap34xxcam_slave_power_timer, (unsigned long)vdev);
++ INIT_WORK(&vdev->poweroff_work, omap34xxcam_slave_power_work);
++#endif /* OMAP34XXCAM_POWEROFF_DELAY */
++
++ if (v4l2_int_device_register(m))
++ goto err;
++ }
++
++ return 0;
++
++err:
++ omap34xxcam_exit();
++ return -ENODEV;
++}
++
++MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
++MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
++MODULE_LICENSE("GPL");
++
++late_initcall(omap34xxcam_init);
++module_exit(omap34xxcam_exit);
+diff --git a/drivers/media/video/omap34xxcam.h b/drivers/media/video/omap34xxcam.h
+new file mode 100644
+index 0000000..9859d15
+--- /dev/null
++++ b/drivers/media/video/omap34xxcam.h
+@@ -0,0 +1,207 @@
++/*
++ * omap34xxcam.h
++ *
++ * Copyright (C) 2006--2009 Nokia Corporation
++ * Copyright (C) 2007--2009 Texas Instruments
++ *
++ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ *
++ * Originally based on the OMAP 2 camera driver.
++ *
++ * Written by Sakari Ailus <sakari.ailus@nokia.com>
++ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Mohit Jalori
++ * Sameer Venkatraman
++ * Leonides Martinez
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++
++#ifndef OMAP34XXCAM_H
++#define OMAP34XXCAM_H
++
++#include <media/v4l2-int-device.h>
++#include "isp/isp.h"
++
++#define CAM_NAME "omap34xxcam"
++#define CAM_SHORT_NAME "omap3"
++
++#define OMAP_ISP_AF (1 << 4)
++#define OMAP_ISP_HIST (1 << 5)
++#define OMAP34XXCAM_XCLK_NONE -1
++#define OMAP34XXCAM_XCLK_A 0
++#define OMAP34XXCAM_XCLK_B 1
++
++#define OMAP34XXCAM_SLAVE_SENSOR 0
++#define OMAP34XXCAM_SLAVE_LENS 1
++#define OMAP34XXCAM_SLAVE_FLASH 2 /* This is the last slave! */
++
++/* mask for omap34xxcam_slave_power_set */
++#define OMAP34XXCAM_SLAVE_POWER_SENSOR (1 << OMAP34XXCAM_SLAVE_SENSOR)
++#define OMAP34XXCAM_SLAVE_POWER_LENS (1 << OMAP34XXCAM_SLAVE_LENS)
++#define OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS \
++ (OMAP34XXCAM_SLAVE_POWER_SENSOR | OMAP34XXCAM_SLAVE_POWER_LENS)
++#define OMAP34XXCAM_SLAVE_POWER_FLASH (1 << OMAP34XXCAM_SLAVE_FLASH)
++#define OMAP34XXCAM_SLAVE_POWER_ALL -1
++
++#define OMAP34XXCAM_VIDEODEVS 4
++
++/* #define OMAP34XXCAM_POWEROFF_DELAY (2 * HZ) */
++
++struct omap34xxcam_device;
++struct omap34xxcam_videodev;
++
++struct omap34xxcam_sensor_config {
++ int xclk;
++ int sensor_isp;
++ u32 capture_mem;
++ struct v4l2_fract ival_default;
++};
++
++struct omap34xxcam_lens_config {
++};
++
++struct omap34xxcam_flash_config {
++};
++
++/**
++ * struct omap34xxcam_hw_config - struct for vidioc_int_g_priv ioctl
++ * @xclk: OMAP34XXCAM_XCLK_A or OMAP34XXCAM_XCLK_B
++ * @sensor_isp: Is sensor smart/SOC or raw
++ * @s_pix_sparm: Access function to set pix and sparm.
++ * Pix will override sparm
++ */
++struct omap34xxcam_hw_config {
++ int dev_index; /* Index in omap34xxcam_sensors */
++ int dev_minor; /* Video device minor number */
++ int dev_type; /* OMAP34XXCAM_SLAVE_* */
++ union {
++ struct omap34xxcam_sensor_config sensor;
++ struct omap34xxcam_lens_config lens;
++ struct omap34xxcam_flash_config flash;
++ } u;
++};
++
++/**
++ * struct omap34xxcam_videodev - per /dev/video* structure
++ * @mutex: serialises access to this structure
++ * @cam: pointer to cam hw structure
++ * @master: we are v4l2_int_device master
++ * @sensor: sensor device
++ * @lens: lens device
++ * @flash: flash device
++ * @slaves: how many slaves we have at the moment
++ * @vfd: our video device
++ * @capture_mem: maximum kernel-allocated capture memory
++ * @if_u: sensor interface stuff
++ * @index: index of this structure in cam->vdevs
++ * @users: how many users we have
++ * @power_state: Current power state
++ * @power_state_wish: New power state when poweroff_timer expires
++ * @power_state_mask: Bitmask of devices to set the new power state
++ * @poweroff_timer: Timer for dispatching poweroff_work
++ * @poweroff_work: Work for slave power state change
++ * @sensor_config: ISP-speicific sensor configuration
++ * @lens_config: ISP-speicific lens configuration
++ * @flash_config: ISP-speicific flash configuration
++ * @want_timeperframe: Desired timeperframe
++ * @want_pix: Desired pix
++ * @pix: Current pix
++ * @streaming: streaming file handle, if streaming is enabled
++ */
++struct omap34xxcam_videodev {
++ struct mutex mutex; /* serialises access to this structure */
++
++ struct omap34xxcam_device *cam;
++ struct v4l2_int_device master;
++
++#define vdev_sensor slave[OMAP34XXCAM_SLAVE_SENSOR]
++#define vdev_lens slave[OMAP34XXCAM_SLAVE_LENS]
++#define vdev_flash slave[OMAP34XXCAM_SLAVE_FLASH]
++ struct v4l2_int_device *slave[OMAP34XXCAM_SLAVE_FLASH + 1];
++
++ /* number of slaves attached */
++ int slaves;
++
++ /*** video device parameters ***/
++ struct video_device *vfd;
++ int capture_mem;
++
++ /*** general driver state information ***/
++ int index;
++ atomic_t users;
++ enum v4l2_power power_state[OMAP34XXCAM_SLAVE_FLASH + 1];
++#ifdef OMAP34XXCAM_POWEROFF_DELAY
++ enum v4l2_power power_state_wish;
++ int power_state_mask;
++ struct timer_list poweroff_timer;
++ struct work_struct poweroff_work;
++#endif /* OMAP34XXCAM_POWEROFF_DELAY */
++
++#define vdev_sensor_config slave_config[OMAP34XXCAM_SLAVE_SENSOR].u.sensor
++#define vdev_lens_config slave_config[OMAP34XXCAM_SLAVE_LENS].u.lens
++#define vdev_flash_config slave_config[OMAP34XXCAM_SLAVE_FLASH].u.flash
++ struct omap34xxcam_hw_config slave_config[OMAP34XXCAM_SLAVE_FLASH + 1];
++
++ /*** capture data ***/
++ struct file *streaming;
++ struct v4l2_fract want_timeperframe;
++ struct v4l2_pix_format want_pix;
++ spinlock_t pix_lock;
++ struct v4l2_pix_format pix;
++};
++
++/**
++ * struct omap34xxcam_device - per-device data structure
++ * @mutex: mutex serialises access to this structure
++ * @sgdma_in_queue: Number or sgdma requests in scatter-gather queue,
++ * protected by the lock above.
++ * @sgdma: ISP sgdma subsystem information structure
++ * @dma_notify: DMA notify flag
++ * @dev: device structure
++ * @vdevs: /dev/video specific structures
++ * @fck: camera module fck clock information
++ * @ick: camera module ick clock information
++ */
++struct omap34xxcam_device {
++ struct mutex mutex; /* serialises access to this structure */
++
++ /*** interfaces and device ***/
++ struct omap34xxcam_videodev vdevs[OMAP34XXCAM_VIDEODEVS];
++
++ /*** camera module clocks ***/
++ struct clk *fck;
++ struct clk *ick;
++ bool sensor_if_enabled;
++};
++
++/**
++ * struct omap34xxcam_fh - per-filehandle data structure
++ * @vbq_lock: spinlock for the videobuf queue
++ * @vbq: V4L2 video buffer queue structure
++ * @field_count: field counter for videobuf_buffer
++ * @vdev: our /dev/video specific structure
++ */
++struct omap34xxcam_fh {
++ spinlock_t vbq_lock; /* spinlock for the videobuf queue */
++ struct videobuf_queue vbq;
++ atomic_t field_count;
++ struct omap34xxcam_videodev *vdev;
++};
++
++#endif /* ifndef OMAP34XXCAM_H */
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
new file mode 100644
index 0000000000..3390599292
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
@@ -0,0 +1,1890 @@
+From 38f3cd5564a466e5251fc2ff47e0504148922304 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:18:56 +0530
+Subject: [PATCH 23/26] OMAP-Resizer: Basic Resizer refreshed with latest gitorious tree
+
+This is same resizer driver patch posted by Sergio onto
+mailing list quite a some time back. This commit refreshes
+the same patch on top of latest gitorious.org tree.
+
+List of New/Modified files:
+ modified: drivers/media/video/Kconfig
+ modified: drivers/media/video/isp/Makefile
+ modified: drivers/media/video/isp/isp.c
+ modified: drivers/media/video/isp/ispreg.h
+ new file: drivers/media/video/isp/omap_resizer.c
+ new file: include/linux/omap_resizer.h
+
+TODO:
+ - Resizer driver needs to be independent from camera and ISP
+ - Custom patches implemented ontop of PSP1.0.2 release
+ to fix some V4L2-buf layer issues.
+ -
+---
+ drivers/media/video/Kconfig | 7 +
+ drivers/media/video/isp/Makefile | 4 +
+ drivers/media/video/isp/isp.c | 15 +
+ drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++++
+ include/linux/omap_resizer.h | 136 +++
+ 5 files changed, 1796 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/omap_resizer.c
+ create mode 100644 include/linux/omap_resizer.h
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 3cdb5a4..d2b4ae1 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -720,6 +720,13 @@ config VIDEO_OMAP3
+ ---help---
+ Driver for an OMAP 3 camera controller.
+
++config VIDEO_OMAP34XX_ISP_RESIZER
++ tristate "OMAP ISP Resizer"
++ depends on VIDEO_V4L2 && ARCH_OMAP34XX
++ select VIDEOBUF_GEN
++ select VIDEOBUF_DMA_SG
++ select OMAP_IOMMU
++
+ config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA
+diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
+index f14d617..d171fb9 100644
+--- a/drivers/media/video/isp/Makefile
++++ b/drivers/media/video/isp/Makefile
+@@ -7,6 +7,10 @@ else
+ isp-mod-objs += \
+ isp.o ispccdc.o ispmmu.o \
+ isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
++
++obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
++ omap_resizer.o
++
+ endif
+
+ obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
+diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
+index 54c839b..f1f92b4 100644
+--- a/drivers/media/video/isp/isp.c
++++ b/drivers/media/video/isp/isp.c
+@@ -505,6 +505,12 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ IRQ0ENABLE_PRV_DONE_IRQ);
+ break;
++ case CBK_RESZ_DONE:
++ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_RSZ_DONE_IRQ);
++ break;
+ default:
+ break;
+ }
+@@ -556,6 +562,10 @@ int isp_unset_callback(enum isp_callback_type type)
+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ ~IRQ0ENABLE_PRV_DONE_IRQ);
+ break;
++ case CBK_RESZ_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_RSZ_DONE_IRQ);
++ break;
+ default:
+ break;
+ }
+@@ -938,6 +948,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
+ if (!ispresizer_busy())
+ ispresizer_config_shadow_registers();
+ isp_buf_process(bufs);
++ } else {
++ if (irqdis->isp_callbk[CBK_RESZ_DONE])
++ irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE,
++ irqdis->isp_callbk_arg1[CBK_RESZ_DONE],
++ irqdis->isp_callbk_arg2[CBK_RESZ_DONE]);
+ }
+ }
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+new file mode 100644
+index 0000000..54bc425
+--- /dev/null
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -0,0 +1,1634 @@
++/*
++ * drivers/media/video/isp/omap_resizer.c
++ *
++ * Wrapper for Resizer module in TI's OMAP3430 ISP
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy <t-laramy@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/mutex.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/uaccess.h>
++#include <media/v4l2-dev.h>
++#include <asm/cacheflush.h>
++
++#include "isp.h"
++#include "ispmmu.h"
++#include "ispreg.h"
++#include "ispresizer.h"
++#include <linux/omap_resizer.h>
++
++#define OMAP_REZR_NAME "omap-resizer"
++
++/* Defines and Constants*/
++#define MAX_CHANNELS 16
++#define MAX_IMAGE_WIDTH 2047
++#define MAX_IMAGE_WIDTH_HIGH 2047
++#define ALIGNMENT 16
++#define CHANNEL_BUSY 1
++#define CHANNEL_FREE 0
++#define PIXEL_EVEN 2
++#define RATIO_MULTIPLIER 256
++/* Bit position Macro */
++/* macro for bit set and clear */
++#define BITSET(variable, bit) ((variable) | (1 << bit))
++#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit)))
++#define SET_BIT_INPUTRAM 28
++#define SET_BIT_CBLIN 29
++#define SET_BIT_INPTYP 27
++#define SET_BIT_YCPOS 26
++#define INPUT_RAM 1
++#define UP_RSZ_RATIO 64
++#define DOWN_RSZ_RATIO 512
++#define UP_RSZ_RATIO1 513
++#define DOWN_RSZ_RATIO1 1024
++#define RSZ_IN_SIZE_VERT_SHIFT 16
++#define MAX_HORZ_PIXEL_8BIT 31
++#define MAX_HORZ_PIXEL_16BIT 15
++#define NUM_PHASES 8
++#define NUM_TAPS 4
++#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x,
++ * number of phases
++ */
++#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x,
++ * number of taps
++ */
++#define ALIGN32 32
++#define MAX_COEF_COUNTER 16
++#define COEFF_ADDRESS_OFFSET 0x04
++
++/* Global structure which contains information about number of channels
++ and protection variables */
++struct device_params {
++
++ unsigned char opened; /* state of the device */
++ struct completion compl_isr; /* Completion for interrupt */
++ struct mutex reszwrap_mutex; /* Semaphore for array */
++
++ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
++};
++
++/* Register mapped structure which contains the every register
++ information */
++struct resizer_config {
++ u32 rsz_pcr; /* pcr register mapping
++ * variable.
++ */
++ u32 rsz_in_start; /* in_start register mapping
++ * variable.
++ */
++ u32 rsz_in_size; /* in_size register mapping
++ * variable.
++ */
++ u32 rsz_out_size; /* out_size register mapping
++ * variable.
++ */
++ u32 rsz_cnt; /* rsz_cnt register mapping
++ * variable.
++ */
++ u32 rsz_sdr_inadd; /* sdr_inadd register mapping
++ * variable.
++ */
++ u32 rsz_sdr_inoff; /* sdr_inoff register mapping
++ * variable.
++ */
++ u32 rsz_sdr_outadd; /* sdr_outadd register mapping
++ * variable.
++ */
++ u32 rsz_sdr_outoff; /* sdr_outbuff register
++ * mapping variable.
++ */
++ u32 rsz_coeff_horz[16]; /* horizontal coefficients
++ * mapping array.
++ */
++ u32 rsz_coeff_vert[16]; /* vertical coefficients
++ * mapping array.
++ */
++ u32 rsz_yehn; /* yehn(luma)register mapping
++ * variable.
++ */
++};
++
++struct rsz_mult {
++ int in_hsize; /* input frame horizontal
++ * size.
++ */
++ int in_vsize; /* input frame vertical size.
++ */
++ int out_hsize; /* output frame horizontal
++ * size.
++ */
++ int out_vsize; /* output frame vertical
++ * size.
++ */
++ int in_pitch; /* offset between two rows of
++ * input frame.
++ */
++ int out_pitch; /* offset between two rows of
++ * output frame.
++ */
++ int end_hsize;
++ int end_vsize;
++ int num_htap; /* 0 = 7tap; 1 = 4tap */
++ int num_vtap; /* 0 = 7tap; 1 = 4tap */
++ int active;
++ int inptyp;
++ int vrsz;
++ int hrsz;
++ int hstph; /* for specifying horizontal
++ * starting phase.
++ */
++ int vstph;
++ int pix_fmt; /* # defined, UYVY or YUYV. */
++ int cbilin; /* # defined, filter with luma
++ * or bi-linear.
++ */
++ u16 tap4filt_coeffs[32]; /* horizontal filter
++ * coefficients.
++ */
++ u16 tap7filt_coeffs[32]; /* vertical filter
++ * coefficients.
++ */
++};
++/* Channel specific structure contains information regarding
++ the every channel */
++struct channel_config {
++ struct resizer_config register_config; /* Instance of register set
++ * mapping structure
++ */
++ int status; /* Specifies whether the
++ * channel is busy or not
++ */
++ struct mutex chanprotection_mutex;
++ enum config_done config_state;
++ u8 input_buf_index;
++ u8 output_buf_index;
++
++};
++
++/* per-filehandle data structure */
++struct rsz_fh {
++ struct rsz_params *params;
++ struct channel_config *config;
++ struct rsz_mult *multipass; /* Multipass to support
++ * resizing ration outside
++ * of 0.25x to 4x
++ */
++ spinlock_t vbq_lock; /* spinlock for videobuf
++ * queues.
++ */
++ enum v4l2_buf_type type;
++ struct videobuf_queue vbq;
++ struct device_params *device;
++
++ dma_addr_t isp_addr_read; /* Input/Output address */
++ dma_addr_t isp_addr_write; /* Input/Output address */
++ u32 rsz_bufsize; /* channel specific buffersize
++ */
++};
++
++static struct device_params *device_config;
++static struct device *rsz_device;
++static int rsz_major = -1;
++/* functions declaration */
++static void rsz_hardware_setup(struct channel_config *rsz_conf_chan);
++static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *,
++ struct channel_config *);
++static int rsz_get_params(struct rsz_params *, struct channel_config *);
++static void rsz_copy_data(struct rsz_mult *multipass,
++ struct rsz_params *params);
++static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1,
++ void *arg2);
++static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
++ struct rsz_cropsize *cropsize);
++static int rsz_set_multipass(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++static int rsz_set_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++static void rsz_config_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++
++/**
++ * rsz_hardware_setup - Sets hardware configuration registers
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Set hardware configuration registers
++ **/
++static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
++{
++ int coeffcounter;
++ int coeffoffset = 0;
++
++ omap_writel(rsz_conf_chan->register_config.rsz_cnt,
++ OMAP3ISP_RESZ_REG(ISPRSZ_CNT));
++
++ omap_writel(rsz_conf_chan->register_config.rsz_in_start,
++ OMAP3ISP_RESZ_REG(ISPRSZ_IN_START));
++ omap_writel(rsz_conf_chan->register_config.rsz_in_size,
++ OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE));
++
++ omap_writel(rsz_conf_chan->register_config.rsz_out_size,
++ OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF));
++ omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH));
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ omap_writel(rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter],
++ OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10
++ + coeffoffset));
++
++ omap_writel(rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter],
++ OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10
++ + coeffoffset));
++ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
++ }
++}
++
++/**
++ * rsz_start - Enables Resizer Wrapper
++ * @arg: Currently not used.
++ * @device: Structure containing ISP resizer wrapper global information
++ *
++ * Submits a resizing task specified by the rsz_resize structure. The call can
++ * either be blocked until the task is completed or returned immediately based
++ * on the value of the blocking argument in the rsz_resize structure. If it is
++ * blocking, the status of the task can be checked by calling ioctl
++ * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
++ *
++ * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
++ * event or the state of the channel is not configured.
++ **/
++int rsz_start(int *arg, struct rsz_fh *fh)
++{
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_mult *multipass = fh->multipass;
++ struct videobuf_queue *q = &fh->vbq;
++ int ret;
++
++ if (rsz_conf_chan->config_state) {
++ dev_err(rsz_device, "State not configured \n");
++ goto err_einval;
++ }
++
++ rsz_conf_chan->status = CHANNEL_BUSY;
++
++ rsz_hardware_setup(rsz_conf_chan);
++
++ if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
++ (void *)NULL)) {
++ dev_err(rsz_device, "No callback for RSZR\n");
++ goto err_einval;
++ }
++mult:
++ device_config->compl_isr.done = 0;
++
++ ispresizer_enable(1);
++
++ ret = wait_for_completion_interruptible(&device_config->compl_isr);
++ if (ret != 0) {
++ dev_dbg(rsz_device, "Unexpected exit from "
++ "wait_for_completion_interruptible\n");
++ wait_for_completion(&device_config->compl_isr);
++ }
++
++ if (multipass->active) {
++ rsz_set_multipass(multipass, rsz_conf_chan);
++ goto mult;
++ }
++
++ if (fh->isp_addr_read) {
++ ispmmu_unmap(fh->isp_addr_read);
++ fh->isp_addr_read = 0;
++ }
++ if (fh->isp_addr_write) {
++ ispmmu_unmap(fh->isp_addr_write);
++ fh->isp_addr_write = 0;
++ }
++
++ rsz_conf_chan->status = CHANNEL_FREE;
++ q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
++ q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
++ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
++ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
++
++ /* Unmap and free the DMA memory allocated for buffers */
++ videobuf_dma_unmap(q, videobuf_to_dma(
++ q->bufs[rsz_conf_chan->input_buf_index]));
++ videobuf_dma_unmap(q, videobuf_to_dma(
++ q->bufs[rsz_conf_chan->output_buf_index]));
++ videobuf_dma_free(videobuf_to_dma(
++ q->bufs[rsz_conf_chan->input_buf_index]));
++ videobuf_dma_free(videobuf_to_dma(
++ q->bufs[rsz_conf_chan->output_buf_index]));
++
++ isp_unset_callback(CBK_RESZ_DONE);
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_set_multipass - Set resizer multipass
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Returns always 0
++ **/
++static int rsz_set_multipass(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ multipass->in_hsize = multipass->out_hsize;
++ multipass->in_vsize = multipass->out_vsize;
++ multipass->out_hsize = multipass->end_hsize;
++ multipass->out_vsize = multipass->end_vsize;
++
++ multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize
++ : (multipass->out_hsize * 2));
++ multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize
++ : (multipass->in_hsize * 2));
++
++ rsz_set_ratio(multipass, rsz_conf_chan);
++ rsz_config_ratio(multipass, rsz_conf_chan);
++ rsz_hardware_setup(rsz_conf_chan);
++ return 0;
++}
++
++/**
++ * rsz_copy_data - Copy data
++ * @params: Structure containing the Resizer Wrapper parameters
++ *
++ * Copy data
++ **/
++static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
++{
++ int i;
++ multipass->in_hsize = params->in_hsize;
++ multipass->in_vsize = params->in_vsize;
++ multipass->out_hsize = params->out_hsize;
++ multipass->out_vsize = params->out_vsize;
++ multipass->end_hsize = params->out_hsize;
++ multipass->end_vsize = params->out_vsize;
++ multipass->in_pitch = params->in_pitch;
++ multipass->out_pitch = params->out_pitch;
++ multipass->hstph = params->hstph;
++ multipass->vstph = params->vstph;
++ multipass->inptyp = params->inptyp;
++ multipass->pix_fmt = params->pix_fmt;
++ multipass->cbilin = params->cbilin;
++
++ for (i = 0; i < 32; i++) {
++ multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i];
++ multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i];
++ }
++}
++
++/**
++ * rsz_set_params - Set parameters for resizer wrapper
++ * @params: Structure containing the Resizer Wrapper parameters
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Used to set the parameters of the Resizer hardware, including input and
++ * output image size, horizontal and vertical poly-phase filter coefficients,
++ * luma enchancement filter coefficients, etc.
++ **/
++static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
++ struct channel_config *rsz_conf_chan)
++{
++ int mul = 1;
++ if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) {
++ dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n");
++ return -EINVAL;
++ }
++ if ((params->in_vsize <= 0) || (params->in_hsize <= 0) ||
++ (params->out_vsize <= 0) || (params->out_hsize <= 0) ||
++ (params->in_pitch <= 0) || (params->out_pitch <= 0)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid size params\n");
++ return -EINVAL;
++ }
++ if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) &&
++ (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid input type\n");
++ return -EINVAL;
++ }
++ if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) &&
++ (params->pix_fmt != RSZ_PIX_FMT_YUYV)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n");
++ return -EINVAL;
++ }
++ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
++ mul = 2;
++ else
++ mul = 1;
++ if (params->in_pitch < (params->in_hsize * mul)) {
++ dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n");
++ return -EINVAL;
++ }
++ if (params->out_pitch < (params->out_hsize * mul)) {
++ dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less"
++ " than out hsize\n");
++ return -EINVAL;
++ }
++ /* Output H size should be even */
++ if ((params->out_hsize % PIXEL_EVEN) != 0) {
++ dev_err(rsz_device, "rsz_set_params: Output H size should"
++ " be even\n");
++ return -EINVAL;
++ }
++ if (params->horz_starting_pixel < 0) {
++ dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot"
++ " be less than zero\n");
++ return -EINVAL;
++ }
++
++ rsz_copy_data(multipass, params);
++ if (0 != rsz_set_ratio(multipass, rsz_conf_chan))
++ goto err_einval;
++
++ if (params->yenh_params.type) {
++ if ((multipass->num_htap && multipass->out_hsize >
++ 1280) ||
++ (!multipass->num_htap && multipass->out_hsize >
++ 640))
++ goto err_einval;
++ }
++
++ if (INPUT_RAM)
++ params->vert_starting_pixel = 0;
++
++ rsz_conf_chan->register_config.rsz_in_start =
++ (params->vert_starting_pixel
++ << ISPRSZ_IN_SIZE_VERT_SHIFT)
++ & ISPRSZ_IN_SIZE_VERT_MASK;
++
++ if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
++ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT)
++ goto err_einval;
++ }
++ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) {
++ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_in_start |=
++ params->horz_starting_pixel
++ & ISPRSZ_IN_START_HORZ_ST_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn =
++ (params->yenh_params.type
++ << ISPRSZ_YENH_ALGO_SHIFT)
++ & ISPRSZ_YENH_ALGO_MASK;
++
++ if (params->yenh_params.type) {
++ rsz_conf_chan->register_config.rsz_yehn |=
++ params->yenh_params.core
++ & ISPRSZ_YENH_CORE_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn |=
++ (params->yenh_params.gain
++ << ISPRSZ_YENH_GAIN_SHIFT)
++ & ISPRSZ_YENH_GAIN_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn |=
++ (params->yenh_params.slop
++ << ISPRSZ_YENH_SLOP_SHIFT)
++ & ISPRSZ_YENH_SLOP_MASK;
++ }
++
++ rsz_config_ratio(multipass, rsz_conf_chan);
++
++ rsz_conf_chan->config_state = STATE_CONFIGURED;
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_set_ratio - Set ratio
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
++ * being requested, or other ratio configuration value is out of bounds
++ **/
++static int rsz_set_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ int alignment = 0;
++
++ rsz_conf_chan->register_config.rsz_cnt = 0;
++
++ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
++ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
++ dev_err(rsz_device, "Invalid output size!");
++ goto err_einval;
++ }
++ if (multipass->cbilin) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_CBLIN);
++ }
++ if (INPUT_RAM) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_INPUTRAM);
++ }
++ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_INPTYP);
++ } else {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITRESET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_INPTYP);
++
++ if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITRESET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_YCPOS);
++ } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_YCPOS);
++ }
++
++ }
++ multipass->vrsz =
++ (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize;
++ multipass->hrsz =
++ (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize;
++ if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) {
++ dev_err(rsz_device, "Upscaling ratio not supported!");
++ goto err_einval;
++ }
++ multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER
++ / (multipass->out_vsize - 1);
++ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER) /
++ (multipass->out_hsize - 1);
++
++ if (multipass->hrsz <= 512) {
++ multipass->hrsz = (multipass->in_hsize - NUM_TAPS)
++ * RATIO_MULTIPLIER
++ / (multipass->out_hsize - 1);
++ if (multipass->hrsz < 64)
++ multipass->hrsz = 64;
++ if (multipass->hrsz > 512)
++ multipass->hrsz = 512;
++ if (multipass->hstph > NUM_PHASES)
++ goto err_einval;
++ multipass->num_htap = 1;
++ } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) {
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_htap = 0;
++ }
++
++ if (multipass->vrsz <= 512) {
++ multipass->vrsz = (multipass->in_vsize - NUM_TAPS)
++ * RATIO_MULTIPLIER
++ / (multipass->out_vsize - 1);
++ if (multipass->vrsz < 64)
++ multipass->vrsz = 64;
++ if (multipass->vrsz > 512)
++ multipass->vrsz = 512;
++ if (multipass->vstph > NUM_PHASES)
++ goto err_einval;
++ multipass->num_vtap = 1;
++ } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) {
++ if (multipass->vstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_vtap = 0;
++ }
++
++ if ((multipass->in_pitch) % ALIGN32) {
++ dev_err(rsz_device, "Invalid input pitch: %d \n",
++ multipass->in_pitch);
++ goto err_einval;
++ }
++ if ((multipass->out_pitch) % ALIGN32) {
++ dev_err(rsz_device, "Invalid output pitch %d \n",
++ multipass->out_pitch);
++ goto err_einval;
++ }
++
++ if (multipass->vrsz < 256 &&
++ (multipass->in_vsize < multipass->out_vsize)) {
++ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT)
++ alignment = ALIGNMENT;
++ else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
++ alignment = (ALIGNMENT / 2);
++ else
++ dev_err(rsz_device, "Invalid input type\n");
++
++ if (!(((multipass->out_hsize % PIXEL_EVEN) == 0)
++ && (multipass->out_hsize % alignment) == 0)) {
++ dev_err(rsz_device, "wrong hsize\n");
++ goto err_einval;
++ }
++ }
++ if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) {
++ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++ multipass->active = 0;
++
++ } else if (multipass->hrsz > 1024) {
++ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_htap = 0;
++ multipass->out_hsize = multipass->in_hsize * 256 / 1024;
++ if (multipass->out_hsize % ALIGN32) {
++ multipass->out_hsize +=
++ abs((multipass->out_hsize % ALIGN32) - ALIGN32);
++ }
++ multipass->out_pitch = ((multipass->inptyp) ?
++ multipass->out_hsize :
++ (multipass->out_hsize * 2));
++ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER)
++ / (multipass->out_hsize - 1);
++ multipass->active = 1;
++
++ }
++
++ if (multipass->vrsz > 1024) {
++ if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++
++ multipass->out_vsize = multipass->in_vsize * 256 / 1024;
++ multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER)
++ / (multipass->out_vsize - 1);
++ multipass->active = 1;
++ multipass->num_vtap = 0;
++
++ }
++ rsz_conf_chan->register_config.rsz_out_size =
++ multipass->out_hsize
++ & ISPRSZ_OUT_SIZE_HORZ_MASK;
++
++ rsz_conf_chan->register_config.rsz_out_size |=
++ (multipass->out_vsize
++ << ISPRSZ_OUT_SIZE_VERT_SHIFT)
++ & ISPRSZ_OUT_SIZE_VERT_MASK;
++
++ rsz_conf_chan->register_config.rsz_sdr_inoff =
++ multipass->in_pitch
++ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
++
++ rsz_conf_chan->register_config.rsz_sdr_outoff =
++ multipass->out_pitch
++ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
++
++ if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->hstph > NUM_PHASES)
++ goto err_einval;
++ } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->hstph
++ << ISPRSZ_CNT_HSTPH_SHIFT)
++ & ISPRSZ_CNT_HSTPH_MASK;
++
++ if (multipass->vrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->vstph > NUM_PHASES)
++ goto err_einval;
++ } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) {
++ if (multipass->vstph > NUM_D2PH)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->vstph
++ << ISPRSZ_CNT_VSTPH_SHIFT)
++ & ISPRSZ_CNT_VSTPH_MASK;
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->hrsz - 1)
++ & ISPRSZ_CNT_HRSZ_MASK;
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ ((multipass->vrsz - 1)
++ << ISPRSZ_CNT_VRSZ_SHIFT)
++ & ISPRSZ_CNT_VRSZ_MASK;
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_config_ratio - Configure ratio
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Configure ratio
++ **/
++static void rsz_config_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ int hsize;
++ int vsize;
++ int coeffcounter;
++
++ if (multipass->hrsz <= 512) {
++ hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1)
++ * multipass->hrsz + 16) >> 8) + 7;
++ } else {
++ hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1)
++ * multipass->hrsz + 32) >> 8) + 7;
++ }
++ if (multipass->vrsz <= 512) {
++ vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1)
++ * multipass->vrsz + 16) >> 8) + 4;
++ } else {
++ vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1)
++ * multipass->vrsz + 32) >> 8) + 7;
++ }
++ rsz_conf_chan->register_config.rsz_in_size = hsize;
++
++ rsz_conf_chan->register_config.rsz_in_size |=
++ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
++ & ISPRSZ_IN_SIZE_VERT_MASK);
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ if (multipass->num_htap) {
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] =
++ (multipass->tap4filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK);
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] |=
++ ((multipass->tap4filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_HFILT10_COEF1_SHIFT)
++ & ISPRSZ_HFILT10_COEF1_MASK);
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] =
++ (multipass->tap7filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK);
++
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] |=
++ ((multipass->tap7filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_HFILT10_COEF1_SHIFT)
++ & ISPRSZ_HFILT10_COEF1_MASK);
++ }
++
++ if (multipass->num_vtap) {
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] =
++ (multipass->tap4filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK);
++
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] |=
++ ((multipass->tap4filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_VFILT10_COEF1_SHIFT) &
++ ISPRSZ_VFILT10_COEF1_MASK);
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] =
++ (multipass->tap7filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK);
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] |=
++ ((multipass->tap7filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_VFILT10_COEF1_SHIFT)
++ & ISPRSZ_VFILT10_COEF1_MASK);
++ }
++ }
++}
++
++/**
++ * rsz_get_params - Gets the parameter values
++ * @params: Structure containing the Resizer Wrapper parameters
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Used to get the Resizer hardware settings associated with the
++ * current logical channel represented by fd.
++ **/
++static int rsz_get_params(struct rsz_params *params,
++ struct channel_config *rsz_conf_chan)
++{
++ int coeffcounter;
++
++ if (rsz_conf_chan->config_state) {
++ dev_err(rsz_device, "state not configured\n");
++ return -EINVAL;
++ }
++
++ params->in_hsize = rsz_conf_chan->register_config.rsz_in_size
++ & ISPRSZ_IN_SIZE_HORZ_MASK;
++ params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size
++ & ISPRSZ_IN_SIZE_VERT_MASK)
++ >> ISPRSZ_IN_SIZE_VERT_SHIFT;
++
++ params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff
++ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
++
++ params->out_hsize = rsz_conf_chan->register_config.rsz_out_size
++ & ISPRSZ_OUT_SIZE_HORZ_MASK;
++
++ params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size
++ & ISPRSZ_OUT_SIZE_VERT_MASK)
++ >> ISPRSZ_OUT_SIZE_VERT_SHIFT;
++
++ params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff
++ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
++
++ params->cbilin = (rsz_conf_chan->register_config.rsz_cnt
++ & SET_BIT_CBLIN) >> SET_BIT_CBLIN;
++
++ params->inptyp = (rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_INPTYP_MASK)
++ >> SET_BIT_INPTYP;
++ params->horz_starting_pixel = ((rsz_conf_chan->register_config.
++ rsz_in_start
++ & ISPRSZ_IN_START_HORZ_ST_MASK));
++ params->vert_starting_pixel = ((rsz_conf_chan->register_config.
++ rsz_in_start
++ & ISPRSZ_IN_START_VERT_ST_MASK)
++ >> ISPRSZ_IN_START_VERT_ST_SHIFT);
++
++ params->hstph = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_HSTPH_MASK
++ >> ISPRSZ_CNT_HSTPH_SHIFT));
++ params->vstph = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_VSTPH_MASK
++ >> ISPRSZ_CNT_VSTPH_SHIFT));
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ params->tap4filt_coeffs[2 * coeffcounter] =
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK;
++
++ params->tap4filt_coeffs[2 * coeffcounter + 1] =
++ (rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter]
++ & ISPRSZ_HFILT10_COEF1_MASK)
++ >> ISPRSZ_HFILT10_COEF1_SHIFT;
++
++ params->tap7filt_coeffs[2 * coeffcounter] =
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK;
++
++ params->tap7filt_coeffs[2 * coeffcounter + 1] =
++ (rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter]
++ & ISPRSZ_VFILT10_COEF1_MASK)
++ >> ISPRSZ_VFILT10_COEF1_SHIFT;
++
++ }
++
++ params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_ALGO_MASK)
++ >> ISPRSZ_YENH_ALGO_SHIFT;
++
++ params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_CORE_MASK;
++
++ params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_GAIN_MASK)
++ >> ISPRSZ_YENH_GAIN_SHIFT;
++
++ params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_SLOP_MASK)
++ >> ISPRSZ_YENH_SLOP_SHIFT;
++
++ params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_PIXFMT_MASK)
++ >> SET_BIT_YCPOS);
++
++ if (params->pix_fmt)
++ params->pix_fmt = RSZ_PIX_FMT_UYVY;
++ else
++ params->pix_fmt = RSZ_PIX_FMT_YUYV;
++
++ return 0;
++}
++
++/**
++ * rsz_calculate_crop - Calculate Crop values
++ * @rsz_conf_chan: Structure containing channel configuration
++ * @cropsize: Structure containing crop parameters
++ *
++ * Calculate Crop values
++ **/
++static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
++ struct rsz_cropsize *cropsize)
++{
++ int luma_enable;
++
++ cropsize->hcrop = 0;
++ cropsize->vcrop = 0;
++
++ luma_enable = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_ALGO_MASK)
++ >> ISPRSZ_YENH_ALGO_SHIFT;
++
++ if (luma_enable)
++ cropsize->hcrop += 2;
++}
++
++/**
++ * rsz_vbq_release - Videobuffer queue release
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @vb: Structure containing the videobuffer used for resizer processing.
++ **/
++static void rsz_vbq_release(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ int i;
++ struct rsz_fh *fh = q->priv_data;
++
++ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
++ struct videobuf_dmabuf *dma = NULL;
++ if (!q->bufs[i])
++ continue;
++ if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
++ continue;
++ dma = videobuf_to_dma(q->bufs[i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ }
++
++ ispmmu_unmap(fh->isp_addr_read);
++ ispmmu_unmap(fh->isp_addr_write);
++ fh->isp_addr_read = 0;
++ fh->isp_addr_write = 0;
++ spin_lock(&fh->vbq_lock);
++ vb->state = VIDEOBUF_NEEDS_INIT;
++ spin_unlock(&fh->vbq_lock);
++
++}
++
++/**
++ * rsz_vbq_setup - Sets up the videobuffer size and validates count.
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @cnt: Number of buffers requested
++ * @size: Size in bytes of the buffer used for previewing
++ *
++ * Always returns 0.
++ **/
++static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt,
++ unsigned int *size)
++{
++ struct rsz_fh *fh = q->priv_data;
++ struct rsz_mult *multipass = fh->multipass;
++ u32 insize, outsize;
++
++ spin_lock(&fh->vbq_lock);
++ if (*cnt <= 0)
++ *cnt = VIDEO_MAX_FRAME;
++
++ if (*cnt > VIDEO_MAX_FRAME)
++ *cnt = VIDEO_MAX_FRAME;
++
++ outsize = multipass->out_pitch * multipass->out_vsize;
++ insize = multipass->in_pitch * multipass->in_vsize;
++ if (*cnt == 1 && (outsize > insize)) {
++ dev_err(rsz_device, "2 buffers are required for Upscaling "
++ "mode\n");
++ goto err_einval;
++ }
++ if (!fh->params->in_hsize || !fh->params->in_vsize) {
++ dev_err(rsz_device, "Can't setup buffer size\n");
++ goto err_einval;
++ } else {
++ if (outsize > insize)
++ *size = outsize;
++ else
++ *size = insize;
++
++ fh->rsz_bufsize = *size;
++ }
++ spin_unlock(&fh->vbq_lock);
++
++ return 0;
++err_einval:
++ spin_unlock(&fh->vbq_lock);
++ return -EINVAL;
++}
++
++/**
++ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @vb: Structure containing the videobuffer used for resizer processing.
++ * @field: Type of field to set in videobuffer device.
++ *
++ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
++ * -EIO if the ISP MMU mapping fails
++ **/
++static int rsz_vbq_prepare(struct videobuf_queue *q,
++ struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ struct rsz_fh *fh = q->priv_data;
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_mult *multipass = fh->multipass;
++ int err = 0;
++ unsigned int isp_addr, insize, outsize;
++ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
++
++ spin_lock(&fh->vbq_lock);
++ if (vb->baddr) {
++ vb->size = fh->rsz_bufsize;
++ vb->bsize = fh->rsz_bufsize;
++ } else {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "No user buffer allocated\n");
++ goto out;
++ }
++ if (vb->i) {
++ vb->width = fh->params->out_hsize;
++ vb->height = fh->params->out_vsize;
++ } else {
++ vb->width = fh->params->in_hsize;
++ vb->height = fh->params->in_vsize;
++ }
++
++ vb->field = field;
++ spin_unlock(&fh->vbq_lock);
++
++ if (vb->state == VIDEOBUF_NEEDS_INIT) {
++ err = videobuf_iolock(q, vb, NULL);
++ if (!err) {
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ if (!isp_addr)
++ err = -EIO;
++ else {
++ if (vb->i) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ fh->isp_addr_write = isp_addr;
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd
++ = isp_addr;
++ rsz_conf_chan->input_buf_index = vb->i;
++ outsize = multipass->out_pitch *
++ multipass->out_vsize;
++ insize = multipass->in_pitch *
++ multipass->in_vsize;
++ if (outsize < insize) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->
++ output_buf_index =
++ vb->i;
++ }
++
++ fh->isp_addr_read = isp_addr;
++ }
++ }
++ }
++
++ }
++
++ if (!err) {
++ spin_lock(&fh->vbq_lock);
++ vb->state = VIDEOBUF_PREPARED;
++ spin_unlock(&fh->vbq_lock);
++ flush_cache_user_range(NULL, vb->baddr, (vb->baddr
++ + vb->bsize));
++ } else
++ rsz_vbq_release(q, vb);
++
++out:
++ return err;
++}
++
++static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
++{
++ return;
++}
++
++/**
++ * rsz_open - Initializes and opens the Resizer Wrapper
++ * @inode: Inode structure associated with the Resizer Wrapper
++ * @filp: File structure associated with the Resizer Wrapper
++ *
++ * Returns 0 if successful, -EBUSY if its already opened or the ISP module is
++ * not available, or -ENOMEM if its unable to allocate the device in kernel
++ * space memory.
++ **/
++static int rsz_open(struct inode *inode, struct file *filp)
++{
++ int ret = 0;
++ struct channel_config *rsz_conf_chan;
++ struct rsz_fh *fh;
++ struct device_params *device = device_config;
++ struct rsz_params *params;
++ struct rsz_mult *multipass;
++
++ if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) {
++ printk(KERN_DEBUG "omap-resizer: Device is opened in "
++ "non blocking mode\n");
++ } else {
++ printk(KERN_DEBUG "omap-resizer: Device is opened in blocking "
++ "mode\n");
++ }
++ fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL);
++ if (NULL == fh)
++ return -ENOMEM;
++
++ isp_get();
++
++ rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL);
++ if (rsz_conf_chan == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to config");
++ ret = -ENOMEM;
++ goto err_enomem0;
++ }
++ params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL);
++ if (params == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to params");
++ ret = -ENOMEM;
++ goto err_enomem1;
++ }
++ multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL);
++ if (multipass == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to multipass");
++ ret = -ENOMEM;
++ goto err_enomem2;
++ }
++
++ fh->multipass = multipass;
++ fh->params = params;
++ fh->config = rsz_conf_chan;
++
++ if (mutex_lock_interruptible(&device->reszwrap_mutex)) {
++ ret = -EINTR;
++ goto err_enomem2;
++ }
++ device->opened++;
++ mutex_unlock(&device->reszwrap_mutex);
++
++ rsz_conf_chan->config_state = STATE_NOT_CONFIGURED;
++ rsz_conf_chan->status = CHANNEL_FREE;
++
++ filp->private_data = fh;
++ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ fh->device = device;
++
++ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
++ &fh->vbq_lock, fh->type,
++ V4L2_FIELD_NONE,
++ sizeof(struct videobuf_buffer), fh);
++
++ spin_lock_init(&fh->vbq_lock);
++ mutex_init(&rsz_conf_chan->chanprotection_mutex);
++
++ return 0;
++err_enomem2:
++ kfree(params);
++err_enomem1:
++ kfree(rsz_conf_chan);
++err_enomem0:
++ kfree(fh);
++ return ret;
++}
++
++/**
++ * rsz_release - Releases Resizer Wrapper and frees up allocated memory
++ * @inode: Inode structure associated with the Resizer Wrapper
++ * @filp: File structure associated with the Resizer Wrapper
++ *
++ * Returns 0 if successful, or -EBUSY if channel is being used.
++ **/
++static int rsz_release(struct inode *inode, struct file *filp)
++{
++ u32 timeout = 0;
++ struct rsz_fh *fh = filp->private_data;
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_params *params = fh->params;
++ struct rsz_mult *multipass = fh->multipass;
++ struct videobuf_queue *q = &fh->vbq;
++
++ while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) {
++ timeout++;
++ schedule();
++ }
++ if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
++ return -EINTR;
++ device_config->opened--;
++ mutex_unlock(&device_config->reszwrap_mutex);
++ /* This will Free memory allocated to the buffers,
++ * and flushes the queue
++ */
++ videobuf_queue_cancel(q);
++ fh->params = NULL;
++ fh->config = NULL;
++
++ fh->rsz_bufsize = 0;
++ filp->private_data = NULL;
++
++ kfree(rsz_conf_chan);
++ kfree(params);
++ kfree(multipass);
++ kfree(fh);
++
++ isp_put();
++
++ return 0;
++}
++
++/**
++ * rsz_mmap - Memory maps the Resizer Wrapper module.
++ * @file: File structure associated with the Resizer Wrapper
++ * @vma: Virtual memory area structure.
++ *
++ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
++ * function.
++ **/
++static int rsz_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct rsz_fh *fh = file->private_data;
++
++ return videobuf_mmap_mapper(&fh->vbq, vma);
++}
++
++/**
++ * rsz_ioctl - I/O control function for Resizer Wrapper
++ * @inode: Inode structure associated with the Resizer Wrapper.
++ * @file: File structure associated with the Resizer Wrapper.
++ * @cmd: Type of command to execute.
++ * @arg: Argument to send to requested command.
++ *
++ * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command
++ * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user()
++ * fails, -EINVAL if parameter validation fails or parameter structure is not
++ * present.
++ **/
++static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ int ret = 0;
++ struct rsz_fh *fh = file->private_data;
++ struct device_params *device = fh->device;
++ struct channel_config *rsz_conf_chan = fh->config;
++
++ if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE)
++ || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) {
++ dev_err(rsz_device, "Bad command value \n");
++ return -1;
++ }
++
++ if (_IOC_DIR(cmd) & _IOC_READ)
++ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
++ else if (_IOC_DIR(cmd) & _IOC_WRITE)
++ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
++
++ if (ret) {
++ dev_err(rsz_device, "Access denied\n");
++ return -1;
++ }
++
++ switch (cmd) {
++ case RSZ_REQBUF:
++ {
++ struct v4l2_requestbuffers req_buf;
++ if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg,
++ sizeof(struct v4l2_requestbuffers))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_QUERYBUF:
++ {
++ struct v4l2_buffer buf;
++ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
++ sizeof(struct v4l2_buffer))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_querybuf(&fh->vbq, (void *)&buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ if (copy_to_user((struct v4l2_buffer *)arg, &buf,
++ sizeof(struct v4l2_buffer)))
++ return -EFAULT;
++ break;
++ }
++ case RSZ_QUEUEBUF:
++ {
++ struct v4l2_buffer buf;
++ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
++ sizeof(struct v4l2_buffer))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_qbuf(&fh->vbq, (void *)&buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_S_PARAM:
++ {
++ struct rsz_params *params = fh->params;
++ if (copy_from_user(params, (struct rsz_params *)arg,
++ sizeof(struct rsz_params))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_G_PARAM:
++ ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan);
++ break;
++
++ case RSZ_G_STATUS:
++ {
++ struct rsz_status *status;
++ status = (struct rsz_status *)arg;
++ status->chan_busy = rsz_conf_chan->status;
++ status->hw_busy = ispresizer_busy();
++ status->src = INPUT_RAM;
++ break;
++ }
++ case RSZ_RESIZE:
++ if (file->f_flags & O_NONBLOCK) {
++ if (ispresizer_busy())
++ return -EBUSY;
++ else {
++ if (!mutex_trylock(&device->reszwrap_mutex))
++ return -EBUSY;
++ }
++ } else {
++ if (mutex_lock_interruptible(&device->reszwrap_mutex))
++ return -EINTR;
++ }
++ ret = rsz_start((int *)arg, fh);
++ mutex_unlock(&device->reszwrap_mutex);
++ break;
++ case RSZ_GET_CROPSIZE:
++ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
++ break;
++
++ default:
++ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
++ return -EINVAL;
++ }
++
++ return (long)ret;
++}
++
++static struct file_operations rsz_fops = {
++ .owner = THIS_MODULE,
++ .open = rsz_open,
++ .release = rsz_release,
++ .mmap = rsz_mmap,
++ .unlocked_ioctl = rsz_unlocked_ioctl,
++};
++
++/**
++ * rsz_isr - Interrupt Service Routine for Resizer wrapper
++ * @status: ISP IRQ0STATUS register value
++ * @arg1: Currently not used
++ * @arg2: Currently not used
++ *
++ * Interrupt Service Routine for Resizer wrapper
++ **/
++static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
++{
++
++ if ((status & RESZ_DONE) != RESZ_DONE)
++ return;
++
++ complete(&(device_config->compl_isr));
++
++}
++
++/**
++ * resizer_platform_release - Acts when Reference count is zero
++ * @device: Structure containing ISP resizer wrapper global information
++ *
++ * This is called when the reference count goes to zero.
++ **/
++static void resizer_platform_release(struct device *device)
++{
++}
++
++/**
++ * resizer_probe - Checks for device presence
++ * @device: Structure containing details of the current device.
++ *
++ * Always returns 0.
++ **/
++static int __init resizer_probe(struct platform_device *device)
++{
++ return 0;
++}
++
++/**
++ * resizer_remove - Handles the removal of the driver
++ * @omap_resizer_device: Structure containing details of the current device.
++ *
++ * Always returns 0.
++ **/
++static int resizer_remove(struct platform_device *omap_resizer_device)
++{
++ return 0;
++}
++
++static struct class *rsz_class;
++static struct cdev c_dev;
++static dev_t dev;
++static struct platform_device omap_resizer_device = {
++ .name = OMAP_REZR_NAME,
++ .id = 2,
++ .dev = {
++ .release = resizer_platform_release,}
++};
++
++static struct platform_driver omap_resizer_driver = {
++ .probe = resizer_probe,
++ .remove = resizer_remove,
++ .driver = {
++ .bus = &platform_bus_type,
++ .name = OMAP_REZR_NAME,
++ },
++};
++
++/**
++ * omap_rsz_init - Initialization of Resizer Wrapper
++ *
++ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
++ * could not register the wrapper as a character device, or other errors if the
++ * device or driver can't register.
++ **/
++static int __init omap_rsz_init(void)
++{
++ int ret = 0;
++ struct device_params *device;
++ device = kzalloc(sizeof(struct device_params), GFP_KERNEL);
++ if (!device) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate "
++ "memory\n");
++ return -ENOMEM;
++ }
++
++ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
++ if (ret < 0) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
++ "Could not allocate region "
++ "for character device\n");
++ kfree(device);
++ return -ENODEV;
++ }
++
++ /* Register the driver in the kernel */
++ /* Initialize of character device */
++ cdev_init(&c_dev, &rsz_fops);
++ c_dev.owner = THIS_MODULE;
++ c_dev.ops = &rsz_fops;
++
++ /* Addding character device */
++ ret = cdev_add(&c_dev, dev, 1);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": Error adding "
++ "device - %d\n", ret);
++ goto fail2;
++ }
++ rsz_major = MAJOR(dev);
++
++ /* register driver as a platform driver */
++ ret = platform_driver_register(&omap_resizer_driver);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to register platform driver!\n");
++ goto fail3;
++ }
++
++ /* Register the drive as a platform device */
++ ret = platform_device_register(&omap_resizer_device);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to register platform device!\n");
++ goto fail4;
++ }
++
++ rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME);
++ if (!rsz_class) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to create class!\n");
++ goto fail5;
++ }
++
++ /* make entry in the devfs */
++ rsz_device = device_create(rsz_class, rsz_device,
++ MKDEV(rsz_major, 0), NULL,
++ OMAP_REZR_NAME);
++ dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n");
++ device->opened = 0;
++
++ device->vbq_ops.buf_setup = rsz_vbq_setup;
++ device->vbq_ops.buf_prepare = rsz_vbq_prepare;
++ device->vbq_ops.buf_release = rsz_vbq_release;
++ device->vbq_ops.buf_queue = rsz_vbq_queue;
++ init_completion(&device->compl_isr);
++ mutex_init(&device->reszwrap_mutex);
++
++ device_config = device;
++ return 0;
++
++fail5:
++ platform_device_unregister(&omap_resizer_device);
++fail4:
++ platform_driver_unregister(&omap_resizer_driver);
++fail3:
++ cdev_del(&c_dev);
++fail2:
++ unregister_chrdev_region(dev, 1);
++ kfree(device);
++ return ret;
++}
++
++/**
++ * omap_rsz_exit - Close of Resizer Wrapper
++ **/
++void __exit omap_rsz_exit(void)
++{
++ device_destroy(rsz_class, dev);
++ class_destroy(rsz_class);
++ platform_device_unregister(&omap_resizer_device);
++ platform_driver_unregister(&omap_resizer_driver);
++ cdev_del(&c_dev);
++ unregister_chrdev_region(dev, 1);
++ kfree(device_config);
++}
++
++module_init(omap_rsz_init)
++module_exit(omap_rsz_exit)
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_DESCRIPTION("OMAP ISP Resizer");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
+new file mode 100644
+index 0000000..5ac0c88
+--- /dev/null
++++ b/include/linux/omap_resizer.h
+@@ -0,0 +1,136 @@
++/*
++ * drivers/media/video/isp/omap_resizer.h
++ *
++ * Include file for Resizer module wrapper in TI's OMAP3430 ISP
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_RESIZER_H
++#define OMAP_RESIZER_H
++
++#include <linux/types.h>
++
++/* ioctls definition */
++#define RSZ_IOC_BASE 'R'
++#define RSZ_IOC_MAXNR 8
++
++/*Ioctl options which are to be passed while calling the ioctl*/
++#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
++ struct v4l2_requestbuffers)
++#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer)
++#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params)
++#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params)
++#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32)
++#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
++#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
++#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
++
++#define RSZ_INTYPE_YCBCR422_16BIT 0
++#define RSZ_INTYPE_PLANAR_8BIT 1
++#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */
++#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */
++
++enum config_done {
++ STATE_CONFIGURED, /* Resizer driver configured
++ * by application.
++ */
++ STATE_NOT_CONFIGURED /* Resizer driver not
++ * configured by application.
++ */
++};
++
++/* Structure Definitions */
++
++/* used to luma enhancement options */
++
++struct rsz_yenh {
++ __s32 type; /* represents luma enable or
++ * disable.
++ */
++ __u8 gain; /* represents gain. */
++ __u8 slop; /* represents slop. */
++ __u8 core; /* Represents core value. */
++};
++
++/* Conatins all the parameters for resizing. This structure
++ * is used to configure resiser parameters
++ */
++struct rsz_params {
++ __s32 in_hsize; /* input frame horizontal
++ * size.
++ */
++ __s32 in_vsize; /* input frame vertical size */
++ __s32 in_pitch; /* offset between two rows of
++ * input frame.
++ */
++ __s32 inptyp; /* for determining 16 bit or
++ * 8 bit data.
++ */
++ __s32 vert_starting_pixel; /* for specifying vertical
++ * starting pixel in input.
++ */
++ __s32 horz_starting_pixel; /* for specyfing horizontal
++ * starting pixel in input.
++ */
++ __s32 cbilin; /* # defined, filter with luma
++ * or bi-linear interpolation.
++ */
++ __s32 pix_fmt; /* # defined, UYVY or YUYV */
++ __s32 out_hsize; /* output frame horizontal
++ * size.
++ */
++ __s32 out_vsize; /* output frame vertical
++ * size.
++ */
++ __s32 out_pitch; /* offset between two rows of
++ * output frame.
++ */
++ __s32 hstph; /* for specifying horizontal
++ * starting phase.
++ */
++ __s32 vstph; /* for specifying vertical
++ * starting phase.
++ */
++ __u16 tap4filt_coeffs[32]; /* horizontal filter
++ * coefficients.
++ */
++ __u16 tap7filt_coeffs[32]; /* vertical filter
++ * coefficients.
++ */
++ struct rsz_yenh yenh_params;
++};
++
++/* Contains the status of hardware and channel */
++struct rsz_status {
++ __s32 chan_busy; /* 1: channel is busy,
++ * 0: channel is not busy
++ */
++ __s32 hw_busy; /* 1: hardware is busy,
++ * 0: hardware is not busy
++ */
++ __s32 src; /* # defined, can be either
++ * SD-RAM or CCDC/PREVIEWER
++ */
++};
++
++/* Passed by application for getting crop size */
++struct rsz_cropsize {
++ __u32 hcrop; /* Number of pixels per line
++ * cropped in output image.
++ */
++
++ __u32 vcrop; /* Number of lines cropped
++ * in output image.
++ */
++};
++
++#endif
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
new file mode 100644
index 0000000000..2c3023643e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
@@ -0,0 +1,729 @@
+From ad3bbadb7fc39a946dfd0cdac19e2ec8647b2c2c Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:20:27 +0530
+Subject: [PATCH 24/26] OMAP3-Resizer: V4L2-buf layer issues fixed
+
+V4L2-Buffer layer issues fixed under this commit.
+This patch is same as available with PSP1.0.2 release
+
+The discussion is initiated on this with V4L2 mailing list.
+
+Please note that this patch is not being tested.
+---
+ drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++--------
+ include/linux/omap_resizer.h | 3 +-
+ 2 files changed, 321 insertions(+), 99 deletions(-)
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+index 54bc425..8059c70 100644
+--- a/drivers/media/video/isp/omap_resizer.c
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -28,6 +28,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/uaccess.h>
++#include <linux/pci.h>
+ #include <media/v4l2-dev.h>
+ #include <asm/cacheflush.h>
+
+@@ -76,6 +77,10 @@
+ #define MAX_COEF_COUNTER 16
+ #define COEFF_ADDRESS_OFFSET 0x04
+
++#define RSZ_DEF_REQ_EXP 0xE /* Default read operation expand
++ * for the Resizer driver; value
++ * taken from Davinci.
++ */
+ /* Global structure which contains information about number of channels
+ and protection variables */
+ struct device_params {
+@@ -85,6 +90,7 @@ struct device_params {
+ struct mutex reszwrap_mutex; /* Semaphore for array */
+
+ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
++ unsigned long extra_page_addr;
+ };
+
+ /* Register mapped structure which contains the every register
+@@ -126,6 +132,9 @@ struct resizer_config {
+ u32 rsz_yehn; /* yehn(luma)register mapping
+ * variable.
+ */
++ u32 sdr_req_exp; /* Configuration for Non
++ * real time read expand
++ */
+ };
+
+ struct rsz_mult {
+@@ -179,6 +188,7 @@ struct channel_config {
+ * channel is busy or not
+ */
+ struct mutex chanprotection_mutex;
++ int buf_address[VIDEO_MAX_FRAME];
+ enum config_done config_state;
+ u8 input_buf_index;
+ u8 output_buf_index;
+@@ -200,8 +210,6 @@ struct rsz_fh {
+ struct videobuf_queue vbq;
+ struct device_params *device;
+
+- dma_addr_t isp_addr_read; /* Input/Output address */
+- dma_addr_t isp_addr_write; /* Input/Output address */
+ u32 rsz_bufsize; /* channel specific buffersize
+ */
+ };
+@@ -227,6 +235,10 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
+ static void rsz_config_ratio(struct rsz_mult *multipass,
+ struct channel_config *rsz_conf_chan);
+
++static void inline rsz_set_exp(unsigned int exp)
++{
++ omap_writel(((exp & 0x3FF) << 10), OMAP3ISP_SBL_REG(0xF8));
++}
+ /**
+ * rsz_hardware_setup - Sets hardware configuration registers
+ * @rsz_conf_chan: Structure containing channel configuration
+@@ -271,12 +283,15 @@ static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
+ + coeffoffset));
+ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
+ }
++ /* Configure the read expand register */
++ rsz_set_exp(rsz_conf_chan->register_config.sdr_req_exp);
+ }
+
+ /**
+ * rsz_start - Enables Resizer Wrapper
+ * @arg: Currently not used.
+- * @device: Structure containing ISP resizer wrapper global information
++ * @fh: File structure containing ISP resizer information specific to
++ * channel opened.
+ *
+ * Submits a resizing task specified by the rsz_resize structure. The call can
+ * either be blocked until the task is completed or returned immediately based
+@@ -292,12 +307,18 @@ int rsz_start(int *arg, struct rsz_fh *fh)
+ struct channel_config *rsz_conf_chan = fh->config;
+ struct rsz_mult *multipass = fh->multipass;
+ struct videobuf_queue *q = &fh->vbq;
++ struct videobuf_buffer *buf;
+ int ret;
+
+ if (rsz_conf_chan->config_state) {
+ dev_err(rsz_device, "State not configured \n");
+ goto err_einval;
+ }
++ if (!rsz_conf_chan->register_config.rsz_sdr_inadd ||
++ !rsz_conf_chan->register_config.rsz_sdr_outadd) {
++ dev_err(rsz_device, "address is null\n");
++ goto err_einval;
++ }
+
+ rsz_conf_chan->status = CHANNEL_BUSY;
+
+@@ -325,33 +346,22 @@ mult:
+ goto mult;
+ }
+
+- if (fh->isp_addr_read) {
+- ispmmu_unmap(fh->isp_addr_read);
+- fh->isp_addr_read = 0;
+- }
+- if (fh->isp_addr_write) {
+- ispmmu_unmap(fh->isp_addr_write);
+- fh->isp_addr_write = 0;
+- }
+-
+ rsz_conf_chan->status = CHANNEL_FREE;
+- q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
+- q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
+ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
+ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
+
+- /* Unmap and free the DMA memory allocated for buffers */
+- videobuf_dma_unmap(q, videobuf_to_dma(
+- q->bufs[rsz_conf_chan->input_buf_index]));
+- videobuf_dma_unmap(q, videobuf_to_dma(
+- q->bufs[rsz_conf_chan->output_buf_index]));
+- videobuf_dma_free(videobuf_to_dma(
+- q->bufs[rsz_conf_chan->input_buf_index]));
+- videobuf_dma_free(videobuf_to_dma(
+- q->bufs[rsz_conf_chan->output_buf_index]));
+-
+ isp_unset_callback(CBK_RESZ_DONE);
+
++ /* Empty the Videobuf queue which was filled during the qbuf */
++ buf = q->bufs[rsz_conf_chan->input_buf_index];
++ buf->state = VIDEOBUF_IDLE;
++ list_del(&buf->stream);
++ if (rsz_conf_chan->input_buf_index != rsz_conf_chan->output_buf_index) {
++ buf = q->bufs[rsz_conf_chan->output_buf_index];
++ buf->state = VIDEOBUF_IDLE;
++ list_del(&buf->stream);
++ }
++
+ return 0;
+ err_einval:
+ return -EINVAL;
+@@ -359,6 +369,8 @@ err_einval:
+
+ /**
+ * rsz_set_multipass - Set resizer multipass
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Returns always 0
+@@ -384,6 +396,8 @@ static int rsz_set_multipass(struct rsz_mult *multipass,
+
+ /**
+ * rsz_copy_data - Copy data
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @params: Structure containing the Resizer Wrapper parameters
+ *
+ * Copy data
+@@ -413,6 +427,8 @@ static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
+
+ /**
+ * rsz_set_params - Set parameters for resizer wrapper
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @params: Structure containing the Resizer Wrapper parameters
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+@@ -524,6 +540,8 @@ static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
+ }
+
+ rsz_config_ratio(multipass, rsz_conf_chan);
++ /* Default value for read expand:Taken from Davinci */
++ rsz_conf_chan->register_config.sdr_req_exp = RSZ_DEF_REQ_EXP;
+
+ rsz_conf_chan->config_state = STATE_CONFIGURED;
+
+@@ -534,6 +552,8 @@ err_einval:
+
+ /**
+ * rsz_set_ratio - Set ratio
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
+@@ -548,7 +568,8 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
+
+ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
+ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
+- dev_err(rsz_device, "Invalid output size!");
++ dev_err(rsz_device, "Invalid output size! - %d", \
++ multipass->out_hsize);
+ goto err_einval;
+ }
+ if (multipass->cbilin) {
+@@ -758,6 +779,8 @@ err_einval:
+
+ /**
+ * rsz_config_ratio - Configure ratio
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Configure ratio
+@@ -789,6 +812,20 @@ static void rsz_config_ratio(struct rsz_mult *multipass,
+ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
+ & ISPRSZ_IN_SIZE_VERT_MASK);
+
++ /* This is another workaround for the ISP-MMU translation fault.
++ For the parameters whose image size comes exactly to PAGE_SIZE
++ generates ISP-MMU translation fault. The root-cause is the equation
++ input width = (32*sph + (ow - 1)*hrsz + 16) >> 8 + 7
++ = (64*sph + (ow - 1)*hrsz + 32) >> 8 + 7
++ input height = (32*spv + (oh - 1)*vrsz + 16) >> 8 + 4
++ = (64*spv + (oh - 1)*vrsz + 32) >> 8 + 7
++
++ we are adjusting the input width to suit for Resizer module,
++ application should use this configuration henceforth.
++ */
++ multipass->in_hsize = hsize;
++ multipass->in_vsize = vsize;
++
+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
+ coeffcounter++) {
+ if (multipass->num_htap) {
+@@ -990,24 +1027,15 @@ static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
+ static void rsz_vbq_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+ {
+- int i;
+ struct rsz_fh *fh = q->priv_data;
++ struct videobuf_dmabuf *dma = NULL;
+
+- for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+- struct videobuf_dmabuf *dma = NULL;
+- if (!q->bufs[i])
+- continue;
+- if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
+- continue;
+- dma = videobuf_to_dma(q->bufs[i]);
+- videobuf_dma_unmap(q, dma);
+- videobuf_dma_free(dma);
+- }
++ dma = videobuf_to_dma(q->bufs[vb->i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ ispmmu_unmap(fh->config->buf_address[vb->i]);
++ fh->config->buf_address[vb->i] = 0;
+
+- ispmmu_unmap(fh->isp_addr_read);
+- ispmmu_unmap(fh->isp_addr_write);
+- fh->isp_addr_read = 0;
+- fh->isp_addr_write = 0;
+ spin_lock(&fh->vbq_lock);
+ vb->state = VIDEOBUF_NEEDS_INIT;
+ spin_unlock(&fh->vbq_lock);
+@@ -1062,7 +1090,105 @@ err_einval:
+ spin_unlock(&fh->vbq_lock);
+ return -EINVAL;
+ }
++/*
++ * This function is work around for the videobuf_iolock API,
++ * for User memory allocated with ioremap (VM_IO flag) the API
++ * get_user_pages fails.
++ *
++ * To fulfill this requirement, we have completely ignored VM layer of
++ * Linux, and configuring the ISP MMU with physical address.
++ */
++static int omap_videobuf_dma_init_user(struct videobuf_buffer *vb,
++ unsigned long physp, unsigned long asize)
++{
++ struct videobuf_dmabuf *dma;
++ struct scatterlist *sglist;
++ unsigned long data, first, last;
++ int len, i = 0;
++
++ dma = videobuf_to_dma(vb);
++ data = vb->baddr;
++
++ first = (data & PAGE_MASK) >> PAGE_SHIFT;
++ last = ((data+asize-1) & PAGE_MASK) >> PAGE_SHIFT;
++ dma->offset = data & ~PAGE_MASK;
++ dma->nr_pages = last-first+1;
++
++ dma->direction = PCI_DMA_FROMDEVICE;
++ /*
++ * Allocate array of sglen + 1, to add entry of extra page
++ * for input buffer. Driver always uses 0th buffer as input buffer.
++ */
++ len = dma->nr_pages + (vb->i ? 0 : 1);
++ sglist = kcalloc(len, sizeof(*sglist), GFP_KERNEL);
++ if (NULL == sglist)
++ return -ENOMEM;
++
++ sglist[0].offset = 0;
++ sglist[0].length = PAGE_SIZE - dma->offset;
++ sglist[0].dma_address = (dma_addr_t)physp;
++ physp += sglist[0].length;
++ /*
++ * Iterate in a loop for the number of pages
++ */
++ for (i = 1; i < (len - (vb->i ? 0 : 1)); i++) {
++ sglist[i].offset = 0;
++ sglist[i].length = PAGE_SIZE;
++ sglist[i].dma_address = (dma_addr_t)physp;
++ physp += PAGE_SIZE;
++ }
++ if (0 == vb->i) {
++ sglist[i].offset = 0;
++ sglist[i].length = PAGE_SIZE;
++ sglist[i].dma_address =
++ (dma_addr_t)device_config->extra_page_addr;
++ }
++ dma->sglist = sglist;
++ dma->sglen = len;
++ return 0;
++
++ }
++/*
++ * This function is workaround for the issue, where ISP-MMU generated
++ * translation fault for specific params whose size is aligned to PAGE_SIZE.
++
++ * As a workaround we are padding one extra page for input buffer. This page
++ * we are allocating during init time and will not be released through-out
++ * life time of resizer driver. Please note that Resizer module only reads
++ * from this extra page.
++ */
++int omap_create_sg(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
++{
++ struct scatterlist *sglist;
++ int sglen;
+
++ sglen = dma->sglen;
++ sglist = kcalloc(sglen + 1, sizeof(*sglist), GFP_KERNEL);
++ if (NULL == sglist)
++ return -ENOMEM;
++ /*
++ * Copy the sglist locally
++ */
++ memcpy(sglist, dma->sglist, sglen * sizeof(*sglist));
++ /*
++ * Release the old sglist, since we already copied it locally
++ */
++ videobuf_dma_unmap(q, dma);
++ /*
++ * Add extra entry to sglist to work with specific params, whose
++ * buffer address alined to PAGE_SIZE.
++ */
++ sglist[sglen].offset = 0;
++ sglist[sglen].length = PAGE_SIZE;
++ sglist[sglen].dma_address = (dma_addr_t)device_config->extra_page_addr;
++ sglen++;
++ /*
++ * Save the sglist for mapping to ISP-MMU space
++ */
++ dma->sglist = sglist;
++ dma->sglen = sglen;
++ return 0;
++}
+ /**
+ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
+ * @q: Structure containing the videobuffer queue file handle, and device
+@@ -1079,19 +1205,24 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+ {
+ struct rsz_fh *fh = q->priv_data;
+ struct channel_config *rsz_conf_chan = fh->config;
+- struct rsz_mult *multipass = fh->multipass;
+ int err = 0;
+ unsigned int isp_addr, insize, outsize;
+- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+-
++ struct rsz_mult *multipass = fh->multipass;
+ spin_lock(&fh->vbq_lock);
+ if (vb->baddr) {
++ /* Check for 32 byte alignement */
++ if (vb->baddr != (vb->baddr & ~0x1F)) {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "Buffer address should be aligned \
++ to 32 byte\n");
++ return -EINVAL;
++ }
+ vb->size = fh->rsz_bufsize;
+ vb->bsize = fh->rsz_bufsize;
+ } else {
+ spin_unlock(&fh->vbq_lock);
+ dev_err(rsz_device, "No user buffer allocated\n");
+- goto out;
++ return -EINVAL;
+ }
+ if (vb->i) {
+ vb->width = fh->params->out_hsize;
+@@ -1103,55 +1234,128 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+
+ vb->field = field;
+ spin_unlock(&fh->vbq_lock);
++ /*
++ * Calculate input and output sizes, will be used while mapping
++ * user pages
++ */
++ outsize = multipass->out_pitch * multipass->out_vsize;
++ insize = multipass->in_pitch * multipass->in_vsize;
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+- err = videobuf_iolock(q, vb, NULL);
+- if (!err) {
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
+- if (!isp_addr)
+- err = -EIO;
+- else {
+- if (vb->i) {
+- rsz_conf_chan->register_config.
+- rsz_sdr_outadd
+- = isp_addr;
+- fh->isp_addr_write = isp_addr;
+- rsz_conf_chan->output_buf_index = vb->i;
+- } else {
++ struct videobuf_dmabuf *dma;
++ struct vm_area_struct *vma;
++ spin_lock(&fh->vbq_lock);
++ dma = videobuf_to_dma(vb);
++ vma = find_vma(current->mm, vb->baddr);
++ if ((vma) && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) {
++ /* This will catch ioremaped buffers to the kernel.
++ * It gives two possible scenarios -
++ * - Driver allocates buffer using either
++ * dma_alloc_coherent or get_free_pages,
++ * and maps to user space using
++ * io_remap_pfn_range/remap_pfn_range
++ * - Drivers maps memory outside from Linux using
++ * io_remap
++ */
++ unsigned long physp = 0, asize;
++ asize = vb->i ? outsize : insize;
++ if ((vb->baddr + asize) > vma->vm_end) {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "User Buffer Allocation:" \
++ "err=%lu[%lu]\n",\
++ (vma->vm_end - vb->baddr), asize);
++ return -ENOMEM;
++ }
++ physp = (vma->vm_pgoff << PAGE_SHIFT) +
++ (vb->baddr - vma->vm_start);
++ err = omap_videobuf_dma_init_user(vb, physp, asize);
++ spin_unlock(&fh->vbq_lock);
++ if (0 != err)
++ return err;
++ } else {
++ err = videobuf_iolock(q, vb, NULL);
++ /*
++ * In case of user pointer mode, the get_user_pages
++ * will fail if user has allocated less memory than
++ * vb->size. But it is not error from resizer driver
++ * point of view. so handled seperately
++ */
++ if ((err < 0) && (dma->nr_pages > 0))
++ err = videobuf_dma_map(q, dma);
++ if (err)
++ goto buf_release;
++ /*
++ * Add one extra page for input buffer
++ */
++ if (0 == vb->i)
++ err = omap_create_sg(q, dma);
++ if (err)
++ goto buf_release;
++ spin_unlock(&fh->vbq_lock);
++ }
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ if (!isp_addr)
++ err = -EIO;
++ else {
++ if (vb->i) {
++ rsz_conf_chan->buf_address[vb->i] = isp_addr;
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->buf_address[vb->i] = isp_addr;
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd
++ = isp_addr;
++ rsz_conf_chan->input_buf_index = vb->i;
++ if (outsize < insize && rsz_conf_chan->
++ register_config.
++ rsz_sdr_outadd == 0) {
+ rsz_conf_chan->register_config.
+- rsz_sdr_inadd
+- = isp_addr;
+- rsz_conf_chan->input_buf_index = vb->i;
+- outsize = multipass->out_pitch *
+- multipass->out_vsize;
+- insize = multipass->in_pitch *
+- multipass->in_vsize;
+- if (outsize < insize) {
+- rsz_conf_chan->register_config.
+- rsz_sdr_outadd
+- = isp_addr;
+- rsz_conf_chan->
+- output_buf_index =
+- vb->i;
+- }
+-
+- fh->isp_addr_read = isp_addr;
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->
++ output_buf_index =
++ vb->i;
+ }
+ }
+ }
+
+- }
++ } else {
++ if(vb->i) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd =
++ rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd =
++ rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->input_buf_index = vb->i;
++ if(outsize < insize && rsz_conf_chan->
++ register_config.
++ rsz_sdr_outadd == 0) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->output_buf_index = vb->i;
++ }
++
++ }
+
++ }
+ if (!err) {
+ spin_lock(&fh->vbq_lock);
+ vb->state = VIDEOBUF_PREPARED;
+ spin_unlock(&fh->vbq_lock);
+- flush_cache_user_range(NULL, vb->baddr, (vb->baddr
+- + vb->bsize));
+ } else
+ rsz_vbq_release(q, vb);
+
+-out:
++ return err;
++buf_release:
++ spin_unlock(&fh->vbq_lock);
++ rsz_vbq_release(q, vb);
+ return err;
+ }
+
+@@ -1255,7 +1459,8 @@ err_enomem0:
+ **/
+ static int rsz_release(struct inode *inode, struct file *filp)
+ {
+- u32 timeout = 0;
++ int i;
++ unsigned int timeout = 0;
+ struct rsz_fh *fh = filp->private_data;
+ struct channel_config *rsz_conf_chan = fh->config;
+ struct rsz_params *params = fh->params;
+@@ -1266,17 +1471,17 @@ static int rsz_release(struct inode *inode, struct file *filp)
+ timeout++;
+ schedule();
+ }
+- if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
+- return -EINTR;
+- device_config->opened--;
+- mutex_unlock(&device_config->reszwrap_mutex);
+- /* This will Free memory allocated to the buffers,
+- * and flushes the queue
+- */
+- videobuf_queue_cancel(q);
+- fh->params = NULL;
+- fh->config = NULL;
++ /* Free memory allocated to the buffers */
++ for (i = 0 ; i < VIDEO_MAX_FRAME ; i++) {
++ struct videobuf_dmabuf *dma = NULL;
++ if (!q->bufs[i])
++ continue;
++ dma = videobuf_to_dma(q->bufs[i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ }
+
++ videobuf_mmap_free(q);
+ fh->rsz_bufsize = 0;
+ filp->private_data = NULL;
+
+@@ -1286,7 +1491,8 @@ static int rsz_release(struct inode *inode, struct file *filp)
+ kfree(fh);
+
+ isp_put();
+-
++ fh->params = NULL;
++ fh->config = NULL;
+ return 0;
+ }
+
+@@ -1353,6 +1559,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ chanprotection_mutex))
+ return -EINTR;
+ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
++ if (ret >= 0) {
++ if (copy_to_user((struct v4l2_requestbuffers *)arg,
++ &req_buf, sizeof(struct
++ v4l2_requestbuffers)))
++ return -EFAULT;
++ }
+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
+ break;
+ }
+@@ -1394,11 +1606,7 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ sizeof(struct rsz_params))) {
+ return -EFAULT;
+ }
+- if (mutex_lock_interruptible(&rsz_conf_chan->
+- chanprotection_mutex))
+- return -EINTR;
+- ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
+- mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ ret = rsz_set_params(fh->multipass, fh->params, rsz_conf_chan);
+ break;
+ }
+ case RSZ_G_PARAM:
+@@ -1433,6 +1641,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
+ break;
+
++ case RSZ_S_EXP:
++ if (mutex_lock_interruptible(&rsz_conf_chan->chanprotection_mutex))
++ return -EINTR;
++ rsz_conf_chan->register_config.sdr_req_exp = *((unsigned int *)arg);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
+ default:
+ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
+ return -EINVAL;
+@@ -1535,14 +1749,18 @@ static int __init omap_rsz_init(void)
+ "memory\n");
+ return -ENOMEM;
+ }
+-
++ device->extra_page_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
++ if (!device->extra_page_addr) {
++ dev_err(rsz_device, OMAP_REZR_NAME ":Allocation failed. ");
++ kfree(device);
++ return -ENOMEM;
++ }
+ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
+ if (ret < 0) {
+ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
+ "Could not allocate region "
+ "for character device\n");
+- kfree(device);
+- return -ENODEV;
++ goto fail1;
+ }
+
+ /* Register the driver in the kernel */
+@@ -1608,6 +1826,8 @@ fail3:
+ cdev_del(&c_dev);
+ fail2:
+ unregister_chrdev_region(dev, 1);
++fail1:
++ free_pages((unsigned long)device->extra_page_addr, 0);
+ kfree(device);
+ return ret;
+ }
+@@ -1623,6 +1843,7 @@ void __exit omap_rsz_exit(void)
+ platform_driver_unregister(&omap_resizer_driver);
+ cdev_del(&c_dev);
+ unregister_chrdev_region(dev, 1);
++ free_pages((unsigned long)device_config->extra_page_addr, 0);
+ kfree(device_config);
+ }
+
+diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
+index 5ac0c88..47b8dd8 100644
+--- a/include/linux/omap_resizer.h
++++ b/include/linux/omap_resizer.h
+@@ -21,7 +21,7 @@
+
+ /* ioctls definition */
+ #define RSZ_IOC_BASE 'R'
+-#define RSZ_IOC_MAXNR 8
++#define RSZ_IOC_MAXNR 9
+
+ /*Ioctl options which are to be passed while calling the ioctl*/
+ #define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
+@@ -33,6 +33,7 @@
+ #define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
+ #define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
+ #define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
++#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE, 9, __s32)
+
+ #define RSZ_INTYPE_YCBCR422_16BIT 0
+ #define RSZ_INTYPE_PLANAR_8BIT 1
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
new file mode 100644
index 0000000000..143a846e3c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
@@ -0,0 +1,36 @@
+From 9fec955e98b4ef7922f629e3a81d2d1af216e028 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 18:12:42 +0530
+Subject: [PATCH 25/26] OMAP3-Resizer: Build issues fixed
+
+There were some building issues with latest gitorious tree,
+fixed them.
+---
+ drivers/media/video/isp/omap_resizer.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+index 8059c70..dd90b24 100644
+--- a/drivers/media/video/isp/omap_resizer.c
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -1033,7 +1033,7 @@ static void rsz_vbq_release(struct videobuf_queue *q,
+ dma = videobuf_to_dma(q->bufs[vb->i]);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+- ispmmu_unmap(fh->config->buf_address[vb->i]);
++ ispmmu_vunmap(fh->config->buf_address[vb->i]);
+ fh->config->buf_address[vb->i] = 0;
+
+ spin_lock(&fh->vbq_lock);
+@@ -1293,7 +1293,7 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+ goto buf_release;
+ spin_unlock(&fh->vbq_lock);
+ }
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
+ if (!isp_addr)
+ err = -EIO;
+ else {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch
new file mode 100644
index 0000000000..d9e4243b4a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch
@@ -0,0 +1,44 @@
+From ad422f476ce04636f911557bbfd066c516e9b472 Mon Sep 17 00:00:00 2001
+From: Aguirre Rodriguez, Sergio Alberto <saaguirre@ti.com>
+Date: Tue, 20 Jan 2009 16:29:26 -0600
+Subject: [PATCH] V4L2: Add COLORFX user control
+
+From 07396d67b39bf7bcc81440d3e72d253ad6c54f11 Mon Sep 17 00:00:00 2001
+From: Sergio Aguirre <saaguirre@ti.com>
+Date: Tue, 20 Jan 2009 15:34:43 -0600
+Subject: [PATCH v2] V4L2: Add COLORFX user control
+
+This is a common feature on many cameras. the options are:
+Default colors,
+B & W,
+Sepia
+
+Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
+---
+ include/linux/videodev2.h | 9 ++++++++-
+ 1 files changed, 8 insertions(+), 1 deletions(-)
+
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 5571dbe..8e4e25e 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -879,8 +879,15 @@ enum v4l2_power_line_frequency {
+ #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28)
+ #define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29)
+ #define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30)
++#define V4L2_CID_COLORFX (V4L2_CID_BASE+31)
++enum v4l2_colorfx {
++ V4L2_COLORFX_NONE = 0,
++ V4L2_COLORFX_BW = 1,
++ V4L2_COLORFX_SEPIA = 2,
++};
++
+ /* last CID + 1 */
+-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+31)
++#define V4L2_CID_LASTP1 (V4L2_CID_BASE+32)
+
+ /* MPEG-class control IDs defined by V4L2 */
+ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch
new file mode 100644
index 0000000000..45e27a2fda
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch
@@ -0,0 +1,50 @@
+From 5b007183d51543624bc9f582966f245a64157b57 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@nokia.com>
+Date: Fri, 31 Oct 2008 11:51:30 +0200
+Subject: [PATCH] V4L: Int if: v4l2_int_device_try_attach_all requires mutex
+
+Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
+---
+ drivers/media/video/v4l2-int-device.c | 12 ++++++++++--
+ 1 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
+index a935bae..eb8dc84 100644
+--- a/drivers/media/video/v4l2-int-device.c
++++ b/drivers/media/video/v4l2-int-device.c
+@@ -32,7 +32,7 @@
+ static DEFINE_MUTEX(mutex);
+ static LIST_HEAD(int_list);
+
+-void v4l2_int_device_try_attach_all(void)
++static void __v4l2_int_device_try_attach_all(void)
+ {
+ struct v4l2_int_device *m, *s;
+
+@@ -66,6 +66,14 @@ void v4l2_int_device_try_attach_all(void)
+ }
+ }
+ }
++
++void v4l2_int_device_try_attach_all(void)
++{
++ mutex_lock(&mutex);
++ __v4l2_int_device_try_attach_all();
++ mutex_unlock(&mutex);
++}
++
+ EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
+
+ static int ioctl_sort_cmp(const void *a, const void *b)
+@@ -89,7 +97,7 @@ int v4l2_int_device_register(struct v4l2_int_device *d)
+ &ioctl_sort_cmp, NULL);
+ mutex_lock(&mutex);
+ list_add(&d->head, &int_list);
+- v4l2_int_device_try_attach_all();
++ __v4l2_int_device_try_attach_all();
+ mutex_unlock(&mutex);
+
+ return 0;
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch
new file mode 100644
index 0000000000..829810fab0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch
@@ -0,0 +1,61 @@
+From cc1d76e0f50321e80f7f50e9e214de2c9a45628a Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@nokia.com>
+Date: Wed, 22 Oct 2008 18:41:20 +0300
+Subject: [PATCH] V4L: Int if: Dummy slave
+
+This patch implements a dummy slave that has no functionality. Helps
+managing slaves in the OMAP 3 camera driver; no need to check for NULL
+pointers.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
+---
+ drivers/media/video/v4l2-int-device.c | 19 +++++++++++++++++++
+ include/media/v4l2-int-device.h | 2 ++
+ 2 files changed, 21 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
+index eb8dc84..483ee2e 100644
+--- a/drivers/media/video/v4l2-int-device.c
++++ b/drivers/media/video/v4l2-int-device.c
+@@ -67,6 +67,25 @@ static void __v4l2_int_device_try_attach_all(void)
+ }
+ }
+
++static struct v4l2_int_slave dummy_slave = {
++ /* Dummy pointer to avoid underflow in find_ioctl. */
++ .ioctls = (void *)sizeof(struct v4l2_int_ioctl_desc),
++ .num_ioctls = 0,
++};
++
++static struct v4l2_int_device dummy = {
++ .type = v4l2_int_type_slave,
++ .u = {
++ .slave = &dummy_slave,
++ },
++};
++
++struct v4l2_int_device *v4l2_int_device_dummy()
++{
++ return &dummy;
++}
++EXPORT_SYMBOL_GPL(v4l2_int_device_dummy);
++
+ void v4l2_int_device_try_attach_all(void)
+ {
+ mutex_lock(&mutex);
+diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
+index fbf5855..5d254c4 100644
+--- a/include/media/v4l2-int-device.h
++++ b/include/media/v4l2-int-device.h
+@@ -84,6 +84,8 @@ struct v4l2_int_device {
+ void *priv;
+ };
+
++struct v4l2_int_device *v4l2_int_device_dummy(void);
++
+ void v4l2_int_device_try_attach_all(void);
+
+ int v4l2_int_device_register(struct v4l2_int_device *d);
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch
new file mode 100644
index 0000000000..b81b20419e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch
@@ -0,0 +1,33 @@
+From e041e57cafca24cf92430cdf3cc091060a271e19 Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@nokia.com>
+Date: Fri, 31 Oct 2008 10:20:31 +0200
+Subject: [PATCH] V4L: int device: add support for VIDIOC_QUERYMENU
+
+Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
+---
+ include/media/v4l2-int-device.h | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
+index 5d254c4..81f4863 100644
+--- a/include/media/v4l2-int-device.h
++++ b/include/media/v4l2-int-device.h
+@@ -178,6 +178,7 @@ enum v4l2_int_ioctl_num {
+ vidioc_int_s_fmt_cap_num,
+ vidioc_int_try_fmt_cap_num,
+ vidioc_int_queryctrl_num,
++ vidioc_int_querymenu_num,
+ vidioc_int_g_ctrl_num,
+ vidioc_int_s_ctrl_num,
+ vidioc_int_cropcap_num,
+@@ -282,6 +283,7 @@ V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
+ V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
+ V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *);
+ V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *);
++V4L2_INT_WRAPPER_1(querymenu, struct v4l2_querymenu, *);
+ V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *);
+ V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *);
+ V4L2_INT_WRAPPER_1(cropcap, struct v4l2_cropcap, *);
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch
new file mode 100644
index 0000000000..a9e06290fa
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch
@@ -0,0 +1,35 @@
+From dc05ee10583dca44e0f8d4109bd1397ee3c5ffae Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@nokia.com>
+Date: Thu, 2 Oct 2008 11:55:07 +0300
+Subject: [PATCH] V4L: Int if: Add vidioc_int_querycap
+
+Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
+---
+ include/media/v4l2-int-device.h | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
+index 81f4863..2830ae1 100644
+--- a/include/media/v4l2-int-device.h
++++ b/include/media/v4l2-int-device.h
+@@ -173,7 +173,8 @@ enum v4l2_int_ioctl_num {
+ * "Proper" V4L ioctls, as in struct video_device.
+ *
+ */
+- vidioc_int_enum_fmt_cap_num = 1,
++ vidioc_int_querycap_num = 1,
++ vidioc_int_enum_fmt_cap_num,
+ vidioc_int_g_fmt_cap_num,
+ vidioc_int_s_fmt_cap_num,
+ vidioc_int_try_fmt_cap_num,
+@@ -278,6 +279,7 @@ enum v4l2_int_ioctl_num {
+ return desc; \
+ }
+
++V4L2_INT_WRAPPER_1(querycap, struct v4l2_capability, *);
+ V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *);
+ V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
+ V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
+--
+1.5.6.5
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/make-alignment-visible.diff b/recipes/linux/linux-omap-pm-2.6.29/make-alignment-visible.diff
new file mode 100644
index 0000000000..9b3958f82a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/make-alignment-visible.diff
@@ -0,0 +1,26 @@
+From: Mans Rullgard <mans@mansr.com>
+Date: Mon, 13 Oct 2008 19:32:16 +0000 (+0100)
+Subject: ARM: Add prompt for CONFIG_ALIGNMENT_TRAP
+X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=60d60f0ca47fcf4fbb649e45aa64f5a0a4c2f2c8
+
+ARM: Add prompt for CONFIG_ALIGNMENT_TRAP
+
+This adds a prompt text for CONFIG_ALIGNMENT_TRAP, thus making it
+visible in make *config.
+
+Signed-off-by: Mans Rullgard <mans@mansr.com>
+---
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 61314f6..18d3119 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -971,7 +971,7 @@ config LEDS_CPU
+ will overrule the CPU usage LED.
+
+ config ALIGNMENT_TRAP
+- bool
++ bool "Enable alignment trap"
+ depends on CPU_CP15_MMU
+ default y if !ARCH_EBSA110
+ help
diff --git a/recipes/linux/linux-omap-pm-2.6.29/mmctiming.patch b/recipes/linux/linux-omap-pm-2.6.29/mmctiming.patch
new file mode 100644
index 0000000000..ec540ab3cb
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/mmctiming.patch
@@ -0,0 +1,16 @@
+Index: git/drivers/mmc/core/core.c
+===================================================================
+--- git.orig/drivers/mmc/core/core.c
++++ git/drivers/mmc/core/core.c
+@@ -284,9 +284,9 @@ void mmc_set_data_timeout(struct mmc_dat
+ * The limit is really 250 ms, but that is
+ * insufficient for some crappy cards.
+ */
+- limit_us = 300000;
++ limit_us = 500000;
+ else
+- limit_us = 100000;
++ limit_us = 200000;
+
+ /*
+ * SDHC cards always use these fixed values.
diff --git a/recipes/linux/linux-omap-pm-2.6.29/modedb-hd720.patch b/recipes/linux/linux-omap-pm-2.6.29/modedb-hd720.patch
new file mode 100644
index 0000000000..0166de651a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/modedb-hd720.patch
@@ -0,0 +1,13 @@
+--- orig/drivers/video/modedb.c.orig 2009-04-07 11:40:10.000000000 +0200
++++ git/drivers/video/modedb.c 2009-04-07 10:35:29.000000000 +0200
+@@ -44,6 +44,10 @@
+ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
+ }, {
++ /* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */
++ "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
++ 0, FB_VMODE_NONINTERLACED
++ }, {
+ /* 800x600 @ 56 Hz, 35.15 kHz hsync */
+ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
+ 0, FB_VMODE_NONINTERLACED
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch
new file mode 100644
index 0000000000..a7898d1440
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch
@@ -0,0 +1,43 @@
+From a9199e8ab6d6fb105aa251d6bf2192e7eafac8ee Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:22:53 -0700
+Subject: [PATCH] USB: musb: only turn off vbus in OTG hosts
+
+Except on DaVinci, VBUS is now switched off as part of idling the
+USB link (after a_wait_bcon) whenever a device is disconnected
+from host. This is correct for OTG hosts, where either SRP or
+an ID interrupt could turn VBUS on again.
+
+However, for non-OTG hosts there's no way to turn VBUS on again,
+so the host becomes unusable. And the procfs entry which once
+allowed a manual workaround for this is now gone.
+
+This patch adds an is_otg_enabled() check before scheduling the
+switch-off timer in disconnect path, supporting a "classic host"
+mode where SRP is unavailable.
+
+[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: tweak patch description ]
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index af77e46..338cd16 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ case OTG_STATE_A_SUSPEND:
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ musb_root_disconnect(musb);
+- if (musb->a_wait_bcon != 0)
++ if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
+ musb_platform_try_idle(musb, jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon));
+ break;
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch
new file mode 100644
index 0000000000..5cb7bcb065
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch
@@ -0,0 +1,76 @@
+From 83eb44b1c84f99d9a5c67612bd94b4ed7c43f64c Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:22:49 -0700
+Subject: [PATCH] USB: composite: avoid inconsistent lock state
+
+Avoid the following INFO from lock debugging:
+
+[ 369.126112] =================================
+[ 369.132063] [ INFO: inconsistent lock state ]
+[ 369.136457] 2.6.28-maemo1 #1
+[ 369.139387] ---------------------------------
+[ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage.
+[ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
+[ 369.154890] (&cdev->lock){+-..}, at: [<bf1979f0>] composite_disconnect+0x1c/0]
+[ 369.163404] {hardirq-on-W} state was registered at:
+[ 369.168348] [<c00788a8>] __lock_acquire+0x5d0/0x7d8
+[ 369.173506] [<c0078b14>] lock_acquire+0x64/0x78
+[ 369.178266] [<c0263a34>] _spin_lock+0x4c/0x80
+[ 369.182905] [<bf19597c>] usb_function_deactivate+0x20/0x70 [g_nokia]
+[ 369.189527] [<bf1a0a88>] 0xbf1a0a88
+[ 369.193281] [<bf19f450>] 0xbf19f450
+[ 369.197004] [<bf19fa3c>] 0xbf19fa3c
+[ 369.200758] [<bf1a03a0>] 0xbf1a03a0
+[ 369.204481] [<bf19f254>] 0xbf19f254
+[ 369.208204] [<bf1a0158>] 0xbf1a0158
+[ 369.211927] [<bf1a130c>] 0xbf1a130c
+[ 369.215650] [<c01c21f0>] usb_gadget_register_driver+0x12c/0x28c
+[ 369.221846] [<bf1a06bc>] 0xbf1a06bc
+[ 369.225569] [<bf1a06e8>] 0xbf1a06e8
+[ 369.229322] [<c002c2dc>] __exception_text_end+0x64/0x19c
+[ 369.234877] [<c0081628>] sys_init_module+0x9c/0x194
+[ 369.240004] [<c002c8e0>] ret_fast_syscall+0x0/0x2c
+[ 369.245039] [<ffffffff>] 0xffffffff
+[ 369.248793] irq event stamp: 218356
+[ 369.252302] hardirqs last enabled at (218355): [<c003a77c>] omap3_enter_idle+8
+[ 369.260420] hardirqs last disabled at (218356): [<c0264774>] __irq_svc+0x34/0x0
+[ 369.267927] softirqs last enabled at (218348): [<c00585a4>] __do_softirq+0x134
+[ 369.275892] softirqs last disabled at (218335): [<c005899c>] irq_exit+0x60/0xb0
+[ 369.283308]
+[ 369.283308] other info that might help us debug this:
+[ 369.289930] no locks held by swapper/0.
+
+Cc: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
+Signed-off-by: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/gadget/composite.c | 5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
+index 5d11c29..40f1da7 100644
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -149,16 +149,17 @@ done:
+ int usb_function_deactivate(struct usb_function *function)
+ {
+ struct usb_composite_dev *cdev = function->config->cdev;
++ unsigned long flags;
+ int status = 0;
+
+- spin_lock(&cdev->lock);
++ spin_lock_irqsave(&cdev->lock, flags);
+
+ if (cdev->deactivations == 0)
+ status = usb_gadget_disconnect(cdev->gadget);
+ if (status == 0)
+ cdev->deactivations++;
+
+- spin_unlock(&cdev->lock);
++ spin_unlock_irqrestore(&cdev->lock, flags);
+ return status;
+ }
+
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch
new file mode 100644
index 0000000000..fadad9e44a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch
@@ -0,0 +1,218 @@
+From ba7b26e69f4bb41f10be444c5fded853330f82b5 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:22:51 -0700
+Subject: [PATCH] USB: musb: NAK timeout scheme on bulk RX endpoint
+
+Fixes endpoint starvation issue when more than one bulk QH is
+multiplexed on the reserved bulk RX endpoint, which is normal
+for cases like serial and ethernet adapters.
+
+This patch sets the NAK timeout interval for such QHs, and when
+a timeout triggers the next QH will be scheduled. (This resembles
+the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.)
+
+This scheme doesn't work for devices which are connected to a
+high to full speed tree (transaction translator) as there is
+no NAK timeout interrupt from the musb controller from such
+devices.
+
+Tested with PIO, Inventra DMA, CPPI DMA.
+
+[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: fold in start_urb() update;
+ clarify only for bulk RX; don't accidentally clear WZC bits ]
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++++++++----------
+ 1 files changed, 85 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 6dbbd07..bd1d5ae 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -64,11 +64,8 @@
+ *
+ * - DMA (Mentor/OMAP) ...has at least toggle update problems
+ *
+- * - Still no traffic scheduling code to make NAKing for bulk or control
+- * transfers unable to starve other requests; or to make efficient use
+- * of hardware with periodic transfers. (Note that network drivers
+- * commonly post bulk reads that stay pending for a long time; these
+- * would make very visible trouble.)
++ * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet
++ * starvation ... nothing yet for TX, interrupt, or bulk.
+ *
+ * - Not tested with HNP, but some SRP paths seem to behave.
+ *
+@@ -88,11 +85,8 @@
+ *
+ * CONTROL transfers all go through ep0. BULK ones go through dedicated IN
+ * and OUT endpoints ... hardware is dedicated for those "async" queue(s).
+- *
+ * (Yes, bulk _could_ use more of the endpoints than that, and would even
+- * benefit from it ... one remote device may easily be NAKing while others
+- * need to perform transfers in that same direction. The same thing could
+- * be done in software though, assuming dma cooperates.)
++ * benefit from it.)
+ *
+ * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
+ * So far that scheduling is both dumb and optimistic: the endpoint will be
+@@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ len = urb->iso_frame_desc[0].length;
+ break;
+ default: /* bulk, interrupt */
+- buf = urb->transfer_buffer;
+- len = urb->transfer_buffer_length;
++ /* actual_length may be nonzero on retry paths */
++ buf = urb->transfer_buffer + urb->actual_length;
++ len = urb->transfer_buffer_length - urb->actual_length;
+ }
+
+ DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
+@@ -1045,7 +1040,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
+
+ /* NOTE: this code path would be a good place to PAUSE a
+ * control transfer, if another one is queued, so that
+- * ep0 is more likely to stay busy.
++ * ep0 is more likely to stay busy. That's already done
++ * for bulk RX transfers.
+ *
+ * if (qh->ring.next != &musb->control), then
+ * we have a candidate... NAKing is *NOT* an error
+@@ -1197,6 +1193,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ /* NOTE: this code path would be a good place to PAUSE a
+ * transfer, if there's some other (nonperiodic) tx urb
+ * that could use this fifo. (dma complicates it...)
++ * That's already done for bulk RX transfers.
+ *
+ * if (bulk && qh->ring.next != &musb->out_bulk), then
+ * we have a candidate... NAKing is *NOT* an error
+@@ -1358,6 +1355,50 @@ finish:
+
+ #endif
+
++/* Schedule next QH from musb->in_bulk and move the current qh to
++ * the end; avoids starvation for other endpoints.
++ */
++static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep)
++{
++ struct dma_channel *dma;
++ struct urb *urb;
++ void __iomem *mbase = musb->mregs;
++ void __iomem *epio = ep->regs;
++ struct musb_qh *cur_qh, *next_qh;
++ u16 rx_csr;
++
++ musb_ep_select(mbase, ep->epnum);
++ dma = is_dma_capable() ? ep->rx_channel : NULL;
++
++ /* clear nak timeout bit */
++ rx_csr = musb_readw(epio, MUSB_RXCSR);
++ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
++ rx_csr &= ~MUSB_RXCSR_DATAERROR;
++ musb_writew(epio, MUSB_RXCSR, rx_csr);
++
++ cur_qh = first_qh(&musb->in_bulk);
++ if (cur_qh) {
++ urb = next_urb(cur_qh);
++ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
++ dma->status = MUSB_DMA_STATUS_CORE_ABORT;
++ musb->dma_controller->channel_abort(dma);
++ urb->actual_length += dma->actual_len;
++ dma->actual_len = 0L;
++ }
++ musb_save_toggle(ep, 1, urb);
++
++ /* move cur_qh to end of queue */
++ list_move_tail(&cur_qh->ring, &musb->in_bulk);
++
++ /* get the next qh from musb->in_bulk */
++ next_qh = first_qh(&musb->in_bulk);
++
++ /* set rx_reinit and schedule the next qh */
++ ep->rx_reinit = 1;
++ musb_start_urb(musb, 1, next_qh);
++ }
++}
++
+ /*
+ * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
+ * and high-bandwidth IN transfer cases.
+@@ -1421,18 +1462,26 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ } else if (rx_csr & MUSB_RXCSR_DATAERROR) {
+
+ if (USB_ENDPOINT_XFER_ISOC != qh->type) {
+- /* NOTE this code path would be a good place to PAUSE a
+- * transfer, if there's some other (nonperiodic) rx urb
+- * that could use this fifo. (dma complicates it...)
++ DBG(6, "RX end %d NAK timeout\n", epnum);
++
++ /* NOTE: NAKing is *NOT* an error, so we want to
++ * continue. Except ... if there's a request for
++ * another QH, use that instead of starving it.
+ *
+- * if (bulk && qh->ring.next != &musb->in_bulk), then
+- * we have a candidate... NAKing is *NOT* an error
++ * Devices like Ethernet and serial adapters keep
++ * reads posted at all times, which will starve
++ * other devices without this logic.
+ */
+- DBG(6, "RX end %d NAK timeout\n", epnum);
++ if (usb_pipebulk(urb->pipe)
++ && qh->mux == 1
++ && !list_is_singular(&musb->in_bulk)) {
++ musb_bulk_rx_nak_timeout(musb, hw_ep);
++ return;
++ }
+ musb_ep_select(mbase, epnum);
+- musb_writew(epio, MUSB_RXCSR,
+- MUSB_RXCSR_H_WZC_BITS
+- | MUSB_RXCSR_H_REQPKT);
++ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
++ rx_csr &= ~MUSB_RXCSR_DATAERROR;
++ musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+ goto finish;
+ } else {
+@@ -1756,6 +1805,17 @@ static int musb_schedule(
+ head = &musb->in_bulk;
+ else
+ head = &musb->out_bulk;
++
++ /* Enable bulk RX NAK timeout scheme when bulk requests are
++ * multiplexed. This scheme doen't work in high speed to full
++ * speed scenario as NAK interrupts are not coming from a
++ * full speed device connected to a high speed device.
++ * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
++ * 4 (8 frame or 8ms) for FS device.
++ */
++ if (is_in && qh->dev)
++ qh->intv_reg =
++ (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
+ goto success;
+ } else if (best_end < 0) {
+ return -ENOSPC;
+@@ -1888,13 +1948,11 @@ static int musb_urb_enqueue(
+ *
+ * The downside of disabling this is that transfer scheduling
+ * gets VERY unfair for nonperiodic transfers; a misbehaving
+- * peripheral could make that hurt. Or for reads, one that's
+- * perfectly normal: network and other drivers keep reads
+- * posted at all times, having one pending for a week should
+- * be perfectly safe.
++ * peripheral could make that hurt. That's perfectly normal
++ * for reads from network or serial adapters ... so we have
++ * partial NAKlimit support for bulk RX.
+ *
+- * The upside of disabling it is avoidng transfer scheduling
+- * code to put this aside for while.
++ * The upside of disabling it is simpler transfer scheduling.
+ */
+ interval = 0;
+ }
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch
new file mode 100644
index 0000000000..438f11cf7a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch
@@ -0,0 +1,106 @@
+From 9ebf351bcd28a89a0b1ba8d0496fffbc72421611 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:22:50 -0700
+Subject: [PATCH] USB: musb: rewrite host periodic endpoint allocation
+
+The current MUSB host code doesn't make use of all the available
+FIFOs in for periodic transfers since it wrongly assumes the RX
+and TX sides of any given hw_ep always share one FIFO.
+
+Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep'
+to check the endpoint's business; get rid of the now-unused 'periodic'
+array in the 'struct musb'. Also optimize a loop induction variable
+in the endpoint lookup code.
+
+(Based on a previous patch from Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>)
+
+[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: clarify description and origin
+ of this fix; whitespace ]
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.h | 1 -
+ drivers/usb/musb/musb_host.c | 28 +++++++++++-----------------
+ 2 files changed, 11 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index 630946a..adf1806 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -331,7 +331,6 @@ struct musb {
+ struct list_head control; /* of musb_qh */
+ struct list_head in_bulk; /* of musb_qh */
+ struct list_head out_bulk; /* of musb_qh */
+- struct musb_qh *periodic[32]; /* tree of interrupt+iso */
+ #endif
+
+ /* called with IRQs blocked; ON/nonzero implies starting a session,
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index bd1d5ae..499c431 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -390,7 +390,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+ * de-allocated if it's tracked and allocated;
+ * and where we'd update the schedule tree...
+ */
+- musb->periodic[ep->epnum] = NULL;
+ kfree(qh);
+ qh = NULL;
+ break;
+@@ -1760,31 +1759,27 @@ static int musb_schedule(
+
+ /* else, periodic transfers get muxed to other endpoints */
+
+- /* FIXME this doesn't consider direction, so it can only
+- * work for one half of the endpoint hardware, and assumes
+- * the previous cases handled all non-shared endpoints...
+- */
+-
+- /* we know this qh hasn't been scheduled, so all we need to do
++ /*
++ * We know this qh hasn't been scheduled, so all we need to do
+ * is choose which hardware endpoint to put it on ...
+ *
+ * REVISIT what we really want here is a regular schedule tree
+- * like e.g. OHCI uses, but for now musb->periodic is just an
+- * array of the _single_ logical endpoint associated with a
+- * given physical one (identity mapping logical->physical).
+- *
+- * that simplistic approach makes TT scheduling a lot simpler;
+- * there is none, and thus none of its complexity...
++ * like e.g. OHCI uses.
+ */
+ best_diff = 4096;
+ best_end = -1;
+
+- for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
++ for (epnum = 1, hw_ep = musb->endpoints + 1;
++ epnum < musb->nr_endpoints;
++ epnum++, hw_ep++) {
+ int diff;
+
+- if (musb->periodic[epnum])
++ if (is_in || hw_ep->is_shared_fifo) {
++ if (hw_ep->in_qh != NULL)
++ continue;
++ } else if (hw_ep->out_qh != NULL)
+ continue;
+- hw_ep = &musb->endpoints[epnum];
++
+ if (hw_ep == musb->bulk_ep)
+ continue;
+
+@@ -1824,7 +1819,6 @@ static int musb_schedule(
+ idle = 1;
+ qh->mux = 0;
+ hw_ep = musb->endpoints + best_end;
+- musb->periodic[best_end] = qh;
+ DBG(4, "qh %p periodic slot %d\n", qh, best_end);
+ success:
+ if (head) {
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch
new file mode 100644
index 0000000000..db3481b87b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch
@@ -0,0 +1,181 @@
+From 60e7ce93befe795357db05001fe4caab522a421d Mon Sep 17 00:00:00 2001
+From: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:22:57 -0700
+Subject: [PATCH] USB: TWL: disable VUSB regulators when cable unplugged
+
+This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1
+when the USB cable is unplugged to reduce power consumption.
+Added a depencency from twl4030 usb driver to TWL_REGULATOR.
+
+Signed-off-by: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Kalle Jokiniemi <kalle.jokiniemi-sMOQStClEysAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/otg/Kconfig | 2 +-
+ drivers/usb/otg/twl4030-usb.c | 73 ++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 65 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
+index ee55b44..5790a5b 100644
+--- a/drivers/usb/otg/Kconfig
++++ b/drivers/usb/otg/Kconfig
+@@ -43,7 +43,7 @@ config ISP1301_OMAP
+
+ config TWL4030_USB
+ tristate "TWL4030 USB Transceiver Driver"
+- depends on TWL4030_CORE
++ depends on TWL4030_CORE && REGULATOR_TWL4030
+ select USB_OTG_UTILS
+ help
+ Enable this to support the USB OTG transceiver on TWL4030
+diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
+index 416e441..d9478d0 100644
+--- a/drivers/usb/otg/twl4030-usb.c
++++ b/drivers/usb/otg/twl4030-usb.c
+@@ -34,6 +34,8 @@
+ #include <linux/delay.h>
+ #include <linux/usb/otg.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/regulator/consumer.h>
++#include <linux/err.h>
+
+
+ /* Register defines */
+@@ -246,6 +248,11 @@ struct twl4030_usb {
+ struct otg_transceiver otg;
+ struct device *dev;
+
++ /* TWL4030 internal USB regulator supplies */
++ struct regulator *usb1v5;
++ struct regulator *usb1v8;
++ struct regulator *usb3v1;
++
+ /* for vbus reporting with irqs disabled */
+ spinlock_t lock;
+
+@@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
+
+ pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
+ if (on) {
++ regulator_enable(twl->usb3v1);
++ regulator_enable(twl->usb1v8);
++ /*
++ * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
++ * in twl4030) resets the VUSB_DEDICATED2 register. This reset
++ * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
++ * SLEEP. We work around this by clearing the bit after usv3v1
++ * is re-activated. This ensures that VUSB3V1 is really active.
++ */
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
++ VUSB_DEDICATED2);
++ regulator_enable(twl->usb1v5);
+ pwr &= ~PHY_PWR_PHYPWD;
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+ twl4030_usb_write(twl, PHY_CLK_CTRL,
+@@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
+ } else {
+ pwr |= PHY_PWR_PHYPWD;
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
++ regulator_disable(twl->usb1v5);
++ regulator_disable(twl->usb1v8);
++ regulator_disable(twl->usb3v1);
+ }
+ }
+
+@@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
+ twl->asleep = 0;
+ }
+
+-static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
++static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
+ {
+ /* Enable writing to power configuration registers */
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
+@@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
+ /* input to VUSB3V1 LDO is from VBAT, not VBUS */
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+
+- /* turn on 3.1V regulator */
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP);
++ /* Initialize 3.1V regulator */
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
++
++ twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
++ if (IS_ERR(twl->usb3v1))
++ return -ENODEV;
++
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+
+- /* turn on 1.5V regulator */
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP);
++ /* Initialize 1.5V regulator */
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
++
++ twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
++ if (IS_ERR(twl->usb1v5))
++ goto fail1;
++
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+
+- /* turn on 1.8V regulator */
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP);
++ /* Initialize 1.8V regulator */
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
++
++ twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
++ if (IS_ERR(twl->usb1v8))
++ goto fail2;
++
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+
+ /* disable access to power configuration registers */
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
++
++ return 0;
++
++fail2:
++ regulator_put(twl->usb1v5);
++ twl->usb1v5 = NULL;
++fail1:
++ regulator_put(twl->usb3v1);
++ twl->usb3v1 = NULL;
++ return -ENODEV;
+ }
+
+ static ssize_t twl4030_usb_vbus_show(struct device *dev,
+@@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
+ {
+ struct twl4030_usb_data *pdata = pdev->dev.platform_data;
+ struct twl4030_usb *twl;
+- int status;
++ int status, err;
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "platform_data not available\n");
+@@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
+ /* init spinlock for workqueue */
+ spin_lock_init(&twl->lock);
+
+- twl4030_usb_ldo_init(twl);
++ err = twl4030_usb_ldo_init(twl);
++ if (err) {
++ dev_err(&pdev->dev, "ldo init failed\n");
++ kfree(twl);
++ return err;
++ }
+ otg_set_transceiver(&twl->otg);
+
+ platform_set_drvdata(pdev, twl);
+@@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
+ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+
+ twl4030_phy_power(twl, 0);
++ regulator_put(twl->usb1v5);
++ regulator_put(twl->usb1v8);
++ regulator_put(twl->usb3v1);
+
+ kfree(twl);
+
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch
new file mode 100644
index 0000000000..3f49a4d636
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch
@@ -0,0 +1,84 @@
+From 7eef82d231578140c6000d04846a48bdaf341a65 Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 24 Mar 2009 17:23:19 -0700
+Subject: [PATCH] USB: gadget: composite device-level suspend/resume hooks
+
+Address one open question in the composite gadget framework:
+Yes, we should have device-level suspend/resume callbacks
+in addition to the function-level ones. We have at least one
+scenario (with gadget zero in OTG test mode) that's awkward
+to handle without it.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org>
+---
+ drivers/usb/gadget/composite.c | 8 ++++++--
+ include/linux/usb/composite.h | 8 ++++++++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
+index 40f1da7..59e8523 100644
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget)
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+- /* REVISIT: should we have config and device level
++ /* REVISIT: should we have config level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "suspend\n");
+@@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget)
+ f->suspend(f);
+ }
+ }
++ if (composite->suspend)
++ composite->suspend(cdev);
+ }
+
+ static void
+@@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget)
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+- /* REVISIT: should we have config and device level
++ /* REVISIT: should we have config level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "resume\n");
++ if (composite->resume)
++ composite->resume(cdev);
+ if (cdev->config) {
+ list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->resume)
+diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
+index 935c380..acd7b0f 100644
+--- a/include/linux/usb/composite.h
++++ b/include/linux/usb/composite.h
+@@ -244,6 +244,10 @@ int usb_add_config(struct usb_composite_dev *,
+ * value; it should return zero on successful initialization.
+ * @unbind: Reverses @bind(); called as a side effect of unregistering
+ * this driver.
++ * @suspend: Notifies when the host stops sending USB traffic,
++ * after function notifications
++ * @resume: Notifies configuration when the host restarts USB traffic,
++ * before function notifications
+ *
+ * Devices default to reporting self powered operation. Devices which rely
+ * on bus powered operation should report this in their @bind() method.
+@@ -268,6 +272,10 @@ struct usb_composite_driver {
+
+ int (*bind)(struct usb_composite_dev *);
+ int (*unbind)(struct usb_composite_dev *);
++
++ /* global suspend hooks */
++ void (*suspend)(struct usb_composite_dev *);
++ void (*resume)(struct usb_composite_dev *);
+ };
+
+ extern int usb_composite_register(struct usb_composite_driver *);
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch
new file mode 100644
index 0000000000..a89bc2ff5c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch
@@ -0,0 +1,47 @@
+From 00c4bd07a64061ec9ab9c35f5bf01ec6187138f4 Mon Sep 17 00:00:00 2001
+From: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org>
+Date: Thu, 26 Mar 2009 00:45:27 -0700
+Subject: [PATCH] usb gadget: fix ethernet link reports to ethtool
+
+The g_ether USB gadget driver currently decides whether or not there's a
+link to report back for eth_get_link based on if the USB link speed is
+set. The USB gadget speed is however often set even before the device is
+enumerated. It seems more sensible to only report a "link" if we're
+actually connected to a host that wants to talk to us. The patch below
+does this for me - tested with the PXA27x UDC driver.
+
+Signed-Off-By: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/gadget/u_ether.c | 8 +-------
+ 1 files changed, 1 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
+index 96d65ca..4007770 100644
+--- a/drivers/usb/gadget/u_ether.c
++++ b/drivers/usb/gadget/u_ether.c
+@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
+ strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
+ }
+
+-static u32 eth_get_link(struct net_device *net)
+-{
+- struct eth_dev *dev = netdev_priv(net);
+- return dev->gadget->speed != USB_SPEED_UNKNOWN;
+-}
+-
+ /* REVISIT can also support:
+ * - WOL (by tracking suspends and issuing remote wakeup)
+ * - msglevel (implies updated messaging)
+@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)
+
+ static struct ethtool_ops ops = {
+ .get_drvinfo = eth_get_drvinfo,
+- .get_link = eth_get_link
++ .get_link = ethtool_op_get_link,
+ };
+
+ static void defer_kevent(struct eth_dev *dev, int flag)
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch
new file mode 100644
index 0000000000..8627825b5a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch
@@ -0,0 +1,60 @@
+From c3b527a21104b6bb61558fba6c65aa80f63e0772 Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Thu, 26 Mar 2009 17:36:57 -0700
+Subject: [PATCH] usb: musb_host, minor enqueue locking fix (v2)
+
+Someone noted that the enqueue path used an unlocked access
+for usb_host_endpoint->hcpriv ... fix that, by being safe
+and always accessing it under spinlock protection.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 17 ++++++++---------
+ 1 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 499c431..ff09595 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -1841,7 +1841,7 @@ static int musb_urb_enqueue(
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+ struct usb_host_endpoint *hep = urb->ep;
+- struct musb_qh *qh = hep->hcpriv;
++ struct musb_qh *qh;
+ struct usb_endpoint_descriptor *epd = &hep->desc;
+ int ret;
+ unsigned type_reg;
+@@ -1853,22 +1853,21 @@ static int musb_urb_enqueue(
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_link_urb_to_ep(hcd, urb);
++ qh = ret ? NULL : hep->hcpriv;
++ if (qh)
++ urb->hcpriv = qh;
+ spin_unlock_irqrestore(&musb->lock, flags);
+- if (ret)
+- return ret;
+
+ /* DMA mapping was already done, if needed, and this urb is on
+- * hep->urb_list ... so there's little to do unless hep wasn't
+- * yet scheduled onto a live qh.
++ * hep->urb_list now ... so we're done, unless hep wasn't yet
++ * scheduled onto a live qh.
+ *
+ * REVISIT best to keep hep->hcpriv valid until the endpoint gets
+ * disabled, testing for empty qh->ring and avoiding qh setup costs
+ * except for the first urb queued after a config change.
+ */
+- if (qh) {
+- urb->hcpriv = qh;
+- return 0;
+- }
++ if (qh || ret)
++ return ret;
+
+ /* Allocate and initialize qh, minimizing the work done each time
+ * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch
new file mode 100644
index 0000000000..09fc0a17d0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch
@@ -0,0 +1,93 @@
+From 48ce47b15bfd420982ee275c595a9139eb6fabf7 Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Thu, 26 Mar 2009 17:38:30 -0700
+Subject: [PATCH] usb: musb_host, fix ep0 fifo flushing
+
+The MUSB host side can't share generic TX FIFO flush logic
+with EP0; the EP0 TX status register bits are different
+from those for other entpoints.
+
+Resolve this issue by providing a new EP0-specific routine
+to flush and reset the FIFO, which pays careful attention to
+restrictions listed in the latest programmer's guide. This
+gets rid of an open issue whereby the usbtest control write
+test (#14) failed.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 38 +++++++++++++++++++++++++-------------
+ 1 files changed, 25 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index ff09595..a5d75aa 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+ }
+ }
+
++static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
++{
++ void __iomem *epio = ep->regs;
++ u16 csr;
++ int retries = 5;
++
++ /* scrub any data left in the fifo */
++ do {
++ csr = musb_readw(epio, MUSB_TXCSR);
++ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
++ break;
++ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
++ csr = musb_readw(epio, MUSB_TXCSR);
++ udelay(10);
++ } while (--retries);
++
++ WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
++ ep->epnum, csr);
++
++ /* and reset for the next transfer */
++ musb_writew(epio, MUSB_TXCSR, 0);
++}
++
+ /*
+ * Start transmit. Caller is responsible for locking shared resources.
+ * musb must be locked.
+@@ -693,11 +716,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+- /* endpoint 0: just flush */
+- musb_writew(epio, MUSB_CSR0,
+- csr | MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0,
+- csr | MUSB_CSR0_FLUSHFIFO);
++ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+@@ -1063,11 +1082,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
+ csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ } else {
+- csr |= MUSB_CSR0_FLUSHFIFO;
+- musb_writew(epio, MUSB_CSR0, csr);
+- musb_writew(epio, MUSB_CSR0, csr);
+- csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+- musb_writew(epio, MUSB_CSR0, csr);
++ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ musb_writeb(epio, MUSB_NAKLIMIT0, 0);
+@@ -1081,9 +1096,6 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
+ * SHOULD NEVER HAPPEN! */
+ ERR("no URB for end 0\n");
+
+- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO);
+- musb_writew(epio, MUSB_CSR0, 0);
+
+ goto done;
+ }
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
new file mode 100644
index 0000000000..bcbe3bbe39
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
@@ -0,0 +1,361 @@
+From c99f4a68268801a2e2ffbef9766c3ac89e4fb22c Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Thu, 26 Mar 2009 18:27:47 -0700
+Subject: [PATCH] musb: sanitize clearing TXCSR DMA bits (take 2)
+
+The MUSB code clears TXCSR_DMAMODE incorrectly in several
+places, either asserting that TXCSR_DMAENAB is clear (when
+sometimes it isn't) or clearing both bits together. Recent
+versions of the programmer's guide require DMAENAB to be
+cleared first, although some older ones didn't.
+
+Fix this and while at it:
+
+ - In musb_gadget::txstate(), stop clearing the AUTOSET
+ and DMAMODE bits for the CPPI case since they never
+ get set anyway (the former bit is reserved on DaVinci);
+ but do clear the DMAENAB bit on the DMA error path.
+
+ - In musb_host::musb_ep_program(), remove the duplicate
+ DMA controller specific code code clearing the TXCSR
+ previous state, add the code to clear TXCSR DMA bits
+ on the Inventra DMA error path, to replace such code
+ (executed late) on the PIO path.
+
+ - In musbhsdma::dma_channel_abort()/dma_controller_irq(),
+ add/use the 'offset' variable to avoid MUSB_EP_OFFSET()
+ invocations on every RXCSR/TXCSR access.
+
+[dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: don't introduce CamelCase,
+shrink diff]
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_gadget.c | 33 +++++++++++------
+ drivers/usb/musb/musb_host.c | 79 ++++++++++++++++------------------------
+ drivers/usb/musb/musbhsdma.c | 59 ++++++++++++++++++------------
+ 3 files changed, 90 insertions(+), 81 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index c7ebd08..f79440c 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status)
+ if (is_dma_capable() && ep->dma) {
+ struct dma_controller *c = ep->musb->dma_controller;
+ int value;
++
+ if (ep->is_in) {
++ /*
++ * The programming guide says that we must not clear
++ * the DMAMODE bit before DMAENAB, so we only
++ * clear it in the second write...
++ */
+ musb_writew(epio, MUSB_TXCSR,
+- 0 | MUSB_TXCSR_FLUSHFIFO);
++ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
+ musb_writew(epio, MUSB_TXCSR,
+ 0 | MUSB_TXCSR_FLUSHFIFO);
+ } else {
+@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
+ | IN token(s) are recd from Host.
+ | -> DMA interrupt on completion
+ | calls TxAvail.
+- | -> stop DMA, ~DmaEenab,
++ | -> stop DMA, ~DMAENAB,
+ | -> set TxPktRdy for last short pkt or zlp
+ | -> Complete Request
+ | -> Continue next request (call txstate)
+@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req)
+ request->dma, request_size);
+ if (use_dma) {
+ if (musb_ep->dma->desired_mode == 0) {
+- /* ASSERT: DMAENAB is clear */
+- csr &= ~(MUSB_TXCSR_AUTOSET |
+- MUSB_TXCSR_DMAMODE);
++ /*
++ * We must not clear the DMAMODE bit
++ * before the DMAENAB bit -- and the
++ * latter doesn't always get cleared
++ * before we get here...
++ */
++ csr &= ~(MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAENAB);
++ musb_writew(epio, MUSB_TXCSR, csr
++ | MUSB_TXCSR_P_WZC_BITS);
++ csr &= ~MUSB_TXCSR_DMAMODE;
+ csr |= (MUSB_TXCSR_DMAENAB |
+ MUSB_TXCSR_MODE);
+ /* against programming guide */
+@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
+
+ #elif defined(CONFIG_USB_TI_CPPI_DMA)
+ /* program endpoint CSR first, then setup DMA */
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_P_UNDERRUN
+- | MUSB_TXCSR_TXPKTRDY);
++ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+ csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
+ musb_writew(epio, MUSB_TXCSR,
+ (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
+@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
+ if (!use_dma) {
+ c->channel_release(musb_ep->dma);
+ musb_ep->dma = NULL;
+- /* ASSERT: DMAENAB clear */
+- csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
++ csr &= ~MUSB_TXCSR_DMAENAB;
++ musb_writew(epio, MUSB_TXCSR, csr);
+ /* invariant: prequest->buf is non-null */
+ }
+ #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index a5d75aa..6591282 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -590,10 +590,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_MODE) {
+ musb_h_tx_flush_fifo(ep);
++ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ musb_writew(ep->regs, MUSB_TXCSR,
+- MUSB_TXCSR_FRCDATATOG);
++ csr | MUSB_TXCSR_FRCDATATOG);
+ }
+- /* clear mode (and everything else) to enable Rx */
++
++ /*
++ * Clear the MODE bit (and everything else) to enable Rx.
++ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
++ */
++ if (csr & MUSB_TXCSR_DMAMODE)
++ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
+ musb_writew(ep->regs, MUSB_TXCSR, 0);
+
+ /* scrub all previous state, clearing toggle */
+@@ -690,12 +697,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+
+ /* general endpoint setup */
+ if (epnum) {
+- /* ASSERT: TXCSR_DMAENAB was already cleared */
+-
+ /* flush all old state, set default */
+ musb_h_tx_flush_fifo(hw_ep);
++
++ /*
++ * We must not clear the DMAMODE bit before or in
++ * the same cycle with the DMAENAB bit, so we clear
++ * the latter first...
++ */
+ csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
+- | MUSB_TXCSR_DMAMODE
++ | MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_FRCDATATOG
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_ERROR
+@@ -703,16 +715,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ );
+ csr |= MUSB_TXCSR_MODE;
+
+- if (usb_gettoggle(urb->dev,
+- qh->epnum, 1))
++ if (usb_gettoggle(urb->dev, qh->epnum, 1))
+ csr |= MUSB_TXCSR_H_WR_DATATOGGLE
+ | MUSB_TXCSR_H_DATATOGGLE;
+ else
+ csr |= MUSB_TXCSR_CLRDATATOG;
+
+- /* twice in case of double packet buffering */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
++ csr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+@@ -755,34 +766,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+
+ #ifdef CONFIG_USB_INVENTRA_DMA
+ if (dma_channel) {
+-
+- /* clear previous state */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_DMAENAB);
+- csr |= MUSB_TXCSR_MODE;
+- musb_writew(epio, MUSB_TXCSR,
+- csr | MUSB_TXCSR_MODE);
+-
+ qh->segsize = min(len, dma_channel->max_len);
+-
+ if (qh->segsize <= packet_sz)
+ dma_channel->desired_mode = 0;
+ else
+ dma_channel->desired_mode = 1;
+
+-
+ if (dma_channel->desired_mode == 0) {
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE);
++ /* Against the programming guide */
+ csr |= (MUSB_TXCSR_DMAENAB);
+- /* against programming guide */
+ } else
+ csr |= (MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_DMAMODE);
+-
+ musb_writew(epio, MUSB_TXCSR, csr);
+
+ dma_ok = dma_controller->channel_program(
+@@ -799,6 +795,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ else
+ hw_ep->rx_channel = NULL;
+ dma_channel = NULL;
++
++ /*
++ * The programming guide says that we must
++ * clear the DMAENAB bit before DMAMODE...
++ */
++ csr = musb_readw(epio, MUSB_TXCSR);
++ csr &= ~(MUSB_TXCSR_DMAENAB
++ | MUSB_TXCSR_AUTOSET);
++ musb_writew(epio, MUSB_TXCSR, csr);
++ csr &= ~MUSB_TXCSR_DMAMODE;
++ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+ }
+ #endif
+@@ -806,18 +813,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ /* candidate for DMA */
+ if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+
+- /* program endpoint CSRs first, then setup DMA.
+- * assume CPPI setup succeeds.
+- * defer enabling dma.
+- */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_DMAENAB);
+- csr |= MUSB_TXCSR_MODE;
+- musb_writew(epio, MUSB_TXCSR,
+- csr | MUSB_TXCSR_MODE);
+-
++ /* Defer enabling DMA */
+ dma_channel->actual_len = 0L;
+ qh->segsize = len;
+
+@@ -846,20 +842,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ }
+
+ if (load_count) {
+- /* ASSERT: TXCSR_DMAENAB was already cleared */
+-
+ /* PIO to load FIFO */
+ qh->segsize = load_count;
+ musb_write_fifo(hw_ep, load_count, buf);
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_AUTOSET);
+- /* write CSR */
+- csr |= MUSB_TXCSR_MODE;
+-
+- if (epnum)
+- musb_writew(epio, MUSB_TXCSR, csr);
+ }
+
+ /* re-enable interrupt */
+diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
+index 8662e9e..40709c3 100644
+--- a/drivers/usb/musb/musbhsdma.c
++++ b/drivers/usb/musb/musbhsdma.c
+@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
+ void __iomem *mbase = musb_channel->controller->base;
+
+ u8 bchannel = musb_channel->idx;
++ int offset;
+ u16 csr;
+
+ if (channel->status == MUSB_DMA_STATUS_BUSY) {
+ if (musb_channel->transmit) {
+-
+- csr = musb_readw(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum,
+- MUSB_TXCSR));
+- csr &= ~(MUSB_TXCSR_AUTOSET |
+- MUSB_TXCSR_DMAENAB |
+- MUSB_TXCSR_DMAMODE);
+- musb_writew(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
+- csr);
++ offset = MUSB_EP_OFFSET(musb_channel->epnum,
++ MUSB_TXCSR);
++
++ /*
++ * The programming guide says that we must clear
++ * the DMAENAB bit before the DMAMODE bit...
++ */
++ csr = musb_readw(mbase, offset);
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
++ musb_writew(mbase, offset, csr);
++ csr &= ~MUSB_TXCSR_DMAMODE;
++ musb_writew(mbase, offset, csr);
+ } else {
+- csr = musb_readw(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum,
+- MUSB_RXCSR));
++ offset = MUSB_EP_OFFSET(musb_channel->epnum,
++ MUSB_RXCSR);
++
++ csr = musb_readw(mbase, offset);
+ csr &= ~(MUSB_RXCSR_AUTOCLEAR |
+ MUSB_RXCSR_DMAENAB |
+ MUSB_RXCSR_DMAMODE);
+- musb_writew(mbase,
+- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
+- csr);
++ musb_writew(mbase, offset, csr);
+ }
+
+ musb_writew(mbase,
+@@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
+ && ((channel->desired_mode == 0)
+ || (channel->actual_len &
+ (musb_channel->max_packet_sz - 1)))
+- ) {
++ ) {
++ u8 epnum = musb_channel->epnum;
++ int offset = MUSB_EP_OFFSET(epnum,
++ MUSB_TXCSR);
++ u16 txcsr;
++
++ /*
++ * The programming guide says that we
++ * must clear DMAENAB before DMAMODE.
++ */
++ musb_ep_select(mbase, epnum);
++ txcsr = musb_readw(mbase, offset);
++ txcsr &= ~(MUSB_TXCSR_DMAENAB
++ | MUSB_TXCSR_AUTOSET);
++ musb_writew(mbase, offset, txcsr);
+ /* Send out the packet */
+- musb_ep_select(mbase,
+- musb_channel->epnum);
+- musb_writew(mbase, MUSB_EP_OFFSET(
+- musb_channel->epnum,
+- MUSB_TXCSR),
+- MUSB_TXCSR_TXPKTRDY);
++ txcsr &= ~MUSB_TXCSR_DMAMODE;
++ txcsr |= MUSB_TXCSR_TXPKTRDY;
++ musb_writew(mbase, offset, txcsr);
+ } else {
+ musb_dma_completion(
+ musb,
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
new file mode 100644
index 0000000000..7d546e10b0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
@@ -0,0 +1,417 @@
+From 035cd4a26e9b1638b4b0419b98409026176563ca Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Thu, 26 Mar 2009 18:29:19 -0700
+Subject: [PATCH] musb: fix isochronous TXDMA (take 2)
+
+Multi-frame isochronous TX URBs transfers in DMA mode never
+complete with CPPI DMA because musb_host_tx() doesn't restart
+DMA on the second frame, only emitting a debug message.
+With Inventra DMA they complete, but in PIO mode. To fix:
+
+ - Factor out programming of the DMA transfer from
+ musb_ep_program() into musb_tx_dma_program();
+
+ - Reorder the code at the end of musb_host_tx() to
+ facilitate the fallback to PIO iff DMA fails;
+
+ - Handle the buffer offset consistently for both
+ PIO and DMA modes;
+
+ - Add an argument to musb_ep_program() for the same
+ reason (it only worked correctly with non-zero
+ offset of the first frame in PIO mode);
+
+ - Set the completed isochronous frame descriptor's
+ 'actual_length' and 'status' fields correctly in
+ DMA mode.
+
+Also, since CPPI reportedly doesn't like sending isochronous
+packets in the RNDIS mode, change the criterion for this
+mode to be used only for multi-packet transfers. (There's
+no need for that mode in the single-packet case anyway.)
+
+[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: split comment paragraph
+into bullet list, shrink patch delta, style tweaks ]
+
+Signed-off-by: Pavel Kiryukhin <pkiryukhin-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/cppi_dma.c | 1 +
+ drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++-----------------------
+ 2 files changed, 105 insertions(+), 123 deletions(-)
+
+diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
+index 569ef0f..ac7227c 100644
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
+ * trigger the "send a ZLP?" confusion.
+ */
+ rndis = (maxpacket & 0x3f) == 0
++ && length > maxpacket
+ && length < 0xffff
+ && (length % maxpacket) != 0;
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 6591282..f6e84a0 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -96,8 +96,8 @@
+
+
+ static void musb_ep_program(struct musb *musb, u8 epnum,
+- struct urb *urb, unsigned int nOut,
+- u8 *buf, u32 len);
++ struct urb *urb, int is_out,
++ u8 *buf, u32 offset, u32 len);
+
+ /*
+ * Clear TX fifo. Needed to avoid BABBLE errors.
+@@ -189,9 +189,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ {
+ u16 frame;
+ u32 len;
+- void *buf;
+ void __iomem *mbase = musb->mregs;
+ struct urb *urb = next_urb(qh);
++ void *buf = urb->transfer_buffer;
++ u32 offset = 0;
+ struct musb_hw_ep *hw_ep = qh->hw_ep;
+ unsigned pipe = urb->pipe;
+ u8 address = usb_pipedevice(pipe);
+@@ -214,7 +215,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ case USB_ENDPOINT_XFER_ISOC:
+ qh->iso_idx = 0;
+ qh->frame = 0;
+- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
++ offset = urb->iso_frame_desc[0].offset;
+ len = urb->iso_frame_desc[0].length;
+ break;
+ default: /* bulk, interrupt */
+@@ -232,14 +233,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
+ default: s = "-intr"; break;
+ }; s; }),
+- epnum, buf, len);
++ epnum, buf + offset, len);
+
+ /* Configure endpoint */
+ if (is_in || hw_ep->is_shared_fifo)
+ hw_ep->in_qh = qh;
+ else
+ hw_ep->out_qh = qh;
+- musb_ep_program(musb, epnum, urb, !is_in, buf, len);
++ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
+
+ /* transmit may have more work: start it when it is time */
+ if (is_in)
+@@ -250,7 +251,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_INT:
+ DBG(3, "check whether there's still time for periodic Tx\n");
+- qh->iso_idx = 0;
+ frame = musb_readw(mbase, MUSB_FRAME);
+ /* FIXME this doesn't implement that scheduling policy ...
+ * or handle framecounter wrapping
+@@ -631,14 +631,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+ ep->rx_reinit = 0;
+ }
+
++static bool musb_tx_dma_program(struct dma_controller *dma,
++ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
++ struct urb *urb, u32 offset, u32 length)
++{
++ struct dma_channel *channel = hw_ep->tx_channel;
++ void __iomem *epio = hw_ep->regs;
++ u16 pkt_size = qh->maxpacket;
++ u16 csr;
++ u8 mode;
++
++#ifdef CONFIG_USB_INVENTRA_DMA
++ if (length > channel->max_len)
++ length = channel->max_len;
++
++ csr = musb_readw(epio, MUSB_TXCSR);
++ if (length > pkt_size) {
++ mode = 1;
++ csr |= MUSB_TXCSR_AUTOSET
++ | MUSB_TXCSR_DMAMODE
++ | MUSB_TXCSR_DMAENAB;
++ } else {
++ mode = 0;
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
++ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
++ }
++ channel->desired_mode = mode;
++ musb_writew(epio, MUSB_TXCSR, csr);
++#else
++ if (!is_cppi_enabled() && !tusb_dma_omap())
++ return false;
++
++ channel->actual_len = 0;
++
++ /*
++ * TX uses "RNDIS" mode automatically but needs help
++ * to identify the zero-length-final-packet case.
++ */
++ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
++#endif
++
++ qh->segsize = length;
++
++ if (!dma->channel_program(channel, pkt_size, mode,
++ urb->transfer_dma + offset, length)) {
++ dma->channel_release(channel);
++ hw_ep->tx_channel = NULL;
++
++ csr = musb_readw(epio, MUSB_TXCSR);
++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
++ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
++ return false;
++ }
++ return true;
++}
+
+ /*
+ * Program an HDRC endpoint as per the given URB
+ * Context: irqs blocked, controller lock held
+ */
+ static void musb_ep_program(struct musb *musb, u8 epnum,
+- struct urb *urb, unsigned int is_out,
+- u8 *buf, u32 len)
++ struct urb *urb, int is_out,
++ u8 *buf, u32 offset, u32 len)
+ {
+ struct dma_controller *dma_controller;
+ struct dma_channel *dma_channel;
+@@ -764,82 +818,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ else
+ load_count = min((u32) packet_sz, len);
+
+-#ifdef CONFIG_USB_INVENTRA_DMA
+- if (dma_channel) {
+- qh->segsize = min(len, dma_channel->max_len);
+- if (qh->segsize <= packet_sz)
+- dma_channel->desired_mode = 0;
+- else
+- dma_channel->desired_mode = 1;
+-
+- if (dma_channel->desired_mode == 0) {
+- /* Against the programming guide */
+- csr |= (MUSB_TXCSR_DMAENAB);
+- } else
+- csr |= (MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_DMAMODE);
+- musb_writew(epio, MUSB_TXCSR, csr);
+-
+- dma_ok = dma_controller->channel_program(
+- dma_channel, packet_sz,
+- dma_channel->desired_mode,
+- urb->transfer_dma,
+- qh->segsize);
+- if (dma_ok) {
+- load_count = 0;
+- } else {
+- dma_controller->channel_release(dma_channel);
+- if (is_out)
+- hw_ep->tx_channel = NULL;
+- else
+- hw_ep->rx_channel = NULL;
+- dma_channel = NULL;
+-
+- /*
+- * The programming guide says that we must
+- * clear the DMAENAB bit before DMAMODE...
+- */
+- csr = musb_readw(epio, MUSB_TXCSR);
+- csr &= ~(MUSB_TXCSR_DMAENAB
+- | MUSB_TXCSR_AUTOSET);
+- musb_writew(epio, MUSB_TXCSR, csr);
+- csr &= ~MUSB_TXCSR_DMAMODE;
+- musb_writew(epio, MUSB_TXCSR, csr);
+- }
+- }
+-#endif
+-
+- /* candidate for DMA */
+- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+-
+- /* Defer enabling DMA */
+- dma_channel->actual_len = 0L;
+- qh->segsize = len;
+-
+- /* TX uses "rndis" mode automatically, but needs help
+- * to identify the zero-length-final-packet case.
+- */
+- dma_ok = dma_controller->channel_program(
+- dma_channel, packet_sz,
+- (urb->transfer_flags
+- & URB_ZERO_PACKET)
+- == URB_ZERO_PACKET,
+- urb->transfer_dma,
+- qh->segsize);
+- if (dma_ok) {
+- load_count = 0;
+- } else {
+- dma_controller->channel_release(dma_channel);
+- hw_ep->tx_channel = NULL;
+- dma_channel = NULL;
+-
+- /* REVISIT there's an error path here that
+- * needs handling: can't do dma, but
+- * there's no pio buffer address...
+- */
+- }
+- }
++ if (dma_channel && musb_tx_dma_program(dma_controller,
++ hw_ep, qh, urb, offset, len))
++ load_count = 0;
+
+ if (load_count) {
+ /* PIO to load FIFO */
+@@ -899,7 +880,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ dma_channel, packet_sz,
+ !(urb->transfer_flags
+ & URB_SHORT_NOT_OK),
+- urb->transfer_dma,
++ urb->transfer_dma + offset,
+ qh->segsize);
+ if (!dma_ok) {
+ dma_controller->channel_release(
+@@ -1142,8 +1123,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ int pipe;
+ bool done = false;
+ u16 tx_csr;
+- size_t wLength = 0;
+- u8 *buf = NULL;
++ size_t length = 0;
++ size_t offset = 0;
+ struct urb *urb;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+@@ -1161,7 +1142,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ /* with CPPI, DMA sometimes triggers "extra" irqs */
+ if (!urb) {
+ DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+- goto finish;
++ return;
+ }
+
+ pipe = urb->pipe;
+@@ -1198,7 +1179,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS
+ | MUSB_TXCSR_TXPKTRDY);
+- goto finish;
++ return;
+ }
+
+ if (status) {
+@@ -1230,29 +1211,28 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ /* second cppi case */
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+- goto finish;
+-
++ return;
+ }
+
+- /* REVISIT this looks wrong... */
+ if (!status || dma || usb_pipeisoc(pipe)) {
+ if (dma)
+- wLength = dma->actual_len;
++ length = dma->actual_len;
+ else
+- wLength = qh->segsize;
+- qh->offset += wLength;
++ length = qh->segsize;
++ qh->offset += length;
+
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+- d->actual_length = qh->segsize;
++ d->actual_length = length;
++ d->status = status;
+ if (++qh->iso_idx >= urb->number_of_packets) {
+ done = true;
+ } else {
+ d++;
+- buf = urb->transfer_buffer + d->offset;
+- wLength = d->length;
++ offset = d->offset;
++ length = d->length;
+ }
+ } else if (dma) {
+ done = true;
+@@ -1265,10 +1245,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ & URB_ZERO_PACKET))
+ done = true;
+ if (!done) {
+- buf = urb->transfer_buffer
+- + qh->offset;
+- wLength = urb->transfer_buffer_length
+- - qh->offset;
++ offset = qh->offset;
++ length = urb->transfer_buffer_length - offset;
+ }
+ }
+ }
+@@ -1287,28 +1265,31 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ urb->status = status;
+ urb->actual_length = qh->offset;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
++ return;
++ } else if (usb_pipeisoc(pipe) && dma) {
++ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
++ offset, length))
++ return;
++ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
++ DBG(1, "not complete, but DMA enabled?\n");
++ return;
++ }
+
+- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
+- /* WARN_ON(!buf); */
+-
+- /* REVISIT: some docs say that when hw_ep->tx_double_buffered,
+- * (and presumably, fifo is not half-full) we should write TWO
+- * packets before updating TXCSR ... other docs disagree ...
+- */
+- /* PIO: start next packet in this URB */
+- if (wLength > qh->maxpacket)
+- wLength = qh->maxpacket;
+- musb_write_fifo(hw_ep, wLength, buf);
+- qh->segsize = wLength;
+-
+- musb_ep_select(mbase, epnum);
+- musb_writew(epio, MUSB_TXCSR,
+- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+- } else
+- DBG(1, "not complete, but dma enabled?\n");
++ /*
++ * PIO: start next packet in this URB.
++ *
++ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
++ * (and presumably, FIFO is not half-full) we should write *two*
++ * packets before updating TXCSR; other docs disagree...
++ */
++ if (length > qh->maxpacket)
++ length = qh->maxpacket;
++ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
++ qh->segsize = length;
+
+-finish:
+- return;
++ musb_ep_select(mbase, epnum);
++ musb_writew(epio, MUSB_TXCSR,
++ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+ }
+
+
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch
new file mode 100644
index 0000000000..2bbde84c16
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch
@@ -0,0 +1,56 @@
+From b9a61b80ea89d9d6d78a23d96a28df94fd612298 Mon Sep 17 00:00:00 2001
+From: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
+Date: Thu, 26 Mar 2009 18:56:51 -0700
+Subject: [PATCH] musb: fix possible panic while resuming
+
+During driver resume processing, musb could cause a kernel panic.
+Fix by enabling the clock earlier, with the resume_early method.
+
+Signed-off-by: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 8 ++------
+ 1 files changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 338cd16..3019725 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2170,16 +2170,13 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
+ return 0;
+ }
+
+-static int musb_resume(struct platform_device *pdev)
++static int musb_resume_early(struct platform_device *pdev)
+ {
+- unsigned long flags;
+ struct musb *musb = dev_to_musb(&pdev->dev);
+
+ if (!musb->clock)
+ return 0;
+
+- spin_lock_irqsave(&musb->lock, flags);
+-
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 1);
+ else
+@@ -2189,7 +2186,6 @@ static int musb_resume(struct platform_device *pdev)
+ * unless for some reason the whole soc powered down and we're
+ * not treating that as a whole-system restart (e.g. swsusp)
+ */
+- spin_unlock_irqrestore(&musb->lock, flags);
+ return 0;
+ }
+
+@@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = {
+ .remove = __devexit_p(musb_remove),
+ .shutdown = musb_shutdown,
+ .suspend = musb_suspend,
+- .resume = musb_resume,
++ .resume_early = musb_resume_early,
+ };
+
+ /*-------------------------------------------------------------------------*/
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch
new file mode 100644
index 0000000000..0202871d41
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch
@@ -0,0 +1,91 @@
+From 2658f7c9029967501cd4d749364f2e02d02eebd5 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:54:21 -0700
+Subject: [PATCH] musb_host: refactor musb_save_toggle() (take 2)
+
+Refactor musb_save_toggle() as follows:
+
+ - replace 'struct musb_hw_ep *ep' parameter by 'struct
+ musb_qh *qh' to avoid re-calculating this value
+
+ - move usb_settogle() call out of the *if* operator.
+
+This is a net minor shrink of source and object code.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 35 ++++++++++++-----------------------
+ 1 files changed, 12 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index f6e84a0..dc32ce4 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -318,35 +318,24 @@ __acquires(musb->lock)
+ spin_lock(&musb->lock);
+ }
+
+-/* for bulk/interrupt endpoints only */
+-static inline void
+-musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb)
++/* For bulk/interrupt endpoints only */
++static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
++ struct urb *urb)
+ {
+- struct usb_device *udev = urb->dev;
++ void __iomem *epio = qh->hw_ep->regs;
+ u16 csr;
+- void __iomem *epio = ep->regs;
+- struct musb_qh *qh;
+
+- /* FIXME: the current Mentor DMA code seems to have
++ /*
++ * FIXME: the current Mentor DMA code seems to have
+ * problems getting toggle correct.
+ */
+
+- if (is_in || ep->is_shared_fifo)
+- qh = ep->in_qh;
++ if (is_in)
++ csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+ else
+- qh = ep->out_qh;
++ csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+
+- if (!is_in) {
+- csr = musb_readw(epio, MUSB_TXCSR);
+- usb_settoggle(udev, qh->epnum, 1,
+- (csr & MUSB_TXCSR_H_DATATOGGLE)
+- ? 1 : 0);
+- } else {
+- csr = musb_readw(epio, MUSB_RXCSR);
+- usb_settoggle(udev, qh->epnum, 0,
+- (csr & MUSB_RXCSR_H_DATATOGGLE)
+- ? 1 : 0);
+- }
++ usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
+ }
+
+ /* caller owns controller lock, irqs are blocked */
+@@ -362,7 +351,7 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+- musb_save_toggle(ep, is_in, urb);
++ musb_save_toggle(qh, is_in, urb);
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (status == 0 && urb->error_count)
+@@ -1362,7 +1351,7 @@ static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep)
+ urb->actual_length += dma->actual_len;
+ dma->actual_len = 0L;
+ }
+- musb_save_toggle(ep, 1, urb);
++ musb_save_toggle(cur_qh, 1, urb);
+
+ /* move cur_qh to end of queue */
+ list_move_tail(&cur_qh->ring, &musb->in_bulk);
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch
new file mode 100644
index 0000000000..08e08a8538
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch
@@ -0,0 +1,32 @@
+From 7766f2ea909b73f56d21746485069e02839b75f1 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:53:32 -0700
+Subject: [PATCH] musb_gadget: suppress "parasitic" TX interrupts with CPPI
+
+Suppress "parasitic" endpoint interrupts in the DMA mode
+when using CPPI DMA driver; they're caused by the MUSB gadget
+driver using the DMA request mode 0 instead of the mode 1.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_gadget.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index f79440c..bc197b2 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -349,7 +349,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
+ #elif defined(CONFIG_USB_TI_CPPI_DMA)
+ /* program endpoint CSR first, then setup DMA */
+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+- csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB;
++ csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
++ MUSB_TXCSR_MODE;
+ musb_writew(epio, MUSB_TXCSR,
+ (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
+ | csr);
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
new file mode 100644
index 0000000000..7115b152d9
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
@@ -0,0 +1,202 @@
+From 5424305125492a2417bde7c6d23ee4b84e25f6be Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:52:43 -0700
+Subject: [PATCH] musb_gadget: fix unhandled endpoint 0 IRQs
+
+The gadget EP0 code routinely ignores an interrupt at end of
+the data phase because of musb_g_ep0_giveback() resetting the
+state machine to "idle, waiting for SETUP" phase prematurely.
+
+The driver also prematurely leaves the status phase on
+receiving the SetupEnd interrupt.
+
+As there were still unhandled endpoint 0 interrupts happening
+from time to time after fixing these issues, there turned to
+be yet another culprit: two distinct gadget states collapsed
+into one.
+
+The (missing) state that comes after STATUS IN/OUT states was
+typically indiscernible from them since the corresponding
+interrupts tend to happen within too little period of time
+(due to only a zero-length status packet in between) and so
+they got coalesced; yet this state is not the same as the next
+one which is associated with the reception of a SETUP packet.
+
+Adding this extra state seems to have fixed the rest of the
+unhandled interrupts that generic_interrupt() and
+davinci_interrupt() hid by faking their result and only
+emitting a debug message -- so, stop doing that.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/davinci.c | 7 +----
+ drivers/usb/musb/musb_core.c | 8 +-----
+ drivers/usb/musb/musb_core.h | 3 +-
+ drivers/usb/musb/musb_gadget_ep0.c | 45 +++++++++++++++++++++++++++++++----
+ 4 files changed, 43 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index 2dc7606..399c435 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -357,12 +357,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+- /* REVISIT we sometimes get unhandled IRQs
+- * (e.g. ep0). not clear why...
+- */
+- if (retval != IRQ_HANDLED)
+- DBG(5, "unhandled? %08x\n", tmp);
+- return IRQ_HANDLED;
++ return retval;
+ }
+
+ int musb_platform_set_mode(struct musb *musb, u8 mode)
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 3019725..a1de43b 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1481,13 +1481,7 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+- /* REVISIT we sometimes get spurious IRQs on g_ep0
+- * not clear why...
+- */
+- if (retval != IRQ_HANDLED)
+- DBG(5, "spurious?\n");
+-
+- return IRQ_HANDLED;
++ return retval;
+ }
+
+ #else
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index adf1806..f56a56c 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -171,7 +171,8 @@ enum musb_h_ep0_state {
+
+ /* peripheral side ep0 states */
+ enum musb_g_ep0_state {
+- MUSB_EP0_STAGE_SETUP, /* idle, waiting for setup */
++ MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */
++ MUSB_EP0_STAGE_SETUP, /* received SETUP */
+ MUSB_EP0_STAGE_TX, /* IN data */
+ MUSB_EP0_STAGE_RX, /* OUT data */
+ MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */
+diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
+index 3f5e30d..ec0e899 100644
+--- a/drivers/usb/musb/musb_gadget_ep0.c
++++ b/drivers/usb/musb/musb_gadget_ep0.c
+@@ -4,6 +4,7 @@
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
++ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -58,7 +59,8 @@
+ static char *decode_ep0stage(u8 stage)
+ {
+ switch (stage) {
+- case MUSB_EP0_STAGE_SETUP: return "idle";
++ case MUSB_EP0_STAGE_IDLE: return "idle";
++ case MUSB_EP0_STAGE_SETUP: return "setup";
+ case MUSB_EP0_STAGE_TX: return "in";
+ case MUSB_EP0_STAGE_RX: return "out";
+ case MUSB_EP0_STAGE_ACKWAIT: return "wait";
+@@ -628,7 +630,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ musb_writew(regs, MUSB_CSR0,
+ csr & ~MUSB_CSR0_P_SENTSTALL);
+ retval = IRQ_HANDLED;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ csr = musb_readw(regs, MUSB_CSR0);
+ }
+
+@@ -636,7 +638,18 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ if (csr & MUSB_CSR0_P_SETUPEND) {
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND);
+ retval = IRQ_HANDLED;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ /* Transition into the early status phase */
++ switch (musb->ep0_state) {
++ case MUSB_EP0_STAGE_TX:
++ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
++ break;
++ case MUSB_EP0_STAGE_RX:
++ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
++ break;
++ default:
++ ERR("SetupEnd came in a wrong ep0stage %s",
++ decode_ep0stage(musb->ep0_state));
++ }
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* NOTE: request may need completion */
+ }
+@@ -697,11 +710,31 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ if (req)
+ musb_g_ep0_giveback(musb, req);
+ }
++
++ /*
++ * In case when several interrupts can get coalesced,
++ * check to see if we've already received a SETUP packet...
++ */
++ if (csr & MUSB_CSR0_RXPKTRDY)
++ goto setup;
++
++ retval = IRQ_HANDLED;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
++ break;
++
++ case MUSB_EP0_STAGE_IDLE:
++ /*
++ * This state is typically (but not always) indiscernible
++ * from the status states since the corresponding interrupts
++ * tend to happen within too little period of time (with only
++ * a zero-length packet in between) and so get coalesced...
++ */
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_SETUP:
++setup:
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ struct usb_ctrlrequest setup;
+ int handled = 0;
+@@ -783,7 +816,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ stall:
+ DBG(3, "stall (%d)\n", handled);
+ musb->ackpend |= MUSB_CSR0_P_SENDSTALL;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ finish:
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend);
+@@ -803,7 +836,7 @@ finish:
+ /* "can't happen" */
+ WARN_ON(1);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL);
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+ }
+
+@@ -959,7 +992,7 @@ static int musb_g_ep0_halt(struct usb_ep *e, int value)
+
+ csr |= MUSB_CSR0_P_SENDSTALL;
+ musb_writew(regs, MUSB_CSR0, csr);
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ musb->ackpend = 0;
+ break;
+ default:
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch
new file mode 100644
index 0000000000..a2f54ff47b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch
@@ -0,0 +1,146 @@
+From f9ca8154cf395ec00129f12016697ef610a826ff Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:55:16 -0700
+Subject: [PATCH] musb_host: factor out musb_ep_{get|set}_qh()
+
+Factor out the often used code to get/set the active 'qh'
+pointer for the hardware endpoint. Change the way the case
+of a shared FIFO is handled by setting *both* 'in_qh' and
+'out_qh' fields of 'struct musb_hw_ep'. That seems more
+consistent and makes getting to the current 'qh' easy when
+the code knows the direction beforehand.
+
+While at it, turn some assignments into intializers and
+fix declaration style in the vicinity.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 56 ++++++++++++++++-------------------------
+ 1 files changed, 22 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index dc32ce4..bc89079 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -178,6 +178,19 @@ static inline void cppi_host_txdma_start(struct musb_hw_ep *ep)
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+ }
+
++static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh)
++{
++ if (is_in != 0 || ep->is_shared_fifo)
++ ep->in_qh = qh;
++ if (is_in == 0 || ep->is_shared_fifo)
++ ep->out_qh = qh;
++}
++
++static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in)
++{
++ return is_in ? ep->in_qh : ep->out_qh;
++}
++
+ /*
+ * Start the URB at the front of an endpoint's queue
+ * end must be claimed from the caller.
+@@ -207,7 +220,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* control transfers always start with SETUP */
+ is_in = 0;
+- hw_ep->out_qh = qh;
+ musb->ep0_stage = MUSB_EP0_START;
+ buf = urb->setup_packet;
+ len = 8;
+@@ -236,10 +248,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ epnum, buf + offset, len);
+
+ /* Configure endpoint */
+- if (is_in || hw_ep->is_shared_fifo)
+- hw_ep->in_qh = qh;
+- else
+- hw_ep->out_qh = qh;
++ musb_ep_set_qh(hw_ep, is_in, qh);
+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
+
+ /* transmit may have more work: start it when it is time */
+@@ -374,11 +383,8 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+ else
+ ep->tx_reinit = 1;
+
+- /* clobber old pointers to this qh */
+- if (is_in || ep->is_shared_fifo)
+- ep->in_qh = NULL;
+- else
+- ep->out_qh = NULL;
++ /* Clobber old pointers to this qh */
++ musb_ep_set_qh(ep, is_in, NULL);
+ qh->hep->hcpriv = NULL;
+
+ switch (qh->type) {
+@@ -421,12 +427,7 @@ static void
+ musb_advance_schedule(struct musb *musb, struct urb *urb,
+ struct musb_hw_ep *hw_ep, int is_in)
+ {
+- struct musb_qh *qh;
+-
+- if (is_in || hw_ep->is_shared_fifo)
+- qh = hw_ep->in_qh;
+- else
+- qh = hw_ep->out_qh;
++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in);
+
+ if (urb->status == -EINPROGRESS)
+ qh = musb_giveback(qh, urb, 0);
+@@ -689,15 +690,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+- struct musb_qh *qh;
+- u16 packet_sz;
+-
+- if (!is_out || hw_ep->is_shared_fifo)
+- qh = hw_ep->in_qh;
+- else
+- qh = hw_ep->out_qh;
+-
+- packet_sz = qh->maxpacket;
++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out);
++ u16 packet_sz = qh->maxpacket;
+
+ DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s "
+ "h_addr%02x h_port%02x bytes %d\n",
+@@ -1114,17 +1108,14 @@ void musb_host_tx(struct musb *musb, u8 epnum)
+ u16 tx_csr;
+ size_t length = 0;
+ size_t offset = 0;
+- struct urb *urb;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+- struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh
+- : hw_ep->out_qh;
++ struct musb_qh *qh = hw_ep->out_qh;
++ struct urb *urb = next_urb(qh);
+ u32 status = 0;
+ void __iomem *mbase = musb->mregs;
+ struct dma_channel *dma;
+
+- urb = next_urb(qh);
+-
+ musb_ep_select(mbase, epnum);
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+
+@@ -1741,10 +1732,7 @@ static int musb_schedule(
+ epnum++, hw_ep++) {
+ int diff;
+
+- if (is_in || hw_ep->is_shared_fifo) {
+- if (hw_ep->in_qh != NULL)
+- continue;
+- } else if (hw_ep->out_qh != NULL)
++ if (musb_ep_get_qh(hw_ep, is_in) != NULL)
+ continue;
+
+ if (hw_ep == musb->bulk_ep)
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch
new file mode 100644
index 0000000000..4a520dff87
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch
@@ -0,0 +1,132 @@
+From 013056a09afd324e729d64b9a0e66a004604e1d6 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:58:31 -0700
+Subject: [PATCH] musb_host: refactor URB giveback
+
+As musb_advance_schedule() is now the only remaning
+caller of musb_giveback() (and the only valid context
+of such call), just fold the latter into the former
+and then rename __musb_giveback() into musb_giveback().
+
+This is a net minor shrink.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 54 +++++++++++++++--------------------------
+ 1 files changed, 20 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index bc89079..e833959 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -292,9 +292,8 @@ start:
+ }
+ }
+
+-/* caller owns controller lock, irqs are blocked */
+-static void
+-__musb_giveback(struct musb *musb, struct urb *urb, int status)
++/* Context: caller owns controller lock, IRQs are blocked */
++static void musb_giveback(struct musb *musb, struct urb *urb, int status)
+ __releases(musb->lock)
+ __acquires(musb->lock)
+ {
+@@ -347,14 +346,22 @@ static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
+ usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
+ }
+
+-/* caller owns controller lock, irqs are blocked */
+-static struct musb_qh *
+-musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
++/*
++ * Advance this hardware endpoint's queue, completing the specified URB and
++ * advancing to either the next URB queued to that qh, or else invalidating
++ * that qh and advancing to the next qh scheduled after the current one.
++ *
++ * Context: caller owns controller lock, IRQs are blocked
++ */
++static void musb_advance_schedule(struct musb *musb, struct urb *urb,
++ struct musb_hw_ep *hw_ep, int is_in)
+ {
++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in);
+ struct musb_hw_ep *ep = qh->hw_ep;
+- struct musb *musb = ep->musb;
+- int is_in = usb_pipein(urb->pipe);
+ int ready = qh->is_ready;
++ int status;
++
++ status = (urb->status == -EINPROGRESS) ? 0 : urb->status;
+
+ /* save toggle eagerly, for paranoia */
+ switch (qh->type) {
+@@ -363,13 +370,13 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+ musb_save_toggle(qh, is_in, urb);
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+- if (status == 0 && urb->error_count)
++ if (urb->error_count)
+ status = -EXDEV;
+ break;
+ }
+
+ qh->is_ready = 0;
+- __musb_giveback(musb, urb, status);
++ musb_giveback(musb, urb, status);
+ qh->is_ready = ready;
+
+ /* reclaim resources (and bandwidth) ASAP; deschedule it, and
+@@ -413,31 +420,10 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
+ break;
+ }
+ }
+- return qh;
+-}
+-
+-/*
+- * Advance this hardware endpoint's queue, completing the specified urb and
+- * advancing to either the next urb queued to that qh, or else invalidating
+- * that qh and advancing to the next qh scheduled after the current one.
+- *
+- * Context: caller owns controller lock, irqs are blocked
+- */
+-static void
+-musb_advance_schedule(struct musb *musb, struct urb *urb,
+- struct musb_hw_ep *hw_ep, int is_in)
+-{
+- struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in);
+-
+- if (urb->status == -EINPROGRESS)
+- qh = musb_giveback(qh, urb, 0);
+- else
+- qh = musb_giveback(qh, urb, urb->status);
+
+ if (qh != NULL && qh->is_ready) {
+ DBG(4, "... next ep%d %cX urb %p\n",
+- hw_ep->epnum, is_in ? 'R' : 'T',
+- next_urb(qh));
++ hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
+ musb_start_urb(musb, is_in, qh);
+ }
+ }
+@@ -2080,7 +2066,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+
+ ret = 0;
+ qh->is_ready = 0;
+- __musb_giveback(musb, urb, 0);
++ musb_giveback(musb, urb, 0);
+ qh->is_ready = ready;
+
+ /* If nothing else (usually musb_giveback) is using it
+@@ -2164,7 +2150,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+ * will activate any of these as it advances.
+ */
+ while (!list_empty(&hep->urb_list))
+- __musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
++ musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
+
+ hep->hcpriv = NULL;
+ list_del(&qh->ring);
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch
new file mode 100644
index 0000000000..bf3d6e7021
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch
@@ -0,0 +1,167 @@
+From b91b067c531c9322f3719951b07303e790b13475 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:59:46 -0700
+Subject: [PATCH] musb: split out CPPI interrupt handler
+
+As DaVinci DM646x has a dedicated CPPI DMA interrupt, replace
+cppi_completion() (which has always been kind of layering
+violation) by a complete CPPI interrupt handler.
+
+[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: only cppi_dma.c needs platform
+device header, not cppi_dma.h ]
+
+Signed-off-by: Dmitry Krivoschekov <dkrivoschekov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/cppi_dma.c | 34 +++++++++++++++++++++++++++++++---
+ drivers/usb/musb/cppi_dma.h | 6 ++++--
+ drivers/usb/musb/davinci.c | 14 ++++----------
+ 3 files changed, 39 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
+index ac7227c..6ff3c67 100644
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -6,6 +6,7 @@
+ * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci.
+ */
+
++#include <linux/platform_device.h>
+ #include <linux/usb.h>
+
+ #include "musb_core.h"
+@@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
+ return completed;
+ }
+
+-void cppi_completion(struct musb *musb, u32 rx, u32 tx)
++irqreturn_t cppi_interrupt(int irq, void *dev_id)
+ {
+- void __iomem *tibase;
+- int i, index;
++ struct musb *musb = dev_id;
+ struct cppi *cppi;
++ void __iomem *tibase;
+ struct musb_hw_ep *hw_ep = NULL;
++ u32 rx, tx;
++ int i, index;
+
+ cppi = container_of(musb->dma_controller, struct cppi, controller);
+
+ tibase = musb->ctrl_base;
+
++ tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
++ rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
++
++ if (!tx && !rx)
++ return IRQ_NONE;
++
++ DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx);
++
+ /* process TX channels */
+ for (index = 0; tx; tx = tx >> 1, index++) {
+ struct cppi_channel *tx_ch;
+@@ -1293,6 +1304,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx)
+
+ /* write to CPPI EOI register to re-enable interrupts */
+ musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
++
++ return IRQ_HANDLED;
+ }
+
+ /* Instantiate a software object representing a DMA controller. */
+@@ -1300,6 +1313,9 @@ struct dma_controller *__init
+ dma_controller_create(struct musb *musb, void __iomem *mregs)
+ {
+ struct cppi *controller;
++ struct device *dev = musb->controller;
++ struct platform_device *pdev = to_platform_device(dev);
++ int irq = platform_get_irq(pdev, 1);
+
+ controller = kzalloc(sizeof *controller, GFP_KERNEL);
+ if (!controller)
+@@ -1330,6 +1346,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs)
+ return NULL;
+ }
+
++ if (irq > 0) {
++ if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) {
++ dev_err(dev, "request_irq %d failed!\n", irq);
++ dma_controller_destroy(&controller->controller);
++ return NULL;
++ }
++ controller->irq = irq;
++ }
++
+ return &controller->controller;
+ }
+
+@@ -1342,6 +1367,9 @@ void dma_controller_destroy(struct dma_controller *c)
+
+ cppi = container_of(c, struct cppi, controller);
+
++ if (cppi->irq)
++ free_irq(cppi->irq, cppi->musb);
++
+ /* assert: caller stopped the controller first */
+ dma_pool_destroy(cppi->pool);
+
+diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h
+index 729b407..8a39de3 100644
+--- a/drivers/usb/musb/cppi_dma.h
++++ b/drivers/usb/musb/cppi_dma.h
+@@ -119,6 +119,8 @@ struct cppi {
+ void __iomem *mregs; /* Mentor regs */
+ void __iomem *tibase; /* TI/CPPI regs */
+
++ int irq;
++
+ struct cppi_channel tx[4];
+ struct cppi_channel rx[4];
+
+@@ -127,7 +129,7 @@ struct cppi {
+ struct list_head tx_complete;
+ };
+
+-/* irq handling hook */
+-extern void cppi_completion(struct musb *, u32 rx, u32 tx);
++/* CPPI IRQ handler */
++extern irqreturn_t cppi_interrupt(int, void *);
+
+ #endif /* end of ifndef _CPPI_DMA_H_ */
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index 399c435..9fd74bf 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -250,6 +250,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+ void __iomem *tibase = musb->ctrl_base;
++ struct cppi *cppi;
+ u32 tmp;
+
+ spin_lock_irqsave(&musb->lock, flags);
+@@ -266,16 +267,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+ /* CPPI interrupts share the same IRQ line, but have their own
+ * mask, state, "vector", and EOI registers.
+ */
+- if (is_cppi_enabled()) {
+- u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
+- u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
+-
+- if (cppi_tx || cppi_rx) {
+- DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx);
+- cppi_completion(musb, cppi_rx, cppi_tx);
+- retval = IRQ_HANDLED;
+- }
+- }
++ cppi = container_of(musb->dma_controller, struct cppi, controller);
++ if (is_cppi_enabled() && musb->dma_controller && !cppi->irq)
++ retval = cppi_interrupt(irq, __hci);
+
+ /* ack and handle non-CPPI interrupts */
+ tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch
new file mode 100644
index 0000000000..c0e57155c8
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch
@@ -0,0 +1,158 @@
+From 69242ddd26151d45f46011cf7abc581b14699fb2 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:56:26 -0700
+Subject: [PATCH] musb_host: simplify check for active URB
+
+The existance of the scheduling list shouldn't matter in
+determining whether there's currectly an URB executing on a
+hardware endpoint. What should actually matter is the 'in_qh'
+or 'out_qh' fields of the 'struct musb_hw_ep' -- those are
+set in musb_start_urb() and cleared in musb_giveback() when
+the endpoint's URB list drains. Hence we should be able to
+replace the big *switch* statements in musb_urb_dequeue()
+and musb_h_disable() with mere musb_ep_get_qh() calls...
+
+While at it, do some more changes:
+
+ - add 'is_in' variable to musb_urb_dequeue();
+
+ - remove the unnecessary 'epnum' variable from musb_h_disable();
+
+ - fix the comment style in the vicinity.
+
+This is a minor shrink of source and object code.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 72 ++++++++---------------------------------
+ 1 files changed, 14 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index e833959..e121e0e 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2008,14 +2008,14 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ struct musb *musb = hcd_to_musb(hcd);
+ struct musb_qh *qh;
+- struct list_head *sched;
+ unsigned long flags;
++ int is_in = usb_pipein(urb->pipe);
+ int ret;
+
+ DBG(4, "urb=%p, dev%d ep%d%s\n", urb,
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+- usb_pipein(urb->pipe) ? "in" : "out");
++ is_in ? "in" : "out");
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+@@ -2026,45 +2026,23 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ if (!qh)
+ goto done;
+
+- /* Any URB not actively programmed into endpoint hardware can be
++ /*
++ * Any URB not actively programmed into endpoint hardware can be
+ * immediately given back; that's any URB not at the head of an
+ * endpoint queue, unless someday we get real DMA queues. And even
+ * if it's at the head, it might not be known to the hardware...
+ *
+- * Otherwise abort current transfer, pending dma, etc.; urb->status
++ * Otherwise abort current transfer, pending DMA, etc.; urb->status
+ * has already been updated. This is a synchronous abort; it'd be
+ * OK to hold off until after some IRQ, though.
++ *
++ * NOTE: qh is invalid unless !list_empty(&hep->urb_list)
+ */
+- if (!qh->is_ready || urb->urb_list.prev != &qh->hep->urb_list)
+- ret = -EINPROGRESS;
+- else {
+- switch (qh->type) {
+- case USB_ENDPOINT_XFER_CONTROL:
+- sched = &musb->control;
+- break;
+- case USB_ENDPOINT_XFER_BULK:
+- if (qh->mux == 1) {
+- if (usb_pipein(urb->pipe))
+- sched = &musb->in_bulk;
+- else
+- sched = &musb->out_bulk;
+- break;
+- }
+- default:
+- /* REVISIT when we get a schedule tree, periodic
+- * transfers won't always be at the head of a
+- * singleton queue...
+- */
+- sched = NULL;
+- break;
+- }
+- }
+-
+- /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
+- if (ret < 0 || (sched && qh != first_qh(sched))) {
++ if (!qh->is_ready
++ || urb->urb_list.prev != &qh->hep->urb_list
++ || musb_ep_get_qh(qh->hw_ep, is_in) != qh) {
+ int ready = qh->is_ready;
+
+- ret = 0;
+ qh->is_ready = 0;
+ musb_giveback(musb, urb, 0);
+ qh->is_ready = ready;
+@@ -2088,13 +2066,11 @@ done:
+ static void
+ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+ {
+- u8 epnum = hep->desc.bEndpointAddress;
++ u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN;
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+- u8 is_in = epnum & USB_DIR_IN;
+ struct musb_qh *qh;
+ struct urb *urb;
+- struct list_head *sched;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+@@ -2102,31 +2078,11 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+ if (qh == NULL)
+ goto exit;
+
+- switch (qh->type) {
+- case USB_ENDPOINT_XFER_CONTROL:
+- sched = &musb->control;
+- break;
+- case USB_ENDPOINT_XFER_BULK:
+- if (qh->mux == 1) {
+- if (is_in)
+- sched = &musb->in_bulk;
+- else
+- sched = &musb->out_bulk;
+- break;
+- }
+- default:
+- /* REVISIT when we get a schedule tree, periodic transfers
+- * won't always be at the head of a singleton queue...
+- */
+- sched = NULL;
+- break;
+- }
+-
+- /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
++ /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
+
+- /* kick first urb off the hardware, if needed */
++ /* Kick the first URB off the hardware, if needed */
+ qh->is_ready = 0;
+- if (!sched || qh == first_qh(sched)) {
++ if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) {
+ urb = next_urb(qh);
+
+ /* make software (then hardware) stop ASAP */
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch
new file mode 100644
index 0000000000..d89eaadd61
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch
@@ -0,0 +1,58 @@
+From d408894fa4263440ed8a9e68566bacea7e6f6bed Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:57:50 -0700
+Subject: [PATCH] musb_host: streamline musb_cleanup_urb() calls
+
+The argument for the 'is_in' parameter of musb_cleanup_urb()
+is always extracted from an URB that's passed to the function.
+So that parameter is superfluous; remove it.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_host.c | 9 +++++----
+ 1 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index e121e0e..71e835e 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -1950,14 +1950,15 @@ done:
+ * called with controller locked, irqs blocked
+ * that hardware queue advances to the next transfer, unless prevented
+ */
+-static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
++static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
+ {
+ struct musb_hw_ep *ep = qh->hw_ep;
+ void __iomem *epio = ep->regs;
+ unsigned hw_end = ep->epnum;
+ void __iomem *regs = ep->musb->mregs;
+- u16 csr;
++ int is_in = usb_pipein(urb->pipe);
+ int status = 0;
++ u16 csr;
+
+ musb_ep_select(regs, hw_end);
+
+@@ -2056,7 +2057,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ kfree(qh);
+ }
+ } else
+- ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
++ ret = musb_cleanup_urb(urb, qh);
+ done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return ret;
+@@ -2090,7 +2091,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+ urb->status = -ESHUTDOWN;
+
+ /* cleanup */
+- musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
++ musb_cleanup_urb(urb, qh);
+
+ /* Then nuke all the others ... and advance the
+ * queue on hw_ep (e.g. bulk ring) when we're done.
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch
new file mode 100644
index 0000000000..d9733f92b0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch
@@ -0,0 +1,70 @@
+From c4804e5a447275553c55bbb0ab1748954cb8fbfc Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 31 Mar 2009 12:26:10 -0700
+Subject: [PATCH] twl4030-usb: fix minor reporting goofage
+
+Fix a reporting glitch in the twl4030 USB transceiver code.
+It wasn't properly distinguishing the two types of active
+USB link: ID grounded, vs not. In the current code that
+distinction doesn't much matter; in the future this bugfix
+should help support better USB controller communications.
+
+Provide a comment sorting out some of the cryptic bits of
+the manual: different sections use different names for
+key signals, and the register definitions don't help much
+without the explanations and diagrams.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/otg/twl4030-usb.c | 26 +++++++++++++++++++-------
+ 1 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
+index d9478d0..f740390 100644
+--- a/drivers/usb/otg/twl4030-usb.c
++++ b/drivers/usb/otg/twl4030-usb.c
+@@ -217,6 +217,7 @@
+
+ /* In module TWL4030_MODULE_PM_MASTER */
+ #define PROTECT_KEY 0x0E
++#define STS_HW_CONDITIONS 0x0F
+
+ /* In module TWL4030_MODULE_PM_RECEIVER */
+ #define VUSB_DEDICATED1 0x7D
+@@ -351,15 +352,26 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl)
+ int status;
+ int linkstat = USB_LINK_UNKNOWN;
+
+- /* STS_HW_CONDITIONS */
+- status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, 0x0f);
++ /*
++ * For ID/VBUS sensing, see manual section 15.4.8 ...
++ * except when using only battery backup power, two
++ * comparators produce VBUS_PRES and ID_PRES signals,
++ * which don't match docs elsewhere. But ... BIT(7)
++ * and BIT(2) of STS_HW_CONDITIONS, respectively, do
++ * seem to match up. If either is true the USB_PRES
++ * signal is active, the OTG module is activated, and
++ * its interrupt may be raised (may wake the system).
++ */
++ status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER,
++ STS_HW_CONDITIONS);
+ if (status < 0)
+ dev_err(twl->dev, "USB link status err %d\n", status);
+- else if (status & BIT(7))
+- linkstat = USB_LINK_VBUS;
+- else if (status & BIT(2))
+- linkstat = USB_LINK_ID;
+- else
++ else if (status & (BIT(7) | BIT(2))) {
++ if (status & BIT(2))
++ linkstat = USB_LINK_ID;
++ else
++ linkstat = USB_LINK_VBUS;
++ } else
+ linkstat = USB_LINK_NONE;
+
+ dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch
new file mode 100644
index 0000000000..16b5b9908b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch
@@ -0,0 +1,38 @@
+From ba59a0812ba0e223bd0af8f4dea6c971b6289696 Mon Sep 17 00:00:00 2001
+From: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org>
+Date: Thu, 2 Apr 2009 12:07:08 -0700
+Subject: [PATCH] musb: use dma mode 1 for TX if transfer size equals maxpacket (v2)
+
+Currently, with Inventra DMA, we use Mode 0 if transfer size is less
+than or equal to the endpoint's maxpacket size. This requires that
+we explicitly set TXPKTRDY for that transfer.
+
+However the musb_g_tx code will not set TXPKTRDY twice if the last
+transfer is exactly equal to maxpacket, even if request->zero is set.
+Using Mode 1 will solve this; a better fix might be in musb_g_tx().
+
+Without this change, musb will not correctly send out a ZLP if the
+last transfer is the maxpacket size and request->zero is set.
+
+Signed-off-by: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_gadget.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index bc197b2..e8f920c 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -310,7 +310,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
+ /* setup DMA, then program endpoint CSR */
+ request_size = min(request->length,
+ musb_ep->dma->max_len);
+- if (request_size <= musb_ep->packet_sz)
++ if (request_size < musb_ep->packet_sz)
+ musb_ep->dma->desired_mode = 0;
+ else
+ musb_ep->dma->desired_mode = 1;
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch
new file mode 100644
index 0000000000..3038dd171d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch
@@ -0,0 +1,187 @@
+From 2e049a88b729ae2fdc0ecdabad1857810bd62737 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Date: Fri, 3 Apr 2009 16:16:17 -0700
+Subject: [PATCH] musb: add high bandwidth ISO support
+
+Tested on OMAP3 host side with Creative (Live! Cam Optia) USB camera
+which uses high bandwidth isochronous IN endpoints. FIFO mode 4 is
+updated to provide the needed 4K endpoint buffer without breaking
+the g_nokia composite gadget configuration. (This is the only
+gadget driver known to use enough endpoints to notice the change.)
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 19 ++++++++---------
+ drivers/usb/musb/musb_core.h | 3 ++
+ drivers/usb/musb/musb_host.c | 47 +++++++++++++++++++++++++++++++----------
+ drivers/usb/musb/musb_host.h | 1 +
+ 4 files changed, 48 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index a1de43b..d953305 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1068,14 +1068,13 @@ static struct fifo_cfg __initdata mode_4_cfg[] = {
+ { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, },
+-{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 512, },
+-{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 512, },
+-{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 512, },
+-{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 512, },
+-{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 512, },
+-{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 512, },
+-{ .hw_ep_num = 13, .style = FIFO_TX, .maxpacket = 512, },
+-{ .hw_ep_num = 13, .style = FIFO_RX, .maxpacket = 512, },
++{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, },
++{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, },
++{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, },
++{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, },
++{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, },
++{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, },
++{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, },
+ { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+ { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+ };
+@@ -1335,11 +1334,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
+ }
+ if (reg & MUSB_CONFIGDATA_HBRXE) {
+ strcat(aInfo, ", HB-ISO Rx");
+- strcat(aInfo, " (X)"); /* no driver support */
++ musb->hb_iso_rx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_HBTXE) {
+ strcat(aInfo, ", HB-ISO Tx");
+- strcat(aInfo, " (X)"); /* no driver support */
++ musb->hb_iso_tx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_SOFTCONE)
+ strcat(aInfo, ", SoftConn");
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index f56a56c..0ac4faf 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -387,6 +387,9 @@ struct musb {
+ unsigned is_multipoint:1;
+ unsigned ignore_disconnect:1; /* during bus resets */
+
++ unsigned hb_iso_rx:1; /* high bandwidth iso rx? */
++ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */
++
+ #ifdef C_MP_TX
+ unsigned bulk_split:1;
+ #define can_bulk_split(musb,type) \
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 71e835e..ece5122 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -602,7 +602,8 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+ musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg);
+ musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg);
+ /* NOTE: bulk combining rewrites high bits of maxpacket */
+- musb_writew(ep->regs, MUSB_RXMAXP, qh->maxpacket);
++ musb_writew(ep->regs, MUSB_RXMAXP,
++ qh->maxpacket | ((qh->hb_mult - 1) << 11));
+
+ ep->rx_reinit = 0;
+ }
+@@ -624,9 +625,10 @@ static bool musb_tx_dma_program(struct dma_controller *dma,
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (length > pkt_size) {
+ mode = 1;
+- csr |= MUSB_TXCSR_AUTOSET
+- | MUSB_TXCSR_DMAMODE
+- | MUSB_TXCSR_DMAENAB;
++ csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB;
++ /* autoset shouldn't be set in high bandwidth */
++ if (qh->hb_mult == 1)
++ csr |= MUSB_TXCSR_AUTOSET;
+ } else {
+ mode = 0;
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
+@@ -1432,6 +1434,10 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ /* packet error reported later */
+ iso_err = true;
+ }
++ } else if (rx_csr & MUSB_RXCSR_INCOMPRX) {
++ DBG(3, "end %d high bandwidth incomplete ISO packet RX\n",
++ epnum);
++ status = -EPROTO;
+ }
+
+ /* faults abort the transfer */
+@@ -1639,7 +1645,11 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ val &= ~MUSB_RXCSR_H_AUTOREQ;
+ else
+ val |= MUSB_RXCSR_H_AUTOREQ;
+- val |= MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB;
++ val |= MUSB_RXCSR_DMAENAB;
++
++ /* autoclear shouldn't be set in high bandwidth */
++ if (qh->hb_mult == 1)
++ val |= MUSB_RXCSR_AUTOCLEAR;
+
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_H_WZC_BITS | val);
+@@ -1725,9 +1735,10 @@ static int musb_schedule(
+ continue;
+
+ if (is_in)
+- diff = hw_ep->max_packet_sz_rx - qh->maxpacket;
++ diff = hw_ep->max_packet_sz_rx;
+ else
+- diff = hw_ep->max_packet_sz_tx - qh->maxpacket;
++ diff = hw_ep->max_packet_sz_tx;
++ diff -= (qh->maxpacket * qh->hb_mult);
+
+ if (diff >= 0 && best_diff > diff) {
+ best_diff = diff;
+@@ -1830,15 +1841,27 @@ static int musb_urb_enqueue(
+ qh->is_ready = 1;
+
+ qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize);
++ qh->type = usb_endpoint_type(epd);
+
+- /* no high bandwidth support yet */
+- if (qh->maxpacket & ~0x7ff) {
+- ret = -EMSGSIZE;
+- goto done;
++ /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier.
++ * Some musb cores don't support high bandwidth ISO transfers; and
++ * we don't (yet!) support high bandwidth interrupt transfers.
++ */
++ qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03);
++ if (qh->hb_mult > 1) {
++ int ok = (qh->type == USB_ENDPOINT_XFER_ISOC);
++
++ if (ok)
++ ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx)
++ || (usb_pipeout(urb->pipe) && musb->hb_iso_tx);
++ if (!ok) {
++ ret = -EMSGSIZE;
++ goto done;
++ }
++ qh->maxpacket &= 0x7ff;
+ }
+
+ qh->epnum = usb_endpoint_num(epd);
+- qh->type = usb_endpoint_type(epd);
+
+ /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */
+ qh->addr_reg = (u8) usb_pipedevice(urb->pipe);
+diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
+index 0b7fbcd..14b0077 100644
+--- a/drivers/usb/musb/musb_host.h
++++ b/drivers/usb/musb/musb_host.h
+@@ -67,6 +67,7 @@ struct musb_qh {
+ u8 is_ready; /* safe to modify hw_ep */
+ u8 type; /* XFERTYPE_* */
+ u8 epnum;
++ u8 hb_mult; /* high bandwidth pkts per uf */
+ u16 maxpacket;
+ u16 frame; /* for periodic schedule */
+ unsigned iso_idx; /* in urb->iso_frame_desc[] */
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch
new file mode 100644
index 0000000000..67004d7ec6
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch
@@ -0,0 +1,259 @@
+From de835357b3597af5304742cbd89771d70533292a Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri, 6 Feb 2009 17:32:35 +0530
+Subject: [PATCH] USB: otg: adding nop usb transceiver
+
+NOP transceiver is used by all the usb transceiver which are mostly
+autonomous and doesn't require any programming or which are built
+into the usb ip itself.NOP transceiver only allocates the memory
+for struct xceiv and calls otg_set_transceiver() so function call
+to otg_get_transceiver() will return a valid transceiver.
+
+NOP transceiver device should be registered by calling
+usb_nop_xceiv_register() from platform files.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Cc: Felipe Balbi <felipe.balbi@nokia.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/otg/Kconfig | 8 ++
+ drivers/usb/otg/Makefile | 1 +
+ drivers/usb/otg/nop-usb-xceiv.c | 180 +++++++++++++++++++++++++++++++++++++++
+ include/linux/usb/otg.h | 4 +
+ 4 files changed, 193 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/usb/otg/nop-usb-xceiv.c
+
+diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
+index 5790a5b..aa884d0 100644
+--- a/drivers/usb/otg/Kconfig
++++ b/drivers/usb/otg/Kconfig
+@@ -51,4 +51,12 @@ config TWL4030_USB
+ This transceiver supports high and full speed devices plus,
+ in host mode, low speed.
+
++config NOP_USB_XCEIV
++ tristate "NOP USB Transceiver Driver"
++ select USB_OTG_UTILS
++ help
++ this driver is to be used by all the usb transceiver which are either
++ built-in with usb ip or which are autonomous and doesn't require any
++ phy programming such as ISP1x04 etc.
++
+ endif # USB || OTG
+diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
+index d73c7cf..2081678 100644
+--- a/drivers/usb/otg/Makefile
++++ b/drivers/usb/otg/Makefile
+@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o
+ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
+ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
+ obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
++obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
+
+ ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
+ ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+new file mode 100644
+index 0000000..4b933f6
+--- /dev/null
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -0,0 +1,180 @@
++/*
++ * drivers/usb/otg/nop-usb-xceiv.c
++ *
++ * NOP USB transceiver for all USB transceiver which are either built-in
++ * into USB IP or which are mostly autonomous.
++ *
++ * Copyright (C) 2009 Texas Instruments Inc
++ * Author: Ajay Kumar Gupta <ajay.gupta@ti.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Current status:
++ * this is to add "nop" transceiver for all those phy which is
++ * autonomous such as isp1504 etc.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/usb/otg.h>
++
++struct nop_usb_xceiv {
++ struct otg_transceiver otg;
++ struct device *dev;
++};
++
++static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
++
++static struct platform_device nop_xceiv_device = {
++ .name = "nop_usb_xceiv",
++ .id = -1,
++ .dev = {
++ .dma_mask = &nop_xceiv_dmamask,
++ .coherent_dma_mask = DMA_32BIT_MASK,
++ .platform_data = NULL,
++ },
++};
++
++void usb_nop_xceiv_register(void)
++{
++ if (platform_device_register(&nop_xceiv_device) < 0) {
++ printk(KERN_ERR "Unable to register usb nop transceiver\n");
++ return;
++ }
++}
++
++void usb_nop_xceiv_unregister(void)
++{
++ platform_device_unregister(&nop_xceiv_device);
++}
++
++static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x)
++{
++ return container_of(x, struct nop_usb_xceiv, otg);
++}
++
++static int nop_set_suspend(struct otg_transceiver *x, int suspend)
++{
++ return 0;
++}
++
++static int nop_set_peripheral(struct otg_transceiver *x,
++ struct usb_gadget *gadget)
++{
++ struct nop_usb_xceiv *nop;
++
++ if (!x)
++ return -ENODEV;
++
++ nop = xceiv_to_nop(x);
++
++ if (!gadget) {
++ nop->otg.gadget = NULL;
++ return -ENODEV;
++ }
++
++ nop->otg.gadget = gadget;
++ nop->otg.state = OTG_STATE_B_IDLE;
++ return 0;
++}
++
++static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host)
++{
++ struct nop_usb_xceiv *nop;
++
++ if (!x)
++ return -ENODEV;
++
++ nop = xceiv_to_nop(x);
++
++ if (!host) {
++ nop->otg.host = NULL;
++ return -ENODEV;
++ }
++
++ nop->otg.host = host;
++ return 0;
++}
++
++static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
++{
++ struct nop_usb_xceiv *nop;
++ int err;
++
++ nop = kzalloc(sizeof *nop, GFP_KERNEL);
++ if (!nop)
++ return -ENOMEM;
++
++ nop->dev = &pdev->dev;
++ nop->otg.dev = nop->dev;
++ nop->otg.label = "nop-xceiv";
++ nop->otg.state = OTG_STATE_UNDEFINED;
++ nop->otg.set_host = nop_set_host;
++ nop->otg.set_peripheral = nop_set_peripheral;
++ nop->otg.set_suspend = nop_set_suspend;
++
++ err = otg_set_transceiver(&nop->otg);
++ if (err) {
++ dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
++ err);
++ goto exit;
++ }
++
++ platform_set_drvdata(pdev, nop);
++
++ return 0;
++exit:
++ kfree(nop);
++ return err;
++}
++
++static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
++{
++ struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
++
++ otg_set_transceiver(NULL);
++
++ platform_set_drvdata(pdev, NULL);
++ kfree(nop);
++
++ return 0;
++}
++
++static struct platform_driver nop_usb_xceiv_driver = {
++ .probe = nop_usb_xceiv_probe,
++ .remove = __devexit_p(nop_usb_xceiv_remove),
++ .driver = {
++ .name = "nop_usb_xceiv",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init nop_usb_xceiv_init(void)
++{
++ return platform_driver_register(&nop_usb_xceiv_driver);
++}
++subsys_initcall(nop_usb_xceiv_init);
++
++static void __exit nop_usb_xceiv_exit(void)
++{
++ platform_driver_unregister(&nop_usb_xceiv_driver);
++}
++module_exit(nop_usb_xceiv_exit);
++
++MODULE_ALIAS("platform:nop_usb_xceiv");
++MODULE_AUTHOR("Texas Instruments Inc");
++MODULE_DESCRIPTION("NOP USB Transceiver driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index 94df4fe..54f2424 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -80,6 +80,10 @@ struct otg_transceiver {
+
+ /* for board-specific init logic */
+ extern int otg_set_transceiver(struct otg_transceiver *);
++#ifdef CONFIG_NOP_USB_XCEIV
++extern void usb_nop_xceiv_register(void);
++extern void usb_nop_xceiv_unregister(void);
++#endif
+
+
+ /* for usb host and peripheral controller drivers */
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch
new file mode 100644
index 0000000000..21fe7bea17
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch
@@ -0,0 +1,90 @@
+From ae4f027580168814f734cf3c41a662a7f10c744c Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 31 Mar 2009 12:28:31 -0700
+Subject: [PATCH] nop-usb-xceiv: behave when linked as a module
+
+The NOP OTG transceiver driver needs to be usable from modules.
+Make sure its symbols are always accessible at both compile and
+link time, and make sure the device instance is allocated from
+the heap so that device lifetime rules are obeyed.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/otg/nop-usb-xceiv.c | 25 ++++++++++---------------
+ include/linux/usb/otg.h | 4 ++--
+ 2 files changed, 12 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index 4b933f6..9ed5ea5 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -22,8 +22,8 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Current status:
+- * this is to add "nop" transceiver for all those phy which is
+- * autonomous such as isp1504 etc.
++ * This provides a "nop" transceiver for PHYs which are
++ * autonomous such as isp1504, isp1707, etc.
+ */
+
+ #include <linux/module.h>
+@@ -36,30 +36,25 @@ struct nop_usb_xceiv {
+ struct device *dev;
+ };
+
+-static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
+-
+-static struct platform_device nop_xceiv_device = {
+- .name = "nop_usb_xceiv",
+- .id = -1,
+- .dev = {
+- .dma_mask = &nop_xceiv_dmamask,
+- .coherent_dma_mask = DMA_32BIT_MASK,
+- .platform_data = NULL,
+- },
+-};
++static struct platform_device *pd;
+
+ void usb_nop_xceiv_register(void)
+ {
+- if (platform_device_register(&nop_xceiv_device) < 0) {
++ if (pd)
++ return;
++ pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
++ if (!pd) {
+ printk(KERN_ERR "Unable to register usb nop transceiver\n");
+ return;
+ }
+ }
++EXPORT_SYMBOL(usb_nop_xceiv_register);
+
+ void usb_nop_xceiv_unregister(void)
+ {
+- platform_device_unregister(&nop_xceiv_device);
++ platform_device_unregister(pd);
+ }
++EXPORT_SYMBOL(usb_nop_xceiv_unregister);
+
+ static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x)
+ {
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index 54f2424..7df8bae 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -80,10 +80,10 @@ struct otg_transceiver {
+
+ /* for board-specific init logic */
+ extern int otg_set_transceiver(struct otg_transceiver *);
+-#ifdef CONFIG_NOP_USB_XCEIV
++
++/* sometimes transceivers are accessed only through e.g. ULPI */
+ extern void usb_nop_xceiv_register(void);
+ extern void usb_nop_xceiv_unregister(void);
+-#endif
+
+
+ /* for usb host and peripheral controller drivers */
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch
new file mode 100644
index 0000000000..035a6c7676
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch
@@ -0,0 +1,1109 @@
+From 43ee46723ffa9dd43d611362064d235440aa04e7 Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 31 Mar 2009 12:30:04 -0700
+Subject: [PATCH] musb: proper hookup to transceiver drivers
+
+Let the otg_transceiver in MUSB be managed by an external driver;
+don't assume it's integrated. OMAP3 chips need it to be external,
+and there may be ways to interact with the transceiver which add
+functionality to the system.
+
+Platform init code is responsible for setting up the transeciver,
+probably using the NOP transceiver for integrated transceivers.
+External ones will use whatever the board init code provided,
+such as twl4030 or something more hands-off.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/Kconfig | 2 +
+ drivers/usb/musb/blackfin.c | 11 +++-
+ drivers/usb/musb/davinci.c | 33 +++++++++-----
+ drivers/usb/musb/musb_core.c | 96 +++++++++++++++++++++------------------
+ drivers/usb/musb/musb_core.h | 2 +-
+ drivers/usb/musb/musb_gadget.c | 38 +++++++--------
+ drivers/usb/musb/musb_host.c | 2 +-
+ drivers/usb/musb/musb_virthub.c | 20 ++++----
+ drivers/usb/musb/omap2430.c | 62 +++++++++----------------
+ drivers/usb/musb/tusb6010.c | 70 ++++++++++++++++++-----------
+ 10 files changed, 181 insertions(+), 155 deletions(-)
+
+diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
+index 9985db0..9eea991 100644
+--- a/drivers/usb/musb/Kconfig
++++ b/drivers/usb/musb/Kconfig
+@@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options"
+ config USB_MUSB_HDRC
+ depends on (USB || USB_GADGET) && HAVE_CLK
+ depends on !SUPERH
++ select NOP_USB_XCEIV if ARCH_DAVINCI
+ select TWL4030_USB if MACH_OMAP_3430SDP
+ select USB_OTG_UTILS
+ tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
+@@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support"
+ config USB_TUSB6010
+ boolean "TUSB 6010 support"
+ depends on USB_MUSB_HDRC && !USB_MUSB_SOC
++ select NOP_USB_XCEIV
+ default y
+ help
+ The TUSB 6010 chip, from Texas Instruments, connects a discrete
+diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
+index 7861348..f2f66eb 100644
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
+ u16 val;
+
+ spin_lock_irqsave(&musb->lock, flags);
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_IDLE:
+ case OTG_STATE_A_WAIT_BCON:
+ /* Start a new session */
+@@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
+ val = musb_readw(musb->mregs, MUSB_DEVCTL);
+ if (!(val & MUSB_DEVCTL_BDEVICE)) {
+ gpio_set_value(musb->config->gpio_vrsel, 1);
+- musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ } else {
+ gpio_set_value(musb->config->gpio_vrsel, 0);
+
+@@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb)
+ }
+ gpio_direction_output(musb->config->gpio_vrsel, 0);
+
++ usb_nop_xceiv_register();
++ musb->xceiv = otg_get_transceiver();
++ if (!musb->xceiv)
++ return -ENODEV;
++
+ if (ANOMALY_05000346) {
+ bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
+ SSYNC();
+@@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb)
+ musb_conn_timer_handler, (unsigned long) musb);
+ }
+ if (is_peripheral_enabled(musb))
+- musb->xceiv.set_power = bfin_set_power;
++ musb->xceiv->set_power = bfin_set_power;
+
+ musb->isr = blackfin_interrupt;
+
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index 9fd74bf..81de742 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -200,7 +200,7 @@ static void otg_timer(unsigned long _musb)
+ DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+ spin_lock_irqsave(&musb->lock, flags);
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_VFALL:
+ /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
+ * seems to mis-handle session "start" otherwise (or in our
+@@ -211,7 +211,7 @@ static void otg_timer(unsigned long _musb)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ break;
+ }
+- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
+ MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
+ break;
+@@ -236,7 +236,7 @@ static void otg_timer(unsigned long _musb)
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ else
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+ break;
+@@ -310,21 +310,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+ * to stop registering in devctl.
+ */
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ WARNING("VBUS error workaround (delay coming)\n");
+ } else if (is_host_enabled(musb) && drvvbus) {
+ musb->is_active = 1;
+ MUSB_HST_MODE(musb);
+- musb->xceiv.default_a = 1;
+- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
++ musb->xceiv->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+ del_timer(&otg_workaround);
+ } else {
+ musb->is_active = 0;
+ MUSB_DEV_MODE(musb);
+- musb->xceiv.default_a = 0;
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+ }
+
+@@ -346,7 +346,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+
+ /* poll for ID change */
+ if (is_otg_enabled(musb)
+- && musb->xceiv.state == OTG_STATE_B_IDLE)
++ && musb->xceiv->state == OTG_STATE_B_IDLE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+@@ -365,6 +365,11 @@ int __init musb_platform_init(struct musb *musb)
+ void __iomem *tibase = musb->ctrl_base;
+ u32 revision;
+
++ usb_nop_xceiv_register();
++ musb->xceiv = otg_get_transceiver();
++ if (!musb->xceiv)
++ return -ENODEV;
++
+ musb->mregs += DAVINCI_BASE_OFFSET;
+
+ clk_enable(musb->clock);
+@@ -372,7 +377,7 @@ int __init musb_platform_init(struct musb *musb)
+ /* returns zero if e.g. not clocked */
+ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
+ if (revision == 0)
+- return -ENODEV;
++ goto fail;
+
+ if (is_host_enabled(musb))
+ setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+@@ -396,6 +401,10 @@ int __init musb_platform_init(struct musb *musb)
+
+ musb->isr = davinci_interrupt;
+ return 0;
++
++fail:
++ usb_nop_xceiv_unregister();
++ return -ENODEV;
+ }
+
+ int musb_platform_exit(struct musb *musb)
+@@ -406,7 +415,7 @@ int musb_platform_exit(struct musb *musb)
+ davinci_source_power(musb, 0 /*off*/, 1);
+
+ /* delay, to avoid problems with module reload */
+- if (is_host_enabled(musb) && musb->xceiv.default_a) {
++ if (is_host_enabled(musb) && musb->xceiv->default_a) {
+ int maxdelay = 30;
+ u8 devctl, warn = 0;
+
+@@ -435,5 +444,7 @@ int musb_platform_exit(struct musb *musb)
+
+ clk_disable(musb->clock);
+
++ usb_nop_xceiv_unregister();
++
+ return 0;
+ }
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index d953305..ac150af 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -267,7 +267,7 @@ void musb_load_testpacket(struct musb *musb)
+
+ const char *otg_state_string(struct musb *musb)
+ {
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_IDLE: return "a_idle";
+ case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise";
+ case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon";
+@@ -302,11 +302,11 @@ void musb_otg_timer_func(unsigned long data)
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_B_WAIT_ACON:
+ DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n");
+ musb_g_disconnect(musb);
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->is_active = 0;
+ break;
+ case OTG_STATE_A_WAIT_BCON:
+@@ -331,20 +331,20 @@ void musb_hnp_stop(struct musb *musb)
+ void __iomem *mbase = musb->mregs;
+ u8 reg;
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_PERIPHERAL:
+ case OTG_STATE_A_WAIT_VFALL:
+ case OTG_STATE_A_WAIT_BCON:
+ DBG(1, "HNP: Switching back to A-host\n");
+ musb_g_disconnect(musb);
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ musb->is_active = 0;
+ break;
+ case OTG_STATE_B_HOST:
+ DBG(1, "HNP: Disabling HR\n");
+ hcd->self.is_b_host = 0;
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ MUSB_DEV_MODE(musb);
+ reg = musb_readb(mbase, MUSB_POWER);
+ reg |= MUSB_POWER_SUSPENDM;
+@@ -402,7 +402,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+
+ if (devctl & MUSB_DEVCTL_HM) {
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_SUSPEND:
+ /* remote wakeup? later, GetPortStatus
+ * will stop RESUME signaling
+@@ -425,12 +425,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ musb->rh_timer = jiffies
+ + msecs_to_jiffies(20);
+
+- musb->xceiv.state = OTG_STATE_A_HOST;
++ musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->is_active = 1;
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->is_active = 1;
+ MUSB_DEV_MODE(musb);
+ break;
+@@ -441,11 +441,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ }
+ #endif
+ } else {
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ case OTG_STATE_A_SUSPEND:
+ /* possibly DISCONNECT is upcoming */
+- musb->xceiv.state = OTG_STATE_A_HOST;
++ musb->xceiv->state = OTG_STATE_A_HOST;
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ break;
+ #endif
+@@ -490,7 +490,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ */
+ musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+ musb->ep0_stage = MUSB_EP0_START;
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ musb_set_vbus(musb, 1);
+
+@@ -516,7 +516,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ * REVISIT: do delays from lots of DEBUG_KERNEL checks
+ * make trouble here, keeping VBUS < 4.4V ?
+ */
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_HOST:
+ /* recovery is dicey once we've gotten past the
+ * initial stages of enumeration, but if VBUS
+@@ -602,11 +602,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ MUSB_HST_MODE(musb);
+
+ /* indicate new connection to OTG machine */
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ if (int_usb & MUSB_INTR_SUSPEND) {
+ DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n");
+- musb->xceiv.state = OTG_STATE_B_HOST;
++ musb->xceiv->state = OTG_STATE_B_HOST;
+ hcd->self.is_b_host = 1;
+ int_usb &= ~MUSB_INTR_SUSPEND;
+ } else
+@@ -614,13 +614,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ DBG(1, "HNP: Waiting to switch to b_host state\n");
+- musb->xceiv.state = OTG_STATE_B_HOST;
++ musb->xceiv->state = OTG_STATE_B_HOST;
+ hcd->self.is_b_host = 1;
+ break;
+ default:
+ if ((devctl & MUSB_DEVCTL_VBUS)
+ == (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
+- musb->xceiv.state = OTG_STATE_A_HOST;
++ musb->xceiv->state = OTG_STATE_A_HOST;
+ hcd->self.is_b_host = 0;
+ }
+ break;
+@@ -650,7 +650,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ }
+ } else if (is_peripheral_capable()) {
+ DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ #ifdef CONFIG_USB_OTG
+ case OTG_STATE_A_SUSPEND:
+ /* We need to ignore disconnect on suspend
+@@ -673,12 +673,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ case OTG_STATE_B_WAIT_ACON:
+ DBG(1, "HNP: RESET (%s), to b_peripheral\n",
+ otg_state_string(musb));
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb_g_reset(musb);
+ break;
+ #endif
+ case OTG_STATE_B_IDLE:
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ /* FALLTHROUGH */
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_reset(musb);
+@@ -763,7 +763,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ MUSB_MODE(musb), devctl);
+ handled = IRQ_HANDLED;
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ case OTG_STATE_A_HOST:
+ case OTG_STATE_A_SUSPEND:
+@@ -805,7 +805,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ otg_state_string(musb), devctl, power);
+ handled = IRQ_HANDLED;
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ #ifdef CONFIG_USB_MUSB_OTG
+ case OTG_STATE_A_PERIPHERAL:
+ /*
+@@ -817,10 +817,10 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_suspend(musb);
+ musb->is_active = is_otg_enabled(musb)
+- && musb->xceiv.gadget->b_hnp_enable;
++ && musb->xceiv->gadget->b_hnp_enable;
+ if (musb->is_active) {
+ #ifdef CONFIG_USB_MUSB_OTG
+- musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
++ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ DBG(1, "HNP: Setting timer for b_ase0_brst\n");
+ musb_otg_timer.data = (unsigned long)musb;
+ mod_timer(&musb_otg_timer, jiffies
+@@ -834,9 +834,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ + msecs_to_jiffies(musb->a_wait_bcon));
+ break;
+ case OTG_STATE_A_HOST:
+- musb->xceiv.state = OTG_STATE_A_SUSPEND;
++ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->is_active = is_otg_enabled(musb)
+- && musb->xceiv.host->b_hnp_enable;
++ && musb->xceiv->host->b_hnp_enable;
+ break;
+ case OTG_STATE_B_HOST:
+ /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+@@ -1681,7 +1681,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb->a_wait_bcon = val;
+- if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON)
++ if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
+ spin_unlock_irqrestore(&musb->lock, flags);
+@@ -1742,8 +1742,8 @@ static void musb_irq_work(struct work_struct *data)
+ struct musb *musb = container_of(data, struct musb, irq_work);
+ static int old_state;
+
+- if (musb->xceiv.state != old_state) {
+- old_state = musb->xceiv.state;
++ if (musb->xceiv->state != old_state) {
++ old_state = musb->xceiv->state;
+ sysfs_notify(&musb->controller->kobj, NULL, "mode");
+ }
+ }
+@@ -1840,7 +1840,7 @@ static void musb_free(struct musb *musb)
+ }
+
+ #ifdef CONFIG_USB_MUSB_OTG
+- put_device(musb->xceiv.dev);
++ put_device(musb->xceiv->dev);
+ #endif
+
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+@@ -1921,10 +1921,18 @@ bad_config:
+ }
+ }
+
+- /* assume vbus is off */
+-
+- /* platform adjusts musb->mregs and musb->isr if needed,
+- * and activates clocks
++ /* The musb_platform_init() call:
++ * - adjusts musb->mregs and musb->isr if needed,
++ * - may initialize an integrated tranceiver
++ * - initializes musb->xceiv, usually by otg_get_transceiver()
++ * - activates clocks.
++ * - stops powering VBUS
++ * - assigns musb->board_set_vbus if host mode is enabled
++ *
++ * There are various transciever configurations. Blackfin,
++ * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
++ * external/discrete ones in various flavors (twl4030 family,
++ * isp1504, non-OTG, etc) mostly hooking up through ULPI.
+ */
+ musb->isr = generic_interrupt;
+ status = musb_platform_init(musb);
+@@ -1992,17 +2000,17 @@ bad_config:
+ ? "DMA" : "PIO",
+ musb->nIrq);
+
+-#ifdef CONFIG_USB_MUSB_HDRC_HCD
+- /* host side needs more setup, except for no-host modes */
+- if (musb->board_mode != MUSB_PERIPHERAL) {
++ /* host side needs more setup */
++ if (is_host_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
+- if (musb->board_mode == MUSB_OTG)
++ otg_set_host(musb->xceiv, &hcd->self);
++
++ if (is_otg_enabled(musb))
+ hcd->self.otg_port = 1;
+- musb->xceiv.host = &hcd->self;
++ musb->xceiv->host = &hcd->self;
+ hcd->power_budget = 2 * (plat->power ? : 250);
+ }
+-#endif /* CONFIG_USB_MUSB_HDRC_HCD */
+
+ /* For the host-only role, we can activate right away.
+ * (We expect the ID pin to be forcibly grounded!!)
+@@ -2010,8 +2018,8 @@ bad_config:
+ */
+ if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+ MUSB_HST_MODE(musb);
+- musb->xceiv.default_a = 1;
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+
+ status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+ if (status)
+@@ -2026,8 +2034,8 @@ bad_config:
+
+ } else /* peripheral is enabled */ {
+ MUSB_DEV_MODE(musb);
+- musb->xceiv.default_a = 0;
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+
+ status = musb_gadget_setup(musb);
+ if (status)
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index 0ac4faf..c3ee348 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -356,7 +356,7 @@ struct musb {
+ u16 int_rx;
+ u16 int_tx;
+
+- struct otg_transceiver xceiv;
++ struct otg_transceiver *xceiv;
+
+ int nIrq;
+ unsigned irq_wake:1;
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index e8f920c..2fbfba5 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ /* NOTE: OTG state machine doesn't include B_SUSPENDED;
+ * that's part of the standard usb 1.1 state machine, and
+@@ -1508,9 +1508,9 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+ {
+ struct musb *musb = gadget_to_musb(gadget);
+
+- if (!musb->xceiv.set_power)
++ if (!musb->xceiv->set_power)
+ return -EOPNOTSUPP;
+- return otg_set_power(&musb->xceiv, mA);
++ return otg_set_power(musb->xceiv, mA);
+ }
+
+ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
+@@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+- /* REVISIT always use otg_set_peripheral(), handling
+- * issues including the root hub one below ...
+- */
+- musb->xceiv.gadget = &musb->g;
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ otg_set_peripheral(musb->xceiv, &musb->g);
+ musb->is_active = 1;
+
+ /* FIXME this ignores the softconnect flag. Drivers are
+@@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ if (!is_otg_enabled(musb))
+ musb_start(musb);
+
++ otg_set_peripheral(musb->xceiv, &musb->g);
++
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ if (is_otg_enabled(musb)) {
+@@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ if (retval < 0) {
+ DBG(1, "add_hcd failed, %d\n", retval);
+ spin_lock_irqsave(&musb->lock, flags);
+- musb->xceiv.gadget = NULL;
+- musb->xceiv.state = OTG_STATE_UNDEFINED;
++ otg_set_peripheral(musb->xceiv, NULL);
+ musb->gadget_driver = NULL;
+ musb->g.dev.driver = NULL;
+ spin_unlock_irqrestore(&musb->lock, flags);
+@@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+
+ (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+- musb->xceiv.state = OTG_STATE_UNDEFINED;
++ musb->xceiv->state = OTG_STATE_UNDEFINED;
+ stop_activity(musb, driver);
++ otg_set_peripheral(musb->xceiv, NULL);
+
+ DBG(3, "unregistering driver %s\n", driver->function);
+ spin_unlock_irqrestore(&musb->lock, flags);
+@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
+ void musb_g_resume(struct musb *musb)
+ {
+ musb->is_suspended = 0;
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_B_IDLE:
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+@@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb)
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ DBG(3, "devctl %02x\n", devctl);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_B_IDLE:
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ musb->is_suspended = 1;
+@@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb)
+ spin_lock(&musb->lock);
+ }
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ default:
+ #ifdef CONFIG_USB_MUSB_OTG
+ DBG(2, "Unhandled disconnect %s, setting a_idle\n",
+ otg_state_string(musb));
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+ #endif
+ case OTG_STATE_B_PERIPHERAL:
+ case OTG_STATE_B_IDLE:
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ break;
+ case OTG_STATE_B_SRP_INIT:
+ break;
+@@ -2029,10 +2027,10 @@ __acquires(musb->lock)
+ * or else after HNP, as A-Device
+ */
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+- musb->xceiv.state = OTG_STATE_B_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->g.is_a_peripheral = 0;
+ } else if (is_otg_enabled(musb)) {
+- musb->xceiv.state = OTG_STATE_A_PERIPHERAL;
++ musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ musb->g.is_a_peripheral = 1;
+ } else
+ WARN_ON(1);
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index ece5122..795dabe 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2169,7 +2169,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
+ {
+ struct musb *musb = hcd_to_musb(hcd);
+
+- if (musb->xceiv.state == OTG_STATE_A_SUSPEND)
++ if (musb->xceiv->state == OTG_STATE_A_SUSPEND)
+ return 0;
+
+ if (is_host_active(musb) && musb->is_active) {
+diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
+index e0e9ce5..7e7900f 100644
+--- a/drivers/usb/musb/musb_virthub.c
++++ b/drivers/usb/musb/musb_virthub.c
+@@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
+ DBG(3, "Root port suspended, power %02x\n", power);
+
+ musb->port1_status |= USB_PORT_STAT_SUSPEND;
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_HOST:
+- musb->xceiv.state = OTG_STATE_A_SUSPEND;
++ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->is_active = is_otg_enabled(musb)
+- && musb->xceiv.host->b_hnp_enable;
++ && musb->xceiv->host->b_hnp_enable;
+ musb_platform_try_idle(musb, 0);
+ break;
+ #ifdef CONFIG_USB_MUSB_OTG
+ case OTG_STATE_B_HOST:
+- musb->xceiv.state = OTG_STATE_B_WAIT_ACON;
++ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ musb->is_active = is_otg_enabled(musb)
+- && musb->xceiv.host->b_hnp_enable;
++ && musb->xceiv->host->b_hnp_enable;
+ musb_platform_try_idle(musb, 0);
+ break;
+ #endif
+@@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
+ void __iomem *mbase = musb->mregs;
+
+ #ifdef CONFIG_USB_MUSB_OTG
+- if (musb->xceiv.state == OTG_STATE_B_IDLE) {
++ if (musb->xceiv->state == OTG_STATE_B_IDLE) {
+ DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n");
+ musb->port1_status &= ~USB_PORT_STAT_RESET;
+ return;
+@@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb)
+ usb_hcd_poll_rh_status(musb_to_hcd(musb));
+ musb->is_active = 0;
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_HOST:
+ case OTG_STATE_A_SUSPEND:
+- musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->is_active = 0;
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ break;
+ default:
+ DBG(1, "host disconnect (%s)\n", otg_state_string(musb));
+@@ -332,7 +332,7 @@ int musb_hub_control(
+ musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+ usb_hcd_poll_rh_status(musb_to_hcd(musb));
+ /* NOTE: it might really be A_WAIT_BCON ... */
+- musb->xceiv.state = OTG_STATE_A_HOST;
++ musb->xceiv->state = OTG_STATE_A_HOST;
+ }
+
+ put_unaligned(cpu_to_le32(musb->port1_status
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 901dffd..5f67b03 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -62,17 +62,17 @@ static void musb_do_idle(unsigned long _musb)
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+@@ -90,7 +90,7 @@ static void musb_do_idle(unsigned long _musb)
+ musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+ usb_hcd_poll_rh_status(musb_to_hcd(musb));
+ /* NOTE: it might really be A_WAIT_BCON ... */
+- musb->xceiv.state = OTG_STATE_A_HOST;
++ musb->xceiv->state = OTG_STATE_A_HOST;
+ }
+ break;
+ #endif
+@@ -98,9 +98,9 @@ static void musb_do_idle(unsigned long _musb)
+ case OTG_STATE_A_HOST:
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ else
+- musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ #endif
+ default:
+ break;
+@@ -119,7 +119,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || ((musb->a_wait_bcon == 0)
+- && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) {
++ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+ del_timer(&musb_idle_timer);
+ last_timer = jiffies;
+@@ -164,8 +164,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
+
+ if (is_on) {
+ musb->is_active = 1;
+- musb->xceiv.default_a = 1;
+- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
++ musb->xceiv->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ devctl |= MUSB_DEVCTL_SESSION;
+
+ MUSB_HST_MODE(musb);
+@@ -176,8 +176,8 @@ static void omap_set_vbus(struct musb *musb, int is_on)
+ * jumping right to B_IDLE...
+ */
+
+- musb->xceiv.default_a = 0;
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+ MUSB_DEV_MODE(musb);
+@@ -189,10 +189,6 @@ static void omap_set_vbus(struct musb *musb, int is_on)
+ otg_state_string(musb),
+ musb_readb(musb->mregs, MUSB_DEVCTL));
+ }
+-static int omap_set_power(struct otg_transceiver *x, unsigned mA)
+-{
+- return 0;
+-}
+
+ static int musb_platform_resume(struct musb *musb);
+
+@@ -203,24 +199,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+- switch (musb_mode) {
+-#ifdef CONFIG_USB_MUSB_HDRC_HCD
+- case MUSB_HOST:
+- otg_set_host(&musb->xceiv, musb->xceiv.host);
+- break;
+-#endif
+-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+- case MUSB_PERIPHERAL:
+- otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget);
+- break;
+-#endif
+-#ifdef CONFIG_USB_MUSB_OTG
+- case MUSB_OTG:
+- break;
+-#endif
+- default:
+- return -EINVAL;
+- }
+ return 0;
+ }
+
+@@ -232,6 +210,16 @@ int __init musb_platform_init(struct musb *musb)
+ omap_cfg_reg(AE5_2430_USB0HS_STP);
+ #endif
+
++ /* We require some kind of external transceiver, hooked
++ * up through ULPI. TWL4030-family PMICs include one,
++ * which needs a driver, drivers aren't always needed.
++ */
++ musb->xceiv = otg_get_transceiver();
++ if (!musb->xceiv) {
++ pr_err("HS USB OTG: no transceiver configured\n");
++ return -ENODEV;
++ }
++
+ musb_platform_resume(musb);
+
+ l = omap_readl(OTG_SYSCONFIG);
+@@ -258,8 +246,6 @@ int __init musb_platform_init(struct musb *musb)
+
+ if (is_host_enabled(musb))
+ musb->board_set_vbus = omap_set_vbus;
+- if (is_peripheral_enabled(musb))
+- musb->xceiv.set_power = omap_set_power;
+ musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
+
+ setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+@@ -283,8 +269,7 @@ int musb_platform_suspend(struct musb *musb)
+ l |= ENABLEWAKEUP; /* enable wakeup */
+ omap_writel(l, OTG_SYSCONFIG);
+
+- if (musb->xceiv.set_suspend)
+- musb->xceiv.set_suspend(&musb->xceiv, 1);
++ otg_set_suspend(musb->xceiv, 1);
+
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 0);
+@@ -301,8 +286,7 @@ static int musb_platform_resume(struct musb *musb)
+ if (!musb->clock)
+ return 0;
+
+- if (musb->xceiv.set_suspend)
+- musb->xceiv.set_suspend(&musb->xceiv, 0);
++ otg_set_suspend(musb->xceiv, 0);
+
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 1);
+diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
+index 9e20fd0..c473dec 100644
+--- a/drivers/usb/musb/tusb6010.c
++++ b/drivers/usb/musb/tusb6010.c
+@@ -260,6 +260,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
+ tusb_fifo_read_unaligned(fifo, buf, len);
+ }
+
++static struct musb *the_musb;
++
+ #ifdef CONFIG_USB_GADGET_MUSB_HDRC
+
+ /* This is used by gadget drivers, and OTG transceiver logic, allowing
+@@ -270,7 +272,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
+ */
+ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
+ {
+- struct musb *musb = container_of(x, struct musb, xceiv);
++ struct musb *musb = the_musb;
+ void __iomem *tbase = musb->ctrl_base;
+ u32 reg;
+
+@@ -420,7 +422,7 @@ static void musb_do_idle(unsigned long _musb)
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ if ((musb->a_wait_bcon != 0)
+ && (musb->idle_timeout == 0
+@@ -484,7 +486,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || ((musb->a_wait_bcon == 0)
+- && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) {
++ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+ del_timer(&musb_idle_timer);
+ last_timer = jiffies;
+@@ -533,8 +535,8 @@ static void tusb_source_power(struct musb *musb, int is_on)
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 1);
+ timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
+- musb->xceiv.default_a = 1;
+- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
++ musb->xceiv->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ devctl |= MUSB_DEVCTL_SESSION;
+
+ conf |= TUSB_DEV_CONF_USB_HOST_MODE;
+@@ -547,24 +549,24 @@ static void tusb_source_power(struct musb *musb, int is_on)
+ /* If ID pin is grounded, we want to be a_idle */
+ otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
+ if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_VRISE:
+ case OTG_STATE_A_WAIT_BCON:
+- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+- musb->xceiv.state = OTG_STATE_A_IDLE;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
+ }
+ musb->is_active = 0;
+- musb->xceiv.default_a = 1;
++ musb->xceiv->default_a = 1;
+ MUSB_HST_MODE(musb);
+ } else {
+ musb->is_active = 0;
+- musb->xceiv.default_a = 0;
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ }
+
+@@ -675,7 +677,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+ else
+ default_a = is_host_enabled(musb);
+ DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
+- musb->xceiv.default_a = default_a;
++ musb->xceiv->default_a = default_a;
+ tusb_source_power(musb, default_a);
+
+ /* Don't allow idling immediately */
+@@ -687,7 +689,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+ if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
+
+ /* B-dev state machine: no vbus ~= disconnect */
+- if ((is_otg_enabled(musb) && !musb->xceiv.default_a)
++ if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
+ || !is_host_enabled(musb)) {
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+ /* ? musb_root_disconnect(musb); */
+@@ -702,9 +704,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+
+ if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
+ DBG(1, "Forcing disconnect (no interrupt)\n");
+- if (musb->xceiv.state != OTG_STATE_B_IDLE) {
++ if (musb->xceiv->state != OTG_STATE_B_IDLE) {
+ /* INTR_DISCONNECT can hide... */
+- musb->xceiv.state = OTG_STATE_B_IDLE;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->int_usb |= MUSB_INTR_DISCONNECT;
+ }
+ musb->is_active = 0;
+@@ -718,7 +720,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+ DBG(2, "vbus change, %s, otg %03x\n",
+ otg_state_string(musb), otg_stat);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_IDLE:
+ DBG(2, "Got SRP, turning on VBUS\n");
+ musb_set_vbus(musb, 1);
+@@ -766,7 +768,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+
+ DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat);
+
+- switch (musb->xceiv.state) {
++ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_VRISE:
+ /* VBUS has probably been valid for a while now,
+ * but may well have bounced out of range a bit
+@@ -778,7 +780,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
+ DBG(2, "devctl %02x\n", devctl);
+ break;
+ }
+- musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->is_active = 0;
+ idle_timeout = jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon);
+@@ -1094,9 +1096,14 @@ int __init musb_platform_init(struct musb *musb)
+ {
+ struct platform_device *pdev;
+ struct resource *mem;
+- void __iomem *sync;
++ void __iomem *sync = NULL;
+ int ret;
+
++ usb_nop_xceiv_register();
++ musb->xceiv = otg_get_transceiver();
++ if (!musb->xceiv)
++ return -ENODEV;
++
+ pdev = to_platform_device(musb->controller);
+
+ /* dma address for async dma */
+@@ -1107,14 +1114,16 @@ int __init musb_platform_init(struct musb *musb)
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!mem) {
+ pr_debug("no sync dma resource?\n");
+- return -ENODEV;
++ ret = -ENODEV;
++ goto done;
+ }
+ musb->sync = mem->start;
+
+ sync = ioremap(mem->start, mem->end - mem->start + 1);
+ if (!sync) {
+ pr_debug("ioremap for sync failed\n");
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto done;
+ }
+ musb->sync_va = sync;
+
+@@ -1127,28 +1136,37 @@ int __init musb_platform_init(struct musb *musb)
+ if (ret) {
+ printk(KERN_ERR "Could not start tusb6010 (%d)\n",
+ ret);
+- return -ENODEV;
++ goto done;
+ }
+ musb->isr = tusb_interrupt;
+
+ if (is_host_enabled(musb))
+ musb->board_set_vbus = tusb_source_power;
+- if (is_peripheral_enabled(musb))
+- musb->xceiv.set_power = tusb_draw_power;
++ if (is_peripheral_enabled(musb)) {
++ musb->xceiv->set_power = tusb_draw_power;
++ the_musb = musb;
++ }
+
+ setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+
++done:
++ if (ret < 0) {
++ if (sync)
++ iounmap(sync);
++ usb_nop_xceiv_unregister();
++ }
+ return ret;
+ }
+
+ int musb_platform_exit(struct musb *musb)
+ {
+ del_timer_sync(&musb_idle_timer);
++ the_musb = NULL;
+
+ if (musb->board_set_power)
+ musb->board_set_power(0);
+
+ iounmap(musb->sync_va);
+-
++ usb_nop_xceiv_unregister();
+ return 0;
+ }
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch
new file mode 100644
index 0000000000..f41b766cfe
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch
@@ -0,0 +1,198 @@
+From b4b8c1e7604784b9877f07400ff2a718118ef05c Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 31 Mar 2009 12:32:12 -0700
+Subject: [PATCH] musb: otg timer cleanup
+
+Minor cleanup of OTG timer handling:
+ * unify decls for OTG time constants, in the core header
+ * set up and use that timer in a more normal way
+ * move to the driver struct, so it's usable outside core
+
+And tighten use and setup of T(a_wait_bcon) so that if it's used,
+it's always valid. (If that timer expires, the A-device will
+stop powering VBUS. For non-OTG systems, that will be a surprise.)
+No behavioral changes, other than more consistency when applying
+that core HNP timeout.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 41 ++++++++++++++++++++++-------------------
+ drivers/usb/musb/musb_core.h | 14 +++++++++++---
+ drivers/usb/musb/omap2430.c | 2 --
+ 3 files changed, 33 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index ac150af..05c5dd3 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -112,6 +112,7 @@
+ #include "davinci.h"
+ #endif
+
++#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
+
+
+ unsigned musb_debug;
+@@ -288,12 +289,6 @@ const char *otg_state_string(struct musb *musb)
+ #ifdef CONFIG_USB_MUSB_OTG
+
+ /*
+- * See also USB_OTG_1-3.pdf 6.6.5 Timers
+- * REVISIT: Are the other timers done in the hardware?
+- */
+-#define TB_ASE0_BRST 100 /* Min 3.125 ms */
+-
+-/*
+ * Handles OTG hnp timeouts, such as b_ase0_brst
+ */
+ void musb_otg_timer_func(unsigned long data)
+@@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data)
+ spin_unlock_irqrestore(&musb->lock, flags);
+ }
+
+-static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0);
+-
+ /*
+- * Stops the B-device HNP state. Caller must take care of locking.
++ * Stops the HNP transition. Caller must take care of locking.
+ */
+ void musb_hnp_stop(struct musb *musb)
+ {
+@@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ musb_g_reset(musb);
+ /* FALLTHROUGH */
+ case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
+- DBG(1, "HNP: Setting timer as %s\n",
+- otg_state_string(musb));
+- musb_otg_timer.data = (unsigned long)musb;
+- mod_timer(&musb_otg_timer, jiffies
+- + msecs_to_jiffies(100));
++ /* never use invalid T(a_wait_bcon) */
++ DBG(1, "HNP: in %s, %d msec timeout\n",
++ otg_state_string(musb),
++ TA_WAIT_BCON(musb));
++ mod_timer(&musb->otg_timer, jiffies
++ + msecs_to_jiffies(TA_WAIT_BCON(musb)));
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb_hnp_stop(musb);
+@@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ #ifdef CONFIG_USB_MUSB_OTG
+ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ DBG(1, "HNP: Setting timer for b_ase0_brst\n");
+- musb_otg_timer.data = (unsigned long)musb;
+- mod_timer(&musb_otg_timer, jiffies
+- + msecs_to_jiffies(TB_ASE0_BRST));
++ mod_timer(&musb->otg_timer, jiffies
++ + msecs_to_jiffies(
++ OTG_TIME_B_ASE0_BRST));
+ #endif
+ }
+ break;
+@@ -1680,7 +1674,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
+ }
+
+ spin_lock_irqsave(&musb->lock, flags);
+- musb->a_wait_bcon = val;
++ /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */
++ musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ;
+ if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
+@@ -1699,10 +1694,13 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
+
+ spin_lock_irqsave(&musb->lock, flags);
+ val = musb->a_wait_bcon;
++ /* FIXME get_vbus_status() is normally #defined as false...
++ * and is effectively TUSB-specific.
++ */
+ vbus = musb_platform_get_vbus_status(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+- return sprintf(buf, "Vbus %s, timeout %lu\n",
++ return sprintf(buf, "Vbus %s, timeout %lu msec\n",
+ vbus ? "on" : "off", val);
+ }
+ static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
+@@ -1775,6 +1773,7 @@ allocate_instance(struct device *dev,
+ hcd->uses_new_polling = 1;
+
+ musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
++ musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
+ #else
+ musb = kzalloc(sizeof *musb, GFP_KERNEL);
+ if (!musb)
+@@ -1969,6 +1968,10 @@ bad_config:
+ if (status < 0)
+ goto fail2;
+
++#ifdef CONFIG_USB_OTG
++ setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
++#endif
++
+ /* Init IRQ workqueue before request_irq */
+ INIT_WORK(&musb->irq_work, musb_irq_work);
+
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index c3ee348..cf3ccb0 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -40,6 +40,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp_lock.h>
+ #include <linux/errno.h>
++#include <linux/timer.h>
+ #include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/usb/ch9.h>
+@@ -180,10 +181,15 @@ enum musb_g_ep0_state {
+ MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */
+ } __attribute__ ((packed));
+
+-/* OTG protocol constants */
++/*
++ * OTG protocol constants. See USB OTG 1.3 spec,
++ * sections 5.5 "Device Timings" and 6.6.5 "Timers".
++ */
+ #define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */
+-#define OTG_TIME_A_WAIT_BCON 0 /* 0=infinite; min 1000 msec */
+-#define OTG_TIME_A_IDLE_BDIS 200 /* msec (min) */
++#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */
++#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */
++#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */
++
+
+ /*************************** REGISTER ACCESS ********************************/
+
+@@ -332,6 +338,8 @@ struct musb {
+ struct list_head control; /* of musb_qh */
+ struct list_head in_bulk; /* of musb_qh */
+ struct list_head out_bulk; /* of musb_qh */
++
++ struct timer_list otg_timer;
+ #endif
+
+ /* called with IRQs blocked; ON/nonzero implies starting a session,
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 5f67b03..3fbc807 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -45,7 +45,6 @@
+ #define get_cpu_rev() 2
+ #endif
+
+-#define MUSB_TIMEOUT_A_WAIT_BCON 1100
+
+ static struct timer_list musb_idle_timer;
+
+@@ -246,7 +245,6 @@ int __init musb_platform_init(struct musb *musb)
+
+ if (is_host_enabled(musb))
+ musb->board_set_vbus = omap_set_vbus;
+- musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
+
+ setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch
new file mode 100644
index 0000000000..6269016223
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch
@@ -0,0 +1,133 @@
+From a637c5056ef52fbb7c41eb7537a9ec3d150231ad Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Thu, 2 Apr 2009 10:16:11 -0700
+Subject: [PATCH] musb: make initial HNP roleswitch work (v2)
+
+Minor HNP bugfixes, so the initial role switch works:
+
+ - A-Device:
+ * disconnect-during-suspend enters A_PERIPHERAL state
+ * kill OTG timer after reset as A_PERIPHERAL ...
+ * ... and also pass that reset to the gadget
+ * once HNP succeeds, clear the "ignore_disconnect" flag
+ * from A_PERIPHERAL, disconnect transitions to A_WAIT_BCON
+
+ - B-Device:
+ * kill OTG timer on entry to B_HOST state (HNP succeeded)
+ * once HNP succeeds, clear "ignore_disconnect" flag
+ * kick the root hub only _after_ the state is adjusted
+
+Other state transitions are left alone. Notably, exit paths from
+the "roles have switched" state ... A_PERIPHERAL handling of that
+stays seriously broken.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 27 ++++++++++++++++-----------
+ drivers/usb/musb/musb_gadget.c | 2 +-
+ drivers/usb/musb/musb_virthub.c | 11 ++++++++++-
+ 3 files changed, 27 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 05c5dd3..9dc995a 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -587,28 +587,23 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ if (devctl & MUSB_DEVCTL_LSDEV)
+ musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
+
+- if (hcd->status_urb)
+- usb_hcd_poll_rh_status(hcd);
+- else
+- usb_hcd_resume_root_hub(hcd);
+-
+- MUSB_HST_MODE(musb);
+-
+ /* indicate new connection to OTG machine */
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ if (int_usb & MUSB_INTR_SUSPEND) {
+ DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n");
+- musb->xceiv->state = OTG_STATE_B_HOST;
+- hcd->self.is_b_host = 1;
+ int_usb &= ~MUSB_INTR_SUSPEND;
++ goto b_host;
+ } else
+ DBG(1, "CONNECT as b_peripheral???\n");
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+- DBG(1, "HNP: Waiting to switch to b_host state\n");
++ DBG(1, "HNP: CONNECT, now b_host\n");
++b_host:
+ musb->xceiv->state = OTG_STATE_B_HOST;
+ hcd->self.is_b_host = 1;
++ musb->ignore_disconnect = 0;
++ del_timer(&musb->otg_timer);
+ break;
+ default:
+ if ((devctl & MUSB_DEVCTL_VBUS)
+@@ -618,6 +613,14 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ }
+ break;
+ }
++
++ /* poke the root hub */
++ MUSB_HST_MODE(musb);
++ if (hcd->status_urb)
++ usb_hcd_poll_rh_status(hcd);
++ else
++ usb_hcd_resume_root_hub(hcd);
++
+ DBG(1, "CONNECT (%s) devctl %02x\n",
+ otg_state_string(musb), devctl);
+ }
+@@ -662,7 +665,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ + msecs_to_jiffies(TA_WAIT_BCON(musb)));
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+- musb_hnp_stop(musb);
++ musb->ignore_disconnect = 0;
++ del_timer(&musb->otg_timer);
++ musb_g_reset(musb);
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ DBG(1, "HNP: RESET (%s), to b_peripheral\n",
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index 2fbfba5..7dd3d59 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -1964,7 +1964,7 @@ void musb_g_disconnect(struct musb *musb)
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
+index 7e7900f..14f7cf3 100644
+--- a/drivers/usb/musb/musb_virthub.c
++++ b/drivers/usb/musb/musb_virthub.c
+@@ -187,8 +187,17 @@ void musb_root_disconnect(struct musb *musb)
+ musb->is_active = 0;
+
+ switch (musb->xceiv->state) {
+- case OTG_STATE_A_HOST:
+ case OTG_STATE_A_SUSPEND:
++#ifdef CONFIG_USB_MUSB_OTG
++ if (is_otg_enabled(musb)
++ && musb->xceiv->host->b_hnp_enable) {
++ musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
++ musb->g.is_a_peripheral = 1;
++ break;
++ }
++#endif
++ /* FALLTHROUGH */
++ case OTG_STATE_A_HOST:
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->is_active = 0;
+ break;
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch
new file mode 100644
index 0000000000..fc34fb983e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch
@@ -0,0 +1,145 @@
+From 4288b7df4ae6629a4fb14aca2c489da01d4d19c3 Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+Date: Tue, 31 Mar 2009 12:35:09 -0700
+Subject: [PATCH] musb: support disconnect after HNP roleswitch
+
+Adjust HNP state machines in MUSB driver so that they handle the
+case where the cable is disconnected. The A-side machine was
+very wrong (unrecoverable); the B-Side was much less so.
+
+ - A_PERIPHERAL ... as usual, the non-observability of the ID
+ pin through Mentor's registers makes trouble. We can't go
+ directly to A_WAIT_VFALL to end the session and start the
+ disconnect processing. We can however sense link suspending,
+ go to A_WAIT_BCON, and from there use OTG timeouts to finally
+ trigger that A_WAIT_VFALL transition. (Hoping that nobody
+ reconnects quickly to that port and notices the wrong state.)
+
+ - B_HOST ... actually clear the Host Request (HR) bit as the
+ messages say, disconnect the peripheral from the root hub,
+ and don't detour through a suspend state. (In some cases
+ this would eventually have cleaned up.)
+
+Also adjust the A_SUSPEND transition to respect the A_AIDL_BDIS
+timeout, so if HNP doesn't trigger quickly enough the A_WAIT_VFALL
+transition happens as it should.
+
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/musb_core.c | 41 +++++++++++++++++++++++++++-----------
+ drivers/usb/musb/musb_gadget.c | 2 +
+ drivers/usb/musb/musb_virthub.c | 4 +++
+ 3 files changed, 35 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 9dc995a..5770ccb 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -304,9 +304,11 @@ void musb_otg_timer_func(unsigned long data)
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->is_active = 0;
+ break;
++ case OTG_STATE_A_SUSPEND:
+ case OTG_STATE_A_WAIT_BCON:
+- DBG(1, "HNP: a_wait_bcon timeout; back to a_host\n");
+- musb_hnp_stop(musb);
++ DBG(1, "HNP: %s timeout\n", otg_state_string(musb));
++ musb_set_vbus(musb, 0);
++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ break;
+ default:
+ DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb));
+@@ -324,15 +326,12 @@ void musb_hnp_stop(struct musb *musb)
+ void __iomem *mbase = musb->mregs;
+ u8 reg;
+
++ DBG(1, "HNP: stop from %s\n", otg_state_string(musb));
++
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_PERIPHERAL:
+- case OTG_STATE_A_WAIT_VFALL:
+- case OTG_STATE_A_WAIT_BCON:
+- DBG(1, "HNP: Switching back to A-host\n");
+ musb_g_disconnect(musb);
+- musb->xceiv->state = OTG_STATE_A_IDLE;
+- MUSB_HST_MODE(musb);
+- musb->is_active = 0;
++ DBG(1, "HNP: back to %s\n", otg_state_string(musb));
+ break;
+ case OTG_STATE_B_HOST:
+ DBG(1, "HNP: Disabling HR\n");
+@@ -775,7 +774,16 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ #endif /* HOST */
+ #ifdef CONFIG_USB_MUSB_OTG
+ case OTG_STATE_B_HOST:
+- musb_hnp_stop(musb);
++ /* REVISIT this behaves for "real disconnect"
++ * cases; make sure the other transitions from
++ * from B_HOST act right too. The B_HOST code
++ * in hnp_stop() is currently not used...
++ */
++ musb_root_disconnect(musb);
++ musb_to_hcd(musb)->self.is_b_host = 0;
++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
++ MUSB_DEV_MODE(musb);
++ musb_g_disconnect(musb);
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb_hnp_stop(musb);
+@@ -807,10 +815,19 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
+ switch (musb->xceiv->state) {
+ #ifdef CONFIG_USB_MUSB_OTG
+ case OTG_STATE_A_PERIPHERAL:
+- /*
+- * We cannot stop HNP here, devctl BDEVICE might be
+- * still set.
++ /* We also come here if the cable is removed, since
++ * this silicon doesn't report ID-no-longer-grounded.
++ *
++ * We depend on T(a_wait_bcon) to shut us down, and
++ * hope users don't do anything dicey during this
++ * undesired detour through A_WAIT_BCON.
+ */
++ musb_hnp_stop(musb);
++ usb_hcd_resume_root_hub(musb_to_hcd(musb));
++ musb_root_disconnect(musb);
++ musb_platform_try_idle(musb, jiffies
++ + msecs_to_jiffies(musb->a_wait_bcon
++ ? : OTG_TIME_A_WAIT_BCON));
+ break;
+ #endif
+ case OTG_STATE_B_PERIPHERAL:
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index 7dd3d59..8b3c4e2 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -1962,9 +1962,11 @@ void musb_g_disconnect(struct musb *musb)
+ DBG(2, "Unhandled disconnect %s, setting a_idle\n",
+ otg_state_string(musb));
+ musb->xceiv->state = OTG_STATE_A_IDLE;
++ MUSB_HST_MODE(musb);
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
++ MUSB_HST_MODE(musb);
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
+index 14f7cf3..e8ef925 100644
+--- a/drivers/usb/musb/musb_virthub.c
++++ b/drivers/usb/musb/musb_virthub.c
+@@ -83,6 +83,10 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
+ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->is_active = is_otg_enabled(musb)
+ && musb->xceiv->host->b_hnp_enable;
++ if (musb->is_active)
++ mod_timer(&musb->otg_timer, jiffies
++ + msecs_to_jiffies(
++ OTG_TIME_A_AIDL_BDIS));
+ musb_platform_try_idle(musb, 0);
+ break;
+ #ifdef CONFIG_USB_MUSB_OTG
+--
+1.6.0.4
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/no-cortex-deadlock.patch b/recipes/linux/linux-omap-pm-2.6.29/no-cortex-deadlock.patch
new file mode 100644
index 0000000000..78547c8969
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/no-cortex-deadlock.patch
@@ -0,0 +1,77 @@
+From: Mans Rullgard <mans@mansr.com>
+Date: Sat, 16 Aug 2008 23:03:06 +0000 (+0100)
+Subject: ARM: Workaround for erratum 451034
+X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=b84fa87873ffb68ad23930cf6cddeea8bec43ede
+
+ARM: Workaround for erratum 451034
+
+On Cortex-A8 r1p0 and r1p1, executing a NEON store with an integer
+store in the store buffer, can cause a processor deadlock under
+certain conditions.
+
+Executing a DMB instruction before saving NEON/VFP registers and before
+return to userspace makes it safe to run code which includes similar
+counter-measures. Userspace code can still trigger the deadlock, so
+a different workaround is required to safely run untrusted code.
+
+See ARM Cortex-A8 Errata Notice (PR120-PRDC-008070) for full details.
+
+Signed-off-by: Mans Rullgard <mans@mansr.com>
+---
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index aa475d9..41d536e 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1117,6 +1117,22 @@ config NEON
+ Say Y to include support code for NEON, the ARMv7 Advanced SIMD
+ Extension.
+
++config ARM_ERRATUM_451034
++ bool "Enable workaround for ARM erratum 451034"
++ depends on VFPv3
++ help
++ On Cortex-A8 r1p0 and r1p1, executing a NEON store with an integer
++ store in the store buffer, can cause a processor deadlock under
++ certain conditions.
++
++ See ARM Cortex-A8 Errata Notice (PR120-PRDC-008070) for full details.
++
++ Say Y to include a partial workaround.
++
++ WARNING: Even with this option enabled, userspace code can trigger
++ the deadlock. To safely run untrusted code, a different fix is
++ required.
++
+ endmenu
+
+ menu "Userspace binary formats"
+diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h
+index 422f3cc..934798b 100644
+--- a/arch/arm/include/asm/vfpmacros.h
++++ b/arch/arm/include/asm/vfpmacros.h
+@@ -32,6 +32,9 @@
+
+ @ write all the working registers out of the VFP
+ .macro VFPFSTMIA, base, tmp
++#ifdef CONFIG_ARM_ERRATUM_451034
++ dmb
++#endif
+ #if __LINUX_ARM_ARCH__ < 6
+ STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15}
+ #else
+diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
+index 060d7e2..9799a35 100644
+--- a/arch/arm/kernel/entry-common.S
++++ b/arch/arm/kernel/entry-common.S
+@@ -69,6 +69,10 @@ no_work_pending:
+ /* perform architecture specific actions before user return */
+ arch_ret_to_user r1, lr
+
++#ifdef CONFIG_ARM_ERRATUM_451034
++ dmb
++#endif
++
+ @ slow_restore_user_regs
+ ldr r1, [sp, #S_PSR] @ get calling cpsr
+ ldr lr, [sp, #S_PC]! @ get pc
diff --git a/recipes/linux/linux-omap-pm-2.6.29/no-empty-flash-warnings.patch b/recipes/linux/linux-omap-pm-2.6.29/no-empty-flash-warnings.patch
new file mode 100644
index 0000000000..ab344b0449
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/no-empty-flash-warnings.patch
@@ -0,0 +1,15 @@
+diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
+index 1d437de..33b3feb 100644
+--- a/fs/jffs2/scan.c
++++ b/fs/jffs2/scan.c
+@@ -647,8 +647,8 @@ scan_more:
+ inbuf_ofs = ofs - buf_ofs;
+ while (inbuf_ofs < scan_end) {
+ if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
+- printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
+- empty_start, ofs);
++// printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
++// empty_start, ofs);
+ if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
+ return err;
+ goto scan_more;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/no-harry-potter.diff b/recipes/linux/linux-omap-pm-2.6.29/no-harry-potter.diff
new file mode 100644
index 0000000000..2bb20ab9c0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/no-harry-potter.diff
@@ -0,0 +1,11 @@
+--- /tmp/Makefile 2008-04-24 14:36:20.509598016 +0200
++++ git/arch/arm/Makefile 2008-04-24 14:36:31.949546584 +0200
+@@ -47,7 +47,7 @@
+ # Note that GCC does not numerically define an architecture version
+ # macro, but instead defines a whole series of macros which makes
+ # testing for a specific architecture or later rather impossible.
+-arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a)
++arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a)
+ arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+ # Only override the compiler option if ARMv6. The ARMv6K extensions are
+ # always available in ARMv7
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap-2430-lcd.patch b/recipes/linux/linux-omap-pm-2.6.29/omap-2430-lcd.patch
new file mode 100644
index 0000000000..8f8a687c06
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap-2430-lcd.patch
@@ -0,0 +1,11 @@
+--- git/drivers/video/omap/lcd_2430sdp.c.orig 2007-08-13 14:35:17.000000000 -0700
++++ git/drivers/video/omap/lcd_2430sdp.c 2007-08-13 14:35:55.000000000 -0700
+@@ -32,7 +32,7 @@
+ #define LCD_PANEL_BACKLIGHT_GPIO 91
+ #define LCD_PANEL_ENABLE_GPIO 154
+ #define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */
+-#define PM_RECEIVER TWL4030_MODULE_PM_RECIEVER
++#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
+ #define ENABLE_VAUX2_DEDICATED 0x09
+ #define ENABLE_VAUX2_DEV_GRP 0x20
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap1710h3/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap1710h3/defconfig
new file mode 100644
index 0000000000..21f7c54e4e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap1710h3/defconfig
@@ -0,0 +1,1224 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc2-omap1
+# Tue Aug 21 23:10:57 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_STI is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+# CONFIG_OMAP_DSP is not set
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+CONFIG_MACH_OMAP_H3=y
+# CONFIG_MACH_OMAP_OSK is not set
+# CONFIG_MACH_NOKIA770 is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+# CONFIG_OMAP_ARM_192MHZ is not set
+CONFIG_OMAP_ARM_168MHZ=y
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_MACH_OMAP_APOLLON_PLUS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10C08000
+CONFIG_ZBOOT_ROM_BSS=0x10200000
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 initrd=0x10A00000,8M root=/dev/ram0 rw ip=dhcp devfs=mount"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+# CONFIG_IRLAN is not set
+# CONFIG_IRNET is not set
+# CONFIG_IRCOMM is not set
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_MCS_FIR is not set
+# CONFIG_OMAP_IR is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_OMAP=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_ISP1301_OMAP=m
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_TLV320AIC23 is not set
+CONFIG_GPIOEXPANDER_OMAP=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_OMAP_UWIRE=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_TSC2101 is not set
+# CONFIG_SPI_TSC2102 is not set
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+# CONFIG_VIDEO_OMAP_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_TEA5761 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_OMAP=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_OMAP=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap2420h4/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap2420h4/defconfig
new file mode 100644
index 0000000000..c1133eef9a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap2420h4/defconfig
@@ -0,0 +1,1119 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc2-omap1
+# Tue Aug 21 22:58:34 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2=y
+# CONFIG_ARCH_OMAP3 is not set
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_DEBUG_DEVICES=y
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_STI is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+# CONFIG_OMAP_DSP is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP Core Type
+#
+CONFIG_ARCH_OMAP24XX=y
+CONFIG_ARCH_OMAP2420=y
+# CONFIG_ARCH_OMAP2430 is not set
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_N800 is not set
+CONFIG_MACH_OMAP_H4=y
+# CONFIG_MACH_OMAP_H4_TUSB is not set
+# CONFIG_MACH_OMAP_H4_OTG is not set
+# CONFIG_MACH_OMAP2_H4_USB1 is not set
+# CONFIG_MACH_OMAP_APOLLON is not set
+# CONFIG_MACH_OMAP_APOLLON_PLUS is not set
+# CONFIG_MACH_OMAP_2430SDP is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_V6=y
+# CONFIG_CPU_32v6K is not set
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw console=ttyS0,115200n8 initrd=0x80600000,8M ramdisk_size=8192"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=y
+CONFIG_IRCOMM=y
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_OMAP_IR=y
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_OMAP=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_TLV320AIC23 is not set
+CONFIG_GPIOEXPANDER_OMAP=y
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+CONFIG_MENELAUS=y
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_OMAP=y
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap2430sdp/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap2430sdp/defconfig
new file mode 100644
index 0000000000..f3897e48a3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap2430sdp/defconfig
@@ -0,0 +1,1303 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc2-omap1
+# Sun Aug 12 17:38:46 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2=y
+# CONFIG_ARCH_OMAP3 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+# CONFIG_OMAP_MUX_WARNINGS is not set
+# CONFIG_OMAP_STI is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+# CONFIG_OMAP_DSP is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP Core Type
+#
+CONFIG_ARCH_OMAP24XX=y
+# CONFIG_ARCH_OMAP2420 is not set
+CONFIG_ARCH_OMAP2430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_N800 is not set
+# CONFIG_MACH_OMAP_H4 is not set
+# CONFIG_MACH_OMAP_APOLLON is not set
+# CONFIG_MACH_OMAP_APOLLON_PLUS is not set
+CONFIG_MACH_OMAP_2430SDP=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_V6=y
+# CONFIG_CPU_32v6K is not set
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw console=ttyS0,115200n8 initrd=0x80600000,8M ramdisk_size=8192"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_OMAP is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_TSC2102 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_OMAP=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_TLV320AIC23 is not set
+# CONFIG_GPIOEXPANDER_OMAP is not set
+# CONFIG_MENELAUS is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_GPIO=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_OMAP24XX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_TSC2101 is not set
+# CONFIG_SPI_TSC2102 is not set
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_PERSIST is not set
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 243x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_USB_INVENTRA_FIFO is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_INVENTRA_HCD_LOGGING=1
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_OMAP=y
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-pandora/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap3-pandora/defconfig
new file mode 100644
index 0000000000..5db83f08da
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-pandora/defconfig
@@ -0,0 +1,2186 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc7-omap1
+# Fri Dec 12 19:50:40 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_DEBUG=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+# CONFIG_OMAP2_DSS_USE_DSI_PLL is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_OMAP_TICK_GPTIMER=12
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+CONFIG_ARM_ERRATUM_451034=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=y
+CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTSDIO=y
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_93CX6=m
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+CONFIG_REALTEK_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_SMC911X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_USB=y
+CONFIG_TWL4030_PWRBUTTON=y
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_LP5521 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_SI21XX is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DVB_LGS8GL5 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=14
+CONFIG_FB_OMAP2=y
+# CONFIG_FB_OMAP2_DEBUG is not set
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_DVI=y
+# CONFIG_PANEL_DVI_640X480 is not set
+# CONFIG_PANEL_DVI_800X600 is not set
+CONFIG_PANEL_DVI_1024X768=y
+# CONFIG_PANEL_DVI_1280X1024 is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_LTV350QV=y
+CONFIG_LCD_ILI9320=y
+# CONFIG_LCD_TDO24M is not set
+CONFIG_LCD_VGG2432A4=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+# CONFIG_LEDS_OMAP is not set
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+CONFIG_PREEMPT_TRACER=y
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch
new file mode 100644
index 0000000000..f6d522e352
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch
@@ -0,0 +1,677 @@
+From 0b60175d1b7db1301e2ad3ad4d64fb0c8d121c0a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sat, 11 Apr 2009 13:05:21 -0700
+Subject: [PATCH] MMA7455L driver.
+
+---
+ drivers/input/misc/Kconfig | 9 +
+ drivers/input/misc/Makefile | 1 +
+ drivers/input/misc/mma7455l.c | 614 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/mma7455l.h | 11 +
+ 4 files changed, 635 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index 6fa9e38..05dca18 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -237,4 +237,13 @@ config INPUT_PCF50633_PMU
+ Say Y to include support for delivering PMU events via input
+ layer on NXP PCF50633.
+
++config INPUT_MMA7455L
++ tristate "Freescale MMA7455L 3-axis accelerometer"
++ depends on SPI_MASTER
++ help
++ SPI driver for the Freescale MMA7455L 3-axis accelerometer.
++
++ The userspace interface is a 3-axis (X/Y/Z) relative movement
++ Linux input device, reporting REL_[XYZ] events.
++
+ endif
+diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
+index 2fabcdb..e355d82 100644
+--- a/drivers/input/misc/Makefile
++++ b/drivers/input/misc/Makefile
+@@ -23,3 +23,4 @@ obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
+ obj-$(CONFIG_INPUT_APANEL) += apanel.o
+ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
+ obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
++obj-$(CONFIG_INPUT_MMA7455L) += mma7455l.o
+diff --git a/drivers/input/misc/mma7455l.c b/drivers/input/misc/mma7455l.c
+new file mode 100644
+index 0000000..b33c513
+--- /dev/null
++++ b/drivers/input/misc/mma7455l.c
+@@ -0,0 +1,614 @@
++/* Linux kernel driver for the Freescale MMA7455L 3-axis accelerometer
++ *
++ * Copyright (C) 2009 by Always Innovating, Inc.
++ * Author: Gregoire Gentil <gregoire@gentil.com>
++ * Author: Tim Yamin <plasm@roo.me.uk>
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ */
++
++/*
++ * What this driver doesn't yet support:
++ *
++ * - I2C
++ * - INT2 handling
++ * - Pulse detection (and the sysctls to control it)
++ * - 10-bit measurement
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/sysfs.h>
++#include <linux/gpio.h>
++
++#include <linux/mma7455l.h>
++#include <linux/spi/spi.h>
++
++#define MMA7455L_WHOAMI_MAGIC 0x55
++
++enum mma7455l_reg {
++ MMA7455L_REG_XOUTL = 0x00,
++ MMA7455L_REG_XOUTH = 0x01,
++ MMA7455L_REG_YOUTL = 0x02,
++ MMA7455L_REG_YOUTH = 0x03,
++ MMA7455L_REG_ZOUTL = 0x04,
++ MMA7455L_REG_ZOUTH = 0x05,
++ MMA7455L_REG_XOUT8 = 0x06,
++ MMA7455L_REG_YOUT8 = 0x07,
++ MMA7455L_REG_ZOUT8 = 0x08,
++ MMA7455L_REG_STATUS = 0x09,
++ MMA7455L_REG_DETSRC = 0x0a,
++ MMA7455L_REG_TOUT = 0x0b,
++ MMA7455L_REG_RESERVED1 = 0x0c,
++ MMA7455L_REG_I2CAD = 0x0d,
++ MMA7455L_REG_USRINF = 0x0e,
++ MMA7455L_REG_WHOAMI = 0x0f,
++ MMA7455L_REG_XOFFL = 0x10,
++ MMA7455L_REG_XOFFH = 0x11,
++ MMA7455L_REG_YOFFL = 0x12,
++ MMA7455L_REG_YOFFH = 0x13,
++ MMA7455L_REG_ZOFFL = 0x14,
++ MMA7455L_REG_ZOFFH = 0x15,
++ MMA7455L_REG_MCTL = 0x16,
++ MMA7455L_REG_INTRST = 0x17,
++ MMA7455L_REG_CTL1 = 0x18,
++ MMA7455L_REG_CTL2 = 0x19,
++ MMA7455L_REG_LDTH = 0x1a,
++ MMA7455L_REG_PDTH = 0x1b,
++ MMA7455L_REG_PW = 0x1c,
++ MMA7455L_REG_LT = 0x1d,
++ MMA7455L_REG_TW = 0x1e,
++ MMA7455L_REG_RESERVED2 = 0x1f,
++};
++
++enum mma7455l_reg_status {
++ MMA7455L_STATUS_XDA = 0x08,
++ MMA7455L_STATUS_YDA = 0x10,
++ MMA7455L_STATUS_ZDA = 0x20,
++};
++
++enum mma7455l_mode {
++ MMA7455L_MODE_STANDBY = 0,
++ MMA7455L_MODE_MEASUREMENT = 1,
++ MMA7455L_MODE_LEVELDETECTION = 0x42, /* Set DRPD to on */
++ MMA7455L_MODE_PULSEDETECTION = 0x43, /* Set DRPD to on */
++ MMA7455L_MODE_MASK = 0x43,
++};
++
++enum mma7455l_gselect {
++ MMA7455L_GSELECT_8 = 0x0,
++ MMA7455L_GSELECT_2 = 0x4,
++ MMA7455L_GSELECT_4 = 0x8,
++ MMA7455L_GSELECT_MASK = 0xC,
++};
++
++/* FIXME */
++#define MMA7455L_F_FS 0x0020 /* ADC full scale */
++
++struct mma7455l_info {
++ struct spi_device *spi_dev;
++ struct input_dev *input_dev;
++ struct mutex lock;
++ struct delayed_work work;
++
++ u8 mode;
++ u8 gSelect;
++
++ u8 flags;
++ u8 working;
++};
++
++/* lowlevel register access functions */
++
++#define WRITE_BIT (1 << 7)
++#define ADDR_SHIFT 1
++
++static inline u_int8_t __reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++ int rc;
++ u_int8_t cmd;
++
++ cmd = ((reg & 0x3f) << ADDR_SHIFT);
++ rc = spi_w8r8(mma->spi_dev, cmd);
++
++ return rc;
++}
++
++static u_int8_t reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++ u_int8_t ret;
++
++ mutex_lock(&mma->lock);
++ ret = __reg_read(mma, reg);
++ mutex_unlock(&mma->lock);
++
++ return ret;
++}
++
++static s16 __reg_read_10(struct mma7455l_info *mma, u8 reg1, u8 reg2)
++{
++ u8 v1, v2;
++
++ v1 = __reg_read(mma, reg1);
++ v2 = __reg_read(mma, reg2);
++
++ return (v2 & 0x4) << 13 | (v2 & 0x3) << 8 | v1;
++}
++
++static inline int __reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++ u_int8_t buf[2];
++
++ buf[0] = ((reg & 0x3f) << ADDR_SHIFT) | WRITE_BIT;
++ buf[1] = val;
++
++ return spi_write(mma->spi_dev, buf, sizeof(buf));
++}
++
++static int reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++ int ret;
++
++ mutex_lock(&mma->lock);
++ ret = __reg_write(mma, reg, val);
++ mutex_unlock(&mma->lock);
++
++ return ret;
++}
++
++static s16 __reg_write_10(struct mma7455l_info *mma, u8 reg1, u8 reg2, s16 value)
++{
++ int ret;
++ u8 v1, v2;
++
++ v1 = value & 0xFF;
++ if(value < 0)
++ v2 = ((value >> 8) & 0x3) | 0x4;
++ else
++ v2 = 0;
++
++ ret = __reg_write(mma, reg1, v1);
++ ret = __reg_write(mma, reg2, v2);
++ return ret;
++}
++
++static void mma7455l_work(struct work_struct *work)
++{
++ struct mma7455l_info *mma =
++ container_of(work, struct mma7455l_info, work.work);
++
++ s8 val;
++ mma->working = 1;
++
++ /* FIXME: 10 bit accuracy? */
++ if (!(mma->flags & MMA7455L_STATUS_XDA)) {
++ val = reg_read(mma, MMA7455L_REG_XOUT8);
++ input_report_abs(mma->input_dev, ABS_X, val);
++ }
++ if (!(mma->flags & MMA7455L_STATUS_YDA)) {
++ val = reg_read(mma, MMA7455L_REG_YOUT8);
++ input_report_abs(mma->input_dev, ABS_Y, val);
++ }
++ if (!(mma->flags & MMA7455L_STATUS_ZDA)) {
++ val = reg_read(mma, MMA7455L_REG_ZOUT8);
++ input_report_abs(mma->input_dev, ABS_Z, val);
++ }
++
++ mma->working = 0;
++ input_sync(mma->input_dev);
++ put_device(&mma->spi_dev->dev);
++
++ /* Enable IRQ and clear out interrupt */
++ reg_write(mma, MMA7455L_REG_INTRST, 0x3);
++ reg_write(mma, MMA7455L_REG_INTRST, 0x0);
++ enable_irq(mma->spi_dev->irq);
++}
++
++static void mma7455l_schedule_work(struct mma7455l_info *mma)
++{
++ int status;
++
++ get_device(&mma->spi_dev->dev);
++ status = schedule_delayed_work(&mma->work, HZ / 10);
++}
++
++static irqreturn_t mma7455l_interrupt(int irq, void *_mma)
++{
++ struct mma7455l_info *mma = _mma;
++ mma7455l_schedule_work(mma);
++
++ /* Disable any further interrupts until we have processed
++ * the current one */
++ disable_irq(mma->spi_dev->irq);
++ return IRQ_HANDLED;
++}
++
++/* sysfs */
++
++static void get_mode(struct mma7455l_info *mma, u8 *mode, u8 *gSelect)
++{
++ u8 tmp = reg_read(mma, MMA7455L_REG_MCTL);
++
++ *mode = tmp & MMA7455L_MODE_MASK;
++ *gSelect = tmp & MMA7455L_GSELECT_MASK;
++}
++
++static void set_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++ reg_write(mma, MMA7455L_REG_MCTL, mode | gSelect);
++}
++
++static void update_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++ mma->mode = mode;
++ mma->gSelect = gSelect;
++
++ reg_write(mma, MMA7455L_REG_MCTL, mma->mode | mma->gSelect);
++}
++
++static ssize_t show_measure(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++ s8 x, y, z;
++ u8 old_Mode, old_gSelect;
++
++ get_mode(mma, &old_Mode, &old_gSelect);
++ set_mode(mma, MMA7455L_MODE_MEASUREMENT, MMA7455L_GSELECT_2);
++
++ while (reg_read(mma, MMA7455L_REG_STATUS) == 0) {
++ msleep(10);
++ }
++
++ x = reg_read(mma, MMA7455L_REG_XOUT8);
++ y = reg_read(mma, MMA7455L_REG_YOUT8);
++ z = reg_read(mma, MMA7455L_REG_ZOUT8);
++
++ set_mode(mma, old_Mode, old_gSelect);
++ return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t show_mode(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ switch(mma->mode)
++ {
++ case MMA7455L_MODE_STANDBY:
++ return sprintf(buf, "Standby\n");
++ break;
++ case MMA7455L_MODE_MEASUREMENT:
++ return sprintf(buf, "Measurement\n");
++ break;
++ case MMA7455L_MODE_LEVELDETECTION:
++ return sprintf(buf, "Level Detection\n");
++ break;
++ case MMA7455L_MODE_PULSEDETECTION:
++ return sprintf(buf, "Pulse Detection\n");
++ break;
++ }
++
++ return sprintf(buf, "Unknown mode!\n");
++}
++
++static ssize_t show_gSelect(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ switch(mma->gSelect)
++ {
++ case MMA7455L_GSELECT_8:
++ return sprintf(buf, "8\n");
++ break;
++ case MMA7455L_GSELECT_4:
++ return sprintf(buf, "4\n");
++ break;
++ case MMA7455L_GSELECT_2:
++ return sprintf(buf, "2\n");
++ break;
++ }
++
++ return sprintf(buf, "Unknown gSelect!\n");
++}
++
++static ssize_t show_level_threshold(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", reg_read(mma, MMA7455L_REG_LDTH));
++}
++
++static ssize_t show_calibration(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ s16 x, y, z;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ mutex_lock(&mma->lock);
++ x = __reg_read_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH);
++ y = __reg_read_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH);
++ z = __reg_read_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH);
++ mutex_unlock(&mma->lock);
++
++ return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t write_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if (!strncmp(buf, "Standby", count))
++ update_mode(mma, MMA7455L_MODE_STANDBY, mma->gSelect);
++ else if (!strncmp(buf, "Measurement", count))
++ update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++ else if (!strncmp(buf, "Level Detection", count))
++ update_mode(mma, MMA7455L_MODE_LEVELDETECTION, mma->gSelect);
++ else if (!strncmp(buf, "Pulse Detection", count))
++ update_mode(mma, MMA7455L_MODE_PULSEDETECTION, mma->gSelect);
++
++ return count;
++}
++
++static ssize_t write_gSelect(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long v;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if(strict_strtoul(buf, 10, &v) == 0)
++ {
++ switch(v)
++ {
++ case 8:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_8);
++ break;
++ case 4:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_4);
++ break;
++ case 2:
++ update_mode(mma, mma->mode, MMA7455L_GSELECT_2);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++ return count;
++ }
++
++ return -EINVAL;
++}
++
++static ssize_t write_level_threshold(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long v;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if(strict_strtoul(buf, 10, &v) == 0)
++ {
++ if(v <= 0xFF) {
++ reg_write(mma, MMA7455L_REG_LDTH, v);
++ return count;
++ } else
++ return -EINVAL;
++ }
++
++ return -EINVAL;
++}
++
++static ssize_t write_calibration(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ int x, y, z;
++ struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++ if (sscanf(buf, "%d %d %d", &x, &y, &z) == 3)
++ {
++ mutex_lock(&mma->lock);
++ __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, x);
++ __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, y);
++ __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, z);
++ mutex_unlock(&mma->lock);
++
++ return count;
++ }
++
++ return -EINVAL;
++}
++
++static DEVICE_ATTR(measure, S_IRUGO, show_measure, NULL);
++static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, write_mode);
++static DEVICE_ATTR(gSelect, S_IRUGO | S_IWUGO, show_gSelect, write_gSelect);
++static DEVICE_ATTR(level_threshold, S_IRUGO | S_IWUGO, show_level_threshold, write_level_threshold);
++static DEVICE_ATTR(calibration, S_IRUGO | S_IWUGO, show_calibration, write_calibration);
++
++static struct attribute *mma7455l_sysfs_entries[] = {
++ &dev_attr_measure.attr,
++ &dev_attr_mode.attr,
++ &dev_attr_gSelect.attr,
++ &dev_attr_level_threshold.attr,
++ &dev_attr_calibration.attr,
++ NULL
++};
++
++static struct attribute_group mma7455l_attr_group = {
++ .attrs = mma7455l_sysfs_entries,
++};
++
++/* input device handling and driver core interaction */
++static int mma7455l_input_open(struct input_dev *inp)
++{
++ struct mma7455l_info *mma = input_get_drvdata(inp);
++ if(mma->mode == MMA7455L_MODE_STANDBY)
++ update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++
++ return 0;
++}
++
++static void mma7455l_input_close(struct input_dev *inp)
++{
++ struct mma7455l_info *mma = input_get_drvdata(inp);
++ update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++}
++
++static int __devinit mma7455l_probe(struct spi_device *spi)
++{
++ int rc;
++ struct mma7455l_info *mma;
++ struct mma7455l_platform_data *pdata = spi->dev.platform_data;
++ u_int8_t wai;
++
++ mma = kzalloc(sizeof(*mma), GFP_KERNEL);
++ if (!mma)
++ return -ENOMEM;
++
++ mutex_init(&mma->lock);
++ INIT_DELAYED_WORK(&mma->work, mma7455l_work);
++ mma->spi_dev = spi;
++ mma->flags = mma->working = 0;
++
++ spi_set_drvdata(spi, mma);
++
++ rc = spi_setup(spi);
++ if (rc < 0) {
++ printk(KERN_ERR "mma7455l error durign spi_setup of mma7455l driver\n");
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++ return rc;
++ }
++
++ wai = reg_read(mma, MMA7455L_REG_WHOAMI);
++ if (wai != MMA7455L_WHOAMI_MAGIC) {
++ printk(KERN_ERR "mma7455l unknown whoami signature 0x%02x\n", wai);
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++ return -ENODEV;
++ }
++
++ rc = request_irq(mma->spi_dev->irq, mma7455l_interrupt, IRQF_TRIGGER_HIGH,
++ "mma7455l", mma);
++ if (rc < 0) {
++ dev_err(&spi->dev, "mma7455l error requesting IRQ %d\n",
++ mma->spi_dev->irq);
++ /* FIXME */
++ return rc;
++ }
++
++ rc = sysfs_create_group(&spi->dev.kobj, &mma7455l_attr_group);
++ if (rc) {
++ dev_err(&spi->dev, "error creating sysfs group\n");
++ return rc;
++ }
++
++ /* initialize input layer details */
++ mma->input_dev = input_allocate_device();
++ if (!mma->input_dev) {
++ dev_err(&spi->dev, "mma7455l Unable to allocate input device\n");
++ /* FIXME */
++ }
++
++ set_bit(EV_ABS, mma->input_dev->evbit);
++ set_bit(ABS_X, mma->input_dev->absbit);
++ set_bit(ABS_Y, mma->input_dev->absbit);
++ set_bit(ABS_Z, mma->input_dev->absbit);
++
++ input_set_drvdata(mma->input_dev, mma);
++ mma->input_dev->name = "MMA7455L";
++ mma->input_dev->open = mma7455l_input_open;
++ mma->input_dev->close = mma7455l_input_close;
++
++ rc = input_register_device(mma->input_dev);
++ if(!rc)
++ {
++ update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++ mutex_lock(&mma->lock);
++ __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, pdata->calibration_x);
++ __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, pdata->calibration_y);
++ __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, pdata->calibration_z);
++ mutex_unlock(&mma->lock);
++
++ return 0;
++ }
++
++ input_free_device(mma->input_dev);
++ return rc;
++}
++
++static int __devexit mma7455l_remove(struct spi_device *spi)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++
++ sysfs_remove_group(&spi->dev.kobj, &mma7455l_attr_group);
++ input_unregister_device(mma->input_dev);
++ dev_set_drvdata(&spi->dev, NULL);
++ kfree(mma);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int mma7455l_suspend(struct spi_device *spi, pm_message_t message)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++ get_mode(mma, &mma->mode, &mma->gSelect);
++ set_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++ return 0;
++}
++
++static int mma7455l_resume(struct spi_device *spi)
++{
++ struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++ update_mode(mma, mma->mode, mma->gSelect);
++
++ return 0;
++}
++#else
++#define mma7455l_suspend NULL
++#define mma7455l_resume NULL
++#endif
++
++static struct spi_driver mma7455l_driver = {
++ .driver = {
++ .name = "mma7455l",
++ .owner = THIS_MODULE,
++ },
++
++ .probe = mma7455l_probe,
++ .remove = __devexit_p(mma7455l_remove),
++ .suspend = mma7455l_suspend,
++ .resume = mma7455l_resume,
++};
++
++static int __init mma7455l_init(void)
++{
++ return spi_register_driver(&mma7455l_driver);
++}
++
++static void __exit mma7455l_exit(void)
++{
++ spi_unregister_driver(&mma7455l_driver);
++}
++
++MODULE_AUTHOR("Gregoire Gentil <gregoire@gentil.com>");
++MODULE_LICENSE("GPL");
++
++module_init(mma7455l_init);
++module_exit(mma7455l_exit);
+diff --git a/include/linux/mma7455l.h b/include/linux/mma7455l.h
+new file mode 100644
+index 0000000..12ab50a
+--- /dev/null
++++ b/include/linux/mma7455l.h
+@@ -0,0 +1,11 @@
++#ifndef _LINUX_MMA7455L_H
++#define _LINUX_MMA7455L_H
++
++struct mma7455l_platform_data {
++ /* Calibration offsets */
++ s16 calibration_x;
++ s16 calibration_y;
++ s16 calibration_z;
++};
++
++#endif /* _LINUX_MMA7455L_H */
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch
new file mode 100644
index 0000000000..57bb4196dd
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch
@@ -0,0 +1,64 @@
+--- a/arch/arm/mach-omap2/devices.c 2009-02-17 21:15:12.000000000 -0800
++++ b/arch/arm/mach-omap2/devices.c 2009-02-17 22:30:26.000000000 -0800
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
++#include <linux/spi/spi_gpio.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -347,6 +348,37 @@
+ .platform_data = &omap2_mcspi4_config,
+ },
+ };
++
++static struct spi_gpio_platform_data spi3_gpio_platform_data = {
++ .miso = 132,
++ .mosi = 131,
++ .sck = 130,
++ .num_chipselect = 1,
++};
++
++static struct platform_device spi3_gpio = {
++ .name = "spi_gpio",
++ .id = 3,
++ .dev = {
++ .platform_data = &spi3_gpio_platform_data,
++ },
++};
++
++static struct spi_gpio_platform_data spi4_gpio_platform_data = {
++ .miso = 159,
++ .mosi = 158,
++ .sck = 156,
++ .num_chipselect = 1,
++};
++
++static struct platform_device spi4_gpio = {
++ .name = "spi_gpio",
++ .id = 4,
++ .dev = {
++ .platform_data = &spi4_gpio_platform_data,
++ },
++};
++
+ #endif
+
+ static void omap_init_mcspi(void)
+--- a/drivers/input/touchscreen/ads7846.c 2009-04-07 10:04:12.000000000 -0700
++++ b/drivers/input/touchscreen/ads7846.c 2009-04-11 12:39:51.000000000 -0700
+@@ -887,13 +919,6 @@
+ return 0;
+ }
+
+- err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+- if (err) {
+- dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
+- pdata->gpio_pendown);
+- return err;
+- }
+-
+ ts->gpio_pendown = pdata->gpio_pendown;
+ return 0;
+ }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch
new file mode 100644
index 0000000000..3b54e71791
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch
@@ -0,0 +1,35 @@
+aufs2 kbuild patch for linux-2.6.29
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 93945dd..75156dd 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -222,6 +222,7 @@ source "fs/qnx4/Kconfig"
+ source "fs/romfs/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
++source "fs/aufs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff --git a/fs/Makefile b/fs/Makefile
+index dc20db3..a4e9a65 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -124,3 +124,4 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_BTRFS_FS) += btrfs/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_AUFS_FS) += aufs/
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 106c3ba..d0c7262 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -34,6 +34,7 @@ header-y += atmppp.h
+ header-y += atmsap.h
+ header-y += atmsvc.h
+ header-y += atm_zatm.h
++header-y += aufs_type.h
+ header-y += auto_fs4.h
+ header-y += ax25.h
+ header-y += b1lli.h
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch
new file mode 100644
index 0000000000..bc3d5d8795
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch
@@ -0,0 +1,285 @@
+aufs2 standalone patch for linux-2.6.29
+
+diff --git a/fs/namei.c b/fs/namei.c
+index bbc15c2..f446c65 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -335,6 +335,9 @@ int deny_write_access(struct file * file)
+
+ return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(deny_write_access);
++#endif
+
+ /**
+ * path_get - get a reference to a path
+@@ -1196,7 +1199,7 @@ out:
+ * needs parent already locked. Doesn't follow mounts.
+ * SMP-safe.
+ */
+-static struct dentry *lookup_hash(struct nameidata *nd)
++struct dentry *lookup_hash(struct nameidata *nd)
+ {
+ int err;
+
+@@ -1205,8 +1208,11 @@ static struct dentry *lookup_hash(struct nameidata *nd)
+ return ERR_PTR(err);
+ return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(lookup_hash);
++#endif
+
+-static int __lookup_one_len(const char *name, struct qstr *this,
++int __lookup_one_len(const char *name, struct qstr *this,
+ struct dentry *base, int len)
+ {
+ unsigned long hash;
+@@ -1227,6 +1233,9 @@ static int __lookup_one_len(const char *name, struct qstr *this,
+ this->hash = end_name_hash(hash);
+ return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(__lookup_one_len);
++#endif
+
+ /**
+ * lookup_one_len - filesystem helper to lookup single pathname component
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 06f8e63..dcdc4ff 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -37,6 +37,9 @@
+
+ /* spinlock for vfsmount related operations, inplace of dcache_lock */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
++#if defined(CONFIG_AUFS_FS_MODULE) && defined(CONFIG_AUFS_EXPORT)
++EXPORT_SYMBOL(vfsmount_lock);
++#endif
+
+ static int event;
+ static DEFINE_IDA(mnt_id_ida);
+diff --git a/fs/open.c b/fs/open.c
+index a3a78ce..7d70245 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -220,6 +220,9 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ return err;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_truncate);
++#endif
+
+ static long do_sys_truncate(const char __user *pathname, loff_t length)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index 4ed0ba4..a110d76 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -888,8 +888,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ int ret;
+
+@@ -908,13 +908,16 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_from);
++#endif
+
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ int ret;
+
+@@ -930,6 +933,9 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+
+ return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_to);
++#endif
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/fs/super.c b/fs/super.c
+index 6ce5014..95eefb9 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -287,6 +287,9 @@ int fsync_super(struct super_block *sb)
+ __fsync_super(sb);
+ return sync_blockdev(sb->s_bdev);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(fsync_super);
++#endif
+
+ /**
+ * generic_shutdown_super - common helper for ->kill_sb()
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 23bf02f..49e5b47 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -58,7 +58,7 @@ enum lock_usage_bit
+ #define LOCKF_USED_IN_IRQ_READ \
+ (LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ)
+
+-#define MAX_LOCKDEP_SUBCLASSES 8UL
++#define MAX_LOCKDEP_SUBCLASSES 12UL
+
+ /*
+ * Lock-classes are keyed via unique addresses, by embedding the
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index fc2e035..182d43b 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -75,6 +75,9 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
+ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+ extern void release_open_intent(struct nameidata *);
+
++extern struct dentry *lookup_hash(struct nameidata *nd);
++extern int __lookup_one_len(const char *name, struct qstr *this,
++ struct dentry *base, int len);
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+ extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
+
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 528dcb9..5123bc6 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -71,4 +71,10 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
+
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
++
+ #endif
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 3aacd0f..76c8876 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -507,6 +507,9 @@ acc_check:
+
+ return -EPERM;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(devcgroup_inode_permission);
++#endif
+
+ int devcgroup_inode_mknod(int mode, dev_t dev)
+ {
+diff --git a/security/security.c b/security/security.c
+index c3586c0..f8798f8 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -389,6 +389,9 @@ int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+ return 0;
+ return security_ops->path_mkdir(path, dentry, mode);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_mkdir);
++#endif
+
+ int security_path_rmdir(struct path *path, struct dentry *dentry)
+ {
+@@ -396,6 +399,9 @@ int security_path_rmdir(struct path *path, struct dentry *dentry)
+ return 0;
+ return security_ops->path_rmdir(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rmdir);
++#endif
+
+ int security_path_unlink(struct path *path, struct dentry *dentry)
+ {
+@@ -403,6 +409,9 @@ int security_path_unlink(struct path *path, struct dentry *dentry)
+ return 0;
+ return security_ops->path_unlink(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_unlink);
++#endif
+
+ int security_path_symlink(struct path *path, struct dentry *dentry,
+ const char *old_name)
+@@ -411,6 +420,9 @@ int security_path_symlink(struct path *path, struct dentry *dentry,
+ return 0;
+ return security_ops->path_symlink(path, dentry, old_name);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_symlink);
++#endif
+
+ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ struct dentry *new_dentry)
+@@ -419,6 +431,9 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ return 0;
+ return security_ops->path_link(old_dentry, new_dir, new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_link);
++#endif
+
+ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ struct path *new_dir, struct dentry *new_dentry)
+@@ -429,6 +444,9 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ return security_ops->path_rename(old_dir, old_dentry, new_dir,
+ new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rename);
++#endif
+
+ int security_path_truncate(struct path *path, loff_t length,
+ unsigned int time_attrs)
+@@ -437,6 +455,9 @@ int security_path_truncate(struct path *path, loff_t length,
+ return 0;
+ return security_ops->path_truncate(path, length, time_attrs);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_truncate);
++#endif
+ #endif
+
+ int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+@@ -506,6 +527,9 @@ int security_inode_readlink(struct dentry *dentry)
+ return 0;
+ return security_ops->inode_readlink(dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_readlink);
++#endif
+
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+@@ -520,6 +544,9 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return security_ops->inode_permission(inode, mask);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_permission);
++#endif
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch
new file mode 100644
index 0000000000..34a035a037
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch
@@ -0,0 +1,23604 @@
+diff -Naur a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs
+--- a/Documentation/ABI/testing/debugfs-aufs 1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/debugfs-aufs 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,40 @@
++What: /debug/aufs/si_<id>/
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ Under /debug/aufs, a directory named si_<id> is created
++ per aufs mount, where <id> is a unique id generated
++ internally.
++
++What: /debug/aufs/si_<id>/xib
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xib (External Inode Number
++ Bitmap), its block size and file size.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
++
++What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xino (External Inode Number
++ Translation Table), its link count, block size and file
++ size.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
++
++What: /debug/aufs/si_<id>/xigen
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the consumed blocks by xigen (External Inode
++ Generation Table), its block size and file size.
++ If CONFIG_AUFS_EXPORT is disabled, this entry will not
++ be created.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs
+--- a/Documentation/ABI/testing/sysfs-aufs 1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/sysfs-aufs 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,25 @@
++What: /sys/fs/aufs/si_<id>/
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ Under /sys/fs/aufs, a directory named si_<id> is created
++ per aufs mount, where <id> is a unique id generated
++ internally.
++
++What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the abolute path of a member directory (which
++ is called branch) in aufs, and its permission.
++
++What: /sys/fs/aufs/si_<id>/xi_path
++Date: March 2009
++Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++ It shows the abolute path of XINO (External Inode Number
++ Bitmap, Translation Table and Generation Table) file
++ even if it is the default path.
++ When the aufs mount option 'noxino' is specified, it
++ will be empty. About XINO files, see
++ Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/fs/aufs/aufs.h b/fs/aufs/aufs.h
+--- a/fs/aufs/aufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/aufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * all header files
++ */
++
++#ifndef __AUFS_H__
++#define __AUFS_H__
++
++#ifdef __KERNEL__
++
++#include "debug.h"
++
++#include "branch.h"
++#include "cpup.h"
++#include "dcsub.h"
++#include "dbgaufs.h"
++#include "dentry.h"
++#include "dir.h"
++#include "file.h"
++#include "fstype.h"
++#include "inode.h"
++#include "loop.h"
++#include "module.h"
++#include "opts.h"
++#include "rwsem.h"
++#include "spl.h"
++#include "super.h"
++#include "sysaufs.h"
++#include "vfsub.h"
++#include "whout.h"
++#include "wkq.h"
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_H__ */
+diff -Naur a/fs/aufs/branch.c b/fs/aufs/branch.c
+--- a/fs/aufs/branch.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,956 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * branch management
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++/*
++ * free a single branch
++ */
++static void au_br_do_free(struct au_branch *br)
++{
++ int i;
++ struct au_wbr *wbr;
++
++ if (br->br_xino.xi_file)
++ fput(br->br_xino.xi_file);
++ mutex_destroy(&br->br_xino.xi_nondir_mtx);
++
++ AuDebugOn(atomic_read(&br->br_count));
++
++ wbr = br->br_wbr;
++ if (wbr) {
++ for (i = 0; i < AuBrWh_Last; i++)
++ dput(wbr->wbr_wh[i]);
++ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
++ au_rwsem_destroy(&wbr->wbr_wh_rwsem);
++ }
++
++ /* some filesystems acquire extra lock */
++ lockdep_off();
++ mntput(br->br_mnt);
++ lockdep_on();
++
++ kfree(wbr);
++ kfree(br);
++}
++
++/*
++ * frees all branches
++ */
++void au_br_free(struct au_sbinfo *sbinfo)
++{
++ aufs_bindex_t bmax;
++ struct au_branch **br;
++
++ bmax = sbinfo->si_bend + 1;
++ br = sbinfo->si_branch;
++ while (bmax--)
++ au_br_do_free(*br++);
++}
++
++/*
++ * find the index of a branch which is specified by @br_id.
++ */
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (au_sbr_id(sb, bindex) == br_id)
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * add a branch
++ */
++
++static int test_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ if (unlikely(h_d1 == h_d2))
++ return 1;
++ return !!au_test_subdir(h_d1, h_d2)
++ || !!au_test_subdir(h_d2, h_d1)
++ || au_test_loopback_overlap(sb, h_d1, h_d2)
++ || au_test_loopback_overlap(sb, h_d2, h_d1);
++}
++
++/*
++ * returns a newly allocated branch. @new_nbranch is a number of branches
++ * after adding a branch.
++ */
++static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
++ int perm)
++{
++ struct au_branch *add_branch;
++ struct dentry *root;
++
++ root = sb->s_root;
++ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
++ if (unlikely(!add_branch))
++ goto out;
++
++ add_branch->br_wbr = NULL;
++ if (au_br_writable(perm)) {
++ /* may be freed separately at changing the branch permission */
++ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
++ GFP_NOFS);
++ if (unlikely(!add_branch->br_wbr))
++ goto out_br;
++ }
++
++ if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
++ || au_di_realloc(au_di(root), new_nbranch)
++ || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
++ goto out_wbr;
++ return add_branch; /* success */
++
++ out_wbr:
++ kfree(add_branch->br_wbr);
++ out_br:
++ kfree(add_branch);
++ out:
++ return ERR_PTR(-ENOMEM);
++}
++
++/*
++ * test if the branch permission is legal or not.
++ */
++static int test_br(struct inode *inode, int brperm, char *path)
++{
++ int err;
++
++ err = 0;
++ if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
++ AuErr("write permission for readonly mount or inode, %s\n",
++ path);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++/*
++ * returns:
++ * 0: success, the caller will add it
++ * plus: success, it is already unified, the caller should ignore it
++ * minus: error
++ */
++static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct dentry *root;
++ struct inode *inode, *h_inode;
++
++ root = sb->s_root;
++ bend = au_sbend(sb);
++ if (unlikely(bend >= 0
++ && au_find_dbindex(root, add->path.dentry) >= 0)) {
++ err = 1;
++ if (!remount) {
++ err = -EINVAL;
++ AuErr("%s duplicated\n", add->pathname);
++ }
++ goto out;
++ }
++
++ err = -ENOSPC; /* -E2BIG; */
++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
++ || AUFS_BRANCH_MAX - 1 <= bend)) {
++ AuErr("number of branches exceeded %s\n", add->pathname);
++ goto out;
++ }
++
++ err = -EDOM;
++ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
++ AuErr("bad index %d\n", add->bindex);
++ goto out;
++ }
++
++ inode = add->path.dentry->d_inode;
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink)) {
++ AuErr("no existence %s\n", add->pathname);
++ goto out;
++ }
++
++ err = -EINVAL;
++ if (unlikely(inode->i_sb == sb)) {
++ AuErr("%s must be outside\n", add->pathname);
++ goto out;
++ }
++
++ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
++ AuErr("unsupported filesystem, %s (%s)\n",
++ add->pathname, au_sbtype(inode->i_sb));
++ goto out;
++ }
++
++ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
++ if (unlikely(err))
++ goto out;
++
++ if (bend < 0)
++ return 0; /* success */
++
++ err = -EINVAL;
++ for (bindex = 0; bindex <= bend; bindex++)
++ if (unlikely(test_overlap(sb, add->path.dentry,
++ au_h_dptr(root, bindex)))) {
++ AuErr("%s is overlapped\n", add->pathname);
++ goto out;
++ }
++
++ err = 0;
++ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
++ h_inode = au_h_dptr(root, 0)->d_inode;
++ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
++ || h_inode->i_uid != inode->i_uid
++ || h_inode->i_gid != inode->i_gid)
++ AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++ add->pathname,
++ inode->i_uid, inode->i_gid,
++ (inode->i_mode & S_IALLUGO),
++ h_inode->i_uid, h_inode->i_gid,
++ (h_inode->i_mode & S_IALLUGO));
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * initialize or clean the whiteouts for an adding branch
++ */
++static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
++ int new_perm, struct dentry *h_root)
++{
++ int err, old_perm;
++ aufs_bindex_t bindex;
++ struct mutex *h_mtx;
++ struct au_wbr *wbr;
++ struct au_hinode *hdir;
++
++ wbr = br->br_wbr;
++ old_perm = br->br_perm;
++ br->br_perm = new_perm;
++ hdir = NULL;
++ h_mtx = NULL;
++ bindex = au_br_index(sb, br->br_id);
++ if (0 <= bindex) {
++ hdir = au_hi(sb->s_root->d_inode, bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ } else {
++ h_mtx = &h_root->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
++ }
++ if (!wbr)
++ err = au_wh_init(h_root, br, sb);
++ else {
++ wbr_wh_write_lock(wbr);
++ err = au_wh_init(h_root, br, sb);
++ wbr_wh_write_unlock(wbr);
++ }
++ if (hdir)
++ au_hin_imtx_unlock(hdir);
++ else
++ mutex_unlock(h_mtx);
++ br->br_perm = old_perm;
++
++ if (!err && wbr && !au_br_writable(new_perm)) {
++ kfree(wbr);
++ br->br_wbr = NULL;
++ }
++
++ return err;
++}
++
++static int au_wbr_init(struct au_branch *br, struct super_block *sb,
++ int perm, struct path *path)
++{
++ int err;
++ struct au_wbr *wbr;
++
++ wbr = br->br_wbr;
++ init_rwsem(&wbr->wbr_wh_rwsem);
++ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
++ atomic_set(&wbr->wbr_wh_running, 0);
++ wbr->wbr_bytes = 0;
++
++ err = au_br_init_wh(sb, br, perm, path->dentry);
++
++ return err;
++}
++
++/* intialize a new branch */
++static int au_br_init(struct au_branch *br, struct super_block *sb,
++ struct au_opt_add *add)
++{
++ int err;
++
++ err = 0;
++ memset(&br->br_xino, 0, sizeof(br->br_xino));
++ mutex_init(&br->br_xino.xi_nondir_mtx);
++ br->br_perm = add->perm;
++ br->br_mnt = add->path.mnt; /* set first, mntget() later */
++ atomic_set(&br->br_count, 0);
++ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
++ atomic_set(&br->br_xino_running, 0);
++ br->br_id = au_new_br_id(sb);
++
++ if (au_br_writable(add->perm)) {
++ err = au_wbr_init(br, sb, add->perm, &add->path);
++ if (unlikely(err))
++ goto out;
++ }
++
++ if (au_opt_test(au_mntflags(sb), XINO)) {
++ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
++ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
++ if (unlikely(err)) {
++ AuDebugOn(br->br_xino.xi_file);
++ goto out;
++ }
++ }
++
++ sysaufs_br_init(br);
++ mntget(add->path.mnt);
++
++ out:
++ return err;
++}
++
++static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
++ struct au_branch *br, aufs_bindex_t bend,
++ aufs_bindex_t amount)
++{
++ struct au_branch **brp;
++
++ brp = sbinfo->si_branch + bindex;
++ memmove(brp + 1, brp, sizeof(*brp) * amount);
++ *brp = br;
++ sbinfo->si_bend++;
++ if (unlikely(bend < 0))
++ sbinfo->si_bend = 0;
++}
++
++static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
++ aufs_bindex_t bend, aufs_bindex_t amount)
++{
++ struct au_hdentry *hdp;
++
++ hdp = dinfo->di_hdentry + bindex;
++ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
++ au_h_dentry_init(hdp);
++ dinfo->di_bend++;
++ if (unlikely(bend < 0))
++ dinfo->di_bstart = 0;
++}
++
++static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
++ aufs_bindex_t bend, aufs_bindex_t amount)
++{
++ struct au_hinode *hip;
++
++ hip = iinfo->ii_hinode + bindex;
++ memmove(hip + 1, hip, sizeof(*hip) * amount);
++ hip->hi_inode = NULL;
++ au_hin_init(hip, NULL);
++ iinfo->ii_bend++;
++ if (unlikely(bend < 0))
++ iinfo->ii_bstart = 0;
++}
++
++static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
++ struct au_branch *br, aufs_bindex_t bindex)
++{
++ struct dentry *root;
++ struct inode *root_inode;
++ aufs_bindex_t bend, amount;
++
++ root = sb->s_root;
++ root_inode = root->d_inode;
++ au_plink_block_maintain(sb);
++ bend = au_sbend(sb);
++ amount = bend + 1 - bindex;
++ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
++ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
++ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
++ au_set_h_dptr(root, bindex, dget(h_dentry));
++ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
++ /*flags*/0);
++}
++
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
++{
++ int err;
++ unsigned long long maxb;
++ aufs_bindex_t bend, add_bindex;
++ struct dentry *root, *h_dentry;
++ struct inode *root_inode;
++ struct au_branch *add_branch;
++
++ root = sb->s_root;
++ root_inode = root->d_inode;
++ IMustLock(root_inode);
++ err = test_add(sb, add, remount);
++ if (unlikely(err < 0))
++ goto out;
++ if (err) {
++ err = 0;
++ goto out; /* success */
++ }
++
++ bend = au_sbend(sb);
++ add_branch = au_br_alloc(sb, bend + 2, add->perm);
++ err = PTR_ERR(add_branch);
++ if (IS_ERR(add_branch))
++ goto out;
++
++ err = au_br_init(add_branch, sb, add);
++ if (unlikely(err)) {
++ au_br_do_free(add_branch);
++ goto out;
++ }
++
++ add_bindex = add->bindex;
++ h_dentry = add->path.dentry;
++ if (!remount)
++ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++ else {
++ sysaufs_brs_del(sb, add_bindex);
++ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++ sysaufs_brs_add(sb, add_bindex);
++ }
++
++ if (!add_bindex)
++ au_cpup_attr_all(root_inode, /*force*/1);
++ else
++ au_add_nlink(root_inode, h_dentry->d_inode);
++ maxb = h_dentry->d_sb->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++
++ /*
++ * this test/set prevents aufs from handling unnecesary inotify events
++ * of xino files, in a case of re-adding a writable branch which was
++ * once detached from aufs.
++ */
++ if (au_xino_brid(sb) < 0
++ && au_br_writable(add_branch->br_perm)
++ && !au_test_fs_bad_xino(h_dentry->d_sb)
++ && add_branch->br_xino.xi_file
++ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
++ au_xino_brid_set(sb, add_branch->br_id);
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * delete a branch
++ */
++
++/* to show the line number, do not make it inlined function */
++#define AuVerbose(do_info, fmt, args...) do { \
++ if (do_info) \
++ AuInfo(fmt, ##args); \
++} while (0)
++
++/*
++ * test if the branch is deletable or not.
++ */
++static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
++ unsigned int sigen)
++{
++ int err, i, j, ndentry;
++ aufs_bindex_t bstart, bend;
++ unsigned char verbose;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry *d;
++ struct inode *inode;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, root, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ ndentry = dpage->ndentry;
++ for (j = 0; !err && j < ndentry; j++) {
++ d = dpage->dentries[j];
++ AuDebugOn(!atomic_read(&d->d_count));
++ inode = d->d_inode;
++ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
++ di_read_lock_child(d, AuLock_IR);
++ else {
++ di_write_lock_child(d);
++ err = au_reval_dpath(d, sigen);
++ if (!err)
++ di_downgrade_lock(d, AuLock_IR);
++ else {
++ di_write_unlock(d);
++ break;
++ }
++ }
++
++ bstart = au_dbstart(d);
++ bend = au_dbend(d);
++ if (bstart <= bindex
++ && bindex <= bend
++ && au_h_dptr(d, bindex)
++ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
++ err = -EBUSY;
++ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
++ }
++ di_read_unlock(d, AuLock_IR);
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
++ unsigned int sigen)
++{
++ int err;
++ struct inode *i;
++ aufs_bindex_t bstart, bend;
++ unsigned char verbose;
++
++ err = 0;
++ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
++ AuDebugOn(!atomic_read(&i->i_count));
++ if (!list_empty(&i->i_dentry))
++ continue;
++
++ if (au_iigen(i) == sigen)
++ ii_read_lock_child(i);
++ else {
++ ii_write_lock_child(i);
++ err = au_refresh_hinode_self(i, /*do_attr*/1);
++ if (!err)
++ ii_downgrade_lock(i);
++ else {
++ ii_write_unlock(i);
++ break;
++ }
++ }
++
++ bstart = au_ibstart(i);
++ bend = au_ibend(i);
++ if (bstart <= bindex
++ && bindex <= bend
++ && au_h_iptr(i, bindex)
++ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
++ err = -EBUSY;
++ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
++ ii_read_unlock(i);
++ break;
++ }
++ ii_read_unlock(i);
++ }
++
++ return err;
++}
++
++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
++{
++ int err;
++ unsigned int sigen;
++
++ sigen = au_sigen(root->d_sb);
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ err = test_dentry_busy(root, bindex, sigen);
++ if (!err)
++ err = test_inode_busy(root->d_sb, bindex, sigen);
++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++ return err;
++}
++
++static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
++ const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_branch **brp, **p;
++
++ brp = sbinfo->si_branch + bindex;
++ if (bindex < bend)
++ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
++ sbinfo->si_branch[0 + bend] = NULL;
++ sbinfo->si_bend--;
++
++ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ sbinfo->si_branch = p;
++}
++
++static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_hdentry *hdp, *p;
++
++ hdp = dinfo->di_hdentry + bindex;
++ if (bindex < bend)
++ memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
++ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
++ dinfo->di_bend--;
++
++ p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ dinfo->di_hdentry = p;
++}
++
++static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
++ const aufs_bindex_t bend)
++{
++ struct au_hinode *hip, *p;
++
++ hip = iinfo->ii_hinode + bindex;
++ if (bindex < bend)
++ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
++ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
++ au_hin_init(iinfo->ii_hinode + bend, NULL);
++ iinfo->ii_bend--;
++
++ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
++ if (p)
++ iinfo->ii_hinode = p;
++}
++
++static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_branch *br)
++{
++ aufs_bindex_t bend;
++ struct au_sbinfo *sbinfo;
++ struct dentry *root;
++ struct inode *inode;
++
++ root = sb->s_root;
++ inode = root->d_inode;
++ au_plink_block_maintain(sb);
++ sbinfo = au_sbi(sb);
++ bend = sbinfo->si_bend;
++
++ dput(au_h_dptr(root, bindex));
++ au_hiput(au_hi(inode, bindex));
++ au_br_do_free(br);
++
++ au_br_do_del_brp(sbinfo, bindex, bend);
++ au_br_do_del_hdp(au_di(root), bindex, bend);
++ au_br_do_del_hip(au_ii(inode), bindex, bend);
++}
++
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
++{
++ int err, rerr, i;
++ unsigned int mnt_flags;
++ aufs_bindex_t bindex, bend, br_id;
++ unsigned char do_wh, verbose;
++ struct au_branch *br;
++ struct au_wbr *wbr;
++
++ err = 0;
++ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
++ if (bindex < 0) {
++ if (remount)
++ goto out; /* success */
++ err = -ENOENT;
++ AuErr("%s no such branch\n", del->pathname);
++ goto out;
++ }
++ AuDbg("bindex b%d\n", bindex);
++
++ err = -EBUSY;
++ mnt_flags = au_mntflags(sb);
++ verbose = !!au_opt_test(mnt_flags, VERBOSE);
++ bend = au_sbend(sb);
++ if (unlikely(!bend)) {
++ AuVerbose(verbose, "no more branches left\n");
++ goto out;
++ }
++ br = au_sbr(sb, bindex);
++ i = atomic_read(&br->br_count);
++ if (unlikely(i)) {
++ AuVerbose(verbose, "%d file(s) opened\n", i);
++ goto out;
++ }
++
++ wbr = br->br_wbr;
++ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
++ if (do_wh) {
++ for (i = 0; i < AuBrWh_Last; i++) {
++ dput(wbr->wbr_wh[i]);
++ wbr->wbr_wh[i] = NULL;
++ }
++ }
++
++ err = test_children_busy(sb->s_root, bindex);
++ if (unlikely(err)) {
++ if (do_wh)
++ goto out_wh;
++ goto out;
++ }
++
++ err = 0;
++ br_id = br->br_id;
++ if (!remount)
++ au_br_do_del(sb, bindex, br);
++ else {
++ sysaufs_brs_del(sb, bindex);
++ au_br_do_del(sb, bindex, br);
++ sysaufs_brs_add(sb, bindex);
++ }
++
++ if (!bindex)
++ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
++ else
++ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
++ if (au_opt_test(mnt_flags, PLINK))
++ au_plink_half_refresh(sb, br_id);
++
++ if (sb->s_maxbytes == del->h_path.dentry->d_sb->s_maxbytes) {
++ bend--;
++ sb->s_maxbytes = 0;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ unsigned long long maxb;
++
++ maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
++ if (sb->s_maxbytes < maxb)
++ sb->s_maxbytes = maxb;
++ }
++ }
++
++ if (au_xino_brid(sb) == br->br_id)
++ au_xino_brid_set(sb, -1);
++ goto out; /* success */
++
++ out_wh:
++ /* revert */
++ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
++ if (rerr)
++ AuWarn("failed re-creating base whiteout, %s. (%d)\n",
++ del->pathname, rerr);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * change a branch permission
++ */
++
++static int do_need_sigen_inc(int a, int b)
++{
++ return au_br_whable(a) && !au_br_whable(b);
++}
++
++static int need_sigen_inc(int old, int new)
++{
++ return do_need_sigen_inc(old, new)
++ || do_need_sigen_inc(new, old);
++}
++
++static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ unsigned long n, ul, bytes, files;
++ aufs_bindex_t bstart;
++ struct file *file, *hf, **a;
++ const int step_bytes = 1024, /* memory allocation unit */
++ step_files = step_bytes / sizeof(*a);
++
++ err = -ENOMEM;
++ n = 0;
++ bytes = step_bytes;
++ files = step_files;
++ a = kmalloc(bytes, GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ /* no need file_list_lock() since sbinfo is locked? defered? */
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
++ if (special_file(file->f_dentry->d_inode->i_mode))
++ continue;
++
++ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
++ fi_read_lock(file);
++ if (unlikely(au_test_mmapped(file))) {
++ err = -EBUSY;
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ goto out_free;
++ }
++
++ bstart = au_fbstart(file);
++ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++ || !(file->f_mode & FMODE_WRITE)
++ || bstart != bindex) {
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++ continue;
++ }
++
++ hf = au_h_fptr(file, bstart);
++ FiMustNoWaiters(file);
++ fi_read_unlock(file);
++
++ if (n < files)
++ a[n++] = hf;
++ else {
++ void *p;
++
++ err = -ENOMEM;
++ bytes += step_bytes;
++ files += step_files;
++ p = krealloc(a, bytes, GFP_NOFS);
++ if (p) {
++ a = p;
++ a[n++] = hf;
++ } else
++ goto out_free;
++ }
++ }
++
++ err = 0;
++ for (ul = 0; ul < n; ul++) {
++ /* todo: already flushed? */
++ /* cf. fs/super.c:mark_files_ro() */
++ hf = a[ul];
++ hf->f_mode &= ~FMODE_WRITE;
++ if (!file_check_writeable(hf)) {
++ file_release_write(hf);
++ mnt_drop_write(hf->f_vfsmnt);
++ }
++ }
++
++ out_free:
++ kfree(a);
++ out:
++ return err;
++}
++
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++ int *do_update)
++{
++ int err, rerr;
++ aufs_bindex_t bindex;
++ struct dentry *root;
++ struct au_branch *br;
++
++ root = sb->s_root;
++ au_plink_block_maintain(sb);
++ bindex = au_find_dbindex(root, mod->h_root);
++ if (bindex < 0) {
++ if (remount)
++ return 0; /* success */
++ err = -ENOENT;
++ AuErr("%s no such branch\n", mod->path);
++ goto out;
++ }
++ AuDbg("bindex b%d\n", bindex);
++
++ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
++ if (unlikely(err))
++ goto out;
++
++ br = au_sbr(sb, bindex);
++ if (br->br_perm == mod->perm)
++ return 0; /* success */
++
++ if (au_br_writable(br->br_perm)) {
++ /* remove whiteout base */
++ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
++ if (unlikely(err))
++ goto out;
++
++ if (!au_br_writable(mod->perm)) {
++ /* rw --> ro, file might be mmapped */
++ DiMustNoWaiters(root);
++ IiMustNoWaiters(root->d_inode);
++ di_write_unlock(root);
++ err = au_br_mod_files_ro(sb, bindex);
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++
++ if (unlikely(err)) {
++ rerr = -ENOMEM;
++ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
++ GFP_NOFS);
++ if (br->br_wbr)
++ rerr = au_br_init_wh
++ (sb, br, br->br_perm,
++ mod->h_root);
++ if (unlikely(rerr)) {
++ AuIOErr("nested error %d (%d)\n",
++ rerr, err);
++ br->br_perm = mod->perm;
++ }
++ }
++ }
++ } else if (au_br_writable(mod->perm)) {
++ /* ro --> rw */
++ err = -ENOMEM;
++ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
++ if (br->br_wbr) {
++ struct path path = {
++ .mnt = br->br_mnt,
++ .dentry = mod->h_root
++ };
++
++ err = au_wbr_init(br, sb, mod->perm, &path);
++ if (unlikely(err)) {
++ kfree(br->br_wbr);
++ br->br_wbr = NULL;
++ }
++ }
++ }
++
++ if (!err) {
++ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++ br->br_perm = mod->perm;
++ }
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/branch.h b/fs/aufs/branch.h
+--- a/fs/aufs/branch.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,215 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * branch filesystems and xino for them
++ */
++
++#ifndef __AUFS_BRANCH_H__
++#define __AUFS_BRANCH_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "super.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* a xino file */
++struct au_xino_file {
++ struct file *xi_file;
++ struct mutex xi_nondir_mtx;
++
++ /* todo: make xino files an array to support huge inode number */
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *xi_dbgaufs;
++#endif
++};
++
++/* members for writable branch only */
++enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
++struct au_wbr {
++ struct rw_semaphore wbr_wh_rwsem;
++ struct dentry *wbr_wh[AuBrWh_Last];
++ atomic_t wbr_wh_running;
++#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
++#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
++#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
++
++ /* mfs mode */
++ unsigned long long wbr_bytes;
++};
++
++/* protected by superblock rwsem */
++struct au_branch {
++ struct au_xino_file br_xino;
++
++ aufs_bindex_t br_id;
++
++ int br_perm;
++ struct vfsmount *br_mnt;
++ atomic_t br_count;
++
++ struct au_wbr *br_wbr;
++
++ /* xino truncation */
++ blkcnt_t br_xino_upper; /* watermark in blocks */
++ atomic_t br_xino_running;
++
++#ifdef CONFIG_SYSFS
++ /* an entry under sysfs per mount-point */
++ char br_name[8];
++ struct attribute br_attr;
++#endif
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* branch permission and attribute */
++enum {
++ AuBrPerm_RW, /* writable, linkable wh */
++ AuBrPerm_RO, /* readonly, no wh */
++ AuBrPerm_RR, /* natively readonly, no wh */
++
++ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
++
++ AuBrPerm_ROWH, /* whiteout-able */
++ AuBrPerm_RRWH, /* whiteout-able */
++
++ AuBrPerm_Last
++};
++
++static inline int au_br_writable(int brperm)
++{
++ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
++}
++
++static inline int au_br_whable(int brperm)
++{
++ return brperm == AuBrPerm_RW
++ || brperm == AuBrPerm_ROWH
++ || brperm == AuBrPerm_RRWH;
++}
++
++static inline int au_br_rdonly(struct au_branch *br)
++{
++ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
++ || !au_br_writable(br->br_perm))
++ ? -EROFS : 0;
++}
++
++static inline int au_br_hinotifyable(int brperm __maybe_unused)
++{
++#ifdef CONFIG_AUFS_HINOTIFY
++ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
++#else
++ return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* branch.c */
++struct au_sbinfo;
++void au_br_free(struct au_sbinfo *sinfo);
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
++struct au_opt_add;
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
++struct au_opt_del;
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
++struct au_opt_mod;
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++ int *do_update);
++
++/* xino.c */
++static const loff_t au_loff_max = LLONG_MAX;
++
++int au_xib_trunc(struct super_block *sb);
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos);
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos);
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
++ino_t au_xino_new_ino(struct super_block *sb);
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino);
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino);
++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t *ino);
++int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
++ struct file *base_file, int do_test);
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
++
++struct au_opt_xino;
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
++void au_xino_clr(struct super_block *sb);
++struct file *au_xino_def(struct super_block *sb);
++int au_xino_path(struct seq_file *seq, struct file *file);
++
++/* ---------------------------------------------------------------------- */
++
++/* Superblock to branch */
++static inline
++aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_id;
++}
++
++static inline
++struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_mnt;
++}
++
++static inline
++struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr_mnt(sb, bindex)->mnt_sb;
++}
++
++static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
++{
++ atomic_dec(&au_sbr(sb, bindex)->br_count);
++}
++
++static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_sbr(sb, bindex)->br_perm;
++}
++
++static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_br_whable(au_sbr_perm(sb, bindex));
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * wbr_wh_read_lock, wbr_wh_write_lock
++ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
++ */
++AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_BRANCH_H__ */
+diff -Naur a/fs/aufs/cpup.c b/fs/aufs/cpup.c
+--- a/fs/aufs/cpup.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1039 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * copy-up functions, see wbr_policy.c for copy-down
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src)
++{
++ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
++ | S_NOATIME | S_NOCMTIME;
++
++ dst->i_flags |= src->i_flags & ~mask;
++ if (au_test_fs_notime(dst->i_sb))
++ dst->i_flags |= S_NOATIME | S_NOCMTIME;
++}
++
++void au_cpup_attr_timesizes(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ fsstack_copy_attr_times(inode, h_inode);
++ vfsub_copy_inode_size(inode, h_inode);
++}
++
++void au_cpup_attr_nlink(struct inode *inode, int force)
++{
++ struct inode *h_inode;
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend;
++
++ sb = inode->i_sb;
++ bindex = au_ibstart(inode);
++ h_inode = au_h_iptr(inode, bindex);
++ if (!force
++ && !S_ISDIR(h_inode->i_mode)
++ && au_opt_test(au_mntflags(sb), PLINK)
++ && au_plink_test(inode))
++ return;
++
++ inode->i_nlink = h_inode->i_nlink;
++
++ /*
++ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
++ * it may includes whplink directory.
++ */
++ if (S_ISDIR(h_inode->i_mode)) {
++ bend = au_ibend(inode);
++ for (bindex++; bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode)
++ au_add_nlink(inode, h_inode);
++ }
++ }
++}
++
++void au_cpup_attr_changeable(struct inode *inode)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ inode->i_mode = h_inode->i_mode;
++ inode->i_uid = h_inode->i_uid;
++ inode->i_gid = h_inode->i_gid;
++ au_cpup_attr_timesizes(inode);
++ au_cpup_attr_flags(inode, h_inode);
++}
++
++void au_cpup_igen(struct inode *inode, struct inode *h_inode)
++{
++ struct au_iinfo *iinfo = au_ii(inode);
++
++ iinfo->ii_higen = h_inode->i_generation;
++ iinfo->ii_hsb1 = h_inode->i_sb;
++}
++
++void au_cpup_attr_all(struct inode *inode, int force)
++{
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ au_cpup_attr_changeable(inode);
++ if (inode->i_nlink > 0)
++ au_cpup_attr_nlink(inode, force);
++ inode->i_rdev = h_inode->i_rdev;
++ inode->i_blkbits = h_inode->i_blkbits;
++ au_cpup_igen(inode, h_inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
++
++/* keep the timestamps of the parent dir when cpup */
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++ struct path *h_path)
++{
++ struct inode *h_inode;
++
++ dt->dt_dentry = dentry;
++ dt->dt_h_path = *h_path;
++ h_inode = h_path->dentry->d_inode;
++ dt->dt_atime = h_inode->i_atime;
++ dt->dt_mtime = h_inode->i_mtime;
++ /* smp_mb(); */
++}
++
++void au_dtime_revert(struct au_dtime *dt)
++{
++ struct iattr attr;
++ int err;
++
++ attr.ia_atime = dt->dt_atime;
++ attr.ia_mtime = dt->dt_mtime;
++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
++ | ATTR_ATIME | ATTR_ATIME_SET;
++
++ err = vfsub_notify_change(&dt->dt_h_path, &attr);
++ if (unlikely(err))
++ AuWarn("restoring timestamps failed(%d). ignored\n", err);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static noinline_for_stack
++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
++{
++ int err, sbits;
++ struct iattr ia;
++ struct path h_path;
++ struct inode *h_isrc;
++
++ h_path.dentry = au_h_dptr(dst, bindex);
++ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
++ h_isrc = h_src->d_inode;
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
++ | ATTR_ATIME | ATTR_MTIME
++ | ATTR_ATIME_SET | ATTR_MTIME_SET;
++ ia.ia_mode = h_isrc->i_mode;
++ ia.ia_uid = h_isrc->i_uid;
++ ia.ia_gid = h_isrc->i_gid;
++ ia.ia_atime = h_isrc->i_atime;
++ ia.ia_mtime = h_isrc->i_mtime;
++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++ au_cpup_attr_flags(h_path.dentry->d_inode, h_isrc);
++ err = vfsub_notify_change(&h_path, &ia);
++
++ /* is this nfs only? */
++ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++ ia.ia_mode = h_isrc->i_mode;
++ err = vfsub_notify_change(&h_path, &ia);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
++ char *buf, unsigned long blksize)
++{
++ int err;
++ size_t sz, rbytes, wbytes;
++ unsigned char all_zero;
++ char *p, *zp;
++ struct mutex *h_mtx;
++ /* reduce stack usage */
++ struct iattr *ia;
++
++ zp = page_address(ZERO_PAGE(0));
++ if (unlikely(!zp))
++ return -ENOMEM; /* possible? */
++
++ err = 0;
++ all_zero = 0;
++ while (len) {
++ AuDbg("len %lld\n", len);
++ sz = blksize;
++ if (len < blksize)
++ sz = len;
++
++ rbytes = 0;
++ /* todo: signal_pending? */
++ while (!rbytes || err == -EAGAIN || err == -EINTR) {
++ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
++ err = rbytes;
++ }
++ if (unlikely(err < 0))
++ break;
++
++ all_zero = 0;
++ if (len >= rbytes && rbytes == blksize)
++ all_zero = !memcmp(buf, zp, rbytes);
++ if (!all_zero) {
++ wbytes = rbytes;
++ p = buf;
++ while (wbytes) {
++ size_t b;
++
++ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
++ err = b;
++ /* todo: signal_pending? */
++ if (unlikely(err == -EAGAIN || err == -EINTR))
++ continue;
++ if (unlikely(err < 0))
++ break;
++ wbytes -= b;
++ p += b;
++ }
++ } else {
++ loff_t res;
++
++ AuLabel(hole);
++ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
++ err = res;
++ if (unlikely(res < 0))
++ break;
++ }
++ len -= rbytes;
++ err = 0;
++ }
++
++ /* the last block may be a hole */
++ if (!err && all_zero) {
++ AuLabel(last hole);
++
++ err = 1;
++ if (au_test_nfs(dst->f_dentry->d_sb)) {
++ /* nfs requires this step to make last hole */
++ /* is this only nfs? */
++ do {
++ /* todo: signal_pending? */
++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ if (err == 1)
++ dst->f_pos--;
++ }
++
++ if (err == 1) {
++ ia = (void *)buf;
++ ia->ia_size = dst->f_pos;
++ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
++ ia->ia_file = dst;
++ h_mtx = &dst->f_dentry->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
++ err = vfsub_notify_change(&dst->f_path, ia);
++ mutex_unlock(h_mtx);
++ }
++ }
++
++ return err;
++}
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len)
++{
++ int err;
++ unsigned long blksize;
++ unsigned char do_kfree;
++ char *buf;
++
++ err = -ENOMEM;
++ blksize = dst->f_dentry->d_sb->s_blocksize;
++ if (!blksize || PAGE_SIZE < blksize)
++ blksize = PAGE_SIZE;
++ AuDbg("blksize %lu\n", blksize);
++ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
++ if (do_kfree)
++ buf = kmalloc(blksize, GFP_NOFS);
++ else
++ buf = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!buf))
++ goto out;
++
++ if (len > (1 << 22))
++ AuDbg("copying a large file %lld\n", (long long)len);
++
++ src->f_pos = 0;
++ dst->f_pos = 0;
++ err = au_do_copy_file(dst, src, len, buf, blksize);
++ if (do_kfree)
++ kfree(buf);
++ else
++ free_page((unsigned long)buf);
++
++ out:
++ return err;
++}
++
++/*
++ * to support a sparse file which is opened with O_APPEND,
++ * we need to close the file.
++ */
++static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len)
++{
++ int err, i;
++ enum { SRC, DST };
++ struct {
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ struct dentry *dentry;
++ struct file *file;
++ void *label, *label_file;
++ } *f, file[] = {
++ {
++ .bindex = bsrc,
++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out,
++ .label_file = &&out_src
++ },
++ {
++ .bindex = bdst,
++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
++ .file = NULL,
++ .label = &&out_src,
++ .label_file = &&out_dst
++ }
++ };
++ struct super_block *sb;
++
++ /* bsrc branch can be ro/rw. */
++ sb = dentry->d_sb;
++ f = file;
++ for (i = 0; i < 2; i++, f++) {
++ f->dentry = au_h_dptr(dentry, f->bindex);
++ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
++ err = PTR_ERR(f->file);
++ if (IS_ERR(f->file))
++ goto *f->label;
++ err = -EINVAL;
++ if (unlikely(!f->file->f_op))
++ goto *f->label_file;
++ }
++
++ /* try stopping to update while we copyup */
++ IMustLock(file[SRC].dentry->d_inode);
++ err = au_copy_file(file[DST].file, file[SRC].file, len);
++
++ out_dst:
++ fput(file[DST].file);
++ au_sbr_put(sb, file[DST].bindex);
++ out_src:
++ fput(file[SRC].file);
++ au_sbr_put(sb, file[SRC].bindex);
++ out:
++ return err;
++}
++
++static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len,
++ struct inode *h_dir, struct path *h_path)
++{
++ int err, rerr;
++ loff_t l;
++
++ err = 0;
++ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
++ if (len == -1 || l < len)
++ len = l;
++ if (len)
++ err = au_cp_regular(dentry, bdst, bsrc, len);
++ if (!err)
++ goto out; /* success */
++
++ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
++ if (rerr) {
++ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
++ AuDLNPair(h_path->dentry), err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ return err;
++}
++
++static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
++ struct inode *h_dir)
++{
++ int err, symlen;
++ mm_segment_t old_fs;
++ char *sym;
++
++ err = -ENOSYS;
++ if (unlikely(!h_src->d_inode->i_op->readlink))
++ goto out;
++
++ err = -ENOMEM;
++ sym = __getname();
++ if (unlikely(!sym))
++ goto out;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
++ PATH_MAX);
++ err = symlen;
++ set_fs(old_fs);
++
++ if (symlen > 0) {
++ sym[symlen] = 0;
++ err = vfsub_symlink(h_dir, h_path, sym);
++ }
++ __putname(sym);
++
++ out:
++ return err;
++}
++
++/* return with the lower dst inode is locked */
++static noinline_for_stack
++int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err;
++ umode_t mode;
++ unsigned int mnt_flags;
++ unsigned char isdir;
++ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
++ struct au_dtime dt;
++ struct path h_path;
++ struct dentry *h_src, *h_dst, *h_parent;
++ struct inode *h_inode, *h_dir;
++ struct super_block *sb;
++
++ /* bsrc branch can be ro/rw. */
++ h_src = au_h_dptr(dentry, bsrc);
++ h_inode = h_src->d_inode;
++ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
++
++ /* try stopping to be referenced while we are creating */
++ h_dst = au_h_dptr(dentry, bdst);
++ h_parent = h_dst->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++ AuDebugOn(h_parent != h_dst->d_parent);
++
++ sb = dentry->d_sb;
++ h_path.mnt = au_sbr_mnt(sb, bdst);
++ if (do_dt) {
++ h_path.dentry = h_parent;
++ au_dtime_store(&dt, dst_parent, &h_path);
++ }
++ h_path.dentry = h_dst;
++
++ isdir = 0;
++ mode = h_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ /* try stopping to update while we are referencing */
++ IMustLock(h_inode);
++ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
++ if (!err)
++ err = au_do_cpup_regular
++ (dentry, bdst, bsrc, len,
++ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ err = vfsub_mkdir(h_dir, &h_path, mode);
++ if (!err) {
++ /*
++ * strange behaviour from the users view,
++ * particularry setattr case
++ */
++ if (au_ibstart(dst_parent->d_inode) == bdst)
++ au_cpup_attr_nlink(dst_parent->d_inode,
++ /*force*/1);
++ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
++ }
++ break;
++ case S_IFLNK:
++ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
++ break;
++ case S_IFCHR:
++ case S_IFBLK:
++ AuDebugOn(!capable(CAP_MKNOD));
++ /*FALLTHROUGH*/
++ case S_IFIFO:
++ case S_IFSOCK:
++ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
++ break;
++ default:
++ AuIOErr("Unknown inode type 0%o\n", mode);
++ err = -EIO;
++ }
++
++ mnt_flags = au_mntflags(sb);
++ if (!au_opt_test(mnt_flags, UDBA_NONE)
++ && !isdir
++ && au_opt_test(mnt_flags, XINO)
++ && h_inode->i_nlink == 1
++ /* todo: unnecessary? */
++ /* && dentry->d_inode->i_nlink == 1 */
++ && bdst < bsrc
++ && !au_ftest_cpup(flags, KEEPLINO))
++ au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
++ /* ignore this error */
++
++ if (do_dt)
++ au_dtime_revert(&dt);
++ return err;
++}
++
++/*
++ * copyup the @dentry from @bsrc to @bdst.
++ * the caller must set the both of lower dentries.
++ * @len is for truncating when it is -1 copyup the entire file.
++ * in link/rename cases, @dst_parent may be different from the real one.
++ */
++static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err, rerr;
++ aufs_bindex_t old_ibstart;
++ unsigned char isdir, plink;
++ struct au_dtime dt;
++ struct path h_path;
++ struct dentry *h_src, *h_dst, *h_parent;
++ struct inode *dst_inode, *h_dir, *inode;
++ struct super_block *sb;
++
++ AuDebugOn(bsrc <= bdst);
++
++ sb = dentry->d_sb;
++ h_path.mnt = au_sbr_mnt(sb, bdst);
++ h_dst = au_h_dptr(dentry, bdst);
++ h_parent = h_dst->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ h_src = au_h_dptr(dentry, bsrc);
++ inode = dentry->d_inode;
++
++ if (!dst_parent)
++ dst_parent = dget_parent(dentry);
++ else
++ dget(dst_parent);
++
++ plink = !!au_opt_test(au_mntflags(sb), PLINK);
++ dst_inode = au_h_iptr(inode, bdst);
++ if (dst_inode) {
++ if (unlikely(!plink)) {
++ err = -EIO;
++ AuIOErr("i%lu exists on a upper branch "
++ "but plink is disabled\n", inode->i_ino);
++ goto out;
++ }
++
++ if (dst_inode->i_nlink) {
++ const int do_dt = au_ftest_cpup(flags, DTIME);
++
++ h_src = au_plink_lkup(inode, bdst);
++ err = PTR_ERR(h_src);
++ if (IS_ERR(h_src))
++ goto out;
++ if (unlikely(!h_src->d_inode)) {
++ err = -EIO;
++ AuIOErr("i%lu exists on a upper branch "
++ "but plink is broken\n", inode->i_ino);
++ dput(h_src);
++ goto out;
++ }
++
++ if (do_dt) {
++ h_path.dentry = h_parent;
++ au_dtime_store(&dt, dst_parent, &h_path);
++ }
++ h_path.dentry = h_dst;
++ err = vfsub_link(h_src, h_dir, &h_path);
++ if (do_dt)
++ au_dtime_revert(&dt);
++ dput(h_src);
++ goto out;
++ } else
++ /* todo: cpup_wh_file? */
++ /* udba work */
++ au_update_brange(inode, 1);
++ }
++
++ old_ibstart = au_ibstart(inode);
++ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
++ if (unlikely(err))
++ goto out;
++ dst_inode = h_dst->d_inode;
++ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
++
++ err = cpup_iattr(dentry, bdst, h_src);
++ isdir = S_ISDIR(dst_inode->i_mode);
++ if (!err) {
++ if (bdst < old_ibstart)
++ au_set_ibstart(inode, bdst);
++ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
++ au_hi_flags(inode, isdir));
++ mutex_unlock(&dst_inode->i_mutex);
++ if (!isdir
++ && h_src->d_inode->i_nlink > 1
++ && plink)
++ au_plink_append(inode, bdst, h_dst);
++ goto out; /* success */
++ }
++
++ /* revert */
++ h_path.dentry = h_parent;
++ mutex_unlock(&dst_inode->i_mutex);
++ au_dtime_store(&dt, dst_parent, &h_path);
++ h_path.dentry = h_dst;
++ if (!isdir)
++ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ else
++ rerr = vfsub_rmdir(h_dir, &h_path);
++ au_dtime_revert(&dt);
++ if (rerr) {
++ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
++ err = -EIO;
++ }
++
++ out:
++ dput(dst_parent);
++ return err;
++}
++
++struct au_cpup_single_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst, bsrc;
++ loff_t len;
++ unsigned int flags;
++ struct dentry *dst_parent;
++};
++
++static void au_call_cpup_single(void *args)
++{
++ struct au_cpup_single_args *a = args;
++ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
++ a->flags, a->dst_parent);
++}
++
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent)
++{
++ int err, wkq_err;
++ umode_t mode;
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bsrc);
++ mode = h_dentry->d_inode->i_mode & S_IFMT;
++ if ((mode != S_IFCHR && mode != S_IFBLK)
++ || capable(CAP_MKNOD))
++ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
++ dst_parent);
++ else {
++ struct au_cpup_single_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .bsrc = bsrc,
++ .len = len,
++ .flags = flags,
++ .dst_parent = dst_parent
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++/*
++ * copyup the @dentry from the first active lower branch to @bdst,
++ * using au_cpup_single().
++ */
++static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err;
++ aufs_bindex_t bsrc, bend;
++
++ bend = au_dbend(dentry);
++ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
++ if (au_h_dptr(dentry, bsrc))
++ break;
++
++ err = au_lkup_neg(dentry, bdst);
++ if (!err) {
++ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
++ if (!err)
++ return 0; /* success */
++
++ /* revert */
++ au_set_h_dptr(dentry, bdst, NULL);
++ au_set_dbstart(dentry, bsrc);
++ }
++
++ return err;
++}
++
++struct au_cpup_simple_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ unsigned int flags;
++};
++
++static void au_call_cpup_simple(void *args)
++{
++ struct au_cpup_simple_args *a = args;
++ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
++}
++
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags)
++{
++ int err, wkq_err;
++ unsigned char do_sio;
++ struct dentry *parent;
++ struct inode *h_dir;
++
++ parent = dget_parent(dentry);
++ h_dir = au_h_iptr(parent->d_inode, bdst);
++ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio) {
++ /*
++ * testing CAP_MKNOD is for generic fs,
++ * but CAP_FSETID is for xfs only, currently.
++ */
++ umode_t mode = dentry->d_inode->i_mode;
++ do_sio = (((mode & (S_IFCHR | S_IFBLK))
++ && !capable(CAP_MKNOD))
++ || ((mode & (S_ISUID | S_ISGID))
++ && !capable(CAP_FSETID)));
++ }
++ if (!do_sio)
++ err = au_cpup_simple(dentry, bdst, len, flags);
++ else {
++ struct au_cpup_simple_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .flags = flags
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * copyup the deleted file for writing.
++ */
++static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *wh_dentry, struct file *file,
++ loff_t len)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct dentry *h_d_dst, *h_d_start;
++
++ dinfo = au_di(dentry);
++ bstart = dinfo->di_bstart;
++ h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
++ dinfo->di_bstart = bdst;
++ dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
++ h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
++ if (file)
++ dinfo->di_hdentry[0 + bstart].hd_dentry
++ = au_h_fptr(file, au_fbstart(file))->f_dentry;
++ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
++ /*h_parent*/NULL);
++ if (!err && file) {
++ err = au_reopen_nondir(file);
++ dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
++ }
++ dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
++ dinfo->di_bstart = bstart;
++
++ return err;
++}
++
++static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file)
++{
++ int err;
++ struct au_dtime dt;
++ struct dentry *parent, *h_parent, *wh_dentry;
++ struct au_branch *br;
++ struct path h_path;
++
++ br = au_sbr(dentry->d_sb, bdst);
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bdst);
++ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ h_path.dentry = h_parent;
++ h_path.mnt = br->br_mnt;
++ au_dtime_store(&dt, parent, &h_path);
++ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
++ if (unlikely(err))
++ goto out_wh;
++
++ dget(wh_dentry);
++ h_path.dentry = wh_dentry;
++ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
++ if (unlikely(err)) {
++ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
++ AuDLNPair(wh_dentry), err);
++ err = -EIO;
++ }
++ au_dtime_revert(&dt);
++ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ dput(parent);
++ return err;
++}
++
++struct au_cpup_wh_args {
++ int *errp;
++ struct dentry *dentry;
++ aufs_bindex_t bdst;
++ loff_t len;
++ struct file *file;
++};
++
++static void au_call_cpup_wh(void *args)
++{
++ struct au_cpup_wh_args *a = args;
++ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
++}
++
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file)
++{
++ int err, wkq_err;
++ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
++ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
++ struct au_wbr *wbr;
++
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ h_orph = NULL;
++ h_parent = NULL;
++ h_dir = au_igrab(au_h_iptr(dir, bdst));
++ h_tmpdir = h_dir;
++ if (!h_dir->i_nlink) {
++ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
++ h_orph = wbr->wbr_orph;
++
++ h_parent = dget(au_h_dptr(parent, bdst));
++ au_set_h_dptr(parent, bdst, NULL);
++ au_set_h_dptr(parent, bdst, dget(h_orph));
++ h_tmpdir = h_orph->d_inode;
++ au_set_h_iptr(dir, bdst, NULL, 0);
++ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
++
++ /* this temporary unlock is safe */
++ if (file)
++ h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
++ else
++ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
++ h_inode = h_dentry->d_inode;
++ IMustLock(h_inode);
++ mutex_unlock(&h_inode->i_mutex);
++ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT2);
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ }
++
++ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
++ err = au_cpup_wh(dentry, bdst, len, file);
++ else {
++ struct au_cpup_wh_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .bdst = bdst,
++ .len = len,
++ .file = file
++ };
++ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ if (h_orph) {
++ mutex_unlock(&h_tmpdir->i_mutex);
++ au_set_h_iptr(dir, bdst, NULL, 0);
++ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
++ au_set_h_dptr(parent, bdst, NULL);
++ au_set_h_dptr(parent, bdst, h_parent);
++ }
++ iput(h_dir);
++ dput(parent);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generic routine for both of copy-up and copy-down.
++ */
++/* cf. revalidate function in file.c */
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg),
++ void *arg)
++{
++ int err;
++ struct au_pin pin;
++ struct dentry *d, *parent, *h_parent, *real_parent;
++
++ err = 0;
++ parent = dget_parent(dentry);
++ if (IS_ROOT(parent))
++ goto out;
++
++ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
++ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
++
++ /* do not use au_dpage */
++ real_parent = parent;
++ while (1) {
++ dput(parent);
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bdst);
++ if (h_parent)
++ goto out; /* success */
++
++ /* find top dir which is necessary to cpup */
++ do {
++ d = parent;
++ dput(parent);
++ parent = dget_parent(d);
++ di_read_lock_parent3(parent, !AuLock_IR);
++ h_parent = au_h_dptr(parent, bdst);
++ di_read_unlock(parent, !AuLock_IR);
++ } while (!h_parent);
++
++ if (d != real_parent)
++ di_write_lock_child3(d);
++
++ /* somebody else might create while we were sleeping */
++ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
++ if (au_h_dptr(d, bdst))
++ au_update_dbstart(d);
++
++ au_pin_set_dentry(&pin, d);
++ err = au_do_pin(&pin);
++ if (!err) {
++ err = cp(d, bdst, h_parent, arg);
++ au_unpin(&pin);
++ }
++ }
++
++ if (d != real_parent)
++ di_write_unlock(d);
++ if (unlikely(err))
++ break;
++ }
++
++ out:
++ dput(parent);
++ return err;
++}
++
++static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent __maybe_unused ,
++ void *arg __maybe_unused)
++{
++ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
++}
++
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
++}
++
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *dir;
++
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ err = 0;
++ if (au_h_iptr(dir, bdst))
++ goto out;
++
++ di_read_unlock(parent, AuLock_IR);
++ di_write_lock_parent(parent);
++ /* someone else might change our inode while we were sleeping */
++ if (!au_h_iptr(dir, bdst))
++ err = au_cpup_dirs(dentry, bdst);
++ di_downgrade_lock(parent, AuLock_IR);
++
++ out:
++ dput(parent);
++ return err;
++}
+diff -Naur a/fs/aufs/cpup.h b/fs/aufs/cpup.h
+--- a/fs/aufs/cpup.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * copy-up/down functions
++ */
++
++#ifndef __AUFS_CPUP_H__
++#define __AUFS_CPUP_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/time.h>
++#include <linux/aufs_type.h>
++
++struct inode;
++struct file;
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src);
++void au_cpup_attr_timesizes(struct inode *inode);
++void au_cpup_attr_nlink(struct inode *inode, int force);
++void au_cpup_attr_changeable(struct inode *inode);
++void au_cpup_igen(struct inode *inode, struct inode *h_inode);
++void au_cpup_attr_all(struct inode *inode, int force);
++
++/* ---------------------------------------------------------------------- */
++
++/* cpup flags */
++#define AuCpup_DTIME 1 /* do dtime_store/revert */
++#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
++ for link(2) */
++#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
++#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
++#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len);
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++ struct dentry *dst_parent);
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ unsigned int flags);
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++ struct file *file);
++
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg),
++ void *arg);
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++/* keep timestamps when copyup */
++struct au_dtime {
++ struct dentry *dt_dentry;
++ struct path dt_h_path;
++ struct timespec dt_atime, dt_mtime;
++};
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++ struct path *h_path);
++void au_dtime_revert(struct au_dtime *dt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_CPUP_H__ */
+diff -Naur a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
+--- a/fs/aufs/dbgaufs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,313 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debugfs interface
++ */
++
++#include <linux/debugfs.h>
++#include "aufs.h"
++
++#ifndef CONFIG_SYSFS
++#error DEBUG_FS depends upon SYSFS
++#endif
++
++static struct dentry *dbgaufs;
++static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
++
++/* 20 is max digits length of ulong 64 */
++struct dbgaufs_arg {
++ int n;
++ char a[20 * 4];
++};
++
++/*
++ * common function for all XINO files
++ */
++static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ kfree(file->private_data);
++ return 0;
++}
++
++static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
++{
++ int err;
++ struct kstat st;
++ struct dbgaufs_arg *p;
++
++ err = -ENOMEM;
++ p = kmalloc(sizeof(*p), GFP_NOFS);
++ if (unlikely(!p))
++ goto out;
++
++ err = 0;
++ p->n = 0;
++ file->private_data = p;
++ if (!xf)
++ goto out;
++
++ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
++ if (!err) {
++ if (do_fcnt)
++ p->n = snprintf
++ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
++ (long)file_count(xf), st.blocks, st.blksize,
++ (long long)st.size);
++ else
++ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
++ st.blocks, st.blksize,
++ (long long)st.size);
++ AuDebugOn(p->n >= sizeof(p->a));
++ } else {
++ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
++ err = 0;
++ }
++
++ out:
++ return err;
++
++}
++
++static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct dbgaufs_arg *p;
++
++ p = file->private_data;
++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int dbgaufs_xib_open(struct inode *inode, struct file *file)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
++ si_read_unlock(sb);
++ return err;
++}
++
++static const struct file_operations dbgaufs_xib_fop = {
++ .open = dbgaufs_xib_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define DbgaufsXi_PREFIX "xi"
++
++static int dbgaufs_xino_open(struct inode *inode, struct file *file)
++{
++ int err;
++ long l;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++ struct file *xf;
++ struct qstr *name;
++
++ err = -ENOENT;
++ xf = NULL;
++ name = &file->f_dentry->d_name;
++ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
++ || memcmp(name->name, DbgaufsXi_PREFIX,
++ sizeof(DbgaufsXi_PREFIX) - 1)))
++ goto out;
++ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
++ if (unlikely(err))
++ goto out;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ if (l <= au_sbend(sb)) {
++ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
++ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
++ } else
++ err = -ENOENT;
++ si_read_unlock(sb);
++
++ out:
++ return err;
++}
++
++static const struct file_operations dbgaufs_xino_fop = {
++ .open = dbgaufs_xino_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ aufs_bindex_t bend;
++ struct au_branch *br;
++ struct au_xino_file *xi;
++
++ if (!au_sbi(sb)->si_dbgaufs)
++ return;
++
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ xi = &br->br_xino;
++ if (xi->xi_dbgaufs) {
++ debugfs_remove(xi->xi_dbgaufs);
++ xi->xi_dbgaufs = NULL;
++ }
++ }
++}
++
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ struct au_sbinfo *sbinfo;
++ struct dentry *parent;
++ struct au_branch *br;
++ struct au_xino_file *xi;
++ aufs_bindex_t bend;
++ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
++
++ sbinfo = au_sbi(sb);
++ parent = sbinfo->si_dbgaufs;
++ if (!parent)
++ return;
++
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
++ br = au_sbr(sb, bindex);
++ xi = &br->br_xino;
++ AuDebugOn(xi->xi_dbgaufs);
++ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
++ sbinfo, &dbgaufs_xino_fop);
++ /* ignore an error */
++ if (unlikely(!xi->xi_dbgaufs))
++ AuWarn1("failed %s under debugfs\n", name);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = inode->i_private;
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
++ si_read_unlock(sb);
++ return err;
++}
++
++static const struct file_operations dbgaufs_xigen_fop = {
++ .open = dbgaufs_xigen_open,
++ .release = dbgaufs_xi_release,
++ .read = dbgaufs_xi_read
++};
++
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++
++ err = -EIO;
++ sbinfo->si_dbgaufs_xigen = debugfs_create_file
++ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++ &dbgaufs_xigen_fop);
++ if (sbinfo->si_dbgaufs_xigen)
++ err = 0;
++
++ return err;
++}
++#else
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++ return 0;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++ debugfs_remove_recursive(sbinfo->si_dbgaufs);
++ sbinfo->si_dbgaufs = NULL;
++ kobject_put(&sbinfo->si_kobj);
++}
++
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++ char name[SysaufsSiNameLen];
++
++ err = -ENOENT;
++ if (!dbgaufs) {
++ AuErr1("/debug/aufs is uninitialized\n");
++ goto out;
++ }
++
++ err = -EIO;
++ sysaufs_name(sbinfo, name);
++ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
++ if (unlikely(!sbinfo->si_dbgaufs))
++ goto out;
++ kobject_get(&sbinfo->si_kobj);
++
++ sbinfo->si_dbgaufs_xib = debugfs_create_file
++ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++ &dbgaufs_xib_fop);
++ if (unlikely(!sbinfo->si_dbgaufs_xib))
++ goto out_dir;
++
++ err = dbgaufs_xigen_init(sbinfo);
++ if (!err)
++ goto out; /* success */
++
++ out_dir:
++ dbgaufs_si_fin(sbinfo);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_fin(void)
++{
++ debugfs_remove(dbgaufs);
++}
++
++int __init dbgaufs_init(void)
++{
++ int err;
++
++ err = -EIO;
++ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
++ if (dbgaufs)
++ err = 0;
++ return err;
++}
+diff -Naur a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
+--- a/fs/aufs/dbgaufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debugfs interface
++ */
++
++#ifndef __DBGAUFS_H__
++#define __DBGAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/init.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++struct au_sbinfo;
++
++#ifdef CONFIG_DEBUG_FS
++/* dbgaufs.c */
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
++int dbgaufs_si_init(struct au_sbinfo *sbinfo);
++void dbgaufs_fin(void);
++int __init dbgaufs_init(void);
++
++#else
++
++static inline
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* empty */
++}
++
++static inline
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* empty */
++}
++
++static inline
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++ /* empty */
++}
++
++static inline
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ return 0;
++}
++
++#define dbgaufs_fin() do {} while (0)
++
++static inline
++int __init dbgaufs_init(void)
++{
++ return 0;
++}
++#endif /* CONFIG_DEBUG_FS */
++
++#endif /* __KERNEL__ */
++#endif /* __DBGAUFS_H__ */
+diff -Naur a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
+--- a/fs/aufs/dcsub.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,223 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#include "aufs.h"
++
++static void au_dpage_free(struct au_dpage *dpage)
++{
++ int i;
++ struct dentry **p;
++
++ p = dpage->dentries;
++ for (i = 0; i < dpage->ndentry; i++)
++ dput(*p++);
++ free_page((unsigned long)dpage->dentries);
++}
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
++{
++ int err;
++ void *p;
++
++ err = -ENOMEM;
++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
++ if (unlikely(!dpages->dpages))
++ goto out;
++
++ p = (void *)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out_dpages;
++
++ dpages->dpages[0].ndentry = 0;
++ dpages->dpages[0].dentries = p;
++ dpages->ndpage = 1;
++ return 0; /* success */
++
++ out_dpages:
++ kfree(dpages->dpages);
++ out:
++ return err;
++}
++
++void au_dpages_free(struct au_dcsub_pages *dpages)
++{
++ int i;
++ struct au_dpage *p;
++
++ p = dpages->dpages;
++ for (i = 0; i < dpages->ndpage; i++)
++ au_dpage_free(p++);
++ kfree(dpages->dpages);
++}
++
++static int au_dpages_append(struct au_dcsub_pages *dpages,
++ struct dentry *dentry, gfp_t gfp)
++{
++ int err, sz;
++ struct au_dpage *dpage;
++ void *p;
++
++ dpage = dpages->dpages + dpages->ndpage - 1;
++ sz = PAGE_SIZE / sizeof(dentry);
++ if (unlikely(dpage->ndentry >= sz)) {
++ AuLabel(new dpage);
++ err = -ENOMEM;
++ sz = dpages->ndpage * sizeof(*dpages->dpages);
++ p = au_kzrealloc(dpages->dpages, sz,
++ sz + sizeof(*dpages->dpages), gfp);
++ if (unlikely(!p))
++ goto out;
++
++ dpages->dpages = p;
++ dpage = dpages->dpages + dpages->ndpage;
++ p = (void *)__get_free_page(gfp);
++ if (unlikely(!p))
++ goto out;
++
++ dpage->ndentry = 0;
++ dpage->dentries = p;
++ dpages->ndpage++;
++ }
++
++ dpage->dentries[dpage->ndentry++] = dget(dentry);
++ return 0; /* success */
++
++ out:
++ return err;
++}
++
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg)
++{
++ int err;
++ struct dentry *this_parent = root;
++ struct list_head *next;
++ struct super_block *sb = root->d_sb;
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ repeat:
++ next = this_parent->d_subdirs.next;
++ resume:
++ if (this_parent->d_sb == sb
++ && !IS_ROOT(this_parent)
++ && atomic_read(&this_parent->d_count)
++ && this_parent->d_inode
++ && (!test || test(this_parent, arg))) {
++ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++
++ while (next != &this_parent->d_subdirs) {
++ struct list_head *tmp = next;
++ struct dentry *dentry = list_entry(tmp, struct dentry,
++ d_u.d_child);
++ next = tmp->next;
++ if (/*d_unhashed(dentry) || */!dentry->d_inode)
++ continue;
++ if (!list_empty(&dentry->d_subdirs)) {
++ this_parent = dentry;
++ goto repeat;
++ }
++ if (dentry->d_sb == sb
++ && atomic_read(&dentry->d_count)
++ && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ }
++
++ if (this_parent != root) {
++ next = this_parent->d_u.d_child.next;
++ this_parent = this_parent->d_parent; /* dcache_lock is locked */
++ goto resume;
++ }
++ out:
++ spin_unlock(&dcache_lock);
++ return err;
++}
++
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++ int do_include, au_dpages_test test, void *arg)
++{
++ int err;
++
++ err = 0;
++ spin_lock(&dcache_lock);
++ if (do_include && (!test || test(dentry, arg))) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ goto out;
++ }
++ while (!IS_ROOT(dentry)) {
++ dentry = dentry->d_parent; /* dcache_lock is locked */
++ if (!test || test(dentry, arg)) {
++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++ if (unlikely(err))
++ break;
++ }
++ }
++
++ out:
++ spin_unlock(&dcache_lock);
++
++ return err;
++}
++
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
++{
++ struct dentry *trap, **dentries;
++ int err, i, j;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++
++ trap = ERR_PTR(-ENOMEM);
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ trap = d1;
++ for (i = 0; !err && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ for (j = 0; !err && j < dpage->ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ err = (d == d2);
++ if (!err)
++ trap = d;
++ }
++ }
++ if (!err)
++ trap = NULL;
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return trap;
++}
+diff -Naur a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
+--- a/fs/aufs/dcsub.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#ifndef __AUFS_DCSUB_H__
++#define __AUFS_DCSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++
++struct dentry;
++
++struct au_dpage {
++ int ndentry;
++ struct dentry **dentries;
++};
++
++struct au_dcsub_pages {
++ int ndpage;
++ struct au_dpage *dpages;
++};
++
++/* ---------------------------------------------------------------------- */
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
++void au_dpages_free(struct au_dcsub_pages *dpages);
++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg);
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++ int do_include, au_dpages_test test, void *arg);
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DCSUB_H__ */
+diff -Naur a/fs/aufs/debug.c b/fs/aufs/debug.c
+--- a/fs/aufs/debug.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,427 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debug print functions
++ */
++
++#include <linux/module.h>
++#include <linux/vt_kern.h>
++#include "aufs.h"
++
++int aufs_debug;
++MODULE_PARM_DESC(debug, "debug print");
++module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
++
++char *au_plevel = KERN_DEBUG;
++#define dpri(fmt, arg...) do { \
++ if (au_debug_test()) \
++ printk("%s" fmt, au_plevel, ##arg); \
++} while (0)
++
++/* ---------------------------------------------------------------------- */
++
++void au_dpri_whlist(struct au_nhash *whlist)
++{
++ unsigned long ul, n;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (ul = 0; ul < n; ul++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ dpri("b%d, %.*s, %d\n",
++ tpos->wh_bindex,
++ tpos->wh_str.len, tpos->wh_str.name,
++ tpos->wh_str.len);
++ head++;
++ }
++}
++
++void au_dpri_vdir(struct au_vdir *vdir)
++{
++ unsigned long ul;
++ union au_vdir_deblk_p p;
++ unsigned char *o;
++
++ if (!vdir || IS_ERR(vdir)) {
++ dpri("err %ld\n", PTR_ERR(vdir));
++ return;
++ }
++
++ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
++ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
++ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
++ for (ul = 0; ul < vdir->vd_nblk; ul++) {
++ p.deblk = vdir->vd_deblk[ul];
++ o = p.deblk;
++ dpri("[%lu]: %p\n", ul, o);
++ }
++}
++
++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
++ struct dentry *wh)
++{
++ char *n = NULL;
++ int l = 0;
++
++ if (!inode || IS_ERR(inode)) {
++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
++ return -1;
++ }
++
++ /* the type of i_blocks depends upon CONFIG_LSF */
++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
++ && sizeof(inode->i_blocks) != sizeof(u64));
++ if (wh) {
++ n = (void *)wh->d_name.name;
++ l = wh->d_name.len;
++ }
++
++ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
++ " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
++ bindex,
++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
++ i_size_read(inode), (unsigned long long)inode->i_blocks,
++ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
++ inode->i_mapping ? inode->i_mapping->nrpages : 0,
++ inode->i_state, inode->i_flags, inode->i_generation,
++ l ? ", wh " : "", l, n);
++ return 0;
++}
++
++void au_dpri_inode(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_inode(-1, inode, NULL);
++ if (err || !au_test_aufs(inode->i_sb))
++ return;
++
++ iinfo = au_ii(inode);
++ if (!iinfo)
++ return;
++ dpri("i-1: bstart %d, bend %d, gen %d\n",
++ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
++ if (iinfo->ii_bstart < 0)
++ return;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
++ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
++ iinfo->ii_hinode[0 + bindex].hi_whdentry);
++}
++
++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
++{
++ struct dentry *wh = NULL;
++
++ if (!dentry || IS_ERR(dentry)) {
++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
++ return -1;
++ }
++ /* do not call dget_parent() here */
++ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
++ bindex,
++ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
++ atomic_read(&dentry->d_count), dentry->d_flags);
++ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
++ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
++ if (iinfo)
++ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
++ }
++ do_pri_inode(bindex, dentry->d_inode, wh);
++ return 0;
++}
++
++void au_dpri_dentry(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_dentry(-1, dentry);
++ if (err || !au_test_aufs(dentry->d_sb))
++ return;
++
++ dinfo = au_di(dentry);
++ if (!dinfo)
++ return;
++ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
++ dinfo->di_bstart, dinfo->di_bend,
++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
++ if (dinfo->di_bstart < 0)
++ return;
++ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
++ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
++}
++
++static int do_pri_file(aufs_bindex_t bindex, struct file *file)
++{
++ char a[32];
++
++ if (!file || IS_ERR(file)) {
++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
++ return -1;
++ }
++ a[0] = 0;
++ if (bindex < 0
++ && file->f_dentry
++ && au_test_aufs(file->f_dentry->d_sb)
++ && au_fi(file))
++ snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
++ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
++ bindex, file->f_mode, file->f_flags, (long)file_count(file),
++ file->f_pos, a);
++ if (file->f_dentry)
++ do_pri_dentry(bindex, file->f_dentry);
++ return 0;
++}
++
++void au_dpri_file(struct file *file)
++{
++ struct au_finfo *finfo;
++ aufs_bindex_t bindex;
++ int err;
++
++ err = do_pri_file(-1, file);
++ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
++ return;
++
++ finfo = au_fi(file);
++ if (!finfo)
++ return;
++ if (finfo->fi_bstart < 0)
++ return;
++ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
++ struct au_hfile *hf;
++
++ hf = finfo->fi_hfile + bindex;
++ do_pri_file(bindex, hf ? hf->hf_file : NULL);
++ }
++}
++
++static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
++{
++ struct vfsmount *mnt;
++ struct super_block *sb;
++
++ if (!br || IS_ERR(br))
++ goto out;
++ mnt = br->br_mnt;
++ if (!mnt || IS_ERR(mnt))
++ goto out;
++ sb = mnt->mnt_sb;
++ if (!sb || IS_ERR(sb))
++ goto out;
++
++ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
++ "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
++ "xino %d\n",
++ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
++ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
++ sb->s_flags, sb->s_count - S_BIAS,
++ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
++ return 0;
++
++ out:
++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
++ return -1;
++}
++
++void au_dpri_sb(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ aufs_bindex_t bindex;
++ int err;
++ /* to reuduce stack size */
++ struct {
++ struct vfsmount mnt;
++ struct au_branch fake;
++ } *a;
++
++ /* this function can be called from magic sysrq */
++ a = kzalloc(sizeof(*a), GFP_ATOMIC);
++ if (unlikely(!a)) {
++ dpri("no memory\n");
++ return;
++ }
++
++ a->mnt.mnt_sb = sb;
++ a->fake.br_perm = 0;
++ a->fake.br_mnt = &a->mnt;
++ a->fake.br_xino.xi_file = NULL;
++ atomic_set(&a->fake.br_count, 0);
++ smp_mb(); /* atomic_set */
++ err = do_pri_br(-1, &a->fake);
++ kfree(a);
++ dpri("dev 0x%x\n", sb->s_dev);
++ if (err || !au_test_aufs(sb))
++ return;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++ dpri("nw %d, gen %u, kobj %d\n",
++ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
++ atomic_read(&sbinfo->si_kobj.kref.refcount));
++ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_sleep_jiffy(int jiffy)
++{
++ while (jiffy)
++ jiffy = schedule_timeout_uninterruptible(jiffy);
++}
++
++void au_dbg_iattr(struct iattr *ia)
++{
++#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
++ dpri(#name "\n")
++ AuBit(MODE);
++ AuBit(UID);
++ AuBit(GID);
++ AuBit(SIZE);
++ AuBit(ATIME);
++ AuBit(MTIME);
++ AuBit(CTIME);
++ AuBit(ATIME_SET);
++ AuBit(MTIME_SET);
++ AuBit(FORCE);
++ AuBit(ATTR_FLAG);
++ AuBit(KILL_SUID);
++ AuBit(KILL_SGID);
++ AuBit(FILE);
++ AuBit(KILL_PRIV);
++ AuBit(OPEN);
++ AuBit(TIMES_SET);
++#undef AuBit
++ dpri("ia_file %p\n", ia->ia_file);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
++{
++ struct dentry *parent;
++
++ parent = dget_parent(dentry);
++ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
++ || IS_ROOT(dentry)
++ || au_digen(parent) != sigen);
++ dput(parent);
++}
++
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
++{
++ struct dentry *parent;
++
++ parent = dget_parent(dentry);
++ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
++ || au_digen(parent) != sigen);
++ dput(parent);
++}
++
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++ int err, i, j;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ AuDebugOn(err);
++ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
++ AuDebugOn(err);
++ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
++ AuDebugOn(au_digen(dentries[j]) != sigen);
++ }
++ au_dpages_free(&dpages);
++}
++
++void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++ struct au_hfile *hf;
++ aufs_bindex_t bend, bindex;
++
++ if (finfo->fi_bstart >= 0) {
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
++ hf = finfo->fi_hfile + bindex;
++ AuDebugOn(hf->hf_file || hf->hf_br);
++ }
++ }
++}
++
++void au_dbg_verify_kthread(void)
++{
++ if (au_test_wkq(current)) {
++ au_dbg_blocked();
++ BUG();
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
++{
++#ifdef AuForceNoPlink
++ au_opt_clr(sbinfo->si_mntflags, PLINK);
++#endif
++#ifdef AuForceNoXino
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++#endif
++#ifdef AuForceNoRefrof
++ au_opt_clr(sbinfo->si_mntflags, REFROF);
++#endif
++#ifdef AuForceHinotify
++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
++#endif
++}
++
++int __init au_debug_init(void)
++{
++ aufs_bindex_t bindex;
++ struct au_vdir_destr destr;
++
++ bindex = -1;
++ AuDebugOn(bindex >= 0);
++
++ destr.len = -1;
++ AuDebugOn(destr.len < NAME_MAX);
++
++#ifdef CONFIG_4KSTACKS
++ AuWarn("CONFIG_4KSTACKS is defined.\n");
++#endif
++
++#ifdef AuForceNoBrs
++ sysaufs_brs = 0;
++#endif
++
++ return 0;
++}
+diff -Naur a/fs/aufs/debug.h b/fs/aufs/debug.h
+--- a/fs/aufs/debug.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,260 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * debug print functions
++ */
++
++#ifndef __AUFS_DEBUG_H__
++#define __AUFS_DEBUG_H__
++
++#ifdef __KERNEL__
++
++#include <linux/bug.h>
++/* #include <linux/err.h> */
++/* #include <linux/init.h> */
++/* #include <linux/kernel.h> */
++#include <linux/delay.h>
++/* #include <linux/kd.h> */
++/* #include <linux/vt_kern.h> */
++#include <linux/sysrq.h>
++#include <linux/aufs_type.h>
++
++#ifdef CONFIG_AUFS_DEBUG
++#define AuDebugOn(a) BUG_ON(a)
++
++/* module parameter */
++extern int aufs_debug;
++static inline void au_debug(int n)
++{
++ aufs_debug = n;
++ smp_mb();
++}
++
++static inline int au_debug_test(void)
++{
++ return aufs_debug;
++}
++#else
++#define AuDebugOn(a) do {} while (0)
++#define au_debug() do {} while (0)
++static inline int au_debug_test(void)
++{
++ return 0;
++}
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++/* debug print */
++
++#define AuDpri(lvl, fmt, arg...) \
++ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
++ __func__, __LINE__, current->comm, current->pid, ##arg)
++#define AuDbg(fmt, arg...) do { \
++ if (au_debug_test()) \
++ AuDpri(KERN_DEBUG, fmt, ##arg); \
++} while (0)
++#define AuLabel(l) AuDbg(#l "\n")
++#define AuInfo(fmt, arg...) AuDpri(KERN_INFO, fmt, ##arg)
++#define AuWarn(fmt, arg...) AuDpri(KERN_WARNING, fmt, ##arg)
++#define AuErr(fmt, arg...) AuDpri(KERN_ERR, fmt, ##arg)
++#define AuIOErr(fmt, arg...) AuErr("I/O Error, " fmt, ##arg)
++#define AuWarn1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuWarn(fmt, ##arg); \
++} while (0)
++
++#define AuErr1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuErr(fmt, ##arg); \
++} while (0)
++
++#define AuIOErr1(fmt, arg...) do { \
++ static unsigned char _c; \
++ if (!_c++) \
++ AuIOErr(fmt, ##arg); \
++} while (0)
++
++#define AuUnsupportMsg "This operation is not supported." \
++ " Please report this application to aufs-users ML."
++#define AuUnsupport(fmt, args...) do { \
++ AuErr(AuUnsupportMsg "\n" fmt, ##args); \
++ dump_stack(); \
++} while (0)
++
++#define AuTraceErr(e) do { \
++ if (unlikely((e) < 0)) \
++ AuDbg("err %d\n", (int)(e)); \
++} while (0)
++
++#define AuTraceErrPtr(p) do { \
++ if (IS_ERR(p)) \
++ AuDbg("err %ld\n", PTR_ERR(p)); \
++} while (0)
++
++/* dirty macros for debug print, use with "%.*s" and caution */
++#define AuLNPair(qstr) (qstr)->len, (qstr)->name
++#define AuDLNPair(d) AuLNPair(&(d)->d_name)
++
++/* ---------------------------------------------------------------------- */
++
++struct au_sbinfo;
++struct au_finfo;
++struct dentry;
++#ifdef CONFIG_AUFS_DEBUG
++extern char *au_plevel;
++struct au_nhash;
++void au_dpri_whlist(struct au_nhash *whlist);
++struct au_vdir;
++void au_dpri_vdir(struct au_vdir *vdir);
++struct inode;
++void au_dpri_inode(struct inode *inode);
++void au_dpri_dentry(struct dentry *dentry);
++struct file;
++void au_dpri_file(struct file *filp);
++struct super_block;
++void au_dpri_sb(struct super_block *sb);
++
++void au_dbg_sleep_jiffy(int jiffy);
++struct iattr;
++void au_dbg_iattr(struct iattr *ia);
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
++void au_dbg_verify_hf(struct au_finfo *finfo);
++void au_dbg_verify_kthread(void);
++
++int __init au_debug_init(void);
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
++#define AuDbgWhlist(w) do { \
++ AuDbg(#w "\n"); \
++ au_dpri_whlist(w); \
++} while (0)
++
++#define AuDbgVdir(v) do { \
++ AuDbg(#v "\n"); \
++ au_dpri_vdir(v); \
++} while (0)
++
++#define AuDbgInode(i) do { \
++ AuDbg(#i "\n"); \
++ au_dpri_inode(i); \
++} while (0)
++
++#define AuDbgDentry(d) do { \
++ AuDbg(#d "\n"); \
++ au_dpri_dentry(d); \
++} while (0)
++
++#define AuDbgFile(f) do { \
++ AuDbg(#f "\n"); \
++ au_dpri_file(f); \
++} while (0)
++
++#define AuDbgSb(sb) do { \
++ AuDbg(#sb "\n"); \
++ au_dpri_sb(sb); \
++} while (0)
++
++#define AuDbgSleep(sec) do { \
++ AuDbg("sleep %d sec\n", sec); \
++ ssleep(sec); \
++} while (0)
++
++#define AuDbgSleepJiffy(jiffy) do { \
++ AuDbg("sleep %d jiffies\n", jiffy); \
++ au_dbg_sleep_jiffy(jiffy); \
++} while (0)
++
++#define AuDbgIAttr(ia) do { \
++ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
++ au_dbg_iattr(ia); \
++} while (0)
++#else
++static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
++ unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
++ unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++ /* empty */
++}
++static inline void au_dbg_verify_kthread(void)
++{
++ /* empty */
++}
++
++static inline int au_debug_init(void)
++{
++ return 0;
++}
++static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
++{
++ /* empty */
++}
++#define AuDbgWhlist(w) do {} while (0)
++#define AuDbgVdir(v) do {} while (0)
++#define AuDbgInode(i) do {} while (0)
++#define AuDbgDentry(d) do {} while (0)
++#define AuDbgFile(f) do {} while (0)
++#define AuDbgSb(sb) do {} while (0)
++#define AuDbgSleep(sec) do {} while (0)
++#define AuDbgSleepJiffy(jiffy) do {} while (0)
++#define AuDbgIAttr(ia) do {} while (0)
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_MAGIC_SYSRQ
++int __init au_sysrq_init(void);
++void au_sysrq_fin(void);
++
++#ifdef CONFIG_HW_CONSOLE
++#define au_dbg_blocked() do { \
++ WARN_ON(1); \
++ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
++} while (0)
++#else
++#define au_dbg_blocked() do {} while (0)
++#endif
++
++#else
++static inline int au_sysrq_init(void)
++{
++ return 0;
++}
++#define au_sysrq_fin() do {} while (0)
++#define au_dbg_blocked() do {} while (0)
++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DEBUG_H__ */
+diff -Naur a/fs/aufs/dentry.c b/fs/aufs/dentry.c
+--- a/fs/aufs/dentry.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#include <linux/namei.h>
++#include "aufs.h"
++
++static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
++{
++ if (nd) {
++ *h_nd = *nd;
++
++ /*
++ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
++ * due to whiteout and branch permission.
++ */
++ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
++ | LOOKUP_FOLLOW);
++ /* unnecessary? */
++ h_nd->intent.open.file = NULL;
++ } else
++ memset(h_nd, 0, sizeof(*h_nd));
++}
++
++struct au_lkup_one_args {
++ struct dentry **errp;
++ struct qstr *name;
++ struct dentry *h_parent;
++ struct au_branch *br;
++ struct nameidata *nd;
++};
++
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++ struct au_branch *br, struct nameidata *nd)
++{
++ struct dentry *h_dentry;
++ int err;
++ struct nameidata h_nd;
++
++ if (au_test_fs_null_nd(h_parent->d_sb))
++ return vfsub_lookup_one_len(name->name, h_parent, name->len);
++
++ au_h_nd(&h_nd, nd);
++ h_nd.path.dentry = h_parent;
++ h_nd.path.mnt = br->br_mnt;
++
++ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
++ h_dentry = ERR_PTR(err);
++ if (!err) {
++ path_get(&h_nd.path);
++ h_dentry = vfsub_lookup_hash(&h_nd);
++ path_put(&h_nd.path);
++ }
++
++ return h_dentry;
++}
++
++static void au_call_lkup_one(void *args)
++{
++ struct au_lkup_one_args *a = args;
++ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
++}
++
++#define AuLkup_ALLOW_NEG 1
++#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
++#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
++#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
++
++struct au_do_lookup_args {
++ unsigned int flags;
++ mode_t type;
++ struct nameidata *nd;
++};
++
++/*
++ * returns positive/negative dentry, NULL or an error.
++ * NULL means whiteout-ed or not-found.
++ */
++static struct dentry*
++au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
++ aufs_bindex_t bindex, struct qstr *wh_name,
++ struct au_do_lookup_args *args)
++{
++ struct dentry *h_dentry;
++ struct inode *h_inode, *inode;
++ struct qstr *name;
++ struct au_branch *br;
++ int wh_found, opq;
++ unsigned char wh_able;
++ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
++
++ name = &dentry->d_name;
++ wh_found = 0;
++ br = au_sbr(dentry->d_sb, bindex);
++ wh_able = !!au_br_whable(br->br_perm);
++ if (wh_able)
++ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
++ h_dentry = ERR_PTR(wh_found);
++ if (!wh_found)
++ goto real_lookup;
++ if (unlikely(wh_found < 0))
++ goto out;
++
++ /* We found a whiteout */
++ /* au_set_dbend(dentry, bindex); */
++ au_set_dbwh(dentry, bindex);
++ if (!allow_neg)
++ return NULL; /* success */
++
++ real_lookup:
++ h_dentry = au_lkup_one(name, h_parent, br, args->nd);
++ if (IS_ERR(h_dentry))
++ goto out;
++
++ h_inode = h_dentry->d_inode;
++ if (!h_inode) {
++ if (!allow_neg)
++ goto out_neg;
++ } else if (wh_found
++ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
++ goto out_neg;
++
++ if (au_dbend(dentry) <= bindex)
++ au_set_dbend(dentry, bindex);
++ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++ au_set_dbstart(dentry, bindex);
++ au_set_h_dptr(dentry, bindex, h_dentry);
++
++ inode = dentry->d_inode;
++ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
++ || (inode && !S_ISDIR(inode->i_mode)))
++ goto out; /* success */
++
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ opq = au_diropq_test(h_dentry, br);
++ mutex_unlock(&h_inode->i_mutex);
++ if (opq > 0)
++ au_set_dbdiropq(dentry, bindex);
++ else if (unlikely(opq < 0)) {
++ au_set_h_dptr(dentry, bindex, NULL);
++ h_dentry = ERR_PTR(opq);
++ }
++ goto out;
++
++ out_neg:
++ dput(h_dentry);
++ h_dentry = NULL;
++ out:
++ return h_dentry;
++}
++
++static int au_test_shwh(struct super_block *sb, const struct qstr *name)
++{
++ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
++ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++ return -EPERM;
++ return 0;
++}
++
++/*
++ * returns the number of lower positive dentries,
++ * otherwise an error.
++ * can be called at unlinking with @type is zero.
++ */
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++ struct nameidata *nd)
++{
++ int npositive, err;
++ aufs_bindex_t bindex, btail, bdiropq;
++ unsigned char isdir;
++ struct qstr whname;
++ struct au_do_lookup_args args = {
++ .flags = 0,
++ .type = type,
++ .nd = nd
++ };
++ const struct qstr *name = &dentry->d_name;
++ struct dentry *parent;
++ struct inode *inode;
++
++ parent = dget_parent(dentry);
++ err = au_test_shwh(dentry->d_sb, name);
++ if (unlikely(err))
++ goto out;
++
++ err = au_wh_name_alloc(&whname, name);
++ if (unlikely(err))
++ goto out;
++
++ inode = dentry->d_inode;
++ isdir = !!(inode && S_ISDIR(inode->i_mode));
++ if (!type)
++ au_fset_lkup(args.flags, ALLOW_NEG);
++
++ npositive = 0;
++ btail = au_dbtaildir(parent);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ struct dentry *h_parent, *h_dentry;
++ struct inode *h_inode, *h_dir;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry) {
++ if (h_dentry->d_inode)
++ npositive++;
++ if (type != S_IFDIR)
++ break;
++ continue;
++ }
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent)
++ continue;
++ h_dir = h_parent->d_inode;
++ if (!h_dir || !S_ISDIR(h_dir->i_mode))
++ continue;
++
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
++ &args);
++ mutex_unlock(&h_dir->i_mutex);
++ err = PTR_ERR(h_dentry);
++ if (IS_ERR(h_dentry))
++ goto out_wh;
++ au_fclr_lkup(args.flags, ALLOW_NEG);
++
++ if (au_dbwh(dentry) >= 0)
++ break;
++ if (!h_dentry)
++ continue;
++ h_inode = h_dentry->d_inode;
++ if (!h_inode)
++ continue;
++ npositive++;
++ if (!args.type)
++ args.type = h_inode->i_mode & S_IFMT;
++ if (args.type != S_IFDIR)
++ break;
++ else if (isdir) {
++ /* the type of lower may be different */
++ bdiropq = au_dbdiropq(dentry);
++ if (bdiropq >= 0 && bdiropq <= bindex)
++ break;
++ }
++ }
++
++ if (npositive) {
++ AuLabel(positive);
++ au_update_dbstart(dentry);
++ }
++ err = npositive;
++ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++ && au_dbstart(dentry) < 0))
++ /* both of real entry and whiteout found */
++ err = -EIO;
++
++ out_wh:
++ kfree(whname.name);
++ out:
++ dput(parent);
++ return err;
++}
++
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++ struct au_branch *br)
++{
++ struct dentry *dentry;
++ int wkq_err;
++
++ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
++ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
++ else {
++ struct au_lkup_one_args args = {
++ .errp = &dentry,
++ .name = name,
++ .h_parent = parent,
++ .br = br,
++ .nd = NULL
++ };
++
++ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
++ if (unlikely(wkq_err))
++ dentry = ERR_PTR(wkq_err);
++ }
++
++ return dentry;
++}
++
++/*
++ * lookup @dentry on @bindex which should be negative.
++ */
++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err;
++ struct dentry *parent, *h_parent, *h_dentry;
++ struct qstr *name;
++
++ name = &dentry->d_name;
++ parent = dget_parent(dentry);
++ h_parent = au_h_dptr(parent, bindex);
++ h_dentry = au_sio_lkup_one(name, h_parent,
++ au_sbr(dentry->d_sb, bindex));
++ err = PTR_ERR(h_dentry);
++ if (IS_ERR(h_dentry))
++ goto out;
++ if (unlikely(h_dentry->d_inode)) {
++ err = -EIO;
++ AuIOErr("b%d %.*s should be negative.\n",
++ bindex, AuDLNPair(h_dentry));
++ dput(h_dentry);
++ goto out;
++ }
++
++ if (bindex < au_dbstart(dentry))
++ au_set_dbstart(dentry, bindex);
++ if (au_dbend(dentry) < bindex)
++ au_set_dbend(dentry, bindex);
++ au_set_h_dptr(dentry, bindex, h_dentry);
++ err = 0;
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* subset of struct inode */
++struct au_iattr {
++ unsigned long i_ino;
++ /* unsigned int i_nlink; */
++ uid_t i_uid;
++ gid_t i_gid;
++ u64 i_version;
++/*
++ loff_t i_size;
++ blkcnt_t i_blocks;
++*/
++ umode_t i_mode;
++};
++
++static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
++{
++ ia->i_ino = h_inode->i_ino;
++ /* ia->i_nlink = h_inode->i_nlink; */
++ ia->i_uid = h_inode->i_uid;
++ ia->i_gid = h_inode->i_gid;
++ ia->i_version = h_inode->i_version;
++/*
++ ia->i_size = h_inode->i_size;
++ ia->i_blocks = h_inode->i_blocks;
++*/
++ ia->i_mode = (h_inode->i_mode & S_IFMT);
++}
++
++static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
++{
++ return ia->i_ino != h_inode->i_ino
++ /* || ia->i_nlink != h_inode->i_nlink */
++ || ia->i_uid != h_inode->i_uid
++ || ia->i_gid != h_inode->i_gid
++ || ia->i_version != h_inode->i_version
++/*
++ || ia->i_size != h_inode->i_size
++ || ia->i_blocks != h_inode->i_blocks
++*/
++ || ia->i_mode != (h_inode->i_mode & S_IFMT);
++}
++
++static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
++ struct au_branch *br)
++{
++ int err;
++ struct au_iattr ia;
++ struct inode *h_inode;
++ struct dentry *h_d;
++ struct super_block *h_sb;
++
++ err = 0;
++ memset(&ia, -1, sizeof(ia));
++ h_sb = h_dentry->d_sb;
++ h_inode = h_dentry->d_inode;
++ if (h_inode)
++ au_iattr_save(&ia, h_inode);
++ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
++ /* nfs d_revalidate may return 0 for negative dentry */
++ /* fuse d_revalidate always return 0 for negative dentry */
++ goto out;
++
++ /* main purpose is namei.c:cached_lookup() and d_revalidate */
++ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
++ err = PTR_ERR(h_d);
++ if (IS_ERR(h_d))
++ goto out;
++
++ err = 0;
++ if (unlikely(h_d != h_dentry
++ || h_d->d_inode != h_inode
++ || (h_inode && au_iattr_test(&ia, h_inode))))
++ err = au_busy_or_stale();
++ dput(h_d);
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++ struct dentry *h_parent, struct au_branch *br)
++{
++ int err;
++
++ err = 0;
++ if (udba == AuOpt_UDBA_REVAL) {
++ IMustLock(h_dir);
++ err = (h_dentry->d_parent->d_inode != h_dir);
++ } else if (udba == AuOpt_UDBA_HINOTIFY)
++ err = au_h_verify_dentry(h_dentry, h_parent, br);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
++ struct dentry *parent)
++{
++ struct dentry *h_d, *h_dp;
++ struct au_hdentry tmp, *q;
++ struct super_block *sb;
++ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
++
++ bend = dinfo->di_bend;
++ bwh = dinfo->di_bwh;
++ bdiropq = dinfo->di_bdiropq;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
++ h_d = p->hd_dentry;
++ if (!h_d)
++ continue;
++
++ h_dp = dget_parent(h_d);
++ if (h_dp == au_h_dptr(parent, bindex)) {
++ dput(h_dp);
++ continue;
++ }
++
++ new_bindex = au_find_dbindex(parent, h_dp);
++ dput(h_dp);
++ if (dinfo->di_bwh == bindex)
++ bwh = new_bindex;
++ if (dinfo->di_bdiropq == bindex)
++ bdiropq = new_bindex;
++ if (new_bindex < 0) {
++ au_hdput(p);
++ p->hd_dentry = NULL;
++ continue;
++ }
++
++ /* swap two lower dentries, and loop again */
++ q = dinfo->di_hdentry + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hd_dentry) {
++ bindex--;
++ p--;
++ }
++ }
++
++ sb = parent->d_sb;
++ dinfo->di_bwh = -1;
++ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
++ dinfo->di_bwh = bwh;
++
++ dinfo->di_bdiropq = -1;
++ if (bdiropq >= 0
++ && bdiropq <= au_sbend(sb)
++ && au_sbr_whable(sb, bdiropq))
++ dinfo->di_bdiropq = bdiropq;
++
++ bend = au_dbend(parent);
++ p = dinfo->di_hdentry;
++ for (bindex = 0; bindex <= bend; bindex++, p++)
++ if (p->hd_dentry) {
++ dinfo->di_bstart = bindex;
++ break;
++ }
++
++ p = dinfo->di_hdentry + bend;
++ for (bindex = bend; bindex >= 0; bindex--, p--)
++ if (p->hd_dentry) {
++ dinfo->di_bend = bindex;
++ break;
++ }
++}
++
++/*
++ * returns the number of found lower positive dentries,
++ * otherwise an error.
++ */
++int au_refresh_hdentry(struct dentry *dentry, mode_t type)
++{
++ int npositive, err;
++ unsigned int sigen;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct super_block *sb;
++ struct dentry *parent;
++
++ sb = dentry->d_sb;
++ AuDebugOn(IS_ROOT(dentry));
++ sigen = au_sigen(sb);
++ parent = dget_parent(dentry);
++ AuDebugOn(au_digen(parent) != sigen
++ || au_iigen(parent->d_inode) != sigen);
++
++ dinfo = au_di(dentry);
++ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
++ npositive = err;
++ if (unlikely(err))
++ goto out;
++ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
++ parent);
++
++ npositive = 0;
++ bstart = au_dbstart(parent);
++ if (type != S_IFDIR && dinfo->di_bstart == bstart)
++ goto out_dgen; /* success */
++
++ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
++ if (npositive < 0)
++ goto out;
++ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
++ d_drop(dentry);
++
++ out_dgen:
++ au_update_digen(dentry);
++ out:
++ dput(parent);
++ AuTraceErr(npositive);
++ return npositive;
++}
++
++static noinline_for_stack
++int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
++ struct dentry *dentry, aufs_bindex_t bindex)
++{
++ int err, valid;
++ int (*reval)(struct dentry *, struct nameidata *);
++
++ err = 0;
++ reval = NULL;
++ if (h_dentry->d_op)
++ reval = h_dentry->d_op->d_revalidate;
++ if (!reval)
++ goto out;
++
++ AuDbg("b%d\n", bindex);
++ if (au_test_fs_null_nd(h_dentry->d_sb))
++ /* it may return tri-state */
++ valid = reval(h_dentry, NULL);
++ else {
++ struct nameidata h_nd;
++ int locked;
++ struct dentry *parent;
++
++ au_h_nd(&h_nd, nd);
++ parent = nd->path.dentry;
++ locked = (nd && nd->path.dentry != dentry);
++ if (locked)
++ di_read_lock_parent(parent, AuLock_IR);
++ BUG_ON(bindex > au_dbend(parent));
++ h_nd.path.dentry = au_h_dptr(parent, bindex);
++ BUG_ON(!h_nd.path.dentry);
++ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
++ path_get(&h_nd.path);
++ valid = reval(h_dentry, &h_nd);
++ path_put(&h_nd.path);
++ if (locked)
++ di_read_unlock(parent, AuLock_IR);
++ }
++
++ if (unlikely(valid < 0))
++ err = valid;
++ else if (!valid)
++ err = -EINVAL;
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++/* todo: remove this */
++static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
++ struct nameidata *nd, int do_udba)
++{
++ int err;
++ umode_t mode, h_mode;
++ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
++ unsigned char plus, unhashed, is_root, h_plus;
++ struct inode *first, *h_inode, *h_cached_inode;
++ struct dentry *h_dentry;
++ struct qstr *name, *h_name;
++
++ err = 0;
++ plus = 0;
++ mode = 0;
++ first = NULL;
++ ibs = -1;
++ ibe = -1;
++ unhashed = !!d_unhashed(dentry);
++ is_root = !!IS_ROOT(dentry);
++ name = &dentry->d_name;
++
++ /*
++ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
++ * But inotify doesn't fire some necessary events,
++ * IN_ATTRIB for atime/nlink/pageio
++ * IN_DELETE for NFS dentry
++ * Let's do REVAL test too.
++ */
++ if (do_udba && inode) {
++ mode = (inode->i_mode & S_IFMT);
++ plus = (inode->i_nlink > 0);
++ first = au_h_iptr(inode, au_ibstart(inode));
++ ibs = au_ibstart(inode);
++ ibe = au_ibend(inode);
++ }
++
++ bstart = au_dbstart(dentry);
++ btail = bstart;
++ if (inode && S_ISDIR(inode->i_mode))
++ btail = au_dbtaildir(dentry);
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++
++ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
++ h_name = &h_dentry->d_name;
++ if (unlikely(do_udba
++ && !is_root
++ && (unhashed != !!d_unhashed(h_dentry)
++ || name->len != h_name->len
++ || memcmp(name->name, h_name->name, name->len))
++ )) {
++ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
++ unhashed, d_unhashed(h_dentry),
++ AuDLNPair(dentry), AuDLNPair(h_dentry));
++ goto err;
++ }
++
++ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
++ if (unlikely(err))
++ /* do not goto err, to keep the errno */
++ break;
++
++ /* todo: plink too? */
++ if (!do_udba)
++ continue;
++
++ /* UDBA tests */
++ h_inode = h_dentry->d_inode;
++ if (unlikely(!!inode != !!h_inode))
++ goto err;
++
++ h_plus = plus;
++ h_mode = mode;
++ h_cached_inode = h_inode;
++ if (h_inode) {
++ h_mode = (h_inode->i_mode & S_IFMT);
++ h_plus = (h_inode->i_nlink > 0);
++ }
++ if (inode && ibs <= bindex && bindex <= ibe)
++ h_cached_inode = au_h_iptr(inode, bindex);
++
++ if (unlikely(plus != h_plus
++ || mode != h_mode
++ || h_cached_inode != h_inode))
++ goto err;
++ continue;
++
++ err:
++ err = -EINVAL;
++ break;
++ }
++
++ return err;
++}
++
++static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct dentry *parent;
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++ return 0;
++
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++ AuDebugOn(au_digen(parent) != sigen
++ || au_iigen(parent->d_inode) != sigen);
++ au_dbg_verify_gen(parent, sigen);
++
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, dentry);
++
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ return err;
++}
++
++int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct dentry *d, *parent;
++ struct inode *inode;
++
++ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
++ return simple_reval_dpath(dentry, sigen);
++
++ /* slow loop, keep it simple and stupid */
++ /* cf: au_cpup_dirs() */
++ err = 0;
++ parent = NULL;
++ while (au_digen(dentry) != sigen
++ || au_iigen(dentry->d_inode) != sigen) {
++ d = dentry;
++ while (1) {
++ dput(parent);
++ parent = dget_parent(d);
++ if (au_digen(parent) == sigen
++ && au_iigen(parent->d_inode) == sigen)
++ break;
++ d = parent;
++ }
++
++ inode = d->d_inode;
++ if (d != dentry)
++ di_write_lock_child(d);
++
++ /* someone might update our dentry while we were sleeping */
++ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
++ di_read_lock_parent(parent, AuLock_IR);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
++ if (err >= 0)
++ err = au_refresh_hinode(inode, d);
++ di_read_unlock(parent, AuLock_IR);
++ }
++
++ if (d != dentry)
++ di_write_unlock(d);
++ dput(parent);
++ if (unlikely(err))
++ break;
++ }
++
++ return err;
++}
++
++/*
++ * if valid returns 1, otherwise 0.
++ */
++static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
++{
++ int valid, err;
++ unsigned int sigen;
++ unsigned char do_udba;
++ struct super_block *sb;
++ struct inode *inode;
++
++ err = -EINVAL;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
++ sigen = au_sigen(sb);
++ if (au_digen(dentry) != sigen) {
++ AuDebugOn(IS_ROOT(dentry));
++ if (inode)
++ err = au_reval_dpath(dentry, sigen);
++ if (unlikely(err))
++ goto out_dgrade;
++ AuDebugOn(au_digen(dentry) != sigen);
++ }
++ if (inode && au_iigen(inode) != sigen) {
++ AuDebugOn(IS_ROOT(dentry));
++ err = au_refresh_hinode(inode, dentry);
++ if (unlikely(err))
++ goto out_dgrade;
++ AuDebugOn(au_iigen(inode) != sigen);
++ }
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ AuDebugOn(au_digen(dentry) != sigen);
++ AuDebugOn(inode && au_iigen(inode) != sigen);
++ err = -EINVAL;
++ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
++ if (do_udba && inode) {
++ aufs_bindex_t bstart = au_ibstart(inode);
++
++ if (bstart >= 0
++ && au_test_higen(inode, au_h_iptr(inode, bstart)))
++ goto out;
++ }
++
++ err = h_d_revalidate(dentry, inode, nd, do_udba);
++ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
++ /* both of real entry and whiteout found */
++ err = -EIO;
++ goto out;
++
++ out_dgrade:
++ di_downgrade_lock(dentry, AuLock_IR);
++ out:
++ au_store_oflag(nd, inode);
++ aufs_read_unlock(dentry, AuLock_IR);
++ AuTraceErr(err);
++ valid = !err;
++ if (!valid)
++ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
++ return valid;
++}
++
++static void aufs_d_release(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ aufs_bindex_t bend, bindex;
++
++ dinfo = dentry->d_fsdata;
++ if (!dinfo)
++ return;
++
++ /* dentry may not be revalidated */
++ bindex = dinfo->di_bstart;
++ if (bindex >= 0) {
++ struct au_hdentry *p;
++
++ bend = dinfo->di_bend;
++ p = dinfo->di_hdentry + bindex;
++ while (bindex++ <= bend) {
++ if (p->hd_dentry)
++ au_hdput(p);
++ p++;
++ }
++ }
++ kfree(dinfo->di_hdentry);
++ au_rwsem_destroy(&dinfo->di_rwsem);
++ au_cache_free_dinfo(dinfo);
++ au_hin_di_reinit(dentry);
++}
++
++struct dentry_operations aufs_dop = {
++ .d_revalidate = aufs_d_revalidate,
++ .d_release = aufs_d_release
++};
+diff -Naur a/fs/aufs/dentry.h b/fs/aufs/dentry.h
+--- a/fs/aufs/dentry.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,221 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#ifndef __AUFS_DENTRY_H__
++#define __AUFS_DENTRY_H__
++
++#ifdef __KERNEL__
++
++#include <linux/dcache.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++/* make a single member structure for future use */
++/* todo: remove this structure */
++struct au_hdentry {
++ struct dentry *hd_dentry;
++};
++
++struct au_dinfo {
++ atomic_t di_generation;
++
++ struct rw_semaphore di_rwsem;
++ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
++ struct au_hdentry *di_hdentry;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry.c */
++extern struct dentry_operations aufs_dop;
++struct au_branch;
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++ struct au_branch *br, struct nameidata *nd);
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++ struct au_branch *br);
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++ struct dentry *h_parent, struct au_branch *br);
++
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++ struct nameidata *nd);
++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
++int au_refresh_hdentry(struct dentry *dentry, mode_t type);
++int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
++
++/* dinfo.c */
++int au_alloc_dinfo(struct dentry *dentry);
++int au_di_realloc(struct au_dinfo *dinfo, int nbr);
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
++void di_read_unlock(struct dentry *d, int flags);
++void di_downgrade_lock(struct dentry *d, int flags);
++void di_write_lock(struct dentry *d, unsigned int lsc);
++void di_write_unlock(struct dentry *d);
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
++void di_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
++aufs_bindex_t au_dbtail(struct dentry *dentry);
++aufs_bindex_t au_dbtaildir(struct dentry *dentry);
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++void au_update_digen(struct dentry *dentry);
++void au_update_dbrange(struct dentry *dentry, int do_put_zero);
++void au_update_dbstart(struct dentry *dentry);
++void au_update_dbend(struct dentry *dentry);
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_dinfo *au_di(struct dentry *dentry)
++{
++ return dentry->d_fsdata;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for dinfo */
++enum {
++ AuLsc_DI_CHILD, /* child first */
++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_DI_CHILD3, /* copyup dirs */
++ AuLsc_DI_PARENT,
++ AuLsc_DI_PARENT2,
++ AuLsc_DI_PARENT3
++};
++
++/*
++ * di_read_lock_child, di_write_lock_child,
++ * di_read_lock_child2, di_write_lock_child2,
++ * di_read_lock_child3, di_write_lock_child3,
++ * di_read_lock_parent, di_write_lock_parent,
++ * di_read_lock_parent2, di_write_lock_parent2,
++ * di_read_lock_parent3, di_write_lock_parent3,
++ */
++#define AuReadLockFunc(name, lsc) \
++static inline void di_read_lock_##name(struct dentry *d, int flags) \
++{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void di_write_lock_##name(struct dentry *d) \
++{ di_write_lock(d, AuLsc_DI_##lsc); }
++
++#define AuRWLockFuncs(name, lsc) \
++ AuReadLockFunc(name, lsc) \
++ AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: memory barrier? */
++static inline unsigned int au_digen(struct dentry *d)
++{
++ return atomic_read(&au_di(d)->di_generation);
++}
++
++static inline void au_h_dentry_init(struct au_hdentry *hdentry)
++{
++ hdentry->hd_dentry = NULL;
++}
++
++static inline void au_hdput(struct au_hdentry *hd)
++{
++ dput(hd->hd_dentry);
++}
++
++static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bstart;
++}
++
++static inline aufs_bindex_t au_dbend(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bend;
++}
++
++static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bwh;
++}
++
++static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
++{
++ return au_di(dentry)->di_bdiropq;
++}
++
++/* todo: hard/soft set? */
++static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bstart = bindex;
++}
++
++static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bend = bindex;
++}
++
++static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ /* dbwh can be outside of bstart - bend range */
++ au_di(dentry)->di_bwh = bindex;
++}
++
++static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ au_di(dentry)->di_bdiropq = bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_digen_dec(struct dentry *d)
++{
++ atomic_dec(&au_di(d)->di_generation);
++}
++
++static inline void au_hin_di_reinit(struct dentry *dentry)
++{
++ dentry->d_fsdata = NULL;
++}
++#else
++static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
++{
++ /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DENTRY_H__ */
+diff -Naur a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
+--- a/fs/aufs/dinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,360 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * dentry private data
++ */
++
++#include "aufs.h"
++
++int au_alloc_dinfo(struct dentry *dentry)
++{
++ struct au_dinfo *dinfo;
++ struct super_block *sb;
++ int nbr;
++
++ dinfo = au_cache_alloc_dinfo();
++ if (unlikely(!dinfo))
++ goto out;
++
++ sb = dentry->d_sb;
++ nbr = au_sbend(sb) + 1;
++ if (nbr <= 0)
++ nbr = 1;
++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
++ if (unlikely(!dinfo->di_hdentry))
++ goto out_dinfo;
++
++ atomic_set(&dinfo->di_generation, au_sigen(sb));
++ /* smp_mb(); */ /* atomic_set */
++ init_rwsem(&dinfo->di_rwsem);
++ down_write_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
++ dinfo->di_bstart = -1;
++ dinfo->di_bend = -1;
++ dinfo->di_bwh = -1;
++ dinfo->di_bdiropq = -1;
++
++ dentry->d_fsdata = dinfo;
++ dentry->d_op = &aufs_dop;
++ return 0; /* success */
++
++ out_dinfo:
++ au_cache_free_dinfo(dinfo);
++ out:
++ return -ENOMEM;
++}
++
++int au_di_realloc(struct au_dinfo *dinfo, int nbr)
++{
++ int err, sz;
++ struct au_hdentry *hdp;
++
++ err = -ENOMEM;
++ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
++ if (!sz)
++ sz = sizeof(*hdp);
++ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
++ if (hdp) {
++ dinfo->di_hdentry = hdp;
++ err = 0;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_write_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_write_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_write_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_write_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_write_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_write_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
++{
++ switch (lsc) {
++ case AuLsc_DI_CHILD:
++ ii_read_lock_child(inode);
++ break;
++ case AuLsc_DI_CHILD2:
++ ii_read_lock_child2(inode);
++ break;
++ case AuLsc_DI_CHILD3:
++ ii_read_lock_child3(inode);
++ break;
++ case AuLsc_DI_PARENT:
++ ii_read_lock_parent(inode);
++ break;
++ case AuLsc_DI_PARENT2:
++ ii_read_lock_parent2(inode);
++ break;
++ case AuLsc_DI_PARENT3:
++ ii_read_lock_parent3(inode);
++ break;
++ default:
++ BUG();
++ }
++}
++
++void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
++{
++ down_read_nested(&au_di(d)->di_rwsem, lsc);
++ if (d->d_inode) {
++ if (au_ftest_lock(flags, IW))
++ do_ii_write_lock(d->d_inode, lsc);
++ else if (au_ftest_lock(flags, IR))
++ do_ii_read_lock(d->d_inode, lsc);
++ }
++}
++
++void di_read_unlock(struct dentry *d, int flags)
++{
++ if (d->d_inode) {
++ if (au_ftest_lock(flags, IW))
++ ii_write_unlock(d->d_inode);
++ else if (au_ftest_lock(flags, IR))
++ ii_read_unlock(d->d_inode);
++ }
++ up_read(&au_di(d)->di_rwsem);
++}
++
++void di_downgrade_lock(struct dentry *d, int flags)
++{
++ downgrade_write(&au_di(d)->di_rwsem);
++ if (d->d_inode && au_ftest_lock(flags, IR))
++ ii_downgrade_lock(d->d_inode);
++}
++
++void di_write_lock(struct dentry *d, unsigned int lsc)
++{
++ down_write_nested(&au_di(d)->di_rwsem, lsc);
++ if (d->d_inode)
++ do_ii_write_lock(d->d_inode, lsc);
++}
++
++void di_write_unlock(struct dentry *d)
++{
++ if (d->d_inode)
++ ii_write_unlock(d->d_inode);
++ up_write(&au_di(d)->di_rwsem);
++}
++
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ AuDebugOn(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir && au_test_subdir(d1, d2)) {
++ di_write_lock_child(d1);
++ di_write_lock_child2(d2);
++ } else {
++ /* there should be no races */
++ di_write_lock_child(d2);
++ di_write_lock_child2(d1);
++ }
++}
++
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
++{
++ AuDebugOn(d1 == d2
++ || d1->d_inode == d2->d_inode
++ || d1->d_sb != d2->d_sb);
++
++ if (isdir && au_test_subdir(d1, d2)) {
++ di_write_lock_parent(d1);
++ di_write_lock_parent2(d2);
++ } else {
++ /* there should be no races */
++ di_write_lock_parent(d2);
++ di_write_lock_parent2(d1);
++ }
++}
++
++void di_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock(d1);
++ if (d1->d_inode == d2->d_inode)
++ up_write(&au_di(d2)->di_rwsem);
++ else
++ di_write_unlock(d2);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ struct dentry *d;
++
++ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++ return NULL;
++ AuDebugOn(bindex < 0);
++ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
++ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
++ return d;
++}
++
++aufs_bindex_t au_dbtail(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bwh;
++
++ bend = au_dbend(dentry);
++ if (0 <= bend) {
++ bwh = au_dbwh(dentry);
++ if (!bwh)
++ return bwh;
++ if (0 < bwh && bwh < bend)
++ return bwh - 1;
++ }
++ return bend;
++}
++
++aufs_bindex_t au_dbtaildir(struct dentry *dentry)
++{
++ aufs_bindex_t bend, bopq;
++
++ bend = au_dbtail(dentry);
++ if (0 <= bend) {
++ bopq = au_dbdiropq(dentry);
++ if (0 <= bopq && bopq < bend)
++ bend = bopq;
++ }
++ return bend;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
++
++ if (hd->hd_dentry)
++ au_hdput(hd);
++ hd->hd_dentry = h_dentry;
++}
++
++void au_update_digen(struct dentry *dentry)
++{
++ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++void au_update_dbrange(struct dentry *dentry, int do_put_zero)
++{
++ struct au_dinfo *dinfo;
++ struct dentry *h_d;
++
++ dinfo = au_di(dentry);
++ if (!dinfo || dinfo->di_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex, bend;
++
++ bend = dinfo->di_bend;
++ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
++ h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
++ if (h_d && !h_d->d_inode)
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++ }
++
++ dinfo->di_bstart = -1;
++ while (++dinfo->di_bstart <= dinfo->di_bend)
++ if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
++ break;
++ if (dinfo->di_bstart > dinfo->di_bend) {
++ dinfo->di_bstart = -1;
++ dinfo->di_bend = -1;
++ return;
++ }
++
++ dinfo->di_bend++;
++ while (0 <= --dinfo->di_bend)
++ if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
++ break;
++ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
++}
++
++void au_update_dbstart(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bend;
++ struct dentry *h_dentry;
++
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ if (h_dentry->d_inode) {
++ au_set_dbstart(dentry, bindex);
++ return;
++ }
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++}
++
++void au_update_dbend(struct dentry *dentry)
++{
++ aufs_bindex_t bindex, bstart;
++ struct dentry *h_dentry;
++
++ bstart = au_dbstart(dentry);
++ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ if (h_dentry->d_inode) {
++ au_set_dbend(dentry, bindex);
++ return;
++ }
++ au_set_h_dptr(dentry, bindex, NULL);
++ }
++}
++
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
++{
++ aufs_bindex_t bindex, bend;
++
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
++ if (au_h_dptr(dentry, bindex) == h_dentry)
++ return bindex;
++ return -1;
++}
+diff -Naur a/fs/aufs/dir.c b/fs/aufs/dir.c
+--- a/fs/aufs/dir.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,532 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * directory operations
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include "aufs.h"
++
++void au_add_nlink(struct inode *dir, struct inode *h_dir)
++{
++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++ dir->i_nlink += h_dir->i_nlink - 2;
++ if (h_dir->i_nlink < 2)
++ dir->i_nlink += 2;
++}
++
++void au_sub_nlink(struct inode *dir, struct inode *h_dir)
++{
++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++ dir->i_nlink -= h_dir->i_nlink - 2;
++ if (h_dir->i_nlink < 2)
++ dir->i_nlink -= 2;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int reopen_dir(struct file *file)
++{
++ int err;
++ unsigned int flags;
++ aufs_bindex_t bindex, btail, bstart;
++ struct dentry *dentry, *h_dentry;
++ struct file *h_file;
++
++ /* open all lower dirs */
++ dentry = file->f_dentry;
++ bstart = au_dbstart(dentry);
++ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbstart(file, bstart);
++
++ btail = au_dbtaildir(dentry);
++ for (bindex = au_fbend(file); btail < bindex; bindex--)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbend(file, btail);
++
++ flags = file->f_flags;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++ h_file = au_h_fptr(file, bindex);
++ if (h_file)
++ continue;
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out; /* close all? */
++ au_set_h_fptr(file, bindex, h_file);
++ }
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ err = 0;
++
++ out:
++ return err;
++}
++
++static int do_open_dir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex, btail;
++ struct dentry *dentry, *h_dentry;
++ struct file *h_file;
++
++ err = 0;
++ dentry = file->f_dentry;
++ au_set_fvdir_cache(file, NULL);
++ au_fi(file)->fi_maintain_plink = 0;
++ file->f_version = dentry->d_inode->i_version;
++ bindex = au_dbstart(dentry);
++ au_set_fbstart(file, bindex);
++ btail = au_dbtaildir(dentry);
++ au_set_fbend(file, btail);
++ for (; !err && bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!h_dentry)
++ continue;
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ if (IS_ERR(h_file)) {
++ err = PTR_ERR(h_file);
++ break;
++ }
++ au_set_h_fptr(file, bindex, h_file);
++ }
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ if (!err)
++ return 0; /* success */
++
++ /* close all */
++ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbstart(file, -1);
++ au_set_fbend(file, -1);
++ return err;
++}
++
++static int aufs_open_dir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ return au_do_open(file, do_open_dir);
++}
++
++static int aufs_release_dir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ struct au_vdir *vdir_cache;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ sb = file->f_dentry->d_sb;
++ si_noflush_read_lock(sb);
++ fi_write_lock(file);
++ vdir_cache = au_fvdir_cache(file);
++ if (vdir_cache)
++ au_vdir_free(vdir_cache);
++ if (au_fi(file)->fi_maintain_plink) {
++ sbinfo = au_sbi(sb);
++ au_fclr_si(sbinfo, MAINTAIN_PLINK);
++ wake_up_all(&sbinfo->si_plink_wq);
++ }
++ fi_write_unlock(file);
++ au_finfo_fin(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct inode *inode;
++ struct super_block *sb;
++
++ err = 0;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
++ struct path h_path;
++ struct inode *h_inode;
++
++ if (au_test_ro(sb, bindex, inode))
++ continue;
++ h_path.dentry = au_h_dptr(dentry, bindex);
++ if (!h_path.dentry)
++ continue;
++ h_inode = h_path.dentry->d_inode;
++ if (!h_inode)
++ continue;
++
++ /* no mnt_want_write() */
++ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
++ /* todo: inotiry fired? */
++ h_path.mnt = au_sbr_mnt(sb, bindex);
++ mutex_lock(&h_inode->i_mutex);
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ AuDebugOn(!h_inode->i_fop);
++ if (!err && h_inode->i_fop->fsync)
++ err = h_inode->i_fop->fsync(NULL, h_path.dentry,
++ datasync);
++ if (!err)
++ err = filemap_fdatawrite(h_inode->i_mapping);
++ if (!err)
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++ mutex_unlock(&h_inode->i_mutex);
++ }
++
++ return err;
++}
++
++static int au_do_fsync_dir(struct file *file, int datasync)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct file *h_file;
++ struct super_block *sb;
++ struct inode *inode;
++ struct mutex *h_mtx;
++
++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ sb = file->f_dentry->d_sb;
++ inode = file->f_dentry->d_inode;
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++ h_file = au_h_fptr(file, bindex);
++ if (!h_file || au_test_ro(sb, bindex, inode))
++ continue;
++
++ err = vfs_fsync(h_file, h_file->f_dentry, datasync);
++ if (!err) {
++ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
++ mutex_lock(h_mtx);
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ mutex_unlock(h_mtx);
++ }
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * @file may be NULL
++ */
++static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct super_block *sb;
++
++ IMustLock(dentry->d_inode);
++
++ err = 0;
++ sb = dentry->d_sb;
++ si_noflush_read_lock(sb);
++ if (file)
++ err = au_do_fsync_dir(file, datasync);
++ else {
++ di_write_lock_child(dentry);
++ err = au_do_fsync_dir_no_file(dentry, datasync);
++ }
++ au_cpup_attr_timesizes(dentry->d_inode);
++ di_write_unlock(dentry);
++ if (file)
++ fi_write_unlock(file);
++
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++ err = au_vdir_init(file);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ if (!au_test_nfsd(current)) {
++ err = au_vdir_fill_de(file, dirent, filldir);
++ fsstack_copy_attr_atime(inode,
++ au_h_iptr(inode, au_ibstart(inode)));
++ } else {
++ /*
++ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
++ * encode_fh() and others.
++ */
++ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
++
++ di_read_unlock(dentry, AuLock_IR);
++ si_read_unlock(sb);
++ lockdep_off();
++ err = au_vdir_fill_de(file, dirent, filldir);
++ lockdep_on();
++ fsstack_copy_attr_atime(inode, h_inode);
++ fi_write_unlock(file);
++
++ AuTraceErr(err);
++ return err;
++ }
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuTestEmpty_WHONLY 1
++#define AuTestEmpty_CALLED (1 << 1)
++#define AuTestEmpty_SHWH (1 << 2)
++#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
++#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
++#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuTestEmpty_SHWH
++#define AuTestEmpty_SHWH 0
++#endif
++
++struct test_empty_arg {
++ struct au_nhash whlist;
++ unsigned int flags;
++ int err;
++ aufs_bindex_t bindex;
++};
++
++static int test_empty_cb(void *__arg, const char *__name, int namelen,
++ loff_t offset __maybe_unused, u64 ino,
++ unsigned int d_type)
++{
++ struct test_empty_arg *arg = __arg;
++ char *name = (void *)__name;
++
++ arg->err = 0;
++ au_fset_testempty(arg->flags, CALLED);
++ /* smp_mb(); */
++ if (name[0] == '.'
++ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
++ goto out; /* success */
++
++ if (namelen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (au_ftest_testempty(arg->flags, WHONLY)
++ && !au_nhash_test_known_wh(&arg->whlist, name, namelen))
++ arg->err = -ENOTEMPTY;
++ goto out;
++ }
++
++ name += AUFS_WH_PFX_LEN;
++ namelen -= AUFS_WH_PFX_LEN;
++ if (!au_nhash_test_known_wh(&arg->whlist, name, namelen))
++ arg->err = au_nhash_append_wh
++ (&arg->whlist, name, namelen, ino, d_type, arg->bindex,
++ au_ftest_testempty(arg->flags, SHWH));
++
++ out:
++ /* smp_mb(); */
++ AuTraceErr(arg->err);
++ return arg->err;
++}
++
++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err;
++ struct file *h_file;
++
++ h_file = au_h_open(dentry, arg->bindex,
++ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
++ /*file*/NULL);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out;
++
++ err = 0;
++ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++ && !h_file->f_dentry->d_inode->i_nlink)
++ goto out_put;
++
++ do {
++ arg->err = 0;
++ au_fclr_testempty(arg->flags, CALLED);
++ /* smp_mb(); */
++ err = vfsub_readdir(h_file, test_empty_cb, arg);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && au_ftest_testempty(arg->flags, CALLED));
++
++ out_put:
++ fput(h_file);
++ au_sbr_put(dentry->d_sb, arg->bindex);
++ out:
++ return err;
++}
++
++struct do_test_empty_args {
++ int *errp;
++ struct dentry *dentry;
++ struct test_empty_arg *arg;
++};
++
++static void call_do_test_empty(void *args)
++{
++ struct do_test_empty_args *a = args;
++ *a->errp = do_test_empty(a->dentry, a->arg);
++}
++
++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++ int err, wkq_err;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, arg->bindex);
++ h_inode = h_dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
++ mutex_unlock(&h_inode->i_mutex);
++ if (!err)
++ err = do_test_empty(dentry, arg);
++ else {
++ struct do_test_empty_args args = {
++ .errp = &err,
++ .dentry = dentry,
++ .arg = arg
++ };
++ unsigned int flags = arg->flags;
++
++ wkq_err = au_wkq_wait(call_do_test_empty, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ arg->flags = flags;
++ }
++
++ return err;
++}
++
++int au_test_empty_lower(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bindex, bstart, btail;
++ struct test_empty_arg arg;
++
++ err = au_nhash_alloc(&arg.whlist, au_sbi(dentry->d_sb)->si_rdhash,
++ GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++
++ bstart = au_dbstart(dentry);
++ arg.flags = 0;
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++ au_fset_testempty(arg.flags, SHWH);
++ arg.bindex = bstart;
++ err = do_test_empty(dentry, &arg);
++ if (unlikely(err))
++ goto out_whlist;
++
++ au_fset_testempty(arg.flags, WHONLY);
++ btail = au_dbtaildir(dentry);
++ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry && h_dentry->d_inode) {
++ arg.bindex = bindex;
++ err = do_test_empty(dentry, &arg);
++ }
++ }
++
++ out_whlist:
++ au_nhash_wh_free(&arg.whlist);
++ out:
++ return err;
++}
++
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
++{
++ int err;
++ struct test_empty_arg arg;
++ aufs_bindex_t bindex, btail;
++
++ err = 0;
++ arg.whlist = *whlist;
++ arg.flags = AuTestEmpty_WHONLY;
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++ au_fset_testempty(arg.flags, SHWH);
++ btail = au_dbtaildir(dentry);
++ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
++ struct dentry *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry && h_dentry->d_inode) {
++ arg.bindex = bindex;
++ err = sio_test_empty(dentry, &arg);
++ }
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_dir_fop = {
++ .read = generic_read_dir,
++ .readdir = aufs_readdir,
++ .unlocked_ioctl = aufs_ioctl_dir,
++ .open = aufs_open_dir,
++ .release = aufs_release_dir,
++ .flush = aufs_flush,
++ .fsync = aufs_fsync_dir
++};
+diff -Naur a/fs/aufs/dir.h b/fs/aufs/dir.h
+--- a/fs/aufs/dir.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * directory operations
++ */
++
++#ifndef __AUFS_DIR_H__
++#define __AUFS_DIR_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* need to be faster and smaller */
++
++struct au_nhash {
++ unsigned int nh_num;
++ struct hlist_head *nh_head;
++};
++
++struct au_vdir_destr {
++ unsigned char len;
++ unsigned char name[0];
++} __packed;
++
++struct au_vdir_dehstr {
++ struct hlist_node hash;
++ struct au_vdir_destr *str;
++};
++
++struct au_vdir_de {
++ ino_t de_ino;
++ unsigned char de_type;
++ /* caution: packed */
++ struct au_vdir_destr de_str;
++} __packed;
++
++struct au_vdir_wh {
++ struct hlist_node wh_hash;
++#ifdef CONFIG_AUFS_SHWH
++ ino_t wh_ino;
++ aufs_bindex_t wh_bindex;
++ unsigned char wh_type;
++#else
++ aufs_bindex_t wh_bindex;
++#endif
++ /* caution: packed */
++ struct au_vdir_destr wh_str;
++} __packed;
++
++union au_vdir_deblk_p {
++ unsigned char *deblk;
++ struct au_vdir_de *de;
++};
++
++struct au_vdir {
++ unsigned char **vd_deblk;
++ unsigned long vd_nblk;
++ struct {
++ unsigned long ul;
++ union au_vdir_deblk_p p;
++ } vd_last;
++
++ unsigned long vd_version;
++ unsigned int vd_deblk_sz;
++ unsigned long vd_jiffy;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dir.c */
++extern const struct file_operations aufs_dir_fop;
++void au_add_nlink(struct inode *dir, struct inode *h_dir);
++void au_sub_nlink(struct inode *dir, struct inode *h_dir);
++int au_test_empty_lower(struct dentry *dentry);
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
++
++/* vdir.c */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
++void au_nhash_wh_free(struct au_nhash *whlist);
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++ int limit);
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++ unsigned int d_type, aufs_bindex_t bindex,
++ unsigned char shwh);
++void au_vdir_free(struct au_vdir *vdir);
++int au_vdir_init(struct file *file);
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
++
++/* ioctl.c */
++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DIR_H__ */
+diff -Naur a/fs/aufs/export.c b/fs/aufs/export.c
+--- a/fs/aufs/export.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/export.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * export via nfs
++ */
++
++#include <linux/exportfs.h>
++#include <linux/file.h>
++#include <linux/mnt_namespace.h>
++#include <linux/namei.h>
++#include <linux/random.h>
++#include "aufs.h"
++
++union conv {
++#ifdef CONFIG_AUFS_INO_T_64
++ __u32 a[2];
++#else
++ __u32 a[1];
++#endif
++ ino_t ino;
++};
++
++static ino_t decode_ino(__u32 *a)
++{
++ union conv u;
++
++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
++ u.a[0] = a[0];
++#ifdef CONFIG_AUFS_INO_T_64
++ u.a[1] = a[1];
++#endif
++ return u.ino;
++}
++
++static void encode_ino(__u32 *a, ino_t ino)
++{
++ union conv u;
++
++ u.ino = ino;
++ a[0] = u.a[0];
++#ifdef CONFIG_AUFS_INO_T_64
++ a[1] = u.a[1];
++#endif
++}
++
++/* NFS file handle */
++enum {
++ Fh_br_id,
++ Fh_sigen,
++#ifdef CONFIG_AUFS_INO_T_64
++ /* support 64bit inode number */
++ Fh_ino1,
++ Fh_ino2,
++ Fh_dir_ino1,
++ Fh_dir_ino2,
++#else
++ Fh_ino1,
++ Fh_dir_ino1,
++#endif
++ Fh_igen,
++ Fh_h_type,
++ Fh_tail,
++
++ Fh_ino = Fh_ino1,
++ Fh_dir_ino = Fh_dir_ino1
++};
++
++static int au_test_anon(struct dentry *dentry)
++{
++ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
++}
++
++/* ---------------------------------------------------------------------- */
++/* inode generation external table */
++
++int au_xigen_inc(struct inode *inode)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ __u32 igen;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ sb = inode->i_sb;
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ goto out;
++
++ pos = inode->i_ino;
++ pos *= sizeof(igen);
++ igen = inode->i_generation + 1;
++ sbinfo = au_sbi(sb);
++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
++ sizeof(igen), &pos);
++ if (sz == sizeof(igen))
++ goto out; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xigen error (%zd)\n", sz);
++ }
++
++ out:
++ return err;
++}
++
++int au_xigen_new(struct inode *inode)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ err = 0;
++ /* todo: dirty, at mount time */
++ if (inode->i_ino == AUFS_ROOT_INO)
++ goto out;
++ sb = inode->i_sb;
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ goto out;
++
++ err = -EFBIG;
++ pos = inode->i_ino;
++ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
++ AuIOErr1("too large i%lld\n", pos);
++ goto out;
++ }
++ pos *= sizeof(inode->i_generation);
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ file = sbinfo->si_xigen;
++ BUG_ON(!file);
++
++ if (i_size_read(file->f_dentry->d_inode)
++ < pos + sizeof(inode->i_generation)) {
++ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
++ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
++ sizeof(inode->i_generation), &pos);
++ } else
++ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
++ sizeof(inode->i_generation), &pos);
++ if (sz == sizeof(inode->i_generation))
++ goto out; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xigen error (%zd)\n", sz);
++ }
++
++ out:
++ return err;
++}
++
++int au_xigen_set(struct super_block *sb, struct file *base)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ sbinfo = au_sbi(sb);
++ file = au_xino_create2(base, sbinfo->si_xigen);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ err = 0;
++ if (sbinfo->si_xigen)
++ fput(sbinfo->si_xigen);
++ sbinfo->si_xigen = file;
++
++ out:
++ return err;
++}
++
++void au_xigen_clr(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (sbinfo->si_xigen) {
++ fput(sbinfo->si_xigen);
++ sbinfo->si_xigen = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino)
++{
++ struct dentry *dentry, *d;
++ struct inode *inode;
++ unsigned int sigen;
++
++ dentry = NULL;
++ inode = ilookup(sb, ino);
++ if (!inode)
++ goto out;
++
++ dentry = ERR_PTR(-ESTALE);
++ sigen = au_sigen(sb);
++ if (unlikely(is_bad_inode(inode)
++ || IS_DEADDIR(inode)
++ || sigen != au_iigen(inode)))
++ goto out_iput;
++
++ dentry = NULL;
++ if (!dir_ino || S_ISDIR(inode->i_mode))
++ dentry = d_find_alias(inode);
++ else {
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias)
++ if (!au_test_anon(d)
++ && d->d_parent->d_inode->i_ino == dir_ino) {
++ dentry = dget_locked(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ }
++ if (unlikely(dentry && sigen != au_digen(dentry))) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++
++ out_iput:
++ iput(inode);
++ out:
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: dirty? */
++/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
++static struct vfsmount *au_mnt_get(struct super_block *sb)
++{
++ struct mnt_namespace *ns;
++ struct vfsmount *pos, *mnt;
++
++ spin_lock(&vfsmount_lock);
++ /* no get/put ?? */
++ AuDebugOn(!current->nsproxy);
++ ns = current->nsproxy->mnt_ns;
++ AuDebugOn(!ns);
++ mnt = NULL;
++ /* the order (reverse) will not be a problem */
++ list_for_each_entry(pos, &ns->list, mnt_list)
++ if (pos->mnt_sb == sb) {
++ mnt = mntget(pos);
++ break;
++ }
++ spin_unlock(&vfsmount_lock);
++ AuDebugOn(!mnt);
++
++ return mnt;
++}
++
++struct au_nfsd_si_lock {
++ const unsigned int sigen;
++ const aufs_bindex_t br_id;
++ unsigned char force_lock;
++};
++
++static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ aufs_bindex_t bindex;
++
++ si_read_lock(sb, AuLock_FLUSH);
++
++ /* branch id may be wrapped around */
++ bindex = au_br_index(sb, nsi_lock->br_id);
++ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
++ goto out; /* success */
++
++ if (!nsi_lock->force_lock)
++ si_read_unlock(sb);
++ bindex = -1;
++
++ out:
++ return bindex;
++}
++
++struct find_name_by_ino {
++ int called, found;
++ ino_t ino;
++ char *name;
++ int namelen;
++};
++
++static int
++find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
++ u64 ino, unsigned int d_type)
++{
++ struct find_name_by_ino *a = arg;
++
++ a->called++;
++ if (a->ino != ino)
++ return 0;
++
++ memcpy(a->name, name, namelen);
++ a->namelen = namelen;
++ a->found = 1;
++ return 1;
++}
++
++static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry, *parent;
++ struct file *file;
++ struct inode *dir;
++ struct find_name_by_ino arg;
++ int err;
++
++ parent = path->dentry;
++ if (nsi_lock)
++ si_read_unlock(parent->d_sb);
++ path_get(path);
++ file = dentry_open(parent, path->mnt, au_dir_roflags, current_cred());
++ dentry = (void *)file;
++ if (IS_ERR(file))
++ goto out;
++
++ dentry = ERR_PTR(-ENOMEM);
++ arg.name = __getname();
++ if (unlikely(!arg.name))
++ goto out_file;
++ arg.ino = ino;
++ arg.found = 0;
++ do {
++ arg.called = 0;
++ /* smp_mb(); */
++ err = vfsub_readdir(file, find_name_by_ino, &arg);
++ } while (!err && !arg.found && arg.called);
++ dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_name;
++ dentry = ERR_PTR(-ENOENT);
++ if (!arg.found)
++ goto out_name;
++
++ /* do not call au_lkup_one() */
++ dir = parent->d_inode;
++ mutex_lock(&dir->i_mutex);
++ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
++ mutex_unlock(&dir->i_mutex);
++ AuTraceErrPtr(dentry);
++ if (IS_ERR(dentry))
++ goto out_name;
++ AuDebugOn(au_test_anon(dentry));
++ if (unlikely(!dentry->d_inode)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ENOENT);
++ }
++
++ out_name:
++ __putname(arg.name);
++ out_file:
++ fput(file);
++ out:
++ if (unlikely(nsi_lock
++ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
++ if (!IS_ERR(dentry)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
++ ino_t dir_ino,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry;
++ struct path path;
++
++ if (dir_ino != AUFS_ROOT_INO) {
++ path.dentry = decode_by_ino(sb, dir_ino, 0);
++ dentry = path.dentry;
++ if (!path.dentry || IS_ERR(path.dentry))
++ goto out;
++ AuDebugOn(au_test_anon(path.dentry));
++ } else
++ path.dentry = dget(sb->s_root);
++
++ path.mnt = au_mnt_get(sb);
++ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
++ path_put(&path);
++
++ out:
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_acceptable(void *expv, struct dentry *dentry)
++{
++ return 1;
++}
++
++static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
++ char *buf, int len, struct super_block *sb)
++{
++ char *p;
++ int n;
++ struct path path;
++
++ p = d_path(h_rootpath, buf, len);
++ if (IS_ERR(p))
++ goto out;
++ n = strlen(p);
++
++ path.mnt = h_rootpath->mnt;
++ path.dentry = h_parent;
++ p = d_path(&path, buf, len);
++ if (IS_ERR(p))
++ goto out;
++ if (n != 1)
++ p += n;
++
++ path.mnt = au_mnt_get(sb);
++ path.dentry = sb->s_root;
++ p = d_path(&path, buf, len - strlen(p));
++ mntput(path.mnt);
++ if (IS_ERR(p))
++ goto out;
++ if (n != 1)
++ p[strlen(p)] = '/';
++
++ out:
++ AuTraceErrPtr(p);
++ return p;
++}
++
++static
++struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
++ ino_t ino, __u32 *fh, int fh_len,
++ struct au_nfsd_si_lock *nsi_lock)
++{
++ struct dentry *dentry, *h_parent, *root;
++ struct super_block *h_sb;
++ char *pathname, *p;
++ struct vfsmount *h_mnt;
++ struct au_branch *br;
++ int err;
++ struct path path;
++
++ br = au_sbr(sb, bindex);
++ /* au_br_get(br); */
++ h_mnt = br->br_mnt;
++ h_sb = h_mnt->mnt_sb;
++ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
++ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
++ fh_len - Fh_tail, fh[Fh_h_type],
++ h_acceptable, /*context*/NULL);
++ dentry = h_parent;
++ if (unlikely(!h_parent || IS_ERR(h_parent))) {
++ AuWarn1("%s decode_fh failed, %ld\n",
++ au_sbtype(h_sb), PTR_ERR(h_parent));
++ goto out;
++ }
++ dentry = NULL;
++ if (unlikely(au_test_anon(h_parent))) {
++ AuWarn1("%s decode_fh returned a disconnected dentry\n",
++ au_sbtype(h_sb));
++ goto out_h_parent;
++ }
++
++ dentry = ERR_PTR(-ENOMEM);
++ pathname = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!pathname))
++ goto out_h_parent;
++
++ root = sb->s_root;
++ path.mnt = h_mnt;
++ di_read_lock_parent(root, !AuLock_IR);
++ path.dentry = au_h_dptr(root, bindex);
++ di_read_unlock(root, !AuLock_IR);
++ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
++ dentry = (void *)p;
++ if (IS_ERR(p))
++ goto out_pathname;
++
++ si_read_unlock(sb);
++ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
++ dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_relock;
++
++ dentry = ERR_PTR(-ENOENT);
++ AuDebugOn(au_test_anon(path.dentry));
++ if (unlikely(!path.dentry->d_inode))
++ goto out_path;
++
++ if (ino != path.dentry->d_inode->i_ino)
++ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
++ else
++ dentry = dget(path.dentry);
++
++ out_path:
++ path_put(&path);
++ out_relock:
++ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
++ if (!IS_ERR(dentry)) {
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ }
++ out_pathname:
++ free_page((unsigned long)pathname);
++ out_h_parent:
++ dput(h_parent);
++ out:
++ /* au_br_put(br); */
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *
++aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
++ int fh_type)
++{
++ struct dentry *dentry;
++ __u32 *fh = fid->raw;
++ ino_t ino, dir_ino;
++ aufs_bindex_t bindex;
++ struct au_nfsd_si_lock nsi_lock = {
++ .sigen = fh[Fh_sigen],
++ .br_id = fh[Fh_br_id],
++ .force_lock = 0
++ };
++
++ AuDebugOn(fh_len < Fh_tail);
++
++ dentry = ERR_PTR(-ESTALE);
++ /* branch id may be wrapped around */
++ bindex = si_nfsd_read_lock(sb, &nsi_lock);
++ if (unlikely(bindex < 0))
++ goto out;
++ nsi_lock.force_lock = 1;
++
++ /* is this inode still cached? */
++ ino = decode_ino(fh + Fh_ino);
++ AuDebugOn(ino == AUFS_ROOT_INO);
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ dentry = decode_by_ino(sb, ino, dir_ino);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (dentry)
++ goto accept;
++
++ /* is the parent dir cached? */
++ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (dentry)
++ goto accept;
++
++ /* lookup path */
++ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
++ if (IS_ERR(dentry))
++ goto out_unlock;
++ if (unlikely(!dentry))
++ /* todo?: make it ESTALE */
++ goto out_unlock;
++
++ accept:
++ if (dentry->d_inode->i_generation == fh[Fh_igen])
++ goto out_unlock; /* success */
++
++ dput(dentry);
++ dentry = ERR_PTR(-ESTALE);
++ out_unlock:
++ si_read_unlock(sb);
++ out:
++ AuTraceErrPtr(dentry);
++ return dentry;
++}
++
++#if 0 /* reserved for future use */
++/* support subtreecheck option */
++static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
++ int fh_len, int fh_type)
++{
++ struct dentry *parent;
++ __u32 *fh = fid->raw;
++ ino_t dir_ino;
++
++ dir_ino = decode_ino(fh + Fh_dir_ino);
++ parent = decode_by_ino(sb, dir_ino, 0);
++ if (IS_ERR(parent))
++ goto out;
++ if (!parent)
++ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
++ dir_ino, fh, fh_len);
++
++ out:
++ AuTraceErrPtr(parent);
++ return parent;
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
++ int connectable)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb, *h_sb;
++ struct inode *inode;
++ struct dentry *parent, *h_parent;
++ struct au_branch *br;
++
++ AuDebugOn(au_test_anon(dentry));
++
++ parent = NULL;
++ err = -ENOSPC;
++ if (unlikely(*max_len <= Fh_tail)) {
++ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
++ goto out;
++ }
++
++ err = FILEID_ROOT;
++ if (IS_ROOT(dentry)) {
++ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
++ goto out;
++ }
++
++ err = -EIO;
++ h_parent = NULL;
++ sb = dentry->d_sb;
++ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, !AuLock_IR);
++ inode = dentry->d_inode;
++ AuDebugOn(!inode);
++#ifdef CONFIG_AUFS_DEBUG
++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++ AuWarn1("NFS-exporting requires xino\n");
++#endif
++
++ bend = au_dbtaildir(parent);
++ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (h_parent) {
++ dget(h_parent);
++ break;
++ }
++ }
++ if (unlikely(!h_parent))
++ goto out_unlock;
++
++ err = -EPERM;
++ br = au_sbr(sb, bindex);
++ h_sb = br->br_mnt->mnt_sb;
++ if (unlikely(!h_sb->s_export_op)) {
++ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
++ goto out_dput;
++ }
++
++ fh[Fh_br_id] = br->br_id;
++ fh[Fh_sigen] = au_sigen(sb);
++ encode_ino(fh + Fh_ino, inode->i_ino);
++ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
++ fh[Fh_igen] = inode->i_generation;
++
++ *max_len -= Fh_tail;
++ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
++ max_len,
++ /*connectable or subtreecheck*/0);
++ err = fh[Fh_h_type];
++ *max_len += Fh_tail;
++ /* todo: macros? */
++ if (err != 255)
++ err = 99;
++ else
++ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
++
++ out_dput:
++ dput(h_parent);
++ out_unlock:
++ di_read_unlock(parent, !AuLock_IR);
++ dput(parent);
++ aufs_read_unlock(dentry, AuLock_IR);
++ out:
++ if (unlikely(err < 0))
++ err = 255;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct export_operations aufs_export_op = {
++ .fh_to_dentry = aufs_fh_to_dentry,
++ /* .fh_to_parent = aufs_fh_to_parent, */
++ .encode_fh = aufs_encode_fh
++};
++
++void au_export_init(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ __u32 u;
++
++ sb->s_export_op = &aufs_export_op;
++ sbinfo = au_sbi(sb);
++ sbinfo->si_xigen = NULL;
++ get_random_bytes(&u, sizeof(u));
++ BUILD_BUG_ON(sizeof(u) != sizeof(int));
++ atomic_set(&sbinfo->si_xigen_next, u);
++}
+diff -Naur a/fs/aufs/file.c b/fs/aufs/file.c
+--- a/fs/aufs/file.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,568 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * handling file/dir, and address_space operation
++ */
++
++#include <linux/file.h>
++#include <linux/fsnotify.h>
++#include <linux/namei.h>
++#include <linux/pagemap.h>
++#include "aufs.h"
++
++/*
++ * a dirty trick for handling deny_write_access().
++ * because FMODE_EXEC flag is not passed to f_op->open(),
++ * set it to file->private_data temporary.
++ */
++void au_store_oflag(struct nameidata *nd, struct inode *inode)
++{
++ if (nd
++ /* && !(nd->flags & LOOKUP_CONTINUE) */
++ && (nd->flags & LOOKUP_OPEN)
++ && (nd->intent.open.flags & vfsub_fmode_to_uint(FMODE_EXEC))
++ && inode
++ && S_ISREG(inode->i_mode)) {
++ /* suppress a warning in lp64 */
++ unsigned long flags = nd->intent.open.flags;
++ nd->intent.open.file->private_data = (void *)flags;
++ /* smp_mb(); */
++ }
++}
++
++/* drop flags for writing */
++unsigned int au_file_roflags(unsigned int flags)
++{
++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
++ flags |= O_RDONLY | O_NOATIME;
++ return flags;
++}
++
++/* common functions to regular file and dir */
++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++ struct file *file)
++{
++ struct file *h_file;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ /* a race condition can happen between open and unlink/rmdir */
++ h_file = ERR_PTR(-ENOENT);
++ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
++ || !h_inode))
++ goto out;
++
++ sb = dentry->d_sb;
++ br = au_sbr(sb, bindex);
++ h_file = ERR_PTR(-EACCES);
++ if (file && (file->f_mode & FMODE_EXEC)
++ && (br->br_mnt->mnt_flags & MNT_NOEXEC))
++ goto out;
++
++ /* drop flags for writing */
++ if (au_test_ro(sb, bindex, dentry->d_inode))
++ flags = au_file_roflags(flags);
++ flags &= ~O_CREAT;
++ atomic_inc(&br->br_count);
++ h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags,
++ current_cred());
++ if (IS_ERR(h_file))
++ goto out_br;
++
++ if (file && (file->f_mode & FMODE_EXEC)) {
++ h_file->f_mode |= FMODE_EXEC;
++ err = deny_write_access(h_file);
++ if (unlikely(err)) {
++ fput(h_file);
++ h_file = ERR_PTR(err);
++ goto out_br;
++ }
++ }
++ fsnotify_open(h_dentry);
++ goto out; /* success */
++
++ out_br:
++ atomic_dec(&br->br_count);
++ out:
++ return h_file;
++}
++
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
++{
++ int err;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_finfo_init(file);
++ if (unlikely(err))
++ goto out;
++
++ di_read_lock_child(dentry, AuLock_IR);
++ err = open(file, file->f_flags);
++ di_read_unlock(dentry, AuLock_IR);
++
++ fi_write_unlock(file);
++ if (unlikely(err))
++ au_finfo_fin(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++int au_reopen_nondir(struct file *file)
++{
++ int err;
++ aufs_bindex_t bstart, bindex, bend;
++ struct dentry *dentry;
++ struct file *h_file, *h_file_tmp;
++
++ dentry = file->f_dentry;
++ bstart = au_dbstart(dentry);
++ h_file_tmp = NULL;
++ if (au_fbstart(file) == bstart) {
++ h_file = au_h_fptr(file, bstart);
++ if (file->f_mode == h_file->f_mode)
++ return 0; /* success */
++ h_file_tmp = h_file;
++ get_file(h_file_tmp);
++ au_set_h_fptr(file, bstart, NULL);
++ }
++ AuDebugOn(au_fbstart(file) < bstart
++ || au_fi(file)->fi_hfile[0 + bstart].hf_file);
++
++ h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
++ err = PTR_ERR(h_file);
++ if (IS_ERR(h_file))
++ goto out; /* todo: close all? */
++
++ err = 0;
++ au_set_fbstart(file, bstart);
++ au_set_h_fptr(file, bstart, h_file);
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++
++ /* close lower files */
++ bend = au_fbend(file);
++ for (bindex = bstart + 1; bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++ au_set_fbend(file, bstart);
++
++ out:
++ if (h_file_tmp)
++ fput(h_file_tmp);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
++ struct dentry *hi_wh)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_dinfo *dinfo;
++ struct dentry *h_dentry;
++
++ dinfo = au_di(file->f_dentry);
++ bstart = dinfo->di_bstart;
++ dinfo->di_bstart = btgt;
++ h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
++ dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
++ err = au_reopen_nondir(file);
++ dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
++ dinfo->di_bstart = bstart;
++
++ return err;
++}
++
++static int au_ready_to_write_wh(struct file *file, loff_t len,
++ aufs_bindex_t bcpup)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *dentry, *hi_wh;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ hi_wh = au_hi_wh(inode, bcpup);
++ if (!hi_wh)
++ err = au_sio_cpup_wh(dentry, bcpup, len, file);
++ else
++ /* already copied-up after unlink */
++ err = au_reopen_wh(file, bcpup, hi_wh);
++
++ sb = dentry->d_sb;
++ if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
++ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
++
++ return err;
++}
++
++/*
++ * prepare the @file for writing.
++ */
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
++{
++ int err;
++ aufs_bindex_t bstart, bcpup;
++ struct dentry *dentry, *parent, *h_dentry;
++ struct inode *h_inode, *inode;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ bstart = au_fbstart(file);
++ inode = dentry->d_inode;
++ err = au_test_ro(sb, bstart, inode);
++ if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
++ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
++ goto out;
++ }
++
++ /* need to cpup */
++ parent = dget_parent(dentry);
++ di_write_lock_parent(parent);
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ bcpup = err;
++ if (unlikely(err < 0))
++ goto out_dgrade;
++ err = 0;
++
++ if (!au_h_dptr(parent, bcpup)) {
++ err = au_cpup_dirs(dentry, bcpup);
++ if (unlikely(err))
++ goto out_dgrade;
++ }
++
++ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out_dgrade;
++
++ h_dentry = au_h_fptr(file, bstart)->f_dentry;
++ h_inode = h_dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
++ /* || !h_inode->i_nlink */) {
++ err = au_ready_to_write_wh(file, len, bcpup);
++ di_downgrade_lock(parent, AuLock_IR);
++ } else {
++ di_downgrade_lock(parent, AuLock_IR);
++ if (!au_h_dptr(dentry, bcpup))
++ err = au_sio_cpup_simple(dentry, bcpup, len,
++ AuCpup_DTIME);
++ if (!err)
++ err = au_reopen_nondir(file);
++ }
++ mutex_unlock(&h_inode->i_mutex);
++
++ if (!err) {
++ au_pin_set_parent_lflag(pin, /*lflag*/0);
++ goto out_dput; /* success */
++ }
++ au_unpin(pin);
++ goto out_unlock;
++
++ out_dgrade:
++ di_downgrade_lock(parent, AuLock_IR);
++ out_unlock:
++ di_read_unlock(parent, AuLock_IR);
++ out_dput:
++ dput(parent);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
++{
++ int err;
++ aufs_bindex_t bstart;
++ struct au_pin pin;
++ struct au_finfo *finfo;
++ struct dentry *dentry, *parent, *hi_wh;
++ struct inode *inode;
++ struct super_block *sb;
++
++ err = 0;
++ finfo = au_fi(file);
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ bstart = au_ibstart(inode);
++ if (bstart == finfo->fi_bstart)
++ goto out;
++
++ parent = dget_parent(dentry);
++ if (au_test_ro(sb, bstart, inode)) {
++ di_read_lock_parent(parent, !AuLock_IR);
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ bstart = err;
++ di_read_unlock(parent, !AuLock_IR);
++ if (unlikely(err < 0))
++ goto out_parent;
++ err = 0;
++ }
++
++ di_read_lock_parent(parent, AuLock_IR);
++ hi_wh = au_hi_wh(inode, bstart);
++ if (au_opt_test(au_mntflags(sb), PLINK)
++ && au_plink_test(inode)
++ && !d_unhashed(dentry)) {
++ err = au_test_and_cpup_dirs(dentry, bstart);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* always superio. */
++ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (!err)
++ err = au_sio_cpup_simple(dentry, bstart, -1,
++ AuCpup_DTIME);
++ au_unpin(&pin);
++ } else if (hi_wh) {
++ /* already copied-up after unlink */
++ err = au_reopen_wh(file, bstart, hi_wh);
++ *need_reopen = 0;
++ }
++
++ out_unlock:
++ di_read_unlock(parent, AuLock_IR);
++ out_parent:
++ dput(parent);
++ out:
++ return err;
++}
++
++static void au_do_refresh_file(struct file *file)
++{
++ aufs_bindex_t bindex, bend, new_bindex, brid;
++ struct au_hfile *p, tmp, *q;
++ struct au_finfo *finfo;
++ struct super_block *sb;
++
++ sb = file->f_dentry->d_sb;
++ finfo = au_fi(file);
++ p = finfo->fi_hfile + finfo->fi_bstart;
++ brid = p->hf_br->br_id;
++ bend = finfo->fi_bend;
++ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
++ if (!p->hf_file)
++ continue;
++
++ new_bindex = au_br_index(sb, p->hf_br->br_id);
++ if (new_bindex == bindex)
++ continue;
++ if (new_bindex < 0) {
++ au_set_h_fptr(file, bindex, NULL);
++ continue;
++ }
++
++ /* swap two lower inode, and loop again */
++ q = finfo->fi_hfile + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hf_file) {
++ bindex--;
++ p--;
++ }
++ }
++
++ p = finfo->fi_hfile;
++ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
++ bend = au_sbend(sb);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p, file);
++ }
++ } else {
++ bend = au_br_index(sb, brid);
++ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
++ finfo->fi_bstart++, p++)
++ if (p->hf_file)
++ au_hfput(p, file);
++ bend = au_sbend(sb);
++ }
++
++ p = finfo->fi_hfile + bend;
++ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
++ finfo->fi_bend--, p--)
++ if (p->hf_file) {
++ if (p->hf_file->f_dentry
++ && p->hf_file->f_dentry->d_inode)
++ break;
++ else
++ au_hfput(p, file);
++ }
++ AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
++}
++
++/*
++ * after branch manipulating, refresh the file.
++ */
++static int refresh_file(struct file *file, int (*reopen)(struct file *file))
++{
++ int err, need_reopen;
++ struct dentry *dentry;
++ aufs_bindex_t bend, bindex;
++
++ dentry = file->f_dentry;
++ err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
++ if (unlikely(err))
++ goto out;
++ au_do_refresh_file(file);
++
++ err = 0;
++ need_reopen = 1;
++ if (!au_test_mmapped(file))
++ err = au_file_refresh_by_inode(file, &need_reopen);
++ if (!err && need_reopen && !d_unhashed(dentry))
++ err = reopen(file);
++ if (!err) {
++ au_update_figen(file);
++ return 0; /* success */
++ }
++
++ /* error, close all lower files */
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++
++ out:
++ return err;
++}
++
++/* common function to regular file and dir */
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++ int wlock)
++{
++ int err;
++ unsigned int sigen, figen;
++ aufs_bindex_t bstart;
++ unsigned char pseudo_link;
++ struct dentry *dentry;
++
++ err = 0;
++ dentry = file->f_dentry;
++ sigen = au_sigen(dentry->d_sb);
++ fi_write_lock(file);
++ figen = au_figen(file);
++ di_write_lock_child(dentry);
++ bstart = au_dbstart(dentry);
++ pseudo_link = (bstart != au_ibstart(dentry->d_inode));
++ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
++ if (!wlock) {
++ di_downgrade_lock(dentry, AuLock_IR);
++ fi_downgrade_lock(file);
++ }
++ goto out; /* success */
++ }
++
++ AuDbg("sigen %d, figen %d\n", sigen, figen);
++ if (sigen != au_digen(dentry)
++ || sigen != au_iigen(dentry->d_inode)) {
++ err = au_reval_dpath(dentry, sigen);
++ if (unlikely(err < 0))
++ goto out;
++ AuDebugOn(au_digen(dentry) != sigen
++ || au_iigen(dentry->d_inode) != sigen);
++ }
++
++ err = refresh_file(file, reopen);
++ if (!err) {
++ if (!wlock) {
++ di_downgrade_lock(dentry, AuLock_IR);
++ fi_downgrade_lock(file);
++ }
++ } else {
++ di_write_unlock(dentry);
++ fi_write_unlock(file);
++ }
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* cf. aufs_nopage() */
++/* for madvise(2) */
++static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
++{
++ unlock_page(page);
++ return 0;
++}
++
++/* they will never be called. */
++#ifdef CONFIG_AUFS_DEBUG
++static int aufs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned copied,
++ struct page *page, void *fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_writepage(struct page *page, struct writeback_control *wbc)
++{ AuUnsupport(); return 0; }
++static void aufs_sync_page(struct page *page)
++{ AuUnsupport(); }
++
++static int aufs_set_page_dirty(struct page *page)
++{ AuUnsupport(); return 0; }
++static void aufs_invalidatepage(struct page *page, unsigned long offset)
++{ AuUnsupport(); }
++static int aufs_releasepage(struct page *page, gfp_t gfp)
++{ AuUnsupport(); return 0; }
++static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs)
++{ AuUnsupport(); return 0; }
++#endif /* CONFIG_AUFS_DEBUG */
++
++struct address_space_operations aufs_aop = {
++ .readpage = aufs_readpage,
++#ifdef CONFIG_AUFS_DEBUG
++ .writepage = aufs_writepage,
++ .sync_page = aufs_sync_page,
++ .set_page_dirty = aufs_set_page_dirty,
++ .write_begin = aufs_write_begin,
++ .write_end = aufs_write_end,
++ .invalidatepage = aufs_invalidatepage,
++ .releasepage = aufs_releasepage,
++ .direct_IO = aufs_direct_IO,
++#endif /* CONFIG_AUFS_DEBUG */
++};
+diff -Naur a/fs/aufs/file.h b/fs/aufs/file.h
+--- a/fs/aufs/file.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file operations
++ */
++
++#ifndef __AUFS_FILE_H__
++#define __AUFS_FILE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct au_branch;
++struct au_hfile {
++ struct file *hf_file;
++ struct au_branch *hf_br;
++};
++
++struct au_vdir;
++struct au_finfo {
++ atomic_t fi_generation;
++
++ struct rw_semaphore fi_rwsem;
++ struct au_hfile *fi_hfile;
++ aufs_bindex_t fi_bstart, fi_bend;
++
++ union {
++ /* non-dir only */
++ struct {
++ struct vm_operations_struct *fi_h_vm_ops;
++ struct vm_operations_struct *fi_vm_ops;
++ };
++
++ /* dir only */
++ struct {
++ struct au_vdir *fi_vdir_cache;
++ int fi_maintain_plink;
++ };
++ };
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* file.c */
++extern struct address_space_operations aufs_aop;
++void au_store_oflag(struct nameidata *nd, struct inode *inode);
++unsigned int au_file_roflags(unsigned int flags);
++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++ struct file *file);
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
++int au_reopen_nondir(struct file *file);
++struct au_pin;
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++ int wlock);
++
++/* f_op.c */
++extern const struct file_operations aufs_file_fop;
++int aufs_flush(struct file *file, fl_owner_t id);
++
++/* finfo.c */
++void au_hfput(struct au_hfile *hf, struct file *file);
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
++ struct file *h_file);
++
++void au_update_figen(struct file *file);
++
++void au_finfo_fin(struct file *file);
++int au_finfo_init(struct file *file);
++int au_fi_realloc(struct au_finfo *finfo, int nbr);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_finfo *au_fi(struct file *file)
++{
++ return file->private_data;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * fi_read_lock, fi_write_lock,
++ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
++ */
++AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
++
++#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: hard/soft set? */
++static inline aufs_bindex_t au_fbstart(struct file *file)
++{
++ return au_fi(file)->fi_bstart;
++}
++
++static inline aufs_bindex_t au_fbend(struct file *file)
++{
++ return au_fi(file)->fi_bend;
++}
++
++static inline struct au_vdir *au_fvdir_cache(struct file *file)
++{
++ return au_fi(file)->fi_vdir_cache;
++}
++
++static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
++{
++ au_fi(file)->fi_bstart = bindex;
++}
++
++static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
++{
++ au_fi(file)->fi_bend = bindex;
++}
++
++static inline void au_set_fvdir_cache(struct file *file,
++ struct au_vdir *vdir_cache)
++{
++ au_fi(file)->fi_vdir_cache = vdir_cache;
++}
++
++static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
++{
++ return au_fi(file)->fi_hfile[0 + bindex].hf_file;
++}
++
++/* todo: memory barrier? */
++static inline unsigned int au_figen(struct file *f)
++{
++ return atomic_read(&au_fi(f)->fi_generation);
++}
++
++static inline int au_test_mmapped(struct file *f)
++{
++ return !!(au_fi(f)->fi_h_vm_ops);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FILE_H__ */
+diff -Naur a/fs/aufs/finfo.c b/fs/aufs/finfo.c
+--- a/fs/aufs/finfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/finfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file private data
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++void au_hfput(struct au_hfile *hf, struct file *file)
++{
++ if (file->f_mode & FMODE_EXEC)
++ allow_write_access(hf->hf_file);
++ fput(hf->hf_file);
++ hf->hf_file = NULL;
++ atomic_dec(&hf->hf_br->br_count);
++ hf->hf_br = NULL;
++}
++
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
++{
++ struct au_finfo *finfo = au_fi(file);
++ struct au_hfile *hf;
++
++ hf = finfo->fi_hfile + bindex;
++ if (hf->hf_file)
++ au_hfput(hf, file);
++ if (val) {
++ hf->hf_file = val;
++ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
++ }
++}
++
++void au_update_figen(struct file *file)
++{
++ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_finfo_fin(struct file *file)
++{
++ struct au_finfo *finfo;
++ aufs_bindex_t bindex, bend;
++
++ fi_write_lock(file);
++ bend = au_fbend(file);
++ bindex = au_fbstart(file);
++ if (bindex >= 0)
++ /*
++ * calls fput() instead of filp_close(),
++ * since no dnotify or lock for the lower file.
++ */
++ for (; bindex <= bend; bindex++)
++ au_set_h_fptr(file, bindex, NULL);
++
++ finfo = au_fi(file);
++ au_dbg_verify_hf(finfo);
++ kfree(finfo->fi_hfile);
++ fi_write_unlock(file);
++ au_rwsem_destroy(&finfo->fi_rwsem);
++ au_cache_free_finfo(finfo);
++}
++
++int au_finfo_init(struct file *file)
++{
++ struct au_finfo *finfo;
++ struct dentry *dentry;
++ unsigned long ul;
++
++ dentry = file->f_dentry;
++ finfo = au_cache_alloc_finfo();
++ if (unlikely(!finfo))
++ goto out;
++
++ finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
++ sizeof(*finfo->fi_hfile), GFP_NOFS);
++ if (unlikely(!finfo->fi_hfile))
++ goto out_finfo;
++
++ init_rwsem(&finfo->fi_rwsem);
++ down_write(&finfo->fi_rwsem);
++ finfo->fi_bstart = -1;
++ finfo->fi_bend = -1;
++ atomic_set(&finfo->fi_generation, au_digen(dentry));
++ /* smp_mb(); */ /* atomic_set */
++
++ /* cf. au_store_oflag() */
++ /* suppress a warning in lp64 */
++ ul = (unsigned long)file->private_data;
++ file->f_mode |= (vfsub_uint_to_fmode(ul) & FMODE_EXEC);
++ file->private_data = finfo;
++ return 0; /* success */
++
++ out_finfo:
++ au_cache_free_finfo(finfo);
++ out:
++ return -ENOMEM;
++}
++
++int au_fi_realloc(struct au_finfo *finfo, int nbr)
++{
++ int err, sz;
++ struct au_hfile *hfp;
++
++ err = -ENOMEM;
++ sz = sizeof(*hfp) * (finfo->fi_bend + 1);
++ if (!sz)
++ sz = sizeof(*hfp);
++ hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
++ if (hfp) {
++ finfo->fi_hfile = hfp;
++ err = 0;
++ }
++
++ return err;
++}
+diff -Naur a/fs/aufs/f_op.c b/fs/aufs/f_op.c
+--- a/fs/aufs/f_op.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/f_op.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,648 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * file and vm operations
++ */
++
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/poll.h>
++#include "aufs.h"
++
++/* common function to regular file and dir */
++int aufs_flush(struct file *file, fl_owner_t id)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct dentry *dentry;
++ struct file *h_file;
++
++ dentry = file->f_dentry;
++ si_noflush_read_lock(dentry->d_sb);
++ fi_read_lock(file);
++ di_read_lock_child(dentry, AuLock_IW);
++
++ err = 0;
++ bend = au_fbend(file);
++ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++ h_file = au_h_fptr(file, bindex);
++ if (!h_file || !h_file->f_op || !h_file->f_op->flush)
++ continue;
++
++ err = h_file->f_op->flush(h_file, id);
++ if (!err)
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ }
++ au_cpup_attr_timesizes(dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IW);
++ fi_read_unlock(file);
++ si_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int do_open_nondir(struct file *file, int flags)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct au_finfo *finfo;
++
++ err = 0;
++ dentry = file->f_dentry;
++ finfo = au_fi(file);
++ finfo->fi_h_vm_ops = NULL;
++ finfo->fi_vm_ops = NULL;
++ bindex = au_dbstart(dentry);
++ /* O_TRUNC is processed already */
++ BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
++ && (flags & O_TRUNC));
++
++ h_file = au_h_open(dentry, bindex, flags, file);
++ if (IS_ERR(h_file))
++ err = PTR_ERR(h_file);
++ else {
++ au_set_fbstart(file, bindex);
++ au_set_fbend(file, bindex);
++ au_set_h_fptr(file, bindex, h_file);
++ au_update_figen(file);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ }
++ return err;
++}
++
++static int aufs_open_nondir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ return au_do_open(file, do_open_nondir);
++}
++
++static int aufs_release_nondir(struct inode *inode __maybe_unused,
++ struct file *file)
++{
++ struct super_block *sb = file->f_dentry->d_sb;
++
++ si_noflush_read_lock(sb);
++ kfree(au_fi(file)->fi_vm_ops);
++ au_finfo_fin(file);
++ si_read_unlock(sb);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ struct dentry *dentry;
++ struct file *h_file;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ err = vfsub_read_u(h_file, buf, count, ppos);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++static ssize_t aufs_write(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ aufs_bindex_t bstart;
++ struct au_pin pin;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *h_file;
++ char __user *buf = (char __user *)ubuf;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ mutex_lock(&inode->i_mutex);
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ bstart = au_fbstart(file);
++ h_file = au_h_fptr(file, bstart);
++ au_unpin(&pin);
++ err = vfsub_write_u(h_file, buf, count, ppos);
++ au_cpup_attr_timesizes(inode);
++ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
++
++static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ ssize_t err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (au_test_loopback_kthread()) {
++ file->f_mapping = h_file->f_mapping;
++ smp_mb(); /* unnecessary? */
++ }
++ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
++ /* todo: necessasry? */
++ /* file->f_ra = h_file->f_ra; */
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++static ssize_t
++aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
++ size_t len, unsigned int flags)
++{
++ ssize_t err;
++ struct au_pin pin;
++ struct dentry *dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *h_file;
++
++ dentry = file->f_dentry;
++ inode = dentry->d_inode;
++ mutex_lock(&inode->i_mutex);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ au_unpin(&pin);
++ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
++ au_cpup_attr_timesizes(inode);
++ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct file *au_safe_file(struct vm_area_struct *vma)
++{
++ struct file *file;
++
++ file = vma->vm_file;
++ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
++ return file;
++ return NULL;
++}
++
++static void au_reset_file(struct vm_area_struct *vma, struct file *file)
++{
++ vma->vm_file = file;
++ /* smp_mb(); */ /* flush vm_file */
++}
++
++static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ int err;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ /* todo: non-robr mode, user vm_file as it is? */
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ /* do not revalidate, no si lock */
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ err = finfo->fi_h_vm_ops->fault(vma, vmf);
++ /* todo: necessary? */
++ /* file->f_ra = h_file->f_ra; */
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++#if 0 /* def CONFIG_SMP */
++ /* wake_up_nr(&wq, online_cpu - 1); */
++ wake_up_all(&wq);
++#else
++ wake_up(&wq);
++#endif
++
++ return err;
++}
++
++static int aufs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
++{
++ int err;
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ err = finfo->fi_h_vm_ops->page_mkwrite(vma, page);
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++ wake_up(&wq);
++
++ return err;
++}
++
++static void aufs_vm_close(struct vm_area_struct *vma)
++{
++ static DECLARE_WAIT_QUEUE_HEAD(wq);
++ struct file *file, *h_file;
++ struct au_finfo *finfo;
++
++ wait_event(wq, (file = au_safe_file(vma)));
++
++ finfo = au_fi(file);
++ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++ AuDebugOn(!h_file || !au_test_mmapped(file));
++
++ fi_write_lock(file);
++ vma->vm_file = h_file;
++ finfo->fi_h_vm_ops->close(vma);
++ au_reset_file(vma, file);
++ fi_write_unlock(file);
++ wake_up(&wq);
++}
++
++static struct vm_operations_struct aufs_vm_ops = {
++ /* .close and .page_mkwrite are not set by default */
++ .fault = aufs_fault,
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct vm_operations_struct *au_vm_ops(struct file *h_file,
++ struct vm_area_struct *vma)
++{
++ struct vm_operations_struct *vm_ops;
++ int err;
++
++ vm_ops = ERR_PTR(-ENODEV);
++ if (!h_file->f_op || !h_file->f_op->mmap)
++ goto out;
++
++ err = h_file->f_op->mmap(h_file, vma);
++ vm_ops = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ vm_ops = vma->vm_ops;
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (unlikely(err)) {
++ AuIOErr("failed internal unmapping %.*s, %d\n",
++ AuDLNPair(h_file->f_dentry), err);
++ vm_ops = ERR_PTR(-EIO);
++ }
++
++ out:
++ return vm_ops;
++}
++
++static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
++{
++ int err;
++ struct vm_operations_struct *h_ops;
++
++ err = 0;
++ h_ops = finfo->fi_h_vm_ops;
++ AuDebugOn(!h_ops);
++ if ((!h_ops->page_mkwrite && !h_ops->close)
++ || finfo->fi_vm_ops)
++ goto out;
++
++ err = -ENOMEM;
++ finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
++ if (unlikely(!finfo->fi_vm_ops))
++ goto out;
++
++ err = 0;
++ if (h_ops->page_mkwrite)
++ finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
++ if (h_ops->close)
++ finfo->fi_vm_ops->close = aufs_vm_close;
++
++ vma->vm_ops = finfo->fi_vm_ops;
++
++ out:
++ return err;
++}
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err;
++ unsigned char wlock, mmapped;
++ struct dentry *dentry;
++ struct super_block *sb;
++ struct file *h_file;
++ struct vm_operations_struct *vm_ops;
++
++ dentry = file->f_dentry;
++ mmapped = !!au_test_mmapped(file); /* can be harmless race condition */
++ wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped);
++ if (unlikely(err))
++ goto out;
++
++ if (wlock) {
++ struct au_pin pin;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++ au_unpin(&pin);
++ } else if (!mmapped)
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
++ /*
++ * by this assignment, f_mapping will differs from aufs inode
++ * i_mapping.
++ * if someone else mixes the use of f_dentry->d_inode and
++ * f_mapping->host, then a problem may arise.
++ */
++ file->f_mapping = h_file->f_mapping;
++ }
++
++ vm_ops = NULL;
++ if (!mmapped) {
++ vm_ops = au_vm_ops(h_file, vma);
++ err = PTR_ERR(vm_ops);
++ if (IS_ERR(vm_ops))
++ goto out_unlock;
++ }
++
++ /*
++ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
++ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
++ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
++ * both of the aufs file and the lower file is deny_write_access()-ed.
++ * finally I hope we can skip handlling MAP_DENYWRITE here.
++ */
++ err = generic_file_mmap(file, vma);
++ if (unlikely(err))
++ goto out_unlock;
++
++ vma->vm_ops = &aufs_vm_ops;
++ /* test again */
++ if (!au_test_mmapped(file))
++ au_fi(file)->fi_h_vm_ops = vm_ops;
++
++ err = au_custom_vm_ops(au_fi(file), vma);
++ if (unlikely(err))
++ goto out_unlock;
++
++ vfsub_file_accessed(h_file);
++ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ if (!wlock && mmapped)
++ fi_read_unlock(file);
++ else
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static unsigned int aufs_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask;
++ int err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ /* We should pretend an error happened. */
++ mask = POLLERR /* | POLLIN | POLLOUT */;
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ /* it is not an error if h_file has no operation */
++ mask = DEFAULT_POLLMASK;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->poll)
++ mask = h_file->f_op->poll(h_file, wait);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ AuTraceErr((int)mask);
++ return mask;
++}
++
++static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
++ int datasync)
++{
++ int err;
++ struct au_pin pin;
++ struct inode *inode;
++ struct file *h_file;
++ struct super_block *sb;
++
++ inode = dentry->d_inode;
++ IMustLock(file->f_mapping->host);
++ if (inode != file->f_mapping->host) {
++ mutex_unlock(&file->f_mapping->host->i_mutex);
++ mutex_lock(&inode->i_mutex);
++ }
++ IMustLock(inode);
++
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ err = 0; /* -EBADF; */ /* posix? */
++ if (unlikely(!(file->f_mode & FMODE_WRITE)))
++ goto out;
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++ if (unlikely(err))
++ goto out;
++
++ err = au_ready_to_write(file, -1, &pin);
++ di_downgrade_lock(dentry, AuLock_IR);
++ if (unlikely(err))
++ goto out_unlock;
++ au_unpin(&pin);
++
++ err = -EINVAL;
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->fsync) {
++ struct dentry *h_d;
++ struct mutex *h_mtx;
++
++ /*
++ * no filemap_fdatawrite() since aufs file has no its own
++ * mapping, but dir.
++ */
++ h_d = h_file->f_dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = h_file->f_op->fsync(h_file, h_d, datasync);
++ if (!err)
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++ /*ignore*/
++ au_cpup_attr_timesizes(inode);
++ mutex_unlock(h_mtx);
++ }
++
++ out_unlock:
++ di_read_unlock(dentry, AuLock_IR);
++ fi_write_unlock(file);
++ out:
++ si_read_unlock(sb);
++ if (inode != file->f_mapping->host) {
++ mutex_unlock(&inode->i_mutex);
++ mutex_lock(&file->f_mapping->host->i_mutex);
++ }
++ return err;
++}
++
++static int aufs_fasync(int fd, struct file *file, int flag)
++{
++ int err;
++ struct file *h_file;
++ struct dentry *dentry;
++ struct super_block *sb;
++
++ dentry = file->f_dentry;
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++ if (unlikely(err))
++ goto out;
++
++ h_file = au_h_fptr(file, au_fbstart(file));
++ if (h_file->f_op && h_file->f_op->fasync)
++ err = h_file->f_op->fasync(fd, h_file, flag);
++
++ di_read_unlock(dentry, AuLock_IR);
++ fi_read_unlock(file);
++
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_file_fop = {
++ /*
++ * while generic_file_llseek/_unlocked() don't use BKL,
++ * don't use it since it operates file->f_mapping->host.
++ * in aufs, it may be a real file and may confuse users by UDBA.
++ */
++ /* .llseek = generic_file_llseek, */
++
++ .read = aufs_read,
++ .write = aufs_write,
++ .poll = aufs_poll,
++ .mmap = aufs_mmap,
++ .open = aufs_open_nondir,
++ .flush = aufs_flush,
++ .release = aufs_release_nondir,
++ .fsync = aufs_fsync_nondir,
++ .fasync = aufs_fasync,
++ .splice_write = aufs_splice_write,
++ .splice_read = aufs_splice_read
++};
+diff -Naur a/fs/aufs/fstype.h b/fs/aufs/fstype.h
+--- a/fs/aufs/fstype.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/fstype.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,474 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * judging filesystem type
++ */
++
++#ifndef __AUFS_FSTYPE_H__
++#define __AUFS_FSTYPE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/cramfs_fs.h>
++#include <linux/fs.h>
++#include <linux/magic.h>
++#include <linux/romfs_fs.h>
++#include <linux/aufs_type.h>
++
++static inline int au_test_aufs(struct super_block *sb)
++{
++ return sb->s_magic == AUFS_SUPER_MAGIC;
++}
++
++static inline const char *au_sbtype(struct super_block *sb)
++{
++ return sb->s_type->name;
++}
++
++static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
++ return sb->s_magic == ROMFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_romfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
++ return sb->s_magic == ISOFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
++ return sb->s_magic == CRAMFS_MAGIC;
++#endif
++ return 0;
++}
++
++static inline int au_test_nfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++ return sb->s_magic == NFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_fuse(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
++ return sb->s_magic == FUSE_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_xfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
++ return sb->s_magic == XFS_SB_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_TMPFS
++ return sb->s_magic == TMPFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "ecryptfs");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
++ return sb->s_magic == SMB_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
++ return sb->s_magic == OCFS2_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
++ return sb->s_magic == DLMFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_coda(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
++ return sb->s_magic == CODA_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
++ return sb->s_magic == V9FS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ext4(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
++ return sb->s_magic == EXT4_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_sysv(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
++ return !strcmp(au_sbtype(sb), "sysv");
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_ramfs(struct super_block *sb)
++{
++ return sb->s_magic == RAMFS_MAGIC;
++}
++
++static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
++ return sb->s_magic == UBIFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_procfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_PROC_FS
++ return sb->s_magic == PROC_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SYSFS
++ return sb->s_magic == SYSFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_configfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
++ return sb->s_magic == CONFIGFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_minix(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
++ return sb->s_magic == MINIX3_SUPER_MAGIC
++ || sb->s_magic == MINIX2_SUPER_MAGIC
++ || sb->s_magic == MINIX2_SUPER_MAGIC2
++ || sb->s_magic == MINIX_SUPER_MAGIC
++ || sb->s_magic == MINIX_SUPER_MAGIC2;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_cifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
++ return sb->s_magic == CIFS_MAGIC_NUMBER;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_fat(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
++ return sb->s_magic == MSDOS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_msdos(struct super_block *sb)
++{
++ return au_test_fat(sb);
++}
++
++static inline int au_test_vfat(struct super_block *sb)
++{
++ return au_test_fat(sb);
++}
++
++static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SECURITYFS
++ return sb->s_magic == SECURITYFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
++ return sb->s_magic == SQUASHFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
++ return sb->s_magic == BTRFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
++ return sb->s_magic == XENFS_SUPER_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_DEBUG_FS
++ return sb->s_magic == DEBUGFS_MAGIC;
++#else
++ return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * they can't be an aufs branch.
++ */
++static inline int au_test_fs_unsuppoted(struct super_block *sb)
++{
++ return
++#ifndef CONFIG_AUFS_BR_RAMFS
++ au_test_ramfs(sb) ||
++#endif
++ au_test_procfs(sb)
++ || au_test_sysfs(sb)
++ || au_test_configfs(sb)
++ || au_test_debugfs(sb)
++ || au_test_securityfs(sb)
++ || au_test_xenfs(sb)
++ /* || !strcmp(au_sbtype(sb), "unionfs") */
++ || au_test_aufs(sb); /* will be supported in next version */
++}
++
++/*
++ * If the filesystem supports NFS-export, then it has to support NULL as
++ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
++ * We can apply this principle when we handle a lower filesystem.
++ */
++static inline int au_test_fs_null_nd(struct super_block *sb)
++{
++ return !!sb->s_export_op;
++}
++
++static inline int au_test_fs_remote(struct super_block *sb)
++{
++ return !au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ && !au_test_ramfs(sb)
++#endif
++ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * Note: these functions (below) are created after reading ->getattr() in all
++ * filesystems under linux/fs. it means we have to do so in every update...
++ */
++
++/*
++ * some filesystems require getattr to refresh the inode attributes before
++ * referencing.
++ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
++ * and leave the work for d_revalidate()
++ */
++static inline int au_test_fs_refresh_iattr(struct super_block *sb)
++{
++ return au_test_nfs(sb)
++ || au_test_fuse(sb)
++ /* || au_test_smbfs(sb) */ /* untested */
++ /* || au_test_ocfs2(sb) */ /* untested */
++ /* || au_test_btrfs(sb) */ /* untested */
++ /* || au_test_coda(sb) */ /* untested */
++ /* || au_test_v9fs(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which don't maintain i_size or i_blocks.
++ */
++static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
++{
++ return au_test_xfs(sb)
++ /* || au_test_ext4(sb) */ /* untested */
++ /* || au_test_ocfs2(sb) */ /* untested */
++ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
++ /* || au_test_sysv(sb) */ /* untested */
++ /* || au_test_ubifs(sb) */ /* untested */
++ /* || au_test_minix(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which don't store the correct value in some of their inode
++ * attributes.
++ */
++static inline int au_test_fs_bad_iattr(struct super_block *sb)
++{
++ return au_test_fs_bad_iattr_size(sb)
++ /* || au_test_cifs(sb) */ /* untested */
++ || au_test_fat(sb)
++ || au_test_msdos(sb)
++ || au_test_vfat(sb);
++}
++
++/* they don't check i_nlink in link(2) */
++static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
++{
++ return au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ || au_test_ramfs(sb)
++#endif
++ || au_test_ubifs(sb);
++}
++
++/*
++ * filesystems which sets S_NOATIME and S_NOCMTIME.
++ */
++static inline int au_test_fs_notime(struct super_block *sb)
++{
++ return au_test_nfs(sb)
++ || au_test_fuse(sb)
++ || au_test_ubifs(sb)
++ /* || au_test_cifs(sb) */ /* untested */
++ ;
++}
++
++/*
++ * filesystems which requires replacing i_mapping.
++ */
++static inline int au_test_fs_bad_mapping(struct super_block *sb)
++{
++ return au_test_fuse(sb)
++ || au_test_ubifs(sb);
++}
++
++/* temporary support for i#1 in cramfs */
++static inline int au_test_fs_unique_ino(struct inode *inode)
++{
++ if (au_test_cramfs(inode->i_sb))
++ return inode->i_ino != 1;
++ return 1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the filesystem where the xino files placed must support i/o after unlink and
++ * maintain i_size and i_blocks.
++ */
++static inline int au_test_fs_bad_xino(struct super_block *sb)
++{
++ return au_test_fs_remote(sb)
++ || au_test_fs_bad_iattr_size(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
++#else
++ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
++#endif
++ /* don't want unnecessary work for xino */
++ || au_test_aufs(sb)
++ || au_test_ecryptfs(sb);
++}
++
++static inline int au_test_fs_trunc_xino(struct super_block *sb)
++{
++ return au_test_tmpfs(sb)
++ || au_test_ramfs(sb);
++}
++
++/*
++ * test if the @sb is real-readonly.
++ */
++static inline int au_test_fs_rr(struct super_block *sb)
++{
++ return au_test_squashfs(sb)
++ || au_test_iso9660(sb)
++ || au_test_cramfs(sb)
++ || au_test_romfs(sb);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FSTYPE_H__ */
+diff -Naur a/fs/aufs/hinotify.c b/fs/aufs/hinotify.c
+--- a/fs/aufs/hinotify.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/hinotify.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,755 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inotify for the lower directories
++ */
++
++#include "aufs.h"
++
++static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
++static struct inotify_handle *au_hin_handle;
++
++AuCacheFuncs(hinotify, HINOTIFY);
++
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++ struct inode *h_inode)
++{
++ int err;
++ struct au_hinotify *hin;
++ s32 wd;
++
++ err = -ENOMEM;
++ hin = au_cache_alloc_hinotify();
++ if (hin) {
++ AuDebugOn(hinode->hi_notify);
++ hinode->hi_notify = hin;
++ hin->hin_aufs_inode = inode;
++
++ inotify_init_watch(&hin->hin_watch);
++ wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
++ AuHinMask);
++ if (wd >= 0)
++ return 0; /* success */
++
++ err = wd;
++ put_inotify_watch(&hin->hin_watch);
++ au_cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++
++ return err;
++}
++
++void au_hin_free(struct au_hinode *hinode)
++{
++ int err;
++ struct au_hinotify *hin;
++
++ hin = hinode->hi_notify;
++ if (hin) {
++ err = 0;
++ if (atomic_read(&hin->hin_watch.count))
++ err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
++ if (unlikely(err))
++ /* it means the watch is already removed */
++ AuWarn("failed inotify_rm_watch() %d\n", err);
++ au_cache_free_hinotify(hin);
++ hinode->hi_notify = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_hin_ctl(struct au_hinode *hinode, int do_set)
++{
++ struct inode *h_inode;
++ struct inotify_watch *watch;
++
++ if (!hinode->hi_notify)
++ return;
++
++ h_inode = hinode->hi_inode;
++ IMustLock(h_inode);
++
++ /* todo: try inotify_find_update_watch()? */
++ watch = &hinode->hi_notify->hin_watch;
++ mutex_lock(&h_inode->inotify_mutex);
++ /* mutex_lock(&watch->ih->mutex); */
++ if (do_set) {
++ AuDebugOn(watch->mask & AuHinMask);
++ watch->mask |= AuHinMask;
++ } else {
++ AuDebugOn(!(watch->mask & AuHinMask));
++ watch->mask &= ~AuHinMask;
++ }
++ /* mutex_unlock(&watch->ih->mutex); */
++ mutex_unlock(&h_inode->inotify_mutex);
++}
++
++void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++ aufs_bindex_t bindex, bend;
++ struct inode *hi;
++ struct dentry *iwhdentry;
++
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++ hi = au_h_iptr(inode, bindex);
++ if (!hi)
++ continue;
++
++ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
++ iwhdentry = au_hi_wh(inode, bindex);
++ if (iwhdentry)
++ dget(iwhdentry);
++ au_igrab(hi);
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ au_set_h_iptr(inode, bindex, au_igrab(hi),
++ flags & ~AuHi_XINO);
++ iput(hi);
++ dput(iwhdentry);
++ /* mutex_unlock(&hi->i_mutex); */
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int hin_xino(struct inode *inode, struct inode *h_inode)
++{
++ int err;
++ aufs_bindex_t bindex, bend, bfound, bstart;
++ struct inode *h_i;
++
++ err = 0;
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("branch root dir was changed\n");
++ goto out;
++ }
++
++ bfound = -1;
++ bend = au_ibend(inode);
++ bstart = au_ibstart(inode);
++#if 0 /* reserved for future use */
++ if (bindex == bend) {
++ /* keep this ino in rename case */
++ goto out;
++ }
++#endif
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (au_h_iptr(inode, bindex) == h_inode) {
++ bfound = bindex;
++ break;
++ }
++ }
++ if (bfound < 0)
++ goto out;
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ h_i = au_h_iptr(inode, bindex);
++ if (!h_i)
++ continue;
++
++ err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino, 0);
++ /* ignore this error */
++ /* bad action? */
++ }
++
++ /* children inode number will be broken */
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int hin_gen_tree(struct dentry *dentry)
++{
++ int err, i, j, ndentry;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++
++ err = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
++ if (unlikely(err))
++ goto out_dpages;
++
++ for (i = 0; i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ if (IS_ROOT(d))
++ continue;
++
++ d_drop(d);
++ au_digen_dec(d);
++ if (d->d_inode)
++ /* todo: reset children xino?
++ cached children only? */
++ au_iigen_dec(d->d_inode);
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++
++ /* discard children */
++ dentry_unhash(dentry);
++ dput(dentry);
++ out:
++ return err;
++}
++
++/*
++ * return 0 if processed.
++ */
++static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
++ const unsigned int isdir)
++{
++ int err;
++ struct dentry *d;
++ struct qstr *dname;
++
++ err = 1;
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("branch root dir was changed\n");
++ err = 0;
++ goto out;
++ }
++
++ if (!isdir) {
++ AuDebugOn(!name);
++ au_iigen_dec(inode);
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &inode->i_dentry, d_alias) {
++ dname = &d->d_name;
++ if (dname->len != nlen
++ && memcmp(dname->name, name, nlen))
++ continue;
++ err = 0;
++ spin_lock(&d->d_lock);
++ __d_drop(d);
++ au_digen_dec(d);
++ spin_unlock(&d->d_lock);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ } else {
++ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
++ d = d_find_alias(inode);
++ if (!d) {
++ au_iigen_dec(inode);
++ goto out;
++ }
++
++ dname = &d->d_name;
++ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
++ err = hin_gen_tree(d);
++ dput(d);
++ }
++
++ out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
++{
++ int err;
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ if (IS_ROOT(dentry)
++ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
++ ) {
++ AuWarn("branch root dir was changed\n");
++ return 0;
++ }
++
++ err = 0;
++ if (!isdir) {
++ d_drop(dentry);
++ au_digen_dec(dentry);
++ if (inode)
++ au_iigen_dec(inode);
++ } else {
++ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
++ if (inode)
++ err = hin_gen_tree(dentry);
++ }
++
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* hinotify job flags */
++#define AuHinJob_XINO0 1
++#define AuHinJob_GEN (1 << 1)
++#define AuHinJob_DIRENT (1 << 2)
++#define AuHinJob_ISDIR (1 << 3)
++#define AuHinJob_TRYXINO0 (1 << 4)
++#define AuHinJob_MNTPNT (1 << 5)
++#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name)
++#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; }
++#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; }
++
++struct hin_job_args {
++ unsigned int flags;
++ struct inode *inode, *h_inode, *dir, *h_dir;
++ struct dentry *dentry;
++ char *h_name;
++ int h_nlen;
++};
++
++static int hin_job(struct hin_job_args *a)
++{
++ const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
++
++ /* reset xino */
++ if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
++ hin_xino(a->inode, a->h_inode); /* ignore this error */
++
++ if (au_ftest_hinjob(a->flags, TRYXINO0)
++ && a->inode
++ && a->h_inode) {
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ if (!a->h_inode->i_nlink)
++ hin_xino(a->inode, a->h_inode); /* ignore this error */
++ mutex_unlock(&a->h_inode->i_mutex);
++ }
++
++ /* make the generation obsolete */
++ if (au_ftest_hinjob(a->flags, GEN)) {
++ int err = -1;
++ if (a->inode)
++ err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
++ isdir);
++ if (err && a->dentry)
++ hin_gen_by_name(a->dentry, isdir);
++ /* ignore this error */
++ }
++
++ /* make dir entries obsolete */
++ if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
++ struct au_vdir *vdir;
++
++ vdir = au_ivdir(a->inode);
++ if (vdir)
++ vdir->vd_jiffy = 0;
++ /* IMustLock(a->inode); */
++ /* a->inode->i_version++; */
++ }
++
++ /* can do nothing but warn */
++ if (au_ftest_hinjob(a->flags, MNTPNT)
++ && a->dentry
++ && d_mountpoint(a->dentry))
++ AuWarn("mount-point %.*s is removed or renamed\n",
++ AuDLNPair(a->dentry));
++
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static char *in_name(u32 mask)
++{
++#ifdef CONFIG_AUFS_DEBUG
++#define test_ret(flag) if (mask & flag) \
++ return #flag;
++ test_ret(IN_ACCESS);
++ test_ret(IN_MODIFY);
++ test_ret(IN_ATTRIB);
++ test_ret(IN_CLOSE_WRITE);
++ test_ret(IN_CLOSE_NOWRITE);
++ test_ret(IN_OPEN);
++ test_ret(IN_MOVED_FROM);
++ test_ret(IN_MOVED_TO);
++ test_ret(IN_CREATE);
++ test_ret(IN_DELETE);
++ test_ret(IN_DELETE_SELF);
++ test_ret(IN_MOVE_SELF);
++ test_ret(IN_UNMOUNT);
++ test_ret(IN_Q_OVERFLOW);
++ test_ret(IN_IGNORED);
++ return "";
++#undef test_ret
++#else
++ return "??";
++#endif
++}
++
++static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
++ struct inode *dir)
++{
++ struct dentry *dentry, *d, *parent;
++ struct qstr *dname;
++
++ parent = d_find_alias(dir);
++ if (!parent)
++ return NULL;
++
++ dentry = NULL;
++ spin_lock(&dcache_lock);
++ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
++ /* AuDbg("%.*s\n", AuDLNPair(d)); */
++ dname = &d->d_name;
++ if (dname->len != nlen || memcmp(dname->name, name, nlen))
++ continue;
++ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
++ spin_lock(&d->d_lock);
++ __d_drop(d);
++ spin_unlock(&d->d_lock);
++ continue;
++ }
++
++ dentry = dget(d);
++ break;
++ }
++ spin_unlock(&dcache_lock);
++ dput(parent);
++
++ if (dentry)
++ di_write_lock_child(dentry);
++
++ return dentry;
++}
++
++static struct inode *lookup_wlock_by_ino(struct super_block *sb,
++ aufs_bindex_t bindex, ino_t h_ino)
++{
++ struct inode *inode;
++ ino_t ino;
++ int err;
++
++ inode = NULL;
++ err = au_xino_read(sb, bindex, h_ino, &ino);
++ if (!err && ino)
++ inode = ilookup(sb, ino);
++ if (!inode)
++ goto out;
++
++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++ AuWarn("wrong root branch\n");
++ iput(inode);
++ inode = NULL;
++ goto out;
++ }
++
++ ii_write_lock_child(inode);
++
++ out:
++ return inode;
++}
++
++enum { CHILD, PARENT };
++struct postproc_args {
++ struct inode *h_dir, *dir, *h_child_inode;
++ u32 mask;
++ unsigned int flags[2];
++ unsigned int h_child_nlen;
++ char h_child_name[];
++};
++
++static void postproc(void *_args)
++{
++ struct postproc_args *a = _args;
++ struct super_block *sb;
++ aufs_bindex_t bindex, bend, bfound;
++ unsigned char xino, try_iput;
++ int err;
++ struct inode *inode;
++ ino_t h_ino;
++ struct hin_job_args args;
++ struct dentry *dentry;
++ struct au_sbinfo *sbinfo;
++
++ AuDebugOn(!_args);
++ AuDebugOn(!a->h_dir);
++ AuDebugOn(!a->dir);
++ AuDebugOn(!a->mask);
++ AuDbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
++ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++ a->h_child_inode ? a->h_child_inode->i_ino : 0);
++
++ inode = NULL;
++ dentry = NULL;
++ /*
++ * do not lock a->dir->i_mutex here
++ * because of d_revalidate() may cause a deadlock.
++ */
++ sb = a->dir->i_sb;
++ AuDebugOn(!sb);
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!sbinfo);
++ /* big aufs lock */
++ si_noflush_write_lock(sb);
++
++ ii_read_lock_parent(a->dir);
++ bfound = -1;
++ bend = au_ibend(a->dir);
++ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
++ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
++ bfound = bindex;
++ break;
++ }
++ ii_read_unlock(a->dir);
++ if (unlikely(bfound < 0))
++ goto out;
++
++ xino = !!au_opt_test(au_mntflags(sb), XINO);
++ h_ino = 0;
++ if (a->h_child_inode)
++ h_ino = a->h_child_inode->i_ino;
++
++ if (a->h_child_nlen
++ && (au_ftest_hinjob(a->flags[CHILD], GEN)
++ || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
++ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
++ a->dir);
++ try_iput = 0;
++ if (dentry)
++ inode = dentry->d_inode;
++ if (xino && !inode && h_ino
++ && (au_ftest_hinjob(a->flags[CHILD], XINO0)
++ || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
++ || au_ftest_hinjob(a->flags[CHILD], GEN))) {
++ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
++ try_iput = 1;
++ }
++
++ args.flags = a->flags[CHILD];
++ args.dentry = dentry;
++ args.inode = inode;
++ args.h_inode = a->h_child_inode;
++ args.dir = a->dir;
++ args.h_dir = a->h_dir;
++ args.h_name = a->h_child_name;
++ args.h_nlen = a->h_child_nlen;
++ err = hin_job(&args);
++ if (dentry) {
++ if (dentry->d_fsdata)
++ di_write_unlock(dentry);
++ dput(dentry);
++ }
++ if (inode && try_iput) {
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++
++ ii_write_lock_parent(a->dir);
++ args.flags = a->flags[PARENT];
++ args.dentry = NULL;
++ args.inode = a->dir;
++ args.h_inode = a->h_dir;
++ args.dir = NULL;
++ args.h_dir = NULL;
++ args.h_name = NULL;
++ args.h_nlen = 0;
++ err = hin_job(&args);
++ ii_write_unlock(a->dir);
++
++ out:
++ au_nwt_done(&sbinfo->si_nowait);
++ si_write_unlock(sb);
++
++ iput(a->h_child_inode);
++ iput(a->h_dir);
++ iput(a->dir);
++ kfree(a);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
++ u32 mask, u32 cookie __maybe_unused,
++ const char *h_child_name, struct inode *h_child_inode)
++{
++ struct au_hinotify *hinotify;
++ struct postproc_args *args;
++ int len, wkq_err;
++ unsigned char isdir, isroot, wh;
++ char *p;
++ struct inode *dir;
++ unsigned int flags[2];
++
++ /* if IN_UNMOUNT happens, there must be another bug */
++ AuDebugOn(mask & IN_UNMOUNT);
++ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++ put_inotify_watch(watch);
++ return;
++ }
++#ifdef AuDbgHinotify
++ au_debug(1);
++ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
++ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
++ " hi%lu\n",
++ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++ h_child_name ? h_child_name : "",
++ h_child_inode ? h_child_inode->i_ino : 0);
++ WARN_ON(1);
++ }
++ au_debug(0);
++#endif
++
++ hinotify = container_of(watch, struct au_hinotify, hin_watch);
++ AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
++ dir = igrab(hinotify->hin_aufs_inode);
++ if (!dir)
++ return;
++
++ isroot = (dir->i_ino == AUFS_ROOT_INO);
++ len = 0;
++ wh = 0;
++ if (h_child_name) {
++ len = strlen(h_child_name);
++ if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ h_child_name += AUFS_WH_PFX_LEN;
++ len -= AUFS_WH_PFX_LEN;
++ wh = 1;
++ }
++ }
++
++ isdir = 0;
++ if (h_child_inode)
++ isdir = !!S_ISDIR(h_child_inode->i_mode);
++ flags[PARENT] = AuHinJob_ISDIR;
++ flags[CHILD] = 0;
++ if (isdir)
++ flags[CHILD] = AuHinJob_ISDIR;
++ switch (mask & IN_ALL_EVENTS) {
++ case IN_MOVED_FROM:
++ case IN_MOVED_TO:
++ AuDebugOn(!h_child_name || !h_child_inode);
++ au_fset_hinjob(flags[CHILD], GEN);
++ au_fset_hinjob(flags[CHILD], XINO0);
++ au_fset_hinjob(flags[CHILD], MNTPNT);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ break;
++
++ case IN_CREATE:
++ AuDebugOn(!h_child_name || !h_child_inode);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ au_fset_hinjob(flags[CHILD], GEN);
++ break;
++
++ case IN_DELETE:
++ /*
++ * aufs never be able to get this child inode.
++ * revalidation should be in d_revalidate()
++ * by checking i_nlink, i_generation or d_unhashed().
++ */
++ AuDebugOn(!h_child_name);
++ au_fset_hinjob(flags[PARENT], DIRENT);
++ au_fset_hinjob(flags[CHILD], GEN);
++ au_fset_hinjob(flags[CHILD], TRYXINO0);
++ au_fset_hinjob(flags[CHILD], MNTPNT);
++ break;
++
++ default:
++ AuDebugOn(1);
++ }
++
++ if (wh)
++ h_child_inode = NULL;
++
++ /* iput() and kfree() will be called in postproc() */
++ /*
++ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
++ * iprune_mutex. strange.
++ */
++ lockdep_off();
++ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
++ lockdep_on();
++ if (unlikely(!args)) {
++ AuErr1("no memory\n");
++ iput(dir);
++ return;
++ }
++ args->flags[PARENT] = flags[PARENT];
++ args->flags[CHILD] = flags[CHILD];
++ args->mask = mask;
++ args->dir = dir;
++ args->h_dir = igrab(watch->inode);
++ if (h_child_inode)
++ h_child_inode = igrab(h_child_inode); /* can be NULL */
++ args->h_child_inode = h_child_inode;
++ args->h_child_nlen = len;
++ if (len) {
++ p = (void *)args;
++ p += sizeof(*args);
++ memcpy(p, h_child_name, len + 1);
++ }
++
++ lockdep_off();
++ wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
++ lockdep_on();
++ if (unlikely(wkq_err))
++ AuErr("wkq %d\n", wkq_err);
++}
++
++static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
++{
++ return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++ .handle_event = aufs_inotify,
++ .destroy_watch = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++static void au_hin_destroy_cache(void)
++{
++ kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
++ au_cachep[AuCache_HINOTIFY] = NULL;
++}
++
++int __init au_hinotify_init(void)
++{
++ int err;
++
++ err = -ENOMEM;
++ au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
++ if (au_cachep[AuCache_HINOTIFY]) {
++ err = 0;
++ au_hin_handle = inotify_init(&aufs_inotify_ops);
++ if (IS_ERR(au_hin_handle)) {
++ err = PTR_ERR(au_hin_handle);
++ au_hin_destroy_cache();
++ }
++ }
++ AuTraceErr(err);
++ return err;
++}
++
++void au_hinotify_fin(void)
++{
++ inotify_destroy(au_hin_handle);
++ if (au_cachep[AuCache_HINOTIFY])
++ au_hin_destroy_cache();
++}
+diff -Naur a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
+--- a/fs/aufs/iinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/iinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,271 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode private data
++ */
++
++#include "aufs.h"
++
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct inode *h_inode;
++
++ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++ return h_inode;
++}
++
++/* todo: hard/soft set? */
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct au_iinfo *iinfo = au_ii(inode);
++ struct inode *h_inode;
++
++ iinfo->ii_bstart = bindex;
++ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
++ if (h_inode)
++ au_cpup_igen(inode, h_inode);
++}
++
++void au_hiput(struct au_hinode *hinode)
++{
++ au_hin_free(hinode);
++ dput(hinode->hi_whdentry);
++ iput(hinode->hi_inode);
++}
++
++unsigned int au_hi_flags(struct inode *inode, int isdir)
++{
++ unsigned int flags;
++ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
++
++ flags = 0;
++ if (au_opt_test(mnt_flags, XINO))
++ au_fset_hi(flags, XINO);
++ if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
++ au_fset_hi(flags, HINOTIFY);
++ return flags;
++}
++
++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags)
++{
++ struct au_hinode *hinode;
++ struct inode *hi;
++ struct au_iinfo *iinfo = au_ii(inode);
++
++ hinode = iinfo->ii_hinode + bindex;
++ hi = hinode->hi_inode;
++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++ AuDebugOn(h_inode && hi);
++
++ if (hi)
++ au_hiput(hinode);
++ hinode->hi_inode = h_inode;
++ if (h_inode) {
++ int err;
++ struct super_block *sb = inode->i_sb;
++ struct au_branch *br;
++
++ if (bindex == iinfo->ii_bstart)
++ au_cpup_igen(inode, h_inode);
++ br = au_sbr(sb, bindex);
++ hinode->hi_id = br->br_id;
++ if (au_ftest_hi(flags, XINO)) {
++ err = au_xino_write(sb, bindex, h_inode->i_ino,
++ inode->i_ino);
++ if (unlikely(err))
++ AuIOErr1("failed au_xino_write() %d\n", err);
++ }
++
++ if (au_ftest_hi(flags, HINOTIFY)
++ && au_br_hinotifyable(br->br_perm)) {
++ err = au_hin_alloc(hinode, inode, h_inode);
++ if (unlikely(err))
++ AuIOErr1("au_hin_alloc() %d\n", err);
++ }
++ }
++}
++
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_wh)
++{
++ struct au_hinode *hinode;
++
++ hinode = au_ii(inode)->ii_hinode + bindex;
++ AuDebugOn(hinode->hi_whdentry);
++ hinode->hi_whdentry = h_wh;
++}
++
++void au_update_iigen(struct inode *inode)
++{
++ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
++ /* smp_mb(); */ /* atomic_set */
++}
++
++/* it may be called at remount time, too */
++void au_update_brange(struct inode *inode, int do_put_zero)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = au_ii(inode);
++ if (!iinfo || iinfo->ii_bstart < 0)
++ return;
++
++ if (do_put_zero) {
++ aufs_bindex_t bindex;
++
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++) {
++ struct inode *h_i;
++
++ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
++ if (h_i && !h_i->i_nlink)
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ }
++ }
++
++ iinfo->ii_bstart = -1;
++ while (++iinfo->ii_bstart <= iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
++ break;
++ if (iinfo->ii_bstart > iinfo->ii_bend) {
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ return;
++ }
++
++ iinfo->ii_bend++;
++ while (0 <= --iinfo->ii_bend)
++ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
++ break;
++ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_iinfo_init(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++ struct super_block *sb;
++ int nbr, i;
++
++ sb = inode->i_sb;
++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++ nbr = au_sbend(sb) + 1;
++ if (unlikely(nbr <= 0))
++ nbr = 1;
++ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
++ if (iinfo->ii_hinode) {
++ for (i = 0; i < nbr; i++)
++ iinfo->ii_hinode[i].hi_id = -1;
++
++ atomic_set(&iinfo->ii_generation, au_sigen(sb));
++ /* smp_mb(); */ /* atomic_set */
++ init_rwsem(&iinfo->ii_rwsem);
++ iinfo->ii_bstart = -1;
++ iinfo->ii_bend = -1;
++ iinfo->ii_vdir = NULL;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
++{
++ int err, sz;
++ struct au_hinode *hip;
++
++ err = -ENOMEM;
++ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
++ if (!sz)
++ sz = sizeof(*hip);
++ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
++ if (hip) {
++ iinfo->ii_hinode = hip;
++ err = 0;
++ }
++
++ return err;
++}
++
++static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
++ ino_t ino)
++{
++ int err;
++ aufs_bindex_t bindex;
++ unsigned char locked;
++
++ err = 0;
++ locked = !!si_noflush_read_trylock(sb);
++ bindex = au_br_index(sb, hinode->hi_id);
++ if (bindex >= 0)
++ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
++ /* error action? */
++ if (locked)
++ si_read_unlock(sb);
++ return err;
++}
++
++void au_iinfo_fin(struct inode *inode)
++{
++ ino_t ino;
++ aufs_bindex_t bend;
++ unsigned char unlinked = !inode->i_nlink;
++ struct au_iinfo *iinfo;
++ struct au_hinode *hi;
++ struct super_block *sb;
++
++ if (unlinked) {
++ int err = au_xigen_inc(inode);
++ if (unlikely(err))
++ AuWarn1("failed resetting i_generation, %d\n", err);
++ }
++
++ iinfo = au_ii(inode);
++ /* bad_inode case */
++ if (!iinfo)
++ return;
++
++ if (iinfo->ii_vdir)
++ au_vdir_free(iinfo->ii_vdir);
++
++ if (iinfo->ii_bstart >= 0) {
++ sb = inode->i_sb;
++ ino = 0;
++ if (unlinked)
++ ino = inode->i_ino;
++ hi = iinfo->ii_hinode + iinfo->ii_bstart;
++ bend = iinfo->ii_bend;
++ while (iinfo->ii_bstart++ <= bend) {
++ if (hi->hi_inode) {
++ if (unlinked || !hi->hi_inode->i_nlink) {
++ au_iinfo_write0(sb, hi, ino);
++ /* ignore this error */
++ ino = 0;
++ }
++ au_hiput(hi);
++ }
++ hi++;
++ }
++ }
++
++ kfree(iinfo->ii_hinode);
++ au_rwsem_destroy(&iinfo->ii_rwsem);
++}
+diff -Naur a/fs/aufs/inode.c b/fs/aufs/inode.c
+--- a/fs/aufs/inode.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,376 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode functions
++ */
++
++#include "aufs.h"
++
++struct inode *au_igrab(struct inode *inode)
++{
++ if (inode) {
++ AuDebugOn(!atomic_read(&inode->i_count));
++ atomic_inc(&inode->i_count);
++ }
++ return inode;
++}
++
++static void au_refresh_hinode_attr(struct inode *inode, int do_version)
++{
++ au_cpup_attr_all(inode, /*force*/0);
++ au_update_iigen(inode);
++ if (do_version)
++ inode->i_version++;
++}
++
++int au_refresh_hinode_self(struct inode *inode, int do_attr)
++{
++ int err;
++ aufs_bindex_t bindex, new_bindex;
++ unsigned char update;
++ struct inode *first;
++ struct au_hinode *p, *q, tmp;
++ struct super_block *sb;
++ struct au_iinfo *iinfo;
++
++ update = 0;
++ sb = inode->i_sb;
++ iinfo = au_ii(inode);
++ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
++ if (unlikely(err))
++ goto out;
++
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ err = 0;
++ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++ bindex++, p++) {
++ if (!p->hi_inode)
++ continue;
++
++ new_bindex = au_br_index(sb, p->hi_id);
++ if (new_bindex == bindex)
++ continue;
++
++ if (new_bindex < 0) {
++ update++;
++ au_hiput(p);
++ p->hi_inode = NULL;
++ continue;
++ }
++
++ if (new_bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = new_bindex;
++ if (iinfo->ii_bend < new_bindex)
++ iinfo->ii_bend = new_bindex;
++ /* swap two lower inode, and loop again */
++ q = iinfo->ii_hinode + new_bindex;
++ tmp = *q;
++ *q = *p;
++ *p = tmp;
++ if (tmp.hi_inode) {
++ bindex--;
++ p--;
++ }
++ }
++ au_update_brange(inode, /*do_put_zero*/0);
++ if (do_attr)
++ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
++
++ out:
++ return err;
++}
++
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
++{
++ int err, update;
++ unsigned int flags;
++ aufs_bindex_t bindex, bend;
++ unsigned char isdir;
++ struct inode *first;
++ struct au_hinode *p;
++ struct au_iinfo *iinfo;
++
++ err = au_refresh_hinode_self(inode, /*do_attr*/0);
++ if (unlikely(err))
++ goto out;
++
++ update = 0;
++ iinfo = au_ii(inode);
++ p = iinfo->ii_hinode + iinfo->ii_bstart;
++ first = p->hi_inode;
++ isdir = S_ISDIR(inode->i_mode);
++ flags = au_hi_flags(inode, isdir);
++ bend = au_dbend(dentry);
++ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++ struct inode *h_i;
++ struct dentry *h_d;
++
++ h_d = au_h_dptr(dentry, bindex);
++ if (!h_d || !h_d->d_inode)
++ continue;
++
++ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
++ h_i = au_h_iptr(inode, bindex);
++ if (h_i) {
++ if (h_i == h_d->d_inode)
++ continue;
++ err = -EIO;
++ break;
++ }
++ }
++ if (bindex < iinfo->ii_bstart)
++ iinfo->ii_bstart = bindex;
++ if (iinfo->ii_bend < bindex)
++ iinfo->ii_bend = bindex;
++ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
++ update = 1;
++ }
++ au_update_brange(inode, /*do_put_zero*/0);
++
++ if (unlikely(err))
++ goto out;
++
++ au_refresh_hinode_attr(inode, update && isdir);
++
++ out:
++ return err;
++}
++
++static int set_inode(struct inode *inode, struct dentry *dentry)
++{
++ int err;
++ unsigned int flags;
++ umode_t mode;
++ aufs_bindex_t bindex, bstart, btail;
++ unsigned char isdir;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++ struct au_iinfo *iinfo;
++
++ err = 0;
++ isdir = 0;
++ bstart = au_dbstart(dentry);
++ h_inode = au_h_dptr(dentry, bstart)->d_inode;
++ mode = h_inode->i_mode;
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_iop;
++ inode->i_fop = &aufs_file_fop;
++ inode->i_mapping->a_ops = &aufs_aop;
++ break;
++ case S_IFDIR:
++ isdir = 1;
++ btail = au_dbtaildir(dentry);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ break;
++ case S_IFLNK:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_symlink_iop;
++ break;
++ case S_IFBLK:
++ case S_IFCHR:
++ case S_IFIFO:
++ case S_IFSOCK:
++ btail = au_dbtail(dentry);
++ inode->i_op = &aufs_iop;
++ init_special_inode(inode, mode, h_inode->i_rdev);
++ break;
++ default:
++ AuIOErr("Unknown file type 0%o\n", mode);
++ err = -EIO;
++ goto out;
++ }
++
++ /* do not set inotify for whiteouted dirs (SHWH mode) */
++ flags = au_hi_flags(inode, isdir);
++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
++ && au_ftest_hi(flags, HINOTIFY)
++ && dentry->d_name.len > AUFS_WH_PFX_LEN
++ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
++ au_fclr_hi(flags, HINOTIFY);
++ iinfo = au_ii(inode);
++ iinfo->ii_bstart = bstart;
++ iinfo->ii_bend = btail;
++ for (bindex = bstart; bindex <= btail; bindex++) {
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (h_dentry)
++ au_set_h_iptr(inode, bindex,
++ au_igrab(h_dentry->d_inode), flags);
++ }
++ au_cpup_attr_all(inode, /*force*/1);
++
++ out:
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct inode *h_inode, *h_dinode;
++
++ *matched = 0;
++
++ /*
++ * before this function, if aufs got any iinfo lock, it must be only
++ * one, the parent dir.
++ * it can happen by UDBA and the obsoleted inode number.
++ */
++ err = -EIO;
++ if (unlikely(inode->i_ino == parent_ino(dentry)))
++ goto out;
++
++ err = 0;
++ ii_write_lock_new_child(inode);
++ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode && h_inode == h_dinode) {
++ *matched = 1;
++ err = 0;
++ if (au_iigen(inode) != au_digen(dentry))
++ err = au_refresh_hinode(inode, dentry);
++ break;
++ }
++ }
++
++ if (unlikely(err))
++ ii_write_unlock(inode);
++ out:
++ return err;
++}
++
++/* successful returns with iinfo write_locked */
++/* todo: return with unlocked? */
++struct inode *au_new_inode(struct dentry *dentry, int must_new)
++{
++ struct inode *inode;
++ struct dentry *h_dentry;
++ struct super_block *sb;
++ ino_t h_ino, ino;
++ int err, match;
++ aufs_bindex_t bstart;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ h_dentry = au_h_dptr(dentry, bstart);
++ h_ino = h_dentry->d_inode->i_ino;
++ err = au_xino_read(sb, bstart, h_ino, &ino);
++ inode = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++ new_ino:
++ if (!ino) {
++ ino = au_xino_new_ino(sb);
++ if (unlikely(!ino)) {
++ inode = ERR_PTR(-EIO);
++ goto out;
++ }
++ }
++
++ AuDbg("i%lu\n", (unsigned long)ino);
++ inode = au_iget_locked(sb, ino);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++
++ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
++ if (inode->i_state & I_NEW) {
++ ii_write_lock_new_child(inode);
++ err = set_inode(inode, dentry);
++ unlock_new_inode(inode);
++ if (!err)
++ goto out; /* success */
++
++ iget_failed(inode);
++ ii_write_unlock(inode);
++ goto out_iput;
++ } else if (!must_new) {
++ err = reval_inode(inode, dentry, &match);
++ if (!err)
++ goto out; /* success */
++ else if (match)
++ goto out_iput;
++ }
++
++ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
++ AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
++ " b%d, %s, %.*s, hi%lu, i%lu.\n",
++ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
++ (unsigned long)h_ino, (unsigned long)ino);
++ ino = 0;
++ err = au_xino_write0(sb, bstart, h_ino, 0);
++ if (!err) {
++ iput(inode);
++ goto new_ino;
++ }
++
++ out_iput:
++ iput(inode);
++ inode = ERR_PTR(err);
++ out:
++ return inode;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode)
++{
++ int err;
++
++ err = au_br_rdonly(au_sbr(sb, bindex));
++
++ /* pseudo-link after flushed may happen out of bounds */
++ if (!err
++ && inode
++ && au_ibstart(inode) <= bindex
++ && bindex <= au_ibend(inode)) {
++ /*
++ * permission check is unnecessary since vfsub routine
++ * will be called later
++ */
++ struct inode *hi = au_h_iptr(inode, bindex);
++ if (hi)
++ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
++ }
++
++ return err;
++}
++
++int au_test_h_perm(struct inode *h_inode, int mask)
++{
++ if (!current_fsuid())
++ return 0;
++ return inode_permission(h_inode, mask);
++}
++
++int au_test_h_perm_sio(struct inode *h_inode, int mask)
++{
++ if (au_test_nfs(h_inode->i_sb)
++ && (mask & MAY_WRITE)
++ && S_ISDIR(h_inode->i_mode))
++ mask |= MAY_READ; /* force permission check */
++ return au_test_h_perm(h_inode, mask);
++}
+diff -Naur a/fs/aufs/inode.h b/fs/aufs/inode.h
+--- a/fs/aufs/inode.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,473 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations
++ */
++
++#ifndef __AUFS_INODE_H__
++#define __AUFS_INODE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/inotify.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct vfsmount;
++
++struct au_hinotify {
++#ifdef CONFIG_AUFS_HINOTIFY
++ struct inotify_watch hin_watch;
++ struct inode *hin_aufs_inode; /* no get/put */
++#endif
++};
++
++struct au_hinode {
++ struct inode *hi_inode;
++ aufs_bindex_t hi_id;
++#ifdef CONFIG_AUFS_HINOTIFY
++ struct au_hinotify *hi_notify;
++#endif
++
++ /* reference to the copied-up whiteout with get/put */
++ struct dentry *hi_whdentry;
++};
++
++struct au_vdir;
++struct au_iinfo {
++ atomic_t ii_generation;
++ struct super_block *ii_hsb1; /* no get/put */
++
++ struct rw_semaphore ii_rwsem;
++ aufs_bindex_t ii_bstart, ii_bend;
++ __u32 ii_higen;
++ struct au_hinode *ii_hinode;
++ struct au_vdir *ii_vdir;
++};
++
++struct au_icntnr {
++ struct au_iinfo iinfo;
++ struct inode vfs_inode;
++};
++
++/* au_pin flags */
++#define AuPin_DI_LOCKED 1
++#define AuPin_MNT_WRITE (1 << 1)
++#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
++#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
++#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
++
++struct au_pin {
++ /* input */
++ struct dentry *dentry;
++ unsigned int udba;
++ unsigned char lsc_di, lsc_hi, flags;
++ aufs_bindex_t bindex;
++
++ /* output */
++ struct dentry *parent;
++ struct au_hinode *hdir;
++ struct vfsmount *h_mnt;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_iinfo *au_ii(struct inode *inode)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++ if (iinfo->ii_hinode)
++ return iinfo;
++ return NULL; /* debugging bad_inode case */
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* inode.c */
++struct inode *au_igrab(struct inode *inode);
++int au_refresh_hinode_self(struct inode *inode, int do_attr);
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
++struct inode *au_new_inode(struct dentry *dentry, int must_new);
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++ struct inode *inode);
++int au_test_h_perm(struct inode *h_inode, int mask);
++int au_test_h_perm_sio(struct inode *h_inode, int mask);
++
++/* i_op.c */
++extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
++
++/* au_wr_dir flags */
++#define AuWrDir_ADD_ENTRY 1
++#define AuWrDir_ISDIR (1 << 1)
++#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
++#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
++#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
++
++struct au_wr_dir_args {
++ aufs_bindex_t force_btgt;
++ unsigned char flags;
++};
++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++ struct au_wr_dir_args *args);
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin);
++void au_pin_init(struct au_pin *pin, struct dentry *dentry,
++ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++ unsigned int udba, unsigned char flags);
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int udba, unsigned char flags) __must_check;
++int au_do_pin(struct au_pin *pin) __must_check;
++void au_unpin(struct au_pin *pin);
++
++/* i_op_add.c */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir);
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd);
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry);
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++
++/* i_op_del.c */
++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir);
++int aufs_unlink(struct inode *dir, struct dentry *dentry);
++int aufs_rmdir(struct inode *dir, struct dentry *dentry);
++
++/* i_op_ren.c */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct dentry *dentry);
++
++/* iinfo.c */
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
++void au_hiput(struct au_hinode *hinode);
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_wh);
++unsigned int au_hi_flags(struct inode *inode, int isdir);
++
++/* hinode flags */
++#define AuHi_XINO 1
++#define AuHi_HINOTIFY (1 << 1)
++#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
++#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
++#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuHi_HINOTIFY
++#define AuHi_HINOTIFY 0
++#endif
++
++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++ struct inode *h_inode, unsigned int flags);
++
++void au_update_iigen(struct inode *inode);
++void au_update_brange(struct inode *inode, int do_put_zero);
++
++int au_iinfo_init(struct inode *inode);
++void au_iinfo_fin(struct inode *inode);
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
++
++/* plink.c */
++void au_plink_block_maintain(struct super_block *sb);
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb);
++#else
++static inline void au_plink_list(struct super_block *sb)
++{
++ /* nothing */
++}
++#endif
++int au_plink_test(struct inode *inode);
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_dentry);
++void au_plink_put(struct super_block *sb);
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for iinfo */
++enum {
++ AuLsc_II_CHILD, /* child first */
++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
++ AuLsc_II_CHILD3, /* copyup dirs */
++ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
++ AuLsc_II_PARENT2,
++ AuLsc_II_PARENT3, /* copyup dirs */
++ AuLsc_II_NEW_CHILD
++};
++
++/*
++ * ii_read_lock_child, ii_write_lock_child,
++ * ii_read_lock_child2, ii_write_lock_child2,
++ * ii_read_lock_child3, ii_write_lock_child3,
++ * ii_read_lock_parent, ii_write_lock_parent,
++ * ii_read_lock_parent2, ii_write_lock_parent2,
++ * ii_read_lock_parent3, ii_write_lock_parent3,
++ * ii_read_lock_new_child, ii_write_lock_new_child,
++ */
++#define AuReadLockFunc(name, lsc) \
++static inline void ii_read_lock_##name(struct inode *i) \
++{ \
++ down_read_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void ii_write_lock_##name(struct inode *i) \
++{ \
++ down_write_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuRWLockFuncs(name, lsc) \
++ AuReadLockFunc(name, lsc) \
++ AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++AuRWLockFuncs(new_child, NEW_CHILD);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++/*
++ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
++ */
++AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
++
++#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++static inline unsigned int au_iigen(struct inode *inode)
++{
++ return atomic_read(&au_ii(inode)->ii_generation);
++}
++
++/* tiny test for inode number */
++/* tmpfs generation is too rough */
++static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
++{
++ struct au_iinfo *iinfo;
++
++ iinfo = au_ii(inode);
++ return !(iinfo->ii_hsb1 == h_inode->i_sb
++ && iinfo->ii_higen == h_inode->i_generation);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
++}
++
++static inline aufs_bindex_t au_ibstart(struct inode *inode)
++{
++ return au_ii(inode)->ii_bstart;
++}
++
++static inline aufs_bindex_t au_ibend(struct inode *inode)
++{
++ return au_ii(inode)->ii_bend;
++}
++
++static inline struct au_vdir *au_ivdir(struct inode *inode)
++{
++ return au_ii(inode)->ii_vdir;
++}
++
++static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
++}
++
++static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
++{
++ au_ii(inode)->ii_bend = bindex;
++}
++
++static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
++{
++ au_ii(inode)->ii_vdir = vdir;
++}
++
++static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
++{
++ return au_ii(inode)->ii_hinode + bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_pinned_parent(struct au_pin *pin)
++{
++ if (pin)
++ return pin->parent;
++ return NULL;
++}
++
++static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
++{
++ if (pin && pin->hdir)
++ return pin->hdir->hi_inode;
++ return NULL;
++}
++
++static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
++{
++ if (pin)
++ return pin->hdir;
++ return NULL;
++}
++
++static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
++{
++ if (pin)
++ pin->dentry = dentry;
++}
++
++static inline void au_pin_set_parent_lflag(struct au_pin *pin,
++ unsigned char lflag)
++{
++ if (pin) {
++ /* dirty macros require brackets */
++ if (lflag) {
++ au_fset_pin(pin->flags, DI_LOCKED);
++ } else {
++ au_fclr_pin(pin->flags, DI_LOCKED);
++ }
++ }
++}
++
++static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
++{
++ if (pin) {
++ dput(pin->parent);
++ pin->parent = dget(parent);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++/* hinotify.c */
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++ struct inode *h_inode);
++void au_hin_free(struct au_hinode *hinode);
++void au_hin_ctl(struct au_hinode *hinode, int do_set);
++void au_reset_hinotify(struct inode *inode, unsigned int flags);
++
++int __init au_hinotify_init(void);
++void au_hinotify_fin(void);
++
++static inline
++void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
++{
++ hinode->hi_notify = val;
++}
++
++static inline void au_iigen_dec(struct inode *inode)
++{
++ atomic_dec(&au_ii(inode)->ii_generation);
++}
++
++#else
++static inline
++int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
++ struct inode *inode __maybe_unused,
++ struct inode *h_inode __maybe_unused)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
++ int do_set __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
++ unsigned int flags __maybe_unused)
++{
++ /* nothing */
++}
++
++static inline int au_hinotify_init(void)
++{
++ return 0;
++}
++
++#define au_hinotify_fin() do {} while (0)
++
++static inline
++void au_hin_init(struct au_hinode *hinode __maybe_unused,
++ struct au_hinotify *val __maybe_unused)
++{
++ /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++static inline void au_hin_suspend(struct au_hinode *hdir)
++{
++ au_hin_ctl(hdir, /*do_set*/0);
++}
++
++static inline void au_hin_resume(struct au_hinode *hdir)
++{
++ au_hin_ctl(hdir, /*do_set*/1);
++}
++
++static inline void au_hin_imtx_lock(struct au_hinode *hdir)
++{
++ mutex_lock(&hdir->hi_inode->i_mutex);
++ au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
++ unsigned int sc __maybe_unused)
++{
++ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
++ au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
++{
++ au_hin_resume(hdir);
++ mutex_unlock(&hdir->hi_inode->i_mutex);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_INODE_H__ */
+diff -Naur a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c
+--- a/fs/aufs/ioctl.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/ioctl.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,68 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * ioctl
++ * currently plink-management only.
++ */
++
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++long aufs_ioctl_dir(struct file *file, unsigned int cmd,
++ unsigned long arg __maybe_unused)
++{
++ long err;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++ err = -EACCES;
++ if (!capable(CAP_SYS_ADMIN))
++ goto out;
++
++ err = 0;
++ sb = file->f_dentry->d_sb;
++ sbinfo = au_sbi(sb);
++ switch (cmd) {
++ case AUFS_CTL_PLINK_MAINT:
++ /*
++ * pseudo-link maintenance mode,
++ * cleared by aufs_release_dir()
++ */
++ si_write_lock(sb);
++ if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
++ au_fset_si(sbinfo, MAINTAIN_PLINK);
++ au_fi(file)->fi_maintain_plink = 1;
++ } else
++ err = -EBUSY;
++ si_write_unlock(sb);
++ break;
++ case AUFS_CTL_PLINK_CLEAN:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) {
++ aufs_write_lock(sb->s_root);
++ au_plink_put(sb);
++ aufs_write_unlock(sb->s_root);
++ }
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
+--- a/fs/aufs/i_op_add.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_add.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,638 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (add entry)
++ */
++
++#include "aufs.h"
++
++/*
++ * final procedure of adding a new entry, except link(2).
++ * remove whiteout, instantiate, copyup the parent dir's times and size
++ * and update version.
++ * if it failed, re-create the removed whiteout.
++ */
++static int epilog(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct dentry *dentry)
++{
++ int err, rerr;
++ aufs_bindex_t bwh;
++ struct path h_path;
++ struct inode *inode, *h_dir;
++ struct dentry *wh;
++
++ bwh = -1;
++ if (wh_dentry) {
++ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(h_dir);
++ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
++ bwh = au_dbwh(dentry);
++ h_path.dentry = wh_dentry;
++ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
++ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
++ dentry);
++ if (unlikely(err))
++ goto out;
++ }
++
++ inode = au_new_inode(dentry, /*must_new*/1);
++ if (!IS_ERR(inode)) {
++ d_instantiate(dentry, inode);
++ dir = dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(dir);
++ if (au_ibstart(dir) == au_dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++ return 0; /* success */
++ }
++
++ err = PTR_ERR(inode);
++ if (!wh_dentry)
++ goto out;
++
++ /* revert */
++ /* dir inode is locked */
++ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
++ rerr = PTR_ERR(wh);
++ if (IS_ERR(wh)) {
++ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ } else
++ dput(wh);
++
++ out:
++ return err;
++}
++
++/*
++ * simple tests for the adding inode operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir)
++{
++ int err;
++ umode_t h_mode;
++ struct dentry *h_dentry;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ if (!dentry->d_inode) {
++ err = -EEXIST;
++ if (unlikely(h_inode))
++ goto out;
++ } else {
++ /* rename(2) case */
++ err = -EIO;
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++
++ h_mode = h_inode->i_mode;
++ if (!isdir) {
++ err = -EISDIR;
++ if (unlikely(S_ISDIR(h_mode)))
++ goto out;
++ } else if (unlikely(!S_ISDIR(h_mode))) {
++ err = -ENOTDIR;
++ goto out;
++ }
++ }
++
++ err = -EIO;
++ /* expected parent dir is locked */
++ if (unlikely(h_parent != h_dentry->d_parent))
++ goto out;
++ err = 0;
++
++ out:
++ return err;
++}
++
++/*
++ * initial procedure of adding a new entry.
++ * prepare writable branch and the parent dir, lock it,
++ * and lookup whiteout for the new entry.
++ */
++static struct dentry*
++lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
++ struct dentry *src_dentry, struct au_pin *pin,
++ struct au_wr_dir_args *wr_dir_args)
++{
++ struct dentry *wh_dentry, *h_parent;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++ unsigned int udba;
++ aufs_bindex_t bcpup;
++
++ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
++ bcpup = err;
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out;
++
++ sb = dentry->d_sb;
++ udba = au_opt_udba(sb);
++ err = au_pin(pin, dentry, bcpup, udba,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ h_parent = au_pinned_h_parent(pin);
++ if (udba != AuOpt_UDBA_NONE
++ && au_dbstart(dentry) == bcpup) {
++ err = au_may_add(dentry, bcpup, h_parent,
++ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_unpin;
++ }
++
++ br = au_sbr(sb, bcpup);
++ if (dt) {
++ struct path tmp = {
++ .dentry = h_parent,
++ .mnt = br->br_mnt
++ };
++ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
++ }
++
++ wh_dentry = NULL;
++ if (bcpup != au_dbwh(dentry))
++ goto out; /* success */
++
++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++
++ out_unpin:
++ if (IS_ERR(wh_dentry))
++ au_unpin(pin);
++ out:
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++enum { Mknod, Symlink, Creat };
++struct simple_arg {
++ int type;
++ union {
++ struct {
++ int mode;
++ struct nameidata *nd;
++ } c;
++ struct {
++ const char *symname;
++ } s;
++ struct {
++ int mode;
++ dev_t dev;
++ } m;
++ } u;
++};
++
++static int add_simple(struct inode *dir, struct dentry *dentry,
++ struct simple_arg *arg)
++{
++ int err;
++ aufs_bindex_t bstart;
++ unsigned char created;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *wh_dentry, *parent;
++ struct inode *h_dir;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ IMustLock(dir);
++
++ parent = dentry->d_parent; /* dir inode is locked */
++ aufs_read_lock(dentry, AuLock_DW);
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ bstart = au_dbstart(dentry);
++ h_path.dentry = au_h_dptr(dentry, bstart);
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ h_dir = au_pinned_h_dir(&pin);
++ switch (arg->type) {
++ case Creat:
++ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
++ break;
++ case Symlink:
++ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
++ break;
++ case Mknod:
++ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
++ break;
++ default:
++ BUG();
++ }
++ created = !err;
++ if (!err)
++ err = epilog(dir, bstart, wh_dentry, dentry);
++
++ /* revert */
++ if (unlikely(created && err && h_path.dentry->d_inode)) {
++ int rerr;
++ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ if (rerr) {
++ AuIOErr("%.*s revert failure(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ au_dtime_revert(&dt);
++ d_drop(dentry);
++ }
++
++ au_unpin(&pin);
++ dput(wh_dentry);
++
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
++
++int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++ struct simple_arg arg = {
++ .type = Mknod,
++ .u.m = {
++ .mode = mode,
++ .dev = dev
++ }
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++ struct simple_arg arg = {
++ .type = Symlink,
++ .u.s.symname = symname
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ struct simple_arg arg = {
++ .type = Creat,
++ .u.c = {
++ .mode = mode,
++ .nd = nd
++ }
++ };
++ return add_simple(dir, dentry, &arg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_link_args {
++ aufs_bindex_t bdst, bsrc;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *src_parent, *parent;
++};
++
++static int au_cpup_before_link(struct dentry *src_dentry,
++ struct au_link_args *a)
++{
++ int err;
++ struct dentry *h_src_dentry;
++ struct mutex *h_mtx;
++
++ di_read_lock_parent(a->src_parent, AuLock_IR);
++ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
++ if (unlikely(err))
++ goto out;
++
++ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
++ h_mtx = &h_src_dentry->d_inode->i_mutex;
++ err = au_pin(&a->pin, src_dentry, a->bdst,
++ au_opt_udba(src_dentry->d_sb),
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
++ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
++ mutex_unlock(h_mtx);
++ au_unpin(&a->pin);
++
++ out:
++ di_read_unlock(a->src_parent, AuLock_IR);
++ return err;
++}
++
++static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
++{
++ int err;
++ unsigned char plink;
++ struct inode *h_inode, *inode;
++ struct dentry *h_src_dentry;
++ struct super_block *sb;
++
++ plink = 0;
++ h_inode = NULL;
++ sb = src_dentry->d_sb;
++ inode = src_dentry->d_inode;
++ if (au_ibstart(inode) <= a->bdst)
++ h_inode = au_h_iptr(inode, a->bdst);
++ if (!h_inode || !h_inode->i_nlink) {
++ /* copyup src_dentry as the name of dentry. */
++ au_set_dbstart(src_dentry, a->bdst);
++ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
++ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
++ AuCpup_KEEPLINO, a->parent);
++ mutex_unlock(&h_inode->i_mutex);
++ au_set_h_dptr(src_dentry, a->bdst, NULL);
++ au_set_dbstart(src_dentry, a->bsrc);
++ } else {
++ /* the inode of src_dentry already exists on a.bdst branch */
++ h_src_dentry = d_find_alias(h_inode);
++ if (!h_src_dentry && au_plink_test(inode)) {
++ plink = 1;
++ h_src_dentry = au_plink_lkup(inode, a->bdst);
++ err = PTR_ERR(h_src_dentry);
++ if (IS_ERR(h_src_dentry))
++ goto out;
++
++ if (unlikely(!h_src_dentry->d_inode)) {
++ dput(h_src_dentry);
++ h_src_dentry = NULL;
++ }
++
++ }
++ if (h_src_dentry) {
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ dput(h_src_dentry);
++ } else {
++ AuIOErr("no dentry found for hi%lu on b%d\n",
++ h_inode->i_ino, a->bdst);
++ err = -EIO;
++ }
++ }
++
++ if (!err && !plink)
++ au_plink_append(inode, a->bdst, a->h_path.dentry);
++
++out:
++ return err;
++}
++
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ int err, rerr;
++ struct au_dtime dt;
++ struct au_link_args *a;
++ struct dentry *wh_dentry, *h_src_dentry;
++ struct inode *inode;
++ struct super_block *sb;
++ struct au_wr_dir_args wr_dir_args = {
++ /* .force_btgt = -1, */
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ IMustLock(dir);
++ inode = src_dentry->d_inode;
++ IMustLock(inode);
++
++ err = -ENOENT;
++ if (unlikely(!inode->i_nlink))
++ goto out;
++
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ a->parent = dentry->d_parent; /* dir inode is locked */
++ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
++ a->src_parent = dget_parent(src_dentry);
++ wr_dir_args.force_btgt = au_dbstart(src_dentry);
++
++ di_write_lock_parent(a->parent);
++ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_unlock;
++
++ err = 0;
++ sb = dentry->d_sb;
++ a->bdst = au_dbstart(dentry);
++ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
++ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
++ a->bsrc = au_dbstart(src_dentry);
++ if (au_opt_test(au_mntflags(sb), PLINK)) {
++ if (a->bdst < a->bsrc
++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
++ err = au_cpup_or_link(src_dentry, a);
++ else {
++ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ }
++ } else {
++ /*
++ * copyup src_dentry to the branch we process,
++ * and then link(2) to it.
++ */
++ if (a->bdst < a->bsrc
++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
++ au_unpin(&a->pin);
++ di_write_unlock(a->parent);
++ err = au_cpup_before_link(src_dentry, a);
++ if (!err) {
++ di_write_lock_parent(a->parent);
++ err = au_pin(&a->pin, dentry, a->bdst,
++ au_opt_udba(sb),
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ if (unlikely(err))
++ goto out_wh;
++ }
++ }
++ if (!err) {
++ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++ &a->h_path);
++ }
++ }
++ if (unlikely(err))
++ goto out_unpin;
++
++ if (wh_dentry) {
++ a->h_path.dentry = wh_dentry;
++ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
++ dentry);
++ if (unlikely(err))
++ goto out_revert;
++ }
++
++ dir->i_version++;
++ if (au_ibstart(dir) == au_dbstart(dentry))
++ au_cpup_attr_timesizes(dir);
++ inc_nlink(inode);
++ inode->i_ctime = dir->i_ctime;
++ if (!d_unhashed(a->h_path.dentry))
++ d_instantiate(dentry, au_igrab(inode));
++ else
++ /* some filesystem calls d_drop() */
++ d_drop(dentry);
++ goto out_unpin; /* success */
++
++ out_revert:
++ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
++ if (!rerr)
++ goto out_dt;
++ AuIOErr("%.*s reverting failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ out_dt:
++ d_drop(dentry);
++ au_dtime_revert(&dt);
++ out_unpin:
++ au_unpin(&a->pin);
++ out_wh:
++ dput(wh_dentry);
++ out_unlock:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(a->parent);
++ dput(a->src_parent);
++ aufs_read_and_write_unlock2(dentry, src_dentry);
++ kfree(a);
++ out:
++ return err;
++}
++
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err, rerr;
++ aufs_bindex_t bindex;
++ unsigned char diropq;
++ struct au_pin pin;
++ struct path h_path;
++ struct dentry *wh_dentry, *parent, *opq_dentry;
++ struct mutex *h_mtx;
++ struct super_block *sb;
++ struct au_dtime dt;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
++ };
++
++ IMustLock(dir);
++
++ aufs_read_lock(dentry, AuLock_DW);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++ &wr_dir_args);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ sb = dentry->d_sb;
++ bindex = au_dbstart(dentry);
++ h_path.dentry = au_h_dptr(dentry, bindex);
++ h_path.mnt = au_sbr_mnt(sb, bindex);
++ err = vfsub_mkdir(au_pinned_h_dir(&pin), &h_path, mode);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* make the dir opaque */
++ diropq = 0;
++ h_mtx = &h_path.dentry->d_inode->i_mutex;
++ if (wh_dentry
++ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ opq_dentry = au_diropq_create(dentry, bindex);
++ mutex_unlock(h_mtx);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out_dir;
++ dput(opq_dentry);
++ diropq = 1;
++ }
++
++ err = epilog(dir, bindex, wh_dentry, dentry);
++ if (!err) {
++ inc_nlink(dir);
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (diropq) {
++ AuLabel(revert opq);
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(dentry, bindex);
++ mutex_unlock(h_mtx);
++ if (rerr) {
++ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ }
++
++ out_dir:
++ AuLabel(revert dir);
++ rerr = vfsub_rmdir(au_pinned_h_dir(&pin), &h_path);
++ if (rerr) {
++ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ err = -EIO;
++ }
++ d_drop(dentry);
++ au_dtime_revert(&dt);
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ out:
++ if (unlikely(err)) {
++ au_update_dbstart(dentry);
++ d_drop(dentry);
++ }
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
+diff -Naur a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+--- a/fs/aufs/i_op.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,874 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (except add/del/rename)
++ */
++
++#include <linux/device_cgroup.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++static int h_permission(struct inode *h_inode, int mask,
++ struct vfsmount *h_mnt, int brperm)
++{
++ int err;
++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++
++ err = -EACCES;
++ if ((write_mask && IS_IMMUTABLE(h_inode))
++ || ((mask & MAY_EXEC)
++ && S_ISREG(h_inode->i_mode)
++ && ((h_mnt->mnt_flags & MNT_NOEXEC)
++ || !(h_inode->i_mode & S_IXUGO))))
++ goto out;
++
++ /*
++ * - skip the lower fs test in the case of write to ro branch.
++ * - nfs dir permission write check is optimized, but a policy for
++ * link/rename requires a real check.
++ */
++ if ((write_mask && !au_br_writable(brperm))
++ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
++ && write_mask && !(mask & MAY_READ))
++ || !h_inode->i_op->permission) {
++ /* AuLabel(generic_permission); */
++ err = generic_permission(h_inode, mask, NULL);
++ } else {
++ /* AuLabel(h_inode->permission); */
++ err = h_inode->i_op->permission(h_inode, mask);
++ AuTraceErr(err);
++ }
++
++ if (!err)
++ err = devcgroup_inode_permission(h_inode, mask);
++ if (!err)
++ err = security_inode_permission
++ (h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
++ | MAY_APPEND));
++
++ out:
++ return err;
++}
++
++static int aufs_permission(struct inode *inode, int mask)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ const unsigned char isdir = !!S_ISDIR(inode->i_mode);
++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++ struct inode *h_inode;
++ struct super_block *sb;
++ struct au_branch *br;
++
++ sb = inode->i_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ ii_read_lock_child(inode);
++
++ if (!isdir || write_mask) {
++ h_inode = au_h_iptr(inode, au_ibstart(inode));
++ AuDebugOn(!h_inode
++ || ((h_inode->i_mode & S_IFMT)
++ != (inode->i_mode & S_IFMT)));
++ err = 0;
++ bindex = au_ibstart(inode);
++ br = au_sbr(sb, bindex);
++ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
++
++ if (write_mask && !err) {
++ /* test whether the upper writable branch exists */
++ err = -EROFS;
++ for (; bindex >= 0; bindex--)
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = 0;
++ break;
++ }
++ }
++ goto out;
++ }
++
++ /* non-write to dir */
++ err = 0;
++ bend = au_ibend(inode);
++ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
++ h_inode = au_h_iptr(inode, bindex);
++ if (h_inode) {
++ AuDebugOn(!S_ISDIR(h_inode->i_mode));
++ br = au_sbr(sb, bindex);
++ err = h_permission(h_inode, mask, br->br_mnt,
++ br->br_perm);
++ }
++ }
++
++ out:
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ struct dentry *ret, *parent;
++ struct inode *inode, *h_inode;
++ struct mutex *mtx;
++ struct super_block *sb;
++ int err, npositive;
++ aufs_bindex_t bstart;
++
++ /* temporary workaround for a bug in NFSD readdir */
++ if (!au_test_nfsd(current))
++ IMustLock(dir);
++ else
++ WARN_ONCE(!mutex_is_locked(&dir->i_mutex),
++ "a known problem of NFSD readdir since 2.6.28\n");
++
++ sb = dir->i_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ err = au_alloc_dinfo(dentry);
++ ret = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_read_lock_parent(parent, AuLock_IR);
++ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
++ di_read_unlock(parent, AuLock_IR);
++ err = npositive;
++ ret = ERR_PTR(err);
++ if (unlikely(err < 0))
++ goto out_unlock;
++
++ inode = NULL;
++ if (npositive) {
++ bstart = au_dbstart(dentry);
++ h_inode = au_h_dptr(dentry, bstart)->d_inode;
++ if (!S_ISDIR(h_inode->i_mode)) {
++ /*
++ * stop 'race'-ing between hardlinks under different
++ * parents.
++ */
++ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
++ mutex_lock(mtx);
++ inode = au_new_inode(dentry, /*must_new*/0);
++ mutex_unlock(mtx);
++ } else
++ inode = au_new_inode(dentry, /*must_new*/0);
++ ret = (void *)inode;
++ }
++ if (IS_ERR(inode))
++ goto out_unlock;
++
++ ret = d_splice_alias(inode, dentry);
++ if (unlikely(IS_ERR(ret) && inode))
++ ii_write_unlock(inode);
++ au_store_oflag(nd, inode);
++
++ out_unlock:
++ di_write_unlock(dentry);
++ out:
++ si_read_unlock(sb);
++ return ret;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
++ const unsigned char add_entry, aufs_bindex_t bcpup,
++ aufs_bindex_t bstart)
++{
++ int err;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++
++ if (add_entry) {
++ au_update_dbstart(dentry);
++ IMustLock(parent->d_inode);
++ } else
++ di_write_lock_parent(parent);
++
++ err = 0;
++ if (!au_h_dptr(parent, bcpup)) {
++ if (bstart < bcpup)
++ err = au_cpdown_dirs(dentry, bcpup);
++ else
++ err = au_cpup_dirs(dentry, bcpup);
++ }
++ if (!err && add_entry) {
++ h_parent = au_h_dptr(parent, bcpup);
++ h_dir = h_parent->d_inode;
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ err = au_lkup_neg(dentry, bcpup);
++ /* todo: no unlock here */
++ mutex_unlock(&h_dir->i_mutex);
++ if (bstart < bcpup && au_dbstart(dentry) < 0) {
++ au_set_dbstart(dentry, 0);
++ au_update_dbrange(dentry, /*do_put_zero*/0);
++ }
++ }
++
++ if (!add_entry)
++ di_write_unlock(parent);
++ if (!err)
++ err = bcpup; /* success */
++
++ return err;
++}
++
++/*
++ * decide the branch and the parent dir where we will create a new entry.
++ * returns new bindex or an error.
++ * copyup the parent dir if needed.
++ */
++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++ struct au_wr_dir_args *args)
++{
++ int err;
++ aufs_bindex_t bcpup, bstart, src_bstart;
++ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
++ ADD_ENTRY);
++ struct super_block *sb;
++ struct dentry *parent;
++ struct au_sbinfo *sbinfo;
++
++ sb = dentry->d_sb;
++ sbinfo = au_sbi(sb);
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(dentry);
++ bcpup = bstart;
++ if (args->force_btgt < 0) {
++ if (src_dentry) {
++ src_bstart = au_dbstart(src_dentry);
++ if (src_bstart < bstart)
++ bcpup = src_bstart;
++ } else if (add_entry) {
++ err = AuWbrCreate(sbinfo, dentry,
++ au_ftest_wrdir(args->flags, ISDIR));
++ bcpup = err;
++ }
++
++ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
++ if (add_entry)
++ err = AuWbrCopyup(sbinfo, dentry);
++ else {
++ if (!IS_ROOT(dentry)) {
++ di_read_lock_parent(parent, !AuLock_IR);
++ err = AuWbrCopyup(sbinfo, dentry);
++ di_read_unlock(parent, !AuLock_IR);
++ } else
++ err = AuWbrCopyup(sbinfo, dentry);
++ }
++ bcpup = err;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else {
++ bcpup = args->force_btgt;
++ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
++ }
++ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
++ if (bstart < bcpup)
++ au_update_dbrange(dentry, /*do_put_zero*/1);
++
++ err = bcpup;
++ if (bcpup == bstart)
++ goto out; /* success */
++
++ /* copyup the new parent into the branch we process */
++ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin)
++{
++ if (pin && pin->parent)
++ return au_h_dptr(pin->parent, pin->bindex);
++ return NULL;
++}
++
++void au_unpin(struct au_pin *p)
++{
++ if (au_ftest_pin(p->flags, MNT_WRITE))
++ mnt_drop_write(p->h_mnt);
++ if (!p->hdir)
++ return;
++
++ au_hin_imtx_unlock(p->hdir);
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_unlock(p->parent, AuLock_IR);
++ iput(p->hdir->hi_inode);
++ dput(p->parent);
++ p->parent = NULL;
++ p->hdir = NULL;
++ p->h_mnt = NULL;
++}
++
++int au_do_pin(struct au_pin *p)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *h_dentry, *h_parent;
++ struct au_branch *br;
++ struct inode *h_dir;
++
++ err = 0;
++ sb = p->dentry->d_sb;
++ br = au_sbr(sb, p->bindex);
++ if (IS_ROOT(p->dentry)) {
++ if (au_ftest_pin(p->flags, MNT_WRITE)) {
++ p->h_mnt = br->br_mnt;
++ err = mnt_want_write(p->h_mnt);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_err;
++ }
++ }
++ goto out;
++ }
++
++ h_dentry = NULL;
++ if (p->bindex <= au_dbend(p->dentry))
++ h_dentry = au_h_dptr(p->dentry, p->bindex);
++
++ p->parent = dget_parent(p->dentry);
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
++
++ h_dir = NULL;
++ h_parent = au_h_dptr(p->parent, p->bindex);
++ p->hdir = au_hi(p->parent->d_inode, p->bindex);
++ if (p->hdir)
++ h_dir = p->hdir->hi_inode;
++
++ /* udba case */
++ if (unlikely(!p->hdir || !h_dir)) {
++ err = au_busy_or_stale();
++ if (!au_ftest_pin(p->flags, DI_LOCKED))
++ di_read_unlock(p->parent, AuLock_IR);
++ dput(p->parent);
++ p->parent = NULL;
++ goto out_err;
++ }
++
++ au_igrab(h_dir);
++ au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
++
++ if (h_dentry) {
++ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_unpin;
++ }
++ }
++
++ if (au_ftest_pin(p->flags, MNT_WRITE)) {
++ p->h_mnt = br->br_mnt;
++ err = mnt_want_write(p->h_mnt);
++ if (unlikely(err)) {
++ au_fclr_pin(p->flags, MNT_WRITE);
++ goto out_unpin;
++ }
++ }
++ goto out; /* success */
++
++ out_unpin:
++ au_unpin(p);
++ out_err:
++ AuErr("err %d\n", err);
++ err = au_busy_or_stale();
++ out:
++ return err;
++}
++
++void au_pin_init(struct au_pin *p, struct dentry *dentry,
++ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++ unsigned int udba, unsigned char flags)
++{
++ p->dentry = dentry;
++ p->udba = udba;
++ p->lsc_di = lsc_di;
++ p->lsc_hi = lsc_hi;
++ p->flags = flags;
++ p->bindex = bindex;
++
++ p->parent = NULL;
++ p->hdir = NULL;
++ p->h_mnt = NULL;
++}
++
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int udba, unsigned char flags)
++{
++ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
++ udba, flags);
++ return au_do_pin(pin);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuIcpup_DID_CPUP 1
++#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
++#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
++#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
++
++struct au_icpup_args {
++ unsigned char flags;
++ unsigned char pin_flags;
++ aufs_bindex_t btgt;
++ struct au_pin pin;
++ struct path h_path;
++ struct inode *h_inode;
++};
++
++static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
++ struct au_icpup_args *a)
++{
++ int err;
++ unsigned int udba;
++ loff_t sz;
++ aufs_bindex_t bstart;
++ struct dentry *hi_wh, *parent;
++ struct inode *inode;
++ struct au_wr_dir_args wr_dir_args = {
++ .force_btgt = -1,
++ .flags = 0
++ };
++
++ di_write_lock_child(dentry);
++ bstart = au_dbstart(dentry);
++ inode = dentry->d_inode;
++ if (S_ISDIR(inode->i_mode))
++ au_fset_wrdir(wr_dir_args.flags, ISDIR);
++ /* plink or hi_wh() case */
++ if (bstart != au_ibstart(inode))
++ wr_dir_args.force_btgt = au_ibstart(inode);
++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
++ if (unlikely(err < 0))
++ goto out_dentry;
++ a->btgt = err;
++ if (err != bstart)
++ au_fset_icpup(a->flags, DID_CPUP);
++
++ err = 0;
++ a->pin_flags = AuPin_MNT_WRITE;
++ parent = NULL;
++ if (!IS_ROOT(dentry)) {
++ au_fset_pin(a->pin_flags, DI_LOCKED);
++ parent = dget_parent(dentry);
++ di_write_lock_parent(parent);
++ }
++
++ udba = au_opt_udba(dentry->d_sb);
++ if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
++ udba = AuOpt_UDBA_NONE;
++ err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
++ if (unlikely(err)) {
++ if (parent) {
++ di_write_unlock(parent);
++ dput(parent);
++ }
++ goto out_dentry;
++ }
++ a->h_path.dentry = au_h_dptr(dentry, bstart);
++ a->h_inode = a->h_path.dentry->d_inode;
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ sz = -1;
++ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
++ sz = ia->ia_size;
++
++ hi_wh = NULL;
++ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
++ hi_wh = au_hi_wh(inode, a->btgt);
++ if (!hi_wh) {
++ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
++ if (unlikely(err))
++ goto out_unlock;
++ hi_wh = au_hi_wh(inode, a->btgt);
++ /* todo: revalidate hi_wh? */
++ }
++ }
++
++ if (parent) {
++ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
++ di_downgrade_lock(parent, AuLock_IR);
++ dput(parent);
++ }
++ if (!au_ftest_icpup(a->flags, DID_CPUP))
++ goto out; /* success */
++
++ if (!d_unhashed(dentry)) {
++ err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
++ if (!err)
++ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++ } else if (!hi_wh)
++ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++ else
++ a->h_path.dentry = hi_wh; /* do not dget here */
++
++ out_unlock:
++ mutex_unlock(&a->h_inode->i_mutex);
++ a->h_inode = a->h_path.dentry->d_inode;
++ if (!err) {
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ goto out; /* success */
++ }
++
++ au_unpin(&a->pin);
++
++ out_dentry:
++ di_write_unlock(dentry);
++ out:
++ return err;
++}
++
++static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err;
++ struct inode *inode;
++ struct super_block *sb;
++ struct file *file;
++ struct au_icpup_args *a;
++
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ inode = dentry->d_inode;
++ IMustLock(inode);
++ sb = dentry->d_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++
++ file = NULL;
++ if (ia->ia_valid & ATTR_FILE) {
++ /* currently ftruncate(2) only */
++ file = ia->ia_file;
++ fi_write_lock(file);
++ ia->ia_file = au_h_fptr(file, au_fbstart(file));
++ }
++
++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
++ ia->ia_valid &= ~ATTR_MODE;
++
++ err = au_lock_and_icpup(dentry, ia, a);
++ if (unlikely(err < 0))
++ goto out_si;
++ if (au_ftest_icpup(a->flags, DID_CPUP)) {
++ ia->ia_file = NULL;
++ ia->ia_valid &= ~ATTR_FILE;
++ }
++
++ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
++ if (ia->ia_valid & ATTR_SIZE) {
++ struct file *f;
++
++ if (ia->ia_size < i_size_read(inode)) {
++ /* unmap only */
++ err = vmtruncate(inode, ia->ia_size);
++ if (unlikely(err))
++ goto out_unlock;
++ }
++
++ f = NULL;
++ if (ia->ia_valid & ATTR_FILE)
++ f = ia->ia_file;
++ mutex_unlock(&a->h_inode->i_mutex);
++ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ } else
++ err = vfsub_notify_change(&a->h_path, ia);
++ if (!err)
++ au_cpup_attr_changeable(inode);
++
++ out_unlock:
++ mutex_unlock(&a->h_inode->i_mutex);
++ au_unpin(&a->pin);
++ di_write_unlock(dentry);
++ out_si:
++ if (file) {
++ fi_write_unlock(file);
++ ia->ia_file = file;
++ ia->ia_valid |= ATTR_FILE;
++ }
++ si_read_unlock(sb);
++ kfree(a);
++ out:
++ return err;
++}
++
++static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *parent;
++
++ err = 0;
++ inode = dentry->d_inode;
++ di_write_lock_child(dentry);
++ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++ /* returns a number of positive dentries */
++ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++ if (err > 0)
++ err = au_refresh_hinode(inode, dentry);
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ if (unlikely(!err))
++ err = -EIO;
++ }
++ di_downgrade_lock(dentry, AuLock_IR);
++
++ return err;
++}
++
++static void au_refresh_iattr(struct inode *inode, struct kstat *st,
++ unsigned int nlink)
++{
++ inode->i_mode = st->mode;
++ inode->i_uid = st->uid;
++ inode->i_gid = st->gid;
++ inode->i_atime = st->atime;
++ inode->i_mtime = st->mtime;
++ inode->i_ctime = st->ctime;
++
++ au_cpup_attr_nlink(inode, /*force*/0);
++ if (S_ISDIR(inode->i_mode)) {
++ inode->i_nlink -= nlink;
++ inode->i_nlink += st->nlink;
++ }
++
++ spin_lock(&inode->i_lock);
++ inode->i_blocks = st->blocks;
++ i_size_write(inode, st->size);
++ spin_unlock(&inode->i_lock);
++}
++
++static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
++ struct dentry *dentry, struct kstat *st)
++{
++ int err;
++ unsigned int mnt_flags;
++ aufs_bindex_t bindex;
++ unsigned char udba_none, positive, did_lock;
++ struct super_block *sb, *h_sb;
++ struct inode *inode;
++ struct vfsmount *h_mnt;
++ struct dentry *h_dentry;
++
++ err = 0;
++ did_lock = 0;
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ si_read_lock(sb, AuLock_FLUSH);
++ if (IS_ROOT(dentry)) {
++ /* lock free root dinfo */
++ h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
++ h_mnt = au_sbr_mnt(sb, 0);
++ goto getattr;
++ }
++
++ did_lock = 1;
++ mnt_flags = au_mntflags(sb);
++ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
++
++ /* support fstat(2) */
++ if (!d_unhashed(dentry) && !udba_none) {
++ unsigned int sigen = au_sigen(sb);
++ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++ di_read_lock_child(dentry, AuLock_IR);
++ else {
++ err = au_getattr_lock_reval(dentry, sigen);
++ if (unlikely(err))
++ goto out;
++ }
++ } else
++ di_read_lock_child(dentry, AuLock_IR);
++
++ bindex = au_ibstart(inode);
++ h_mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_mnt->mnt_sb;
++ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
++ goto out_fill; /* success */
++
++ if (au_dbstart(dentry) == bindex)
++ h_dentry = dget(au_h_dptr(dentry, bindex));
++ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
++ h_dentry = au_plink_lkup(inode, bindex);
++ if (IS_ERR(h_dentry))
++ goto out_fill; /* pretending success */
++ } else
++ /* illegally overlapped or something */
++ goto out_fill; /* pretending success */
++
++ getattr:
++ positive = !!h_dentry->d_inode;
++ if (positive)
++ err = vfs_getattr(h_mnt, h_dentry, st);
++ dput(h_dentry);
++ if (!err) {
++ if (positive)
++ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
++ goto out_fill; /* success */
++ }
++ goto out;
++
++ out_fill:
++ generic_fillattr(inode, st);
++ out:
++ if (did_lock)
++ di_read_unlock(dentry, AuLock_IR);
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *h_dentry;
++
++ err = -EINVAL;
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (unlikely(/* !h_dentry
++ || !h_dentry->d_inode
++ || !h_dentry->d_inode->i_op
++ || */ !h_dentry->d_inode->i_op->readlink))
++ goto out;
++
++ err = security_inode_readlink(h_dentry);
++ if (unlikely(err))
++ goto out;
++
++ sb = dentry->d_sb;
++ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
++ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
++ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
++ }
++ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
++
++ out:
++ return err;
++}
++
++static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
++{
++ int err;
++
++ aufs_read_lock(dentry, AuLock_IR);
++ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
++ aufs_read_unlock(dentry, AuLock_IR);
++
++ return err;
++}
++
++static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ int err;
++ char *buf;
++ mm_segment_t old_fs;
++
++ err = -ENOMEM;
++ buf = __getname();
++ if (unlikely(!buf))
++ goto out;
++
++ aufs_read_lock(dentry, AuLock_IR);
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
++ PATH_MAX);
++ set_fs(old_fs);
++ aufs_read_unlock(dentry, AuLock_IR);
++
++ if (err >= 0) {
++ buf[err] = 0;
++ /* will be freed by put_link */
++ nd_set_link(nd, buf);
++ return NULL; /* success */
++ }
++ __putname(buf);
++
++ out:
++ path_put(&nd->path);
++ AuTraceErr(err);
++ return ERR_PTR(err);
++}
++
++static void aufs_put_link(struct dentry *dentry __maybe_unused,
++ struct nameidata *nd, void *cookie __maybe_unused)
++{
++ __putname(nd_get_link(nd));
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_truncate_range(struct inode *inode __maybe_unused,
++ loff_t start __maybe_unused,
++ loff_t end __maybe_unused)
++{
++ AuUnsupport();
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct inode_operations aufs_symlink_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr,
++ .readlink = aufs_readlink,
++ .follow_link = aufs_follow_link,
++ .put_link = aufs_put_link
++};
++
++struct inode_operations aufs_dir_iop = {
++ .create = aufs_create,
++ .lookup = aufs_lookup,
++ .link = aufs_link,
++ .unlink = aufs_unlink,
++ .symlink = aufs_symlink,
++ .mkdir = aufs_mkdir,
++ .rmdir = aufs_rmdir,
++ .mknod = aufs_mknod,
++ .rename = aufs_rename,
++
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr
++};
++
++struct inode_operations aufs_iop = {
++ .permission = aufs_permission,
++ .setattr = aufs_setattr,
++ .getattr = aufs_getattr,
++ .truncate_range = aufs_truncate_range
++};
+diff -Naur a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
+--- a/fs/aufs/i_op_del.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_del.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,466 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operations (del entry)
++ */
++
++#include "aufs.h"
++
++/*
++ * decide if a new whiteout for @dentry is necessary or not.
++ * when it is necessary, prepare the parent dir for the upper branch whose
++ * branch index is @bcpup for creation. the actual creation of the whiteout will
++ * be done by caller.
++ * return value:
++ * 0: wh is unnecessary
++ * plus: wh is necessary
++ * minus: error
++ */
++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
++{
++ int need_wh, err;
++ aufs_bindex_t bstart;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ if (*bcpup < 0) {
++ *bcpup = bstart;
++ if (au_test_ro(sb, bstart, dentry->d_inode)) {
++ err = AuWbrCopyup(au_sbi(sb), dentry);
++ *bcpup = err;
++ if (unlikely(err < 0))
++ goto out;
++ }
++ } else
++ AuDebugOn(bstart < *bcpup
++ || au_test_ro(sb, *bcpup, dentry->d_inode));
++ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
++
++ if (*bcpup != bstart) {
++ err = au_cpup_dirs(dentry, *bcpup);
++ if (unlikely(err))
++ goto out;
++ need_wh = 1;
++ } else {
++ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
++
++ old_bend = au_dbend(dentry);
++ if (isdir) {
++ bdiropq = au_dbdiropq(dentry);
++ au_set_dbdiropq(dentry, -1);
++ }
++ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
++ /*nd*/NULL);
++ err = need_wh;
++ if (isdir)
++ au_set_dbdiropq(dentry, bdiropq);
++ if (unlikely(err < 0))
++ goto out;
++ new_bend = au_dbend(dentry);
++ if (!need_wh && old_bend != new_bend) {
++ au_set_h_dptr(dentry, new_bend, NULL);
++ au_set_dbend(dentry, old_bend);
++ }
++ }
++ AuDbg("need_wh %d\n", need_wh);
++ err = need_wh;
++
++ out:
++ return err;
++}
++
++/*
++ * simple tests for the del-entry operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent, int isdir)
++{
++ int err;
++ umode_t h_mode;
++ struct dentry *h_dentry, *h_latest;
++ struct inode *h_inode;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ h_inode = h_dentry->d_inode;
++ if (dentry->d_inode) {
++ err = -ENOENT;
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++
++ h_mode = h_inode->i_mode;
++ if (!isdir) {
++ err = -EISDIR;
++ if (unlikely(S_ISDIR(h_mode)))
++ goto out;
++ } else if (unlikely(!S_ISDIR(h_mode))) {
++ err = -ENOTDIR;
++ goto out;
++ }
++ } else {
++ /* rename(2) case */
++ err = -EIO;
++ if (unlikely(h_inode))
++ goto out;
++ }
++
++ err = -ENOENT;
++ /* expected parent dir is locked */
++ if (unlikely(h_parent != h_dentry->d_parent))
++ goto out;
++ err = 0;
++
++ /*
++ * rmdir a dir may break the consistency on some filesystem.
++ * let's try heavy test.
++ */
++ err = -EACCES;
++ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
++ goto out;
++
++ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
++ au_sbr(dentry->d_sb, bindex));
++ err = -EIO;
++ if (IS_ERR(h_latest))
++ goto out;
++ if (h_latest == h_dentry)
++ err = 0;
++ dput(h_latest);
++
++ out:
++ return err;
++}
++
++/*
++ * decide the branch where we operate for @dentry. the branch index will be set
++ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
++ * dir for reverting.
++ * when a new whiteout is necessary, create it.
++ */
++static struct dentry*
++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
++ struct au_dtime *dt, struct au_pin *pin)
++{
++ struct dentry *wh_dentry;
++ struct super_block *sb;
++ struct path h_path;
++ int err, need_wh;
++ unsigned int udba;
++ aufs_bindex_t bcpup;
++
++ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
++ wh_dentry = ERR_PTR(need_wh);
++ if (unlikely(need_wh < 0))
++ goto out;
++
++ sb = dentry->d_sb;
++ udba = au_opt_udba(sb);
++ bcpup = *rbcpup;
++ err = au_pin(pin, dentry, bcpup, udba,
++ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
++ h_path.dentry = au_pinned_h_parent(pin);
++ if (udba != AuOpt_UDBA_NONE
++ && au_dbstart(dentry) == bcpup) {
++ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
++ wh_dentry = ERR_PTR(err);
++ if (unlikely(err))
++ goto out_unpin;
++ }
++
++ h_path.mnt = au_sbr_mnt(sb, bcpup);
++ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
++ wh_dentry = NULL;
++ if (!need_wh)
++ goto out; /* success, no need to create whiteout */
++
++ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
++ if (!IS_ERR(wh_dentry))
++ goto out; /* success */
++ /* returns with the parent is locked and wh_dentry is dget-ed */
++
++ out_unpin:
++ au_unpin(pin);
++ out:
++ return wh_dentry;
++}
++
++/*
++ * when removing a dir, rename it to a unique temporary whiteout-ed name first
++ * in order to be revertible and save time for removing many child whiteouts
++ * under the dir.
++ * returns 1 when there are too many child whiteout and caller should remove
++ * them asynchronously. returns 0 when the number of children is enough small to
++ * remove now or the branch fs is a remote fs.
++ * otherwise return an error.
++ */
++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
++ struct au_nhash *whlist, struct inode *dir)
++{
++ int rmdir_later, err, dirwh;
++ struct dentry *h_dentry;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ h_dentry = au_h_dptr(dentry, bindex);
++ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
++ if (unlikely(err))
++ goto out;
++
++ /* stop monitoring */
++ au_hin_free(au_hi(dentry->d_inode, bindex));
++
++ if (!au_test_fs_remote(h_dentry->d_sb)) {
++ dirwh = au_sbi(sb)->si_dirwh;
++ rmdir_later = (dirwh <= 1);
++ if (!rmdir_later)
++ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
++ dirwh);
++ if (rmdir_later)
++ return rmdir_later;
++ }
++
++ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
++ if (unlikely(err)) {
++ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
++ AuDLNPair(h_dentry), bindex, err);
++ err = 0;
++ }
++
++ out:
++ return err;
++}
++
++/*
++ * final procedure for deleting a entry.
++ * maintain dentry and iattr.
++ */
++static void epilog(struct inode *dir, struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ struct inode *inode;
++
++ inode = dentry->d_inode;
++ d_drop(dentry);
++ inode->i_ctime = dir->i_ctime;
++
++ if (atomic_read(&dentry->d_count) == 1) {
++ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
++ au_update_dbstart(dentry);
++ }
++ if (au_ibstart(dir) == bindex)
++ au_cpup_attr_timesizes(dir);
++ dir->i_version++;
++}
++
++/*
++ * when an error happened, remove the created whiteout and revert everything.
++ */
++static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
++ struct dentry *wh_dentry, struct dentry *dentry,
++ struct au_dtime *dt)
++{
++ int rerr;
++ struct path h_path = {
++ .dentry = wh_dentry,
++ .mnt = au_sbr_mnt(dir->i_sb, bwh)
++ };
++
++ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
++ if (!rerr) {
++ au_set_dbwh(dentry, bwh);
++ au_dtime_revert(dt);
++ return 0;
++ }
++
++ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++ AuDLNPair(dentry), err, rerr);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct path h_path;
++ struct inode *inode, *h_dir;
++ struct dentry *parent, *wh_dentry;
++
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ if (unlikely(!inode))
++ return -ENOENT; /* possible? */
++ IMustLock(inode);
++
++ aufs_read_lock(dentry, AuLock_DW);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++
++ bstart = au_dbstart(dentry);
++ bwh = au_dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++ h_path.dentry = au_h_dptr(dentry, bstart);
++ dget(h_path.dentry);
++ if (bindex == bstart) {
++ h_dir = au_pinned_h_dir(&pin);
++ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ } else {
++ /* dir inode is locked */
++ h_dir = wh_dentry->d_parent->d_inode;
++ IMustLock(h_dir);
++ err = 0;
++ }
++
++ if (!err) {
++ drop_nlink(inode);
++ epilog(dir, dentry, bindex);
++
++ /* update target timestamps */
++ if (bindex == bstart) {
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
++ } else
++ /* todo: this timestamp may be reverted later */
++ inode->i_ctime = h_dir->i_ctime;
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ if (wh_dentry) {
++ int rerr;
++
++ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ dput(h_path.dentry);
++ out:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ return err;
++}
++
++int aufs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err, rmdir_later;
++ aufs_bindex_t bwh, bindex, bstart;
++ struct au_dtime dt;
++ struct au_pin pin;
++ struct inode *inode;
++ struct dentry *parent, *wh_dentry, *h_dentry;
++ struct au_whtmp_rmdir *args;
++
++ IMustLock(dir);
++ inode = dentry->d_inode;
++ err = -ENOENT; /* possible? */
++ if (unlikely(!inode))
++ goto out;
++ IMustLock(inode);
++
++ err = -ENOMEM;
++ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
++ if (unlikely(!args))
++ goto out;
++
++ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
++ parent = dentry->d_parent; /* dir inode is locked */
++ di_write_lock_parent(parent);
++ err = au_test_empty(dentry, &args->whlist);
++ if (unlikely(err))
++ goto out_args;
++
++ bstart = au_dbstart(dentry);
++ bwh = au_dbwh(dentry);
++ bindex = -1;
++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out_args;
++
++ h_dentry = au_h_dptr(dentry, bstart);
++ dget(h_dentry);
++ rmdir_later = 0;
++ if (bindex == bstart) {
++ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
++ if (err > 0) {
++ rmdir_later = err;
++ err = 0;
++ }
++ } else {
++ /* stop monitoring */
++ au_hin_free(au_hi(inode, bstart));
++
++ /* dir inode is locked */
++ IMustLock(wh_dentry->d_parent->d_inode);
++ err = 0;
++ }
++
++ if (!err) {
++ clear_nlink(inode);
++ au_set_dbdiropq(dentry, -1);
++ epilog(dir, dentry, bindex);
++
++ if (rmdir_later) {
++ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
++ args = NULL;
++ }
++
++ goto out_unlock; /* success */
++ }
++
++ /* revert */
++ AuLabel(revert);
++ if (wh_dentry) {
++ int rerr;
++
++ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ if (rerr)
++ err = rerr;
++ }
++
++ out_unlock:
++ au_unpin(&pin);
++ dput(wh_dentry);
++ dput(h_dentry);
++ out_args:
++ di_write_unlock(parent);
++ aufs_read_unlock(dentry, AuLock_DW);
++ if (args)
++ au_whtmp_rmdir_free(args);
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
+--- a/fs/aufs/i_op_ren.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_ren.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,942 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * inode operation (rename entry)
++ * todo: this is crazy monster
++ */
++
++#include "aufs.h"
++
++enum { AuSRC, AuDST, AuSrcDst };
++enum { AuPARENT, AuCHILD, AuParentChild };
++
++#define AuRen_ISDIR 1
++#define AuRen_ISSAMEDIR (1 << 1)
++#define AuRen_WHSRC (1 << 2)
++#define AuRen_WHDST (1 << 3)
++#define AuRen_MNT_WRITE (1 << 4)
++#define AuRen_DT_DSTDIR (1 << 5)
++#define AuRen_DIROPQ (1 << 6)
++#define AuRen_CPUP (1 << 7)
++#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
++#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
++#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
++
++struct au_ren_args {
++ struct {
++ struct dentry *dentry, *h_dentry, *parent, *h_parent,
++ *wh_dentry;
++ struct inode *dir, *inode;
++ struct au_hinode *hdir;
++ struct au_dtime dt[AuParentChild];
++ aufs_bindex_t bstart;
++ } sd[AuSrcDst];
++
++#define src_dentry sd[AuSRC].dentry
++#define src_dir sd[AuSRC].dir
++#define src_inode sd[AuSRC].inode
++#define src_h_dentry sd[AuSRC].h_dentry
++#define src_parent sd[AuSRC].parent
++#define src_h_parent sd[AuSRC].h_parent
++#define src_wh_dentry sd[AuSRC].wh_dentry
++#define src_hdir sd[AuSRC].hdir
++#define src_h_dir sd[AuSRC].hdir->hi_inode
++#define src_dt sd[AuSRC].dt
++#define src_bstart sd[AuSRC].bstart
++
++#define dst_dentry sd[AuDST].dentry
++#define dst_dir sd[AuDST].dir
++#define dst_inode sd[AuDST].inode
++#define dst_h_dentry sd[AuDST].h_dentry
++#define dst_parent sd[AuDST].parent
++#define dst_h_parent sd[AuDST].h_parent
++#define dst_wh_dentry sd[AuDST].wh_dentry
++#define dst_hdir sd[AuDST].hdir
++#define dst_h_dir sd[AuDST].hdir->hi_inode
++#define dst_dt sd[AuDST].dt
++#define dst_bstart sd[AuDST].bstart
++
++ struct dentry *h_trap;
++ struct au_branch *br;
++ struct au_hinode *src_hinode;
++ struct path h_path;
++ struct au_nhash whlist;
++ aufs_bindex_t btgt;
++
++ unsigned int flags;
++
++ struct au_whtmp_rmdir *thargs;
++ struct dentry *h_dst;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * functions for reverting.
++ * when an error happened in a single rename systemcall, we should revert
++ * everything as if nothing happend.
++ * we don't need to revert the copied-up/down the parent dir since they are
++ * harmless.
++ */
++
++#define RevertFailure(fmt, args...) do { \
++ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
++ ##args, err, rerr); \
++ err = -EIO; \
++} while (0)
++
++static void au_ren_rev_diropq(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(a->src_dentry, a->btgt);
++ au_hin_imtx_unlock(a->src_hinode);
++ if (rerr)
++ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
++}
++
++
++static void au_ren_rev_rename(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
++ a->br, /*nd*/NULL);
++ rerr = PTR_ERR(a->h_path.dentry);
++ if (IS_ERR(a->h_path.dentry)) {
++ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
++ return;
++ }
++
++ rerr = vfsub_rename(a->dst_h_dir,
++ au_h_dptr(a->src_dentry, a->btgt),
++ a->src_h_dir, &a->h_path);
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
++ if (rerr)
++ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
++}
++
++static void au_ren_rev_cpup(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = a->dst_h_dentry;
++ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
++ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
++ au_set_dbstart(a->src_dentry, a->src_bstart);
++ if (rerr)
++ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
++}
++
++
++static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
++ a->br, /*nd*/NULL);
++ rerr = PTR_ERR(a->h_path.dentry);
++ if (IS_ERR(a->h_path.dentry)) {
++ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
++ return;
++ }
++ if (a->h_path.dentry->d_inode) {
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ return;
++ }
++
++ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
++ d_drop(a->h_path.dentry);
++ dput(a->h_path.dentry);
++ if (!rerr) {
++ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
++ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
++ } else
++ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
++}
++
++static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
++{
++ int rerr;
++
++ a->h_path.dentry = a->src_wh_dentry;
++ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
++ if (rerr)
++ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
++}
++
++static void au_ren_rev_drop(struct au_ren_args *a)
++{
++ struct dentry *d, *h_d;
++ int i;
++ aufs_bindex_t bend, bindex;
++
++ for (i = 0; i < AuSrcDst; i++) {
++ d = a->sd[i].dentry;
++ d_drop(d);
++ bend = au_dbend(d);
++ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
++ h_d = au_h_dptr(d, bindex);
++ if (h_d)
++ d_drop(h_d);
++ }
++ }
++
++ au_update_dbstart(a->dst_dentry);
++ if (a->thargs)
++ d_drop(a->h_dst);
++}
++#undef RevertFailure
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * when we have to copyup the renaming entry, do it with the rename-target name
++ * in order to minimize the cost (the later actual rename is unnecessary).
++ * otherwise rename it on the target branch.
++ */
++static int au_ren_or_cpup(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d;
++
++ d = a->src_dentry;
++ if (au_dbstart(d) == a->btgt) {
++ a->h_path.dentry = a->dst_h_dentry;
++ if (au_ftest_ren(a->flags, DIROPQ)
++ && au_dbdiropq(d) == a->btgt)
++ au_fclr_ren(a->flags, DIROPQ);
++ AuDebugOn(au_dbstart(d) != a->btgt);
++ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
++ a->dst_h_dir, &a->h_path);
++ } else {
++ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++ au_fset_ren(a->flags, CPUP);
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_set_dbstart(d, a->btgt);
++ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
++ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
++ !AuCpup_DTIME, a->dst_parent);
++ if (unlikely(err)) {
++ au_set_h_dptr(d, a->btgt, NULL);
++ au_set_dbstart(d, a->src_bstart);
++ }
++ mutex_unlock(h_mtx);
++ }
++
++ return err;
++}
++
++/* cf. aufs_rmdir() */
++static int au_ren_del_whtmp(struct au_ren_args *a)
++{
++ int err;
++ struct inode *dir;
++
++ dir = a->dst_dir;
++ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
++ au_sbi(dir->i_sb)->si_dirwh)
++ || au_test_fs_remote(a->h_dst->d_sb)) {
++ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
++ if (unlikely(err))
++ AuWarn("failed removing whtmp dir %.*s (%d), "
++ "ignored.\n", AuDLNPair(a->h_dst), err);
++ } else {
++ au_nhash_wh_free(&a->thargs->whlist);
++ a->thargs->whlist = a->whlist;
++ a->whlist.nh_num = 0;
++ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
++ dput(a->h_dst);
++ a->thargs = NULL;
++ }
++
++ return 0;
++}
++
++/* make it 'opaque' dir. */
++static int au_ren_diropq(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *diropq;
++
++ err = 0;
++ a->src_hinode = au_hi(a->src_inode, a->btgt);
++ au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++ diropq = au_diropq_create(a->src_dentry, a->btgt);
++ au_hin_imtx_unlock(a->src_hinode);
++ if (IS_ERR(diropq))
++ err = PTR_ERR(diropq);
++ dput(diropq);
++
++ return err;
++}
++
++static int do_rename(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d, *h_d;
++
++ /* prepare workqueue args for asynchronous rmdir */
++ h_d = a->dst_h_dentry;
++ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
++ err = -ENOMEM;
++ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
++ if (unlikely(!a->thargs))
++ goto out;
++ a->h_dst = dget(h_d);
++ }
++
++ /* create whiteout for src_dentry */
++ if (au_ftest_ren(a->flags, WHSRC)) {
++ a->src_wh_dentry
++ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
++ err = PTR_ERR(a->src_wh_dentry);
++ if (IS_ERR(a->src_wh_dentry))
++ goto out_thargs;
++ }
++
++ /* lookup whiteout for dentry */
++ if (au_ftest_ren(a->flags, WHDST)) {
++ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
++ a->br);
++ err = PTR_ERR(h_d);
++ if (IS_ERR(h_d))
++ goto out_whsrc;
++ if (!h_d->d_inode)
++ dput(h_d);
++ else
++ a->dst_wh_dentry = h_d;
++ }
++
++ /* rename dentry to tmpwh */
++ if (a->thargs) {
++ err = au_whtmp_ren(a->dst_h_dentry, a->br);
++ if (unlikely(err))
++ goto out_whdst;
++
++ d = a->dst_dentry;
++ au_set_h_dptr(d, a->btgt, NULL);
++ err = au_lkup_neg(d, a->btgt);
++ if (unlikely(err))
++ goto out_whtmp;
++ a->dst_h_dentry = au_h_dptr(d, a->btgt);
++ }
++
++ /* cpup src */
++ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
++ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
++ !AuCpup_DTIME);
++ mutex_unlock(h_mtx);
++ if (unlikely(err))
++ goto out_whtmp;
++ }
++
++ /* rename by vfs_rename or cpup */
++ d = a->dst_dentry;
++ if (au_ftest_ren(a->flags, ISDIR)
++ && (a->dst_wh_dentry
++ || au_dbdiropq(d) == a->btgt
++ /* hide the lower to keep xino */
++ || a->btgt < au_dbend(d)
++ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
++ au_fset_ren(a->flags, DIROPQ);
++ err = au_ren_or_cpup(a);
++ if (unlikely(err))
++ /* leave the copied-up one */
++ goto out_whtmp;
++
++ /* make dir opaque */
++ if (au_ftest_ren(a->flags, DIROPQ)) {
++ err = au_ren_diropq(a);
++ if (unlikely(err))
++ goto out_rename;
++ }
++
++ /* update target timestamps */
++ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
++ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
++ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
++
++ /* remove whiteout for dentry */
++ if (a->dst_wh_dentry) {
++ a->h_path.dentry = a->dst_wh_dentry;
++ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
++ a->dst_dentry);
++ if (unlikely(err))
++ goto out_diropq;
++ }
++
++ /* remove whtmp */
++ if (a->thargs)
++ au_ren_del_whtmp(a); /* ignore this error */
++
++ err = 0;
++ goto out_success;
++
++ out_diropq:
++ if (au_ftest_ren(a->flags, DIROPQ))
++ au_ren_rev_diropq(err, a);
++ out_rename:
++ if (!au_ftest_ren(a->flags, CPUP))
++ au_ren_rev_rename(err, a);
++ else
++ au_ren_rev_cpup(err, a);
++ out_whtmp:
++ if (a->thargs)
++ au_ren_rev_whtmp(err, a);
++ out_whdst:
++ dput(a->dst_wh_dentry);
++ a->dst_wh_dentry = NULL;
++ out_whsrc:
++ if (a->src_wh_dentry)
++ au_ren_rev_whsrc(err, a);
++ au_ren_rev_drop(a);
++ out_success:
++ dput(a->src_wh_dentry);
++ dput(a->dst_wh_dentry);
++ out_thargs:
++ if (a->thargs) {
++ dput(a->h_dst);
++ au_whtmp_rmdir_free(a->thargs);
++ a->thargs = NULL;
++ }
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if @dentry dir can be rename destination or not.
++ * success means, it is a logically empty dir.
++ */
++static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
++{
++ return au_test_empty(dentry, whlist);
++}
++
++/*
++ * test if @dentry dir can be rename source or not.
++ * if it can, return 0 and @children is filled.
++ * success means,
++ * - it is a logically empty dir.
++ * - or, it exists on writable branch and has no children including whiteouts
++ * on the lower branch.
++ */
++static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ int err;
++ aufs_bindex_t bstart;
++
++ bstart = au_dbstart(dentry);
++ if (bstart != btgt) {
++ struct au_nhash whlist;
++
++ err = au_nhash_alloc(&whlist, au_sbi(dentry->d_sb)->si_rdhash,
++ GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_test_empty(dentry, &whlist);
++ au_nhash_wh_free(&whlist);
++ goto out;
++ }
++
++ if (bstart == au_dbtaildir(dentry))
++ return 0; /* success */
++
++ err = au_test_empty_lower(dentry);
++
++ out:
++ if (err == -ENOTEMPTY) {
++ AuWarn1("renaming dir who has child(ren) on multiple branches,"
++ " is not supported\n");
++ err = -EXDEV;
++ }
++ return err;
++}
++
++/* side effect: sets whlist and h_dentry */
++static int au_ren_may_dir(struct au_ren_args *a)
++{
++ int err;
++ struct dentry *d;
++
++ d = a->dst_dentry;
++ err = au_nhash_alloc(&a->whlist, au_sbi(d->d_sb)->si_rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++
++ err = 0;
++ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
++ au_set_dbstart(d, a->dst_bstart);
++ err = may_rename_dstdir(d, &a->whlist);
++ au_set_dbstart(d, a->btgt);
++ }
++ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
++ if (unlikely(err))
++ goto out;
++
++ d = a->src_dentry;
++ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
++ if (au_ftest_ren(a->flags, ISDIR)) {
++ err = may_rename_srcdir(d, a->btgt);
++ if (unlikely(err)) {
++ au_nhash_wh_free(&a->whlist);
++ a->whlist.nh_num = 0;
++ }
++ }
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * simple tests for rename.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++static int au_may_ren(struct au_ren_args *a)
++{
++ int err, isdir;
++ struct inode *h_inode;
++
++ if (a->src_bstart == a->btgt) {
++ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
++ au_ftest_ren(a->flags, ISDIR));
++ if (unlikely(err))
++ goto out;
++ err = -EINVAL;
++ if (unlikely(a->src_h_dentry == a->h_trap))
++ goto out;
++ }
++
++ err = 0;
++ if (a->dst_bstart != a->btgt)
++ goto out;
++
++ err = -EIO;
++ h_inode = a->dst_h_dentry->d_inode;
++ isdir = !!au_ftest_ren(a->flags, ISDIR);
++ if (!a->dst_dentry->d_inode) {
++ if (unlikely(h_inode))
++ goto out;
++ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
++ isdir);
++ } else {
++ if (unlikely(!h_inode || !h_inode->i_nlink))
++ goto out;
++ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
++ isdir);
++ if (unlikely(err))
++ goto out;
++ err = -ENOTEMPTY;
++ if (unlikely(a->dst_h_dentry == a->h_trap))
++ goto out;
++ err = 0;
++ }
++
++ out:
++ if (unlikely(err == -ENOENT || err == -EEXIST))
++ err = -EIO;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * locking order
++ * (VFS)
++ * - src_dir and dir by lock_rename()
++ * - inode if exitsts
++ * (aufs)
++ * - lock all
++ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
++ * + si_read_lock
++ * + di_write_lock2_child()
++ * + di_write_lock_child()
++ * + ii_write_lock_child()
++ * + di_write_lock_child2()
++ * + ii_write_lock_child2()
++ * + src_parent and parent
++ * + di_write_lock_parent()
++ * + ii_write_lock_parent()
++ * + di_write_lock_parent2()
++ * + ii_write_lock_parent2()
++ * + lower src_dir and dir by vfsub_lock_rename()
++ * + verify the every relationships between child and parent. if any
++ * of them failed, unlock all and return -EBUSY.
++ */
++static void au_ren_unlock(struct au_ren_args *a)
++{
++ struct super_block *sb;
++
++ sb = a->dst_dentry->d_sb;
++ if (au_ftest_ren(a->flags, MNT_WRITE))
++ mnt_drop_write(a->br->br_mnt);
++ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
++ a->dst_h_parent, a->dst_hdir);
++}
++
++static int au_ren_lock(struct au_ren_args *a)
++{
++ int err;
++ unsigned int udba;
++
++ err = 0;
++ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
++ a->src_hdir = au_hi(a->src_dir, a->btgt);
++ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
++ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
++ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
++ a->dst_h_parent, a->dst_hdir);
++ udba = au_opt_udba(a->src_dentry->d_sb);
++ if (au_dbstart(a->src_dentry) == a->btgt)
++ err = au_h_verify(a->src_h_dentry, udba,
++ a->src_h_parent->d_inode, a->src_h_parent,
++ a->br);
++ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
++ err = au_h_verify(a->dst_h_dentry, udba,
++ a->dst_h_parent->d_inode, a->dst_h_parent,
++ a->br);
++ if (!err) {
++ err = mnt_want_write(a->br->br_mnt);
++ if (unlikely(err))
++ goto out_unlock;
++ au_fset_ren(a->flags, MNT_WRITE);
++ goto out; /* success */
++ }
++
++ err = au_busy_or_stale();
++
++ out_unlock:
++ au_ren_unlock(a);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_ren_refresh_dir(struct au_ren_args *a)
++{
++ struct inode *dir;
++
++ dir = a->dst_dir;
++ dir->i_version++;
++ if (au_ftest_ren(a->flags, ISDIR)) {
++ /* is this updating defined in POSIX? */
++ au_cpup_attr_timesizes(a->src_inode);
++ au_cpup_attr_nlink(dir, /*force*/1);
++ if (a->dst_inode) {
++ clear_nlink(a->dst_inode);
++ au_cpup_attr_timesizes(a->dst_inode);
++ }
++ }
++ if (au_ibstart(dir) == a->btgt)
++ au_cpup_attr_timesizes(dir);
++
++ if (au_ftest_ren(a->flags, ISSAMEDIR))
++ return;
++
++ dir = a->src_dir;
++ dir->i_version++;
++ if (au_ftest_ren(a->flags, ISDIR))
++ au_cpup_attr_nlink(dir, /*force*/1);
++ if (au_ibstart(dir) == a->btgt)
++ au_cpup_attr_timesizes(dir);
++}
++
++static void au_ren_refresh(struct au_ren_args *a)
++{
++ aufs_bindex_t bend, bindex;
++ struct dentry *d, *h_d;
++ struct inode *i, *h_i;
++ struct super_block *sb;
++
++ d = a->src_dentry;
++ au_set_dbwh(d, -1);
++ bend = au_dbend(d);
++ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++ h_d = au_h_dptr(d, bindex);
++ if (h_d)
++ au_set_h_dptr(d, bindex, NULL);
++ }
++ au_set_dbend(d, a->btgt);
++
++ sb = d->d_sb;
++ i = a->src_inode;
++ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
++ return; /* success */
++
++ bend = au_ibend(i);
++ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++ h_i = au_h_iptr(i, bindex);
++ if (h_i) {
++ au_xino_write0(sb, bindex, h_i->i_ino, 0);
++ /* ignore this error */
++ au_set_h_iptr(i, bindex, NULL, 0);
++ }
++ }
++ au_set_ibend(i, a->btgt);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* mainly for link(2) and rename(2) */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
++{
++ aufs_bindex_t bdiropq, bwh;
++ struct dentry *parent;
++ struct au_branch *br;
++
++ parent = dentry->d_parent;
++ IMustLock(parent->d_inode); /* dir is locked */
++
++ bdiropq = au_dbdiropq(parent);
++ bwh = au_dbwh(dentry);
++ br = au_sbr(dentry->d_sb, btgt);
++ if (au_br_rdonly(br)
++ || (0 <= bdiropq && bdiropq < btgt)
++ || (0 <= bwh && bwh < btgt))
++ btgt = -1;
++
++ AuDbg("btgt %d\n", btgt);
++ return btgt;
++}
++
++/* sets src_bstart, dst_bstart and btgt */
++static int au_ren_wbr(struct au_ren_args *a)
++{
++ int err;
++ struct au_wr_dir_args wr_dir_args = {
++ /* .force_btgt = -1, */
++ .flags = AuWrDir_ADD_ENTRY
++ };
++
++ a->src_bstart = au_dbstart(a->src_dentry);
++ a->dst_bstart = au_dbstart(a->dst_dentry);
++ if (au_ftest_ren(a->flags, ISDIR))
++ au_fset_wrdir(wr_dir_args.flags, ISDIR);
++ wr_dir_args.force_btgt = a->src_bstart;
++ if (a->dst_inode && a->dst_bstart < a->src_bstart)
++ wr_dir_args.force_btgt = a->dst_bstart;
++ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
++ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
++ a->btgt = err;
++
++ return err;
++}
++
++static void au_ren_dt(struct au_ren_args *a)
++{
++ a->h_path.dentry = a->src_h_parent;
++ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
++ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
++ a->h_path.dentry = a->dst_h_parent;
++ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
++ }
++
++ au_fclr_ren(a->flags, DT_DSTDIR);
++ if (!au_ftest_ren(a->flags, ISDIR))
++ return;
++
++ a->h_path.dentry = a->src_h_dentry;
++ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
++ if (a->dst_h_dentry->d_inode) {
++ au_fset_ren(a->flags, DT_DSTDIR);
++ a->h_path.dentry = a->dst_h_dentry;
++ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
++ }
++}
++
++static void au_ren_rev_dt(int err, struct au_ren_args *a)
++{
++ struct dentry *h_d;
++ struct mutex *h_mtx;
++
++ au_dtime_revert(a->src_dt + AuPARENT);
++ if (!au_ftest_ren(a->flags, ISSAMEDIR))
++ au_dtime_revert(a->dst_dt + AuPARENT);
++
++ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
++ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_dtime_revert(a->src_dt + AuCHILD);
++ mutex_unlock(h_mtx);
++
++ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
++ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
++ h_mtx = &h_d->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++ au_dtime_revert(a->dst_dt + AuCHILD);
++ mutex_unlock(h_mtx);
++ }
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
++ struct inode *_dst_dir, struct dentry *_dst_dentry)
++{
++ int err;
++ /* reduce stack space */
++ struct au_ren_args *a;
++
++ IMustLock(_src_dir);
++ IMustLock(_dst_dir);
++
++ err = -ENOMEM;
++ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ a->src_dir = _src_dir;
++ a->src_dentry = _src_dentry;
++ a->src_inode = a->src_dentry->d_inode;
++ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
++ a->dst_dir = _dst_dir;
++ a->dst_dentry = _dst_dentry;
++ a->dst_inode = a->dst_dentry->d_inode;
++ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
++ if (a->dst_inode) {
++ IMustLock(a->dst_inode);
++ au_igrab(a->dst_inode);
++ }
++
++ err = -ENOTDIR;
++ if (S_ISDIR(a->src_inode->i_mode)) {
++ au_fset_ren(a->flags, ISDIR);
++ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
++ goto out_free;
++ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++ AuLock_DIR | AuLock_FLUSH);
++ } else
++ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++ AuLock_FLUSH);
++
++ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
++ di_write_lock_parent(a->dst_parent);
++
++ /* which branch we process */
++ err = au_ren_wbr(a);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
++ a->h_path.mnt = a->br->br_mnt;
++
++ /* are they available to be renamed */
++ err = au_ren_may_dir(a);
++ if (unlikely(err))
++ goto out_unlock;
++
++ /* prepare the writable parent dir on the same branch */
++ if (a->dst_bstart == a->btgt) {
++ au_fset_ren(a->flags, WHDST);
++ } else {
++ err = au_cpup_dirs(a->dst_dentry, a->btgt);
++ if (unlikely(err))
++ goto out_children;
++ }
++
++ if (a->src_dir != a->dst_dir) {
++ /*
++ * this temporary unlock is safe,
++ * because both dir->i_mutex are locked.
++ */
++ di_write_unlock(a->dst_parent);
++ di_write_lock_parent(a->src_parent);
++ err = au_wr_dir_need_wh(a->src_dentry,
++ au_ftest_ren(a->flags, ISDIR),
++ &a->btgt);
++ di_write_unlock(a->src_parent);
++ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
++ au_fclr_ren(a->flags, ISSAMEDIR);
++ } else
++ err = au_wr_dir_need_wh(a->src_dentry,
++ au_ftest_ren(a->flags, ISDIR),
++ &a->btgt);
++ if (unlikely(err < 0))
++ goto out_children;
++ if (err)
++ au_fset_ren(a->flags, WHSRC);
++
++ /* lock them all */
++ err = au_ren_lock(a);
++ if (unlikely(err))
++ goto out_children;
++
++ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) {
++ err = au_may_ren(a);
++ if (unlikely(err))
++ goto out_hdir;
++ }
++
++ /* store timestamps to be revertible */
++ au_ren_dt(a);
++
++ /* here we go */
++ err = do_rename(a);
++ if (unlikely(err))
++ goto out_dt;
++
++ /* update dir attributes */
++ au_ren_refresh_dir(a);
++
++ /* dput/iput all lower dentries */
++ au_ren_refresh(a);
++
++ goto out_hdir; /* success */
++
++ out_dt:
++ au_ren_rev_dt(err, a);
++ out_hdir:
++ au_ren_unlock(a);
++ out_children:
++ au_nhash_wh_free(&a->whlist);
++ out_unlock:
++ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
++ au_update_dbstart(a->dst_dentry);
++ d_drop(a->dst_dentry);
++ }
++ if (!err)
++ d_move(a->src_dentry, a->dst_dentry);
++ if (au_ftest_ren(a->flags, ISSAMEDIR))
++ di_write_unlock(a->dst_parent);
++ else
++ di_write_unlock2(a->src_parent, a->dst_parent);
++ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
++ out_free:
++ iput(a->dst_inode);
++ if (a->thargs)
++ au_whtmp_rmdir_free(a->thargs);
++ kfree(a);
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/Kconfig b/fs/aufs/Kconfig
+--- a/fs/aufs/Kconfig 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Kconfig 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,117 @@
++config AUFS_FS
++ tristate "Aufs (Advanced multi layered unification filesystem) support"
++ depends on EXPERIMENTAL
++ help
++ Aufs is a stackable unification filesystem such as Unionfs,
++ which unifies several directories and provides a merged single
++ directory.
++ In the early days, aufs was entirely re-designed and
++ re-implemented Unionfs Version 1.x series. Introducing many
++ original ideas, approaches and improvements, it becomes totally
++ different from Unionfs while keeping the basic features.
++
++if AUFS_FS
++choice
++ prompt "Maximum number of branches"
++ default AUFS_BRANCH_MAX_127
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_127
++ bool "127"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_511
++ bool "511"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_1023
++ bool "1023"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++config AUFS_BRANCH_MAX_32767
++ bool "32767"
++ help
++ Specifies the maximum number of branches (or member directories)
++ in a single aufs. The larger value consumes more system
++ resources and has a minor impact to performance.
++endchoice
++
++config AUFS_HINOTIFY
++ bool "Use inotify to detect actions on a branch"
++ depends on INOTIFY
++ help
++ If you want to modify files on branches directly, eg. bypassing aufs,
++ and want aufs to detect the changes of them fully, then enable this
++ option and use 'udba=inotify' mount option.
++ It will have a negative impact to the performance.
++ See detail in aufs.5.
++
++config AUFS_EXPORT
++ bool "NFS-exportable aufs"
++ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
++ help
++ If you want to export your mounted aufs via NFS, then enable this
++ option. There are several requirements for this configuration.
++ See detail in aufs.5.
++
++config AUFS_SHWH
++ bool "Show whiteouts"
++ help
++ If you want to make the whiteouts in aufs visible, then enable
++ this option and specify 'shwh' mount option. Although it may
++ sounds like philosophy or something, but in technically it
++ simply shows the name of whiteout with keeping its behaviour.
++
++config AUFS_BR_RAMFS
++ bool "Ramfs (initramfs/rootfs) as an aufs branch"
++ help
++ If you want to use ramfs as an aufs branch fs, then enable this
++ option. Generally tmpfs is recommended.
++ Aufs prohibited them to be a branch fs by default, because
++ initramfs becomes unusable after switch_root or something
++ generally. If you sets initramfs as an aufs branch and boot your
++ system by switch_root, you will meet a problem easily since the
++ files in initramfs may be inaccessible.
++ Unless you are going to use ramfs as an aufs branch fs without
++ switch_root or something, leave it N.
++
++config AUFS_DEBUG
++ bool "Debug aufs"
++ help
++ Enable this to compile aufs internal debug code.
++ It will have a negative impact to the performance.
++
++config AUFS_MAGIC_SYSRQ
++ bool
++ depends on AUFS_DEBUG && MAGIC_SYSRQ
++ default y
++ help
++ Automatic configuration for internal use.
++ When aufs supports Magic SysRq, enabled automatically.
++
++config AUFS_BDEV_LOOP
++ bool
++ depends on BLK_DEV_LOOP
++ default y
++ help
++ Automatic configuration for internal use.
++ Convert =[ym] into =y.
++
++config AUFS_INO_T_64
++ bool
++ depends on AUFS_EXPORT
++ depends on 64BIT && !(ALPHA || S390)
++ default y
++ help
++ Automatic configuration for internal use.
++ /* typedef unsigned long/int __kernel_ino_t */
++ /* alpha and s390x are int */
++endif
+diff -Naur a/fs/aufs/loop.c b/fs/aufs/loop.c
+--- a/fs/aufs/loop.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * support for loopback block device as a branch
++ */
++
++#include <linux/loop.h>
++#include "aufs.h"
++
++/*
++ * test if two lower dentries have overlapping branches.
++ */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ struct inode *h_inode;
++ struct loop_device *l;
++
++ h_inode = h_d1->d_inode;
++ if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
++ return 0;
++
++ l = h_inode->i_sb->s_bdev->bd_disk->private_data;
++ h_d1 = l->lo_backing_file->f_dentry;
++ /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
++ if (unlikely(h_d1->d_sb == sb))
++ return 1;
++ return !!au_test_subdir(h_d1, h_d2);
++}
++
++/* true if a kernel thread named 'loop[0-9].*' accesses a file */
++int au_test_loopback_kthread(void)
++{
++ const char c = current->comm[4];
++
++ return current->mm == NULL
++ && '0' <= c && c <= '9'
++ && strncmp(current->comm, "loop", 4) == 0;
++}
+diff -Naur a/fs/aufs/loop.h b/fs/aufs/loop.h
+--- a/fs/aufs/loop.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * support for loopback mount as a branch
++ */
++
++#ifndef __AUFS_LOOP_H__
++#define __AUFS_LOOP_H__
++
++#ifdef __KERNEL__
++
++struct dentry;
++struct super_block;
++
++#ifdef CONFIG_AUFS_BDEV_LOOP
++/* loop.c */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2);
++int au_test_loopback_kthread(void);
++#else
++static inline
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++ struct dentry *h_d2)
++{
++ return 0;
++}
++
++static inline int au_test_loopback_kthread(void)
++{
++ return 0;
++}
++#endif /* BLK_DEV_LOOP */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_LOOP_H__ */
+diff -Naur a/fs/aufs/magic.mk b/fs/aufs/magic.mk
+--- a/fs/aufs/magic.mk 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/magic.mk 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,52 @@
++
++# defined in ${srctree}/fs/fuse/inode.c
++# tristate
++ifdef CONFIG_FUSE_FS
++ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
++endif
++
++# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
++# tristate
++ifdef CONFIG_OCFS2_FS
++ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
++endif
++
++# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
++# tristate
++ifdef CONFIG_OCFS2_FS_O2CB
++ccflags-y += -DDLMFS_MAGIC=0x76a9f425
++endif
++
++# defined in ${srctree}/fs/ramfs/inode.c
++# always true
++ccflags-y += -DRAMFS_MAGIC=0x858458f6
++
++# defined in ${srctree}/fs/cifs/cifsfs.c
++# tristate
++ifdef CONFIG_CIFS_FS
++ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
++endif
++
++# defined in ${srctree}/fs/xfs/xfs_sb.h
++# tristate
++ifdef CONFIG_XFS_FS
++ccflags-y += -DXFS_SB_MAGIC=0x58465342
++endif
++
++# defined in ${srctree}/fs/configfs/mount.c
++# tristate
++ifdef CONFIG_CONFIGFS_FS
++ccflags-y += -DCONFIGFS_MAGIC=0x62656570
++endif
++
++# defined in ${srctree}/fs/9p/v9fs.h
++# tristate
++ifdef CONFIG_9P_FS
++ccflags-y += -DV9FS_MAGIC=0x01021997
++endif
++
++# defined in ${srctree}/fs/ubifs/ubifs.h
++# tristate
++ifdef CONFIG_UBIFS_FS
++ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
++endif
+diff -Naur a/fs/aufs/Makefile b/fs/aufs/Makefile
+--- a/fs/aufs/Makefile 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Makefile 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,22 @@
++
++include ${src}/magic.mk
++-include ${src}/priv_def.mk
++
++obj-$(CONFIG_AUFS_FS) += aufs.o
++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
++ wkq.o vfsub.o dcsub.o \
++ cpup.o whout.o plink.o wbr_policy.o \
++ dinfo.o dentry.o \
++ finfo.o file.o f_op.o \
++ dir.o vdir.o \
++ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
++ ioctl.o
++
++# all are boolean
++aufs-$(CONFIG_SYSFS) += sysfs.o
++aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
++aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
++aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
++aufs-$(CONFIG_AUFS_EXPORT) += export.o
++aufs-$(CONFIG_AUFS_DEBUG) += debug.o
++aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
+diff -Naur a/fs/aufs/module.c b/fs/aufs/module.c
+--- a/fs/aufs/module.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * module global variables and operations
++ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include "aufs.h"
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
++{
++ if (new_sz <= nused)
++ return p;
++
++ p = krealloc(p, new_sz, gfp);
++ if (p)
++ memset(p + nused, 0, new_sz - nused);
++ return p;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * aufs caches
++ */
++struct kmem_cache *au_cachep[AuCache_Last];
++static int __init au_cache_init(void)
++{
++ au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
++ if (au_cachep[AuCache_DINFO])
++ au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
++ if (au_cachep[AuCache_ICNTNR])
++ au_cachep[AuCache_FINFO] = AuCache(au_finfo);
++ if (au_cachep[AuCache_FINFO])
++ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
++ if (au_cachep[AuCache_VDIR])
++ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
++ if (au_cachep[AuCache_DEHSTR])
++ return 0;
++
++ return -ENOMEM;
++}
++
++static void au_cache_fin(void)
++{
++ int i;
++ for (i = 0; i < AuCache_Last; i++)
++ if (au_cachep[i]) {
++ kmem_cache_destroy(au_cachep[i]);
++ au_cachep[i] = NULL;
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_dir_roflags;
++
++/*
++ * functions for module interface.
++ */
++MODULE_LICENSE("GPL");
++/* MODULE_LICENSE("GPL v2"); */
++MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
++MODULE_DESCRIPTION(AUFS_NAME
++ " -- Advanced multi layered unification filesystem");
++MODULE_VERSION(AUFS_VERSION);
++
++/* it should be 'byte', but param_set_byte() prints it by "%c" */
++short aufs_nwkq = AUFS_NWKQ_DEF;
++MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
++module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
++
++/* this module parameter has no meaning when SYSFS is disabled */
++int sysaufs_brs = 1;
++MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
++module_param_named(brs, sysaufs_brs, int, S_IRUGO);
++
++/* ---------------------------------------------------------------------- */
++
++static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
++
++int au_seq_path(struct seq_file *seq, struct path *path)
++{
++ return seq_path(seq, path, au_esc_chars);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int __init aufs_init(void)
++{
++ int err, i;
++ char *p;
++
++ p = au_esc_chars;
++ for (i = 1; i <= ' '; i++)
++ *p++ = i;
++ *p++ = '\\';
++ *p++ = '\x7f';
++ *p = 0;
++
++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
++
++ sysaufs_brs_init();
++ au_debug_init();
++
++ err = -EINVAL;
++ if (unlikely(aufs_nwkq <= 0))
++ goto out;
++
++ err = sysaufs_init();
++ if (unlikely(err))
++ goto out;
++ err = au_wkq_init();
++ if (unlikely(err))
++ goto out_sysaufs;
++ err = au_hinotify_init();
++ if (unlikely(err))
++ goto out_wkq;
++ err = au_sysrq_init();
++ if (unlikely(err))
++ goto out_hin;
++ err = au_cache_init();
++ if (unlikely(err))
++ goto out_sysrq;
++ err = register_filesystem(&aufs_fs_type);
++ if (unlikely(err))
++ goto out_cache;
++ pr_info(AUFS_NAME " " AUFS_VERSION "\n");
++ goto out; /* success */
++
++ out_cache:
++ au_cache_fin();
++ out_sysrq:
++ au_sysrq_fin();
++ out_hin:
++ au_hinotify_fin();
++ out_wkq:
++ au_wkq_fin();
++ out_sysaufs:
++ sysaufs_fin();
++ out:
++ return err;
++}
++
++static void __exit aufs_exit(void)
++{
++ unregister_filesystem(&aufs_fs_type);
++ au_cache_fin();
++ au_sysrq_fin();
++ au_hinotify_fin();
++ au_wkq_fin();
++ sysaufs_fin();
++}
++
++module_init(aufs_init);
++module_exit(aufs_exit);
+diff -Naur a/fs/aufs/module.h b/fs/aufs/module.h
+--- a/fs/aufs/module.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * module initialization and module-global
++ */
++
++#ifndef __AUFS_MODULE_H__
++#define __AUFS_MODULE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/slab.h>
++
++struct path;
++struct seq_file;
++
++/* module parameters */
++extern short aufs_nwkq;
++extern int sysaufs_brs;
++
++/* ---------------------------------------------------------------------- */
++
++extern int au_dir_roflags;
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
++int au_seq_path(struct seq_file *seq, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++/* kmem cache */
++enum {
++ AuCache_DINFO,
++ AuCache_ICNTNR,
++ AuCache_FINFO,
++ AuCache_VDIR,
++ AuCache_DEHSTR,
++#ifdef CONFIG_AUFS_HINOTIFY
++ AuCache_HINOTIFY,
++#endif
++ AuCache_Last
++};
++
++#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
++
++extern struct kmem_cache *au_cachep[];
++
++#define AuCacheFuncs(name, index) \
++static inline void *au_cache_alloc_##name(void) \
++{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
++static inline void au_cache_free_##name(void *p) \
++{ kmem_cache_free(au_cachep[AuCache_##index], p); }
++
++AuCacheFuncs(dinfo, DINFO);
++AuCacheFuncs(icntnr, ICNTNR);
++AuCacheFuncs(finfo, FINFO);
++AuCacheFuncs(vdir, VDIR);
++AuCacheFuncs(dehstr, DEHSTR);
++
++/* ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MODULE_H__ */
+diff -Naur a/fs/aufs/opts.c b/fs/aufs/opts.c
+--- a/fs/aufs/opts.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1533 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount options/flags
++ */
++
++#include <linux/file.h>
++#include <linux/namei.h>
++#include <linux/types.h> /* a distribution requires */
++#include <linux/parser.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++enum {
++ Opt_br,
++ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
++ Opt_idel, Opt_imod, Opt_ireorder,
++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
++ Opt_rdblk_def, Opt_rdhash_def,
++ Opt_xino, Opt_zxino, Opt_noxino,
++ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
++ Opt_trunc_xino_path, Opt_itrunc_xino,
++ Opt_trunc_xib, Opt_notrunc_xib,
++ Opt_shwh, Opt_noshwh,
++ Opt_plink, Opt_noplink, Opt_list_plink,
++ Opt_udba,
++ /* Opt_lock, Opt_unlock, */
++ Opt_cmd, Opt_cmd_args,
++ Opt_diropq_a, Opt_diropq_w,
++ Opt_warn_perm, Opt_nowarn_perm,
++ Opt_wbr_copyup, Opt_wbr_create,
++ Opt_refrof, Opt_norefrof,
++ Opt_verbose, Opt_noverbose,
++ Opt_sum, Opt_nosum, Opt_wsum,
++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
++};
++
++static match_table_t options = {
++ {Opt_br, "br=%s"},
++ {Opt_br, "br:%s"},
++
++ {Opt_add, "add=%d:%s"},
++ {Opt_add, "add:%d:%s"},
++ {Opt_add, "ins=%d:%s"},
++ {Opt_add, "ins:%d:%s"},
++ {Opt_append, "append=%s"},
++ {Opt_append, "append:%s"},
++ {Opt_prepend, "prepend=%s"},
++ {Opt_prepend, "prepend:%s"},
++
++ {Opt_del, "del=%s"},
++ {Opt_del, "del:%s"},
++ /* {Opt_idel, "idel:%d"}, */
++ {Opt_mod, "mod=%s"},
++ {Opt_mod, "mod:%s"},
++ /* {Opt_imod, "imod:%d:%s"}, */
++
++ {Opt_dirwh, "dirwh=%d"},
++
++ {Opt_xino, "xino=%s"},
++ {Opt_noxino, "noxino"},
++ {Opt_trunc_xino, "trunc_xino"},
++ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
++ {Opt_notrunc_xino, "notrunc_xino"},
++ {Opt_trunc_xino_path, "trunc_xino=%s"},
++ {Opt_itrunc_xino, "itrunc_xino=%d"},
++ /* {Opt_zxino, "zxino=%s"}, */
++ {Opt_trunc_xib, "trunc_xib"},
++ {Opt_notrunc_xib, "notrunc_xib"},
++
++ {Opt_plink, "plink"},
++ {Opt_noplink, "noplink"},
++#ifdef CONFIG_AUFS_DEBUG
++ {Opt_list_plink, "list_plink"},
++#endif
++
++ {Opt_udba, "udba=%s"},
++
++ {Opt_diropq_a, "diropq=always"},
++ {Opt_diropq_a, "diropq=a"},
++ {Opt_diropq_w, "diropq=whiteouted"},
++ {Opt_diropq_w, "diropq=w"},
++
++ {Opt_warn_perm, "warn_perm"},
++ {Opt_nowarn_perm, "nowarn_perm"},
++
++ /* keep them temporary */
++ {Opt_ignore_silent, "coo=%s"},
++ {Opt_ignore_silent, "nodlgt"},
++ {Opt_ignore_silent, "nodirperm1"},
++ {Opt_ignore_silent, "clean_plink"},
++
++#ifdef CONFIG_AUFS_SHWH
++ {Opt_shwh, "shwh"},
++#endif
++ {Opt_noshwh, "noshwh"},
++
++ {Opt_rendir, "rendir=%d"},
++
++ {Opt_refrof, "refrof"},
++ {Opt_norefrof, "norefrof"},
++
++ {Opt_verbose, "verbose"},
++ {Opt_verbose, "v"},
++ {Opt_noverbose, "noverbose"},
++ {Opt_noverbose, "quiet"},
++ {Opt_noverbose, "q"},
++ {Opt_noverbose, "silent"},
++
++ {Opt_sum, "sum"},
++ {Opt_nosum, "nosum"},
++ {Opt_wsum, "wsum"},
++
++ {Opt_rdcache, "rdcache=%d"},
++ {Opt_rdblk, "rdblk=%d"},
++ {Opt_rdblk_def, "rdblk=def"},
++ {Opt_rdhash, "rdhash=%d"},
++ {Opt_rdhash_def, "rdhash=def"},
++
++ {Opt_wbr_create, "create=%s"},
++ {Opt_wbr_create, "create_policy=%s"},
++ {Opt_wbr_copyup, "cpup=%s"},
++ {Opt_wbr_copyup, "copyup=%s"},
++ {Opt_wbr_copyup, "copyup_policy=%s"},
++
++ /* internal use for the scripts */
++ {Opt_ignore_silent, "si=%s"},
++
++ {Opt_br, "dirs=%s"},
++ {Opt_ignore, "debug=%d"},
++ {Opt_ignore, "delete=whiteout"},
++ {Opt_ignore, "delete=all"},
++ {Opt_ignore, "imap=%s"},
++
++ {Opt_err, NULL}
++};
++
++/* ---------------------------------------------------------------------- */
++
++static const char *au_parser_pattern(int val, struct match_token *token)
++{
++ while (token->pattern) {
++ if (token->token == val)
++ return token->pattern;
++ token++;
++ }
++ BUG();
++ return "??";
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t brperms = {
++ {AuBrPerm_RO, AUFS_BRPERM_RO},
++ {AuBrPerm_RR, AUFS_BRPERM_RR},
++ {AuBrPerm_RW, AUFS_BRPERM_RW},
++
++ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
++ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
++ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
++
++ {AuBrPerm_ROWH, "nfsro"},
++ {AuBrPerm_RO, NULL}
++};
++
++static int br_perm_val(char *perm)
++{
++ int val;
++ substring_t args[MAX_OPT_ARGS];
++
++ val = match_token(perm, brperms, args);
++ return val;
++}
++
++const char *au_optstr_br_perm(int brperm)
++{
++ return au_parser_pattern(brperm, (void *)brperms);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t udbalevel = {
++ {AuOpt_UDBA_REVAL, "reval"},
++ {AuOpt_UDBA_NONE, "none"},
++#ifdef CONFIG_AUFS_HINOTIFY
++ {AuOpt_UDBA_HINOTIFY, "inotify"},
++#endif
++ {-1, NULL}
++};
++
++static int udba_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++
++ return match_token(str, udbalevel, args);
++}
++
++const char *au_optstr_udba(int udba)
++{
++ return au_parser_pattern(udba, (void *)udbalevel);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t au_wbr_create_policy = {
++ {AuWbrCreate_TDP, "tdp"},
++ {AuWbrCreate_TDP, "top-down-parent"},
++ {AuWbrCreate_RR, "rr"},
++ {AuWbrCreate_RR, "round-robin"},
++ {AuWbrCreate_MFS, "mfs"},
++ {AuWbrCreate_MFS, "most-free-space"},
++ {AuWbrCreate_MFSV, "mfs:%d"},
++ {AuWbrCreate_MFSV, "most-free-space:%d"},
++
++ {AuWbrCreate_MFSRR, "mfsrr:%d"},
++ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
++ {AuWbrCreate_PMFS, "pmfs"},
++ {AuWbrCreate_PMFSV, "pmfs:%d"},
++
++ {-1, NULL}
++};
++
++/*
++ * cf. linux/lib/parser.c and cmdline.c
++ * gave up calling memparse() since it uses simple_strtoull() instead of
++ * strict_...().
++ */
++static int au_match_ull(substring_t *s, unsigned long long *result)
++{
++ int err;
++ unsigned int len;
++ char a[32];
++
++ err = -ERANGE;
++ len = s->to - s->from;
++ if (len + 1 <= sizeof(a)) {
++ memcpy(a, s->from, len);
++ a[len] = '\0';
++ err = strict_strtoull(a, 0, result);
++ }
++ return err;
++}
++
++static int au_wbr_mfs_wmark(substring_t *arg, char *str,
++ struct au_opt_wbr_create *create)
++{
++ int err;
++ unsigned long long ull;
++
++ err = 0;
++ if (!au_match_ull(arg, &ull))
++ create->mfsrr_watermark = ull;
++ else {
++ AuErr("bad integer in %s\n", str);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static int au_wbr_mfs_sec(substring_t *arg, char *str,
++ struct au_opt_wbr_create *create)
++{
++ int n, err;
++
++ err = 0;
++ if (!match_int(arg, &n) && 0 <= n)
++ create->mfs_second = n;
++ else {
++ AuErr("bad integer in %s\n", str);
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
++{
++ int err, e;
++ substring_t args[MAX_OPT_ARGS];
++
++ err = match_token(str, au_wbr_create_policy, args);
++ create->wbr_create = err;
++ switch (err) {
++ case AuWbrCreate_MFSRRV:
++ e = au_wbr_mfs_wmark(&args[0], str, create);
++ if (!e)
++ e = au_wbr_mfs_sec(&args[1], str, create);
++ if (unlikely(e))
++ err = e;
++ break;
++ case AuWbrCreate_MFSRR:
++ e = au_wbr_mfs_wmark(&args[0], str, create);
++ if (unlikely(e)) {
++ err = e;
++ break;
++ }
++ /*FALLTHROUGH*/
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_PMFS:
++ create->mfs_second = AUFS_MFS_SECOND_DEF;
++ break;
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFSV:
++ e = au_wbr_mfs_sec(&args[0], str, create);
++ if (unlikely(e))
++ err = e;
++ break;
++ }
++
++ return err;
++}
++
++const char *au_optstr_wbr_create(int wbr_create)
++{
++ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
++}
++
++static match_table_t au_wbr_copyup_policy = {
++ {AuWbrCopyup_TDP, "tdp"},
++ {AuWbrCopyup_TDP, "top-down-parent"},
++ {AuWbrCopyup_BUP, "bup"},
++ {AuWbrCopyup_BUP, "bottom-up-parent"},
++ {AuWbrCopyup_BU, "bu"},
++ {AuWbrCopyup_BU, "bottom-up"},
++ {-1, NULL}
++};
++
++static int au_wbr_copyup_val(char *str)
++{
++ substring_t args[MAX_OPT_ARGS];
++
++ return match_token(str, au_wbr_copyup_policy, args);
++}
++
++const char *au_optstr_wbr_copyup(int wbr_copyup)
++{
++ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
++
++static void dump_opts(struct au_opts *opts)
++{
++#ifdef CONFIG_AUFS_DEBUG
++ /* reduce stack space */
++ union {
++ struct au_opt_add *add;
++ struct au_opt_del *del;
++ struct au_opt_mod *mod;
++ struct au_opt_xino *xino;
++ struct au_opt_xino_itrunc *xino_itrunc;
++ struct au_opt_wbr_create *create;
++ } u;
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ u.add = &opt->add;
++ AuDbg("add {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ u.del = &opt->del;
++ AuDbg("del {%s, %p}\n",
++ u.del->pathname, u.del->h_path.dentry);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ u.mod = &opt->mod;
++ AuDbg("mod {%s, 0x%x, %p}\n",
++ u.mod->path, u.mod->perm, u.mod->h_root);
++ break;
++ case Opt_append:
++ u.add = &opt->add;
++ AuDbg("append {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_prepend:
++ u.add = &opt->add;
++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_dirwh:
++ AuDbg("dirwh %d\n", opt->dirwh);
++ break;
++ case Opt_rdcache:
++ AuDbg("rdcache %d\n", opt->rdcache);
++ break;
++ case Opt_rdblk:
++ AuDbg("rdblk %u\n", opt->rdblk);
++ break;
++ case Opt_rdblk_def:
++ AuDbg("rdblk_def\n");
++ break;
++ case Opt_rdhash:
++ AuDbg("rdhash %u\n", opt->rdhash);
++ break;
++ case Opt_rdhash_def:
++ AuDbg("rdhash_def\n");
++ break;
++ case Opt_xino:
++ u.xino = &opt->xino;
++ AuDbg("xino {%s %.*s}\n",
++ u.xino->path,
++ AuDLNPair(u.xino->file->f_dentry));
++ break;
++ case Opt_trunc_xino:
++ AuLabel(trunc_xino);
++ break;
++ case Opt_notrunc_xino:
++ AuLabel(notrunc_xino);
++ break;
++ case Opt_trunc_xino_path:
++ case Opt_itrunc_xino:
++ u.xino_itrunc = &opt->xino_itrunc;
++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
++ break;
++
++ case Opt_noxino:
++ AuLabel(noxino);
++ break;
++ case Opt_trunc_xib:
++ AuLabel(trunc_xib);
++ break;
++ case Opt_notrunc_xib:
++ AuLabel(notrunc_xib);
++ break;
++ case Opt_shwh:
++ AuLabel(shwh);
++ break;
++ case Opt_noshwh:
++ AuLabel(noshwh);
++ break;
++ case Opt_plink:
++ AuLabel(plink);
++ break;
++ case Opt_noplink:
++ AuLabel(noplink);
++ break;
++ case Opt_list_plink:
++ AuLabel(list_plink);
++ break;
++ case Opt_udba:
++ AuDbg("udba %d, %s\n",
++ opt->udba, au_optstr_udba(opt->udba));
++ break;
++ case Opt_diropq_a:
++ AuLabel(diropq_a);
++ break;
++ case Opt_diropq_w:
++ AuLabel(diropq_w);
++ break;
++ case Opt_warn_perm:
++ AuLabel(warn_perm);
++ break;
++ case Opt_nowarn_perm:
++ AuLabel(nowarn_perm);
++ break;
++ case Opt_refrof:
++ AuLabel(refrof);
++ break;
++ case Opt_norefrof:
++ AuLabel(norefrof);
++ break;
++ case Opt_verbose:
++ AuLabel(verbose);
++ break;
++ case Opt_noverbose:
++ AuLabel(noverbose);
++ break;
++ case Opt_sum:
++ AuLabel(sum);
++ break;
++ case Opt_nosum:
++ AuLabel(nosum);
++ break;
++ case Opt_wsum:
++ AuLabel(wsum);
++ break;
++ case Opt_wbr_create:
++ u.create = &opt->wbr_create;
++ AuDbg("create %d, %s\n", u.create->wbr_create,
++ au_optstr_wbr_create(u.create->wbr_create));
++ switch (u.create->wbr_create) {
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFSV:
++ AuDbg("%d sec\n", u.create->mfs_second);
++ break;
++ case AuWbrCreate_MFSRR:
++ AuDbg("%llu watermark\n",
++ u.create->mfsrr_watermark);
++ break;
++ case AuWbrCreate_MFSRRV:
++ AuDbg("%llu watermark, %d sec\n",
++ u.create->mfsrr_watermark,
++ u.create->mfs_second);
++ break;
++ }
++ break;
++ case Opt_wbr_copyup:
++ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
++ au_optstr_wbr_copyup(opt->wbr_copyup));
++ break;
++ default:
++ BUG();
++ }
++ opt++;
++ }
++#endif
++}
++
++void au_opts_free(struct au_opts *opts)
++{
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ case Opt_append:
++ case Opt_prepend:
++ path_put(&opt->add.path);
++ break;
++ case Opt_del:
++ case Opt_idel:
++ path_put(&opt->del.h_path);
++ break;
++ case Opt_mod:
++ case Opt_imod:
++ dput(opt->mod.h_root);
++ break;
++ case Opt_xino:
++ fput(opt->xino.file);
++ break;
++ }
++ opt++;
++ }
++}
++
++static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct au_opt_add *add = &opt->add;
++ char *p;
++
++ add->bindex = bindex;
++ add->perm = AuBrPerm_Last;
++ add->pathname = opt_str;
++ p = strchr(opt_str, '=');
++ if (p) {
++ *p++ = 0;
++ if (*p)
++ add->perm = br_perm_val(p);
++ }
++
++ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
++ if (!err) {
++ if (!p) {
++ add->perm = AuBrPerm_RO;
++ if (au_test_fs_rr(add->path.dentry->d_sb))
++ add->perm = AuBrPerm_RR;
++ else if (!bindex && !(sb_flags & MS_RDONLY))
++ add->perm = AuBrPerm_RW;
++ }
++ opt->type = Opt_add;
++ goto out;
++ }
++ AuErr("lookup failed %s (%d)\n", add->pathname, err);
++ err = -EINVAL;
++
++ out:
++ return err;
++}
++
++static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
++{
++ int err;
++
++ del->pathname = args[0].from;
++ AuDbg("del path %s\n", del->pathname);
++
++ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
++ if (unlikely(err))
++ AuErr("lookup failed %s (%d)\n", del->pathname, err);
++
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_opt_del *del, substring_t args[])
++{
++ int err;
++ struct dentry *root;
++
++ err = -EINVAL;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (bindex < 0 || au_sbend(sb) < bindex) {
++ AuErr("out of bounds, %d\n", bindex);
++ goto out;
++ }
++
++ err = 0;
++ del->h_path.dentry = dget(au_h_dptr(root, bindex));
++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
++
++ out:
++ aufs_read_unlock(root, !AuLock_IR);
++ return err;
++}
++#endif
++
++static int au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
++{
++ int err;
++ struct path path;
++ char *p;
++
++ err = -EINVAL;
++ mod->path = args[0].from;
++ p = strchr(mod->path, '=');
++ if (unlikely(!p)) {
++ AuErr("no permssion %s\n", args[0].from);
++ goto out;
++ }
++
++ *p++ = 0;
++ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
++ if (unlikely(err)) {
++ AuErr("lookup failed %s (%d)\n", mod->path, err);
++ goto out;
++ }
++
++ mod->perm = br_perm_val(p);
++ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
++ mod->h_root = dget(path.dentry);
++ path_put(&path);
++
++ out:
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
++ struct au_opt_mod *mod, substring_t args[])
++{
++ int err;
++ struct dentry *root;
++
++ err = -EINVAL;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (bindex < 0 || au_sbend(sb) < bindex) {
++ AuErr("out of bounds, %d\n", bindex);
++ goto out;
++ }
++
++ err = 0;
++ mod->perm = br_perm_val(args[1].from);
++ AuDbg("mod path %s, perm 0x%x, %s\n",
++ mod->path, mod->perm, args[1].from);
++ mod->h_root = dget(au_h_dptr(root, bindex));
++
++ out:
++ aufs_read_unlock(root, !AuLock_IR);
++ return err;
++}
++#endif
++
++static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
++ substring_t args[])
++{
++ int err;
++ struct file *file;
++
++ file = au_xino_create(sb, args[0].from, /*silent*/0);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++
++ err = -EINVAL;
++ if (unlikely(file->f_dentry->d_sb == sb)) {
++ fput(file);
++ AuErr("%s must be outside\n", args[0].from);
++ goto out;
++ }
++
++ err = 0;
++ xino->file = file;
++ xino->path = args[0].from;
++
++ out:
++ return err;
++}
++
++static
++int au_opts_parse_xino_itrunc_path(struct super_block *sb,
++ struct au_opt_xino_itrunc *xino_itrunc,
++ substring_t args[])
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct path path;
++ struct dentry *root;
++
++ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
++ if (unlikely(err)) {
++ AuErr("lookup failed %s (%d)\n", args[0].from, err);
++ goto out;
++ }
++
++ xino_itrunc->bindex = -1;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ if (au_h_dptr(root, bindex) == path.dentry) {
++ xino_itrunc->bindex = bindex;
++ break;
++ }
++ }
++ aufs_read_unlock(root, !AuLock_IR);
++ path_put(&path);
++
++ if (unlikely(xino_itrunc->bindex < 0)) {
++ AuErr("no such branch %s\n", args[0].from);
++ err = -EINVAL;
++ }
++
++ out:
++ return err;
++}
++
++/* called without aufs lock */
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
++{
++ int err, n, token;
++ aufs_bindex_t bindex;
++ unsigned char skipped;
++ struct dentry *root;
++ struct au_opt *opt, *opt_tail;
++ char *opt_str;
++ /* reduce the stack space */
++ union {
++ struct au_opt_xino_itrunc *xino_itrunc;
++ struct au_opt_wbr_create *create;
++ } u;
++ struct {
++ substring_t args[MAX_OPT_ARGS];
++ } *a;
++
++ err = -ENOMEM;
++ a = kmalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ root = sb->s_root;
++ err = 0;
++ bindex = 0;
++ opt = opts->opt;
++ opt_tail = opt + opts->max_opt - 1;
++ opt->type = Opt_tail;
++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
++ err = -EINVAL;
++ skipped = 0;
++ token = match_token(opt_str, options, a->args);
++ switch (token) {
++ case Opt_br:
++ err = 0;
++ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
++ && *opt_str) {
++ err = opt_add(opt, opt_str, opts->sb_flags,
++ bindex++);
++ if (unlikely(!err && ++opt > opt_tail)) {
++ err = -E2BIG;
++ break;
++ }
++ opt->type = Opt_tail;
++ skipped = 1;
++ }
++ break;
++ case Opt_add:
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ bindex = n;
++ err = opt_add(opt, a->args[1].from, opts->sb_flags,
++ bindex);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_append:
++ err = opt_add(opt, a->args[0].from, opts->sb_flags,
++ /*dummy bindex*/1);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_prepend:
++ err = opt_add(opt, a->args[0].from, opts->sb_flags,
++ /*bindex*/0);
++ if (!err)
++ opt->type = token;
++ break;
++ case Opt_del:
++ err = au_opts_parse_del(&opt->del, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#if 0 /* reserved for future use */
++ case Opt_idel:
++ del->pathname = "(indexed)";
++ if (unlikely(match_int(&args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#endif
++ case Opt_mod:
++ err = au_opts_parse_mod(&opt->mod, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#ifdef IMOD /* reserved for future use */
++ case Opt_imod:
++ u.mod->path = "(indexed)";
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++#endif
++ case Opt_xino:
++ err = au_opts_parse_xino(sb, &opt->xino, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++
++ case Opt_trunc_xino_path:
++ err = au_opts_parse_xino_itrunc_path
++ (sb, &opt->xino_itrunc, a->args);
++ if (!err)
++ opt->type = token;
++ break;
++
++ case Opt_itrunc_xino:
++ u.xino_itrunc = &opt->xino_itrunc;
++ if (unlikely(match_int(&a->args[0], &n))) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ u.xino_itrunc->bindex = n;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (n < 0 || au_sbend(sb) < n) {
++ AuErr("out of bounds, %d\n", n);
++ aufs_read_unlock(root, !AuLock_IR);
++ break;
++ }
++ aufs_read_unlock(root, !AuLock_IR);
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_dirwh:
++ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_rdcache:
++ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
++ break;
++ err = 0;
++ opt->type = token;
++ break;
++ case Opt_rdblk:
++ if (unlikely(match_int(&a->args[0], &n)
++ || n <= 0
++ || n > KMALLOC_MAX_SIZE)) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ if (unlikely(n < NAME_MAX)) {
++ AuErr("rdblk must be larger than %d\n",
++ NAME_MAX);
++ break;
++ }
++ opt->rdblk = n;
++ err = 0;
++ opt->type = token;
++ break;
++ case Opt_rdhash:
++ if (unlikely(match_int(&a->args[0], &n)
++ || n <= 0
++ || n * sizeof(struct hlist_head)
++ > KMALLOC_MAX_SIZE)) {
++ AuErr("bad integer in %s\n", opt_str);
++ break;
++ }
++ opt->rdhash = n;
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_trunc_xino:
++ case Opt_notrunc_xino:
++ case Opt_noxino:
++ case Opt_trunc_xib:
++ case Opt_notrunc_xib:
++ case Opt_shwh:
++ case Opt_noshwh:
++ case Opt_plink:
++ case Opt_noplink:
++ case Opt_list_plink:
++ case Opt_diropq_a:
++ case Opt_diropq_w:
++ case Opt_warn_perm:
++ case Opt_nowarn_perm:
++ case Opt_refrof:
++ case Opt_norefrof:
++ case Opt_verbose:
++ case Opt_noverbose:
++ case Opt_sum:
++ case Opt_nosum:
++ case Opt_wsum:
++ case Opt_rdblk_def:
++ case Opt_rdhash_def:
++ err = 0;
++ opt->type = token;
++ break;
++
++ case Opt_udba:
++ opt->udba = udba_val(a->args[0].from);
++ if (opt->udba >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++
++ case Opt_wbr_create:
++ u.create = &opt->wbr_create;
++ u.create->wbr_create
++ = au_wbr_create_val(a->args[0].from, u.create);
++ if (u.create->wbr_create >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++ case Opt_wbr_copyup:
++ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
++ if (opt->wbr_copyup >= 0) {
++ err = 0;
++ opt->type = token;
++ } else
++ AuErr("wrong value, %s\n", opt_str);
++ break;
++
++ case Opt_ignore:
++ AuWarn("ignored %s\n", opt_str);
++ /*FALLTHROUGH*/
++ case Opt_ignore_silent:
++ skipped = 1;
++ err = 0;
++ break;
++ case Opt_err:
++ AuErr("unknown option %s\n", opt_str);
++ break;
++ }
++
++ if (!err && !skipped) {
++ if (unlikely(++opt > opt_tail)) {
++ err = -E2BIG;
++ opt--;
++ opt->type = Opt_tail;
++ break;
++ }
++ opt->type = Opt_tail;
++ }
++ }
++
++ kfree(a);
++ dump_opts(opts);
++ if (unlikely(err))
++ au_opts_free(opts);
++
++ out:
++ return err;
++}
++
++static int au_opt_wbr_create(struct super_block *sb,
++ struct au_opt_wbr_create *create)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = 1; /* handled */
++ sbinfo = au_sbi(sb);
++ if (sbinfo->si_wbr_create_ops->fin) {
++ err = sbinfo->si_wbr_create_ops->fin(sb);
++ if (!err)
++ err = 1;
++ }
++
++ sbinfo->si_wbr_create = create->wbr_create;
++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
++ switch (create->wbr_create) {
++ case AuWbrCreate_MFSRRV:
++ case AuWbrCreate_MFSRR:
++ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
++ /*FALLTHROUGH*/
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_MFSV:
++ case AuWbrCreate_PMFS:
++ case AuWbrCreate_PMFSV:
++ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
++ break;
++ }
++
++ if (sbinfo->si_wbr_create_ops->init)
++ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
++
++ return err;
++}
++
++/*
++ * returns,
++ * plus: processed without an error
++ * zero: unprocessed
++ */
++static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
++ struct au_opts *opts)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = 1; /* handled */
++ sbinfo = au_sbi(sb);
++ switch (opt->type) {
++ case Opt_udba:
++ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++ sbinfo->si_mntflags |= opt->udba;
++ opts->given_udba |= opt->udba;
++ break;
++
++ case Opt_plink:
++ au_opt_set(sbinfo->si_mntflags, PLINK);
++ break;
++ case Opt_noplink:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_put(sb);
++ au_opt_clr(sbinfo->si_mntflags, PLINK);
++ break;
++ case Opt_list_plink:
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_list(sb);
++ break;
++
++ case Opt_diropq_a:
++ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++ break;
++ case Opt_diropq_w:
++ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++ break;
++
++ case Opt_warn_perm:
++ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
++ break;
++ case Opt_nowarn_perm:
++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
++ break;
++
++ case Opt_refrof:
++ au_opt_set(sbinfo->si_mntflags, REFROF);
++ break;
++ case Opt_norefrof:
++ au_opt_clr(sbinfo->si_mntflags, REFROF);
++ break;
++
++ case Opt_verbose:
++ au_opt_set(sbinfo->si_mntflags, VERBOSE);
++ break;
++ case Opt_noverbose:
++ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
++ break;
++
++ case Opt_sum:
++ au_opt_set(sbinfo->si_mntflags, SUM);
++ break;
++ case Opt_wsum:
++ au_opt_clr(sbinfo->si_mntflags, SUM);
++ au_opt_set(sbinfo->si_mntflags, SUM_W);
++ case Opt_nosum:
++ au_opt_clr(sbinfo->si_mntflags, SUM);
++ au_opt_clr(sbinfo->si_mntflags, SUM_W);
++ break;
++
++ case Opt_wbr_create:
++ err = au_opt_wbr_create(sb, &opt->wbr_create);
++ break;
++ case Opt_wbr_copyup:
++ sbinfo->si_wbr_copyup = opt->wbr_copyup;
++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
++ break;
++
++ case Opt_dirwh:
++ sbinfo->si_dirwh = opt->dirwh;
++ break;
++
++ case Opt_rdcache:
++ sbinfo->si_rdcache = opt->rdcache * HZ;
++ break;
++ case Opt_rdblk:
++ sbinfo->si_rdblk = opt->rdblk;
++ break;
++ case Opt_rdblk_def:
++ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++ break;
++ case Opt_rdhash:
++ sbinfo->si_rdhash = opt->rdhash;
++ break;
++ case Opt_rdhash_def:
++ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++ break;
++
++ case Opt_shwh:
++ au_opt_set(sbinfo->si_mntflags, SHWH);
++ break;
++ case Opt_noshwh:
++ au_opt_clr(sbinfo->si_mntflags, SHWH);
++ break;
++
++ case Opt_trunc_xino:
++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
++ break;
++ case Opt_notrunc_xino:
++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
++ break;
++
++ case Opt_trunc_xino_path:
++ case Opt_itrunc_xino:
++ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
++ if (!err)
++ err = 1;
++ break;
++
++ case Opt_trunc_xib:
++ au_fset_opts(opts->flags, TRUNC_XIB);
++ break;
++ case Opt_notrunc_xib:
++ au_fclr_opts(opts->flags, TRUNC_XIB);
++ break;
++
++ default:
++ err = 0;
++ break;
++ }
++
++ return err;
++}
++
++/*
++ * returns tri-state.
++ * plus: processed without an error
++ * zero: unprocessed
++ * minus: error
++ */
++static int au_opt_br(struct super_block *sb, struct au_opt *opt,
++ struct au_opts *opts)
++{
++ int err, do_refresh;
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_append:
++ opt->add.bindex = au_sbend(sb) + 1;
++ if (opt->add.bindex < 0)
++ opt->add.bindex = 0;
++ goto add;
++ case Opt_prepend:
++ opt->add.bindex = 0;
++ add:
++ case Opt_add:
++ err = au_br_add(sb, &opt->add,
++ au_ftest_opts(opts->flags, REMOUNT));
++ if (!err) {
++ err = 1;
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ if (au_br_whable(opt->add.perm))
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ break;
++
++ case Opt_del:
++ case Opt_idel:
++ err = au_br_del(sb, &opt->del,
++ au_ftest_opts(opts->flags, REMOUNT));
++ if (!err) {
++ err = 1;
++ au_fset_opts(opts->flags, TRUNC_XIB);
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ break;
++
++ case Opt_mod:
++ case Opt_imod:
++ err = au_br_mod(sb, &opt->mod,
++ au_ftest_opts(opts->flags, REMOUNT),
++ &do_refresh);
++ if (!err) {
++ err = 1;
++ if (do_refresh) {
++ au_fset_opts(opts->flags, REFRESH_DIR);
++ au_fset_opts(opts->flags, REFRESH_NONDIR);
++ }
++ }
++ break;
++ }
++
++ return err;
++}
++
++static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
++ struct au_opt_xino **opt_xino,
++ struct au_opts *opts)
++{
++ int err;
++ aufs_bindex_t bend, bindex;
++ struct dentry *root, *parent, *h_root;
++
++ err = 0;
++ switch (opt->type) {
++ case Opt_xino:
++ err = au_xino_set(sb, &opt->xino,
++ !!au_ftest_opts(opts->flags, REMOUNT));
++ if (unlikely(err))
++ break;
++
++ *opt_xino = &opt->xino;
++ au_xino_brid_set(sb, -1);
++
++ /* safe d_parent access */
++ parent = opt->xino.file->f_dentry->d_parent;
++ root = sb->s_root;
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ h_root = au_h_dptr(root, bindex);
++ if (h_root == parent) {
++ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
++ break;
++ }
++ }
++ break;
++
++ case Opt_noxino:
++ au_xino_clr(sb);
++ au_xino_brid_set(sb, -1);
++ *opt_xino = (void *)-1;
++ break;
++ }
++
++ return err;
++}
++
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++ unsigned int pending)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ unsigned char do_plink, skip, do_free;
++ struct au_branch *br;
++ struct au_wbr *wbr;
++ struct dentry *root;
++ struct inode *dir, *h_dir;
++ struct au_sbinfo *sbinfo;
++ struct au_hinode *hdir;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
++
++ if (!(sb_flags & MS_RDONLY)) {
++ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
++ AuWarn("first branch should be rw\n");
++ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
++ AuWarn("shwh should be used with ro\n");
++ }
++
++ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
++ && !au_opt_test(sbinfo->si_mntflags, XINO))
++ AuWarn("udba=inotify requires xino\n");
++
++ err = 0;
++ root = sb->s_root;
++ dir = sb->s_root->d_inode;
++ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
++ bend = au_sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ skip = 0;
++ h_dir = au_h_iptr(dir, bindex);
++ br = au_sbr(sb, bindex);
++ do_free = 0;
++
++ wbr = br->br_wbr;
++ if (wbr)
++ wbr_wh_read_lock(wbr);
++
++ switch (br->br_perm) {
++ case AuBrPerm_RO:
++ case AuBrPerm_ROWH:
++ case AuBrPerm_RR:
++ case AuBrPerm_RRWH:
++ do_free = !!wbr;
++ skip = (!wbr
++ || (!wbr->wbr_whbase
++ && !wbr->wbr_plink
++ && !wbr->wbr_orph));
++ break;
++
++ case AuBrPerm_RWNoLinkWH:
++ /* skip = (!br->br_whbase && !br->br_orph); */
++ skip = (!wbr || !wbr->wbr_whbase);
++ if (skip && wbr) {
++ if (do_plink)
++ skip = !!wbr->wbr_plink;
++ else
++ skip = !wbr->wbr_plink;
++ }
++ break;
++
++ case AuBrPerm_RW:
++ /* skip = (br->br_whbase && br->br_ohph); */
++ skip = (wbr && wbr->wbr_whbase);
++ if (skip) {
++ if (do_plink)
++ skip = !!wbr->wbr_plink;
++ else
++ skip = !wbr->wbr_plink;
++ }
++ break;
++
++ default:
++ BUG();
++ }
++ if (wbr)
++ wbr_wh_read_unlock(wbr);
++
++ if (skip)
++ continue;
++
++ hdir = au_hi(dir, bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ if (wbr)
++ wbr_wh_write_lock(wbr);
++ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
++ if (wbr)
++ wbr_wh_write_unlock(wbr);
++ au_hin_imtx_unlock(hdir);
++
++ if (!err && do_free) {
++ kfree(wbr);
++ br->br_wbr = NULL;
++ }
++ }
++
++ return err;
++}
++
++int au_opts_mount(struct super_block *sb, struct au_opts *opts)
++{
++ int err;
++ unsigned int tmp;
++ aufs_bindex_t bend;
++ struct au_opt *opt;
++ struct au_opt_xino *opt_xino, xino;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_opt_simple(sb, opt++, opts);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ /* disable xino and udba temporary */
++ sbinfo = au_sbi(sb);
++ tmp = sbinfo->si_mntflags;
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
++
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail)
++ err = au_opt_br(sb, opt++, opts);
++ if (err > 0)
++ err = 0;
++ else if (unlikely(err < 0))
++ goto out;
++
++ bend = au_sbend(sb);
++ if (unlikely(bend < 0)) {
++ err = -EINVAL;
++ AuErr("no branches\n");
++ goto out;
++ }
++
++ if (au_opt_test(tmp, XINO))
++ au_opt_set(sbinfo->si_mntflags, XINO);
++ opt = opts->opt;
++ while (!err && opt->type != Opt_tail)
++ err = au_opt_xino(sb, opt++, &opt_xino, opts);
++ if (unlikely(err))
++ goto out;
++
++ err = au_opts_verify(sb, sb->s_flags, tmp);
++ if (unlikely(err))
++ goto out;
++
++ /* restore xino */
++ if (au_opt_test(tmp, XINO) && !opt_xino) {
++ xino.file = au_xino_def(sb);
++ err = PTR_ERR(xino.file);
++ if (IS_ERR(xino.file))
++ goto out;
++
++ err = au_xino_set(sb, &xino, /*remount*/0);
++ fput(xino.file);
++ if (unlikely(err))
++ goto out;
++ }
++
++ /* restore udba */
++ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
++ if (au_opt_test(tmp, UDBA_HINOTIFY)) {
++ struct inode *dir = sb->s_root->d_inode;
++ au_reset_hinotify(dir,
++ au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
++ }
++
++ out:
++ return err;
++}
++
++int au_opts_remount(struct super_block *sb, struct au_opts *opts)
++{
++ int err, rerr;
++ struct inode *dir;
++ struct au_opt_xino *opt_xino;
++ struct au_opt *opt;
++ struct au_sbinfo *sbinfo;
++
++ dir = sb->s_root->d_inode;
++ sbinfo = au_sbi(sb);
++ err = 0;
++ opt_xino = NULL;
++ opt = opts->opt;
++ while (err >= 0 && opt->type != Opt_tail) {
++ err = au_opt_simple(sb, opt, opts);
++ if (!err)
++ err = au_opt_br(sb, opt, opts);
++ if (!err)
++ err = au_opt_xino(sb, opt, &opt_xino, opts);
++ opt++;
++ }
++ if (err > 0)
++ err = 0;
++ AuTraceErr(err);
++ /* go on even err */
++
++ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
++ if (unlikely(rerr && !err))
++ err = rerr;
++
++ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
++ rerr = au_xib_trunc(sb);
++ if (unlikely(rerr && !err))
++ err = rerr;
++ }
++
++ /* will be handled by the caller */
++ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
++ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
++ au_fset_opts(opts->flags, REFRESH_DIR);
++
++ AuDbg("status 0x%x\n", opts->flags);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_opt_udba(struct super_block *sb)
++{
++ return au_mntflags(sb) & AuOptMask_UDBA;
++}
+diff -Naur a/fs/aufs/opts.h b/fs/aufs/opts.h
+--- a/fs/aufs/opts.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,196 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount options/flags
++ */
++
++#ifndef __AUFS_OPTS_H__
++#define __AUFS_OPTS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/aufs_type.h>
++
++struct file;
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/* mount flags */
++#define AuOpt_XINO 1 /* external inode number bitmap
++ and translation table */
++#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
++#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
++#define AuOpt_UDBA_REVAL (1 << 3)
++#define AuOpt_UDBA_HINOTIFY (1 << 4)
++#define AuOpt_SHWH (1 << 5) /* show whiteout */
++#define AuOpt_PLINK (1 << 6) /* pseudo-link */
++#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
++#define AuOpt_REFROF (1 << 8) /* unimplemented */
++#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
++#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
++#define AuOpt_SUM_W (1 << 11) /* unimplemented */
++#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
++#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuOpt_UDBA_HINOTIFY
++#define AuOpt_UDBA_HINOTIFY 0
++#endif
++#ifndef CONFIG_AUFS_SHWH
++#undef AuOpt_SHWH
++#define AuOpt_SHWH 0
++#endif
++
++#define AuOpt_Def (AuOpt_XINO \
++ | AuOpt_UDBA_REVAL \
++ | AuOpt_PLINK \
++ /* | AuOpt_DIRPERM1 */ \
++ | AuOpt_WARN_PERM)
++#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
++ | AuOpt_UDBA_REVAL \
++ | AuOpt_UDBA_HINOTIFY)
++
++#define au_opt_test(flags, name) (flags & AuOpt_##name)
++#define au_opt_set(flags, name) do { \
++ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
++ ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_set_udba(flags, name) do { \
++ (flags) &= ~AuOptMask_UDBA; \
++ ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
++
++/* ---------------------------------------------------------------------- */
++
++/* policies to select one among multiple writable branches */
++enum {
++ AuWbrCreate_TDP, /* top down parent */
++ AuWbrCreate_RR, /* round robin */
++ AuWbrCreate_MFS, /* most free space */
++ AuWbrCreate_MFSV, /* mfs with seconds */
++ AuWbrCreate_MFSRR, /* mfs then rr */
++ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
++ AuWbrCreate_PMFS, /* parent and mfs */
++ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
++
++ AuWbrCreate_Def = AuWbrCreate_TDP
++};
++
++enum {
++ AuWbrCopyup_TDP, /* top down parent */
++ AuWbrCopyup_BUP, /* bottom up parent */
++ AuWbrCopyup_BU, /* bottom up */
++
++ AuWbrCopyup_Def = AuWbrCopyup_TDP
++};
++
++/* ---------------------------------------------------------------------- */
++
++struct au_opt_add {
++ aufs_bindex_t bindex;
++ char *pathname;
++ int perm;
++ struct path path;
++};
++
++struct au_opt_del {
++ char *pathname;
++ struct path h_path;
++};
++
++struct au_opt_mod {
++ char *path;
++ int perm;
++ struct dentry *h_root;
++};
++
++struct au_opt_xino {
++ char *path;
++ struct file *file;
++};
++
++struct au_opt_xino_itrunc {
++ aufs_bindex_t bindex;
++};
++
++struct au_opt_wbr_create {
++ int wbr_create;
++ int mfs_second;
++ unsigned long long mfsrr_watermark;
++};
++
++struct au_opt {
++ int type;
++ union {
++ struct au_opt_xino xino;
++ struct au_opt_xino_itrunc xino_itrunc;
++ struct au_opt_add add;
++ struct au_opt_del del;
++ struct au_opt_mod mod;
++ int dirwh;
++ int rdcache;
++ unsigned int rdblk;
++ unsigned int rdhash;
++ int udba;
++ struct au_opt_wbr_create wbr_create;
++ int wbr_copyup;
++ };
++};
++
++/* opts flags */
++#define AuOpts_REMOUNT 1
++#define AuOpts_REFRESH_DIR (1 << 1)
++#define AuOpts_REFRESH_NONDIR (1 << 2)
++#define AuOpts_TRUNC_XIB (1 << 3)
++#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
++#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
++#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
++
++struct au_opts {
++ struct au_opt *opt;
++ int max_opt;
++
++ unsigned int given_udba;
++ unsigned int flags;
++ unsigned long sb_flags;
++};
++
++/* ---------------------------------------------------------------------- */
++
++const char *au_optstr_br_perm(int brperm);
++const char *au_optstr_udba(int udba);
++const char *au_optstr_wbr_copyup(int wbr_copyup);
++const char *au_optstr_wbr_create(int wbr_create);
++
++void au_opts_free(struct au_opts *opts);
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++ unsigned int pending);
++int au_opts_mount(struct super_block *sb, struct au_opts *opts);
++int au_opts_remount(struct super_block *sb, struct au_opts *opts);
++
++unsigned int au_opt_udba(struct super_block *sb);
++
++/* ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_OPTS_H__ */
+diff -Naur a/fs/aufs/plink.c b/fs/aufs/plink.c
+--- a/fs/aufs/plink.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/plink.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,344 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * pseudo-link
++ */
++
++#include "aufs.h"
++
++/*
++ * during a user process maintains the pseudo-links,
++ * prohibit adding a new plink and branch manipulation.
++ */
++void au_plink_block_maintain(struct super_block *sb)
++{
++ struct au_sbinfo *sbi = au_sbi(sb);
++ /* gave up wake_up_bit() */
++ wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct pseudo_link {
++ struct list_head list;
++ struct inode *inode;
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list)
++ AuDbg("%lu\n", plink->inode->i_ino);
++ spin_unlock(&sbinfo->si_plink.spin);
++}
++#endif
++
++/* is the inode pseudo-linked? */
++int au_plink_test(struct inode *inode)
++{
++ int found;
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++
++ sbinfo = au_sbi(inode->i_sb);
++ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
++
++ found = 0;
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list)
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ spin_unlock(&sbinfo->si_plink.spin);
++ return found;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generate a name for plink.
++ * the file will be stored under AUFS_WH_PLINKDIR.
++ */
++/* 20 is max digits length of ulong 64 */
++#define PLINK_NAME_LEN ((20 + 1) * 2)
++
++static int plink_name(char *name, int len, struct inode *inode,
++ aufs_bindex_t bindex)
++{
++ int rlen;
++ struct inode *h_inode;
++
++ h_inode = au_h_iptr(inode, bindex);
++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
++ return rlen;
++}
++
++/* lookup the plink-ed @inode under the branch at @bindex */
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
++{
++ struct dentry *h_dentry, *h_parent;
++ struct au_branch *br;
++ struct inode *h_dir;
++ char a[PLINK_NAME_LEN];
++ struct qstr tgtname = {
++ .name = a
++ };
++
++ br = au_sbr(inode->i_sb, bindex);
++ h_parent = br->br_wbr->wbr_plink;
++ h_dir = h_parent->d_inode;
++ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++ /* always superio. */
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
++ mutex_unlock(&h_dir->i_mutex);
++ return h_dentry;
++}
++
++/* create a pseudo-link */
++static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
++ struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++
++ h_dir = h_parent->d_inode;
++ again:
++ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ err = 0;
++ /* wh.plink dir is not monitored */
++ if (h_path.dentry->d_inode
++ && h_path.dentry->d_inode != h_dentry->d_inode) {
++ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++ dput(h_path.dentry);
++ h_path.dentry = NULL;
++ if (!err)
++ goto again;
++ }
++ if (!err && !h_path.dentry->d_inode)
++ err = vfsub_link(h_dentry, h_dir, &h_path);
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++struct do_whplink_args {
++ int *errp;
++ struct qstr *tgt;
++ struct dentry *h_parent;
++ struct dentry *h_dentry;
++ struct au_branch *br;
++};
++
++static void call_do_whplink(void *args)
++{
++ struct do_whplink_args *a = args;
++ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
++}
++
++static int whplink(struct dentry *h_dentry, struct inode *inode,
++ aufs_bindex_t bindex, struct au_branch *br)
++{
++ int err, wkq_err;
++ struct au_wbr *wbr;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ char a[PLINK_NAME_LEN];
++ struct qstr tgtname = {
++ .name = a
++ };
++
++ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
++ h_parent = wbr->wbr_plink;
++ h_dir = h_parent->d_inode;
++ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++ /* always superio. */
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++ if (!au_test_wkq(current)) {
++ struct do_whplink_args args = {
++ .errp = &err,
++ .tgt = &tgtname,
++ .h_parent = h_parent,
++ .h_dentry = h_dentry,
++ .br = br
++ };
++ wkq_err = au_wkq_wait(call_do_whplink, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ } else
++ err = do_whplink(&tgtname, h_parent, h_dentry, br);
++ mutex_unlock(&h_dir->i_mutex);
++
++ return err;
++}
++
++/* free a single plink */
++static void do_put_plink(struct pseudo_link *plink, int do_del)
++{
++ iput(plink->inode);
++ if (do_del)
++ list_del(&plink->list);
++ kfree(plink);
++}
++
++/*
++ * create a new pseudo-link for @h_dentry on @bindex.
++ * the linked inode is held in aufs @inode.
++ */
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++ struct dentry *h_dentry)
++{
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink;
++ int found, err, cnt;
++
++ sb = inode->i_sb;
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ err = 0;
++ cnt = 0;
++ found = 0;
++ plink_list = &sbinfo->si_plink.head;
++ spin_lock(&sbinfo->si_plink.spin);
++ list_for_each_entry(plink, plink_list, list) {
++ cnt++;
++ if (plink->inode == inode) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ spin_unlock(&sbinfo->si_plink.spin);
++ return;
++ }
++
++ plink = NULL;
++ if (!found) {
++ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
++ if (plink) {
++ plink->inode = au_igrab(inode);
++ list_add(&plink->list, plink_list);
++ cnt++;
++ } else
++ err = -ENOMEM;
++ }
++ spin_unlock(&sbinfo->si_plink.spin);
++
++ if (!err) {
++ au_plink_block_maintain(sb);
++ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
++ }
++
++ if (unlikely(cnt > AUFS_PLINK_WARN))
++ AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
++ if (unlikely(err)) {
++ AuWarn("err %d, damaged pseudo link.\n", err);
++ if (!found && plink)
++ do_put_plink(plink, /*do_del*/1);
++ }
++}
++
++/* free all plinks */
++void au_plink_put(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ /* no spin_lock since sbinfo is write-locked */
++ list_for_each_entry_safe(plink, tmp, plink_list, list)
++ do_put_plink(plink, 0);
++ INIT_LIST_HEAD(plink_list);
++}
++
++/* free the plinks on a branch specified by @br_id */
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
++{
++ struct au_sbinfo *sbinfo;
++ struct list_head *plink_list;
++ struct pseudo_link *plink, *tmp;
++ struct inode *inode;
++ aufs_bindex_t bstart, bend, bindex;
++ unsigned char do_put;
++
++ sbinfo = au_sbi(sb);
++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++ plink_list = &sbinfo->si_plink.head;
++ /* no spin_lock since sbinfo is write-locked */
++ list_for_each_entry_safe(plink, tmp, plink_list, list) {
++ do_put = 0;
++ inode = au_igrab(plink->inode);
++ ii_write_lock_child(inode);
++ bstart = au_ibstart(inode);
++ bend = au_ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (!au_h_iptr(inode, bindex)
++ || au_ii_br_id(inode, bindex) != br_id)
++ continue;
++ au_set_h_iptr(inode, bindex, NULL, 0);
++ do_put = 1;
++ break;
++ }
++ } else
++ do_put_plink(plink, 1);
++
++ if (do_put) {
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (au_h_iptr(inode, bindex)) {
++ do_put = 0;
++ break;
++ }
++ if (do_put)
++ do_put_plink(plink, 1);
++ }
++ ii_write_unlock(inode);
++ iput(inode);
++ }
++}
+diff -Naur a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h
+--- a/fs/aufs/rwsem.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/rwsem.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,61 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * simple read-write semaphore wrappers
++ */
++
++#ifndef __AUFS_RWSEM_H__
++#define __AUFS_RWSEM_H__
++
++#ifdef __KERNEL__
++
++#include <linux/rwsem.h>
++
++#define au_rwsem_destroy(rw) AuDebugOn(rwsem_is_locked(rw))
++#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->wait_list))
++
++#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_lock(param) \
++{ down_read(rwsem); } \
++static inline void prefix##_write_lock(param) \
++{ down_write(rwsem); } \
++static inline int prefix##_read_trylock(param) \
++{ return down_read_trylock(rwsem); } \
++static inline int prefix##_write_trylock(param) \
++{ return down_write_trylock(rwsem); }
++/* why is not _nested version defined */
++/* static inline void prefix##_read_trylock_nested(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc)); }
++static inline void prefix##_write_trylock_nestd(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc); } */
++
++#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_unlock(param) \
++{ up_read(rwsem); } \
++static inline void prefix##_write_unlock(param) \
++{ up_write(rwsem); } \
++static inline void prefix##_downgrade_lock(param) \
++{ downgrade_write(rwsem); }
++
++#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
++ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_RWSEM_H__ */
+diff -Naur a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
+--- a/fs/aufs/sbinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sbinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * superblock private data
++ */
++
++#include "aufs.h"
++
++/*
++ * they are necessary regardless sysfs is disabled.
++ */
++void au_si_free(struct kobject *kobj)
++{
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
++
++ sb = sbinfo->si_sb;
++ si_write_lock(sb);
++ au_xino_clr(sb);
++ au_br_free(sbinfo);
++ kfree(sbinfo->si_branch);
++ mutex_destroy(&sbinfo->si_xib_mtx);
++ si_write_unlock(sb);
++ au_rwsem_destroy(&sbinfo->si_rwsem);
++
++ kfree(sbinfo);
++}
++
++int au_si_alloc(struct super_block *sb)
++{
++ int err;
++ struct au_sbinfo *sbinfo;
++
++ err = -ENOMEM;
++ sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
++ if (unlikely(!sbinfo))
++ goto out;
++
++ /* will be reallocated separately */
++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
++ if (unlikely(!sbinfo->si_branch))
++ goto out_sbinfo;
++
++ memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
++ err = sysaufs_si_init(sbinfo);
++ if (unlikely(err))
++ goto out_br;
++
++ au_nwt_init(&sbinfo->si_nowait);
++ init_rwsem(&sbinfo->si_rwsem);
++ down_write(&sbinfo->si_rwsem);
++ sbinfo->si_generation = 0;
++ sbinfo->au_si_status = 0;
++ sbinfo->si_bend = -1;
++ sbinfo->si_last_br_id = 0;
++
++ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
++ sbinfo->si_wbr_create = AuWbrCreate_Def;
++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
++
++ sbinfo->si_mntflags = AuOpt_Def;
++
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ sbinfo->si_xib = NULL;
++ mutex_init(&sbinfo->si_xib_mtx);
++ sbinfo->si_xib_buf = NULL;
++ sbinfo->si_xino_brid = -1;
++ /* leave si_xib_last_pindex and si_xib_next_bit */
++
++ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
++
++ au_spl_init(&sbinfo->si_plink);
++ init_waitqueue_head(&sbinfo->si_plink_wq);
++
++ /* leave other members for sysaufs and si_mnt. */
++ sbinfo->si_sb = sb;
++ sb->s_fs_info = sbinfo;
++ au_debug_sbinfo_init(sbinfo);
++ return 0; /* success */
++
++ out_br:
++ kfree(sbinfo->si_branch);
++ out_sbinfo:
++ kfree(sbinfo);
++ out:
++ return err;
++}
++
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
++{
++ int err, sz;
++ struct au_branch **brp;
++
++ err = -ENOMEM;
++ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
++ if (unlikely(!sz))
++ sz = sizeof(*brp);
++ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
++ if (brp) {
++ sbinfo->si_branch = brp;
++ err = 0;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_sigen_inc(struct super_block *sb)
++{
++ unsigned int gen;
++
++ gen = ++au_sbi(sb)->si_generation;
++ au_update_digen(sb->s_root);
++ au_update_iigen(sb->s_root->d_inode);
++ sb->s_root->d_inode->i_version++;
++ return gen;
++}
++
++aufs_bindex_t au_new_br_id(struct super_block *sb)
++{
++ aufs_bindex_t br_id;
++ int i;
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
++ br_id = ++sbinfo->si_last_br_id;
++ if (br_id && au_br_index(sb, br_id) < 0)
++ return br_id;
++ }
++
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry and super_block lock. call at entry point */
++void aufs_read_lock(struct dentry *dentry, int flags)
++{
++ si_read_lock(dentry->d_sb, flags);
++ if (au_ftest_lock(flags, DW))
++ di_write_lock_child(dentry);
++ else
++ di_read_lock_child(dentry, flags);
++}
++
++void aufs_read_unlock(struct dentry *dentry, int flags)
++{
++ if (au_ftest_lock(flags, DW))
++ di_write_unlock(dentry);
++ else
++ di_read_unlock(dentry, flags);
++ si_read_unlock(dentry->d_sb);
++}
++
++void aufs_write_lock(struct dentry *dentry)
++{
++ si_write_lock(dentry->d_sb);
++ di_write_lock_child(dentry);
++}
++
++void aufs_write_unlock(struct dentry *dentry)
++{
++ di_write_unlock(dentry);
++ si_write_unlock(dentry->d_sb);
++}
++
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
++{
++ si_read_lock(d1->d_sb, flags);
++ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
++}
++
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++ di_write_unlock2(d1, d2);
++ si_read_unlock(d1->d_sb);
++}
+diff -Naur a/fs/aufs/spl.h b/fs/aufs/spl.h
+--- a/fs/aufs/spl.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/spl.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * simple list protected by a spinlock
++ */
++
++#ifndef __AUFS_SPL_H__
++#define __AUFS_SPL_H__
++
++#ifdef __KERNEL__
++
++#include <linux/spinlock.h>
++#include <linux/list.h>
++
++struct au_splhead {
++ spinlock_t spin;
++ struct list_head head;
++};
++
++static inline void au_spl_init(struct au_splhead *spl)
++{
++ spin_lock_init(&spl->spin);
++ INIT_LIST_HEAD(&spl->head);
++}
++
++static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
++{
++ spin_lock(&spl->spin);
++ list_add(list, &spl->head);
++ spin_unlock(&spl->spin);
++}
++
++static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
++{
++ spin_lock(&spl->spin);
++ list_del(list);
++ spin_unlock(&spl->spin);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SPL_H__ */
+diff -Naur a/fs/aufs/super.c b/fs/aufs/super.c
+--- a/fs/aufs/super.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,870 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * mount and super_block operations
++ */
++
++#include <linux/buffer_head.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/*
++ * super_operations
++ */
++static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
++{
++ struct au_icntnr *c;
++
++ c = au_cache_alloc_icntnr();
++ if (c) {
++ inode_init_once(&c->vfs_inode);
++ c->vfs_inode.i_version = 1; /* sigen(sb); */
++ c->iinfo.ii_hinode = NULL;
++ return &c->vfs_inode;
++ }
++ return NULL;
++}
++
++static void aufs_destroy_inode(struct inode *inode)
++{
++ au_iinfo_fin(inode);
++ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
++}
++
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
++{
++ struct inode *inode;
++ int err;
++
++ inode = iget_locked(sb, ino);
++ if (unlikely(!inode)) {
++ inode = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++ if (!(inode->i_state & I_NEW))
++ goto out;
++
++ err = au_xigen_new(inode);
++ if (!err)
++ err = au_iinfo_init(inode);
++ if (!err)
++ inode->i_version++;
++ else {
++ iget_failed(inode);
++ inode = ERR_PTR(err);
++ }
++
++ out:
++ /* never return NULL */
++ AuDebugOn(!inode);
++ AuTraceErrPtr(inode);
++ return inode;
++}
++
++/* lock free root dinfo */
++static int au_show_brs(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ struct path path;
++ struct au_hdentry *hd;
++ struct au_branch *br;
++
++ err = 0;
++ bend = au_sbend(sb);
++ hd = au_di(sb->s_root)->di_hdentry;
++ for (bindex = 0; !err && bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ path.mnt = br->br_mnt;
++ path.dentry = hd[bindex].hd_dentry;
++ err = au_seq_path(seq, &path);
++ if (err > 0)
++ err = seq_printf(seq, "=%s",
++ au_optstr_br_perm(br->br_perm));
++ if (!err && bindex != bend)
++ err = seq_putc(seq, ':');
++ }
++
++ return err;
++}
++
++static void au_show_wbr_create(struct seq_file *m, int v,
++ struct au_sbinfo *sbinfo)
++{
++ const char *pat;
++
++ seq_printf(m, ",create=");
++ pat = au_optstr_wbr_create(v);
++ switch (v) {
++ case AuWbrCreate_TDP:
++ case AuWbrCreate_RR:
++ case AuWbrCreate_MFS:
++ case AuWbrCreate_PMFS:
++ seq_printf(m, pat);
++ break;
++ case AuWbrCreate_MFSV:
++ seq_printf(m, /*pat*/"mfs:%lu",
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ case AuWbrCreate_PMFSV:
++ seq_printf(m, /*pat*/"pmfs:%lu",
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ case AuWbrCreate_MFSRR:
++ seq_printf(m, /*pat*/"mfsrr:%llu",
++ sbinfo->si_wbr_mfs.mfsrr_watermark);
++ break;
++ case AuWbrCreate_MFSRRV:
++ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
++ sbinfo->si_wbr_mfs.mfsrr_watermark,
++ sbinfo->si_wbr_mfs.mfs_expire / HZ);
++ break;
++ }
++}
++
++static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
++{
++#ifdef CONFIG_SYSFS
++ return 0;
++#else
++ int err;
++ const int len = sizeof(AUFS_XINO_FNAME) - 1;
++ aufs_bindex_t bindex, brid;
++ struct super_block *sb;
++ struct qstr *name;
++ struct file *f;
++ struct dentry *d, *h_root;
++
++ err = 0;
++ sb = mnt->mnt_sb;
++ f = au_sbi(sb)->si_xib;
++ if (!f)
++ goto out;
++
++ /* stop printing the default xino path on the first writable branch */
++ h_root = NULL;
++ brid = au_xino_brid(sb);
++ if (brid >= 0) {
++ bindex = au_br_index(sb, brid);
++ h_root = au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
++ }
++ d = f->f_dentry;
++ name = &d->d_name;
++ /* safe ->d_parent because the file is unlinked */
++ if (d->d_parent == h_root
++ && name->len == len
++ && !memcmp(name->name, AUFS_XINO_FNAME, len))
++ goto out;
++
++ seq_puts(seq, ",xino=");
++ err = au_xino_path(seq, f);
++
++ out:
++ return err;
++#endif
++}
++
++/* seq_file will re-call me in case of too long string */
++static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ int err, n;
++ unsigned int mnt_flags, v;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++
++#define AuBool(name, str) do { \
++ v = au_opt_test(mnt_flags, name); \
++ if (v != au_opt_test(AuOpt_Def, name)) \
++ seq_printf(m, ",%s" #str, v ? "" : "no"); \
++} while (0)
++
++#define AuStr(name, str) do { \
++ v = mnt_flags & AuOptMask_##name; \
++ if (v != (AuOpt_Def & AuOptMask_##name)) \
++ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
++} while (0)
++
++#define AuUInt(name, str, val) do { \
++ if (val != AUFS_##name##_DEF) \
++ seq_printf(m, "," #str "=%u", val); \
++} while (0)
++
++ /* lock free root dinfo */
++ sb = mnt->mnt_sb;
++ si_noflush_read_lock(sb);
++ sbinfo = au_sbi(sb);
++ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
++
++ mnt_flags = au_mntflags(sb);
++ if (au_opt_test(mnt_flags, XINO)) {
++ err = au_show_xino(m, mnt);
++ if (unlikely(err))
++ goto out;
++ } else
++ seq_puts(m, ",noxino");
++
++ AuBool(TRUNC_XINO, trunc_xino);
++ AuStr(UDBA, udba);
++ AuBool(SHWH, shwh);
++ AuBool(PLINK, plink);
++ /* AuBool(DIRPERM1, dirperm1); */
++ /* AuBool(REFROF, refrof); */
++
++ v = sbinfo->si_wbr_create;
++ if (v != AuWbrCreate_Def)
++ au_show_wbr_create(m, v, sbinfo);
++
++ v = sbinfo->si_wbr_copyup;
++ if (v != AuWbrCopyup_Def)
++ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
++
++ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
++ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
++ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
++
++ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
++
++ n = sbinfo->si_rdcache / HZ;
++ AuUInt(RDCACHE, rdcache, n);
++
++ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
++ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
++
++ AuBool(SUM, sum);
++ /* AuBool(SUM_W, wsum); */
++ AuBool(WARN_PERM, warn_perm);
++ AuBool(VERBOSE, verbose);
++
++ out:
++ /* be sure to print "br:" last */
++ if (!sysaufs_brs) {
++ seq_puts(m, ",br:");
++ au_show_brs(m, sb);
++ }
++ si_read_unlock(sb);
++ return 0;
++
++#undef Deleted
++#undef AuBool
++#undef AuStr
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* sum mode which returns the summation for statfs(2) */
++
++static u64 au_add_till_max(u64 a, u64 b)
++{
++ u64 old;
++
++ old = a;
++ a += b;
++ if (old < a)
++ return a;
++ return ULLONG_MAX;
++}
++
++static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
++{
++ int err;
++ u64 blocks, bfree, bavail, files, ffree;
++ aufs_bindex_t bend, bindex, i;
++ unsigned char shared;
++ struct vfsmount *h_mnt;
++ struct super_block *h_sb;
++
++ blocks = 0;
++ bfree = 0;
++ bavail = 0;
++ files = 0;
++ ffree = 0;
++
++ err = 0;
++ bend = au_sbend(sb);
++ for (bindex = bend; bindex >= 0; bindex--) {
++ h_mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_mnt->mnt_sb;
++ shared = 0;
++ for (i = bindex + 1; !shared && i <= bend; i++)
++ shared = (au_sbr_sb(sb, i) == h_sb);
++ if (shared)
++ continue;
++
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(h_mnt->mnt_root, buf);
++ if (unlikely(err))
++ goto out;
++
++ blocks = au_add_till_max(blocks, buf->f_blocks);
++ bfree = au_add_till_max(bfree, buf->f_bfree);
++ bavail = au_add_till_max(bavail, buf->f_bavail);
++ files = au_add_till_max(files, buf->f_files);
++ ffree = au_add_till_max(ffree, buf->f_ffree);
++ }
++
++ buf->f_blocks = blocks;
++ buf->f_bfree = bfree;
++ buf->f_bavail = bavail;
++ buf->f_files = files;
++ buf->f_ffree = ffree;
++
++ out:
++ return err;
++}
++
++static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ int err;
++ struct super_block *sb;
++
++ /* lock free root dinfo */
++ sb = dentry->d_sb;
++ si_noflush_read_lock(sb);
++ if (!au_opt_test(au_mntflags(sb), SUM))
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
++ else
++ err = au_statfs_sum(sb, buf);
++ si_read_unlock(sb);
++
++ if (!err) {
++ buf->f_type = AUFS_SUPER_MAGIC;
++ buf->f_namelen -= AUFS_WH_PFX_LEN;
++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
++ }
++ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* try flushing the lower fs at aufs remount/unmount time */
++
++static void au_fsync_br(struct super_block *sb)
++{
++ aufs_bindex_t bend, bindex;
++ int brperm;
++ struct au_branch *br;
++ struct super_block *h_sb;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex < bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ brperm = br->br_perm;
++ if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
++ continue;
++ h_sb = br->br_mnt->mnt_sb;
++ if (bdev_read_only(h_sb->s_bdev))
++ continue;
++
++ lockdep_off();
++ down_write(&h_sb->s_umount);
++ shrink_dcache_sb(h_sb);
++ fsync_super(h_sb);
++ up_write(&h_sb->s_umount);
++ lockdep_on();
++ }
++}
++
++/*
++ * this IS NOT for super_operations.
++ * I guess it will be reverted someday.
++ */
++static void aufs_umount_begin(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++
++ si_write_lock(sb);
++ au_fsync_br(sb);
++ if (au_opt_test(au_mntflags(sb), PLINK))
++ au_plink_put(sb);
++ if (sbinfo->si_wbr_create_ops->fin)
++ sbinfo->si_wbr_create_ops->fin(sb);
++ si_write_unlock(sb);
++}
++
++/* final actions when unmounting a file system */
++static void aufs_put_super(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ return;
++
++ aufs_umount_begin(sb);
++ dbgaufs_si_fin(sbinfo);
++ kobject_put(&sbinfo->si_kobj);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * refresh dentry and inode at remount time.
++ */
++static int do_refresh(struct dentry *dentry, mode_t type,
++ unsigned int dir_flags)
++{
++ int err;
++ struct dentry *parent;
++
++ di_write_lock_child(dentry);
++ parent = dget_parent(dentry);
++ di_read_lock_parent(parent, AuLock_IR);
++
++ /* returns the number of positive dentries */
++ err = au_refresh_hdentry(dentry, type);
++ if (err >= 0) {
++ struct inode *inode = dentry->d_inode;
++ err = au_refresh_hinode(inode, dentry);
++ if (!err && type == S_IFDIR)
++ au_reset_hinotify(inode, dir_flags);
++ }
++ if (unlikely(err))
++ AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
++
++ di_read_unlock(parent, AuLock_IR);
++ dput(parent);
++ di_write_unlock(dentry);
++
++ return err;
++}
++
++static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
++{
++ return S_ISDIR(dentry->d_inode->i_mode);
++}
++
++/* gave up consolidating with refresh_nondir() */
++static int refresh_dir(struct dentry *root, unsigned int sigen)
++{
++ int err, i, j, ndentry, e;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++ struct inode *inode;
++ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
++
++ err = 0;
++ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++ ii_write_lock_child(inode);
++ e = au_refresh_hinode_self(inode, /*do_attr*/1);
++ ii_write_unlock(inode);
++ if (unlikely(e)) {
++ AuDbg("e %d, i%lu\n", e, inode->i_ino);
++ if (!err)
++ err = e;
++ /* go on even if err */
++ }
++ }
++
++ e = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out;
++ }
++ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out_dpages;
++ }
++
++ for (i = 0; !e && i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; !e && j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ au_dbg_verify_dir_parent(d, sigen);
++ if (au_digen(d) != sigen) {
++ e = do_refresh(d, S_IFDIR, flags);
++ if (unlikely(e && !err))
++ err = e;
++ /* break on err */
++ }
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
++{
++ return !S_ISDIR(dentry->d_inode->i_mode);
++}
++
++static int refresh_nondir(struct dentry *root, unsigned int sigen,
++ int do_dentry)
++{
++ int err, i, j, ndentry, e;
++ struct au_dcsub_pages dpages;
++ struct au_dpage *dpage;
++ struct dentry **dentries;
++ struct inode *inode;
++
++ err = 0;
++ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++ ii_write_lock_child(inode);
++ e = au_refresh_hinode_self(inode, /*do_attr*/1);
++ ii_write_unlock(inode);
++ if (unlikely(e)) {
++ AuDbg("e %d, i%lu\n", e, inode->i_ino);
++ if (!err)
++ err = e;
++ /* go on even if err */
++ }
++ }
++
++ if (!do_dentry)
++ goto out;
++
++ e = au_dpages_init(&dpages, GFP_NOFS);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out;
++ }
++ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
++ if (unlikely(e)) {
++ if (!err)
++ err = e;
++ goto out_dpages;
++ }
++
++ for (i = 0; i < dpages.ndpage; i++) {
++ dpage = dpages.dpages + i;
++ dentries = dpage->dentries;
++ ndentry = dpage->ndentry;
++ for (j = 0; j < ndentry; j++) {
++ struct dentry *d;
++
++ d = dentries[j];
++ au_dbg_verify_nondir_parent(d, sigen);
++ inode = d->d_inode;
++ if (inode && au_digen(d) != sigen) {
++ e = do_refresh(d, inode->i_mode & S_IFMT,
++ /*dir_flags*/0);
++ if (unlikely(e && !err))
++ err = e;
++ /* go on even err */
++ }
++ }
++ }
++
++ out_dpages:
++ au_dpages_free(&dpages);
++ out:
++ return err;
++}
++
++static void au_remount_refresh(struct super_block *sb, unsigned int flags)
++{
++ int err;
++ unsigned int sigen;
++ struct au_sbinfo *sbinfo;
++ struct dentry *root;
++ struct inode *inode;
++
++ au_sigen_inc(sb);
++ sigen = au_sigen(sb);
++ sbinfo = au_sbi(sb);
++ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
++
++ root = sb->s_root;
++ DiMustNoWaiters(root);
++ inode = root->d_inode;
++ IiMustNoWaiters(inode);
++ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++ di_write_unlock(root);
++
++ err = refresh_dir(root, sigen);
++ if (unlikely(err)) {
++ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
++ AuWarn("Refreshing directories failed, ignored (%d)\n", err);
++ }
++
++ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
++ err = refresh_nondir(root, sigen, !err);
++ if (unlikely(err))
++ AuWarn("Refreshing non-directories failed, ignored"
++ "(%d)\n", err);
++ }
++
++ /* aufs_write_lock() calls ..._child() */
++ di_write_lock_child(root);
++ au_cpup_attr_all(root->d_inode, /*force*/1);
++}
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++ AuTraceErr(err);
++
++ switch (err) {
++ case -ENOENT:
++ case -ENOTDIR:
++ case -EEXIST:
++ case -EIO:
++ err = -EINVAL;
++ }
++ return err;
++}
++
++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++ int err;
++ struct au_opts opts;
++ struct dentry *root;
++ struct inode *inode;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ root = sb->s_root;
++ if (!data || !*data) {
++ aufs_write_lock(root);
++ err = au_opts_verify(sb, *flags, /*pending*/0);
++ if (!err)
++ au_fsync_br(sb);
++ aufs_write_unlock(root);
++ goto out;
++ }
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++ opts.flags = AuOpts_REMOUNT;
++ opts.sb_flags = *flags;
++
++ /* parse it before aufs lock */
++ err = au_opts_parse(sb, data, &opts);
++ if (unlikely(err))
++ goto out_opts;
++
++ sbinfo = au_sbi(sb);
++ inode = root->d_inode;
++ mutex_lock(&inode->i_mutex);
++ aufs_write_lock(root);
++ au_fsync_br(sb);
++
++ /* au_opts_remount() may return an error */
++ err = au_opts_remount(sb, &opts);
++ au_opts_free(&opts);
++
++ if (au_ftest_opts(opts.flags, REFRESH_DIR)
++ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
++ au_remount_refresh(sb, opts.flags);
++
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ err = cvt_err(err);
++ AuTraceErr(err);
++ return err;
++}
++
++static struct super_operations aufs_sop = {
++ .alloc_inode = aufs_alloc_inode,
++ .destroy_inode = aufs_destroy_inode,
++ .drop_inode = generic_delete_inode,
++ .show_options = aufs_show_options,
++ .statfs = aufs_statfs,
++ .put_super = aufs_put_super,
++ .remount_fs = aufs_remount_fs
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int alloc_root(struct super_block *sb)
++{
++ int err;
++ struct inode *inode;
++ struct dentry *root;
++
++ err = -ENOMEM;
++ inode = au_iget_locked(sb, AUFS_ROOT_INO);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ goto out;
++
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ inode->i_mode = S_IFDIR;
++ inode->i_nlink = 2;
++ unlock_new_inode(inode);
++
++ root = d_alloc_root(inode);
++ if (unlikely(!root))
++ goto out_iput;
++ err = PTR_ERR(root);
++ if (IS_ERR(root))
++ goto out_iput;
++
++ err = au_alloc_dinfo(root);
++ if (!err) {
++ sb->s_root = root;
++ return 0; /* success */
++ }
++ dput(root);
++ goto out; /* do not iput */
++
++ out_iput:
++ iget_failed(inode);
++ iput(inode);
++ out:
++ return err;
++
++}
++
++static int aufs_fill_super(struct super_block *sb, void *raw_data,
++ int silent __maybe_unused)
++{
++ int err;
++ struct au_opts opts;
++ struct dentry *root;
++ struct inode *inode;
++ char *arg = raw_data;
++
++ if (unlikely(!arg || !*arg)) {
++ err = -EINVAL;
++ AuErr("no arg\n");
++ goto out;
++ }
++
++ err = -ENOMEM;
++ memset(&opts, 0, sizeof(opts));
++ opts.opt = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!opts.opt))
++ goto out;
++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++ opts.sb_flags = sb->s_flags;
++
++ err = au_si_alloc(sb);
++ if (unlikely(err))
++ goto out_opts;
++
++ /* all timestamps always follow the ones on the branch */
++ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
++ sb->s_op = &aufs_sop;
++ sb->s_magic = AUFS_SUPER_MAGIC;
++ sb->s_maxbytes = 0;
++ au_export_init(sb);
++
++ err = alloc_root(sb);
++ if (unlikely(err)) {
++ si_write_unlock(sb);
++ goto out_info;
++ }
++ root = sb->s_root;
++ inode = root->d_inode;
++
++ /*
++ * actually we can parse options regardless aufs lock here.
++ * but at remount time, parsing must be done before aufs lock.
++ * so we follow the same rule.
++ */
++ ii_write_lock_parent(inode);
++ aufs_write_unlock(root);
++ err = au_opts_parse(sb, arg, &opts);
++ if (unlikely(err))
++ goto out_root;
++
++ /* lock vfs_inode first, then aufs. */
++ mutex_lock(&inode->i_mutex);
++ inode->i_op = &aufs_dir_iop;
++ inode->i_fop = &aufs_dir_fop;
++ aufs_write_lock(root);
++ err = au_opts_mount(sb, &opts);
++ au_opts_free(&opts);
++ if (unlikely(err))
++ goto out_unlock;
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++ goto out_opts; /* success */
++
++ out_unlock:
++ aufs_write_unlock(root);
++ mutex_unlock(&inode->i_mutex);
++ out_root:
++ dput(root);
++ sb->s_root = NULL;
++ out_info:
++ kobject_put(&au_sbi(sb)->si_kobj);
++ sb->s_fs_info = NULL;
++ out_opts:
++ free_page((unsigned long)opts.opt);
++ out:
++ AuTraceErr(err);
++ err = cvt_err(err);
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name __maybe_unused, void *raw_data,
++ struct vfsmount *mnt)
++{
++ int err;
++ struct super_block *sb;
++
++ /* all timestamps always follow the ones on the branch */
++ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
++ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
++ if (!err) {
++ sb = mnt->mnt_sb;
++ si_write_lock(sb);
++ sysaufs_brs_add(sb, 0);
++ si_write_unlock(sb);
++ }
++ return err;
++}
++
++struct file_system_type aufs_fs_type = {
++ .name = AUFS_FSTYPE,
++ .fs_flags =
++ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
++ | FS_REVAL_DOT, /* for NFS branch and udba */
++ .get_sb = aufs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ /* no need to __module_get() and module_put(). */
++ .owner = THIS_MODULE,
++};
+diff -Naur a/fs/aufs/super.h b/fs/aufs/super.h
+--- a/fs/aufs/super.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,359 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * super_block operations
++ */
++
++#ifndef __AUFS_SUPER_H__
++#define __AUFS_SUPER_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "spl.h"
++#include "wkq.h"
++
++typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
++typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
++ loff_t *);
++
++/* policies to select one among multiple writable branches */
++struct au_wbr_copyup_operations {
++ int (*copyup)(struct dentry *dentry);
++};
++
++struct au_wbr_create_operations {
++ int (*create)(struct dentry *dentry, int isdir);
++ int (*init)(struct super_block *sb);
++ int (*fin)(struct super_block *sb);
++};
++
++struct au_wbr_mfs {
++ struct mutex mfs_lock; /* protect this structure */
++ unsigned long mfs_jiffy;
++ unsigned long mfs_expire;
++ aufs_bindex_t mfs_bindex;
++
++ unsigned long long mfsrr_bytes;
++ unsigned long long mfsrr_watermark;
++};
++
++/* sbinfo status flags */
++/*
++ * set true when refresh_dirs() failed at remount time.
++ * then try refreshing dirs at access time again.
++ * if it is false, refreshing dirs at access time is unnecesary
++ */
++#define AuSi_FAILED_REFRESH_DIRS 1
++#define AuSi_MAINTAIN_PLINK (1 << 1) /* ioctl */
++#define au_ftest_si(sbinfo, name) ((sbinfo)->au_si_status & AuSi_##name)
++#define au_fset_si(sbinfo, name) \
++ { (sbinfo)->au_si_status |= AuSi_##name; }
++#define au_fclr_si(sbinfo, name) \
++ { (sbinfo)->au_si_status &= ~AuSi_##name; }
++
++struct au_branch;
++struct au_sbinfo {
++ /* nowait tasks in the system-wide workqueue */
++ struct au_nowait_tasks si_nowait;
++
++ struct rw_semaphore si_rwsem;
++
++ /* branch management */
++ unsigned int si_generation;
++
++ /* see above flags */
++ unsigned char au_si_status;
++
++ aufs_bindex_t si_bend;
++ aufs_bindex_t si_last_br_id;
++ struct au_branch **si_branch;
++
++ /* policy to select a writable branch */
++ unsigned char si_wbr_copyup;
++ unsigned char si_wbr_create;
++ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
++ struct au_wbr_create_operations *si_wbr_create_ops;
++
++ /* round robin */
++ atomic_t si_wbr_rr_next;
++
++ /* most free space */
++ struct au_wbr_mfs si_wbr_mfs;
++
++ /* mount flags */
++ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
++ unsigned int si_mntflags;
++
++ /* external inode number (bitmap and translation table) */
++ au_readf_t si_xread;
++ au_writef_t si_xwrite;
++ struct file *si_xib;
++ struct mutex si_xib_mtx; /* protect xib members */
++ unsigned long *si_xib_buf;
++ unsigned long si_xib_last_pindex;
++ int si_xib_next_bit;
++ aufs_bindex_t si_xino_brid;
++ /* reserved for future use */
++ /* unsigned long long si_xib_limit; */ /* Max xib file size */
++
++#ifdef CONFIG_AUFS_EXPORT
++ /* i_generation */
++ struct file *si_xigen;
++ atomic_t si_xigen_next;
++#endif
++
++ /* vdir parameters */
++ unsigned long si_rdcache; /* max cache time in HZ */
++ unsigned int si_rdblk; /* deblk size */
++ unsigned int si_rdhash; /* hash size */
++
++ /*
++ * If the number of whiteouts are larger than si_dirwh, leave all of
++ * them after au_whtmp_ren to reduce the cost of rmdir(2).
++ * future fsck.aufs or kernel thread will remove them later.
++ * Otherwise, remove all whiteouts and the dir in rmdir(2).
++ */
++ unsigned int si_dirwh;
++
++ /*
++ * rename(2) a directory with all children.
++ */
++ /* reserved for future use */
++ /* int si_rendir; */
++
++ /* pseudo_link list */
++ struct au_splhead si_plink;
++ wait_queue_head_t si_plink_wq;
++
++ /*
++ * sysfs and lifetime management.
++ * this is not a small structure and it may be a waste of memory in case
++ * of sysfs is disabled, particulary when many aufs-es are mounted.
++ * but using sysfs is majority.
++ */
++ struct kobject si_kobj;
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
++#ifdef CONFIG_AUFS_EXPORT
++ struct dentry *si_dbgaufs_xigen;
++#endif
++#endif
++
++ /* dirty, necessary for unmounting, sysfs and sysrq */
++ struct super_block *si_sb;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* policy to select one among writable branches */
++#define AuWbrCopyup(sbinfo, args...) \
++ ((sbinfo)->si_wbr_copyup_ops->copyup(args))
++#define AuWbrCreate(sbinfo, args...) \
++ ((sbinfo)->si_wbr_create_ops->create(args))
++
++/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
++#define AuLock_DW 1 /* write-lock dentry */
++#define AuLock_IR (1 << 1) /* read-lock inode */
++#define AuLock_IW (1 << 2) /* write-lock inode */
++#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
++#define AuLock_DIR (1 << 4) /* target is a dir */
++#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
++#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
++#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
++
++/* ---------------------------------------------------------------------- */
++
++/* super.c */
++extern struct file_system_type aufs_fs_type;
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
++
++/* sbinfo.c */
++void au_si_free(struct kobject *kobj);
++int au_si_alloc(struct super_block *sb);
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
++
++unsigned int au_sigen_inc(struct super_block *sb);
++aufs_bindex_t au_new_br_id(struct super_block *sb);
++
++void aufs_read_lock(struct dentry *dentry, int flags);
++void aufs_read_unlock(struct dentry *dentry, int flags);
++void aufs_write_lock(struct dentry *dentry);
++void aufs_write_unlock(struct dentry *dentry);
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
++
++/* wbr_policy.c */
++extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
++extern struct au_wbr_create_operations au_wbr_create_ops[];
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_sbinfo *au_sbi(struct super_block *sb)
++{
++ return sb->s_fs_info;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++void au_export_init(struct super_block *sb);
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
++}
++
++int au_xigen_inc(struct inode *inode);
++int au_xigen_new(struct inode *inode);
++int au_xigen_set(struct super_block *sb, struct file *base);
++void au_xigen_clr(struct super_block *sb);
++
++static inline int au_busy_or_stale(void)
++{
++ if (!au_test_nfsd(current))
++ return -EBUSY;
++ return -ESTALE;
++}
++#else
++static inline void au_export_init(struct super_block *sb)
++{
++ /* nothing */
++}
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++ return 0;
++}
++
++static inline int au_xigen_inc(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int au_xigen_new(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int au_xigen_set(struct super_block *sb, struct file *base)
++{
++ return 0;
++}
++
++static inline void au_xigen_clr(struct super_block *sb)
++{
++ /* empty */
++}
++
++static inline int au_busy_or_stale(void)
++{
++ return -EBUSY;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
++{
++#ifdef CONFIG_DEBUG_FS
++ sbinfo->si_dbgaufs = NULL;
++ sbinfo->si_dbgaufs_xib = NULL;
++#ifdef CONFIG_AUFS_EXPORT
++ sbinfo->si_dbgaufs_xigen = NULL;
++#endif
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock superblock. mainly for entry point functions */
++/*
++ * si_noflush_read_lock, si_noflush_write_lock,
++ * si_read_unlock, si_write_unlock, si_downgrade_lock
++ */
++AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
++ &au_sbi(sb)->si_rwsem);
++AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
++
++static inline void si_read_lock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ si_noflush_read_lock(sb);
++}
++
++static inline void si_write_lock(struct super_block *sb)
++{
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ si_noflush_write_lock(sb);
++}
++
++static inline int si_read_trylock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ return si_noflush_read_trylock(sb);
++}
++
++static inline int si_write_trylock(struct super_block *sb, int flags)
++{
++ if (au_ftest_lock(flags, FLUSH))
++ au_nwt_flush(&au_sbi(sb)->si_nowait);
++ return si_noflush_write_trylock(sb);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_sbend(struct super_block *sb)
++{
++ return au_sbi(sb)->si_bend;
++}
++
++static inline unsigned int au_mntflags(struct super_block *sb)
++{
++ return au_sbi(sb)->si_mntflags;
++}
++
++static inline unsigned int au_sigen(struct super_block *sb)
++{
++ return au_sbi(sb)->si_generation;
++}
++
++static inline struct au_branch *au_sbr(struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ return au_sbi(sb)->si_branch[0 + bindex];
++}
++
++static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
++{
++ au_sbi(sb)->si_xino_brid = brid;
++}
++
++static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
++{
++ return au_sbi(sb)->si_xino_brid;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SUPER_H__ */
+diff -Naur a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
+--- a/fs/aufs/sysaufs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface and lifetime management
++ * they are necessary regardless sysfs is disabled.
++ */
++
++#include <linux/fs.h>
++#include <linux/random.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++unsigned long sysaufs_si_mask;
++struct kset *sysaufs_ket;
++
++#define AuSiAttr(_name) { \
++ .attr = { .name = __stringify(_name), .mode = 0444 }, \
++ .show = sysaufs_si_##_name, \
++}
++
++static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
++struct attribute *sysaufs_si_attrs[] = {
++ &sysaufs_si_attr_xi_path.attr,
++ NULL,
++};
++
++static struct sysfs_ops au_sbi_ops = {
++ .show = sysaufs_si_show
++};
++
++static struct kobj_type au_sbi_ktype = {
++ .release = au_si_free,
++ .sysfs_ops = &au_sbi_ops,
++ .default_attrs = sysaufs_si_attrs
++};
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_init(struct au_sbinfo *sbinfo)
++{
++ int err;
++
++ sbinfo->si_kobj.kset = sysaufs_ket;
++ /* cf. sysaufs_name() */
++ err = kobject_init_and_add
++ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
++ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
++
++ dbgaufs_si_null(sbinfo);
++ if (!err) {
++ err = dbgaufs_si_init(sbinfo);
++ if (unlikely(err))
++ kobject_put(&sbinfo->si_kobj);
++ }
++ return err;
++}
++
++void sysaufs_fin(void)
++{
++ dbgaufs_fin();
++ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++ kset_unregister(sysaufs_ket);
++}
++
++int __init sysaufs_init(void)
++{
++ int err;
++
++ do {
++ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
++ } while (!sysaufs_si_mask);
++
++ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
++ err = PTR_ERR(sysaufs_ket);
++ if (IS_ERR(sysaufs_ket))
++ goto out;
++ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++ if (unlikely(err)) {
++ kset_unregister(sysaufs_ket);
++ goto out;
++ }
++
++ err = dbgaufs_init();
++ if (unlikely(err))
++ sysaufs_fin();
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
+--- a/fs/aufs/sysaufs.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface and mount lifetime management
++ */
++
++#ifndef __SYSAUFS_H__
++#define __SYSAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sysfs.h>
++#include <linux/aufs_type.h>
++#include "module.h"
++
++struct super_block;
++struct au_sbinfo;
++
++struct sysaufs_si_attr {
++ struct attribute attr;
++ int (*show)(struct seq_file *seq, struct super_block *sb);
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* sysaufs.c */
++extern unsigned long sysaufs_si_mask;
++extern struct kset *sysaufs_ket;
++extern struct attribute *sysaufs_si_attrs[];
++int sysaufs_si_init(struct au_sbinfo *sbinfo);
++int __init sysaufs_init(void);
++void sysaufs_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++/* some people doesn't like to show a pointer in kernel */
++static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
++{
++ return sysaufs_si_mask ^ (unsigned long)sbinfo;
++}
++
++#define SysaufsSiNamePrefix "si_"
++#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
++static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
++{
++ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
++ sysaufs_si_id(sbinfo));
++}
++
++struct au_branch;
++#ifdef CONFIG_SYSFS
++/* sysfs.c */
++extern struct attribute_group *sysaufs_attr_group;
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf);
++
++void sysaufs_br_init(struct au_branch *br);
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++
++#define sysaufs_brs_init() do {} while (0)
++
++#else
++#define sysaufs_attr_group NULL
++
++static inline
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++ return 0;
++}
++
++static inline
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ return 0;
++}
++
++static inline void sysaufs_br_init(struct au_branch *br)
++{
++ /* empty */
++}
++
++static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ /* nothing */
++}
++
++static inline void sysaufs_brs_init(void)
++{
++ sysaufs_brs = 0;
++}
++
++#endif /* CONFIG_SYSFS */
++
++#endif /* __KERNEL__ */
++#endif /* __SYSAUFS_H__ */
+diff -Naur a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
+--- a/fs/aufs/sysfs.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysfs.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,208 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sysfs interface
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++static struct attribute *au_attr[] = {
++ NULL, /* need to NULL terminate the list of attributes */
++};
++
++static struct attribute_group sysaufs_attr_group_body = {
++ .attrs = au_attr
++};
++
++struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++ int err;
++
++ err = 0;
++ if (au_opt_test(au_mntflags(sb), XINO)) {
++ err = au_xino_path(seq, au_sbi(sb)->si_xib);
++ seq_putc(seq, '\n');
++ }
++ return err;
++}
++
++/*
++ * the lifetime of branch is independent from the entry under sysfs.
++ * sysfs handles the lifetime of the entry, and never call ->show() after it is
++ * unlinked.
++ */
++static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
++ aufs_bindex_t bindex)
++{
++ struct path path;
++ struct dentry *root;
++ struct au_branch *br;
++
++ AuDbg("b%d\n", bindex);
++
++ root = sb->s_root;
++ di_read_lock_parent(root, !AuLock_IR);
++ br = au_sbr(sb, bindex);
++ path.mnt = br->br_mnt;
++ path.dentry = au_h_dptr(root, bindex);
++ au_seq_path(seq, &path);
++ di_read_unlock(root, !AuLock_IR);
++ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct seq_file *au_seq(char *p, ssize_t len)
++{
++ struct seq_file *seq;
++
++ seq = kzalloc(sizeof(*seq), GFP_NOFS);
++ if (seq) {
++ /* mutex_init(&seq.lock); */
++ seq->buf = p;
++ seq->size = len;
++ return seq; /* success */
++ }
++
++ seq = ERR_PTR(-ENOMEM);
++ return seq;
++}
++
++#define SysaufsBr_PREFIX "br"
++
++/* todo: file size may exceed PAGE_SIZE */
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ ssize_t err;
++ long l;
++ aufs_bindex_t bend;
++ struct au_sbinfo *sbinfo;
++ struct super_block *sb;
++ struct seq_file *seq;
++ char *name;
++ struct attribute **cattr;
++
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ sb = sbinfo->si_sb;
++ si_noflush_read_lock(sb);
++
++ seq = au_seq(buf, PAGE_SIZE);
++ err = PTR_ERR(seq);
++ if (IS_ERR(seq))
++ goto out;
++
++ name = (void *)attr->name;
++ cattr = sysaufs_si_attrs;
++ while (*cattr) {
++ if (!strcmp(name, (*cattr)->name)) {
++ err = container_of(*cattr, struct sysaufs_si_attr, attr)
++ ->show(seq, sb);
++ goto out_seq;
++ }
++ cattr++;
++ }
++
++ bend = au_sbend(sb);
++ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
++ name += sizeof(SysaufsBr_PREFIX) - 1;
++ err = strict_strtol(name, 10, &l);
++ if (!err) {
++ if (l <= bend)
++ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
++ else
++ err = -ENOENT;
++ }
++ goto out_seq;
++ }
++ BUG();
++
++ out_seq:
++ if (!err) {
++ err = seq->count;
++ /* sysfs limit */
++ if (unlikely(err == PAGE_SIZE))
++ err = -EFBIG;
++ }
++ kfree(seq);
++ out:
++ si_read_unlock(sb);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void sysaufs_br_init(struct au_branch *br)
++{
++ br->br_attr.name = br->br_name;
++ br->br_attr.mode = S_IRUGO;
++ br->br_attr.owner = THIS_MODULE;
++}
++
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++ struct au_branch *br;
++ struct kobject *kobj;
++ aufs_bindex_t bend;
++
++ dbgaufs_brs_del(sb, bindex);
++
++ if (!sysaufs_brs)
++ return;
++
++ kobj = &au_sbi(sb)->si_kobj;
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ sysfs_remove_file(kobj, &br->br_attr);
++ }
++}
++
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ aufs_bindex_t bend;
++ struct kobject *kobj;
++ struct au_branch *br;
++
++ dbgaufs_brs_add(sb, bindex);
++
++ if (!sysaufs_brs)
++ return;
++
++ kobj = &au_sbi(sb)->si_kobj;
++ bend = au_sbend(sb);
++ for (; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
++ "%d", bindex);
++ err = sysfs_create_file(kobj, &br->br_attr);
++ if (unlikely(err))
++ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
++ }
++}
+diff -Naur a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c
+--- a/fs/aufs/sysrq.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysrq.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,115 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * magic sysrq hanlder
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++/* #include <linux/sysrq.h> */
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++static void sysrq_sb(struct super_block *sb)
++{
++ char *plevel;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ plevel = au_plevel;
++ au_plevel = KERN_WARNING;
++ au_debug(1);
++
++ sbinfo = au_sbi(sb);
++ pr_warning("si=%lx\n", sysaufs_si_id(sbinfo));
++ pr_warning(AUFS_NAME ": superblock\n");
++ au_dpri_sb(sb);
++ pr_warning(AUFS_NAME ": root dentry\n");
++ au_dpri_dentry(sb->s_root);
++ pr_warning(AUFS_NAME ": root inode\n");
++ au_dpri_inode(sb->s_root->d_inode);
++#if 0
++ struct inode *i;
++ pr_warning(AUFS_NAME ": isolated inode\n");
++ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
++ if (list_empty(&i->i_dentry))
++ au_dpri_inode(i);
++#endif
++ pr_warning(AUFS_NAME ": files\n");
++ list_for_each_entry(file, &sb->s_files, f_u.fu_list)
++ if (!special_file(file->f_dentry->d_inode->i_mode))
++ au_dpri_file(file);
++
++ au_plevel = plevel;
++ au_debug(0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* module parameter */
++static char *aufs_sysrq_key = "a";
++module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
++MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
++
++static void au_sysrq(int key __maybe_unused,
++ struct tty_struct *tty __maybe_unused)
++{
++ struct kobject *kobj;
++ struct au_sbinfo *sbinfo;
++
++ /* spin_lock(&sysaufs_ket->list_lock); */
++ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++ sysrq_sb(sbinfo->si_sb);
++ }
++ /* spin_unlock(&sysaufs_ket->list_lock); */
++}
++
++static struct sysrq_key_op au_sysrq_op = {
++ .handler = au_sysrq,
++ .help_msg = "Aufs",
++ .action_msg = "Aufs",
++ .enable_mask = SYSRQ_ENABLE_DUMP
++};
++
++/* ---------------------------------------------------------------------- */
++
++int __init au_sysrq_init(void)
++{
++ int err;
++ char key;
++
++ err = -1;
++ key = *aufs_sysrq_key;
++ if ('a' <= key && key <= 'z')
++ err = register_sysrq_key(key, &au_sysrq_op);
++ if (unlikely(err))
++ AuErr("err %d, sysrq=%c\n", err, key);
++ return err;
++}
++
++void au_sysrq_fin(void)
++{
++ int err;
++ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
++ if (unlikely(err))
++ AuErr("err %d (ignored)\n", err);
++}
+diff -Naur a/fs/aufs/vdir.c b/fs/aufs/vdir.c
+--- a/fs/aufs/vdir.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vdir.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * virtual or vertical directory
++ */
++
++#include <linux/hash.h>
++#include "aufs.h"
++
++static unsigned int calc_size(int nlen)
++{
++ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
++ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
++}
++
++static int set_deblk_end(union au_vdir_deblk_p *p,
++ union au_vdir_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
++ p->de->de_str.len = 0;
++ /* smp_mb(); */
++ return 0;
++ }
++ return -1; /* error */
++}
++
++/* returns true or false */
++static int is_deblk_end(union au_vdir_deblk_p *p,
++ union au_vdir_deblk_p *deblk_end)
++{
++ if (calc_size(0) <= deblk_end->deblk - p->deblk)
++ return !p->de->de_str.len;
++ return 1;
++}
++
++static unsigned char *last_deblk(struct au_vdir *vdir)
++{
++ return vdir->vd_deblk[vdir->vd_nblk - 1];
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the allocated memory has to be freed by
++ * au_nhash_wh_free() or au_nhash_de_free().
++ */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
++{
++ struct hlist_head *head;
++ unsigned int u;
++
++ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
++ if (head) {
++ nhash->nh_num = num_hash;
++ nhash->nh_head = head;
++ for (u = 0; u < num_hash; u++)
++ INIT_HLIST_HEAD(head++);
++ return 0; /* success */
++ }
++
++ return -ENOMEM;
++}
++
++static void nhash_count(struct hlist_head *head)
++{
++#if 0
++ unsigned long n;
++ struct hlist_node *pos;
++
++ n = 0;
++ hlist_for_each(pos, head)
++ n++;
++ AuInfo("%lu\n", n);
++#endif
++}
++
++static void au_nhash_wh_do_free(struct hlist_head *head)
++{
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos, *node;
++
++ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
++ /* hlist_del(pos); */
++ kfree(tpos);
++ }
++}
++
++static void au_nhash_de_do_free(struct hlist_head *head)
++{
++ struct au_vdir_dehstr *tpos;
++ struct hlist_node *pos, *node;
++
++ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
++ /* hlist_del(pos); */
++ au_cache_free_dehstr(tpos);
++ }
++}
++
++static void au_nhash_do_free(struct au_nhash *nhash,
++ void (*free)(struct hlist_head *head))
++{
++ unsigned int u, n;
++ struct hlist_head *head;
++
++ n = nhash->nh_num;
++ head = nhash->nh_head;
++ for (u = 0; u < n; u++) {
++ nhash_count(head);
++ free(head++);
++ }
++ kfree(nhash->nh_head);
++}
++
++void au_nhash_wh_free(struct au_nhash *whlist)
++{
++ au_nhash_do_free(whlist, au_nhash_wh_do_free);
++}
++
++static void au_nhash_de_free(struct au_nhash *delist)
++{
++ au_nhash_do_free(delist, au_nhash_de_do_free);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++ int limit)
++{
++ int num;
++ unsigned int u, n;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++
++ num = 0;
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (u = 0; u < n; u++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash)
++ if (tpos->wh_bindex == btgt && ++num > limit)
++ return 1;
++ head++;
++ }
++ return 0;
++}
++
++static struct hlist_head *au_name_hash(struct au_nhash *nhash,
++ unsigned char *name,
++ unsigned int len)
++{
++ unsigned int v;
++ /* const unsigned int magic_bit = 12; */
++
++ v = 0;
++ while (len--)
++ v += *name++;
++ /* v = hash_long(v, magic_bit); */
++ v %= nhash->nh_num;
++ return nhash->nh_head + v;
++}
++
++static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
++ int nlen)
++{
++ return str->len == nlen && !memcmp(str->name, name, nlen);
++}
++
++/* returns found or not */
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
++{
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ head = au_name_hash(whlist, name, nlen);
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ str = &tpos->wh_str;
++ AuDbg("%.*s\n", str->len, str->name);
++ if (au_nhash_test_name(str, name, nlen))
++ return 1;
++ }
++ return 0;
++}
++
++/* returns found(true) or not */
++static int test_known(struct au_nhash *delist, char *name, int nlen)
++{
++ struct hlist_head *head;
++ struct au_vdir_dehstr *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ head = au_name_hash(delist, name, nlen);
++ hlist_for_each_entry(tpos, pos, head, hash) {
++ str = tpos->str;
++ AuDbg("%.*s\n", str->len, str->name);
++ if (au_nhash_test_name(str, name, nlen))
++ return 1;
++ }
++ return 0;
++}
++
++static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
++ unsigned char d_type)
++{
++#ifdef CONFIG_AUFS_SHWH
++ wh->wh_ino = ino;
++ wh->wh_type = d_type;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++ unsigned int d_type, aufs_bindex_t bindex,
++ unsigned char shwh)
++{
++ int err;
++ struct au_vdir_destr *str;
++ struct au_vdir_wh *wh;
++
++ AuDbg("%.*s\n", nlen, name);
++ err = -ENOMEM;
++ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
++ if (unlikely(!wh))
++ goto out;
++
++ err = 0;
++ wh->wh_bindex = bindex;
++ if (shwh)
++ au_shwh_init_wh(wh, ino, d_type);
++ str = &wh->wh_str;
++ str->len = nlen;
++ memcpy(str->name, name, nlen);
++ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
++ /* smp_mb(); */
++
++ out:
++ return err;
++}
++
++static int append_deblk(struct au_vdir *vdir)
++{
++ int err;
++ unsigned long ul;
++ const unsigned int deblk_sz = vdir->vd_deblk_sz;
++ union au_vdir_deblk_p p, deblk_end;
++ unsigned char **o;
++
++ err = -ENOMEM;
++ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
++ GFP_NOFS);
++ if (unlikely(!o))
++ goto out;
++
++ vdir->vd_deblk = o;
++ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
++ if (p.deblk) {
++ ul = vdir->vd_nblk++;
++ vdir->vd_deblk[ul] = p.deblk;
++ vdir->vd_last.ul = ul;
++ vdir->vd_last.p.deblk = p.deblk;
++ deblk_end.deblk = p.deblk + deblk_sz;
++ err = set_deblk_end(&p, &deblk_end);
++ }
++
++ out:
++ return err;
++}
++
++static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
++ unsigned int d_type, struct au_nhash *delist)
++{
++ int err;
++ unsigned int sz;
++ const unsigned int deblk_sz = vdir->vd_deblk_sz;
++ union au_vdir_deblk_p p, *room, deblk_end;
++ struct au_vdir_dehstr *dehstr;
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + deblk_sz;
++ room = &vdir->vd_last.p;
++ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
++ || !is_deblk_end(room, &deblk_end));
++
++ sz = calc_size(nlen);
++ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
++ err = append_deblk(vdir);
++ if (unlikely(err))
++ goto out;
++
++ p.deblk = last_deblk(vdir);
++ deblk_end.deblk = p.deblk + deblk_sz;
++ /* smp_mb(); */
++ AuDebugOn(room->deblk != p.deblk);
++ }
++
++ err = -ENOMEM;
++ dehstr = au_cache_alloc_dehstr();
++ if (unlikely(!dehstr))
++ goto out;
++
++ dehstr->str = &room->de->de_str;
++ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
++ room->de->de_ino = ino;
++ room->de->de_type = d_type;
++ room->de->de_str.len = nlen;
++ memcpy(room->de->de_str.name, name, nlen);
++
++ err = 0;
++ room->deblk += sz;
++ if (unlikely(set_deblk_end(room, &deblk_end)))
++ err = append_deblk(vdir);
++ /* smp_mb(); */
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_vdir_free(struct au_vdir *vdir)
++{
++ unsigned char **deblk;
++
++ deblk = vdir->vd_deblk;
++ while (vdir->vd_nblk--)
++ kfree(*deblk++);
++ kfree(vdir->vd_deblk);
++ au_cache_free_vdir(vdir);
++}
++
++static struct au_vdir *alloc_vdir(struct super_block *sb)
++{
++ struct au_vdir *vdir;
++ int err;
++
++ err = -ENOMEM;
++ vdir = au_cache_alloc_vdir();
++ if (unlikely(!vdir))
++ goto out;
++
++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
++ if (unlikely(!vdir->vd_deblk))
++ goto out_free;
++
++ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
++ vdir->vd_nblk = 0;
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ err = append_deblk(vdir);
++ if (!err)
++ return vdir; /* success */
++
++ kfree(vdir->vd_deblk);
++
++ out_free:
++ au_cache_free_vdir(vdir);
++ out:
++ vdir = ERR_PTR(err);
++ return vdir;
++}
++
++static int reinit_vdir(struct au_vdir *vdir)
++{
++ int err;
++ union au_vdir_deblk_p p, deblk_end;
++
++ while (vdir->vd_nblk > 1) {
++ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
++ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
++ vdir->vd_nblk--;
++ }
++ p.deblk = vdir->vd_deblk[0];
++ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
++ err = set_deblk_end(&p, &deblk_end);
++ /* keep vd_dblk_sz */
++ vdir->vd_last.ul = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ vdir->vd_version = 0;
++ vdir->vd_jiffy = 0;
++ /* smp_mb(); */
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ unsigned int d_type, ino_t *ino)
++{
++ int err;
++ struct mutex *mtx;
++ const int isdir = (d_type == DT_DIR);
++
++ /* prevent hardlinks from race condition */
++ mtx = NULL;
++ if (!isdir) {
++ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
++ mutex_lock(mtx);
++ }
++ err = au_xino_read(sb, bindex, h_ino, ino);
++ if (unlikely(err))
++ goto out;
++
++ if (!*ino) {
++ err = -EIO;
++ *ino = au_xino_new_ino(sb);
++ if (unlikely(!*ino))
++ goto out;
++ err = au_xino_write(sb, bindex, h_ino, *ino);
++ if (unlikely(err))
++ goto out;
++ }
++
++ out:
++ if (!isdir)
++ mutex_unlock(mtx);
++ return err;
++}
++
++static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ unsigned int d_type, ino_t *ino)
++{
++#ifdef CONFIG_AUFS_SHWH
++ return au_ino(sb, bindex, h_ino, d_type, ino);
++#else
++ return 0;
++#endif
++}
++
++#define AuFillVdir_CALLED 1
++#define AuFillVdir_WHABLE (1 << 1)
++#define AuFillVdir_SHWH (1 << 2)
++#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
++#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
++#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuFillVdir_SHWH
++#define AuFillVdir_SHWH 0
++#endif
++
++struct fillvdir_arg {
++ struct file *file;
++ struct au_vdir *vdir;
++ struct au_nhash delist;
++ struct au_nhash whlist;
++ aufs_bindex_t bindex;
++ unsigned int flags;
++ int err;
++};
++
++static int fillvdir(void *__arg, const char *__name, int nlen,
++ loff_t offset __maybe_unused, u64 h_ino,
++ unsigned int d_type)
++{
++ struct fillvdir_arg *arg = __arg;
++ char *name = (void *)__name;
++ struct super_block *sb;
++ ino_t ino;
++ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
++
++ arg->err = 0;
++ sb = arg->file->f_dentry->d_sb;
++ au_fset_fillvdir(arg->flags, CALLED);
++ /* smp_mb(); */
++ if (nlen <= AUFS_WH_PFX_LEN
++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++ if (test_known(&arg->delist, name, nlen)
++ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
++ goto out; /* already exists or whiteouted */
++
++ sb = arg->file->f_dentry->d_sb;
++ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
++ if (!arg->err)
++ arg->err = append_de(arg->vdir, name, nlen, ino,
++ d_type, &arg->delist);
++ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
++ name += AUFS_WH_PFX_LEN;
++ nlen -= AUFS_WH_PFX_LEN;
++ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
++ goto out; /* already whiteouted */
++
++ if (shwh)
++ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
++ &ino);
++ if (!arg->err)
++ arg->err = au_nhash_append_wh
++ (&arg->whlist, name, nlen, ino, d_type,
++ arg->bindex, shwh);
++ }
++
++ out:
++ if (!arg->err)
++ arg->vdir->vd_jiffy = jiffies;
++ /* smp_mb(); */
++ AuTraceErr(arg->err);
++ return arg->err;
++}
++
++static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
++ struct au_nhash *whlist, struct au_nhash *delist)
++{
++#ifdef CONFIG_AUFS_SHWH
++ int err;
++ unsigned int nh, u;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos, *n;
++ char *p, *o;
++ struct au_vdir_destr *destr;
++
++ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
++
++ err = -ENOMEM;
++ o = p = __getname();
++ if (unlikely(!p))
++ goto out;
++
++ err = 0;
++ nh = whlist->nh_num;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++ for (u = 0; u < nh; u++) {
++ head = whlist->nh_head + u;
++ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
++ destr = &tpos->wh_str;
++ memcpy(p, destr->name, destr->len);
++ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
++ tpos->wh_ino, tpos->wh_type, delist);
++ if (unlikely(err))
++ break;
++ }
++ }
++
++ __putname(o);
++
++ out:
++ AuTraceErr(err);
++ return err;
++#else
++ return 0;
++#endif
++}
++
++static int au_do_read_vdir(struct fillvdir_arg *arg)
++{
++ int err;
++ unsigned int rdhash;
++ loff_t offset;
++ aufs_bindex_t bend, bindex, bstart;
++ unsigned char shwh;
++ struct file *hf, *file;
++ struct super_block *sb;
++
++ file = arg->file;
++ sb = file->f_dentry->d_sb;
++ rdhash = au_sbi(sb)->si_rdhash;
++ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out;
++ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
++ if (unlikely(err))
++ goto out_delist;
++
++ err = 0;
++ arg->flags = 0;
++ shwh = 0;
++ if (au_opt_test(au_mntflags(sb), SHWH)) {
++ shwh = 1;
++ au_fset_fillvdir(arg->flags, SHWH);
++ }
++ bstart = au_fbstart(file);
++ bend = au_fbend(file);
++ for (bindex = bstart; !err && bindex <= bend; bindex++) {
++ hf = au_h_fptr(file, bindex);
++ if (!hf)
++ continue;
++
++ offset = vfsub_llseek(hf, 0, SEEK_SET);
++ err = offset;
++ if (unlikely(offset))
++ break;
++
++ arg->bindex = bindex;
++ au_fclr_fillvdir(arg->flags, WHABLE);
++ if (shwh
++ || (bindex != bend
++ && au_br_whable(au_sbr_perm(sb, bindex))))
++ au_fset_fillvdir(arg->flags, WHABLE);
++ do {
++ arg->err = 0;
++ au_fclr_fillvdir(arg->flags, CALLED);
++ /* smp_mb(); */
++ err = vfsub_readdir(hf, fillvdir, arg);
++ if (err >= 0)
++ err = arg->err;
++ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
++ }
++
++ if (!err && shwh)
++ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
++
++ au_nhash_wh_free(&arg->whlist);
++
++ out_delist:
++ au_nhash_de_free(&arg->delist);
++ out:
++ return err;
++}
++
++static int read_vdir(struct file *file, int may_read)
++{
++ int err;
++ unsigned long expire;
++ unsigned char do_read;
++ struct fillvdir_arg arg;
++ struct inode *inode;
++ struct au_vdir *vdir, *allocated;
++
++ err = 0;
++ inode = file->f_dentry->d_inode;
++ IMustLock(inode);
++ allocated = NULL;
++ do_read = 0;
++ expire = au_sbi(inode->i_sb)->si_rdcache;
++ vdir = au_ivdir(inode);
++ if (!vdir) {
++ do_read = 1;
++ vdir = alloc_vdir(inode->i_sb);
++ err = PTR_ERR(vdir);
++ if (IS_ERR(vdir))
++ goto out;
++ err = 0;
++ allocated = vdir;
++ } else if (may_read
++ && (inode->i_version != vdir->vd_version
++ || time_after(jiffies, vdir->vd_jiffy + expire))) {
++ do_read = 1;
++ err = reinit_vdir(vdir);
++ if (unlikely(err))
++ goto out;
++ }
++
++ if (!do_read)
++ return 0; /* success */
++
++ arg.file = file;
++ arg.vdir = vdir;
++ err = au_do_read_vdir(&arg);
++ if (!err) {
++ /* file->f_pos = 0; */
++ vdir->vd_version = inode->i_version;
++ vdir->vd_last.ul = 0;
++ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++ if (allocated)
++ au_set_ivdir(inode, allocated);
++ } else if (allocated)
++ au_vdir_free(allocated);
++
++ out:
++ return err;
++}
++
++static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
++{
++ int err, rerr;
++ unsigned long ul, n;
++ const unsigned int deblk_sz = src->vd_deblk_sz;
++
++ AuDebugOn(tgt->vd_nblk != 1);
++
++ err = -ENOMEM;
++ if (tgt->vd_nblk < src->vd_nblk) {
++ unsigned char **p;
++
++ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
++ GFP_NOFS);
++ if (unlikely(!p))
++ goto out;
++ tgt->vd_deblk = p;
++ }
++
++ tgt->vd_nblk = src->vd_nblk;
++ tgt->vd_deblk_sz = deblk_sz;
++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
++ /* tgt->vd_last.i = 0; */
++ /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */
++ tgt->vd_version = src->vd_version;
++ tgt->vd_jiffy = src->vd_jiffy;
++
++ n = src->vd_nblk;
++ for (ul = 1; ul < n; ul++) {
++ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
++ GFP_NOFS);
++ if (unlikely(!tgt->vd_deblk[ul]))
++ goto out;
++ }
++ /* smp_mb(); */
++ return 0; /* success */
++
++ out:
++ rerr = reinit_vdir(tgt);
++ BUG_ON(rerr);
++ return err;
++}
++
++int au_vdir_init(struct file *file)
++{
++ int err;
++ struct inode *inode;
++ struct au_vdir *vdir_cache, *allocated;
++
++ err = read_vdir(file, !file->f_pos);
++ if (unlikely(err))
++ goto out;
++
++ allocated = NULL;
++ vdir_cache = au_fvdir_cache(file);
++ if (!vdir_cache) {
++ vdir_cache = alloc_vdir(file->f_dentry->d_sb);
++ err = PTR_ERR(vdir_cache);
++ if (IS_ERR(vdir_cache))
++ goto out;
++ allocated = vdir_cache;
++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
++ err = reinit_vdir(vdir_cache);
++ if (unlikely(err))
++ goto out;
++ } else
++ return 0; /* success */
++
++ inode = file->f_dentry->d_inode;
++ err = copy_vdir(vdir_cache, au_ivdir(inode));
++ if (!err) {
++ file->f_version = inode->i_version;
++ if (allocated)
++ au_set_fvdir_cache(file, allocated);
++ } else if (allocated)
++ au_vdir_free(allocated);
++
++ out:
++ return err;
++}
++
++static loff_t calc_offset(struct au_vdir *vdir)
++{
++ loff_t offset;
++ union au_vdir_deblk_p p;
++
++ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
++ offset = vdir->vd_last.p.deblk - p.deblk;
++ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
++ return offset;
++}
++
++/* returns true or false */
++static int seek_vdir(struct file *file)
++{
++ int valid;
++ unsigned int deblk_sz;
++ unsigned long ul, n;
++ loff_t offset;
++ union au_vdir_deblk_p p, deblk_end;
++ struct au_vdir *vdir_cache;
++
++ valid = 1;
++ vdir_cache = au_fvdir_cache(file);
++ offset = calc_offset(vdir_cache);
++ AuDbg("offset %lld\n", offset);
++ if (file->f_pos == offset)
++ goto out;
++
++ vdir_cache->vd_last.ul = 0;
++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
++ if (!file->f_pos)
++ goto out;
++
++ valid = 0;
++ deblk_sz = vdir_cache->vd_deblk_sz;
++ ul = div64_u64(file->f_pos, deblk_sz);
++ AuDbg("ul %lu\n", ul);
++ if (ul >= vdir_cache->vd_nblk)
++ goto out;
++
++ n = vdir_cache->vd_nblk;
++ for (; ul < n; ul++) {
++ p.deblk = vdir_cache->vd_deblk[ul];
++ deblk_end.deblk = p.deblk + deblk_sz;
++ offset = ul;
++ offset *= deblk_sz;
++ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
++ unsigned int l;
++
++ l = calc_size(p.de->de_str.len);
++ offset += l;
++ p.deblk += l;
++ }
++ if (!is_deblk_end(&p, &deblk_end)) {
++ valid = 1;
++ vdir_cache->vd_last.ul = ul;
++ vdir_cache->vd_last.p = p;
++ break;
++ }
++ }
++
++ out:
++ /* smp_mb(); */
++ AuTraceErr(!valid);
++ return valid;
++}
++
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err;
++ unsigned int l, deblk_sz;
++ union au_vdir_deblk_p deblk_end;
++ struct au_vdir *vdir_cache;
++ struct au_vdir_de *de;
++
++ vdir_cache = au_fvdir_cache(file);
++ if (!seek_vdir(file))
++ return 0;
++
++ deblk_sz = vdir_cache->vd_deblk_sz;
++ while (1) {
++ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++ deblk_end.deblk += deblk_sz;
++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
++ de = vdir_cache->vd_last.p.de;
++ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
++ de->de_str.len, de->de_str.name, file->f_pos,
++ (unsigned long)de->de_ino, de->de_type);
++ err = filldir(dirent, de->de_str.name, de->de_str.len,
++ file->f_pos, de->de_ino, de->de_type);
++ if (unlikely(err)) {
++ AuTraceErr(err);
++ /* todo: ignore the error caused by udba? */
++ /* return err; */
++ return 0;
++ }
++
++ l = calc_size(de->de_str.len);
++ vdir_cache->vd_last.p.deblk += l;
++ file->f_pos += l;
++ }
++ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
++ vdir_cache->vd_last.ul++;
++ vdir_cache->vd_last.p.deblk
++ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
++ continue;
++ }
++ break;
++ }
++
++ /* smp_mb(); */
++ return 0;
++}
+diff -Naur a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
+--- a/fs/aufs/vfsub.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/splice.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++int vfsub_update_h_iattr(struct path *h_path, int *did)
++{
++ int err;
++ struct kstat st;
++ struct super_block *h_sb;
++
++ /* for remote fs, leave work for its getattr or d_revalidate */
++ /* for bad i_attr fs, handle them in aufs_getattr() */
++ /* still some fs may acquire i_mutex. we need to skip them */
++ err = 0;
++ if (!did)
++ did = &err;
++ h_sb = h_path->dentry->d_sb;
++ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
++ if (*did)
++ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct file *vfsub_filp_open(const char *path, int oflags, int mode)
++{
++ struct file *file;
++
++ lockdep_off();
++ file = filp_open(path, oflags, mode);
++ lockdep_on();
++ if (IS_ERR(file))
++ goto out;
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++
++ out:
++ return file;
++}
++
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
++{
++ int err;
++
++ /* lockdep_off(); */
++ err = kern_path(name, flags, path);
++ /* lockdep_on(); */
++ if (!err && path->dentry->d_inode)
++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++ int len)
++{
++ struct path path = {
++ .mnt = NULL
++ };
++
++ IMustLock(parent->d_inode);
++
++ path.dentry = lookup_one_len(name, parent, len);
++ if (IS_ERR(path.dentry))
++ goto out;
++ if (path.dentry->d_inode)
++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++ out:
++ return path.dentry;
++}
++
++struct dentry *vfsub_lookup_hash(struct nameidata *nd)
++{
++ struct path path = {
++ .mnt = nd->path.mnt
++ };
++
++ IMustLock(nd->path.dentry->d_inode);
++
++ path.dentry = lookup_hash(nd);
++ if (!IS_ERR(path.dentry) && path.dentry->d_inode)
++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++ return path.dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2)
++{
++ struct dentry *d;
++
++ lockdep_off();
++ d = lock_rename(d1, d2);
++ lockdep_on();
++ au_hin_suspend(hdir1);
++ if (hdir1 != hdir2)
++ au_hin_suspend(hdir2);
++
++ return d;
++}
++
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2)
++{
++ au_hin_resume(hdir1);
++ if (hdir1 != hdir2)
++ au_hin_resume(hdir2);
++ lockdep_off();
++ unlock_rename(d1, d2);
++ lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_create(struct inode *dir, struct path *path, int mode)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mknod(path, path->dentry, mode, 0);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ if (au_test_fs_null_nd(dir->i_sb))
++ err = vfs_create(dir, path->dentry, mode, NULL);
++ else {
++ struct nameidata h_nd;
++
++ memset(&h_nd, 0, sizeof(h_nd));
++ h_nd.flags = LOOKUP_CREATE;
++ h_nd.intent.open.flags = O_CREAT
++ | vfsub_fmode_to_uint(FMODE_READ);
++ h_nd.intent.open.create_mode = mode;
++ h_nd.path.dentry = path->dentry->d_parent;
++ h_nd.path.mnt = path->mnt;
++ path_get(&h_nd.path);
++ err = vfs_create(dir, path->dentry, mode, &h_nd);
++ path_put(&h_nd.path);
++ }
++
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_symlink(path, path->dentry, symname);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_symlink(dir, path->dentry, symname);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mknod(path, path->dentry, mode, dev);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_mknod(dir, path->dentry, mode, dev);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++static int au_test_nlink(struct inode *inode)
++{
++ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
++
++ if (!au_test_fs_no_limit_nlink(inode->i_sb)
++ || inode->i_nlink < link_max)
++ return 0;
++ return -EMLINK;
++}
++
++int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ err = au_test_nlink(src_dentry->d_inode);
++ if (unlikely(err))
++ return err;
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_link(src_dentry, path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_link(src_dentry, dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ /* fuse has different memory inode for the same inumber */
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ tmp.dentry = src_dentry;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++ struct inode *dir, struct path *path)
++{
++ int err;
++ struct path tmp = {
++ .mnt = path->mnt
++ };
++ struct dentry *d;
++
++ IMustLock(dir);
++ IMustLock(src_dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ tmp.dentry = src_dentry->d_parent;
++ err = security_path_rename(&tmp, src_dentry, path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ int did;
++
++ tmp.dentry = d->d_parent;
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = src_dentry;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ tmp.dentry = src_dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_mkdir(path, path->dentry, mode);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ err = vfs_mkdir(dir, path->dentry, mode);
++ if (!err) {
++ struct path tmp = *path;
++ int did;
++
++ vfsub_update_h_iattr(&tmp, &did);
++ if (did) {
++ tmp.dentry = path->dentry->d_parent;
++ vfsub_update_h_iattr(&tmp, /*did*/NULL);
++ }
++ /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++int vfsub_rmdir(struct inode *dir, struct path *path)
++{
++ int err;
++ struct dentry *d;
++
++ IMustLock(dir);
++
++ d = path->dentry;
++ path->dentry = d->d_parent;
++ err = security_path_rmdir(path, path->dentry);
++ path->dentry = d;
++ if (unlikely(err))
++ goto out;
++
++ lockdep_off();
++ err = vfs_rmdir(dir, path->dentry);
++ lockdep_on();
++ if (!err) {
++ struct path tmp = {
++ .dentry = path->dentry->d_parent,
++ .mnt = path->mnt
++ };
++
++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++ }
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ err = vfs_read(file, ubuf, count, ppos);
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++/* todo: kernel_read()? */
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos)
++{
++ ssize_t err;
++
++ lockdep_off();
++ err = vfs_write(file, ubuf, count, ppos);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
++ set_fs(oldfs);
++ return err;
++}
++
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_readdir(file, filldir, arg);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ long err;
++
++ lockdep_off();
++ err = do_splice_to(in, ppos, pipe, len, flags);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
++{
++ long err;
++
++ lockdep_off();
++ err = do_splice_from(pipe, out, ppos, len, flags);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
++ return err;
++}
++
++/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++ struct file *h_file)
++{
++ int err;
++ struct inode *h_inode;
++
++ h_inode = h_path->dentry->d_inode;
++ if (!h_file) {
++ err = mnt_want_write(h_path->mnt);
++ if (err)
++ goto out;
++ err = inode_permission(h_inode, MAY_WRITE);
++ if (err)
++ goto out_mnt;
++ err = get_write_access(h_inode);
++ if (err)
++ goto out_mnt;
++ err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
++ if (err)
++ goto out_inode;
++ }
++
++ err = locks_verify_truncate(h_inode, h_file, length);
++ if (!err)
++ err = security_path_truncate(h_path, length, attr);
++ if (!err) {
++ lockdep_off();
++ err = do_truncate(h_path->dentry, length, attr, h_file);
++ lockdep_on();
++ }
++
++ out_inode:
++ if (!h_file)
++ put_write_access(h_inode);
++ out_mnt:
++ if (!h_file)
++ mnt_drop_write(h_path->mnt);
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_vfsub_mkdir_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++ int mode;
++};
++
++static void au_call_vfsub_mkdir(void *args)
++{
++ struct au_vfsub_mkdir_args *a = args;
++ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
++}
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
++{
++ int err, do_sio, wkq_err;
++
++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio)
++ err = vfsub_mkdir(dir, path, mode);
++ else {
++ struct au_vfsub_mkdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path,
++ .mode = mode
++ };
++ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++struct au_vfsub_rmdir_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++};
++
++static void au_call_vfsub_rmdir(void *args)
++{
++ struct au_vfsub_rmdir_args *a = args;
++ *a->errp = vfsub_rmdir(a->dir, a->path);
++}
++
++int vfsub_sio_rmdir(struct inode *dir, struct path *path)
++{
++ int err, do_sio, wkq_err;
++
++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ if (!do_sio)
++ err = vfsub_rmdir(dir, path);
++ else {
++ struct au_vfsub_rmdir_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path
++ };
++ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct notify_change_args {
++ int *errp;
++ struct path *path;
++ struct iattr *ia;
++};
++
++static void call_notify_change(void *args)
++{
++ struct notify_change_args *a = args;
++ struct inode *h_inode;
++
++ h_inode = a->path->dentry->d_inode;
++ IMustLock(h_inode);
++
++ *a->errp = -EPERM;
++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ lockdep_off();
++ *a->errp = notify_change(a->path->dentry, a->ia);
++ lockdep_on();
++ if (!*a->errp)
++ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
++ }
++ AuTraceErr(*a->errp);
++}
++
++int vfsub_notify_change(struct path *path, struct iattr *ia)
++{
++ int err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .path = path,
++ .ia = ia
++ };
++
++ call_notify_change(&args);
++
++ return err;
++}
++
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
++{
++ int err, wkq_err;
++ struct notify_change_args args = {
++ .errp = &err,
++ .path = path,
++ .ia = ia
++ };
++
++ wkq_err = au_wkq_wait(call_notify_change, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct unlink_args {
++ int *errp;
++ struct inode *dir;
++ struct path *path;
++};
++
++static void call_unlink(void *args)
++{
++ struct unlink_args *a = args;
++ struct dentry *d = a->path->dentry;
++ struct inode *h_inode;
++ const int stop_sillyrename = (au_test_nfs(d->d_sb)
++ && atomic_read(&d->d_count) == 1);
++
++ IMustLock(a->dir);
++
++ a->path->dentry = d->d_parent;
++ *a->errp = security_path_unlink(a->path, d);
++ a->path->dentry = d;
++ if (unlikely(*a->errp))
++ return;
++
++ if (!stop_sillyrename)
++ dget(d);
++ h_inode = d->d_inode;
++ if (h_inode)
++ atomic_inc(&h_inode->i_count);
++
++ lockdep_off();
++ *a->errp = vfs_unlink(a->dir, d);
++ lockdep_on();
++ if (!*a->errp) {
++ struct path tmp = {
++ .dentry = d->d_parent,
++ .mnt = a->path->mnt
++ };
++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++ }
++
++ if (!stop_sillyrename)
++ dput(d);
++ if (h_inode)
++ iput(h_inode);
++
++ AuTraceErr(*a->errp);
++}
++
++/*
++ * @dir: must be locked.
++ * @dentry: target dentry.
++ */
++int vfsub_unlink(struct inode *dir, struct path *path, int force)
++{
++ int err;
++ struct unlink_args args = {
++ .errp = &err,
++ .dir = dir,
++ .path = path
++ };
++
++ if (!force)
++ call_unlink(&args);
++ else {
++ int wkq_err;
++
++ wkq_err = au_wkq_wait(call_unlink, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++
++ return err;
++}
+diff -Naur a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+--- a/fs/aufs/vfsub.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,171 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#ifndef __AUFS_VFSUB_H__
++#define __AUFS_VFSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/fs_stack.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for lower inode */
++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
++/* reduce? gave up. */
++enum {
++ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
++ AuLsc_I_PARENT, /* lower inode, parent first */
++ AuLsc_I_PARENT2, /* copyup dirs */
++ AuLsc_I_CHILD,
++ AuLsc_I_CHILD2,
++ AuLsc_I_End
++};
++
++/* to debug easier, do not make them inlined functions */
++#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
++#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
++
++/* ---------------------------------------------------------------------- */
++
++static inline void vfsub_copy_inode_size(struct inode *inode,
++ struct inode *h_inode)
++{
++ spin_lock(&inode->i_lock);
++ fsstack_copy_inode_size(inode, h_inode);
++ spin_unlock(&inode->i_lock);
++}
++
++int vfsub_update_h_iattr(struct path *h_path, int *did);
++struct file *vfsub_filp_open(const char *path, int oflags, int mode);
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++ int len);
++struct dentry *vfsub_lookup_hash(struct nameidata *nd);
++
++/* ---------------------------------------------------------------------- */
++
++struct au_hinode;
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2);
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++ struct dentry *d2, struct au_hinode *hdir2);
++
++int vfsub_create(struct inode *dir, struct path *path, int mode);
++int vfsub_symlink(struct inode *dir, struct path *path,
++ const char *symname);
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++ struct path *path);
++int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
++ struct inode *hdir, struct path *path);
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_rmdir(struct inode *dir, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++ loff_t *ppos);
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
++ loff_t *ppos);
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
++
++static inline void vfsub_file_accessed(struct file *h_file)
++{
++ file_accessed(h_file);
++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
++}
++
++static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
++ struct dentry *h_dentry)
++{
++ struct path h_path = {
++ .dentry = h_dentry,
++ .mnt = h_mnt
++ };
++ touch_atime(h_mnt, h_dentry);
++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++ struct file *h_file);
++
++/* ---------------------------------------------------------------------- */
++
++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
++{
++ loff_t err;
++
++ lockdep_off();
++ err = vfs_llseek(file, offset, origin);
++ lockdep_on();
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dirty workaround for strict type of fmode_t */
++union vfsub_fmu {
++ fmode_t fm;
++ unsigned int ui;
++};
++
++static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
++{
++ union vfsub_fmu u = {
++ .fm = fm
++ };
++
++ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
++
++ return u.ui;
++}
++
++static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
++{
++ union vfsub_fmu u = {
++ .ui = ui
++ };
++
++ return u.fm;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_sio_rmdir(struct inode *dir, struct path *path);
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
++int vfsub_notify_change(struct path *path, struct iattr *ia);
++int vfsub_unlink(struct inode *dir, struct path *path, int force);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_VFSUB_H__ */
+diff -Naur a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c
+--- a/fs/aufs/wbr_policy.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wbr_policy.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,637 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * policies for selecting one among multiple writable branches
++ */
++
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/* subset of cpup_attr() */
++static noinline_for_stack
++int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
++{
++ int err, sbits;
++ struct iattr ia;
++ struct inode *h_isrc;
++
++ h_isrc = h_src->d_inode;
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
++ ia.ia_mode = h_isrc->i_mode;
++ ia.ia_uid = h_isrc->i_uid;
++ ia.ia_gid = h_isrc->i_gid;
++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
++ err = vfsub_sio_notify_change(h_path, &ia);
++
++ /* is this nfs only? */
++ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
++ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++ ia.ia_mode = h_isrc->i_mode;
++ err = vfsub_sio_notify_change(h_path, &ia);
++ }
++
++ return err;
++}
++
++#define AuCpdown_PARENT_OPQ 1
++#define AuCpdown_WHED (1 << 1)
++#define AuCpdown_MADE_DIR (1 << 2)
++#define AuCpdown_DIROPQ (1 << 3)
++#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
++#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
++#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
++
++struct au_cpdown_dir_args {
++ struct dentry *parent;
++ unsigned int flags;
++};
++
++static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
++ struct au_cpdown_dir_args *a)
++{
++ int err;
++ struct dentry *opq_dentry;
++
++ opq_dentry = au_diropq_create(dentry, bdst);
++ err = PTR_ERR(opq_dentry);
++ if (IS_ERR(opq_dentry))
++ goto out;
++ dput(opq_dentry);
++ au_fset_cpdown(a->flags, DIROPQ);
++
++ out:
++ return err;
++}
++
++static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
++ struct inode *dir, aufs_bindex_t bdst)
++{
++ int err;
++ struct path h_path;
++ struct au_branch *br;
++
++ br = au_sbr(dentry->d_sb, bdst);
++ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ err = 0;
++ if (h_path.dentry->d_inode) {
++ h_path.mnt = br->br_mnt;
++ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
++ dentry);
++ }
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
++ struct dentry *h_parent, void *arg)
++{
++ int err, rerr;
++ aufs_bindex_t bend, bopq, bstart;
++ unsigned char parent_opq;
++ struct path h_path;
++ struct dentry *parent;
++ struct inode *h_dir, *h_inode, *inode, *dir;
++ struct au_cpdown_dir_args *args = arg;
++
++ bstart = au_dbstart(dentry);
++ /* dentry is di-locked */
++ parent = dget_parent(dentry);
++ dir = parent->d_inode;
++ h_dir = h_parent->d_inode;
++ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
++ IMustLock(h_dir);
++
++ err = au_lkup_neg(dentry, bdst);
++ if (unlikely(err < 0))
++ goto out;
++ h_path.dentry = au_h_dptr(dentry, bdst);
++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
++ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
++ S_IRWXU | S_IRUGO | S_IXUGO);
++ if (unlikely(err))
++ goto out_put;
++ au_fset_cpdown(args->flags, MADE_DIR);
++
++ bend = au_dbend(dentry);
++ bopq = au_dbdiropq(dentry);
++ au_fclr_cpdown(args->flags, WHED);
++ au_fclr_cpdown(args->flags, DIROPQ);
++ if (au_dbwh(dentry) == bdst)
++ au_fset_cpdown(args->flags, WHED);
++ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
++ au_fset_cpdown(args->flags, PARENT_OPQ);
++ parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
++ && args->parent == dentry);
++ h_inode = h_path.dentry->d_inode;
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ if (au_ftest_cpdown(args->flags, WHED)) {
++ err = au_cpdown_dir_opq(dentry, bdst, args);
++ if (unlikely(err)) {
++ mutex_unlock(&h_inode->i_mutex);
++ goto out_dir;
++ }
++ }
++
++ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
++ mutex_unlock(&h_inode->i_mutex);
++ if (unlikely(err))
++ goto out_opq;
++
++ if (au_ftest_cpdown(args->flags, WHED)) {
++ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
++ if (unlikely(err))
++ goto out_opq;
++ }
++
++ inode = dentry->d_inode;
++ if (au_ibend(inode) < bdst)
++ au_set_ibend(inode, bdst);
++ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
++ au_hi_flags(inode, /*isdir*/1));
++ goto out; /* success */
++
++ /* revert */
++ out_opq:
++ if (au_ftest_cpdown(args->flags, DIROPQ)) {
++ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++ rerr = au_diropq_remove(dentry, bdst);
++ mutex_unlock(&h_inode->i_mutex);
++ if (unlikely(rerr)) {
++ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
++ AuDLNPair(dentry), bdst, rerr);
++ err = -EIO;
++ goto out;
++ }
++ }
++ out_dir:
++ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
++ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
++ if (unlikely(rerr)) {
++ AuIOErr("failed removing %.*s b%d (%d)\n",
++ AuDLNPair(dentry), bdst, rerr);
++ err = -EIO;
++ }
++ }
++ out_put:
++ au_set_h_dptr(dentry, bdst, NULL);
++ if (au_dbend(dentry) == bdst)
++ au_update_dbend(dentry);
++ out:
++ dput(parent);
++ return err;
++}
++
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++ int err;
++ struct au_cpdown_dir_args args = {
++ .parent = dget_parent(dentry),
++ .flags = 0
++ };
++
++ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
++ dput(args.parent);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for create */
++
++static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
++{
++ for (; bindex >= 0; bindex--)
++ if (!au_br_rdonly(au_sbr(sb, bindex)))
++ return bindex;
++ return -EROFS;
++}
++
++/* top down parent */
++static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
++{
++ int err;
++ aufs_bindex_t bstart, bindex;
++ struct super_block *sb;
++ struct dentry *parent, *h_parent;
++
++ sb = dentry->d_sb;
++ bstart = au_dbstart(dentry);
++ err = bstart;
++ if (!au_br_rdonly(au_sbr(sb, bstart)))
++ goto out;
++
++ err = -EROFS;
++ parent = dget_parent(dentry);
++ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = bindex;
++ break;
++ }
++ }
++ dput(parent);
++
++ /* bottom up here */
++ if (unlikely(err < 0))
++ err = au_wbr_bu(sb, bstart - 1);
++
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* an exception for the policy other than tdp */
++static int au_wbr_create_exp(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bwh, bdiropq;
++ struct dentry *parent;
++
++ err = -1;
++ bwh = au_dbwh(dentry);
++ parent = dget_parent(dentry);
++ bdiropq = au_dbdiropq(parent);
++ if (bwh >= 0) {
++ if (bdiropq >= 0)
++ err = min(bdiropq, bwh);
++ else
++ err = bwh;
++ AuDbg("%d\n", err);
++ } else if (bdiropq >= 0) {
++ err = bdiropq;
++ AuDbg("%d\n", err);
++ }
++ dput(parent);
++
++ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
++ err = -1;
++
++ AuDbg("%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* round robin */
++static int au_wbr_create_init_rr(struct super_block *sb)
++{
++ int err;
++
++ err = au_wbr_bu(sb, au_sbend(sb));
++ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_rr(struct dentry *dentry, int isdir)
++{
++ int err, nbr;
++ unsigned int u;
++ aufs_bindex_t bindex, bend;
++ struct super_block *sb;
++ atomic_t *next;
++
++ err = au_wbr_create_exp(dentry);
++ if (err >= 0)
++ goto out;
++
++ sb = dentry->d_sb;
++ next = &au_sbi(sb)->si_wbr_rr_next;
++ bend = au_sbend(sb);
++ nbr = bend + 1;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ if (!isdir) {
++ err = atomic_dec_return(next) + 1;
++ /* modulo for 0 is meaningless */
++ if (unlikely(!err))
++ err = atomic_dec_return(next) + 1;
++ } else
++ err = atomic_read(next);
++ AuDbg("%d\n", err);
++ u = err;
++ err = u % nbr;
++ AuDbg("%d\n", err);
++ if (!au_br_rdonly(au_sbr(sb, err)))
++ break;
++ err = -EROFS;
++ }
++
++ out:
++ AuDbg("%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space */
++static void au_mfs(struct dentry *dentry)
++{
++ struct super_block *sb;
++ struct au_branch *br;
++ struct au_wbr_mfs *mfs;
++ aufs_bindex_t bindex, bend;
++ int err;
++ unsigned long long b, bavail;
++ /* reduce the stack usage */
++ struct kstatfs *st;
++
++ st = kmalloc(sizeof(*st), GFP_NOFS);
++ if (unlikely(!st)) {
++ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
++ return;
++ }
++
++ bavail = 0;
++ sb = dentry->d_sb;
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mfs->mfs_bindex = -EROFS;
++ mfs->mfsrr_bytes = 0;
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (au_br_rdonly(br))
++ continue;
++
++ /* sb->s_root for NFS is unreliable */
++ err = vfs_statfs(br->br_mnt->mnt_root, st);
++ if (unlikely(err)) {
++ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
++ continue;
++ }
++
++ /* when the available size is equal, select the lower one */
++ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
++ || sizeof(b) < sizeof(st->f_bsize));
++ b = st->f_bavail * st->f_bsize;
++ br->br_wbr->wbr_bytes = b;
++ if (b >= bavail) {
++ bavail = b;
++ mfs->mfs_bindex = bindex;
++ mfs->mfs_jiffy = jiffies;
++ }
++ }
++
++ mfs->mfsrr_bytes = bavail;
++ AuDbg("b%d\n", mfs->mfs_bindex);
++ kfree(st);
++}
++
++static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
++{
++ int err;
++ struct super_block *sb;
++ struct au_wbr_mfs *mfs;
++
++ err = au_wbr_create_exp(dentry);
++ if (err >= 0)
++ goto out;
++
++ sb = dentry->d_sb;
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mutex_lock(&mfs->mfs_lock);
++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
++ || mfs->mfs_bindex < 0
++ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
++ au_mfs(dentry);
++ mutex_unlock(&mfs->mfs_lock);
++ err = mfs->mfs_bindex;
++
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_init_mfs(struct super_block *sb)
++{
++ struct au_wbr_mfs *mfs;
++
++ mfs = &au_sbi(sb)->si_wbr_mfs;
++ mutex_init(&mfs->mfs_lock);
++ mfs->mfs_jiffy = 0;
++ mfs->mfs_bindex = -EROFS;
++
++ return 0;
++}
++
++static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
++{
++ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space and then round robin */
++static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
++{
++ int err;
++ struct au_wbr_mfs *mfs;
++
++ err = au_wbr_create_mfs(dentry, isdir);
++ if (err >= 0) {
++ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
++ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
++ err = au_wbr_create_rr(dentry, isdir);
++ }
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++static int au_wbr_create_init_mfsrr(struct super_block *sb)
++{
++ int err;
++
++ au_wbr_create_init_mfs(sb); /* ignore */
++ err = au_wbr_create_init_rr(sb);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* top down parent and most free space */
++static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
++{
++ int err, e2;
++ unsigned long long b;
++ aufs_bindex_t bindex, bstart, bend;
++ struct super_block *sb;
++ struct dentry *parent, *h_parent;
++ struct au_branch *br;
++
++ err = au_wbr_create_tdp(dentry, isdir);
++ if (unlikely(err < 0))
++ goto out;
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(parent);
++ bend = au_dbtaildir(parent);
++ if (bstart == bend)
++ goto out_parent; /* success */
++
++ e2 = au_wbr_create_mfs(dentry, isdir);
++ if (e2 < 0)
++ goto out_parent; /* success */
++
++ /* when the available size is equal, select upper one */
++ sb = dentry->d_sb;
++ br = au_sbr(sb, err);
++ b = br->br_wbr->wbr_bytes;
++ AuDbg("b%d, %llu\n", err, b);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ br = au_sbr(sb, bindex);
++ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
++ b = br->br_wbr->wbr_bytes;
++ err = bindex;
++ AuDbg("b%d, %llu\n", err, b);
++ }
++ }
++
++ out_parent:
++ dput(parent);
++ out:
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for copyup */
++
++/* top down parent */
++static int au_wbr_copyup_tdp(struct dentry *dentry)
++{
++ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
++}
++
++/* bottom up parent */
++static int au_wbr_copyup_bup(struct dentry *dentry)
++{
++ int err;
++ aufs_bindex_t bindex, bstart;
++ struct dentry *parent, *h_parent;
++ struct super_block *sb;
++
++ err = -EROFS;
++ sb = dentry->d_sb;
++ parent = dget_parent(dentry);
++ bstart = au_dbstart(parent);
++ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
++ h_parent = au_h_dptr(parent, bindex);
++ if (!h_parent || !h_parent->d_inode)
++ continue;
++
++ if (!au_br_rdonly(au_sbr(sb, bindex))) {
++ err = bindex;
++ break;
++ }
++ }
++ dput(parent);
++
++ /* bottom up here */
++ if (unlikely(err < 0))
++ err = au_wbr_bu(sb, bstart - 1);
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* bottom up */
++static int au_wbr_copyup_bu(struct dentry *dentry)
++{
++ int err;
++
++ err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
++
++ AuDbg("b%d\n", err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
++ [AuWbrCopyup_TDP] = {
++ .copyup = au_wbr_copyup_tdp
++ },
++ [AuWbrCopyup_BUP] = {
++ .copyup = au_wbr_copyup_bup
++ },
++ [AuWbrCopyup_BU] = {
++ .copyup = au_wbr_copyup_bu
++ }
++};
++
++struct au_wbr_create_operations au_wbr_create_ops[] = {
++ [AuWbrCreate_TDP] = {
++ .create = au_wbr_create_tdp
++ },
++ [AuWbrCreate_RR] = {
++ .create = au_wbr_create_rr,
++ .init = au_wbr_create_init_rr
++ },
++ [AuWbrCreate_MFS] = {
++ .create = au_wbr_create_mfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSV] = {
++ .create = au_wbr_create_mfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSRR] = {
++ .create = au_wbr_create_mfsrr,
++ .init = au_wbr_create_init_mfsrr,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_MFSRRV] = {
++ .create = au_wbr_create_mfsrr,
++ .init = au_wbr_create_init_mfsrr,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_PMFS] = {
++ .create = au_wbr_create_pmfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ },
++ [AuWbrCreate_PMFSV] = {
++ .create = au_wbr_create_pmfs,
++ .init = au_wbr_create_init_mfs,
++ .fin = au_wbr_create_fin_mfs
++ }
++};
+diff -Naur a/fs/aufs/whout.c b/fs/aufs/whout.c
+--- a/fs/aufs/whout.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1042 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#include <linux/fs.h>
++#include "aufs.h"
++
++#define WH_MASK S_IRUGO
++
++/*
++ * If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++static struct qstr diropq_name = {
++ .name = AUFS_WH_DIROPQ,
++ .len = sizeof(AUFS_WH_DIROPQ) - 1
++};
++
++/*
++ * generate whiteout name, which is NOT terminated by NULL.
++ * @name: original d_name.name
++ * @len: original d_name.len
++ * @wh: whiteout qstr
++ * returns zero when succeeds, otherwise error.
++ * succeeded value as wh->name should be freed by kfree().
++ */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
++{
++ char *p;
++
++ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
++ return -ENAMETOOLONG;
++
++ wh->len = name->len + AUFS_WH_PFX_LEN;
++ p = kmalloc(wh->len, GFP_NOFS);
++ wh->name = p;
++ if (p) {
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
++ /* smp_mb(); */
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the @wh_name exists under @h_parent.
++ * @try_sio specifies the necessary of super-io.
++ */
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++ struct au_branch *br, int try_sio)
++{
++ int err;
++ struct dentry *wh_dentry;
++ struct inode *h_dir;
++
++ h_dir = h_parent->d_inode;
++ if (!try_sio)
++ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
++ else
++ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
++ err = PTR_ERR(wh_dentry);
++ if (IS_ERR(wh_dentry))
++ goto out;
++
++ err = 0;
++ if (!wh_dentry->d_inode)
++ goto out_wh; /* success */
++
++ err = 1;
++ if (S_ISREG(wh_dentry->d_inode->i_mode))
++ goto out_wh; /* success */
++
++ err = -EIO;
++ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
++ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
++
++ out_wh:
++ dput(wh_dentry);
++ out:
++ return err;
++}
++
++/*
++ * test if the @h_dentry sets opaque or not.
++ */
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct inode *h_dir;
++
++ h_dir = h_dentry->d_inode;
++ err = au_wh_test(h_dentry, &diropq_name, br,
++ au_test_h_perm_sio(h_dir, MAY_EXEC));
++ return err;
++}
++
++/*
++ * returns a negative dentry whose name is unique and temporary.
++ */
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++ struct qstr *prefix)
++{
++#define HEX_LEN 4
++ struct dentry *dentry;
++ int i;
++ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
++ + HEX_LEN + 1], *name, *p;
++ static unsigned short cnt;
++ struct qstr qs;
++
++ name = defname;
++ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
++ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
++ dentry = ERR_PTR(-ENAMETOOLONG);
++ if (unlikely(qs.len >= PATH_MAX))
++ goto out;
++ dentry = ERR_PTR(-ENOMEM);
++ name = kmalloc(qs.len + 1, GFP_NOFS);
++ if (unlikely(!name))
++ goto out;
++ }
++
++ /* doubly whiteout-ed */
++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
++ p = name + AUFS_WH_PFX_LEN * 2;
++ memcpy(p, prefix->name, prefix->len);
++ p += prefix->len;
++ *p++ = '.';
++ AuDebugOn(name + qs.len + 1 - p <= HEX_LEN);
++
++ qs.name = name;
++ for (i = 0; i < 3; i++) {
++ sprintf(p, "%.*d", HEX_LEN, cnt++);
++ dentry = au_sio_lkup_one(&qs, h_parent, br);
++ if (IS_ERR(dentry) || !dentry->d_inode)
++ goto out_name;
++ dput(dentry);
++ }
++ /* AuWarn("could not get random name\n"); */
++ dentry = ERR_PTR(-EEXIST);
++ AuDbg("%.*s\n", AuLNPair(&qs));
++ BUG();
++
++ out_name:
++ if (name != defname)
++ kfree(name);
++ out:
++ return dentry;
++#undef HEX_LEN
++}
++
++/*
++ * rename the @h_dentry on @br to the whiteouted temporary name.
++ */
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++ struct dentry *h_parent;
++
++ h_parent = h_dentry->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
++ err = PTR_ERR(h_path.dentry);
++ if (IS_ERR(h_path.dentry))
++ goto out;
++
++ /* under the same dir, no need to lock_rename() */
++ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
++ AuTraceErr(err);
++ dput(h_path.dentry);
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * functions for removing a whiteout
++ */
++
++static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
++{
++ int force;
++
++ /*
++ * forces superio when the dir has a sticky bit.
++ * this may be a violation of unix fs semantics.
++ */
++ force = (h_dir->i_mode & S_ISVTX)
++ && h_path->dentry->d_inode->i_uid != current_fsuid();
++ return vfsub_unlink(h_dir, h_path, force);
++}
++
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++ struct dentry *dentry)
++{
++ int err;
++
++ err = do_unlink_wh(h_dir, h_path);
++ if (!err && dentry)
++ au_set_dbwh(dentry, -1);
++
++ return err;
++}
++
++static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
++ struct au_branch *br)
++{
++ int err;
++ struct path h_path = {
++ .mnt = br->br_mnt
++ };
++
++ err = 0;
++ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
++ if (IS_ERR(h_path.dentry))
++ err = PTR_ERR(h_path.dentry);
++ else {
++ if (h_path.dentry->d_inode
++ && S_ISREG(h_path.dentry->d_inode->i_mode))
++ err = do_unlink_wh(h_parent->d_inode, &h_path);
++ dput(h_path.dentry);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * initialize/clean whiteout for a branch
++ */
++
++static void au_wh_clean(struct inode *h_dir, struct path *whpath,
++ const int isdir)
++{
++ int err;
++
++ if (!whpath->dentry->d_inode)
++ return;
++
++ err = mnt_want_write(whpath->mnt);
++ if (!err) {
++ if (isdir)
++ err = vfsub_rmdir(h_dir, whpath);
++ else
++ err = vfsub_unlink(h_dir, whpath, /*force*/0);
++ mnt_drop_write(whpath->mnt);
++ }
++ if (unlikely(err))
++ AuWarn("failed removing %.*s (%d), ignored.\n",
++ AuDLNPair(whpath->dentry), err);
++}
++
++static int test_linkable(struct dentry *h_root)
++{
++ struct inode *h_dir = h_root->d_inode;
++
++ if (h_dir->i_op->link)
++ return 0;
++
++ AuErr("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
++ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++ return -ENOSYS;
++}
++
++/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
++static int au_whdir(struct inode *h_dir, struct path *path)
++{
++ int err;
++
++ err = -EEXIST;
++ if (!path->dentry->d_inode) {
++ int mode = S_IRWXU;
++
++ if (au_test_nfs(path->dentry->d_sb))
++ mode |= S_IXUGO;
++ err = mnt_want_write(path->mnt);
++ if (!err) {
++ err = vfsub_mkdir(h_dir, path, mode);
++ mnt_drop_write(path->mnt);
++ }
++ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
++ err = 0;
++ else
++ AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
++
++ return err;
++}
++
++struct au_wh_base {
++ const struct qstr *name;
++ struct dentry *dentry;
++};
++
++static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
++ struct path *h_path)
++{
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/0);
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++}
++
++/*
++ * returns tri-state,
++ * minus: error, caller should print the mesage
++ * zero: succuess
++ * plus: error, caller should NOT print the mesage
++ */
++static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
++ int do_plink, struct au_wh_base base[],
++ struct path *h_path)
++{
++ int err;
++ struct inode *h_dir;
++
++ h_dir = h_root->d_inode;
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ au_wh_clean(h_dir, h_path, /*isdir*/0);
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ if (do_plink) {
++ err = test_linkable(h_root);
++ if (unlikely(err)) {
++ err = 1;
++ goto out;
++ }
++
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++ } else
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++ return err;
++}
++
++/*
++ * for the moment, aufs supports the branch filesystem which does not support
++ * link(2). testing on FAT which does not support i_op->setattr() fully either,
++ * copyup failed. finally, such filesystem will not be used as the writable
++ * branch.
++ *
++ * returns tri-state, see above.
++ */
++static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
++ int do_plink, struct au_wh_base base[],
++ struct path *h_path)
++{
++ int err;
++ struct inode *h_dir;
++
++ err = test_linkable(h_root);
++ if (unlikely(err)) {
++ err = 1;
++ goto out;
++ }
++
++ /*
++ * todo: should this create be done in /sbin/mount.aufs helper?
++ */
++ err = -EEXIST;
++ h_dir = h_root->d_inode;
++ if (!base[AuBrWh_BASE].dentry->d_inode) {
++ err = mnt_want_write(h_path->mnt);
++ if (!err) {
++ h_path->dentry = base[AuBrWh_BASE].dentry;
++ err = vfsub_create(h_dir, h_path, WH_MASK);
++ mnt_drop_write(h_path->mnt);
++ }
++ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
++ err = 0;
++ else
++ AuErr("unknown %.*s/%.*s exists\n",
++ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
++ if (unlikely(err))
++ goto out;
++
++ h_path->dentry = base[AuBrWh_PLINK].dentry;
++ if (do_plink) {
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++ } else
++ au_wh_clean(h_dir, h_path, /*isdir*/1);
++ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
++
++ h_path->dentry = base[AuBrWh_ORPH].dentry;
++ err = au_whdir(h_dir, h_path);
++ if (unlikely(err))
++ goto out;
++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++ return err;
++}
++
++/*
++ * initialize the whiteout base file/dir for @br.
++ */
++int au_wh_init(struct dentry *h_root, struct au_branch *br,
++ struct super_block *sb)
++{
++ int err, i;
++ const unsigned char do_plink
++ = !!au_opt_test(au_mntflags(sb), PLINK);
++ struct path path = {
++ .mnt = br->br_mnt
++ };
++ struct inode *h_dir;
++ struct au_wbr *wbr = br->br_wbr;
++ static const struct qstr base_name[] = {
++ [AuBrWh_BASE] = {
++ .name = AUFS_BASE_NAME,
++ .len = sizeof(AUFS_BASE_NAME) - 1
++ },
++ [AuBrWh_PLINK] = {
++ .name = AUFS_PLINKDIR_NAME,
++ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
++ },
++ [AuBrWh_ORPH] = {
++ .name = AUFS_ORPHDIR_NAME,
++ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
++ }
++ };
++ struct au_wh_base base[] = {
++ [AuBrWh_BASE] = {
++ .name = base_name + AuBrWh_BASE,
++ .dentry = NULL
++ },
++ [AuBrWh_PLINK] = {
++ .name = base_name + AuBrWh_PLINK,
++ .dentry = NULL
++ },
++ [AuBrWh_ORPH] = {
++ .name = base_name + AuBrWh_ORPH,
++ .dentry = NULL
++ }
++ };
++
++
++ h_dir = h_root->d_inode;
++ for (i = 0; i < AuBrWh_Last; i++) {
++ /* doubly whiteouted */
++ struct dentry *d;
++
++ d = au_wh_lkup(h_root, (void *)base[i].name, br);
++ err = PTR_ERR(d);
++ if (IS_ERR(d))
++ goto out;
++
++ base[i].dentry = d;
++ AuDebugOn(wbr
++ && wbr->wbr_wh[i]
++ && wbr->wbr_wh[i] != base[i].dentry);
++ }
++
++ if (wbr)
++ for (i = 0; i < AuBrWh_Last; i++) {
++ dput(wbr->wbr_wh[i]);
++ wbr->wbr_wh[i] = NULL;
++ }
++
++ err = 0;
++
++ switch (br->br_perm) {
++ case AuBrPerm_RO:
++ case AuBrPerm_ROWH:
++ case AuBrPerm_RR:
++ case AuBrPerm_RRWH:
++ au_wh_init_ro(h_dir, base, &path);
++ break;
++
++ case AuBrPerm_RWNoLinkWH:
++ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
++ if (err > 0)
++ goto out;
++ else if (err)
++ goto out_err;
++ break;
++
++ case AuBrPerm_RW:
++ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
++ if (err > 0)
++ goto out;
++ else if (err)
++ goto out_err;
++ break;
++
++ default:
++ BUG();
++ }
++ goto out; /* success */
++
++ out_err:
++ AuErr("an error(%d) on the writable branch %.*s(%s)\n",
++ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++ out:
++ for (i = 0; i < AuBrWh_Last; i++)
++ dput(base[i].dentry);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * whiteouts are all hard-linked usually.
++ * when its link count reaches a ceiling, we create a new whiteout base
++ * asynchronously.
++ */
++
++struct reinit_br_wh {
++ struct super_block *sb;
++ struct au_branch *br;
++};
++
++static void reinit_br_wh(void *arg)
++{
++ int err;
++ aufs_bindex_t bindex;
++ struct path h_path;
++ struct reinit_br_wh *a = arg;
++ struct au_wbr *wbr;
++ struct inode *dir;
++ struct dentry *h_root;
++ struct au_hinode *hdir;
++
++ err = 0;
++ wbr = a->br->br_wbr;
++ /* big aufs lock */
++ si_noflush_write_lock(a->sb);
++ if (!au_br_writable(a->br->br_perm))
++ goto out;
++ bindex = au_br_index(a->sb, a->br->br_id);
++ if (unlikely(bindex < 0))
++ goto out;
++
++ dir = a->sb->s_root->d_inode;
++ /* ii_read_lock_parent(dir); */
++ hdir = au_hi(dir, bindex);
++ h_root = au_h_dptr(a->sb->s_root, bindex);
++
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ wbr_wh_write_lock(wbr);
++ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
++ h_root, a->br);
++ if (!err) {
++ err = mnt_want_write(a->br->br_mnt);
++ if (!err) {
++ h_path.dentry = wbr->wbr_whbase;
++ h_path.mnt = a->br->br_mnt;
++ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
++ mnt_drop_write(a->br->br_mnt);
++ }
++ } else {
++ AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
++ err = 0;
++ }
++ dput(wbr->wbr_whbase);
++ wbr->wbr_whbase = NULL;
++ if (!err)
++ err = au_wh_init(h_root, a->br, a->sb);
++ wbr_wh_write_unlock(wbr);
++ au_hin_imtx_unlock(hdir);
++ /* ii_read_unlock(dir); */
++
++ out:
++ if (wbr)
++ atomic_dec(&wbr->wbr_wh_running);
++ atomic_dec(&a->br->br_count);
++ au_nwt_done(&au_sbi(a->sb)->si_nowait);
++ si_write_unlock(a->sb);
++ kfree(arg);
++ if (unlikely(err))
++ AuIOErr("err %d\n", err);
++}
++
++static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
++{
++ int do_dec, wkq_err;
++ struct reinit_br_wh *arg;
++
++ do_dec = 1;
++ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
++ goto out;
++
++ /* ignore ENOMEM */
++ arg = kmalloc(sizeof(*arg), GFP_NOFS);
++ if (arg) {
++ /*
++ * dec(wh_running), kfree(arg) and dec(br_count)
++ * in reinit function
++ */
++ arg->sb = sb;
++ arg->br = br;
++ atomic_inc(&br->br_count);
++ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
++ if (unlikely(wkq_err)) {
++ atomic_dec(&br->br_wbr->wbr_wh_running);
++ atomic_dec(&br->br_count);
++ kfree(arg);
++ }
++ do_dec = 0;
++ }
++
++ out:
++ if (do_dec)
++ atomic_dec(&br->br_wbr->wbr_wh_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create the whiteout @wh.
++ */
++static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
++ struct dentry *wh)
++{
++ int err;
++ struct path h_path = {
++ .dentry = wh
++ };
++ struct au_branch *br;
++ struct au_wbr *wbr;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++
++ h_parent = wh->d_parent; /* dir inode is locked */
++ h_dir = h_parent->d_inode;
++ IMustLock(h_dir);
++
++ br = au_sbr(sb, bindex);
++ h_path.mnt = br->br_mnt;
++ wbr = br->br_wbr;
++ wbr_wh_read_lock(wbr);
++ if (wbr->wbr_whbase) {
++ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
++ if (!err || err != -EMLINK)
++ goto out;
++
++ /* link count full. re-initialize br_whbase. */
++ kick_reinit_br_wh(sb, br);
++ }
++
++ /* return this error in this context */
++ err = vfsub_create(h_dir, &h_path, WH_MASK);
++
++ out:
++ wbr_wh_read_unlock(wbr);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create or remove the diropq.
++ */
++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags)
++{
++ struct dentry *opq_dentry, *h_dentry;
++ struct super_block *sb;
++ struct au_branch *br;
++ int err;
++
++ sb = dentry->d_sb;
++ br = au_sbr(sb, bindex);
++ h_dentry = au_h_dptr(dentry, bindex);
++ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
++ if (IS_ERR(opq_dentry))
++ goto out;
++
++ if (au_ftest_diropq(flags, CREATE)) {
++ err = link_or_create_wh(sb, bindex, opq_dentry);
++ if (!err) {
++ au_set_dbdiropq(dentry, bindex);
++ goto out; /* success */
++ }
++ } else {
++ struct path tmp = {
++ .dentry = opq_dentry,
++ .mnt = br->br_mnt
++ };
++ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
++ if (!err)
++ au_set_dbdiropq(dentry, -1);
++ }
++ dput(opq_dentry);
++ opq_dentry = ERR_PTR(err);
++
++ out:
++ return opq_dentry;
++}
++
++struct do_diropq_args {
++ struct dentry **errp;
++ struct dentry *dentry;
++ aufs_bindex_t bindex;
++ unsigned int flags;
++};
++
++static void call_do_diropq(void *args)
++{
++ struct do_diropq_args *a = args;
++ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
++}
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags)
++{
++ struct dentry *diropq, *h_dentry;
++
++ h_dentry = au_h_dptr(dentry, bindex);
++ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
++ diropq = do_diropq(dentry, bindex, flags);
++ else {
++ int wkq_err;
++ struct do_diropq_args args = {
++ .errp = &diropq,
++ .dentry = dentry,
++ .bindex = bindex,
++ .flags = flags
++ };
++
++ wkq_err = au_wkq_wait(call_do_diropq, &args);
++ if (unlikely(wkq_err))
++ diropq = ERR_PTR(wkq_err);
++ }
++
++ return diropq;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * lookup whiteout dentry.
++ * @h_parent: lower parent dentry which must exist and be locked
++ * @base_name: name of dentry which will be whiteouted
++ * returns dentry for whiteout.
++ */
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++ struct au_branch *br)
++{
++ int err;
++ struct qstr wh_name;
++ struct dentry *wh_dentry;
++
++ err = au_wh_name_alloc(&wh_name, base_name);
++ wh_dentry = ERR_PTR(err);
++ if (!err) {
++ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
++ kfree(wh_name.name);
++ }
++ return wh_dentry;
++}
++
++/*
++ * link/create a whiteout for @dentry on @bindex.
++ */
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent)
++{
++ struct dentry *wh_dentry;
++ struct super_block *sb;
++ int err;
++
++ sb = dentry->d_sb;
++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
++ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
++ err = link_or_create_wh(sb, bindex, wh_dentry);
++ if (!err)
++ au_set_dbwh(dentry, bindex);
++ else {
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(err);
++ }
++ }
++
++ return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Delete all whiteouts in this directory on branch bindex. */
++static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
++ aufs_bindex_t bindex, struct au_branch *br)
++{
++ int err;
++ unsigned long ul, n;
++ struct qstr wh_name;
++ char *p;
++ struct hlist_head *head;
++ struct au_vdir_wh *tpos;
++ struct hlist_node *pos;
++ struct au_vdir_destr *str;
++
++ err = -ENOMEM;
++ p = __getname();
++ wh_name.name = p;
++ if (unlikely(!wh_name.name))
++ goto out;
++
++ err = 0;
++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++ p += AUFS_WH_PFX_LEN;
++ n = whlist->nh_num;
++ head = whlist->nh_head;
++ for (ul = 0; !err && ul < n; ul++, head++) {
++ hlist_for_each_entry(tpos, pos, head, wh_hash) {
++ if (tpos->wh_bindex != bindex)
++ continue;
++
++ str = &tpos->wh_str;
++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
++ memcpy(p, str->name, str->len);
++ wh_name.len = AUFS_WH_PFX_LEN + str->len;
++ err = unlink_wh_name(h_dentry, &wh_name, br);
++ if (!err)
++ continue;
++ break;
++ }
++ AuIOErr("whiteout name too long %.*s\n",
++ str->len, str->name);
++ err = -EIO;
++ break;
++ }
++ }
++ __putname(wh_name.name);
++
++ out:
++ return err;
++}
++
++struct del_wh_children_args {
++ int *errp;
++ struct dentry *h_dentry;
++ struct au_nhash whlist;
++ aufs_bindex_t bindex;
++ struct au_branch *br;
++};
++
++static void call_del_wh_children(void *args)
++{
++ struct del_wh_children_args *a = args;
++ *a->errp = del_wh_children(a->h_dentry, &a->whlist, a->bindex, a->br);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
++{
++ struct au_whtmp_rmdir *whtmp;
++ int err;
++
++ whtmp = kmalloc(sizeof(*whtmp), gfp);
++ if (unlikely(!whtmp)) {
++ whtmp = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++
++ whtmp->dir = NULL;
++ whtmp->wh_dentry = NULL;
++ err = au_nhash_alloc(&whtmp->whlist, au_sbi(sb)->si_rdhash, gfp);
++ if (!err)
++ return whtmp; /* success */
++
++ kfree(whtmp);
++ whtmp = ERR_PTR(err);
++
++ out:
++ return whtmp;
++}
++
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
++{
++ dput(whtmp->wh_dentry);
++ iput(whtmp->dir);
++ au_nhash_wh_free(&whtmp->whlist);
++ kfree(whtmp);
++}
++
++/*
++ * rmdir the whiteouted temporary named dir @h_dentry.
++ * @whlist: whiteouted children.
++ */
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_nhash *whlist)
++{
++ int err;
++ struct path h_tmp;
++ struct inode *wh_inode, *h_dir;
++ struct au_branch *br;
++
++ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++ IMustLock(h_dir);
++
++ br = au_sbr(dir->i_sb, bindex);
++ wh_inode = wh_dentry->d_inode;
++ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
++
++ /*
++ * someone else might change some whiteouts while we were sleeping.
++ * it means this whlist may have an obsoleted entry.
++ */
++ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
++ err = del_wh_children(wh_dentry, whlist, bindex, br);
++ else {
++ int wkq_err;
++ struct del_wh_children_args args = {
++ .errp = &err,
++ .h_dentry = wh_dentry,
++ .whlist = *whlist,
++ .bindex = bindex,
++ .br = br
++ };
++
++ wkq_err = au_wkq_wait(call_del_wh_children, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ }
++ mutex_unlock(&wh_inode->i_mutex);
++
++ if (!err) {
++ h_tmp.dentry = wh_dentry;
++ h_tmp.mnt = br->br_mnt;
++ err = vfsub_rmdir(h_dir, &h_tmp);
++ /* d_drop(h_dentry); */
++ }
++
++ if (!err) {
++ if (au_ibstart(dir) == bindex) {
++ au_cpup_attr_timesizes(dir);
++ drop_nlink(dir);
++ }
++ return 0; /* success */
++ }
++
++ AuWarn("failed removing %.*s(%d), ignored\n",
++ AuDLNPair(wh_dentry), err);
++ return err;
++}
++
++static void call_rmdir_whtmp(void *args)
++{
++ int err;
++ struct au_whtmp_rmdir *a = args;
++ struct super_block *sb;
++ struct dentry *h_parent;
++ struct inode *h_dir;
++ struct au_branch *br;
++ struct au_hinode *hdir;
++
++ /* rmdir by nfsd may cause deadlock with this i_mutex */
++ /* mutex_lock(&a->dir->i_mutex); */
++ sb = a->dir->i_sb;
++ si_noflush_read_lock(sb);
++ err = au_test_ro(sb, a->bindex, NULL);
++ if (unlikely(err))
++ goto out;
++
++ err = -EIO;
++ br = au_sbr(sb, a->bindex);
++ ii_write_lock_parent(a->dir);
++ h_parent = dget_parent(a->wh_dentry);
++ h_dir = h_parent->d_inode;
++ hdir = au_hi(a->dir, a->bindex);
++ au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
++ if (!err) {
++ err = mnt_want_write(br->br_mnt);
++ if (!err) {
++ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
++ &a->whlist);
++ mnt_drop_write(br->br_mnt);
++ }
++ }
++ au_hin_imtx_unlock(hdir);
++ dput(h_parent);
++ ii_write_unlock(a->dir);
++
++ out:
++ /* mutex_unlock(&a->dir->i_mutex); */
++ au_nwt_done(&au_sbi(sb)->si_nowait);
++ si_read_unlock(sb);
++ au_whtmp_rmdir_free(a);
++ if (unlikely(err))
++ AuIOErr("err %d\n", err);
++}
++
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
++{
++ int wkq_err;
++
++ IMustLock(dir);
++
++ /* all post-process will be done in do_rmdir_whtmp(). */
++ args->dir = au_igrab(dir);
++ args->bindex = bindex;
++ args->wh_dentry = dget(wh_dentry);
++ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
++ if (unlikely(wkq_err)) {
++ AuWarn("rmdir error %.*s (%d), ignored\n",
++ AuDLNPair(wh_dentry), wkq_err);
++ au_whtmp_rmdir_free(args);
++ }
++}
+diff -Naur a/fs/aufs/whout.h b/fs/aufs/whout.h
+--- a/fs/aufs/whout.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#ifndef __AUFS_WHOUT_H__
++#define __AUFS_WHOUT_H__
++
++#ifdef __KERNEL__
++
++#include <linux/aufs_type.h>
++#include "dir.h"
++
++/* whout.c */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
++struct au_branch;
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++ struct au_branch *br, int try_sio);
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++ struct qstr *prefix);
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++ struct dentry *dentry);
++int au_wh_init(struct dentry *h_parent, struct au_branch *br,
++ struct super_block *sb);
++
++/* diropq flags */
++#define AuDiropq_CREATE 1
++#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
++#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
++#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++ unsigned int flags);
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++ struct au_branch *br);
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++ struct dentry *h_parent);
++
++/* real rmdir for the whiteout-ed dir */
++struct au_whtmp_rmdir {
++ struct inode *dir;
++ aufs_bindex_t bindex;
++ struct dentry *wh_dentry;
++ struct au_nhash whlist;
++};
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_nhash *whlist);
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_diropq_create(struct dentry *dentry,
++ aufs_bindex_t bindex)
++{
++ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
++}
++
++static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
++{
++ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WHOUT_H__ */
+diff -Naur a/fs/aufs/wkq.c b/fs/aufs/wkq.c
+--- a/fs/aufs/wkq.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,259 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new dredential scheme
++ */
++
++#include <linux/module.h>
++#include "aufs.h"
++
++/* internal workqueue named AUFS_WKQ_NAME */
++static struct au_wkq {
++ struct workqueue_struct *q;
++
++ /* balancing */
++ atomic_t busy;
++} *au_wkq;
++
++struct au_wkinfo {
++ struct work_struct wk;
++ struct super_block *sb;
++
++ unsigned int flags; /* see wkq.h */
++
++ au_wkq_func_t func;
++ void *args;
++
++ atomic_t *busyp;
++ struct completion *comp;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++ wkinfo->busyp = &wkq->busy;
++ if (au_ftest_wkq(wkinfo->flags, WAIT))
++ return !queue_work(wkq->q, &wkinfo->wk);
++ else
++ return !schedule_work(&wkinfo->wk);
++}
++
++static void do_wkq(struct au_wkinfo *wkinfo)
++{
++ unsigned int idle, n;
++ int i, idle_idx;
++
++ while (1) {
++ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
++ idle_idx = 0;
++ idle = UINT_MAX;
++ for (i = 0; i < aufs_nwkq; i++) {
++ n = atomic_inc_return(&au_wkq[i].busy);
++ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
++ return; /* success */
++
++ if (n < idle) {
++ idle_idx = i;
++ idle = n;
++ }
++ atomic_dec(&au_wkq[i].busy);
++ }
++ } else
++ idle_idx = aufs_nwkq;
++
++ atomic_inc(&au_wkq[idle_idx].busy);
++ if (!enqueue(au_wkq + idle_idx, wkinfo))
++ return; /* success */
++
++ /* impossible? */
++ AuWarn1("failed to queue_work()\n");
++ yield();
++ }
++}
++
++static void wkq_func(struct work_struct *wk)
++{
++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
++
++ wkinfo->func(wkinfo->args);
++ atomic_dec(wkinfo->busyp);
++ if (au_ftest_wkq(wkinfo->flags, WAIT))
++ complete(wkinfo->comp);
++ else {
++ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
++ module_put(THIS_MODULE);
++ kfree(wkinfo);
++ }
++}
++
++/*
++ * Since struct completion is large, try allocating it dynamically.
++ */
++#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
++#define AuWkqCompDeclare(name) struct completion *comp = NULL
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
++ if (*comp) {
++ init_completion(*comp);
++ wkinfo->comp = *comp;
++ return 0;
++ }
++ return -ENOMEM;
++}
++
++static void au_wkq_comp_free(struct completion *comp)
++{
++ kfree(comp);
++}
++
++#else
++
++/* no braces */
++#define AuWkqCompDeclare(name) \
++ DECLARE_COMPLETION_ONSTACK(_ ## name); \
++ struct completion *comp = &_ ## name
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++ wkinfo->comp = *comp;
++ return 0;
++}
++
++static void au_wkq_comp_free(struct completion *comp __maybe_unused)
++{
++ /* empty */
++}
++#endif /* 4KSTACKS */
++
++static void au_wkq_run(struct au_wkinfo *wkinfo)
++{
++ au_dbg_verify_kthread();
++ INIT_WORK(&wkinfo->wk, wkq_func);
++ do_wkq(wkinfo);
++}
++
++int au_wkq_wait(au_wkq_func_t func, void *args)
++{
++ int err;
++ AuWkqCompDeclare(comp);
++ struct au_wkinfo wkinfo = {
++ .flags = AuWkq_WAIT,
++ .func = func,
++ .args = args
++ };
++
++ err = au_wkq_comp_alloc(&wkinfo, &comp);
++ if (!err) {
++ au_wkq_run(&wkinfo);
++ /* no timeout, no interrupt */
++ wait_for_completion(wkinfo.comp);
++ au_wkq_comp_free(comp);
++ }
++
++ return err;
++
++}
++
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
++{
++ int err;
++ struct au_wkinfo *wkinfo;
++
++ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
++
++ /*
++ * wkq_func() must free this wkinfo.
++ * it highly depends upon the implementation of workqueue.
++ */
++ err = 0;
++ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
++ if (wkinfo) {
++ wkinfo->sb = sb;
++ wkinfo->flags = !AuWkq_WAIT;
++ wkinfo->func = func;
++ wkinfo->args = args;
++ wkinfo->comp = NULL;
++ kobject_get(&au_sbi(sb)->si_kobj);
++ __module_get(THIS_MODULE);
++
++ au_wkq_run(wkinfo);
++ } else {
++ err = -ENOMEM;
++ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_nwt_init(struct au_nowait_tasks *nwt)
++{
++ atomic_set(&nwt->nw_len, 0);
++ /* smp_mb();*/ /* atomic_set */
++ init_waitqueue_head(&nwt->nw_wq);
++}
++
++void au_wkq_fin(void)
++{
++ int i;
++
++ for (i = 0; i < aufs_nwkq; i++)
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
++ destroy_workqueue(au_wkq[i].q);
++ kfree(au_wkq);
++}
++
++int __init au_wkq_init(void)
++{
++ int err, i;
++ struct au_wkq *nowaitq;
++
++ /* '+1' is for accounting of nowait queue */
++ err = -ENOMEM;
++ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
++ if (unlikely(!au_wkq))
++ goto out;
++
++ err = 0;
++ for (i = 0; i < aufs_nwkq; i++) {
++ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
++ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
++ atomic_set(&au_wkq[i].busy, 0);
++ continue;
++ }
++
++ err = PTR_ERR(au_wkq[i].q);
++ au_wkq_fin();
++ goto out;
++ }
++
++ /* nowait accounting */
++ nowaitq = au_wkq + aufs_nwkq;
++ atomic_set(&nowaitq->busy, 0);
++ nowaitq->q = NULL;
++ /* smp_mb(); */ /* atomic_set */
++
++ out:
++ return err;
++}
+diff -Naur a/fs/aufs/wkq.h b/fs/aufs/wkq.h
+--- a/fs/aufs/wkq.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new credentials management scheme
++ */
++
++#ifndef __AUFS_WKQ_H__
++#define __AUFS_WKQ_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
++ */
++struct au_nowait_tasks {
++ atomic_t nw_len;
++ wait_queue_head_t nw_wq;
++};
++
++/* ---------------------------------------------------------------------- */
++
++typedef void (*au_wkq_func_t)(void *args);
++
++/* wkq flags */
++#define AuWkq_WAIT 1
++#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
++#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
++#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
++
++/* wkq.c */
++int au_wkq_wait(au_wkq_func_t func, void *args);
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
++void au_nwt_init(struct au_nowait_tasks *nwt);
++int __init au_wkq_init(void);
++void au_wkq_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_test_wkq(struct task_struct *tsk)
++{
++ return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
++}
++
++static inline void au_nwt_done(struct au_nowait_tasks *nwt)
++{
++ if (!atomic_dec_return(&nwt->nw_len))
++ wake_up_all(&nwt->nw_wq);
++}
++
++static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
++{
++ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
++ return 0;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WKQ_H__ */
+diff -Naur a/fs/aufs/xino.c b/fs/aufs/xino.c
+--- a/fs/aufs/xino.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/xino.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1191 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/*
++ * external inode number translation table and bitmap
++ */
++
++#include <linux/file.h>
++#include <linux/seq_file.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ do {
++ /* todo: signal_pending? */
++ err = func(file, (char __user *)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++ if (err > 0)
++ fsnotify_access(file->f_dentry);
++#endif
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
++ size_t size, loff_t *pos)
++{
++ ssize_t err;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ lockdep_off();
++ do {
++ /* todo: signal_pending? */
++ err = func(file, (const char __user *)buf, size, pos);
++ } while (err == -EAGAIN || err == -EINTR);
++ lockdep_on();
++ set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++ if (err > 0)
++ fsnotify_modify(file->f_dentry);
++#endif
++
++ return err;
++}
++
++struct do_xino_fwrite_args {
++ ssize_t *errp;
++ au_writef_t func;
++ struct file *file;
++ void *buf;
++ size_t size;
++ loff_t *pos;
++};
++
++static void call_do_xino_fwrite(void *args)
++{
++ struct do_xino_fwrite_args *a = args;
++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
++}
++
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++ loff_t *pos)
++{
++ ssize_t err;
++
++ /* todo: signal block and no wkq? */
++ /* todo: new credential scheme */
++ /*
++ * it breaks RLIMIT_FSIZE and normal user's limit,
++ * users should care about quota and real 'filesystem full.'
++ */
++ if (!au_test_wkq(current)) {
++ int wkq_err;
++ struct do_xino_fwrite_args args = {
++ .errp = &err,
++ .func = func,
++ .file = file,
++ .buf = buf,
++ .size = size,
++ .pos = pos
++ };
++
++ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
++ if (unlikely(wkq_err))
++ err = wkq_err;
++ } else
++ err = do_xino_fwrite(func, file, buf, size, pos);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a new xinofile at the same place/path as @base_file.
++ */
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
++{
++ struct file *file;
++ struct dentry *base, *dentry, *parent;
++ struct inode *dir;
++ struct qstr *name;
++ int err;
++
++ base = base_file->f_dentry;
++ parent = base->d_parent; /* dir inode is locked */
++ dir = parent->d_inode;
++ IMustLock(dir);
++
++ file = ERR_PTR(-EINVAL);
++ name = &base->d_name;
++ dentry = vfsub_lookup_one_len(name->name, parent, name->len);
++ if (IS_ERR(dentry)) {
++ file = (void *)dentry;
++ AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
++ goto out;
++ }
++
++ /* no need to mnt_want_write() since we call dentry_open() later */
++ err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
++ if (unlikely(err)) {
++ file = ERR_PTR(err);
++ AuErr("%.*s create err %d\n", AuLNPair(name), err);
++ goto out_dput;
++ }
++
++ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ current_cred());
++ if (IS_ERR(file)) {
++ AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
++ goto out_dput;
++ }
++
++ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
++ if (unlikely(err)) {
++ AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
++ goto out_fput;
++ }
++
++ if (copy_src) {
++ /* no one can touch copy_src xino */
++ err = au_copy_file(file, copy_src,
++ i_size_read(copy_src->f_dentry->d_inode));
++ if (unlikely(err)) {
++ AuErr("%.*s copy err %d\n", AuLNPair(name), err);
++ goto out_fput;
++ }
++ }
++ goto out_dput; /* success */
++
++ out_fput:
++ fput(file);
++ file = ERR_PTR(err);
++ out_dput:
++ dput(dentry);
++ out:
++ return file;
++}
++
++struct au_xino_lock_dir {
++ struct au_hinode *hdir;
++ struct dentry *parent;
++ struct mutex *mtx;
++};
++
++static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
++ struct au_xino_lock_dir *ldir)
++{
++ aufs_bindex_t brid, bindex;
++
++ ldir->hdir = NULL;
++ bindex = -1;
++ brid = au_xino_brid(sb);
++ if (brid >= 0)
++ bindex = au_br_index(sb, brid);
++ if (bindex >= 0) {
++ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
++ au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
++ } else {
++ ldir->parent = dget_parent(xino->f_dentry);
++ ldir->mtx = &ldir->parent->d_inode->i_mutex;
++ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
++ }
++}
++
++static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
++{
++ if (ldir->hdir)
++ au_hin_imtx_unlock(ldir->hdir);
++ else {
++ mutex_unlock(ldir->mtx);
++ dput(ldir->parent);
++ }
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate xino files asynchronously */
++
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
++{
++ int err;
++ aufs_bindex_t bi, bend;
++ struct au_branch *br;
++ struct file *new_xino, *file;
++ struct super_block *h_sb;
++ struct au_xino_lock_dir ldir;
++
++ err = -EINVAL;
++ bend = au_sbend(sb);
++ if (unlikely(bindex < 0 || bend < bindex))
++ goto out;
++ br = au_sbr(sb, bindex);
++ file = br->br_xino.xi_file;
++ if (!file)
++ goto out;
++
++ au_xino_lock_dir(sb, file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ new_xino = au_xino_create2(file, file);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(new_xino);
++ if (IS_ERR(new_xino))
++ goto out;
++ err = 0;
++ fput(file);
++ br->br_xino.xi_file = new_xino;
++
++ h_sb = br->br_mnt->mnt_sb;
++ for (bi = 0; bi <= bend; bi++) {
++ if (unlikely(bi == bindex))
++ continue;
++ br = au_sbr(sb, bi);
++ if (br->br_mnt->mnt_sb != h_sb)
++ continue;
++
++ fput(br->br_xino.xi_file);
++ br->br_xino.xi_file = new_xino;
++ get_file(new_xino);
++ }
++
++ out:
++ return err;
++}
++
++struct xino_do_trunc_args {
++ struct super_block *sb;
++ struct au_branch *br;
++};
++
++static void xino_do_trunc(void *_args)
++{
++ struct xino_do_trunc_args *args = _args;
++ struct super_block *sb;
++ struct au_branch *br;
++ struct inode *dir;
++ int err;
++ aufs_bindex_t bindex;
++
++ err = 0;
++ sb = args->sb;
++ dir = sb->s_root->d_inode;
++ br = args->br;
++
++ si_noflush_write_lock(sb);
++ ii_read_lock_parent(dir);
++ bindex = au_br_index(sb, br->br_id);
++ err = au_xino_trunc(sb, bindex);
++ if (unlikely(err))
++ goto out;
++
++ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++ >= br->br_xino_upper)
++ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
++
++ out:
++ ii_read_unlock(dir);
++ if (unlikely(err))
++ AuWarn("err b%d, (%d)\n", bindex, err);
++ atomic_dec(&br->br_xino_running);
++ atomic_dec(&br->br_count);
++ au_nwt_done(&au_sbi(sb)->si_nowait);
++ si_write_unlock(sb);
++ kfree(args);
++}
++
++static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
++{
++ struct xino_do_trunc_args *args;
++ int wkq_err;
++
++ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++ < br->br_xino_upper)
++ return;
++
++ if (atomic_inc_return(&br->br_xino_running) > 1)
++ goto out;
++
++ /* lock and kfree() will be called in trunc_xino() */
++ args = kmalloc(sizeof(*args), GFP_NOFS);
++ if (unlikely(!args)) {
++ AuErr1("no memory\n");
++ goto out_args;
++ }
++
++ atomic_inc(&br->br_count);
++ args->sb = sb;
++ args->br = br;
++ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
++ if (!wkq_err)
++ return; /* success */
++
++ AuErr("wkq %d\n", wkq_err);
++ atomic_dec(&br->br_count);
++
++ out_args:
++ kfree(args);
++ out:
++ atomic_dec(&br->br_xino_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_xino_do_write(au_writef_t write, struct file *file,
++ ino_t h_ino, ino_t ino)
++{
++ loff_t pos;
++ ssize_t sz;
++
++ pos = h_ino;
++ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
++ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++ return -EFBIG;
++ }
++ pos *= sizeof(ino);
++ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
++ if (sz == sizeof(ino))
++ return 0; /* success */
++
++ AuIOErr("write failed (%zd)\n", sz);
++ return -EIO;
++}
++
++/*
++ * write @ino to the xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * even if @ino is zero, it is written to the xinofile and means no entry.
++ * if the size of the xino file on a specific filesystem exceeds the watermark,
++ * try truncating it.
++ */
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino)
++{
++ int err;
++ unsigned int mnt_flags;
++ struct au_branch *br;
++
++ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
++ || ((loff_t)-1) > 0);
++
++ mnt_flags = au_mntflags(sb);
++ if (!au_opt_test(mnt_flags, XINO))
++ return 0;
++
++ br = au_sbr(sb, bindex);
++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++ h_ino, ino);
++ if (!err) {
++ if (au_opt_test(mnt_flags, TRUNC_XINO)
++ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
++ xino_try_trunc(sb, br);
++ return 0; /* success */
++ }
++
++ AuIOErr("write failed (%d)\n", err);
++ return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* aufs inode number bitmap */
++
++static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
++static ino_t xib_calc_ino(unsigned long pindex, int bit)
++{
++ ino_t ino;
++
++ AuDebugOn(bit < 0 || page_bits <= bit);
++ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
++ return ino;
++}
++
++static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
++{
++ AuDebugOn(ino < AUFS_FIRST_INO);
++ ino -= AUFS_FIRST_INO;
++ *pindex = ino / page_bits;
++ *bit = ino % page_bits;
++}
++
++static int xib_pindex(struct super_block *sb, unsigned long pindex)
++{
++ int err;
++ loff_t pos;
++ ssize_t sz;
++ struct au_sbinfo *sbinfo;
++ struct file *xib;
++ unsigned long *p;
++
++ sbinfo = au_sbi(sb);
++ MtxMustLock(&sbinfo->si_xib_mtx);
++ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
++ || !au_opt_test(sbinfo->si_mntflags, XINO));
++
++ if (pindex == sbinfo->si_xib_last_pindex)
++ return 0;
++
++ xib = sbinfo->si_xib;
++ p = sbinfo->si_xib_buf;
++ pos = sbinfo->si_xib_last_pindex;
++ pos *= PAGE_SIZE;
++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ if (unlikely(sz != PAGE_SIZE))
++ goto out;
++
++ pos = pindex;
++ pos *= PAGE_SIZE;
++ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
++ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
++ else {
++ memset(p, 0, PAGE_SIZE);
++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ }
++ if (sz == PAGE_SIZE) {
++ sbinfo->si_xib_last_pindex = pindex;
++ return 0; /* success */
++ }
++
++ out:
++ AuIOErr1("write failed (%zd)\n", sz);
++ err = sz;
++ if (sz >= 0)
++ err = -EIO;
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t ino)
++{
++ int err, bit;
++ unsigned long pindex;
++ struct au_sbinfo *sbinfo;
++
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return 0;
++
++ err = 0;
++ if (ino) {
++ sbinfo = au_sbi(sb);
++ xib_calc_bit(ino, &pindex, &bit);
++ AuDebugOn(page_bits <= bit);
++ mutex_lock(&sbinfo->si_xib_mtx);
++ err = xib_pindex(sb, pindex);
++ if (!err) {
++ clear_bit(bit, sbinfo->si_xib_buf);
++ sbinfo->si_xib_next_bit = bit;
++ }
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ }
++
++ if (!err)
++ err = au_xino_write(sb, bindex, h_ino, 0);
++ return err;
++}
++
++/* get an unused inode number from bitmap */
++ino_t au_xino_new_ino(struct super_block *sb)
++{
++ ino_t ino;
++ unsigned long *p, pindex, ul, pend;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++ int free_bit, err;
++
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return iunique(sb, AUFS_FIRST_INO);
++
++ sbinfo = au_sbi(sb);
++ mutex_lock(&sbinfo->si_xib_mtx);
++ p = sbinfo->si_xib_buf;
++ free_bit = sbinfo->si_xib_next_bit;
++ if (free_bit < page_bits && !test_bit(free_bit, p))
++ goto out; /* success */
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++
++ pindex = sbinfo->si_xib_last_pindex;
++ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
++ err = xib_pindex(sb, ul);
++ if (unlikely(err))
++ goto out_err;
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++ }
++
++ file = sbinfo->si_xib;
++ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
++ for (ul = pindex + 1; ul <= pend; ul++) {
++ err = xib_pindex(sb, ul);
++ if (unlikely(err))
++ goto out_err;
++ free_bit = find_first_zero_bit(p, page_bits);
++ if (free_bit < page_bits)
++ goto out; /* success */
++ }
++ BUG();
++
++ out:
++ set_bit(free_bit, p);
++ sbinfo->si_xib_next_bit++;
++ pindex = sbinfo->si_xib_last_pindex;
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ ino = xib_calc_ino(pindex, free_bit);
++ AuDbg("i%lu\n", (unsigned long)ino);
++ return ino;
++ out_err:
++ mutex_unlock(&sbinfo->si_xib_mtx);
++ AuDbg("i0\n");
++ return 0;
++}
++
++/*
++ * read @ino from xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * if @ino does not exist and @do_new is true, get new one.
++ */
++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++ ino_t *ino)
++{
++ int err;
++ ssize_t sz;
++ loff_t pos;
++ struct file *file;
++ struct au_sbinfo *sbinfo;
++
++ *ino = 0;
++ if (!au_opt_test(au_mntflags(sb), XINO))
++ return 0; /* no xino */
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ pos = h_ino;
++ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
++ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++ return -EFBIG;
++ }
++ pos *= sizeof(*ino);
++
++ file = au_sbr(sb, bindex)->br_xino.xi_file;
++ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
++ return 0; /* no ino */
++
++ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
++ if (sz == sizeof(*ino))
++ return 0; /* success */
++
++ err = sz;
++ if (unlikely(sz >= 0)) {
++ err = -EIO;
++ AuIOErr("xino read error (%zd)\n", sz);
++ }
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* create and set a new xino file */
++
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
++{
++ struct file *file;
++ struct dentry *h_parent, *d;
++ struct inode *h_dir;
++ int err;
++
++ /*
++ * at mount-time, and the xino file is the default path,
++ * hinotify is disabled so we have no inotify events to ignore.
++ * when a user specified the xino, we cannot get au_hdir to be ignored.
++ */
++ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++ S_IRUGO | S_IWUGO);
++ if (IS_ERR(file)) {
++ if (!silent)
++ AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
++ return file;
++ }
++
++ /* keep file count */
++ h_parent = dget_parent(file->f_dentry);
++ h_dir = h_parent->d_inode;
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++ /* mnt_want_write() is unnecessary here */
++ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
++ mutex_unlock(&h_dir->i_mutex);
++ dput(h_parent);
++ if (unlikely(err)) {
++ if (!silent)
++ AuErr("unlink %s(%d)\n", fname, err);
++ goto out;
++ }
++
++ err = -EINVAL;
++ d = file->f_dentry;
++ if (unlikely(sb == d->d_sb)) {
++ if (!silent)
++ AuErr("%s must be outside\n", fname);
++ goto out;
++ }
++ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
++ if (!silent)
++ AuErr("xino doesn't support %s(%s)\n",
++ fname, au_sbtype(d->d_sb));
++ goto out;
++ }
++ return file; /* success */
++
++ out:
++ fput(file);
++ file = ERR_PTR(err);
++ return file;
++}
++
++/*
++ * find another branch who is on the same filesystem of the specified
++ * branch{@btgt}. search until @bend.
++ */
++static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
++ aufs_bindex_t bend)
++{
++ aufs_bindex_t bindex;
++ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
++
++ for (bindex = 0; bindex < btgt; bindex++)
++ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++ return bindex;
++ for (bindex++; bindex <= bend; bindex++)
++ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++ return bindex;
++ return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * initialize the xinofile for the specified branch @br
++ * at the place/path where @base_file indicates.
++ * test whether another branch is on the same filesystem or not,
++ * if @do_test is true.
++ */
++int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
++ struct file *base_file, int do_test)
++{
++ int err;
++ ino_t ino;
++ aufs_bindex_t bend, bindex;
++ struct au_branch *shared_br, *b;
++ struct file *file;
++ struct super_block *tgt_sb;
++
++ shared_br = NULL;
++ bend = au_sbend(sb);
++ if (do_test) {
++ tgt_sb = br->br_mnt->mnt_sb;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ b = au_sbr(sb, bindex);
++ if (tgt_sb == b->br_mnt->mnt_sb) {
++ shared_br = b;
++ break;
++ }
++ }
++ }
++
++ if (!shared_br || !shared_br->br_xino.xi_file) {
++ struct au_xino_lock_dir ldir;
++
++ au_xino_lock_dir(sb, base_file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ file = au_xino_create2(base_file, NULL);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ br->br_xino.xi_file = file;
++ } else {
++ br->br_xino.xi_file = shared_br->br_xino.xi_file;
++ get_file(br->br_xino.xi_file);
++ }
++
++ ino = AUFS_ROOT_INO;
++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++ h_ino, ino);
++ if (!err)
++ return 0; /* success */
++
++
++ out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate a xino bitmap file */
++
++/* todo: slow */
++static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
++{
++ int err, bit;
++ ssize_t sz;
++ unsigned long pindex;
++ loff_t pos, pend;
++ struct au_sbinfo *sbinfo;
++ au_readf_t func;
++ ino_t *ino;
++ unsigned long *p;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ p = sbinfo->si_xib_buf;
++ func = sbinfo->si_xread;
++ pend = i_size_read(file->f_dentry->d_inode);
++ pos = 0;
++ while (pos < pend) {
++ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
++ err = sz;
++ if (unlikely(sz <= 0))
++ goto out;
++
++ err = 0;
++ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
++ if (unlikely(*ino < AUFS_FIRST_INO))
++ continue;
++
++ xib_calc_bit(*ino, &pindex, &bit);
++ AuDebugOn(page_bits <= bit);
++ err = xib_pindex(sb, pindex);
++ if (!err)
++ set_bit(bit, p);
++ else
++ goto out;
++ }
++ }
++
++ out:
++ return err;
++}
++
++static int xib_restore(struct super_block *sb)
++{
++ int err;
++ aufs_bindex_t bindex, bend;
++ void *page;
++
++ err = -ENOMEM;
++ page = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!page))
++ goto out;
++
++ err = 0;
++ bend = au_sbend(sb);
++ for (bindex = 0; !err && bindex <= bend; bindex++)
++ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
++ err = do_xib_restore
++ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
++ else
++ AuDbg("b%d\n", bindex);
++ free_page((unsigned long)page);
++
++ out:
++ return err;
++}
++
++int au_xib_trunc(struct super_block *sb)
++{
++ int err;
++ ssize_t sz;
++ loff_t pos;
++ struct au_xino_lock_dir ldir;
++ struct au_sbinfo *sbinfo;
++ unsigned long *p;
++ struct file *file;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ if (!au_opt_test(sbinfo->si_mntflags, XINO))
++ goto out;
++
++ file = sbinfo->si_xib;
++ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
++ goto out;
++
++ au_xino_lock_dir(sb, file, &ldir);
++ /* mnt_want_write() is unnecessary here */
++ file = au_xino_create2(sbinfo->si_xib, NULL);
++ au_xino_unlock_dir(&ldir);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = file;
++
++ p = sbinfo->si_xib_buf;
++ memset(p, 0, PAGE_SIZE);
++ pos = 0;
++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
++ if (unlikely(sz != PAGE_SIZE)) {
++ err = sz;
++ AuIOErr("err %d\n", err);
++ if (sz >= 0)
++ err = -EIO;
++ goto out;
++ }
++
++ mutex_lock(&sbinfo->si_xib_mtx);
++ /* mnt_want_write() is unnecessary here */
++ err = xib_restore(sb);
++ mutex_unlock(&sbinfo->si_xib_mtx);
++
++out:
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * xino mount option handlers
++ */
++static au_readf_t find_readf(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->read)
++ return fop->read;
++ if (fop->aio_read)
++ return do_sync_read;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++static au_writef_t find_writef(struct file *h_file)
++{
++ const struct file_operations *fop = h_file->f_op;
++
++ if (fop) {
++ if (fop->write)
++ return fop->write;
++ if (fop->aio_write)
++ return do_sync_write;
++ }
++ return ERR_PTR(-ENOSYS);
++}
++
++/* xino bitmap */
++static void xino_clear_xib(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ sbinfo = au_sbi(sb);
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ if (sbinfo->si_xib)
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = NULL;
++ free_page((unsigned long)sbinfo->si_xib_buf);
++ sbinfo->si_xib_buf = NULL;
++}
++
++static int au_xino_set_xib(struct super_block *sb, struct file *base)
++{
++ int err;
++ loff_t pos;
++ struct au_sbinfo *sbinfo;
++ struct file *file;
++
++ sbinfo = au_sbi(sb);
++ file = au_xino_create2(base, sbinfo->si_xib);
++ err = PTR_ERR(file);
++ if (IS_ERR(file))
++ goto out;
++ if (sbinfo->si_xib)
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = file;
++ sbinfo->si_xread = find_readf(file);
++ sbinfo->si_xwrite = find_writef(file);
++
++ err = -ENOMEM;
++ if (!sbinfo->si_xib_buf)
++ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
++ if (unlikely(!sbinfo->si_xib_buf))
++ goto out_unset;
++
++ sbinfo->si_xib_last_pindex = 0;
++ sbinfo->si_xib_next_bit = 0;
++ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
++ pos = 0;
++ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
++ PAGE_SIZE, &pos);
++ if (unlikely(err != PAGE_SIZE))
++ goto out_free;
++ }
++ err = 0;
++ goto out; /* success */
++
++ out_free:
++ free_page((unsigned long)sbinfo->si_xib_buf);
++ sbinfo->si_xib_buf = NULL;
++ if (err >= 0)
++ err = -EIO;
++ out_unset:
++ fput(sbinfo->si_xib);
++ sbinfo->si_xib = NULL;
++ sbinfo->si_xread = NULL;
++ sbinfo->si_xwrite = NULL;
++ out:
++ return err;
++}
++
++/* xino for each branch */
++static void xino_clear_br(struct super_block *sb)
++{
++ aufs_bindex_t bindex, bend;
++ struct au_branch *br;
++
++ bend = au_sbend(sb);
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (!br || !br->br_xino.xi_file)
++ continue;
++
++ fput(br->br_xino.xi_file);
++ br->br_xino.xi_file = NULL;
++ }
++}
++
++static int au_xino_set_br(struct super_block *sb, struct file *base)
++{
++ int err;
++ ino_t ino;
++ aufs_bindex_t bindex, bend, bshared;
++ struct {
++ struct file *old, *new;
++ } *fpair, *p;
++ struct au_branch *br;
++ struct inode *inode;
++ au_writef_t writef;
++
++ err = -ENOMEM;
++ bend = au_sbend(sb);
++ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
++ if (unlikely(!fpair))
++ goto out;
++
++ inode = sb->s_root->d_inode;
++ ino = AUFS_ROOT_INO;
++ writef = au_sbi(sb)->si_xwrite;
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++ br = au_sbr(sb, bindex);
++ bshared = is_sb_shared(sb, bindex, bindex - 1);
++ if (bshared >= 0) {
++ /* shared xino */
++ *p = fpair[bshared];
++ get_file(p->new);
++ }
++
++ if (!p->new) {
++ /* new xino */
++ p->old = br->br_xino.xi_file;
++ p->new = au_xino_create2(base, br->br_xino.xi_file);
++ err = PTR_ERR(p->new);
++ if (IS_ERR(p->new)) {
++ p->new = NULL;
++ goto out_pair;
++ }
++ }
++
++ err = au_xino_do_write(writef, p->new,
++ au_h_iptr(inode, bindex)->i_ino, ino);
++ if (unlikely(err))
++ goto out_pair;
++ }
++
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++ br = au_sbr(sb, bindex);
++ if (br->br_xino.xi_file)
++ fput(br->br_xino.xi_file);
++ get_file(p->new);
++ br->br_xino.xi_file = p->new;
++ }
++
++ out_pair:
++ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
++ if (p->new)
++ fput(p->new);
++ else
++ break;
++ kfree(fpair);
++ out:
++ return err;
++}
++
++void au_xino_clr(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++
++ au_xigen_clr(sb);
++ xino_clear_xib(sb);
++ xino_clear_br(sb);
++ sbinfo = au_sbi(sb);
++ /* lvalue, do not call au_mntflags() */
++ au_opt_clr(sbinfo->si_mntflags, XINO);
++}
++
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
++{
++ int err, skip;
++ struct dentry *parent, *cur_parent;
++ struct qstr *dname, *cur_name;
++ struct file *cur_xino;
++ struct inode *dir;
++ struct au_sbinfo *sbinfo;
++
++ err = 0;
++ sbinfo = au_sbi(sb);
++ parent = dget_parent(xino->file->f_dentry);
++ if (remount) {
++ skip = 0;
++ dname = &xino->file->f_dentry->d_name;
++ cur_xino = sbinfo->si_xib;
++ if (cur_xino) {
++ cur_parent = dget_parent(cur_xino->f_dentry);
++ cur_name = &cur_xino->f_dentry->d_name;
++ skip = (cur_parent == parent
++ && dname->len == cur_name->len
++ && !memcmp(dname->name, cur_name->name,
++ dname->len));
++ dput(cur_parent);
++ }
++ if (skip)
++ goto out;
++ }
++
++ au_opt_set(sbinfo->si_mntflags, XINO);
++ dir = parent->d_inode;
++ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
++ /* mnt_want_write() is unnecessary here */
++ err = au_xino_set_xib(sb, xino->file);
++ if (!err)
++ err = au_xigen_set(sb, xino->file);
++ if (!err)
++ err = au_xino_set_br(sb, xino->file);
++ mutex_unlock(&dir->i_mutex);
++ if (!err)
++ goto out; /* success */
++
++ /* reset all */
++ AuIOErr("failed creating xino(%d).\n", err);
++
++ out:
++ dput(parent);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a xinofile at the default place/path.
++ */
++struct file *au_xino_def(struct super_block *sb)
++{
++ struct file *file;
++ char *page, *p;
++ struct au_branch *br;
++ struct super_block *h_sb;
++ struct path path;
++ aufs_bindex_t bend, bindex, bwr;
++
++ br = NULL;
++ bend = au_sbend(sb);
++ bwr = -1;
++ for (bindex = 0; bindex <= bend; bindex++) {
++ br = au_sbr(sb, bindex);
++ if (au_br_writable(br->br_perm)
++ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
++ bwr = bindex;
++ break;
++ }
++ }
++
++ if (bwr >= 0) {
++ file = ERR_PTR(-ENOMEM);
++ page = __getname();
++ if (unlikely(!page))
++ goto out;
++ path.mnt = br->br_mnt;
++ path.dentry = au_h_dptr(sb->s_root, bwr);
++ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
++ file = (void *)p;
++ if (!IS_ERR(p)) {
++ strcat(p, "/" AUFS_XINO_FNAME);
++ AuDbg("%s\n", p);
++ file = au_xino_create(sb, p, /*silent*/0);
++ if (!IS_ERR(file))
++ au_xino_brid_set(sb, br->br_id);
++ }
++ __putname(page);
++ } else {
++ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
++ if (IS_ERR(file))
++ goto out;
++ h_sb = file->f_dentry->d_sb;
++ if (unlikely(au_test_fs_bad_xino(h_sb))) {
++ AuErr("xino doesn't support %s(%s)\n",
++ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
++ fput(file);
++ file = ERR_PTR(-EINVAL);
++ }
++ if (!IS_ERR(file))
++ au_xino_brid_set(sb, -1);
++ }
++
++ out:
++ return file;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_path(struct seq_file *seq, struct file *file)
++{
++ int err;
++
++ err = au_seq_path(seq, &file->f_path);
++ if (unlikely(err < 0))
++ goto out;
++
++ err = 0;
++#define Deleted "\\040(deleted)"
++ seq->count -= sizeof(Deleted) - 1;
++ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
++ sizeof(Deleted) - 1));
++#undef Deleted
++
++ out:
++ return err;
++}
+diff -Naur a/include/linux/aufs_type.h b/include/linux/aufs_type.h
+--- a/include/linux/aufs_type.h 1969-12-31 16:00:00.000000000 -0800
++++ b/include/linux/aufs_type.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#include <linux/ioctl.h>
++
++#define AUFS_VERSION "2-standalone.tree-29-20090622"
++
++/* todo? move this to linux-2.6.19/include/magic.h */
++#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++/* some environments treat 'char' as 'unsigned char' by default */
++typedef signed char aufs_bindex_t;
++#define AUFS_BRANCH_MAX 127
++#else
++typedef short aufs_bindex_t;
++#ifdef CONFIG_AUFS_BRANCH_MAX_511
++#define AUFS_BRANCH_MAX 511
++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
++#define AUFS_BRANCH_MAX 1023
++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
++#define AUFS_BRANCH_MAX 32767
++#endif
++#endif
++
++#ifdef __KERNEL__
++#ifndef AUFS_BRANCH_MAX
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif /* __KERNEL__ */
++
++/* ---------------------------------------------------------------------- */
++
++#define AUFS_NAME "aufs"
++#define AUFS_FSTYPE AUFS_NAME
++
++#define AUFS_ROOT_INO 2
++#define AUFS_FIRST_INO 11
++
++#define AUFS_WH_PFX ".wh."
++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
++#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
++#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
++#define AUFS_DIRWH_DEF 3
++#define AUFS_RDCACHE_DEF 10 /* seconds */
++#define AUFS_RDBLK_DEF 512 /* bytes */
++#define AUFS_RDHASH_DEF 32
++#define AUFS_WKQ_NAME AUFS_NAME "d"
++#define AUFS_NWKQ_DEF 4
++#define AUFS_MFS_SECOND_DEF 30 /* seconds */
++#define AUFS_PLINK_WARN 100 /* number of plinks */
++
++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
++#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
++#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
++
++/* doubly whiteouted */
++#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
++#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
++#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
++
++/* branch permission */
++#define AUFS_BRPERM_RW "rw"
++#define AUFS_BRPERM_RO "ro"
++#define AUFS_BRPERM_RR "rr"
++#define AUFS_BRPERM_WH "wh"
++#define AUFS_BRPERM_NLWH "nolwh"
++#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {
++ AuCtl_PLINK_MAINT,
++ AuCtl_PLINK_CLEAN
++};
++
++#define AuCtlType 'A'
++#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
++#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
++
++#endif /* __AUFS_TYPE_H__ */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch
new file mode 100644
index 0000000000..9a9b982fef
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch
@@ -0,0 +1,40 @@
+--- linux-omap-2.6/init/do_mounts.c 2008-11-23 01:22:52.000000000 -0800
++++ linux-omap-2.6/init/do_mounts.c 2008-11-23 02:17:58.000000000 -0800
+@@ -325,6 +325,37 @@
+
+ void __init mount_root(void)
+ {
++ int do_special = 0;
++ if (strcmp(root_device_name, "special") == 0)
++ do_special = 1;
++ //do_special = 1;
++
++ if (do_special) {
++ dev_t ROOT_DEV_RO;
++ dev_t ROOT_DEV_RW;
++
++ sys_mkdir("/root-ro", 0700);
++ ROOT_DEV_RO = name_to_dev_t("/dev/mtd4");
++ create_dev("/dev/root-ro", ROOT_DEV_RO);
++ if (sys_mount("/dev/root-ro", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0) {
++ ROOT_DEV_RO = name_to_dev_t("/dev/mmcblk0p2");
++ create_dev("/dev/root-ro2", ROOT_DEV_RO);
++ if (sys_mount("/dev/root-ro2", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0)
++ goto no_special;
++ }
++
++ sys_mkdir("/root-rw", 0700);
++ ROOT_DEV_RW = name_to_dev_t("/dev/mmcblk0p3");
++ create_dev("/dev/root-rw", ROOT_DEV_RW);
++ if (sys_mount("/dev/root-rw", "/root-rw", "ext3", MS_SILENT, NULL) != 0)
++ goto no_special;
++ sys_mount("none", "/root", "aufs", 0, "br:/root-rw:/root-ro=ro");
++ sys_chdir("/root");
++ return;
++ }
++
++no_special:
++
+ #ifdef CONFIG_ROOT_NFS
+ if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (mount_nfs_root())
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch
new file mode 100644
index 0000000000..035627ac79
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch
@@ -0,0 +1,221 @@
+From 1b3e7e2e095648f244a08b1459ff035bbdc99942 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Tue, 5 May 2009 23:33:00 -0700
+Subject: [PATCH] TWL BCI: Make charge current controllable and backup battery optional.
+
+This patch makes the charging current controllable via sysfs and also
+makes the backup battery optional. Also, if you don't care about the
+temperature readings, you can opt-out from having to supply a
+temperature lookup table.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/power/twl4030_bci_battery.c | 91 +++++++++++++++++++++++++++++------
+ include/linux/i2c/twl4030.h | 2 +
+ 2 files changed, 78 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index ddba62b..eab0933 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -125,6 +125,14 @@
+ /* BCIEDR3 */
+ #define VBATLVL_EDRRISIN 0x02
+
++/* BCIIREF1 */
++#define REG_BCIIREF1 0x027
++#define REG_BCIIREF2 0x028
++
++/* Key */
++#define KEY_IIREF 0xE7
++#define REG_BCIMFKEY 0x011
++
+ /* Step size and prescaler ratio */
+ #define TEMP_STEP_SIZE 147
+ #define TEMP_PSR_R 100
+@@ -142,9 +150,6 @@
+ #define ENABLE 1
+ #define DISABLE 1
+
+-/* Ptr to thermistor table */
+-int *therm_tbl;
+-
+ struct twl4030_bci_device_info {
+ struct device *dev;
+
+@@ -160,6 +165,8 @@ struct twl4030_bci_device_info {
+ struct power_supply bk_bat;
+ struct delayed_work twl4030_bci_monitor_work;
+ struct delayed_work twl4030_bk_bci_monitor_work;
++
++ struct twl4030_bci_platform_data *pdata;
+ };
+
+ static int usb_charger_flag;
+@@ -518,11 +525,15 @@ int twl4030charger_usb_en(int enable)
+ * Return battery temperature
+ * Or < 0 on failure.
+ */
+-static int twl4030battery_temperature(void)
++static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
+ {
+ u8 val;
+ int temp, curr, volt, res, ret;
+
++ /* Is a temperature table specified? */
++ if (!di->pdata->tblsize)
++ return 0;
++
+ /* Getting and calculating the thermistor voltage */
+ ret = read_bci_val(T2_BATTERY_TEMP);
+ if (ret < 0)
+@@ -543,7 +554,7 @@ static int twl4030battery_temperature(void)
+
+ /*calculating temperature*/
+ for (temp = 58; temp >= 0; temp--) {
+- int actual = therm_tbl[temp];
++ int actual = di->pdata->battery_tmp_tbl[temp];
+ if ((actual - res) >= 0)
+ break;
+ }
+@@ -772,13 +783,14 @@ static void twl4030_bk_bci_battery_work(struct work_struct *work)
+ struct twl4030_bci_device_info,
+ twl4030_bk_bci_monitor_work.work);
+
+- twl4030_bk_bci_battery_read_status(di);
++ if(!di->pdata->no_backup_battery)
++ twl4030_bk_bci_battery_read_status(di);
+ schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
+ }
+
+ static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
+ {
+- di->temp_C = twl4030battery_temperature();
++ di->temp_C = twl4030battery_temperature(di);
+ di->voltage_uV = twl4030battery_voltage();
+ di->current_uA = twl4030battery_current();
+ }
+@@ -819,6 +831,43 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ #define to_twl4030_bk_bci_device_info(x) container_of((x), \
+ struct twl4030_bci_device_info, bk_bat);
+
++static ssize_t
++show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++}
++
++static ssize_t
++set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long newCurrent;
++ int ret;
++
++ ret = strict_strtoul(buf, 10, &newCurrent);
++ if (ret)
++ return -EINVAL;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++ if (ret)
++ return ret;
++
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
++
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+@@ -912,8 +961,6 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ int irq;
+ int ret;
+
+- therm_tbl = pdata->battery_tmp_tbl;
+-
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+@@ -937,6 +984,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
+ di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
+ di->bk_bat.external_power_changed = NULL;
++ di->pdata = pdata;
+
+ twl4030charger_ac_en(ENABLE);
+ twl4030charger_usb_en(ENABLE);
+@@ -951,9 +999,12 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ goto temp_setup_fail;
+
+ /* enabling GPCH09 for read back battery voltage */
+- ret = twl4030backupbatt_voltage_setup();
+- if (ret)
+- goto voltage_setup_fail;
++ if(!di->pdata->no_backup_battery)
++ {
++ ret = twl4030backupbatt_voltage_setup();
++ if (ret)
++ goto voltage_setup_fail;
++ }
+
+ /* REVISIT do we need to request both IRQs ?? */
+
+@@ -988,9 +1039,18 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ twl4030_bci_battery_work);
+ schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
+
+- ret = power_supply_register(&pdev->dev, &di->bk_bat);
++ if(!pdata->no_backup_battery)
++ {
++ ret = power_supply_register(&pdev->dev, &di->bk_bat);
++ if (ret) {
++ dev_dbg(&pdev->dev, "failed to register backup battery\n");
++ goto bk_batt_failed;
++ }
++ }
++
++ ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
+ if (ret) {
+- dev_dbg(&pdev->dev, "failed to register backup battery\n");
++ dev_err(&pdev->dev, "failed to create sysfs entries\n");
+ goto bk_batt_failed;
+ }
+
+@@ -1001,7 +1061,8 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ return 0;
+
+ bk_batt_failed:
+- power_supply_unregister(&di->bat);
++ if(!pdata->no_backup_battery)
++ power_supply_unregister(&di->bat);
+ batt_failed:
+ free_irq(irq, di);
+ chg_irq_fail:
+diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
+index 87accda..a188b6c 100644
+--- a/include/linux/i2c/twl4030.h
++++ b/include/linux/i2c/twl4030.h
+@@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+ struct twl4030_bci_platform_data {
+ int *battery_tmp_tbl;
+ unsigned int tblsize;
++
++ bool no_backup_battery;
+ };
+
+ /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch
new file mode 100644
index 0000000000..ce5a98f69d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch
@@ -0,0 +1,246 @@
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index eab0933..d1220d7 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -15,6 +15,9 @@
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
++/* Boot with automatic charge */
++#define CHARGE_MODE 1
++
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -50,6 +53,7 @@
+ /* Boot BCI flag bits */
+ #define BCIAUTOWEN 0x020
+ #define CONFIG_DONE 0x010
++#define CVENAC 0x004
+ #define BCIAUTOUSB 0x002
+ #define BCIAUTOAC 0x001
+ #define BCIMSTAT_MASK 0x03F
+@@ -81,6 +85,11 @@
+ #define REG_BB_CFG 0x012
+ #define BBCHEN 0x010
+
++/* GPBR */
++#define REG_GPBR1 0x0c
++#define MADC_HFCLK_EN 0x80
++#define DEFAULT_MADC_CLK_EN 0x10
++
+ /* Power supply charge interrupt */
+ #define REG_PWR_ISR1 0x00
+ #define REG_PWR_IMR1 0x01
+@@ -129,8 +138,12 @@
+ #define REG_BCIIREF1 0x027
+ #define REG_BCIIREF2 0x028
+
++/* BCIMFTH1 */
++#define REG_BCIMFTH1 0x016
++
+ /* Key */
+ #define KEY_IIREF 0xE7
++#define KEY_FTH1 0xD2
+ #define REG_BCIMFKEY 0x011
+
+ /* Step size and prescaler ratio */
+@@ -432,15 +445,21 @@ static int twl4030battery_hw_presence_en(int enable)
+ /*
+ * Enable/Disable AC Charge funtionality.
+ */
+-static int twl4030charger_ac_en(int enable)
++static int twl4030charger_ac_en(int enable, int automatic)
+ {
+ int ret;
+
+ if (enable) {
+ /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
+- ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+- (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
+- REG_BOOT_BCI);
++ if(!automatic) {
++ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
++ (CONFIG_DONE | BCIAUTOWEN),
++ REG_BOOT_BCI);
++ } else {
++ ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
++ (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
++ REG_BOOT_BCI);
++ }
+ if (ret)
+ return ret;
+ } else {
+@@ -672,6 +691,9 @@ static int twl4030bci_status(void)
+ return ret;
+ }
+
++#ifdef DEBUG
++ printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
++#endif
+ return (int) (status & BCIMSTAT_MASK);
+ }
+
+@@ -720,14 +742,43 @@ static int twl4030backupbatt_voltage_setup(void)
+ */
+ static int twl4030battery_temp_setup(void)
+ {
+- int ret;
++#ifdef DEBUG
++ u8 i;
++#endif
++ u8 ret;
+
+ /* Enabling thermistor current */
+- ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
++ ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
+ REG_BCICTL1);
+ if (ret)
+ return ret;
+
++#ifdef DEBUG
++ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
++ printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
++ printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
++ printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
++ printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
++ printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
++
++ twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
++ printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
++
++ for(i = 0x0; i <= 0x32; i++)
++ {
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
++ printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
++ }
++#endif
++
+ return 0;
+ }
+
+@@ -743,7 +794,6 @@ static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
+ ret = twl4030_i2c_read_u8(mod_no, &val, reg);
+ if (ret)
+ return ret;
+-
+ /* Clearing all those bits to clear */
+ val &= ~(clear);
+
+@@ -834,7 +884,19 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ static ssize_t
+ show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++ u8 ctl;
++ int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
++
++ if (ctl & CGAIN)
++ ret |= 0x200;
++
++#ifdef DEBUG
++ /* Dump debug */
++ twl4030battery_temp_setup();
++#endif
++
++ return sprintf(buf, "%d\n", ret);
+ }
+
+ static ssize_t
+@@ -859,13 +921,45 @@ set_charge_current(struct device *dev, struct device_attribute *attr, const char
+ if (ret)
+ return ret;
+
+- ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+ if (ret)
+ return ret;
+
++ /* Set software-controlled charge */
++ twl4030charger_ac_en(ENABLE, 0);
++
++ /* Set CGAIN = 0 or 1 */
++ if(newCurrent > 511) {
++ u8 tmp;
++
++ /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
++ while(!ret) {
++ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++ ret = tmp & CGAIN;
++ if(!ret)
++ mdelay(50);
++ }
++ } else {
++ u8 tmp;
++
++ /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
++ while(!ret) {
++ clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
++ twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++ ret = !(tmp & CGAIN);
++ if(!ret)
++ mdelay(50);
++ }
++ }
++
++ /* Set automatic charge (CGAIN = 0/1 persists) */
++ twl4030charger_ac_en(ENABLE, 1);
++
+ return count;
+ }
+-
+ static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
+
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+@@ -986,7 +1080,10 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ di->bk_bat.external_power_changed = NULL;
+ di->pdata = pdata;
+
+- twl4030charger_ac_en(ENABLE);
++ /* Set up clocks */
++ twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
++
++ twl4030charger_ac_en(ENABLE, CHARGE_MODE);
+ twl4030charger_usb_en(ENABLE);
+ twl4030battery_hw_level_en(ENABLE);
+ twl4030battery_hw_presence_en(ENABLE);
+@@ -1058,6 +1155,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+ twl4030_bk_bci_battery_work);
+ schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
+
++ set_charge_current (NULL, NULL, "1023", 4);
+ return 0;
+
+ bk_batt_failed:
+@@ -1071,7 +1169,7 @@ chg_irq_fail:
+ batt_irq_fail:
+ voltage_setup_fail:
+ temp_setup_fail:
+- twl4030charger_ac_en(DISABLE);
++ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+ twl4030charger_usb_en(DISABLE);
+ twl4030battery_hw_level_en(DISABLE);
+ twl4030battery_hw_presence_en(DISABLE);
+@@ -1085,7 +1183,7 @@ static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+ int irq;
+
+- twl4030charger_ac_en(DISABLE);
++ twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+ twl4030charger_usb_en(DISABLE);
+ twl4030battery_hw_level_en(DISABLE);
+ twl4030battery_hw_presence_en(DISABLE);
+
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch
new file mode 100644
index 0000000000..fd629078ca
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch
@@ -0,0 +1,53 @@
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index bc6ef06..df7aa70 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -28,6 +28,7 @@
+
+ #define DRIVER_VERSION "1.0.0"
+
++#define BQ27x00_REG_MODE 0x00
+ #define BQ27x00_REG_TEMP 0x06
+ #define BQ27x00_REG_VOLT 0x08
+ #define BQ27x00_REG_RSOC 0x0B /* Relative State-of-Charge */
+@@ -65,6 +66,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
++ POWER_SUPPLY_PROP_ONLINE,
+ };
+
+ /*
+@@ -83,6 +85,22 @@ static int bq27x00_read(u8 reg, int *rt_value, int b_single,
+ }
+
+ /*
++ * Return the GPIO status (0 or 1)
++ * Or < 0 if something fails.
++ */
++static int bq27x00_gpio(struct bq27x00_device_info *di)
++{
++ int ret;
++ int gpio = 0;
++
++ ret = bq27x00_read(BQ27x00_REG_MODE, &gpio, 0, di);
++ if (ret)
++ return ret;
++
++ return (gpio & 0x40) >> 6;
++}
++
++/*
+ * Return the battery temperature in Celcius degrees
+ * Or < 0 if something fails.
+ */
+@@ -184,6 +202,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = bq27x00_battery_temperature(di);
+ break;
++ case POWER_SUPPLY_PROP_ONLINE:
++ val->intval = bq27x00_gpio(di);
++ break;
+ default:
+ return -EINVAL;
+ }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch
new file mode 100644
index 0000000000..eb7c8c9699
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch
@@ -0,0 +1,39 @@
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -93,7 +93,6 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading temperature\n");
+ return ret;
+ }
+
+@@ -111,7 +110,6 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading voltage\n");
+ return ret;
+ }
+
+@@ -131,12 +129,10 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
+ if (ret) {
+- dev_err(di->dev, "error reading current\n");
+ return 0;
+ }
+ ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+ if (ret < 0) {
+- dev_err(di->dev, "error reading flags\n");
+ return 0;
+ }
+ if ((flags & (1 << 7)) != 0) {
+@@ -157,7 +153,6 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
+
+ ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di);
+ if (ret) {
+- dev_err(di->dev, "error reading relative State-of-Charge\n");
+ return ret;
+ }
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch
new file mode 100644
index 0000000000..b2b920037e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch
@@ -0,0 +1,35 @@
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 4f7f040..ccd8973 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
++
++config SND_OMAP_SOC_OMAP3_BEAGLE
++ tristate "SoC Audio support for OMAP3 Beagle"
++ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE
++ select SND_OMAP_SOC_MCBSP
++ select SND_SOC_TWL4030
++ help
++ Say Y if you want to add support for SoC audio on the Beagleboard.
++
++
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index 76fedd9..0c9e4ac 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o
+ snd-soc-omap2evm-objs := omap2evm.o
+ snd-soc-sdp3430-objs := sdp3430.o
+ snd-soc-omap3pandora-objs := omap3pandora.o
++snd-soc-omap3beagle-objs := omap3beagle.o
+
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+@@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+ obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
+ obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
++obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c
new file mode 100644
index 0000000000..c7867bef2f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c
@@ -0,0 +1,744 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3beagle.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/mcspi.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/mma7455l.h>
+
+#include <mach/dmtimer.h>
+#include <linux/backlight.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/omapfb.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/board.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/gpmc.h>
+#include <mach/nand.h>
+#include <mach/mux.h>
+#include <mach/omap-pm.h>
+#include <mach/clock.h>
+#include <mach/display.h>
+
+#include "twl4030-generic-scripts.h"
+#include "mmc-twl4030.h"
+#include "pm.h"
+#include "omap3-opp.h"
+
+
+#define GPMC_CS0_BASE 0x60
+#define GPMC_CS_SIZE 0x30
+
+#define NAND_BLOCK_SIZE SZ_128K
+
+#define OMAP3_AC_GPIO 136 //Int1 DRDY
+#define OMAP3_TS_GPIO 162
+#define TB_BL_PWM_TIMER 9
+#define TB_KILL_POWER_GPIO 168
+
+static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader",
+ .offset = 0,
+ .size = 4 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 15 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot Env",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
+ .size = 1 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "Kernel",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 32 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "File System",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct omap_nand_platform_data omap3beagle_nand_data = {
+ .options = NAND_BUSWIDTH_16,
+ .parts = omap3beagle_nand_partitions,
+ .nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions),
+ .dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .nand_setup = NULL,
+ .dev_ready = NULL,
+};
+
+static struct resource omap3beagle_nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device omap3beagle_nand_device = {
+ .name = "omap2-nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &omap3beagle_nand_data,
+ },
+ .num_resources = 1,
+ .resource = &omap3beagle_nand_resource,
+};
+
+#include "sdram-micron-mt46h32m32lf-6.h"
+
+static struct omap_uart_config omap3_beagle_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct twl4030_usb_data beagle_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+ {
+ .mmc = 1,
+ .wires = 8,
+ .gpio_wp = 29,
+ },
+ {} /* Terminator */
+};
+
+static struct regulator_consumer_supply beagle_vmmc1_supply = {
+ .supply = "vmmc",
+};
+
+static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+};
+
+static struct gpio_led gpio_leds[];
+
+static int beagle_twl_gpio_setup(struct device *dev,
+ unsigned gpio, unsigned ngpio)
+{
+ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+ omap_cfg_reg(AH8_34XX_GPIO29);
+ mmc[0].gpio_cd = gpio + 0;
+ twl4030_mmc_init(mmc);
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+ * power switch and overcurrent detect
+ */
+
+#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+ gpio_request(gpio + 1, "EHCI_nOC");
+ gpio_direction_input(gpio + 1);
+
+ /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+ gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+ return 0;
+}
+
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+ .use_leds = true,
+ .pullups = BIT(1),
+ .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+ | BIT(15) | BIT(16) | BIT(17),
+ .setup = beagle_twl_gpio_setup,
+};
+
+static struct platform_device omap3_beagle_lcd_device = {
+ .name = "omap3beagle_lcd",
+ .id = -1,
+};
+
+static struct regulator_consumer_supply beagle_vdac_supply = {
+ .supply = "vdac",
+ .dev = &omap3_beagle_lcd_device.dev,
+};
+
+static struct regulator_consumer_supply beagle_vdvi_supply = {
+ .supply = "vdvi",
+ .dev = &omap3_beagle_lcd_device.dev,
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data beagle_vmmc1 = {
+ .constraints = {
+ .min_uV = 1850000,
+ .max_uV = 3150000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vmmc1_supply,
+};
+
+/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 3000000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data beagle_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data beagle_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vdvi_supply,
+};
+
+static const struct twl4030_resconfig beagle_resconfig[] = {
+ /* disable regulators that u-boot left enabled; the
+ * devices' drivers should be managing these.
+ */
+ { .resource = RES_VAUX3, }, /* not even connected! */
+ { .resource = RES_VMMC1, },
+ { .resource = RES_VSIM, },
+ { .resource = RES_VPLL2, },
+ { .resource = RES_VDAC, },
+ { .resource = RES_VUSB_1V5, },
+ { .resource = RES_VUSB_1V8, },
+ { .resource = RES_VUSB_3V1, },
+ { 0, },
+};
+
+static struct twl4030_power_data beagle_power_data = {
+ .resource_config = beagle_resconfig,
+ /* REVISIT can't use GENERIC3430_T2SCRIPTS_DATA;
+ * among other things, it makes reboot fail.
+ */
+};
+
+static struct twl4030_bci_platform_data touchbook_bci_data = {
+ .tblsize = 0,
+ .no_backup_battery = 1,
+};
+
+static struct twl4030_platform_data beagle_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .usb = &beagle_usb_data,
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
+
+ /* TouchBook BCI */
+ .bci = &touchbook_bci_data,
+};
+
+static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .irq = INT_34XX_SYS_NIRQ,
+ .platform_data = &beagle_twldata,
+ },
+};
+
+static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("bq27200", 0x55),
+ },
+};
+
+static int __init omap3_beagle_i2c_init(void)
+{
+ /* Standard BeagleBoard bus */
+ omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+ ARRAY_SIZE(beagle_i2c_boardinfo));
+
+ /* TouchBook keyboard bus */
+ omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
+ ARRAY_SIZE(touchBook_i2c_boardinfo));
+
+ return 0;
+}
+
+static void __init omap3_ads7846_init(void)
+{
+ if (gpio_request(OMAP3_TS_GPIO, "ads7846_pen_down")) {
+ printk(KERN_ERR "Failed to request GPIO %d for "
+ "ads7846 pen down IRQ\n", OMAP3_TS_GPIO);
+ return;
+ }
+
+ gpio_direction_input(OMAP3_TS_GPIO);
+ omap_set_gpio_debounce(OMAP3_TS_GPIO, 1);
+ omap_set_gpio_debounce_time(OMAP3_TS_GPIO, 0xa);
+}
+
+static struct ads7846_platform_data ads7846_config = {
+ .x_min = 100,
+ .y_min = 265,
+ .x_max = 3950,
+ .y_max = 3750,
+ .x_plate_ohms = 40,
+ .pressure_max = 255,
+ .debounce_max = 10,
+ .debounce_tol = 5,
+ .debounce_rep = 1,
+ .gpio_pendown = OMAP3_TS_GPIO,
+ .keep_vref_on = 1,
+};
+
+static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_ads7846_spi_board_info[] __initdata = {
+ {
+ .modalias = "ads7846",
+ .bus_num = 4,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ .controller_data = &ads7846_mcspi_config, //(void *) 161,
+ .irq = OMAP_GPIO_IRQ(OMAP3_TS_GPIO),
+ .platform_data = &ads7846_config,
+ }
+};
+
+static void __init omap3_beagle_init_irq(void)
+{
+ omap2_init_common_hw(mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
+ omap3_dsp_rate_table, omap3_l3_rate_table);
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "beagleboard::usr0",
+ .default_trigger = "heartbeat",
+ .gpio = 150,
+ },
+ {
+ .name = "beagleboard::usr1",
+ .default_trigger = "mmc0",
+ .gpio = 149,
+ },
+ {
+ .name = "beagleboard::pmu_stat",
+ .gpio = -EINVAL, /* gets replaced */
+ .active_low = true,
+ },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_led_info,
+ },
+};
+
+static struct gpio_keys_button gpio_buttons[] = {
+ {
+ .code = BTN_EXTRA,
+ .gpio = 7,
+ .desc = "user",
+ .wakeup = 1,
+ },
+ {
+ .code = KEY_POWER,
+ .gpio = 183,
+ .desc = "power",
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device keys_gpio = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* DSS */
+
+static int beagle_enable_dvi(struct omap_display *display)
+{
+ if (display->hw_config.panel_reset_gpio != -1)
+ gpio_set_value(display->hw_config.panel_reset_gpio, 1);
+
+ return 0;
+}
+
+static void beagle_disable_dvi(struct omap_display *display)
+{
+ if (display->hw_config.panel_reset_gpio != -1)
+ gpio_set_value(display->hw_config.panel_reset_gpio, 0);
+}
+
+static struct omap_dss_display_config beagle_display_data_dvi = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "dvi",
+ .panel_name = "panel-generic",
+ .u.dpi.data_lines = 24,
+ .panel_reset_gpio = 176,
+ .panel_enable = beagle_enable_dvi,
+ .panel_disable = beagle_disable_dvi,
+};
+
+
+static int beagle_panel_enable_tv(struct omap_display *display)
+{
+#define ENABLE_VDAC_DEDICATED 0x03
+#define ENABLE_VDAC_DEV_GRP 0x20
+
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ ENABLE_VDAC_DEDICATED,
+ TWL4030_VDAC_DEDICATED);
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+
+ return 0;
+}
+
+static void beagle_panel_disable_tv(struct omap_display *display)
+{
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+ TWL4030_VDAC_DEDICATED);
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+ TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_dss_display_config beagle_display_data_tv = {
+ .type = OMAP_DISPLAY_TYPE_VENC,
+ .name = "tv",
+ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+ .panel_enable = beagle_panel_enable_tv,
+ .panel_disable = beagle_panel_disable_tv,
+};
+
+static struct omap_dss_board_info beagle_dss_data = {
+ .num_displays = 2,
+ .displays = {
+ &beagle_display_data_dvi,
+ &beagle_display_data_tv,
+ }
+};
+
+static struct platform_device beagle_dss_device = {
+ .name = "omapdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &beagle_dss_data,
+ },
+};
+
+static void __init beagle_display_init(void)
+{
+ int r;
+
+ r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+ if (r < 0) {
+ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+ return;
+ }
+
+ gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+}
+
+static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_beagle_uart_config },
+};
+
+static struct platform_device *omap3_beagle_devices[] __initdata = {
+ &beagle_dss_device,
+ &leds_gpio,
+ &keys_gpio,
+};
+
+static void __init omap3beagle_flash_init(void)
+{
+ u8 cs = 0;
+ u8 nandcs = GPMC_CS_NUM + 1;
+
+ u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+ /* find out the chip-select on which NAND exists */
+ while (cs < GPMC_CS_NUM) {
+ u32 ret = 0;
+ ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+ if ((ret & 0xC00) == 0x800) {
+ printk(KERN_INFO "Found NAND on CS%d\n", cs);
+ if (nandcs > GPMC_CS_NUM)
+ nandcs = cs;
+ }
+ cs++;
+ }
+
+ if (nandcs > GPMC_CS_NUM) {
+ printk(KERN_INFO "NAND: Unable to find configuration "
+ "in GPMC\n ");
+ return;
+ }
+
+ if (nandcs < GPMC_CS_NUM) {
+ omap3beagle_nand_data.cs = nandcs;
+ omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
+ (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
+ omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
+
+ printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+ if (platform_device_register(&omap3beagle_nand_device) < 0)
+ printk(KERN_ERR "Unable to register NAND device\n");
+ }
+}
+
+static void __init omap3_mma7455l_init(void)
+{
+ int ret;
+
+ ret = gpio_request(OMAP3_AC_GPIO, "mma7455l");
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to request GPIO %d for mma7455l IRQ\n", OMAP3_AC_GPIO);
+ return;
+ }
+
+ gpio_direction_input(OMAP3_AC_GPIO);
+}
+
+static struct mma7455l_platform_data mma7455l_config = {
+ .calibration_x = -4, //26 for Beagleboard
+ .calibration_y = 28, //44 for Beagleboard
+ .calibration_z = -28, //26 for Beagleboard
+};
+
+static struct omap2_mcspi_device_config mma7455l_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_mma7455l_spi_board_info[] __initdata = {
+ {
+ .modalias = "mma7455l",
+ .bus_num = 3,
+ .chip_select = 0,
+ .max_speed_hz = 200000,
+ .irq = OMAP_GPIO_IRQ(OMAP3_AC_GPIO),
+ .controller_data = &mma7455l_mcspi_config, //(void *) 135,
+ .platform_data = &mma7455l_config,
+ }
+};
+
+static int touchbook_backlight_brightness = 50;
+static struct omap_dm_timer *touchbook_backlight_pwm;
+
+static int touchbook_backlight_read(struct backlight_device *bd)
+{
+ return touchbook_backlight_brightness;
+}
+
+static int touchbook_backlight_update(struct backlight_device *bd)
+{
+ int value = bd->props.brightness;
+ touchbook_backlight_brightness = value;
+
+ /* Frequency calculation:
+ - For 200Hz PWM, you want to load -164 (=> -32768Hz / 200Hz).
+ - Minimum duty cycle for the backlight is 15%.
+ - You have (164*0.85) => ~140 levels of brightness.
+ */
+
+ /* Convert from 0-100 range to 0-140 range */
+ value = (value * 14) / 10 / 2;
+
+ /* For maximum brightness, just stop the timer... */
+ if(value != bd->props.max_brightness)
+ {
+ omap_dm_timer_set_load(touchbook_backlight_pwm, 1, -164);
+ omap_dm_timer_set_match(touchbook_backlight_pwm, 1, -24 - value);
+ omap_dm_timer_write_counter(touchbook_backlight_pwm, -1);
+ //omap_dm_timer_stop(touchbook_backlight_pwm);
+ omap_dm_timer_start(touchbook_backlight_pwm);
+ }
+ else
+ omap_dm_timer_stop(touchbook_backlight_pwm);
+
+
+ return 0;
+}
+
+static struct backlight_ops touchbook_backlight_properties = {
+ .get_brightness = touchbook_backlight_read,
+ .update_status = touchbook_backlight_update,
+};
+
+static void __init omap3_touchbook_backlight_init(void)
+{
+ static struct backlight_device *bd;
+ bd = backlight_device_register("touchbook", NULL, NULL, &touchbook_backlight_properties);
+
+ if(bd)
+ {
+ touchbook_backlight_pwm = omap_dm_timer_request_specific(TB_BL_PWM_TIMER);
+ omap_dm_timer_enable(touchbook_backlight_pwm);
+ omap_dm_timer_set_source(touchbook_backlight_pwm, OMAP_TIMER_SRC_32_KHZ);
+ omap_dm_timer_set_pwm(touchbook_backlight_pwm, 1, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+
+ bd->props.max_brightness = 100;
+ bd->props.brightness = touchbook_backlight_brightness;
+ }
+
+ touchbook_backlight_update(bd);
+}
+
+static void omap3_touchbook_poweroff(void)
+{
+ int r;
+
+ r = gpio_request(TB_KILL_POWER_GPIO, "DVI reset");
+ if (r < 0) {
+ printk(KERN_ERR "Unable to get kill power GPIO\n");
+ return;
+ }
+
+ gpio_direction_output(TB_KILL_POWER_GPIO, 0);
+}
+
+static void __init omap3_beagle_init(void)
+{
+ pm_power_off = omap3_touchbook_poweroff;
+
+ omap3_beagle_i2c_init();
+ platform_add_devices(omap3_beagle_devices,
+ ARRAY_SIZE(omap3_beagle_devices));
+ omap_board_config = omap3_beagle_config;
+ omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+ omap_serial_init();
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+
+ omap3beagle_flash_init();
+ beagle_display_init();
+ omap3_touchbook_backlight_init();
+
+ /* Touch Book */
+ spi_register_board_info(omap3_ads7846_spi_board_info, ARRAY_SIZE(omap3_ads7846_spi_board_info));
+ spi_register_board_info(omap3_mma7455l_spi_board_info, ARRAY_SIZE(omap3_mma7455l_spi_board_info));
+
+ omap3_ads7846_init();
+ omap3_mma7455l_init();
+
+ usb_musb_init();
+ usb_ehci_init();
+}
+
+static void __init omap3_beagle_map_io(void)
+{
+ omap2_set_globals_343x();
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP3_BEAGLE, "OMAP3 Touch Book")
+ /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap3_beagle_map_io,
+ .init_irq = omap3_beagle_init_irq,
+ .init_machine = omap3_beagle_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch
new file mode 100644
index 0000000000..4be59a4212
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch
@@ -0,0 +1,11 @@
+--- a/arch/arm/mach-omap2/pm34xx.c 2009-07-18 10:13:43.000000000 -0700
++++ b/arch/arm/mach-omap2/pm34xx.c 2009-07-18 10:13:54.000000000 -0700
+@@ -625,7 +625,7 @@
+ struct power_state *pwrst, *tmp;
+ int ret;
+
+- printk(KERN_ERR "Power Management for TI OMAP3.\n");
++// printk(KERN_ERR "Power Management for TI OMAP3.\n");
+
+ /* XXX prcm_setup_regs needs to be before enabling hw
+ * supervised mode for powerdomains */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig
new file mode 100644
index 0000000000..e628b28d28
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig
@@ -0,0 +1,2747 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri Sep 25 11:38:50 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=m
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+# CONFIG_OMAP_PM_NOOP is not set
+CONFIG_OMAP_PM_SRF=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=6
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_MMA7455L=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=y
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_TWL4030_BCI_BATTERY=y
+CONFIG_BATTERY_BQ27x00=y
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_VIDEO_OMAP3=m
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+CONFIG_MPU_BRIDGE=m
+# CONFIG_BRIDGE_DVFS is not set
+CONFIG_BRIDGE_MEMPOOL_SIZE=0x600000
+# CONFIG_BRIDGE_DEBUG is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+# CONFIG_AUFS_HINOTIFY is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+CONFIG_AUFS_DEBUG=y
+CONFIG_AUFS_MAGIC_SYSRQ=y
+CONFIG_AUFS_BDEV_LOOP=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig
new file mode 100644
index 0000000000..1aa7cf57ac
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig
@@ -0,0 +1,2701 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri May 29 14:47:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OMAP24XX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch
new file mode 100644
index 0000000000..621ae93d3b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch
@@ -0,0 +1,66715 @@
+From ea83ad971e877ef8e9b1304f2678469c2fc74c67 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sun, 26 Apr 2009 18:58:30 -0700
+Subject: [PATCH] Merge in tidspbridge from git://gitorious.org/tidspbridge/mainline.git
+ revisions fe30e75..20f5ca.
+
+Made a few changes so this compiles clean against a 2.6.29 non-PM
+tree.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ Documentation/tidspbridge/README | 70 +
+ arch/arm/Kconfig | 2 +
+ arch/arm/mach-omap2/Makefile | 2 +
+ arch/arm/mach-omap2/dspbridge.c | 74 +
+ arch/arm/mach-omap2/io.c | 3 +
+ arch/arm/plat-omap/devices.c | 28 +
+ arch/arm/plat-omap/include/dspbridge/_chnl_sm.h | 212 ++
+ arch/arm/plat-omap/include/dspbridge/_dcd.h | 187 +
+ arch/arm/plat-omap/include/dspbridge/brddefs.h | 54 +
+ arch/arm/plat-omap/include/dspbridge/cfg.h | 339 ++
+ arch/arm/plat-omap/include/dspbridge/cfgdefs.h | 126 +
+ arch/arm/plat-omap/include/dspbridge/chnl.h | 170 +
+ arch/arm/plat-omap/include/dspbridge/chnl_sm.h | 168 +
+ arch/arm/plat-omap/include/dspbridge/chnldefs.h | 92 +
+ arch/arm/plat-omap/include/dspbridge/chnlpriv.h | 136 +
+ arch/arm/plat-omap/include/dspbridge/clk.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/cmm.h | 420 +++
+ arch/arm/plat-omap/include/dspbridge/cmmdefs.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/cod.h | 433 +++
+ arch/arm/plat-omap/include/dspbridge/csl.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/dbc.h | 66 +
+ arch/arm/plat-omap/include/dspbridge/dbdcd.h | 388 +++
+ arch/arm/plat-omap/include/dspbridge/dbdcddef.h | 94 +
+ arch/arm/plat-omap/include/dspbridge/dbdefs.h | 580 ++++
+ arch/arm/plat-omap/include/dspbridge/dbg.h | 110 +
+ arch/arm/plat-omap/include/dspbridge/dbl.h | 354 ++
+ arch/arm/plat-omap/include/dspbridge/dbldefs.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/dbll.h | 70 +
+ arch/arm/plat-omap/include/dspbridge/dblldefs.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/dbof.h | 117 +
+ arch/arm/plat-omap/include/dspbridge/dbreg.h | 113 +
+ arch/arm/plat-omap/include/dspbridge/dbtype.h | 103 +
+ arch/arm/plat-omap/include/dspbridge/dehdefs.h | 42 +
+ arch/arm/plat-omap/include/dspbridge/dev.h | 785 +++++
+ arch/arm/plat-omap/include/dspbridge/devdefs.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/disp.h | 236 ++
+ arch/arm/plat-omap/include/dspbridge/dispdefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/dmm.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/dpc.h | 167 +
+ arch/arm/plat-omap/include/dspbridge/drv.h | 449 +++
+ arch/arm/plat-omap/include/dspbridge/drvdefs.h | 34 +
+ arch/arm/plat-omap/include/dspbridge/dspdrv.h | 106 +
+ .../plat-omap/include/dspbridge/dynamic_loader.h | 505 +++
+ arch/arm/plat-omap/include/dspbridge/errbase.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/gb.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/getsection.h | 118 +
+ arch/arm/plat-omap/include/dspbridge/gh.h | 37 +
+ arch/arm/plat-omap/include/dspbridge/gs.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/gt.h | 315 ++
+ arch/arm/plat-omap/include/dspbridge/host_os.h | 96 +
+ arch/arm/plat-omap/include/dspbridge/io.h | 132 +
+ arch/arm/plat-omap/include/dspbridge/io_sm.h | 335 ++
+ arch/arm/plat-omap/include/dspbridge/iodefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/kfile.h | 216 ++
+ arch/arm/plat-omap/include/dspbridge/ldr.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/list.h | 296 ++
+ arch/arm/plat-omap/include/dspbridge/mbx_sh.h | 213 ++
+ arch/arm/plat-omap/include/dspbridge/mem.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/memdefs.h | 52 +
+ arch/arm/plat-omap/include/dspbridge/mgr.h | 234 ++
+ arch/arm/plat-omap/include/dspbridge/mgrpriv.h | 55 +
+ arch/arm/plat-omap/include/dspbridge/msg.h | 106 +
+ arch/arm/plat-omap/include/dspbridge/msgdefs.h | 43 +
+ arch/arm/plat-omap/include/dspbridge/nldr.h | 81 +
+ arch/arm/plat-omap/include/dspbridge/nldrdefs.h | 307 ++
+ arch/arm/plat-omap/include/dspbridge/node.h | 619 ++++
+ arch/arm/plat-omap/include/dspbridge/nodedefs.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/nodepriv.h | 202 ++
+ arch/arm/plat-omap/include/dspbridge/ntfy.h | 146 +
+ arch/arm/plat-omap/include/dspbridge/proc.h | 648 ++++
+ arch/arm/plat-omap/include/dspbridge/procpriv.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/pwr.h | 129 +
+ arch/arm/plat-omap/include/dspbridge/pwr_sh.h | 41 +
+ arch/arm/plat-omap/include/dspbridge/reg.h | 257 ++
+ .../plat-omap/include/dspbridge/resourcecleanup.h | 88 +
+ arch/arm/plat-omap/include/dspbridge/rmm.h | 199 ++
+ arch/arm/plat-omap/include/dspbridge/rms_sh.h | 125 +
+ arch/arm/plat-omap/include/dspbridge/rmstypes.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/services.h | 63 +
+ arch/arm/plat-omap/include/dspbridge/std.h | 143 +
+ arch/arm/plat-omap/include/dspbridge/strm.h | 441 +++
+ arch/arm/plat-omap/include/dspbridge/strmdefs.h | 57 +
+ arch/arm/plat-omap/include/dspbridge/sync.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/util.h | 122 +
+ arch/arm/plat-omap/include/dspbridge/utildefs.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/uuidutil.h | 74 +
+ arch/arm/plat-omap/include/dspbridge/wcd.h | 61 +
+ arch/arm/plat-omap/include/dspbridge/wcdioctl.h | 519 +++
+ arch/arm/plat-omap/include/dspbridge/wmd.h | 1193 +++++++
+ arch/arm/plat-omap/include/dspbridge/wmdchnl.h | 90 +
+ arch/arm/plat-omap/include/dspbridge/wmddeh.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/wmdio.h | 53 +
+ arch/arm/plat-omap/include/dspbridge/wmdioctl.h | 91 +
+ arch/arm/plat-omap/include/dspbridge/wmdmsg.h | 70 +
+ drivers/Makefile | 1 +
+ drivers/dsp/bridge/Kbuild | 39 +
+ drivers/dsp/bridge/Kconfig | 36 +
+ drivers/dsp/bridge/dynload/cload.c | 1854 ++++++++++
+ drivers/dsp/bridge/dynload/dlclasses_hdr.h | 41 +
+ drivers/dsp/bridge/dynload/dload_internal.h | 237 ++
+ drivers/dsp/bridge/dynload/doff.h | 347 ++
+ drivers/dsp/bridge/dynload/getsection.c | 412 +++
+ drivers/dsp/bridge/dynload/header.h | 59 +
+ drivers/dsp/bridge/dynload/module_list.h | 161 +
+ drivers/dsp/bridge/dynload/params.h | 231 ++
+ drivers/dsp/bridge/dynload/reloc.c | 425 +++
+ drivers/dsp/bridge/dynload/reloc_table.h | 102 +
+ drivers/dsp/bridge/dynload/reloc_table_c6000.c | 258 ++
+ drivers/dsp/bridge/gen/_gt_para.c | 107 +
+ drivers/dsp/bridge/gen/gb.c | 182 +
+ drivers/dsp/bridge/gen/gh.c | 191 ++
+ drivers/dsp/bridge/gen/gs.c | 108 +
+ drivers/dsp/bridge/gen/gt.c | 348 ++
+ drivers/dsp/bridge/gen/uuidutil.c | 238 ++
+ drivers/dsp/bridge/hw/EasiGlobal.h | 42 +
+ drivers/dsp/bridge/hw/GlobalTypes.h | 325 ++
+ drivers/dsp/bridge/hw/IPIAccInt.h | 41 +
+ drivers/dsp/bridge/hw/IVA2RegAcM.h | 28 +
+ drivers/dsp/bridge/hw/MLBAccInt.h | 132 +
+ drivers/dsp/bridge/hw/MLBRegAcM.h | 200 ++
+ drivers/dsp/bridge/hw/MMUAccInt.h | 76 +
+ drivers/dsp/bridge/hw/MMURegAcM.h | 253 ++
+ drivers/dsp/bridge/hw/PRCMAccInt.h | 300 ++
+ drivers/dsp/bridge/hw/PRCMRegAcM.h | 669 ++++
+ drivers/dsp/bridge/hw/hw_defs.h | 73 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.c | 55 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.h | 48 +
+ drivers/dsp/bridge/hw/hw_mbox.c | 244 ++
+ drivers/dsp/bridge/hw/hw_mbox.h | 323 ++
+ drivers/dsp/bridge/hw/hw_mmu.c | 598 ++++
+ drivers/dsp/bridge/hw/hw_mmu.h | 177 +
+ drivers/dsp/bridge/hw/hw_prcm.c | 167 +
+ drivers/dsp/bridge/hw/hw_prcm.h | 168 +
+ drivers/dsp/bridge/pmgr/chnl.c | 260 ++
+ drivers/dsp/bridge/pmgr/chnlobj.h | 71 +
+ drivers/dsp/bridge/pmgr/cmm.c | 1291 +++++++
+ drivers/dsp/bridge/pmgr/cod.c | 683 ++++
+ drivers/dsp/bridge/pmgr/dbl.c | 1385 ++++++++
+ drivers/dsp/bridge/pmgr/dbll.c | 1564 +++++++++
+ drivers/dsp/bridge/pmgr/dev.c | 1476 ++++++++
+ drivers/dsp/bridge/pmgr/dmm.c | 692 ++++
+ drivers/dsp/bridge/pmgr/io.c | 205 ++
+ drivers/dsp/bridge/pmgr/ioobj.h | 52 +
+ drivers/dsp/bridge/pmgr/msg.c | 173 +
+ drivers/dsp/bridge/pmgr/msgobj.h | 52 +
+ drivers/dsp/bridge/pmgr/wcd.c | 1647 +++++++++
+ drivers/dsp/bridge/rmgr/dbdcd.c | 1573 +++++++++
+ drivers/dsp/bridge/rmgr/disp.c | 916 +++++
+ drivers/dsp/bridge/rmgr/drv.c | 1893 +++++++++++
+ drivers/dsp/bridge/rmgr/drv_interface.c | 777 +++++
+ drivers/dsp/bridge/rmgr/drv_interface.h | 40 +
+ drivers/dsp/bridge/rmgr/dspdrv.c | 276 ++
+ drivers/dsp/bridge/rmgr/mgr.c | 491 +++
+ drivers/dsp/bridge/rmgr/nldr.c | 1967 +++++++++++
+ drivers/dsp/bridge/rmgr/node.c | 3544 ++++++++++++++++++++
+ drivers/dsp/bridge/rmgr/proc.c | 1985 +++++++++++
+ drivers/dsp/bridge/rmgr/pwr.c | 184 +
+ drivers/dsp/bridge/rmgr/rmm.c | 604 ++++
+ drivers/dsp/bridge/rmgr/strm.c | 1066 ++++++
+ drivers/dsp/bridge/services/cfg.c | 483 +++
+ drivers/dsp/bridge/services/clk.c | 375 +++
+ drivers/dsp/bridge/services/csl.c | 173 +
+ drivers/dsp/bridge/services/dbg.c | 119 +
+ drivers/dsp/bridge/services/dpc.c | 274 ++
+ drivers/dsp/bridge/services/kfile.c | 338 ++
+ drivers/dsp/bridge/services/list.c | 285 ++
+ drivers/dsp/bridge/services/mem.c | 599 ++++
+ drivers/dsp/bridge/services/ntfy.c | 329 ++
+ drivers/dsp/bridge/services/reg.c | 196 ++
+ drivers/dsp/bridge/services/regsup.c | 368 ++
+ drivers/dsp/bridge/services/regsup.h | 58 +
+ drivers/dsp/bridge/services/services.c | 193 ++
+ drivers/dsp/bridge/services/sync.c | 602 ++++
+ drivers/dsp/bridge/wmd/_cmm.h | 59 +
+ drivers/dsp/bridge/wmd/_deh.h | 46 +
+ drivers/dsp/bridge/wmd/_msg_sm.h | 158 +
+ drivers/dsp/bridge/wmd/_tiomap.h | 384 +++
+ drivers/dsp/bridge/wmd/_tiomap_mmu.h | 53 +
+ drivers/dsp/bridge/wmd/_tiomap_pwr.h | 102 +
+ drivers/dsp/bridge/wmd/_tiomap_util.h | 46 +
+ drivers/dsp/bridge/wmd/chnl_sm.c | 1100 ++++++
+ drivers/dsp/bridge/wmd/io_sm.c | 2011 +++++++++++
+ drivers/dsp/bridge/wmd/mmu_fault.c | 172 +
+ drivers/dsp/bridge/wmd/mmu_fault.h | 45 +
+ drivers/dsp/bridge/wmd/msg_sm.c | 643 ++++
+ drivers/dsp/bridge/wmd/tiomap3430.c | 2149 ++++++++++++
+ drivers/dsp/bridge/wmd/tiomap3430_pwr.c | 731 ++++
+ drivers/dsp/bridge/wmd/tiomap_io.c | 427 +++
+ drivers/dsp/bridge/wmd/tiomap_io.h | 112 +
+ drivers/dsp/bridge/wmd/tiomap_sm.c | 195 ++
+ drivers/dsp/bridge/wmd/ue_deh.c | 329 ++
+ 191 files changed, 65137 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/tidspbridge/README
+ create mode 100644 arch/arm/mach-omap2/dspbridge.c
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_dcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/brddefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/clk.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cod.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/csl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbll.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dblldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbof.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbreg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbtype.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dehdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dev.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/devdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/disp.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dispdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dpc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drvdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dspdrv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/errbase.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gb.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/getsection.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gt.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/host_os.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/iodefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/kfile.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/list.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mem.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/memdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/node.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodedefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodepriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ntfy.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/proc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/procpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/reg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rms_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmstypes.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/services.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/std.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/sync.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/util.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/utildefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/uuidutil.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmddeh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdio.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+ create mode 100644 drivers/dsp/bridge/Kbuild
+ create mode 100644 drivers/dsp/bridge/Kconfig
+ create mode 100644 drivers/dsp/bridge/dynload/cload.c
+ create mode 100644 drivers/dsp/bridge/dynload/dlclasses_hdr.h
+ create mode 100644 drivers/dsp/bridge/dynload/dload_internal.h
+ create mode 100644 drivers/dsp/bridge/dynload/doff.h
+ create mode 100644 drivers/dsp/bridge/dynload/getsection.c
+ create mode 100644 drivers/dsp/bridge/dynload/header.h
+ create mode 100644 drivers/dsp/bridge/dynload/module_list.h
+ create mode 100644 drivers/dsp/bridge/dynload/params.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc.c
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table_c6000.c
+ create mode 100644 drivers/dsp/bridge/gen/_gt_para.c
+ create mode 100644 drivers/dsp/bridge/gen/gb.c
+ create mode 100644 drivers/dsp/bridge/gen/gh.c
+ create mode 100644 drivers/dsp/bridge/gen/gs.c
+ create mode 100644 drivers/dsp/bridge/gen/gt.c
+ create mode 100644 drivers/dsp/bridge/gen/uuidutil.c
+ create mode 100644 drivers/dsp/bridge/hw/EasiGlobal.h
+ create mode 100644 drivers/dsp/bridge/hw/GlobalTypes.h
+ create mode 100644 drivers/dsp/bridge/hw/IPIAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/IVA2RegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MMUAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MMURegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_defs.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.h
+ create mode 100644 drivers/dsp/bridge/pmgr/chnl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/chnlobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/cmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/cod.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbll.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dev.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/io.c
+ create mode 100644 drivers/dsp/bridge/pmgr/ioobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/msg.c
+ create mode 100644 drivers/dsp/bridge/pmgr/msgobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/wcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/disp.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
+ create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/node.c
+ create mode 100644 drivers/dsp/bridge/rmgr/proc.c
+ create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
+ create mode 100644 drivers/dsp/bridge/rmgr/strm.c
+ create mode 100644 drivers/dsp/bridge/services/cfg.c
+ create mode 100644 drivers/dsp/bridge/services/clk.c
+ create mode 100644 drivers/dsp/bridge/services/csl.c
+ create mode 100644 drivers/dsp/bridge/services/dbg.c
+ create mode 100644 drivers/dsp/bridge/services/dpc.c
+ create mode 100644 drivers/dsp/bridge/services/kfile.c
+ create mode 100644 drivers/dsp/bridge/services/list.c
+ create mode 100644 drivers/dsp/bridge/services/mem.c
+ create mode 100644 drivers/dsp/bridge/services/ntfy.c
+ create mode 100644 drivers/dsp/bridge/services/reg.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.h
+ create mode 100644 drivers/dsp/bridge/services/services.c
+ create mode 100644 drivers/dsp/bridge/services/sync.c
+ create mode 100644 drivers/dsp/bridge/wmd/_cmm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_deh.h
+ create mode 100644 drivers/dsp/bridge/wmd/_msg_sm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_mmu.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_pwr.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_util.h
+ create mode 100644 drivers/dsp/bridge/wmd/chnl_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/io_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.h
+ create mode 100644 drivers/dsp/bridge/wmd/msg_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.h
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/ue_deh.c
+
+diff --git a/Documentation/tidspbridge/README b/Documentation/tidspbridge/README
+new file mode 100644
+index 0000000..df6d371
+--- /dev/null
++++ b/Documentation/tidspbridge/README
+@@ -0,0 +1,70 @@
++ Linux DSP/BIOS Bridge release
++
++DSP/BIOS Bridge overview
++========================
++
++DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more
++attached DSPs. The GPP is considered the master or "host" processor, and the
++attached DSPs are processing resources that can be utilized by applications
++and drivers running on the GPP.
++
++The abstraction that DSP/BIOS Bridge supplies, is a direct link between a GPP
++program and a DSP task. This communication link is partitioned into two
++types of sub-links: messaging (short, fixed-length packets) and data
++streaming (multiple, large buffers). Each sub-link operates independently,
++and features in-order delivery of data, meaning that messages are delivered
++in the order they were submitted to the message link, and stream buffers are
++delivered in the order they were submitted to the stream link.
++
++In addition, a GPP client can specify what inputs and outputs a DSP task
++uses. DSP tasks typically use message objects for passing control and status
++information and stream objects for efficient streaming of real-time data.
++
++GPP Software Architecture
++=========================
++
++A GPP application communicates with its associated DSP task running on the
++DSP subsystem using the DSP/BIOS Bridge API. For example, a GPP audio
++application can use the API to pass messages to a DSP task that is managing
++data flowing from analog-to-digital converters (ADCs) to digital-to-analog
++converters (DACs).
++
++From the perspective of the GPP OS, the DSP is treated as just another
++peripheral device. Most high level GPP OS typically support a device driver
++model, whereby applications can safely access and share a hardware peripheral
++through standard driver interfaces. Therefore, to allow multiple GPP
++applications to share access to the DSP, the GPP side of DSP/BIOS Bridge
++implements a device driver for the DSP.
++
++Since driver interfaces are not always standard across GPP OS, and to provide
++some level of interoperability of application code using DSP/BIOS Bridge
++between GPP OS, DSP/BIOS Bridge provides a standard library of APIs which
++wrap calls into the device driver. So, rather than calling GPP OS specific
++driver interfaces, applications (and even other device drivers) can use the
++standard API library directly.
++
++DSP Software Architecture
++=========================
++
++For DSP/BIOS, DSP/BIOS Bridge adds a device-independent streaming I/O (STRM)
++interface, a messaging interface (NODE), and a Resource Manager (RM) Server.
++The RM Server runs as a task of DSP/BIOS and is subservient to commands
++and queries from the GPP. It executes commands to start and stop DSP signal
++processing nodes in response to GPP programs making requests through the
++(GPP-side) API.
++
++DSP tasks started by the RM Server are similar to any other DSP task with two
++important differences: they must follow a specific task model consisting of
++three C-callable functions (node create, execute, and delete), with specific
++sets of arguments, and they have a pre-defined task environment established
++by the RM Server.
++
++Tasks started by the RM Server communicate using the STRM and NODE interfaces
++and act as servers for their corresponding GPP clients, performing signal
++processing functions as requested by messages sent by their GPP client.
++Typically, a DSP task moves data from source devices to sink devices using
++device independent I/O streams, performing application-specific processing
++and transformations on the data while it is moved. For example, an audio
++task might perform audio decompression (ADPCM, MPEG, CELP) on data received
++from a GPP audio driver and then send the decompressed linear samples to a
++digital-to-analog converter.
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index e7fb201..2060772 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1331,6 +1331,8 @@ if ARCH_OMAP
+ source "drivers/cbus/Kconfig"
+ endif
+
++source "drivers/dsp/bridge/Kconfig"
++
+ endmenu
+
+ source "fs/Kconfig"
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 9b270d8..e52e01e 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -34,6 +34,8 @@ obj-$(CONFIG_OMAP_SMARTREFLEX) += smartreflex.o
+ obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
+ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+
++obj-$(CONFIG_MPU_BRIDGE) += dspbridge.o
++
+ # DSP
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+ mailbox_mach-objs := mailbox.o
+diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
+new file mode 100644
+index 0000000..221e8ff
+--- /dev/null
++++ b/arch/arm/mach-omap2/dspbridge.c
+@@ -0,0 +1,74 @@
++/*
++ * TI's dspbridge platform device registration
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ * Copyright (C) 2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <dspbridge/host_os.h>
++
++static struct platform_device *dspbridge_pdev;
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++static struct dspbridge_platform_data dspbridge_pdata __initdata = {
++ .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
++ .dsp_get_opp = omap_pm_dsp_get_opp,
++ .cpu_set_freq = omap_pm_cpu_set_freq,
++ .cpu_get_freq = omap_pm_cpu_get_freq,
++};
++#else
++static struct dspbridge_platform_data dspbridge_pdata;
++#endif
++
++static int __init dspbridge_init(void)
++{
++ struct platform_device *pdev;
++ int err = -ENOMEM;
++ struct dspbridge_platform_data *pdata = &dspbridge_pdata;
++
++ pdata->phys_mempool_base = dspbridge_get_mempool_base();
++
++ if (pdata->phys_mempool_base) {
++ pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++ pr_info("%s: %x bytes @ %x\n", __func__,
++ pdata->phys_mempool_size, pdata->phys_mempool_base);
++ }
++
++ pdev = platform_device_alloc("C6410", -1);
++ if (!pdev)
++ goto err_out;
++
++ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
++ if (err)
++ goto err_out;
++
++ err = platform_device_add(pdev);
++ if (err)
++ goto err_out;
++
++ dspbridge_pdev = pdev;
++ return 0;
++
++err_out:
++ platform_device_put(pdev);
++ return err;
++}
++module_init(dspbridge_init);
++
++static void __exit dspbridge_exit(void)
++{
++ platform_device_unregister(dspbridge_pdev);
++}
++module_exit(dspbridge_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU");
++MODULE_DESCRIPTION("TI's dspbridge platform device registration");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index a04e3ee..40488ae 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -38,6 +38,8 @@
+ #include <mach/clockdomain.h>
+ #include "clockdomains.h"
+
++#include <dspbridge/host_os.h>
++
+ /*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+@@ -192,6 +194,7 @@ void __init omap2_map_common_io(void)
+ omap2_check_revision();
+ omap_sram_init();
+ omapfb_reserve_sdram();
++ dspbridge_reserve_sdram();
+ }
+
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
+index 6b742a8..e66dd8a 100644
+--- a/arch/arm/plat-omap/devices.c
++++ b/arch/arm/plat-omap/devices.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/i2c/menelaus.h>
++#include <linux/bootmem.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -89,6 +90,33 @@ EXPORT_SYMBOL(dsp_kfunc_device_register);
+ static inline void omap_init_dsp(void) { }
+ #endif /* CONFIG_OMAP_DSP */
+
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++
++static unsigned long dspbridge_phys_mempool_base;
++
++void dspbridge_reserve_sdram(void)
++{
++ void *va;
++ unsigned long size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++
++ if (!size)
++ return;
++
++ va = __alloc_bootmem_nopanic(size, SZ_1M, 0);
++ if (!va) {
++ pr_err("%s: Failed to bootmem allocation(%lu bytes)\n",
++ __func__, size);
++ return;
++ }
++ dspbridge_phys_mempool_base = virt_to_phys(va);
++}
++
++unsigned long dspbridge_get_mempool_base(void)
++{
++ return dspbridge_phys_mempool_base;
++}
++EXPORT_SYMBOL(dspbridge_get_mempool_base);
++#endif
+ /*-------------------------------------------------------------------------*/
+ #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+new file mode 100644
+index 0000000..28af799
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+@@ -0,0 +1,212 @@
++/*
++ * _chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _chnl_sm.h ========
++ * Description:
++ * Private header file defining channel manager and channel objects for
++ * a shared memory channel driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ * Shared between the modules implementing the shared memory channel class
++ * library.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc Removed legacy PERF code.
++ *! 12-Jan-2002 ag Removed unused gppReqIO & ddmaChnlId DDMA fields.
++ *! Added zero-copy chnl descriptor array: zchnldesc.
++ *! 21-Dec-2001 ag Moved descPaGpp to private chnl obj from chnl descriptor.
++ *! 20-May-2001 ag/jeh Removed fShmSyms field from CHNL_MGR.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 26-Oct-2000 jeh Added arg and resvd to SHM control structure. Added dwArg
++ *! to CHNL_IRP.
++ *! 16-Oct-2000 jeh Removed #ifdef DEBUG from around channel object's cIOCs
++ *! field, added cIOReqs.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 03-Nov-1999 ag: Added szEventName[] to CHNL object for name event support.
++ *! 02-Nov-1999 ag: _SHM_BEG & _END Syms from COFF now used for IO and SM CLASS.
++ *! 27-Oct-1999 jeh Define SHM structure to work for 16-bit targets.
++ *! 25-May-1999 jg: Added target side symbol names for share memory buffer
++ *! 03-Jan-1997 gp: Added fSharedIRQ field.
++ *! 22-Oct-1996 gp: Made dwProcessID a handle.
++ *! 09-Sep-1996 gp: Added dwProcessID field to CHNL_OBJECT.
++ *! 13-Aug-1996 gp: Created.
++ */
++
++#ifndef _CHNL_SM_
++#define _CHNL_SM_
++
++#include <dspbridge/wcd.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dpc.h>
++
++#include <dspbridge/list.h>
++#include <dspbridge/ntfy.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of shared memory buffer. They are defined in the *cfg.cmd file by
++ * cdb code.
++ */
++#define CHNL_SHARED_BUFFER_BASE_SYM "_SHM_BEG"
++#define CHNL_SHARED_BUFFER_LIMIT_SYM "_SHM_END"
++#define BRIDGEINIT_BIOSGPTIMER "_BRIDGEINIT_BIOSGPTIMER"
++#define BRIDGEINIT_LOADMON_GPTIMER "_BRIDGEINIT_LOADMON_GPTIMER"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++#define MAXOPPS 16
++
++struct oppTableEntry {
++ u32 voltage;
++ u32 frequency;
++ u32 minFreq;
++ u32 maxFreq;
++} ;
++
++struct oppStruct {
++ u32 currOppPt;
++ u32 numOppPts;
++ struct oppTableEntry oppPoint[MAXOPPS];
++} ;
++
++/* Request to MPU */
++struct oppRqstStruct {
++ u32 rqstDspFreq;
++ u32 rqstOppPt;
++};
++
++/* Info to MPU */
++struct loadMonStruct {
++ u32 currDspLoad;
++ u32 currDspFreq;
++ u32 predDspLoad;
++ u32 predDspFreq;
++};
++
++ enum SHM_DESCTYPE {
++ SHM_CURROPP = 0,
++ SHM_OPPINFO = 1,
++ SHM_GETOPP = 2, /* Get DSP requested OPP info */
++ } ;
++
++/* Structure in shared between DSP and PC for communication.*/
++ struct SHM {
++ u32 dspFreeMask; /* Written by DSP, read by PC. */
++ u32 hostFreeMask; /* Written by PC, read by DSP */
++
++ u32 inputFull; /* Input channel has unread data. */
++ u32 inputId; /* Channel for which input is available. */
++ u32 inputSize; /* Size of data block (in DSP words). */
++
++ u32 outputFull; /* Output channel has unread data. */
++ u32 outputId; /* Channel for which output is available. */
++ u32 outputSize; /* Size of data block (in DSP words). */
++
++ u32 arg; /* Arg for Issue/Reclaim (23 bits for 55x). */
++ u32 resvd; /* Keep structure size even for 32-bit DSPs */
++
++ /* Operating Point structure */
++ struct oppStruct oppTableStruct;
++ /* Operating Point Request structure */
++ struct oppRqstStruct oppRequest;
++ /* load monitor information structure*/
++ struct loadMonStruct loadMonInfo;
++ char dummy[184]; /* padding to 256 byte boundary */
++ u32 shm_dbg_var[64]; /* shared memory debug variables */
++ } ;
++
++ /* Channel Manager: only one created per board: */
++ struct CHNL_MGR {
++ u32 dwSignature; /* Used for object validation */
++ /* Function interface to WMD */
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr; /* IO manager */
++ /* Device this board represents */
++ struct DEV_OBJECT *hDevObject;
++
++ /* These fields initialized in WMD_CHNL_Create(): */
++ u32 dwOutputMask; /* Host output channels w/ full buffers */
++ u32 dwLastOutput; /* Last output channel fired from DPC */
++ /* Critical section object handle */
++ struct SYNC_CSOBJECT *hCSObj;
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u32 cChannels; /* Total number of channels */
++ u32 cOpenChannels; /* Total number of open channels */
++ struct CHNL_OBJECT **apChannel; /* Array of channels */
++ u32 dwType; /* Type of channel class library */
++ /* If no SHM syms, return for CHNL_Open */
++ DSP_STATUS chnlOpenStatus;
++ } ;
++
++/*
++ * Channel: up to CHNL_MAXCHANNELS per board or if DSP-DMA supported then
++ * up to CHNL_MAXCHANNELS + CHNL_MAXDDMACHNLS per board.
++ */
++ struct CHNL_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Pointer back to channel manager */
++ struct CHNL_MGR *pChnlMgr;
++ u32 uId; /* Channel id */
++ u32 dwState; /* Current channel state */
++ u32 uMode; /* Chnl mode and attributes */
++ /* Chnl I/O completion event (user mode) */
++ HANDLE hUserEvent;
++ /* Abstract syncronization object */
++ struct SYNC_OBJECT *hSyncEvent;
++ /* Name of Sync event */
++ char szEventName[SYNC_MAXNAMELENGTH + 1];
++ u32 hProcess; /* Process which created this channel */
++ u32 pCBArg; /* Argument to use with callback */
++ struct LST_LIST *pIORequests; /* List of IOR's to driver */
++ s32 cIOCs; /* Number of IOC's in queue */
++ s32 cIOReqs; /* Number of IORequests in queue */
++ s32 cChirps; /* Initial number of free Irps */
++ /* List of IOC's from driver */
++ struct LST_LIST *pIOCompletions;
++ struct LST_LIST *pFreeList; /* List of free Irps */
++ struct NTFY_OBJECT *hNtfy;
++ u32 cBytesMoved; /* Total number of bytes transfered */
++
++ /* For DSP-DMA */
++
++ /* Type of chnl transport:CHNL_[PCPY][DDMA] */
++ u32 uChnlType;
++ } ;
++
++/* I/O Request/completion packet: */
++ struct CHNL_IRP {
++ struct LST_ELEM link; /* Link to next CHIRP in queue. */
++ /* Buffer to be filled/emptied. (User) */
++ u8 *pHostUserBuf;
++ /* Buffer to be filled/emptied. (System) */
++ u8 *pHostSysBuf;
++ u32 dwArg; /* Issue/Reclaim argument. */
++ u32 uDspAddr; /* Transfer address on DSP side. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size when allocated. */
++ u32 status; /* Status of IO completion. */
++ } ;
++
++#endif /* _CHNL_SM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/_dcd.h b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+new file mode 100644
+index 0000000..b6a8d9e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+@@ -0,0 +1,187 @@
++/*
++ * _dcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _dcd.h ========
++ * Description:
++ * Includes the wrapper functions called directly by the
++ * DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ * Notes:
++ * Compiled with CDECL calling convention.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 30-Jan-2002 ag Renamed CMMWRAP_AllocBuf to CMMWRAP_CallocBuf.
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data to acquire PERF stats.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 10-Oct-2000 ag: Added user CMM wrappers.
++ *! 04-Aug-2000 rr: MEMWRAP and UTIL_Wrap added.
++ *! 27-Jul-2000 rr: NODEWRAP, STRMWRAP added.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 03-Dec-1999 rr: WCD_InitComplete2 enabled for BRD_AutoStart.
++ *! 09-Nov-1999 kc: Added MEMRY.
++ *! 02-Nov-1999 ag: Added CHNL.
++ *! 08-Oct-1999 rr: Utilwrap_Testdll fxn added
++ *! 24-Sep-1999 rr: header changed from _wcd.h to _dcd.h
++ *! 09-Sep-1997 gp: Created.
++ */
++
++#ifndef _WCD_
++#define _WCD_
++
++#include <dspbridge/wcdioctl.h>
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ * Parameters:
++ * cmd: IOCTL id, base 0.
++ * args: Argument structure.
++ * pResult:
++ * Returns:
++ * DSP_SOK if command called; DSP_EINVALIDARG if command not in IOCTL
++ * table.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_CallDevIOCtl(unsigned int cmd,
++ union Trapped_Args *args,
++ u32 *pResult);
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Initialize WCD modules, and export WCD services to WMD's.
++ * This procedure is called when the class driver is loaded.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool WCD_Init(void);
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init(void) or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_InitComplete2(void);
++
++/*
++ * ======== WCD_Exit ========
++ * Purpose:
++ * Exit all modules initialized in WCD_Init(void).
++ * This procedure is called when the class driver is unloaded.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * WCD_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in WCD_Init(void) are freed.
++ */
++ extern void WCD_Exit(void);
++
++/* MGR wrapper functions */
++ extern u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_RegisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_UnregisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args);
++
++#ifndef RES_CLEANUP_DISABLE
++ extern u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args);
++#endif
++
++
++/* CPRC (Processor) wrapper Functions */
++ extern u32 PROCWRAP_Attach(union Trapped_Args *args);
++ extern u32 PROCWRAP_Ctrl(union Trapped_Args *args);
++ extern u32 PROCWRAP_Detach(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumResources(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetState(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetTrace(union Trapped_Args *args);
++ extern u32 PROCWRAP_Load(union Trapped_Args *args);
++ extern u32 PROCWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 PROCWRAP_Start(union Trapped_Args *args);
++ extern u32 PROCWRAP_ReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Map(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnMap(union Trapped_Args *args);
++ extern u32 PROCWRAP_FlushMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Stop(union Trapped_Args *args);
++ extern u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args);
++
++/* NODE wrapper functions */
++ extern u32 NODEWRAP_Allocate(union Trapped_Args *args);
++ extern u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_ChangePriority(union Trapped_Args *args);
++ extern u32 NODEWRAP_Connect(union Trapped_Args *args);
++ extern u32 NODEWRAP_Create(union Trapped_Args *args);
++ extern u32 NODEWRAP_Delete(union Trapped_Args *args);
++ extern u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetAttr(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_Pause(union Trapped_Args *args);
++ extern u32 NODEWRAP_PutMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 NODEWRAP_Run(union Trapped_Args *args);
++ extern u32 NODEWRAP_Terminate(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args);
++
++/* STRM wrapper functions */
++ extern u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_Close(union Trapped_Args *args);
++ extern u32 STRMWRAP_FreeBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetEventHandle(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetInfo(union Trapped_Args *args);
++ extern u32 STRMWRAP_Idle(union Trapped_Args *args);
++ extern u32 STRMWRAP_Issue(union Trapped_Args *args);
++ extern u32 STRMWRAP_Open(union Trapped_Args *args);
++ extern u32 STRMWRAP_Reclaim(union Trapped_Args *args);
++ extern u32 STRMWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 STRMWRAP_Select(union Trapped_Args *args);
++
++ extern u32 CMMWRAP_CallocBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_FreeBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetHandle(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetInfo(union Trapped_Args *args);
++
++#endif /* _WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/brddefs.h b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+new file mode 100644
+index 0000000..c62388c
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+@@ -0,0 +1,54 @@
++/*
++ * brddefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== brddefs.h ========
++ * Description:
++ * Global BRD constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: Comment Exec changed to Monitor
++ *! 22-Jul-1999 jeh Added BRD_LOADED state.
++ *! 26-Mar-1997 gp: Added BRD_SYNCINIT state.
++ *! 11-Dec-1996 cr: Added BRD_LASTSTATE definition.
++ *! 11-Jul-1996 gp: Added missing u32 callback argument to BRD_CALLBACK.
++ *! 10-Jun-1996 gp: Created from board.h and brd.h.
++ */
++
++#ifndef BRDDEFS_
++#define BRDDEFS_
++
++/* platform status values */
++#define BRD_STOPPED 0x0 /* No Monitor Loaded, Not running. */
++#define BRD_IDLE 0x1 /* Monitor Loaded, but suspended. */
++#define BRD_RUNNING 0x2 /* Monitor loaded, and executing. */
++#define BRD_UNKNOWN 0x3 /* Board state is indeterminate. */
++#define BRD_SYNCINIT 0x4
++#define BRD_LOADED 0x5
++#define BRD_LASTSTATE BRD_LOADED /* Set to highest legal board state. */
++#define BRD_SLEEP_TRANSITION 0x6 /* Sleep transition in progress */
++#define BRD_HIBERNATION 0x7 /* MPU initiated hibernation */
++#define BRD_RETENTION 0x8 /* Retention mode */
++#define BRD_DSP_HIBERNATION 0x9 /* DSP initiated hibernation */
++#define BRD_ERROR 0xA /* Board state is Error */
++ typedef u32 BRD_STATUS;
++
++/* BRD Object */
++ struct BRD_OBJECT;
++
++#endif /* BRDDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfg.h b/arch/arm/plat-omap/include/dspbridge/cfg.h
+new file mode 100644
+index 0000000..68db842
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfg.h
+@@ -0,0 +1,339 @@
++/*
++ * cfg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfg.h ========
++ * Purpose:
++ * PM Configuration module.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetCDVersion
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_GetPerfValue
++ * CFG_GetWMDFileName
++ * CFG_GetZLFile
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *! Revision History:
++ *! =================
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 28-Aug-2001 jeh Added CFG_GetLoaderName.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName to retrieve the DCD Dll name.
++ *! 13-Jul-2000 rr: Added CFG_GetObject & CFG_SetObject.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! CFG_GetWinBRIDGEDir/Directory,CFG_GetSearchPath removed.
++ *! 15-Jan-1998 cr: Code review cleanup.
++ *! 16-Aug-1997 cr: Added explicit cdecl identifiers.
++ *! 12-Dec-1996 gp: Moved CFG_FindInSearchPath to CSP module.
++ *! 13-Sep-1996 gp: Added CFG_GetBoardName().
++ *! 22-Jul-1996 gp: Added CFG_GetTraceStr, to retrieve an initial GT trace.
++ *! 26-Jun-1996 cr: Added CFG_FindInSearchPath.
++ *! 25-Jun-1996 cr: Added CFG_GetWinSPOXDir.
++ *! 17-Jun-1996 cr: Added CFG_GetDevNode.
++ *! 11-Jun-1996 cr: Cleaned up for code review.
++ *! 07-Jun-1996 cr: Added CFG_GetExecFile and CFG_GetZLFileName functions.
++ *! 04-Jun-1996 gp: Added AutoStart regkey and accessor function. Placed
++ *! OUT parameters in accessor function param. lists at end.
++ *! 29-May-1996 gp: Moved DEV_HDEVNODE to here and renamed CFG_HDEVNODE.
++ *! 22-May-1996 cr: Added GetHostResources, GetDSPResources, and
++ *! GetWMDFileName services.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef CFG_
++#define CFG_
++#include <dspbridge/host_os.h>
++#include <dspbridge/cfgdefs.h>
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CFG_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in CFG_Init(void) are freed.
++ */
++ extern void CFG_Exit(void);
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * pdwAutoStart: Ptr to location for 32 bit autostart mask.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: Unable to retreive resource.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwAutoStart contains autostart mask for this devnode.
++ */
++ extern DSP_STATUS CFG_GetAutoStart(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart);
++
++/*
++ * ======== CFG_GetCDVersion ========
++ * Purpose:
++ * Retrieves the version of the PM Class Driver.
++ * Parameters:
++ * pdwVersion: Ptr to u32 to contain version number upon return.
++ * Returns:
++ * DSP_SOK: Success. pdwVersion contains Class Driver version in
++ * the form: 0xAABBCCDD where AABB is Major version and
++ * CCDD is Minor.
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Success.
++ * else: *pdwVersion is NULL.
++ */
++ extern DSP_STATUS CFG_GetCDVersion(OUT u32 *pdwVersion);
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle from which to retrieve value.
++ * pdwValue: Ptr to location to store the value.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: phDevObject is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32.
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwValue);
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pDSPResTable: Ptr to a location to store the DSP resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The DSP Resource information is not
++ * available
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pDSPResTable points to a filled table of resources allocated
++ * for the specified WMD.
++ */
++ extern DSP_STATUS CFG_GetDSPResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable);
++
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrExecFile: Ptr to character buf to hold ExecFile.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: pstrExecFile is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into pstrExecFile,
++ * and *pstrExecFile contains default executable for this
++ * devnode.
++ */
++ extern DSP_STATUS CFG_GetExecFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrExecFile);
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host PC allocated resources assigned to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pHostResTable: Ptr to a location to store the host resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDPOINTER: pHostResTable is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pHostResTable points to a filled table of resources
++ * allocated for the specified WMD.
++ *
++ */
++ extern DSP_STATUS CFG_GetHostResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable);
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Driver Object handle From the Registry
++ * Parameters:
++ * pdwValue: Ptr to location to store the value.
++ * dwType Type of Object to Get
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32(non-Zero).
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType);
++
++/*
++ * ======== CFG_GetPerfValue ========
++ * Purpose:
++ * Retrieve a flag indicating whether PERF should log statistics for the
++ * PM class driver.
++ * Parameters:
++ * pfEnablePerf: Location to store flag. 0 indicates the key was
++ * not found, or had a zero value. A nonzero value
++ * means the key was found and had a nonzero value.
++ * Returns:
++ * Requires:
++ * pfEnablePerf != NULL;
++ * Ensures:
++ */
++ extern void CFG_GetPerfValue(OUT bool *pfEnablePerf);
++
++/*
++ * ======== CFG_GetWMDFileName ========
++ * Purpose:
++ * Get the mini-driver file name for a given device.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pWMDFileName: Ptr to a character buffer to hold the WMD filename.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The filename is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied
++ * into pWMDFileName.
++ *
++ */
++ extern DSP_STATUS CFG_GetWMDFileName(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pWMDFileName);
++
++/*
++ * ======== CFG_GetZLFile ========
++ * Purpose:
++ * Retreive the ZLFile, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrZLFileName: Ptr to character buf to hold ZLFileName.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDPOINTER: pstrZLFileName is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: couldn't find the ZLFileName.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into
++ * pstrZLFileName, and *pstrZLFileName contains ZLFileName
++ * for this devnode.
++ */
++ extern DSP_STATUS CFG_GetZLFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrZLFileName);
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CFG functions.
++ */
++ extern bool CFG_Init(void);
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle we are storing value with.
++ * dwValue: Arbitrary value to store.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 dwValue);
++
++/*
++ * ======== CFG_SetDrvObject ========
++ * Purpose:
++ * Store the Driver Object handle.
++ * Parameters:
++ * dwValue: Arbitrary value to store.
++ * dwType Type of Object to Store
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetObject(IN u32 dwValue, IN u32 dwType);
++
++#endif /* CFG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+new file mode 100644
+index 0000000..4f78d82
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+@@ -0,0 +1,126 @@
++/*
++ * cfgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cfgdefs.h ========
++ * Purpose:
++ * Global CFG constants and types, shared between class and mini driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* in CFG_HOSTRES.
++ *! 06-Sep-2000 jeh Added channel info to CFG_HOSTRES.
++ *! 09-May-2000 rr: CFG_HOSTRES now support multiple windows for PCI support.
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 06-Jan-2000 rr: Bus Type included in CFG_HOSTRES.
++ *! 12-Nov-1999 rr: CFG_HOSTRES member names changed.
++ *! 25-Oct-1999 rr: Modified the CFG_HOSTRES Structure
++ *! PCMCIA ISR Register/Unregister fxn removed..
++ *! New flag PCCARD introduced during compile time.
++ *! 10-Sep-1999 ww: Added PCMCIA ISR Register/Unregister fxn.
++ *! 01-Sep-1999 ag: Removed NT/95 specific fields in CFG_HOSTRES
++ *! 27-Oct-1997 cr: Updated CFG_HOSTRES struct to support 1+ IRQs per board.
++ *! 17-Sep-1997 gp: Tacked some NT config info to end of CFG_HOSTRES structure.
++ *! 12-Dec-1996 cr: Cleaned up after code review.
++ *! 14-Nov-1996 gp: Renamed from wsxcfg.h
++ *! 19-Jun-1996 cr: Created.
++ */
++
++#ifndef CFGDEFS_
++#define CFGDEFS_
++
++/* Maximum length of module search path. */
++#define CFG_MAXSEARCHPATHLEN 255
++
++/* Maximum length of general paths. */
++#define CFG_MAXPATH 255
++
++/* Host Resources: */
++#define CFG_MAXMEMREGISTERS 9
++#define CFG_MAXIOPORTS 20
++#define CFG_MAXIRQS 7
++#define CFG_MAXDMACHANNELS 7
++
++/* IRQ flag */
++#define CFG_IRQSHARED 0x01 /* IRQ can be shared */
++
++/* DSP Resources: */
++#define CFG_DSPMAXMEMTYPES 10
++#define CFG_DEFAULT_NUM_WINDOWS 1 /* We support only one window. */
++
++/* A platform-related device handle: */
++ struct CFG_DEVNODE;
++
++/*
++ * Host resource structure.
++ */
++ struct CFG_HOSTRES {
++ u32 wNumMemWindows; /* Set to default */
++ /* This is the base.memory */
++ u32 dwMemBase[CFG_MAXMEMREGISTERS]; /* SHM virtual address */
++ u32 dwMemLength[CFG_MAXMEMREGISTERS]; /* Length of the Base */
++ u32 dwMemPhys[CFG_MAXMEMREGISTERS]; /* SHM Physical address */
++ u8 bIRQRegisters; /* IRQ Number */
++ u8 bIRQAttrib; /* IRQ Attribute */
++ u32 dwOffsetForMonitor; /* The Shared memory starts from
++ * dwMemBase + this offset */
++ u32 dwBusType; /* Bus type for this device */
++ u32 dwProgBase; /* DSP ProgBase */
++ u32 dwProgLength; /* DSP ProgBase Length */
++ u32 dwRegBase; /* DSP memory mapped register base */
++ u32 dwRegLength; /* DSP Register Base Length */
++ u32 ClientHandle; /* Client Handle */
++ u32 SocketHandle; /* Socket and Function Pair */
++ u32 CardInfo; /* This will be used as a context data in
++ * in the CardRequestIRQ */
++ /*
++ * Info needed by NODE for allocating channels to communicate with RMS:
++ * dwChnlOffset: Offset of RMS channels. Lower channels are
++ * reserved.
++ * dwChnlBufSize: Size of channel buffer to send to RMS
++ * dwNumChnls: Total number of channels (including reserved).
++ */
++ u32 dwChnlOffset;
++ u32 dwChnlBufSize;
++ u32 dwNumChnls;
++ u32 dwPrmBase;
++ u32 dwCmBase;
++ u32 dwPerBase;
++ u32 dwPerPmBase;
++ u32 dwCorePmBase;
++ u32 dwWdTimerDspBase;
++ u32 dwMboxBase;
++ u32 dwDmmuBase;
++ u32 dwDipiBase;
++ u32 dwSysCtrlBase;
++ } ;
++
++ struct CFG_DSPMEMDESC {
++ u32 uMemType; /* Type of memory. */
++ u32 ulMin; /* Minimum amount of memory of this type. */
++ u32 ulMax; /* Maximum amount of memory of this type. */
++ } ;
++
++ struct CFG_DSPRES {
++ u32 uChipType; /* DSP chip type. */
++ u32 uWordSize; /* Number of bytes in a word */
++ u32 cChips; /* Number of chips. */
++ u32 cMemTypes; /* Types of memory. */
++ struct CFG_DSPMEMDESC aMemDesc[CFG_DSPMAXMEMTYPES];
++ /* DSP Memory types */
++ } ;
++
++#endif /* CFGDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl.h b/arch/arm/plat-omap/include/dspbridge/chnl.h
+new file mode 100644
+index 0000000..f39e3f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl.h
+@@ -0,0 +1,170 @@
++/*
++ * chnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.h ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a mini-driver.
++ *
++ * Public Functions:
++ * CHNL_AddIOReq
++ * CHNL_AllocBuffer
++ * CHNL_CancelIO
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_FlushIO
++ * CHNL_FreeBuffer
++ * CHNL_GetEventHandle
++ * CHNL_GetHandle
++ * CHNL_GetIOCompletion
++ * CHNL_GetId
++ * CHNL_GetMgr
++ * CHNL_GetMode
++ * CHNL_GetPosition
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * See DSP API chnl.h for more details.
++ *
++ *! Revision History:
++ *! ================
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 24-Oct-1996 gp: Move CloseOrphans into here from dspsys.
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessID() and CHNL_GetHandle().
++ *! 10-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNL_
++#define CHNL_
++
++#include <dspbridge/chnlpriv.h>
++
++/*
++ * ======== CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * CHNL_Init(void) called.
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: The I/O completion event for this channel is freed.
++ * hChnl is no longer valid.
++ */
++ extern DSP_STATUS CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: hDevObject is invalid.
++ * DSP_EINVALIDARG: cChannels is 0.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_MAXCHANNELS: This manager cannot handle this many channels.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * CHNL_E_MGREXISTS: Channel manager already exists for this device.
++ * Requires:
++ * CHNL_Init(void) called.
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Subsequent calls to CHNL_Create() for the same
++ * board without an intervening call to
++ * CHNL_Destroy() will fail.
++ */
++ extern DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * CHNL_Init(void) called.
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel.
++ * Closes each open channel.
++ * CHNL_Create may subsequently be called for the
++ * same board.
++ */
++ extern DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CHNL_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in CHNL_Init(void), are freed when the last
++ * client of CHNL calls CHNL_Exit(void).
++ */
++ extern void CHNL_Exit(void);
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool CHNL_Init(void);
++
++
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+new file mode 100644
+index 0000000..789b9bd
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+@@ -0,0 +1,168 @@
++/*
++ * chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.h ========
++ * Description:
++ * Prototypes for channel lower edge functions for a WinBRIDGE mini driver
++ * implementing data transfer via shared memory.
++ *
++ * Public Functions:
++ * CHNLSM_DisableInterrupt;
++ * CHNLSM_EnableInterrupt;
++ * CHNLSM_ISR;
++ * CHNLSM_Read;
++ * CHNLSM_UpdateSHMLength;
++ * CHNLSM_Write;
++ *
++ * Notes:
++ * These lower edge functions must be implemented by the WMD writer.
++ * Currently, CHNLSM_Read() and CHNLSM_Write() are not called, but must
++ * be defined to link.
++ *
++ */
++
++#ifndef CHNLSM_
++#define CHNLSM_
++
++#include <dspbridge/wmd.h>
++
++/*
++ * ======== CHNLSM_DisableInterrupt ========
++ * Purpose:
++ * Disable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_EnableInterrupt ========
++ * Purpose:
++ * Enable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_InterruptDSP2 ========
++ * Purpose:
++ * Set interrupt value & send an interrupt to the DSP processor(s).
++ * This is typicaly used when mailbox interrupt mechanisms allow data
++ * to be associated with interrupt such as for OMAP's CMD/DATA regs.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * wMbVal: Value associated with interrupt(e.g. mailbox value).
++ * Returns:
++ * DSP_SOK: Interrupt sent;
++ * else: Unable to send interrupt.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT*
++ hDevContext, u16 wMbVal);
++
++/*
++ * ======== CHNLSM_ISR ========
++ * Purpose:
++ * Mini-driver's ISR, called by WCD when the board interrupts the host.
++ * Parameters:
++ * hDevContext: Handle to the mini-driver defined device info.
++ * pfSchedDPC: Set to TRUE to schedule a deferred procedure call
++ * to advance the channel protocol. The channel class
++ * library will call the WMD's CHNLSM_DPC routine during
++ * its own DPC, before dispatching I/O.
++ * The channel class library should ignore *pfSchedDPC when
++ * CHNLSM_ISR returns FALSE.
++ * pwMBRegVal: Value of mailbox register.
++ * Returns:
++ * TRUE if this interrupt is was generated by the DSP board.
++ * FALSE otherwise.
++ * Requires:
++ * Interrupts to the host processor are disabled on entry.
++ * Must only call functions which are in page locked memory.
++ * Must only call asynchronous OS services.
++ * The EOI for this interrupt has already been sent to the PIC.
++ * Ensures:
++ * If the interrupt is *not* shared, this routine must return TRUE.
++ */
++ extern bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT bool *pfSchedDPC,
++ OUT u16 *pwIntrVal);
++
++/*
++ * ======== CHNLSM_Read ========
++ * Purpose:
++ * Read data from DSP board memory into a Host buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++/*
++ * ======== CHNLSM_UpdateSHMLength ========
++ * Purpose:
++ * Allow the minidriver a chance to override the SHM length as reported
++ * to the mini driver (chnl_sm.lib) by Windows Plug and Play.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pSHMLength: Pointer to size of SHM window (in DSP words).
++ * Returns:
++ * TRUE if pSHMLength updated; FALSE otherwise.
++ * Requires:
++ * pSHMLength != NULL.
++ * Ensures:
++ * No more than sizeof(u32) bytes written to *pSHMLength
++ */
++ extern bool CHNLSM_UpdateSHMLength(struct WMD_DEV_CONTEXT *hDevContext,
++ IN OUT u32 *pSHMLength);
++
++/*
++ * ======== CHNLSM_Write ========
++ * Purpose:
++ * Write data from a Host buffer to DSP board memory.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Source).
++ * dwDSPAddr: Address on DSP board (Destination).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++#endif /* CHNLSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnldefs.h b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+new file mode 100644
+index 0000000..9f59229
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+@@ -0,0 +1,92 @@
++/*
++ * chnldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnldefs.h ========
++ * Purpose:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Jan-2002 ag Added cBufSize to IOC.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 02-Dec-1999 ag: Added new chnl attribute pstrEventName.
++ *! 12-Nov-1999 kc: Enabled hEvent attribute for tests.
++ *! 01-Nov-1999 ag: hEvent attribute not supported(yet).
++ *! 16-Jan-1997 gp: Moved private stuff into chnlpriv.h
++ *! 14-Jan-1997 gp: Updated based on code review feedback:
++ *! Removed CHNL_MODENOWAIT, CHNL_MODEDIRECT,
++ *! 03-Jan-1997 gp: Added channel class library types.
++ *! 14-Dec-1996 gp: Moved uChnlId field from CHNL_ATTRS to CHNL_Open().
++ *! 10-Dec-1996 gp: Added CHNL_IsTimedOut() macro.
++ *! 14-Nov-1996 gp: Renamed from wsxchnl.h.
++ *! 09-Sep-1996 gp: Added hReserved2 field to CHNL_ATTRS. Updated CHNL_INFO.
++ *! 10-Jul-1996 gp: Created from channel.h.
++ */
++
++#ifndef CHNLDEFS_
++#define CHNLDEFS_
++
++/* Channel id option. */
++#define CHNL_PICKFREE (~0UL) /* Let manager pick a free channel. */
++
++/* Channel manager limits: */
++#define CHNL_INITIOREQS 4 /* Default # of I/O requests. */
++
++/* Channel modes */
++#define CHNL_MODETODSP 0x0000 /* Data streaming to the DSP. */
++#define CHNL_MODEFROMDSP 0x0001 /* Data streaming from the DSP. */
++
++/* GetIOCompletion flags */
++#define CHNL_IOCINFINITE 0xffffffff /* Wait forever for IO completion. */
++#define CHNL_IOCNOWAIT 0x0 /* Dequeue an IOC, if available. */
++
++/* IO Completion Record status: */
++#define CHNL_IOCSTATCOMPLETE 0x0000 /* IO Completed. */
++#define CHNL_IOCSTATCANCEL 0x0002 /* IO was cancelled */
++#define CHNL_IOCSTATTIMEOUT 0x0008 /* Wait for IOC timed out. */
++#define CHNL_IOCSTATEOS 0x8000 /* End Of Stream reached. */
++
++/* Macros for checking I/O Completion status: */
++#define CHNL_IsEOS(ioc) (ioc.status & CHNL_IOCSTATEOS)
++#define CHNL_IsIOComplete(ioc) (!(ioc.status & ~CHNL_IOCSTATEOS))
++#define CHNL_IsIOCancelled(ioc) (ioc.status & CHNL_IOCSTATCANCEL)
++#define CHNL_IsTimedOut(ioc) (ioc.status & CHNL_IOCSTATTIMEOUT)
++
++/* CHNL types: */
++ typedef u32 CHNL_MODE; /* Channel transfer mode. */
++
++/* Channel attributes: */
++ struct CHNL_ATTRS {
++ u32 uIOReqs; /* Max # of preallocated I/O requests. */
++ HANDLE hEvent; /* User supplied auto-reset event object. */
++ char *pstrEventName; /* Ptr to name of user event object. */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++
++ };
++
++/* I/O completion record: */
++ struct CHNL_IOC {
++ void *pBuf; /* Buffer to be filled/emptied. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size in bytes */
++ u32 status; /* Status of IO completion. */
++ u32 dwArg; /* User argument associated with pBuf. */
++ } ;
++
++#endif /* CHNLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnlpriv.h b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+new file mode 100644
+index 0000000..fdcda24
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+@@ -0,0 +1,136 @@
++/*
++ * chnlpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlpriv.h ========
++ * Description:
++ * Private channel header shared between DSPSYS, WCD and WMD modules.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Jan-2002 ag Added cChannels(total # of chnls) to CHNL_MGRINFO struct.
++ *! Added private CHNL_[PCPY][ZCPY][DDMA].
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory from CHNL_MGRATTRS, since these
++ *! now belong to IO_ATTRS.
++ *! 21-Jan-2000 ag: Code review comments added.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 11-Dec-1999 ag: Added CHNL_MAXLOCKPAGES for CHNL_PrepareBuffer().
++ *! 04-Dec-1999 ag: Added CHNL_MAXEVTNAMELEN for i/o compl named event support.
++ *! 01-Nov-1999 ag: CHNL_MAXCHANNELS set to 16 for 16-bit DSPs.
++ *! 27-Oct-1997 cr: Expanded CHNL_MAXIRQ from 0x0f to 0xff.
++ *! 16-Jan-1997 gp: Moved symbols into here from chnldefs.h.
++ *! 03-Jan-1997 gp: Added CHNL_MAXIRQ define.
++ *! 09-Dec-1996 gp: Removed CHNL_STATEIDLE.
++ *! 15-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNLPRIV_
++#define CHNLPRIV_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/sync.h>
++
++/* CHNL Object validation signatures: */
++#define CHNL_MGRSIGNATURE 0x52474D43 /* "CMGR" (in reverse). */
++#define CHNL_SIGNATURE 0x4C4E4843 /* "CHNL" (in reverse). */
++
++/* Channel manager limits: */
++#define CHNL_MAXCHANNELS 32 /* Max channels available per transport */
++
++
++/*
++ * Trans port channel Id definitions:(must match dsp-side).
++ *
++ * For CHNL_MAXCHANNELS = 16:
++ *
++ * ChnlIds:
++ * 0-15 (PCPY) - transport 0)
++ * 16-31 (DDMA) - transport 1)
++ * 32-47 (ZCPY) - transport 2)
++ */
++#define CHNL_PCPY 0 /* Proc-copy transport 0 */
++
++#define CHNL_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* The following modes are private: */
++#define CHNL_MODEUSEREVENT 0x1000 /* User provided the channel event. */
++#define CHNL_MODEMASK 0x1001
++
++/* Higher level channel states: */
++#define CHNL_STATEREADY 0x0000 /* Channel ready for I/O. */
++#define CHNL_STATECANCEL 0x0001 /* I/O was cancelled. */
++#define CHNL_STATEEOS 0x0002 /* End Of Stream reached. */
++
++/* Determine if user supplied an event for this channel: */
++#define CHNL_IsUserEvent(mode) (mode & CHNL_MODEUSEREVENT)
++
++/* Macros for checking mode: */
++#define CHNL_IsInput(mode) (mode & CHNL_MODEFROMDSP)
++#define CHNL_IsOutput(mode) (!CHNL_IsInput(mode))
++
++/* Types of channel class libraries: */
++#define CHNL_TYPESM 1 /* Shared memory driver. */
++#define CHNL_TYPEBM 2 /* Bus Mastering driver. */
++
++/* Max string length of channel I/O completion event name - change if needed */
++#define CHNL_MAXEVTNAMELEN 32
++
++/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
++#define CHNL_MAXLOCKPAGES 64
++
++/* Channel info. */
++ struct CHNL_INFO {
++ struct CHNL_MGR *hChnlMgr; /* Owning channel manager. */
++ u32 dwID; /* Channel ID. */
++ HANDLE hEvent; /* Channel I/O completion event. */
++ /*Abstraction of I/O completion event.*/
++ struct SYNC_OBJECT *hSyncEvent;
++ u32 dwMode; /* Channel mode. */
++ u32 dwState; /* Current channel state. */
++ u32 cPosition; /* Total bytes transferred. */
++ u32 cIOCs; /* Number of IOCs in queue. */
++ u32 cIOReqs; /* Number of IO Requests in queue. */
++ u32 hProcess; /* Process owning this channel. */
++ /*
++ * Name of channel I/O completion event. Not required in Linux
++ */
++ char szEventName[CHNL_MAXEVTNAMELEN + 1];
++ } ;
++
++/* Channel manager info: */
++ struct CHNL_MGRINFO {
++ u32 dwType; /* Type of channel class library. */
++ /* Channel handle, given the channel id. */
++ struct CHNL_OBJECT *hChnl;
++ u32 cOpenChannels; /* Number of open channels. */
++ u32 cChannels; /* total # of chnls supported */
++ } ;
++
++/* Channel Manager Attrs: */
++ struct CHNL_MGRATTRS {
++ /* Max number of channels this manager can use. */
++ u32 cChannels;
++ u32 uWordSize; /* DSP Word size. */
++ } ;
++
++#endif /* CHNLPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/clk.h b/arch/arm/plat-omap/include/dspbridge/clk.h
+new file mode 100644
+index 0000000..4a23dab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/clk.h
+@@ -0,0 +1,155 @@
++/*
++ * clk.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.h ========
++ * Purpose: Provides Clock functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: Moved all clock functions from sync module.
++ */
++
++#ifndef _CLK_H
++#define _CLK_H
++
++ /* Generic TIMER object: */
++ struct TIMER_OBJECT;
++ enum SERVICES_ClkId {
++ SERVICESCLK_iva2_ck = 0,
++ SERVICESCLK_mailbox_ick,
++ SERVICESCLK_gpt5_fck,
++ SERVICESCLK_gpt5_ick,
++ SERVICESCLK_gpt6_fck,
++ SERVICESCLK_gpt6_ick,
++ SERVICESCLK_gpt7_fck,
++ SERVICESCLK_gpt7_ick,
++ SERVICESCLK_gpt8_fck,
++ SERVICESCLK_gpt8_ick,
++ SERVICESCLK_wdt3_fck,
++ SERVICESCLK_wdt3_ick,
++ SERVICESCLK_mcbsp1_fck,
++ SERVICESCLK_mcbsp1_ick,
++ SERVICESCLK_mcbsp2_fck,
++ SERVICESCLK_mcbsp2_ick,
++ SERVICESCLK_mcbsp3_fck,
++ SERVICESCLK_mcbsp3_ick,
++ SERVICESCLK_mcbsp4_fck,
++ SERVICESCLK_mcbsp4_ick,
++ SERVICESCLK_mcbsp5_fck,
++ SERVICESCLK_mcbsp5_ick,
++ SERVICESCLK_ssi_fck,
++ SERVICESCLK_ssi_ick,
++ SERVICESCLK_sys_32k_ck,
++ SERVICESCLK_sys_ck,
++ SERVICESCLK_NOT_DEFINED
++ } ;
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CLK initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void CLK_Exit(void);
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initializes private state of CLK module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CLK initialized.
++ */
++ extern bool CLK_Init(void);
++
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while enabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while disabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * Get the clock rate of requested clock.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while Getting the clock rate.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id,
++ u32 *speedMhz);
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * Set the requested clock to 32KHz.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while setting the clock parent to 32KHz.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id);
++ extern void SSI_Clk_Prepare(bool FLAG);
++
++/*
++ * ======== CLK_Get_RefCnt ========
++ * Purpose:
++ * get the reference count for the clock.
++ * Parameters:
++ * Returns:
++ * s32: Reference Count for the clock.
++ * DSP_EFAIL: Error occured while getting the reference count of a clock.
++ * Requires:
++ * Ensures:
++ */
++ extern s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmm.h b/arch/arm/plat-omap/include/dspbridge/cmm.h
+new file mode 100644
+index 0000000..0df8b83
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmm.h
+@@ -0,0 +1,420 @@
++/*
++ * cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cmm.h ========
++ * Purpose:
++ * The Communication Memory Management(CMM) module provides shared memory
++ * management services for DSP/BIOS Bridge data streaming and messaging.
++ * Multiple shared memory segments can be registered with CMM. Memory is
++ * coelesced back to the appropriate pool when a buffer is freed.
++ *
++ * The CMM_Xlator[xxx] functions are used for node messaging and data
++ * streaming address translation to perform zero-copy inter-processor
++ * data transfer(GPP<->DSP). A "translator" object is created for a node or
++ * stream object that contains per thread virtual address information. This
++ * translator info is used at runtime to perform SM address translation
++ * to/from the DSP address space.
++ *
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ * CMM_XlatorAllocBuf (Note #1 below)
++ * CMM_XlatorCreate "
++ * CMM_XlatorDelete "
++ * CMM_XlatorFreeBuf "
++ * CMM_XlatorTranslate "
++ *
++ *
++ * Notes:
++ * #1: Used by Node and Stream modules for SM address translation.
++ *
++ *! Revision History:
++ *! ================
++ *! 30-Jan-2002 ag Removed unused CMM_Alloc[Free]Desc & CMM_XlatorRegisterPa.
++ *! Renamed CMM_AllocBuf() to CMM_CallocBuf().
++ *! 29-Aug-2001 ag: Added dsp virt base and size to CMM_RegisterGPPSMSeg().
++ *! 12-Aug-2001 ag: Added CMM_UnRegisterGPP[DSP}SMSeg[s]().
++ *! 05-Dec-2000 ag: Added param to CMM_XlatorDelete() to force buf cleanup.
++ *! 30-Oct-2000 ag: Added conversion factor to CMM_RegisterDSP[GPP]SMSeg().
++ *! 12-Oct-2000 ag: Added CMM_Xlator[xxx] functions.
++ *! 10-Aug-2000 ag: Created.
++ *!
++ */
++
++#ifndef CMM_
++#define CMM_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/cmmdefs.h>
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate memory buffers that can be used for data streaming or
++ * messaging.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * uSize: Number of bytes to allocate.
++ * pAttr: Attributes of memory to allocate.
++ * ppBufVA: Address of where to place VA.
++ * Returns:
++ * Pointer to a zero'd block of SM memory;
++ * NULL if memory couldn't be allocated,
++ * or if cBytes == 0,
++ * Requires:
++ * Valid hCmmMgr.
++ * CMM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ *
++ */
++ extern void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr,
++ u32 uSize, struct CMM_ATTRS *pAttrs,
++ OUT void **ppBufVA);
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ * Parameters:
++ * phCmmMgr: Location to store a communication manager handle on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Comm mem manager attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Failed to initialize critical sect sync object.
++ *
++ * Requires:
++ * CMM_Init(void) called.
++ * phCmmMgr != NULL.
++ * pMgrAttrs->ulMinBlockSize >= 4 bytes.
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Destroy the communication memory manager object.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * bForce: Force deallocation of all cmm memory immediately if set TRUE.
++ * If FALSE, and outstanding allocations will return DSP_EFAIL
++ * status.
++ * Returns:
++ * DSP_SOK: CMM object & resources deleted.
++ * DSP_EFAIL: Unable to free CMM object due to outstanding allocation.
++ * DSP_EHANDLE: Unable to free CMM due to bad handle.
++ * Requires:
++ * CMM is initialized.
++ * hCmmMgr != NULL.
++ * Ensures:
++ * Memory resources used by Cmm Mgr are freed.
++ */
++ extern DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce);
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module. Cleanup CMM module if CMM cRef reaches zero.
++ * Parameters:
++ * n/a
++ * Returns:
++ * n/a
++ * Requires:
++ * CMM is initialized.
++ * Ensures:
++ */
++ extern void CMM_Exit(void);
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * pBuf: Pointer to memory allocated by CMM_CallocBuf().
++ * ulSegId: SM segment Id used in CMM_Calloc() attrs.
++ * Set to 0 to use default segment.
++ * Returns:
++ * DSP_SOK
++ * DSP_EFAIL
++ * Requires:
++ * CMM initialized.
++ * pBufPA != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr,
++ void *pBufPA, u32 ulSegId);
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the handle to the cmm mgr for the given device obj.
++ * Parameters:
++ * hProcessor: Handle to a Processor.
++ * phCmmMgr: Location to store the shared memory mgr handle on output.
++ *
++ * Returns:
++ * DSP_SOK: Cmm Mgr opaque handle returned.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * phCmmMgr != NULL
++ * hDevObject != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr);
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current SM and VM utilization information.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * pCmmInfo: Location to store the Cmm information on output.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG Invalid input argument.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo);
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CMM initialized.
++ */
++ extern bool CMM_Init(void);
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * lpGPPBasePA: GPP Base Physical address.
++ * ulSize: Size in GPP bytes.
++ * dwDSPAddrOffset GPP PA to DSP PA Offset.
++ * cFactor: Add offset if CMM_ADDTODSPPA, sub if CMM_SUBFROMDSPPA.
++ * dwDSPBase: DSP virtual base byte address.
++ * ulDSPSize: Size of DSP segment in bytes.
++ * pulSegId: Address to store segment Id.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hCmmMgr handle.
++ * DSP_EINVALIDARG: Invalid input argument.
++ * DSP_EFAIL: Unable to register.
++ * - On success *pulSegId is a valid SM segment ID.
++ * Requires:
++ * ulSize > 0
++ * pulSegId != NULL
++ * dwGPPBasePA != 0
++ * cFactor = CMM_ADDTODSPPA || cFactor = CMM_SUBFROMDSPPA
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ unsigned int dwGPPBasePA,
++ u32 ulSize,
++ u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor,
++ unsigned int dwDSPBase,
++ u32 ulDSPSize,
++ u32 *pulSegId,
++ u32 dwGPPBaseBA);
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * Unregister the given memory segment that was previously registered
++ * by CMM_RegisterGPPSMSeg.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * ulSegId Segment identifier returned by CMM_RegisterGPPSMSeg.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG: Invalid ulSegId.
++ * DSP_EFAIL: Unable to unregister for unknown reason.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ u32 ulSegId);
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ * Purpose:
++ * Allocate the specified SM buffer and create a local memory descriptor.
++ * Place on the descriptor on the translator's HaQ (Host Alloc'd Queue).
++ * Parameters:
++ * hXlator: Handle to a Xlator object.
++ * pVaBuf: Virtual address ptr(client context)
++ * uPaSize: Size of SM memory to allocate.
++ * Returns:
++ * Ptr to valid physical address(Pa) of uPaSize bytes, NULL if failed.
++ * Requires:
++ * pVaBuf != 0.
++ * uPaSize != 0.
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pVaBuf, u32 uPaSize);
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create a translator(xlator) object used for process specific Va<->Pa
++ * address translation. Node messaging and streams use this to perform
++ * inter-processor(GPP<->DSP) zero-copy data transfer.
++ * Parameters:
++ * phXlator: Address to place handle to a new Xlator handle.
++ * hCmmMgr: Handle to Cmm Mgr associated with this translator.
++ * pXlatorAttrs: Translator attributes used for the client NODE or STREAM.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Bad input Attrs.
++ * DSP_EMEMORY: Insufficient memory(local) for requested resources.
++ * Requires:
++ * phXlator != NULL
++ * hCmmMgr != NULL
++ * pXlatorAttrs != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs);
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Delete translator resources
++ * Parameters:
++ * hXlator: handle to translator.
++ * bForce: bForce = TRUE will free XLators SM buffers/dscriptrs.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * DSP_EFAIL: Unable to free translator resources.
++ * Requires:
++ * cRefs > 0
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator,
++ bool bForce);
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free SM buffer and descriptor.
++ * Does not free client process VM.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pBufVa Virtual address of PA to free.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pBufVa);
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get process specific "translator" address info.
++ * This is used to perform fast virtaul address translation
++ * for shared memory buffers between the GPP and DSP.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr: Virtual base address of segment.
++ * ulSize: Size in bytes.
++ * uSegId: Segment identifier of SM segment(s)
++ * bSetInfo Set xlator fields if TRUE, else return base addr
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * (cRefs > 0)
++ * (pAddr != NULL)
++ * (ulSize > 0)
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator,
++ IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId,
++ bool bSetInfo);
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ * Purpose:
++ * Perform address translation VA<->PA for the specified stream or
++ * message shared memory buffer.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr address of buffer to translate.
++ * xType Type of address xlation. CMM_PA2VA or CMM_VA2PA.
++ * Returns:
++ * Valid address on success, else NULL.
++ * Requires:
++ * cRefs > 0
++ * pAddr != NULL
++ * xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA)
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator,
++ void *pAddr, enum CMM_XLATETYPE xType);
++
++#endif /* CMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmmdefs.h b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+new file mode 100644
+index 0000000..a779377
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+@@ -0,0 +1,135 @@
++/*
++ * cmmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmmdefs.h ========
++ * Purpose:
++ * Global MEM constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-2001 ag CMM_KERNMAPTYPE added for dsp<->device process addr map'n.
++ *! This allows addr conversion from drvr process <-> DSP addr.
++ *! 29-Aug-2001 ag Added CMM_ALLSEGMENTS.
++ *! 08-Dec-2000 ag Added bus address conversion type CMM_POMAPEMIF2DSPBUS.
++ *! 05-Dec-2000 ag Added default CMM_DEFLTCONVFACTOR & CMM_DEFLTDSPADDROFFSET.
++ *! 29-Oct-2000 ag Added converstion factor for GPP DSP Pa translation.
++ *! 15-Oct-2000 ag Added address translator attributes and defaults.
++ *! 12-Jul-2000 ag Created.
++ */
++
++#ifndef CMMDEFS_
++#define CMMDEFS_
++
++#include <dspbridge/list.h>
++
++/* Cmm attributes used in CMM_Create() */
++ struct CMM_MGRATTRS {
++ /* Minimum SM allocation; default 32 bytes. */
++ u32 ulMinBlockSize;
++ } ;
++
++/* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
++ struct CMM_ATTRS {
++ u32 ulSegId; /* 1,2... are SM segments. 0 is not. */
++ u32 ulAlignment; /* 0,1,2,4....ulMinBlockSize */
++ } ;
++
++/*
++ * DSPPa to GPPPa Conversion Factor.
++ *
++ * For typical platforms:
++ * converted Address = PaDSP + ( cFactor * addressToConvert).
++ */
++ enum CMM_CNVTTYPE {
++ CMM_SUBFROMDSPPA = -1,
++ /* PreOMAP is special case: not simple offset */
++ CMM_POMAPEMIF2DSPBUS = 0,
++ CMM_ADDTODSPPA = 1
++ } ;
++
++#define CMM_DEFLTDSPADDROFFSET 0
++#define CMM_DEFLTCONVFACTOR CMM_POMAPEMIF2DSPBUS /* PreOMAP DSPBUS<->EMIF */
++#define CMM_ALLSEGMENTS 0xFFFFFF /* All SegIds */
++#define CMM_MAXGPPSEGS 1 /* Maximum # of SM segs */
++
++/*
++ * SMSEGs are SM segments the DSP allocates from.
++ *
++ * This info is used by the GPP to xlate DSP allocated PAs.
++ */
++
++ struct CMM_SEGINFO {
++ u32 dwSegBasePa; /* Start Phys address of SM segment */
++ /* Total size in bytes of segment: DSP+GPP */
++ u32 ulTotalSegSize;
++ u32 dwGPPBasePA; /* Start Phys addr of Gpp SM seg */
++ u32 ulGPPSize; /* Size of Gpp SM seg in bytes */
++ u32 dwDSPBaseVA; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ /* # of current GPP allocations from this segment */
++ u32 ulInUseCnt;
++ u32 dwSegBaseVa; /* Start Virt address of SM seg */
++
++ } ;
++
++/* CMM useful information */
++ struct CMM_INFO {
++ /* # of SM segments registered with this Cmm. */
++ u32 ulNumGPPSMSegs;
++ /* Total # of allocations outstanding for CMM */
++ u32 ulTotalInUseCnt;
++ /* Min SM block size allocation from CMM_Create() */
++ u32 ulMinBlockSize;
++ /* Info per registered SM segment. */
++ struct CMM_SEGINFO segInfo[CMM_MAXGPPSEGS];
++ } ;
++
++/* XlatorCreate attributes */
++ struct CMM_XLATORATTRS {
++ u32 ulSegId; /* segment Id used for SM allocations */
++ u32 dwDSPBufs; /* # of DSP-side bufs */
++ u32 dwDSPBufSize; /* size of DSP-side bufs in GPP bytes */
++ /* Vm base address alloc'd in client process context */
++ void *pVmBase;
++ /* dwVmSize must be >= (dwMaxNumBufs * dwMaxSize) */
++ u32 dwVmSize;
++ } ;
++
++/*
++ * Cmm translation types. Use to map SM addresses to process context.
++ */
++ enum CMM_XLATETYPE {
++ CMM_VA2PA = 0, /* Virtual to GPP physical address xlation */
++ CMM_PA2VA = 1, /* GPP Physical to virtual */
++ CMM_VA2DSPPA = 2, /* Va to DSP Pa */
++ CMM_PA2DSPPA = 3, /* GPP Pa to DSP Pa */
++ CMM_DSPPA2PA = 4, /* DSP Pa to GPP Pa */
++ } ;
++
++/*
++ * Used to "map" between device process virt addr and dsp addr.
++ */
++ enum CMM_KERNMAPTYPE {
++ CMM_KERNVA2DSP = 0, /* Device process context to dsp address. */
++ CMM_DSP2KERNVA = 1, /* Dsp address to device process context. */
++ } ;
++
++ struct CMM_OBJECT;
++ struct CMM_XLATOROBJECT;
++
++#endif /* CMMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cod.h b/arch/arm/plat-omap/include/dspbridge/cod.h
+new file mode 100644
+index 0000000..a8a12c6
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cod.h
+@@ -0,0 +1,433 @@
++/*
++ * cod.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.h ========
++ * Description:
++ * Code management module for DSPs. This module provides an interface
++ * interface for loading both static and dynamic code objects onto DSP
++ * systems.
++ *
++ * Public Functions:
++ * COD_Close
++ * COD_Create
++ * COD_Delete
++ * COD_Exit
++ * COD_GetBaseLib
++ * COD_GetBaseName
++ * COD_GetLoader
++ * COD_GetSection
++ * COD_GetSymValue
++ * COD_Init
++ * COD_LoadBase
++ * COD_Open
++ * COD_OpenBase
++ * COD_ReadSection
++ * COD_UnloadSection
++ *
++ * Note:
++ * Currently, only static loading is supported.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Changed DBL to DBLL
++ *! 07-Aug-2002 jeh: Added COD_GetBaseName().
++ *! 17-Jul-2002 jeh: Added COD_Open(), COD_Close().
++ *! 15-Mar-2002 jeh: Added DBL_Flags param to COD_OpenBase().
++ *! 19-Oct-2001 jeh: Added COD_GetBaseLib, COD_GetLoader, (left in
++ *! COD_LoadSection(), COD_UnloadSection(), since they
++ *! may be needed for BridgeLite).
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 11-Jan-2001 jeh: Added COD_OpenBase.
++ *! 29-Sep-2000 kc: Added size param to COD_ReadSection for input buffer
++ *! validation.
++ *! 02-Aug-2000 kc: Added COD_ReadSection.
++ *! 04-Sep-1997 gp: Added CDECL identifier to COD_WRITEFXN (for NT)..
++ *! 18-Aug-1997 cr: Added explicit CDECL identifier.
++ *! 28-Oct-1996 gp: Added COD_GetSection.
++ *! 30-Jul-1996 gp: Added envp[] argument to COD_LoadBase().
++ *! 12-Jun-1996 gp: Moved OUT param first in _Create(). Updated _Create()
++ *! call to take a ZLFileName. Moved COD_ processor types
++ *! to CFG.
++ *! 29-May-1996 gp: Changed WCD_STATUS to DSP_STATUS. Removed include's.
++ *! 07-May-1996 mg: Created.
++ *
++ */
++
++#ifndef COD_
++#define COD_
++
++#include <dspbridge/dblldefs.h>
++
++#define COD_MAXPATHLENGTH 255
++#define COD_TRACEBEG "SYS_PUTCBEG"
++#define COD_TRACEEND "SYS_PUTCEND"
++#define COD_TRACESECT "trace"
++#define COD_TRACEBEGOLD "PUTCBEG"
++#define COD_TRACEENDOLD "PUTCEND"
++
++#define COD_NOLOAD DBLL_NOLOAD
++#define COD_SYMB DBLL_SYMB
++
++/* Flags passed to COD_Open */
++ typedef DBLL_Flags COD_FLAGS;
++
++/* COD code manager handle */
++ struct COD_MANAGER;
++
++/* COD library handle */
++ struct COD_LIBRARYOBJ;
++
++/* COD attributes */
++ struct COD_ATTRS {
++ u32 ulReserved;
++ } ;
++
++/*
++ * Function prototypes for writing memory to a DSP system, allocating
++ * and freeing DSP memory.
++ */
++ typedef u32(*COD_WRITEFXN) (void *pPrivRef, u32 ulDspAddr,
++ void *pBuf, u32 ulNumBytes,
++ u32 nMemSpace);
++
++
++/*
++ * ======== COD_Close ========
++ * Purpose:
++ * Close a library opened with COD_Open().
++ * Parameters:
++ * lib - Library handle returned by COD_Open().
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid lib.
++ * Ensures:
++ *
++ */
++ extern void COD_Close(struct COD_LIBRARYOBJ *lib);
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system. This object can be
++ * used to load an initial program image with arguments that can later
++ * be expanded with dynamically loaded object files.
++ * Symbol table information is managed by this object and can be retrieved
++ * using the COD_GetSymValue() function.
++ * Parameters:
++ * phManager: created manager object
++ * pstrZLFile: ZL DLL filename, of length < COD_MAXPATHLENGTH.
++ * attrs: attributes to be used by this object. A NULL value
++ * will cause default attrs to be used.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOZLFUNCTIONS: Could not initialize ZL functions.
++ * COD_E_ZLCREATEFAILED: ZL_Create failed.
++ * DSP_ENOTIMPL: attrs was not NULL. We don't yet support
++ * non default values of attrs.
++ * Requires:
++ * COD module initialized.
++ * pstrZLFile != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Create(OUT struct COD_MANAGER **phManager,
++ char *pstrZLFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs);
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * Ensures:
++ */
++ extern void COD_Delete(struct COD_MANAGER *hManager);
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ * Parameters:
++ * None.
++ * Returns:
++ * None.
++ * Requires:
++ * COD initialized.
++ * Ensures:
++ * Resources acquired in COD_Init(void) are freed.
++ */
++ extern void COD_Exit(void);
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * plib: location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * plib != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib);
++
++/*
++ * ======== COD_GetBaseName ========
++ * Purpose:
++ * Get the name of the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pszName: location to store library name on output.
++ * uSize: size of name buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Buffer too small.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pszName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager,
++ char *pszName, u32 uSize);
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pulEntry: pointer to location for entry point
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pulEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager,
++ u32 *pulEntry);
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBL loader.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * phLoader: location to store loader handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * phLoader != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader);
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ * Parameters:
++ * lib Library handle returned from COD_Open().
++ * pstrSect: name of the section, with or without leading "."
++ * puAddr: Location to store address.
++ * puLen: Location to store length.
++ * Returns:
++ * DSP_SOK: Success
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * puAddr != NULL;
++ * puLen != NULL;
++ * Ensures:
++ * DSP_SOK: *puAddr and *puLen contain the address and length of the
++ * section.
++ * else: *puAddr == 0 and *puLen == 0;
++ *
++ */
++ extern DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT u32 *puAddr,
++ OUT u32 *puLen);
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ * Parameters:
++ * lib: library handle returned from COD_Open().
++ * pstrSymbol: name of the symbol
++ * value: value of the symbol
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * Valid hManager.
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hManager,
++ IN char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ * Parameters:
++ * None.
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public COD functions.
++ */
++ extern bool COD_Init(void);
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * nArgc: number of arguments in the args array
++ * args: array of strings for arguments to DSP program
++ * writeFxn: board-specific function to write data to DSP system
++ * pArb: arbitrary pointer to be passed as first arg to writeFxn
++ * envp: array of environment strings for DSP exec.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * COD_E_LOADFAILED: Failed to load code onto target.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * nArgc > 0.
++ * aArgs != NULL.
++ * aArgs[0] != NULL.
++ * pfnWrite != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_LoadBase(struct COD_MANAGER *hManager,
++ u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb,
++ char *envp[]);
++
++
++/*
++ * ======== COD_Open ========
++ * Purpose:
++ * Open a library for reading sections. Does not load or set the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: COD_NOLOAD (don't load symbols) or COD_SYMB (load
++ * symbols).
++ * pLib: Handle returned that can be used in calls to COD_Close
++ * and COD_GetSection.
++ * Returns:
++ * S_OK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * flags == COD_NOLOAD || flags == COD_SYMB.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Open(struct COD_MANAGER *hMgr,
++ IN char *pszCoffPath,
++ COD_FLAGS flags,
++ OUT struct COD_LIBRARYOBJ **pLib);
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections. Does not load the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: Specifies whether to load symbols.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++extern DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags);
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ * Parameters:
++ * hManager - manager in which to search for the symbol
++ * pstrSect - name of the section, with or without leading "."
++ * pstrContent - buffer to store content of the section.
++ * Returns:
++ * DSP_SOK: on success, error code on failure
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_READFAILED: Failed to read content of code section.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * pstrContent != NULL;
++ * Ensures:
++ * DSP_SOK: *pstrContent stores the content of the named section.
++ */
++ extern DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT char *pstrContent,
++ IN u32 cContentSize);
++
++
++
++#endif /* COD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/csl.h b/arch/arm/plat-omap/include/dspbridge/csl.h
+new file mode 100644
+index 0000000..b90d6ff
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/csl.h
+@@ -0,0 +1,135 @@
++/*
++ * csl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== csl.h ========
++ * Purpose:
++ * Platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_AnsiToWchar
++ * CSL_ByteSwap
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtok
++ * CSL_Strtokr
++ * CSL_WcharToAnsi
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap().
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen().
++ *! 20-Sep-1999 ag: Added CSL_Wchar2Ansi().
++ *! 19-Jan-1998 cr: Code review cleanup (mostly documentation fixes).
++ *! 29-Dec-1997 cr: Changed CSL_lowercase to CSL_Uppercase, added
++ *! CSL_AnsiToWchar.
++ *! 30-Sep-1997 cr: Added explicit cdecl descriptors to fxn definitions.
++ *! 25-Jun-1997 cr: Added CSL_strcmp.
++ *! 12-Jun-1996 gp: Created.
++ */
++
++#ifndef CSL_
++#define CSL_
++
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CSL initialized.
++ * Ensures:
++ * Resources acquired in CSL_Init(void) are freed.
++ */
++ extern void CSL_Exit(void);
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CSL functions.
++ */
++ extern bool CSL_Init(void);
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ * Parameters:
++ * pstrNumber: Buffer to store converted string.
++ * dwNum: Number to convert.
++ * Returns:
++ * Requires:
++ * pstrNumber must be able to hold at least three characters.
++ * Ensures:
++ * pstrNumber will be null terminated.
++ */
++ extern void CSL_NumToAscii(OUT char *pstrNumber, IN u32 dwNum);
++
++
++/*
++ * ======== CSL_Strtok ========
++ * Purpose:
++ * Tokenize a NULL terminated string
++ * Parameters:
++ * ptstrSrc: pointer to string.
++ * szSeparators: pointer to a string of seperators
++ * Returns:
++ * char *
++ * Requires:
++ * CSL initialized.
++ * ptstrSrc is a valid string pointer.
++ * szSeparators is a valid string pointer.
++ * Ensures:
++ */
++ extern char *CSL_Strtok(IN char *ptstrSrc,
++ IN CONST char *szSeparators);
++
++/*
++ * ======== CSL_Strtokr ========
++ * Purpose:
++ * Re-entrant version of strtok.
++ * Parameters:
++ * pstrSrc: Pointer to string. May be NULL on subsequent calls.
++ * szSeparators: Pointer to a string of seperators
++ * ppstrCur: Location to store start of string for next call to
++ * to CSL_Strtokr.
++ * Returns:
++ * char * (the token)
++ * Requires:
++ * CSL initialized.
++ * szSeparators != NULL
++ * ppstrCur != NULL
++ * Ensures:
++ */
++ extern char *CSL_Strtokr(IN char *pstrSrc,
++ IN CONST char *szSeparators,
++ OUT char **ppstrCur);
++
++#endif /* CSL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbc.h b/arch/arm/plat-omap/include/dspbridge/dbc.h
+new file mode 100644
+index 0000000..0e6a67d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbc.h
+@@ -0,0 +1,66 @@
++/*
++ * dbc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbc.h ========
++ * Purpose:
++ * "Design by Contract" programming macros.
++ *
++ * Public Functions:
++ * DBC_Assert
++ * DBC_Require
++ * DBC_Ensure
++ *
++ * Notes:
++ * Requires that the GT->ERROR function has been defaulted to a valid
++ * error handler for the given execution environment.
++ *
++ * Does not require that GT_init() be called.
++ *
++ *! Revision History:
++ *! ================
++ *! 11-Aug-2000 ag: Removed include <dspbridge/std.h>
++ *! 22-Apr-1996 gp: Created.
++ */
++
++#ifndef DBC_
++#define DBC_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++/* Assertion Macros: */
++#if GT_TRACE
++
++#include <dspbridge/gt.h>
++
++#define DBC_Assert(exp) \
++ if (!(exp)) \
++ printk("%s, line %d: Assertion (" #exp ") failed.\n", \
++ __FILE__, __LINE__)
++#define DBC_Require DBC_Assert /* Function Precondition. */
++#define DBC_Ensure DBC_Assert /* Function Postcondition. */
++
++#else
++
++#define DBC_Assert(exp)
++#define DBC_Require(exp)
++#define DBC_Ensure(exp)
++
++#endif /* DEBUG */
++
++#endif /* DBC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcd.h b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+new file mode 100644
+index 0000000..fbc3870
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+@@ -0,0 +1,388 @@
++/*
++ * dbdcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdcd.h ========
++ * Description:
++ * Defines the DSP/BIOS Bridge Configuration Database (DCD) API.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 24-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 05-Aug-2002 jeh Added DCD_GetObjects().
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 22-Apr-2002 jeh Added DCD_GetLibraryName().
++ *! 03-Apr-2001 sg Changed error names to have DCD_E* format.
++ *! 13-Feb-2001 kc Name changed from dcdbs.h to dbdcd.h.
++ *! 12-Dec-2000 kc Added DCD_AutoUnregister.
++ *! 09-Nov-2000 kc Updated usage of DCD_EnumerateObject.
++ *! 30-Oct-2000 kc Added DCD_AutoRegister. Updated error DCD error codes.
++ *! 29-Sep-2000 kc Incorporated code review comments. See
++ *! /src/reviews/dcd_review.txt.
++ *! 26-Jul-2000 kc Created.
++ *!
++ */
++
++#ifndef DBDCD_
++#define DBDCD_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/host_os.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * This function automatically registers DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects to be registered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * This function automatically unregisters DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing
++ * DCD objects to be unregistered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto unregistration.
++ */
++ extern DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * This function creates a DCD module manager.
++ * Parameters:
++ * pszZlDllName: Pointer to a DLL name string.
++ * phDcdMgr: A pointer to a DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for DCD manager handle.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * pszZlDllName is non-NULL.
++ * phDcdMgr is non-NULL.
++ * Ensures:
++ * A DCD manager handle is created.
++ */
++ extern DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr);
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * This function destroys a DCD module manager.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid DCD manager handle.
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr);
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * This function enumerates currently visible DSP/BIOS Bridge objects
++ * and returns the UUID and type of each enumerated object.
++ * Parameters:
++ * cIndex: The object enumeration index.
++ * objType: Type of object to enumerate.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to enumerate through the DCD database.
++ * DSP_SENUMCOMPLETE: Enumeration completed. This is not an error code.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a valid pointer.
++ * Ensures:
++ * Details:
++ * This function can be used in conjunction with DCD_GetObjectDef to
++ * retrieve object properties.
++ */
++ extern DSP_STATUS DCD_EnumerateObject(IN s32 cIndex,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid);
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * This function cleans up the DCD module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern void DCD_Exit(void);
++
++/*
++ * ======== DCD_GetDepLibs ========
++ * Purpose:
++ * Given the uuid of a library and size of array of uuids, this function
++ * fills the array with the uuids of all dependent libraries of the input
++ * library.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * numLibs: Size of uuid array (number of library uuids).
++ * pDepLibUuids: Array of dependent library uuids to be filled in.
++ * pPersistentDepLibs: Array indicating if corresponding lib is persistent.
++ * phase: phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pDepLibUuids != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs,
++ OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ * Purpose:
++ * Given the uuid of a library, determine its number of dependent
++ * libraries.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * pNumLibs: Size of uuid array (number of library uuids).
++ * pNumPersLibs: number of persistent dependent library.
++ * phase: Phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pNumLibs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * This function returns the name of a (dynamic) library for a given
++ * UUID.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique DSP/BIOS
++ * Bridge object.
++ * pstrLibName: Buffer to hold library name.
++ * pdwSize: Contains buffer size. Set to string size on output.
++ * phase: Which phase to load
++ * fPhaseSplit: Are phases in multiple libraries
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pstrLibName != NULL.
++ * pUuid != NULL
++ * pdwSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName,
++ IN OUT u32 *pdwSize,
++ IN enum NLDR_PHASE phase,
++ OUT bool *fPhaseSplit);
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * This function returns the properties/attributes of a DSP/BIOS Bridge
++ * object.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique
++ * DSP/BIOS Bridge object.
++ * objType: The type of DSP/BIOS Bridge object to be
++ * referenced (node, processor, etc).
++ * pObjDef: Pointer to an object definition structure. A
++ * union of various possible DCD object types.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDPARSESECT: Unable to parse content of object code section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDGETSECT: Unable to access object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EFAIL: General failure.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle.
++ * Requires:
++ * DCD initialized.
++ * pObjUuid is non-NULL.
++ * pObjDef is non-NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef);
++
++/*
++ * ======== DCD_GetObjects ========
++ * Purpose:
++ * This function finds all DCD objects specified in a special
++ * COFF section called ".dcd_register", and for each object,
++ * call a "register" function. The "register" function may perform
++ * various actions, such as 1) register nodes in the node database, 2)
++ * unregister nodes from the node database, and 3) add overlay nodes.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects.
++ * registerFxn: Callback fxn to be applied on each located
++ * DCD object.
++ * handle: Handle to pass to callback.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find .dcd_register section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn,
++ void *handle);
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * This function initializes DCD.
++ * Parameters:
++ * Returns:
++ * FALSE: Initialization failed.
++ * TRUE: Initialization succeeded.
++ * Requires:
++ * Ensures:
++ * DCD initialized.
++ */
++ extern bool DCD_Init(void);
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * This function registers a DSP/BIOS Bridge object in the DCD database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS
++ * Bridge object.
++ * objType: Type of object.
++ * pszPathName: Path to the object's COFF file.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to register object.
++ * Requires:
++ * DCD initialized.
++ * pUuid and szPathName are non-NULL values.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName);
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Purpose:
++ * This function de-registers a valid DSP/BIOS Bridge object from the DCD
++ * database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS Bridge
++ * object.
++ * objType: Type of object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to de-register the specified object.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a non-NULL value.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType);
++
++#endif /* _DBDCD_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcddef.h b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+new file mode 100644
+index 0000000..91b1c45
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+@@ -0,0 +1,94 @@
++/*
++ * dbdcddef.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcddef.h ========
++ * Description:
++ * DCD (DSP/BIOS Bridge Configuration Database) constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Dec-2003 map Moved and renamed DCD_OBJTYPE to DSP_DCDOBJTYPE in dbdefs.h
++ *! 05-Dec-2002 map Added DCD_CREATELIBTYPE, DCD_EXECUTELIBTYPE,
++ * DCD_DELETELIBTYPE
++ *! 24-Feb-2003 kc Updated REG entry names to DspBridge.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! 05-Aug-2002 jeh Added DCD_REGISTERFXN.
++ *! 19-Apr-2002 jeh Added DCD_LIBRARYTYPE to DCD_OBJTYPE, dynamic load
++ *! properties to DCD_NODEPROPS.
++ *! 29-Jul-2001 ag Added extended procObj.
++ *! 13-Feb-2001 kc: Named changed from dcdbsdef.h dbdcddef.h.
++ *! 12-Dec-2000 jeh Added DAIS iAlg name to DCD_NODEPROPS.
++ *! 30-Oct-2000 kc: Added #defines for DCD_AutoRegister function.
++ *! 05-Sep-2000 jeh Added DCD_NODEPROPS.
++ *! 12-Aug-2000 kc: Incoroporated the use of types defined in <dspdefs.h>.
++ *! 29-Jul-2000 kc: Created.
++ */
++
++#ifndef DBDCDDEF_
++#define DBDCDDEF_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/mgrpriv.h> /* for MGR_PROCESSOREXTINFO */
++
++/*
++ * The following defines are critical elements for the DCD module:
++ *
++ * - DCD_REGKEY enables DCD functions to locate registered DCD objects.
++ * - DCD_REGISTER_SECTION identifies the COFF section where the UUID of
++ * registered DCD objects are stored.
++ */
++#define DCD_REGKEY "Software\\TexasInstruments\\DspBridge\\DCD"
++#define DCD_REGISTER_SECTION ".dcd_register"
++
++/* DCD Manager Object */
++ struct DCD_MANAGER;
++
++/* DCD Node Properties */
++ struct DCD_NODEPROPS {
++ struct DSP_NDBPROPS ndbProps;
++ u32 uMsgSegid;
++ u32 uMsgNotifyType;
++ char *pstrCreatePhaseFxn;
++ char *pstrDeletePhaseFxn;
++ char *pstrExecutePhaseFxn;
++ char *pstrIAlgName;
++
++ /* Dynamic load properties */
++ u16 usLoadType; /* Static, dynamic, overlay */
++ u32 ulDataMemSegMask; /* Data memory requirements */
++ u32 ulCodeMemSegMask; /* Code memory requirements */
++ } ;
++
++/* DCD Generic Object Type */
++ struct DCD_GENERICOBJ {
++ union dcdObjUnion {
++ struct DCD_NODEPROPS nodeObj; /* node object. */
++ /* processor object. */
++ struct DSP_PROCESSORINFO procObj;
++ /* extended proc object (private) */
++ struct MGR_PROCESSOREXTINFO extProcObj;
++ } objData;
++ } ;
++
++/* DCD Internal Callback Type */
++ typedef DSP_STATUS(*DCD_REGISTERFXN) (IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++
++#endif /* DBDCDDEF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+new file mode 100644
+index 0000000..9782693
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+@@ -0,0 +1,580 @@
++/*
++ * dbdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdefs.h ========
++ * Description:
++ * Global definitions and constants for DSP/BIOS Bridge.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added MAPATTR & ELEM_SIZE for Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Added processor ID numbers for DSP and IVA
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE. Updated IsValid*Event macros.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! Removed unused DSP_ENUMLASTNODE define.
++ *! 13-Feb-2002 jeh Added uSysStackSize to DSP_NDBPROPS.
++ *! 23-Jan-2002 ag Added #define DSP_SHMSEG0.
++ *! 12-Dec-2001 ag Added DSP_ESTRMMODE error code.
++ *! 04-Dec-2001 jeh Added DSP_ENOTCONNECTED error code.
++ *! 10-Dec-2001 kc: Modified macros and definitions to disable DSP_POSTMESSAGE.
++ *! 01-Nov-2001 jeh Added DSP_EOVERLAYMEMORY.
++ *! 18-Oct-2001 ag Added DSP_STRMMODE type.
++ *! Added DSP_ENOTSHAREDMEM.
++ *! 21-Sep-2001 ag Added additional error codes.
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 11-May-2001 jeh Changed DSP_NODE_MIN_PRIORITY from 0 to 1. Removed hNode
++ *! from DSP_NODEINFO.
++ *! 02-Apr-2001 sg Added missing error codes, rearranged codes, switched to
++ *! hex offsets, renamed some codes to match API spec.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Dec-2000 ag: Added DSP_RMSxxx user available message command codes.
++ *! 09-Nov-2000 rr: Added DSP_PROCEESORRESTART define; Removed DSP_PBUFFER.
++ *! Added DSP_DCD_ENOAUTOREGISTER, DSP_EUSER1-16, DSP_ESTRMFUL
++ *! Removed DSP_EDONE. Macros's modified.
++ *! 23-Oct-2000 jeh Replaced DSP_STREAMSTATECHANGE with DSP_STREAMDONE.
++ *! 09-Oct-2000 jeh Updated to version 0.9 DSP Bridge API spec.
++ *! 29-Sep-2000 kc Added error codes for DCD and REG to simplify use of
++ *! these codes within the RM module.
++ *! 27-Sep-2000 jeh Added segid, alignment, uNumBufs to DSP_STREAMATTRIN.
++ *! 29-Aug-2000 jeh Added DSP_NODETYPE enum, changed DSP_EALREADYATTACHED to
++ *! DSP_EALREADYCONNECTED. Changed scStreamConnection[1]
++ *! to scStreamConnection[16] in DSP_NODEINFO structure.
++ *! Added DSP_NOTIFICATION, DSP_STRMATTR. PSTRING changed
++ *! back to TCHAR * and moved to dbtype.h.
++ *! 11-Aug-2000 rr: Macros to check valid events and notify masks added.
++ *! 09-Aug-2000 rr: Changed PSTRING to *s8
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! 20-Jul-2000 rr: Updated to version 0.8
++ *! 17-Jul-2000 rr: New PROC states added to the DSP_PROCSTATE.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef DBDEFS_
++#define DBDEFS_
++
++#include <linux/types.h>
++
++#include <dspbridge/dbtype.h> /* GPP side type definitions */
++#include <dspbridge/std.h> /* DSP/BIOS type definitions */
++#include <dspbridge/rms_sh.h> /* Types shared between GPP and DSP */
++
++#define PG_SIZE_4K 4096
++#define PG_MASK(pg_size) (~((pg_size)-1))
++#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
++#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
++
++/* API return value and calling convention */
++#define DBAPI DSP_STATUS
++
++/* Infinite time value for the uTimeout parameter to DSPStream_Select() */
++#define DSP_FOREVER (-1)
++
++/* Maximum length of node name, used in DSP_NDBPROPS */
++#define DSP_MAXNAMELEN 32
++
++/* uNotifyType values for the RegisterNotify() functions. */
++#define DSP_SIGNALEVENT 0x00000001
++
++/* Types of events for processors */
++#define DSP_PROCESSORSTATECHANGE 0x00000001
++#define DSP_PROCESSORATTACH 0x00000002
++#define DSP_PROCESSORDETACH 0x00000004
++#define DSP_PROCESSORRESTART 0x00000008
++
++/* DSP exception events (DSP/BIOS and DSP MMU fault) */
++#define DSP_MMUFAULT 0x00000010
++#define DSP_SYSERROR 0x00000020
++#define DSP_EXCEPTIONABORT 0x00000300
++
++/* IVA exception events (IVA MMU fault) */
++#define IVA_MMUFAULT 0x00000040
++/* Types of events for nodes */
++#define DSP_NODESTATECHANGE 0x00000100
++#define DSP_NODEMESSAGEREADY 0x00000200
++
++/* Types of events for streams */
++#define DSP_STREAMDONE 0x00001000
++#define DSP_STREAMIOCOMPLETION 0x00002000
++
++/* Handle definition representing the GPP node in DSPNode_Connect() calls */
++#define DSP_HGPPNODE 0xFFFFFFFF
++
++/* Node directions used in DSPNode_Connect() */
++#define DSP_TONODE 1
++#define DSP_FROMNODE 2
++
++/* Define Node Minimum and Maximum Priorities */
++#define DSP_NODE_MIN_PRIORITY 1
++#define DSP_NODE_MAX_PRIORITY 15
++
++/* Pre-Defined Message Command Codes available to user: */
++#define DSP_RMSUSERCODESTART RMS_USER /* Start of RMS user cmd codes */
++/* end of user codes */
++#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
++#define DSP_RMSBUFDESC RMS_BUFDESC /* MSG contains SM buffer description */
++
++/* Shared memory identifier for MEM segment named "SHMSEG0" */
++#define DSP_SHMSEG0 (u32)(-1)
++
++/* Processor ID numbers */
++#define DSP_UNIT 0
++#define IVA_UNIT 1
++
++#define DSPWORD unsigned char
++#define DSPWORDSIZE sizeof(DSPWORD)
++
++/* Success & Failure macros */
++#define DSP_SUCCEEDED(Status) likely((s32)(Status) >= 0)
++#define DSP_FAILED(Status) unlikely((s32)(Status) < 0)
++
++/* Power control enumerations */
++#define PROC_PWRCONTROL 0x8070
++
++#define PROC_PWRMGT_ENABLE (PROC_PWRCONTROL + 0x3)
++#define PROC_PWRMGT_DISABLE (PROC_PWRCONTROL + 0x4)
++
++/* Bridge Code Version */
++#define BRIDGE_VERSION_CODE 333
++
++#define MAX_PROFILES 16
++
++/* Types defined for 'Bridge API */
++ typedef u32 DSP_STATUS; /* API return code type */
++
++ typedef HANDLE DSP_HNODE; /* Handle to a DSP Node object */
++ typedef HANDLE DSP_HPROCESSOR; /* Handle to a Processor object */
++ typedef HANDLE DSP_HSTREAM; /* Handle to a Stream object */
++
++ typedef u32 DSP_PROCFAMILY; /* Processor family */
++ typedef u32 DSP_PROCTYPE; /* Processor type (w/in family) */
++ typedef u32 DSP_RTOSTYPE; /* Type of DSP RTOS */
++
++/* Handy Macros */
++#define IsValidProcEvent(x) (((x) == 0) || (((x) & (DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR)) && \
++ !((x) & ~(DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR))))
++
++#define IsValidNodeEvent(x) (((x) == 0) || (((x) & (DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY)) && \
++ !((x) & ~(DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY))))
++
++#define IsValidStrmEvent(x) (((x) == 0) || (((x) & (DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION)) && \
++ !((x) & ~(DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION))))
++
++#define IsValidNotifyMask(x) ((x) & DSP_SIGNALEVENT)
++
++/* The Node UUID structure */
++ struct DSP_UUID {
++ u32 ulData1;
++ u16 usData2;
++ u16 usData3;
++ u8 ucData4;
++ u8 ucData5;
++ u8 ucData6[6];
++ };
++
++/* DCD types */
++ enum DSP_DCDOBJTYPE {
++ DSP_DCDNODETYPE,
++ DSP_DCDPROCESSORTYPE,
++ DSP_DCDLIBRARYTYPE,
++ DSP_DCDCREATELIBTYPE,
++ DSP_DCDEXECUTELIBTYPE,
++ DSP_DCDDELETELIBTYPE
++ } ;
++
++/* Processor states */
++ enum DSP_PROCSTATE {
++ PROC_STOPPED,
++ PROC_LOADED,
++ PROC_RUNNING,
++ PROC_ERROR
++ } ;
++
++/*
++ * Node types: Message node, task node, xDAIS socket node, and
++ * device node. _NODE_GPP is used when defining a stream connection
++ * between a task or socket node and the GPP.
++ *
++ */
++ enum NODE_TYPE {
++ NODE_DEVICE,
++ NODE_TASK,
++ NODE_DAISSOCKET,
++ NODE_MESSAGE,
++ NODE_GPP
++ } ;
++
++/*
++ * ======== NODE_STATE ========
++ * Internal node states.
++ */
++ enum NODE_STATE {
++ NODE_ALLOCATED,
++ NODE_CREATED,
++ NODE_RUNNING,
++ NODE_PAUSED,
++ NODE_DONE,
++ NODE_CREATING,
++ NODE_STARTING,
++ NODE_PAUSING,
++ NODE_TERMINATING,
++ NODE_DELETING,
++ } ;
++
++/* Stream states */
++ enum DSP_STREAMSTATE {
++ STREAM_IDLE,
++ STREAM_READY,
++ STREAM_PENDING,
++ STREAM_DONE
++ } ;
++
++/* Stream connect types */
++ enum DSP_CONNECTTYPE {
++ CONNECTTYPE_NODEOUTPUT,
++ CONNECTTYPE_GPPOUTPUT,
++ CONNECTTYPE_NODEINPUT,
++ CONNECTTYPE_GPPINPUT
++ } ;
++
++/* Stream mode types */
++ enum DSP_STRMMODE {
++ STRMMODE_PROCCOPY, /* Processor(s) copy stream data payloads */
++ STRMMODE_ZEROCOPY, /* Strm buffer ptrs swapped no data copied */
++ STRMMODE_LDMA, /* Local DMA : OMAP's System-DMA device */
++ STRMMODE_RDMA /* Remote DMA: OMAP's DSP-DMA device */
++ } ;
++
++/* Resource Types */
++ enum DSP_RESOURCEINFOTYPE {
++ DSP_RESOURCE_DYNDARAM = 0,
++ DSP_RESOURCE_DYNSARAM,
++ DSP_RESOURCE_DYNEXTERNAL,
++ DSP_RESOURCE_DYNSRAM,
++ DSP_RESOURCE_PROCLOAD
++ } ;
++
++/* Memory Segment Types */
++ enum DSP_MEMTYPE {
++ DSP_DYNDARAM = 0,
++ DSP_DYNSARAM,
++ DSP_DYNEXTERNAL,
++ DSP_DYNSRAM
++ } ;
++
++/* Memory Flush Types */
++ enum DSP_FLUSHTYPE {
++ PROC_INVALIDATE_MEM = 0,
++ PROC_WRITEBACK_MEM,
++ PROC_WRITEBACK_INVALIDATE_MEM,
++ } ;
++
++/* Memory Segment Status Values */
++ struct DSP_MEMSTAT {
++ u32 ulSize;
++ u32 ulTotalFreeSize;
++ u32 ulLenMaxFreeBlock;
++ u32 ulNumFreeBlocks;
++ u32 ulNumAllocBlocks;
++ } ;
++
++/* Processor Load information Values */
++ struct DSP_PROCLOADSTAT {
++ u32 uCurrLoad;
++ u32 uPredictedLoad;
++ u32 uCurrDspFreq;
++ u32 uPredictedFreq;
++ } ;
++
++/* Attributes for STRM connections between nodes */
++ struct DSP_STRMATTR {
++ u32 uSegid; /* Memory segment on DSP to allocate buffers */
++ u32 uBufsize; /* Buffer size (DSP words) */
++ u32 uNumBufs; /* Number of buffers */
++ u32 uAlignment; /* Buffer alignment */
++ u32 uTimeout; /* Timeout for blocking STRM calls */
++ enum DSP_STRMMODE lMode; /* mode of stream when opened */
++ /* DMA chnl id if DSP_STRMMODE is LDMA or RDMA */
++ u32 uDMAChnlId;
++ u32 uDMAPriority; /* DMA channel priority 0=lowest, >0=high */
++ } ;
++
++/* The DSP_CBDATA structure */
++ struct DSP_CBDATA {
++ u32 cbData;
++ u8 cData[1];
++ } ;
++
++/* The DSP_MSG structure */
++ struct DSP_MSG {
++ u32 dwCmd;
++ u32 dwArg1;
++ u32 dwArg2;
++ } ;
++
++/* The DSP_RESOURCEREQMTS structure for node's resource requirements */
++ struct DSP_RESOURCEREQMTS {
++ u32 cbStruct;
++ u32 uStaticDataSize;
++ u32 uGlobalDataSize;
++ u32 uProgramMemSize;
++ u32 uWCExecutionTime;
++ u32 uWCPeriod;
++ u32 uWCDeadline;
++ u32 uAvgExectionTime;
++ u32 uMinimumPeriod;
++ } ;
++
++/*
++ * The DSP_STREAMCONNECT structure describes a stream connection
++ * between two nodes, or between a node and the GPP
++ */
++ struct DSP_STREAMCONNECT {
++ u32 cbStruct;
++ enum DSP_CONNECTTYPE lType;
++ u32 uThisNodeStreamIndex;
++ DSP_HNODE hConnectedNode;
++ struct DSP_UUID uiConnectedNodeID;
++ u32 uConnectedNodeStreamIndex;
++ } ;
++
++ struct DSP_NODEPROFS {
++ u32 ulHeapSize;
++ } ;
++
++/* The DSP_NDBPROPS structure reports the attributes of a node */
++ struct DSP_NDBPROPS {
++ u32 cbStruct;
++ struct DSP_UUID uiNodeID;
++ char acName[DSP_MAXNAMELEN];
++ enum NODE_TYPE uNodeType;
++ u32 bCacheOnGPP;
++ struct DSP_RESOURCEREQMTS dspResourceReqmts;
++ s32 iPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uMessageDepth;
++ u32 uNumInputStreams;
++ u32 uNumOutputStreams;
++ u32 uTimeout;
++ u32 uCountProfiles; /* Number of supported profiles */
++ /* Array of profiles */
++ struct DSP_NODEPROFS aProfiles[MAX_PROFILES];
++ u32 uStackSegName; /* Stack Segment Name */
++ } ;
++
++ /* The DSP_NODEATTRIN structure describes the attributes of a
++ * node client */
++ struct DSP_NODEATTRIN {
++ u32 cbStruct;
++ s32 iPriority;
++ u32 uTimeout;
++ u32 uProfileID;
++ /* Reserved, for Bridge Internal use only */
++ u32 uHeapSize;
++ void *pGPPVirtAddr; /* Reserved, for Bridge Internal use only */
++ } ;
++
++ /* The DSP_NODEINFO structure is used to retrieve information
++ * about a node */
++ struct DSP_NODEINFO {
++ u32 cbStruct;
++ struct DSP_NDBPROPS nbNodeDatabaseProps;
++ u32 uExecutionPriority;
++ enum NODE_STATE nsExecutionState;
++ DSP_HNODE hDeviceOwner;
++ u32 uNumberStreams;
++ struct DSP_STREAMCONNECT scStreamConnection[16];
++ u32 uNodeEnv;
++ } ;
++
++ /* The DSP_NODEATTR structure describes the attributes of a node */
++ struct DSP_NODEATTR {
++ u32 cbStruct;
++ struct DSP_NODEATTRIN inNodeAttrIn;
++ u32 uInputs;
++ u32 uOutputs;
++ struct DSP_NODEINFO iNodeInfo;
++ } ;
++
++/*
++ * Notification type: either the name of an opened event, or an event or
++ * window handle.
++ */
++ struct DSP_NOTIFICATION {
++ char *psName;
++ HANDLE handle;
++ } ;
++
++/* The DSP_PROCESSORATTRIN structure describes the attributes of a processor */
++ struct DSP_PROCESSORATTRIN{
++ u32 cbStruct;
++ u32 uTimeout;
++ } ;
++
++ enum chipTypes {
++ DSPTYPE_55 = 6,
++ IVA_ARM7 = 0x97,
++ DSPTYPE_64 = 0x99
++ };
++
++/*
++ * The DSP_PROCESSORINFO structure describes basic capabilities of a
++ * DSP processor
++ */
++ struct DSP_PROCESSORINFO {
++ u32 cbStruct;
++ DSP_PROCFAMILY uProcessorFamily;
++ DSP_PROCTYPE uProcessorType;
++ u32 uClockRate;
++ u32 ulInternalMemSize;
++ u32 ulExternalMemSize;
++ u32 uProcessorID;
++ DSP_RTOSTYPE tyRunningRTOS;
++ s32 nNodeMinPriority;
++ s32 nNodeMaxPriority;
++ } ;
++
++/* Error information of last DSP exception signalled to the GPP */
++ struct DSP_ERRORINFO {
++ u32 dwErrMask;
++ u32 dwVal1;
++ u32 dwVal2;
++ u32 dwVal3;
++ } ;
++
++/* The DSP_PROCESSORSTATE structure describes the state of a DSP processor */
++ struct DSP_PROCESSORSTATE {
++ u32 cbStruct;
++ enum DSP_PROCSTATE iState;
++ struct DSP_ERRORINFO errInfo;
++ } ;
++
++/*
++ * The DSP_RESOURCEINFO structure is used to retrieve information about a
++ * processor's resources
++ */
++ struct DSP_RESOURCEINFO {
++ u32 cbStruct;
++ enum DSP_RESOURCEINFOTYPE uResourceType;
++ union {
++ u32 ulResource;
++ struct DSP_MEMSTAT memStat;
++ struct DSP_PROCLOADSTAT procLoadStat;
++ } result;
++ } ;
++
++/*
++ * The DSP_STREAMATTRIN structure describes the attributes of a stream,
++ * including segment and alignment of data buffers allocated with
++ * DSPStream_AllocateBuffers(), if applicable
++ */
++ struct DSP_STREAMATTRIN {
++ u32 cbStruct;
++ u32 uTimeout;
++ u32 uSegment;
++ u32 uAlignment;
++ u32 uNumBufs;
++ enum DSP_STRMMODE lMode;
++ u32 uDMAChnlId;
++ u32 uDMAPriority;
++ } ;
++
++/* The DSP_BUFFERATTR structure describes the attributes of a data buffer */
++ struct DSP_BUFFERATTR {
++ u32 cbStruct;
++ u32 uSegment;
++ u32 uAlignment;
++ } ;
++
++/*
++ * The DSP_STREAMINFO structure is used to retrieve information
++ * about a stream.
++ */
++ struct DSP_STREAMINFO {
++ u32 cbStruct;
++ u32 uNumberBufsAllowed;
++ u32 uNumberBufsInStream;
++ u32 ulNumberBytes;
++ HANDLE hSyncObjectHandle;
++ enum DSP_STREAMSTATE ssStreamState;
++ } ;
++
++/* DMM MAP attributes
++It is a bit mask with each bit value indicating a specific attribute
++bit 0 - GPP address type (user virtual=0, physical=1)
++bit 1 - MMU Endianism (Big Endian=1, Little Endian=0)
++bit 2 - MMU mixed page attribute (Mixed/ CPUES=1, TLBES =0)
++bit 3 - MMU element size = 8bit (valid only for non mixed page entries)
++bit 4 - MMU element size = 16bit (valid only for non mixed page entries)
++bit 5 - MMU element size = 32bit (valid only for non mixed page entries)
++bit 6 - MMU element size = 64bit (valid only for non mixed page entries)
++*/
++
++/* Types of mapping attributes */
++
++/* MPU address is virtual and needs to be translated to physical addr */
++#define DSP_MAPVIRTUALADDR 0x00000000
++#define DSP_MAPPHYSICALADDR 0x00000001
++
++/* Mapped data is big endian */
++#define DSP_MAPBIGENDIAN 0x00000002
++#define DSP_MAPLITTLEENDIAN 0x00000000
++
++/* Element size is based on DSP r/w access size */
++#define DSP_MAPMIXEDELEMSIZE 0x00000004
++
++/*
++ * Element size for MMU mapping (8, 16, 32, or 64 bit)
++ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
++ */
++#define DSP_MAPELEMSIZE8 0x00000008
++#define DSP_MAPELEMSIZE16 0x00000010
++#define DSP_MAPELEMSIZE32 0x00000020
++#define DSP_MAPELEMSIZE64 0x00000040
++
++#define DSP_MAPVMALLOCADDR 0x00000080
++
++#define DSP_MAPDONOTLOCK 0x00000100
++
++
++#define GEM_CACHE_LINE_SIZE 128
++#define GEM_L1P_PREFETCH_SIZE 128
++
++#endif /* DBDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbg.h b/arch/arm/plat-omap/include/dspbridge/dbg.h
+new file mode 100644
+index 0000000..7f44ff9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbg.h
+@@ -0,0 +1,110 @@
++/*
++ * dbg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbg.h ========
++ * Purpose:
++ * Provide debugging services for 'Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Printf
++ * DBG_Trace
++ *
++ * Notes:
++ * WMD's must not call DBG_Init or DBG_Exit.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Feb-2000 rr: DBG Levels redefined.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 15-May-1996 gp: Created.
++ */
++
++#ifndef DBG_
++#define DBG_
++#include <dspbridge/host_os.h>
++#include <linux/types.h>
++
++/* Levels of trace debug messages: */
++#define DBG_ENTER (u8)(0x01) /* Function entry point. */
++#define DBG_LEVEL1 (u8)(0x02) /* Display debugging state/varibles */
++#define DBG_LEVEL2 (u8)(0x04) /* Display debugging state/varibles */
++#define DBG_LEVEL3 (u8)(0x08) /* Display debugging state/varibles */
++#define DBG_LEVEL4 (u8)(0x10) /* Display debugging state/varibles */
++#define DBG_LEVEL5 (u8)(0x20) /* Module Init, Exit */
++#define DBG_LEVEL6 (u8)(0x40) /* Warn SERVICES Failures */
++#define DBG_LEVEL7 (u8)(0x80) /* Warn Critical Errors */
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void DBG_Exit(void);
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Initializes private state of DBG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ */
++ extern bool DBG_Init(void);
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ * Parameters:
++ * bLevel: Trace level.
++ * pstrFormat: sprintf-style format string.
++ * ...: Arguments for format string.
++ * Returns:
++ * DSP_SOK: Success, or trace level masked.
++ * DSP_EFAIL: On Error.
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Debug message is printed to debugger output window, if trace level
++ * is unmasked.
++ */
++ extern DSP_STATUS DBG_Trace(IN u8 bLevel, IN char *pstrFormat, ...);
++#else
++
++#define DBG_Exit(void)
++#define DBG_Init(void) true
++#define DBG_Trace(bLevel, pstrFormat, args...)
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++#endif /* DBG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbl.h b/arch/arm/plat-omap/include/dspbridge/dbl.h
+new file mode 100644
+index 0000000..19847f9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbl.h
+@@ -0,0 +1,354 @@
++/*
++ * dbl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Pass DBL_Symbol pointer to DBL_getAddr, DBL_getCAddr
++ *! to accomodate dynamic loader library.
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 24-Sep-2001 jeh Code review changes.
++ *! 07-Sep-2001 jeh Added DBL_LoadSect(), DBL_UnloadSect().
++ *! 05-Jun-2001 jeh Created based on zl.h.
++ */
++
++#ifndef DBL_
++#define DBL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbldefs.h>
++
++/*
++ * ======== DBL_close ========
++ * Close library opened with DBL_open.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_close(struct DBL_LibraryObj *lib);
++
++/*
++ * ======== DBL_create ========
++ * Create a target object by specifying the alloc, free, and write
++ * functions for the target.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++ extern DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++ extern void DBL_delete(struct DBL_TargetObj *target);
++
++/*
++ * ======== DBL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++ extern void DBL_exit(void);
++
++/*
++ * ======== DBL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_getAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_getCAddr ========
++ * Get address of "C" name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getEntry ========
++ * Get program entry point.
++ *
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * pEntry - Location to store entry address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry);
++
++/*
++ * ======== DBL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++
++/*
++ * ======== DBL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++ extern bool DBL_init(void);
++
++/*
++ * ======== DBL_load ========
++ * Add symbols/code/data defined in file to that already present on
++ * the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * flags - Specifies whether loading code, data, and/or symbols.
++ * attrs - May contain write, alloc, and free functions.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry);
++
++/*
++ * ======== DBL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_open ========
++ * DBL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBL_load()/DBL_unload().
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * file - Name of file to open.
++ * flags - Specifies whether to load symbols now.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * struct DBL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++ extern DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file,
++ DBL_Flags flags,
++ struct DBL_LibraryObj **pLib);
++
++/*
++ * ======== DBL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name,
++ char *pBuf, u32 size);
++
++/*
++ * ======== DBL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_setAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_unload ========
++ * Remove the symbols/code/data corresponding to the library lib.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_unload(struct DBL_LibraryObj *lib,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++#endif /* DBL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbldefs.h b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+new file mode 100644
+index 0000000..79b9e54
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+@@ -0,0 +1,155 @@
++/*
++ * dbldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLDEFS_
++#define DBLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBL_SYMB 0x1 /* load symbols */
++#define DBL_CODE 0x2 /* load code */
++#define DBL_DATA 0x4 /* load data */
++#define DBL_DYNAMIC 0x8 /* dynamic load */
++#define DBL_BSS 0x20 /* Unitialized section */
++
++#define DBL_MAXPATHLENGTH 255
++
++
++
++/*
++ * ======== DBL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBL_Flags;
++
++/*
++ * ======== DBL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req, bool reserved);
++
++
++
++/*
++ * ======== DBL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBL_LogWriteFxn) (void *handle, struct DBL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++
++/*
++ * ======== DBL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBL_Symbol **sym);
++
++
++/*
++ * ======== DBL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBL_Attrs ========
++ */
++struct DBL_Attrs {
++ DBL_AllocFxn alloc;
++ DBL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++
++ DBL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbll.h b/arch/arm/plat-omap/include/dspbridge/dbll.h
+new file mode 100644
+index 0000000..c3aa212
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbll.h
+@@ -0,0 +1,70 @@
++/*
++ * dbll.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbll.h ========
++ * DSP/BIOS Bridge Dynamic load library module interface. Function header
++ * comments are in the file dblldefs.h.
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function comments (now in dblldefs.h).
++ *! 17-Apr-2002 jeh Created based on zl.h.
++ */
++
++#ifndef DBLL_
++#define DBLL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dblldefs.h>
++
++ extern void DBLL_close(struct DBLL_LibraryObj *lib);
++ extern DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_delete(struct DBLL_TarObj *target);
++ extern void DBLL_exit(void);
++ extern bool DBLL_getAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern void DBLL_getAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern bool DBLL_getCAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++ extern bool DBLL_init(void);
++ extern DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry);
++ extern DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++ extern DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib,
++ char *name,
++ char *pBuf, u32 size);
++ extern void DBLL_setAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_unload(struct DBLL_LibraryObj *lib,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++
++#endif /* DBLL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dblldefs.h b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+new file mode 100644
+index 0000000..2361ce8
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+@@ -0,0 +1,509 @@
++/*
++ * dblldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dblldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map Consolidated DBL into DBLL name
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLLDEFS_
++#define DBLLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBLL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBLL_SYMB 0x1 /* load symbols */
++#define DBLL_CODE 0x2 /* load code */
++#define DBLL_DATA 0x4 /* load data */
++#define DBLL_DYNAMIC 0x8 /* dynamic load */
++#define DBLL_BSS 0x20 /* Unitialized section */
++
++#define DBLL_MAXPATHLENGTH 255
++
++
++/*
++ * ======== DBLL_Target ========
++ *
++ */
++struct DBLL_TarObj;
++
++/*
++ * ======== DBLL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBLL_Flags;
++
++/*
++ * ======== DBLL_Library ========
++ *
++ */
++struct DBLL_LibraryObj;
++
++/*
++ * ======== DBLL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBLL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBLL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBLL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBLL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBLL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBLL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req,
++ bool reserved);
++
++/*
++ * ======== DBLL_CloseFxn ========
++ */
++typedef s32(*DBLL_FCloseFxn) (void *);
++
++/*
++ * ======== DBLL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBLL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBLL_FOpenFxn ========
++ */
++typedef void *(*DBLL_FOpenFxn) (const char *, const char *);
++
++/*
++ * ======== DBLL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBLL_LogWriteFxn)(void *handle, struct DBLL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++/*
++ * ======== DBLL_ReadFxn ========
++ */
++typedef s32(*DBLL_ReadFxn) (void *, size_t, size_t, void *);
++
++/*
++ * ======== DBLL_SeekFxn ========
++ */
++typedef s32(*DBLL_SeekFxn) (void *, long, int);
++
++/*
++ * ======== DBLL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBLL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBLL_Symbol **sym);
++
++/*
++ * ======== DBLL_TellFxn ========
++ */
++typedef s32(*DBLL_TellFxn) (void *);
++
++/*
++ * ======== DBLL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBLL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBLL_Attrs ========
++ */
++struct DBLL_Attrs {
++ DBLL_AllocFxn alloc;
++ DBLL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBLL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++ bool baseImage;
++ DBLL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBLL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++/*
++ * ======== DBLL_close ========
++ * Close library opened with DBLL_open.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_CloseFxn) (struct DBLL_LibraryObj *library);
++
++/*
++ * ======== DBLL_create ========
++ * Create a target object, specifying the alloc, free, and write functions.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++typedef DSP_STATUS(*DBLL_CreateFxn)(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++typedef void(*DBLL_DeleteFxn) (struct DBLL_TarObj *target);
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++typedef void(*DBLL_ExitFxn) (void);
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid library.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_GetAttrsFxn) (struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of "C" name on the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetCAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_GetSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ u32 *addr, u32 *size);
++
++/*
++ * ======== DBLL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++typedef bool(*DBLL_InitFxn) (void);
++
++/*
++ * ======== DBLL_load ========
++ * Load library onto the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * flags - Load code, data and/or symbols.
++ * attrs - May contain alloc, free, and write function.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadFxn) (struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *entry);
++
++/*
++ * ======== DBLL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * DSP_ENOTIMPL: Function not implemented.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_open ========
++ * DBLL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBLL_load()/DBLL_unload().
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * file - Name of file to open.
++ * flags - If flags & DBLL_SYMB, load symbols.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * DBLL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++typedef DSP_STATUS(*DBLL_OpenFxn) (struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++
++/*
++ * ======== DBLL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_ReadSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ char *content, u32 uContentSize);
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_SetAttrsFxn)(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unload ========
++ * Unload library loaded with DBLL_load().
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_UnloadFxn) (struct DBLL_LibraryObj *library,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * DSP_ENOTIMPL
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_UnloadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++struct DBLL_Fxns {
++ DBLL_CloseFxn closeFxn;
++ DBLL_CreateFxn createFxn;
++ DBLL_DeleteFxn deleteFxn;
++ DBLL_ExitFxn exitFxn;
++ DBLL_GetAttrsFxn getAttrsFxn;
++ DBLL_GetAddrFxn getAddrFxn;
++ DBLL_GetCAddrFxn getCAddrFxn;
++ DBLL_GetSectFxn getSectFxn;
++ DBLL_InitFxn initFxn;
++ DBLL_LoadFxn loadFxn;
++ DBLL_LoadSectFxn loadSectFxn;
++ DBLL_OpenFxn openFxn;
++ DBLL_ReadSectFxn readSectFxn;
++ DBLL_SetAttrsFxn setAttrsFxn;
++ DBLL_UnloadFxn unloadFxn;
++ DBLL_UnloadSectFxn unloadSectFxn;
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbof.h b/arch/arm/plat-omap/include/dspbridge/dbof.h
+new file mode 100644
+index 0000000..54f4250
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbof.h
+@@ -0,0 +1,117 @@
++/*
++ * dbof.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbof.h ========
++ * Description:
++ * Defines and typedefs for DSP/BIOS Bridge Object File Format (DBOF).
++ *
++ *! Revision History
++ *! ================
++ *! 12-Jul-2002 jeh Added defines for DBOF_SectHdr page.
++ *! 12-Oct-2001 jeh Converted to std.h format.
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 06-Jul-2001 jeh Created.
++ */
++
++#ifndef DBOF_
++#define DBOF_
++
++/* Enough to hold DCD section names: 32 digit ID + underscores */
++#define DBOF_DCDSECTNAMELEN 40
++
++/* Values for DBOF_SectHdr page field. */
++#define DBOF_PROGRAM 0
++#define DBOF_DATA 1
++#define DBOF_CINIT 2
++
++/*
++ * ======== DBOF_FileHdr ========
++ */
++ struct DBOF_FileHdr {
++ u32 magic; /* COFF magic number */
++ u32 entry; /* Program entry point */
++ u16 numSymbols; /* Number of bridge symbols */
++ u16 numDCDSects; /* Number of DCD sections */
++ u16 numSects; /* Number of sections to load */
++ u16 numOvlySects; /* Number of overlay sections */
++ u32 symOffset; /* Offset in file to symbols */
++ u32 dcdSectOffset; /* Offset to DCD sections */
++ u32 loadSectOffset; /* Offset to loadable sections */
++ u32 ovlySectOffset; /* Offset to overlay data */
++ u16 version; /* DBOF version number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_DCDSectHdr ========
++ */
++ struct DBOF_DCDSectHdr {
++ u32 size; /* Sect size (target MAUs) */
++ char name[DBOF_DCDSECTNAMELEN]; /* DCD section name */
++ } ;
++
++/*
++ * ======== DBOF_OvlySectHdr ========
++ */
++ struct DBOF_OvlySectHdr {
++ u16 nameLen; /* Length of section name */
++ u16 numCreateSects; /* # of sects loaded for create phase */
++ u16 numDeleteSects; /* # of sects loaded for delete phase */
++ u16 numExecuteSects; /* # of sects loaded for execute phase */
++
++ /*
++ * Number of sections where load/unload phase is not specified.
++ * These sections will be loaded when create phase sects are
++ * loaded, and unloaded when the delete phase is unloaded.
++ */
++ u16 numOtherSects;
++ u16 resvd; /* Reserved for future use */
++ };
++
++/*
++ * ======== DBOF_OvlySectData ========
++ */
++ struct DBOF_OvlySectData {
++ u32 loadAddr; /* Section load address */
++ u32 runAddr; /* Section run address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Memory page number */
++ u16 resvd; /* Reserved */
++ } ;
++
++/*
++ * ======== DBOF_SectHdr ========
++ */
++ struct DBOF_SectHdr {
++ u32 addr; /* Section address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Page number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_SymbolHdr ========
++ */
++ struct DBOF_SymbolHdr {
++ u32 value; /* Symbol value */
++ u16 nameLen; /* Length of symbol name */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++#endif /* DBOF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbreg.h b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+new file mode 100644
+index 0000000..d311b88
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+@@ -0,0 +1,113 @@
++/*
++ * dbreg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbreg.h ========
++ * Purpose:
++ * Registry keys for use in Linux. This is the clearinghouse for
++ * registry definitions, hopefully eliminating overlapping between
++ * modules.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Apr-2003 vp: Added macro for subkey TCWORDSWAP.
++ *! 21-Mar-2003 sb: Added macro for subkey SHMSize
++ *! 27-Aug-2001 jeh Added WSXREG_LOADERFILENAME.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 29-Nov-2000 rr: Added WSXREG_DSPTYPE_55 as 6.
++ *! 06-Sep-2000 jeh: Added WSXREG_CHNLOFFSET, WSXREG_NUMCHNLS,
++ *! WSXREG_CHNLBUFSIZE.
++ *! 26-Aug-2000 rr: MEMBASE expanded to 9 entries.
++ *! 26-Jul-2000 rr: Added WSXREG_DCDNAME for the DCD Dll name. It will
++ *! live under WSXREG_WINSPOXCONFIG.
++ *! 17-Jul-2000 rr: REG_MGR_OBJECT and REG_DRV_OBJECT defined. They
++ *! are stored in the Registrty under WSXREG_WINSPOXCONFIG
++ *! when they are created in DSP_Init. WSXREG_DEVOBJECT
++ *! and WSXREG_MGROBJECT defined.
++ *! 11-Dec-1999 ag: Renamed Isa to IsaBus due to conflict with ceddk.h.
++ *! 12-Nov-1999 rr: New Registry Defnitions.
++ *! 15-Oct-1999 rr: New entry for DevObject created. WSXREG_DEVOBJECT
++ *! under WSXREG_DDSPDRIVERPATH
++ *! 10-Nov-1997 cr: Added WSXREG_INFPATH, WSXREG_WINDEVICEPATH,
++ *! WSXREG_WINCURVERSION
++ *! 21-Oct-1997 cr: Added WSXREG_BUSTYPE.
++ *! 08-Sep-1997 cr: Added WSXREG_SERVICES, WSXREG_SERVICENAME and
++ *! WSXREG_CLASSINDEX.
++ *! 30-Aug-1997 cr: Added WSXREG_SOFTWAREPATHNT & WSXREG_WBCLASSGUID.
++ *! 24-Mar-1997 gp: Added MAXCHIPINFOSUBKEY def.
++ *! 18-Feb-1997 cr: Changed Version1.1 -> Version1.0
++ *! 12-Feb-1997 cr: Changed WinSPOX -> WinBRIDGE.
++ *! 11-Dec-1996 gp: Added Perf key name in WinSPOX Config.
++ *! 22-Jul-1996 gp: Added Trace key name.
++ *! 30-May-1996 cr: Created.
++ */
++
++#ifndef DBREG_
++#define DBREG_ 1 /* Defined as "1" so InstallShield programs compile. */
++
++#define REG_MGR_OBJECT 1
++#define REG_DRV_OBJECT 2
++/* general registry definitions */
++#define MAXREGPATHLENGTH 255 /* Max registry path length. Also the
++ max registry value length. */
++#define DSPTYPE_55 6 /* This is the DSP Chip type for 55 */
++#define DSPTYPE_64 0x99
++#define IVA_ARM7 0x97 /* This is the DSP Chip type for IVA/ARM7 */
++
++#define DSPPROCTYPE_C55 5510
++#define DSPPROCTYPE_C64 6410
++#define IVAPROCTYPE_ARM7 470
++/* registry */
++#define DEVNODESTRING "DevNode" /* u32 devnode */
++#define CONFIG "Software\\TexasInstruments\\DirectDSP\\Config"
++#define DRVOBJECT "DrvObject"
++#define MGROBJECT "MgrObject"
++#define CLASS "Device" /* device class */
++#define TRACE "Trace" /* GT Trace settings. */
++#define PERFR "Perf" /* Enable perf bool. */
++#define ROOT "Root" /* root dir */
++
++/* MiniDriver related definitions */
++/* The following definitions are under "Drivers\\DirectDSP\\Device\\XXX "
++ * Where XXX is the device or board name */
++
++#define WMDFILENAME "MiniDriver" /* WMD entry name */
++#define CHIPTYPE "ChipType" /* Chip type */
++#define CHIPNUM "NumChips" /* Number of chips */
++#define NUMPROCS "NumOfProcessors" /* Number of processors */
++#define DEFEXEC "DefaultExecutable" /* Default executable */
++#define AUTOSTART "AutoStart" /* Statically load flag */
++#define IVAAUTOSTART "IvaAutoStart" /* Statically load flag */
++#define BOARDNAME "BoardName" /* Name of the Board */
++#define UNITNUMBER "UnitNumber" /* Unit # of the Board */
++#define BUSTYPE "BusType" /* Bus type board is on */
++#define BUSNUMBER "BusNumber" /* Bus number board is on */
++#define CURRENTCONFIG "CurrentConfig" /* Current resources */
++#define PCIVENDEVID "VendorDeviceId" /* The board's id */
++#define INFPATH "InfPath" /* wmd's inf filename */
++#define DEVOBJECT "DevObject"
++#define ZLFILENAME "ZLFileName" /* Name of ZL file */
++#define WORDSIZE "WordSize" /* NumBytes in DSP Word */
++#define SHMSIZE "SHMSize" /* Size of SHM reservd on MPU */
++#define IVAEXTMEMSIZE "IVAEXTMEMSize" /* IVA External Memeory size */
++#define TCWORDSWAP "TCWordSwap" /* Traffic Contoller Word Swap */
++#define DSPRESOURCES "DspTMSResources" /* C55 DSP resurces on OMAP */
++#define IVA1RESOURCES "ARM7IvaResources" /* ARM7 IVA resurces on OMAP */
++#define PHYSMEMPOOLBASE "PhysicalMemBase" /* Physical mem passed to driver */
++#define PHYSMEMPOOLSIZE "PhysicalMemSize" /* Physical mem passed to driver */
++
++#endif /* DBREG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbtype.h b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+new file mode 100644
+index 0000000..b4953a0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+@@ -0,0 +1,103 @@
++/*
++ * dbtype.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbtype.h ========
++ * Description:
++ * This header defines data types for DSP/BIOS Bridge APIs and device
++ * driver modules. It also defines the Hungarian
++ * prefix to use for each base type.
++ *
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Nov-2002 gp: Purpose -> Description in file header.
++ *! 13-Feb-2001 kc: Name changed from ddsptype.h dbtype.h.
++ *! 09-Oct-2000 jeh Added CHARACTER.
++ *! 11-Aug-2000 ag: Added 'typedef void void'.
++ *! 08-Apr-2000 ww: Cloned.
++ */
++
++#ifndef DBTYPE_
++#define DBTYPE_
++
++/*============================================================================*/
++/* Argument specification syntax */
++/*============================================================================*/
++
++#ifndef IN
++#define IN /* Following parameter is for input. */
++#endif
++
++#ifndef OUT
++#define OUT /* Following parameter is for output. */
++#endif
++
++#ifndef OPTIONAL
++#define OPTIONAL /* Function may optionally use previous parameter. */
++#endif
++
++#ifndef CONST
++#define CONST const
++#endif
++
++/*============================================================================*/
++/* Boolean constants */
++/*============================================================================*/
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++/*============================================================================*/
++/* NULL (Definition is language specific) */
++/*============================================================================*/
++
++#ifndef NULL
++#define NULL ((void *)0) /* Null pointer. */
++#endif
++
++/*============================================================================*/
++/* NULL character (normally used for string termination) */
++/*============================================================================*/
++
++#ifndef NULL_CHAR
++#define NULL_CHAR '\0' /* Null character. */
++#endif
++
++/*============================================================================*/
++/* Basic Type definitions (with Prefixes for Hungarian notation) */
++/*============================================================================*/
++
++#ifndef OMAPBRIDGE_TYPES
++#define OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++
++typedef void *HANDLE; /* h */
++
++#define TEXT(x) x
++
++#define DLLIMPORT
++#define DLLEXPORT
++
++/* Define DSPAPIDLL correctly in dspapi.h */
++#define _DSPSYSDLL32_
++
++#endif /* DBTYPE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dehdefs.h b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+new file mode 100644
+index 0000000..06e5582
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+@@ -0,0 +1,42 @@
++/*
++ * dehdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dehdefs.h ========
++ * Purpose:
++ * Definition for mini-driver module DEH.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Dec-2001 ag: added #include <dspbridge/mbx_sh.h> for shared mailbox codes.
++ *! 10-Dec-2001 kc: added DEH error base value and error max value.
++ *! 11-Sep-2001 kc: created.
++ */
++
++#ifndef DEHDEFS_
++#define DEHDEFS_
++
++#include <dspbridge/mbx_sh.h> /* shared mailbox codes */
++
++/* DEH object manager */
++ struct DEH_MGR;
++
++/* Magic code used to determine if DSP signaled exception. */
++#define DEH_BASE MBX_DEH_BASE
++#define DEH_USERS_BASE MBX_DEH_USERS_BASE
++#define DEH_LIMIT MBX_DEH_LIMIT
++
++#endif /* _DEHDEFS_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dev.h b/arch/arm/plat-omap/include/dspbridge/dev.h
+new file mode 100644
+index 0000000..5f468c9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dev.h
+@@ -0,0 +1,785 @@
++/*
++ * dev.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.h ========
++ * Description:
++ * 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetMsgMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ *! Revision History:
++ *! ================
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature - Dev_GetDmmMgr
++ *! 09-Feb-2004 vp Added functions required for IVA
++ *! 25-Feb-2003 swa PMGR Code Review changes incorporated
++ *! 05-Nov-2001 kc: Added DEV_GetDehMgr.
++ *! 05-Dec-2000 jeh Added DEV_SetMsgMgr.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added DEV_GetMsgMgr.
++ *! 05-Oct-2000 rr: DEV_Create2 & DEV_Destroy2 Added.
++ *! 02-Oct-2000 rr: Added DEV_GetNodeManager.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr() for shared memory management.
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 05-Nov-1999 kc: Updated function prototypes.
++ *! 08-Oct-1997 cr: Added explicit CDECL function identifiers.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 22-Oct-1996 gp: Added DEV_CleanupProcessState().
++ *! 29-May-1996 gp: Changed DEV_HDEVNODE --> CFG_HDEVNODE.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef DEV_
++#define DEV_
++
++/* ----------------------------------- Module Dependent Headers */
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dmm.h>
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/devdefs.h>
++
++
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject by ZL in pArb, then calls the
++ * device's WMD_BRD_Write() function.
++ * Parameters:
++ * pArb: Handle to a Device Object.
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * Number of bytes written. Returns 0 if the DEV_hObject passed in via
++ * pArb is invalid.
++ * Requires:
++ * DEV Initialized.
++ * pHostBuf != NULL
++ * Ensures:
++ */
++ extern u32 DEV_BrdWriteFxn(void *pArb,
++ u32 ulDspAddr,
++ void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for a
++ * 'Bridge device.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES
++ *pHostConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_CreateIVADevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for IVA.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateIVADevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr != NULL
++ * else hDevObject->hNodeMgr == NULL
++ */
++ extern DSP_STATUS DEV_Create2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr == NULL
++ * else DSP_EFAIL.
++ */
++ extern DSP_STATUS DEV_Destroy2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * DSP_EFAIL: The WMD failed it's WMD_DEV_Destroy() function.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr);
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phCodMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phCodMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phCodMgr contains a handle to a COD manager object.
++ * else: *phCodMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr);
++
++/*
++ * ======== DEV_GetDehMgr ========
++ * Purpose:
++ * Retrieve the DEH manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * *phDehMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDehMgr != NULL.
++ * DEH Initialized.
++ * Ensures:
++ * DSP_SOK: *phDehMgr contains a handle to a DEH manager object.
++ * else: *phDehMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr);
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: In Win95, returns a DEVNODE in *hDevNode; In NT, ???
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode);
++
++/*
++ * ======== DEV_GetDevType ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject,
++ u32 *devType);
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV.
++ * Parameters:
++ * Returns:
++ * NULL if there are no device objects stored; else
++ * a valid DEV_HOBJECT.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetFirst(void);
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *ppIntfFxns: Ptr to location to store fxn interface.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * ppIntfFxns != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *ppIntfFxns contains a pointer to the WMD interface;
++ * else: *ppIntfFxns is NULL.
++ */
++ extern DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns);
++
++/*
++ * ======== DEV_GetIOMgr ========
++ * Purpose:
++ * Retrieve the handle to the IO manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to an IO manager object.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phMgr);
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ * Parameters:
++ * hDevObject: Handle to the device object returned from a previous
++ * call to DEV_GetFirst() or DEV_GetNext().
++ * Returns:
++ * NULL if there are no further device objects on the list or hDevObject
++ * was invalid;
++ * else the next valid DEV_HOBJECT in the list.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ * Purpose:
++ * Retrieve the MSG Manager Handle from the DevObject.
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phMsgMgr: Location where MSG Manager handle will be returned.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Valid hDevObject.
++ * phNodeMgr != NULL.
++ * Ensures:
++ */
++ extern void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr);
++
++/*
++ * ========= DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle from the DevObject. It is an
++ * accessor function
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phNodeMgr: Location where Handle to the Node Manager will be
++ * returned..
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid Dev Object handle.
++ * Requires:
++ * DEV Initialized.
++ * phNodeMgr is not null
++ * Ensures:
++ * DSP_SOK: *phNodeMgr contains a handle to a Node manager object.
++ * else: *phNodeMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT
++ *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr);
++
++/*
++ * ======== DEV_GetSymbol ========
++ * Purpose:
++ * Get the value of a symbol in the currently loaded program.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * pstrSym: Name of symbol to look up.
++ * pulValue: Ptr to symbol value.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *pulValue contains the symbol value;
++ */
++ extern DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice()
++ * *phWmdContext: Ptr to location to store context handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phWmdContext != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phWmdContext contains context handle;
++ * else: *phWmdContext is NULL;
++ */
++ extern DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext);
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DEV is initialized.
++ * Ensures:
++ * When reference count == 0, DEV's private resources are freed.
++ */
++ extern void DEV_Exit(void);
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public DEV functions.
++ */
++ extern bool DEV_Init(void);
++
++/*
++ * ======== DEV_IsLocked ========
++ * Purpose:
++ * Predicate function to determine if the device has been
++ * locked by a client for exclusive access.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: TRUE: device has been locked.
++ * DSP_SFALSE: FALSE: device not locked.
++ * DSP_EHANDLE: hDevObject was invalid.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_IsLocked(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Inserts the Processor Object into the List of PROC Objects
++ * kept in the DEV Object
++ * Parameters:
++ * hProcObject: Handle to the Proc Object
++ * hDevObject Handle to the Dev Object
++ * bAttachedNew Specifies if there are already processors attached
++ * Returns:
++ * DSP_SOK: Successfully inserted into the list
++ * Requires:
++ * hProcObject is not NULL
++ * hDevObject is a valid handle to the DEV.
++ * DEV Initialized.
++ * List(of Proc object in Dev) Exists.
++ * Ensures:
++ * DSP_SOK & the PROC Object is inserted and the list is not empty
++ * Details:
++ * If the List of Proc Object is empty bAttachedNew is TRUE, it indicated
++ * this is the first Processor attaching.
++ * If it is False, there are already processors attached.
++ */
++ extern DSP_STATUS DEV_InsertProcObject(IN struct DEV_OBJECT
++ *hDevObject,
++ IN u32 hProcObject,
++ OUT bool *
++ pbAlreadyAttached);
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL Failure to Remove the PROC Object from the list
++ * Requires:
++ * DevObject is Valid
++ * hProcObject != 0
++ * pDevObject->procList != NULL
++ * !LST_IsEmpty(pDevObject->procList)
++ * pbAlreadyAttached !=NULL
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ *
++ */
++ extern DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT
++ *hDevObject,
++ u32 hProcObject);
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ * Clients may include multiple users of BRD, as well as CHNL.
++ * This function is asychronous, and may be called by a timer event
++ * set up by a watchdog timer.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * ulStatus: A status word, most likely a BRD_STATUS.
++ * Returns:
++ * DSP_SOK: All registered clients were asynchronously notified.
++ * DSP_EINVALIDARG: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: Notifications are queued by the operating system to be
++ * delivered to clients. This function does not ensure that
++ * the notifications will ever be delivered.
++ */
++ extern DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject,
++ u32 ulStatus);
++
++
++
++/*
++ * ======== DEV_RemoveDevice ========
++ * Purpose:
++ * Destroys the Device Object created by DEV_StartDevice.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * hMgr: Handle to a channel manager, or NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject,
++ struct CHNL_MGR *hMgr);
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the Message manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * hMgr: Handle to a message manager, or NULL.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject,
++ struct MSG_MGR *hMgr);
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the WinBRIDGE environment. This
++ * involves querying CM for allocated resources, querying the registry
++ * for necessary dsp resources (requested in the INF file), and using
++ * this information to create a WinBRIDGE device object.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * DEV initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode);
++
++#endif /* DEV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/devdefs.h b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+new file mode 100644
+index 0000000..e9ff725
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+@@ -0,0 +1,35 @@
++/*
++ * devdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== devdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and dev.h. Required
++ * to break circular dependency between WMD and DEV include files.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-1996 gp: Renamed from dev1.h.
++ *! 30-May-1996 gp: Broke out from dev.h
++ */
++
++#ifndef DEVDEFS_
++#define DEVDEFS_
++
++/* WCD Device Object */
++ struct DEV_OBJECT;
++
++#endif /* DEVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/disp.h b/arch/arm/plat-omap/include/dspbridge/disp.h
+new file mode 100644
+index 0000000..e116734
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/disp.h
+@@ -0,0 +1,236 @@
++/*
++ * disp.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Dispatcher.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 28-Jan-2003 map Removed DISP_DoCinit().
++ *! 15-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 07-Sep-2001 jeh Added DISP_MemCopy().
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 08-Aug-2000 jeh Removed DISP_NodeTerminate since it no longer uses RMS.
++ *! 17-Jul-2000 jeh Updates to function headers.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef DISP_
++#define DISP_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/dispdefs.h>
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target, through communication
++ * with the Resource Manager Server running on the target. Each NODE
++ * Manager object should have exactly one NODE Dispatcher.
++ *
++ * Parameters:
++ * phDispObject: Location to store node dispatcher object on output.
++ * hDevObject: Device for this processor.
++ * pDispAttrs: Node dispatcher attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Unable to create dispatcher.
++ * Requires:
++ * DISP_Init(void) called.
++ * pDispAttrs != NULL.
++ * hDevObject != NULL.
++ * phDispObject != NULL.
++ * Ensures:
++ * DSP_SOK: IsValid(*phDispObject).
++ * error: *phDispObject == NULL.
++ */
++ extern DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs);
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * Returns:
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * Ensures:
++ * hDispObject is invalid.
++ */
++ extern void DISP_Delete(struct DISP_OBJECT *hDispObject);
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DISP_Init(void) previously called.
++ * Ensures:
++ * Any resources acquired in DISP_Init(void) will be freed when last DISP
++ * client calls DISP_Exit(void).
++ */
++ extern void DISP_Exit(void);
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool DISP_Init(void);
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * allocated or running on the DSP.
++ * ulFxnAddress: Address of RMS function for changing priority.
++ * nodeEnv: Address of node's environment structure.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT
++ *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ NODE_ENV nodeEnv,
++ s32 nPriority);
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node handle obtained from NODE_Allocate().
++ * ulFxnAddr: Address or RMS create node function.
++ * ulCreateFxn: Address of node's create function.
++ * pArgs: Arguments to pass to RMS node create function.
++ * pNodeEnv: Location to store node environment pointer on
++ * output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETASK: Unable to create the node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER: A user-defined failure occurred.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * pArgs != NULL.
++ * hNode != NULL.
++ * pNodeEnv != NULL.
++ * NODE_GetType(hNode) != NODE_DEVICE.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS
++ *pArgs,
++ OUT NODE_ENV *pNodeEnv);
++
++/*
++ * ======== DISP_NodeDelete ========
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * loaded on the DSP.
++ * ulFxnAddr: Address or RMS delete node function.
++ * ulDeleteFxn: Address of node's delete function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulDeleteFxn, NODE_ENV nodeEnv);
++
++/*
++ * ======== DISP_NodeRun ========
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node to be executed
++ * on the DSP.
++ * ulFxnAddr: Address or RMS node execute function.
++ * ulExecuteFxn: Address of node's execute function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulExecuteFxn, NODE_ENV nodeEnv);
++
++#endif /* DISP_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dispdefs.h b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+new file mode 100644
+index 0000000..401ad4f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+@@ -0,0 +1,45 @@
++/*
++ * dispdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dispdefs.h ========
++ * Description:
++ * Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Aug-2000 jeh Added fields to DISP_ATTRS.
++ *! 06-Jul-2000 jeh Created.
++ */
++
++#ifndef DISPDEFS_
++#define DISPDEFS_
++
++ struct DISP_OBJECT;
++
++/* Node Dispatcher attributes */
++ struct DISP_ATTRS {
++ u32 ulChnlOffset; /* Offset of channel ids reserved for RMS */
++ /* Size of buffer for sending data to RMS */
++ u32 ulChnlBufSize;
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++ } ;
++
++#endif /* DISPDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dmm.h b/arch/arm/plat-omap/include/dspbridge/dmm.h
+new file mode 100644
+index 0000000..ef37668
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dmm.h
+@@ -0,0 +1,85 @@
++/*
++ * dmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dmm.h ========
++ * Purpose:
++ * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ *
++ *! Revision History:
++ *! ================
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++#ifndef DMM_
++#define DMM_
++
++#include <dspbridge/dbdefs.h>
++
++ struct DMM_OBJECT;
++
++/* DMM attributes used in DMM_Create() */
++ struct DMM_MGRATTRS {
++ u32 reserved;
++ } ;
++
++#define DMMPOOLSIZE 0x4000000
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++
++ extern DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr);
++
++ extern DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 size,
++ u32 *pRsvAddr);
++
++ extern DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 rsvAddr);
++
++ extern DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr,
++ u32 size);
++
++ extern DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 addr,
++ u32 *pSize);
++
++ extern DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs);
++
++ extern bool DMM_Init(void);
++
++ extern void DMM_Exit(void);
++
++ extern DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr,
++ u32 addr, u32 size);
++ extern u32 *DMM_GetPhysicalAddrTable(void);
++#endif /* DMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dpc.h b/arch/arm/plat-omap/include/dspbridge/dpc.h
+new file mode 100644
+index 0000000..8c20506
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dpc.h
+@@ -0,0 +1,167 @@
++/*
++ * dpc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpc.h ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ * Public Functions:
++ * DPC_Cancel
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: DPC_Destroy ensures Suceess and DPC Object is NULL.
++ *! 21-Jan-2000 ag: Updated comments per code review.
++ *! 06-Jan-2000 ag: Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 14-Jan-1998 gp: Added DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 18-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 28-Jul-1996 gp: Created.
++ */
++
++#ifndef DPC_
++#define DPC_
++
++ struct DPC_OBJECT;
++
++/*
++ * ======== DPC_PROC ========
++ * Purpose:
++ * Deferred processing routine. Typically scheduled from an ISR to
++ * complete I/O processing.
++ * Parameters:
++ * pRefData: Ptr to user data: passed in via ISR_ScheduleDPC.
++ * Returns:
++ * Requires:
++ * The DPC should not block, or otherwise acquire resources.
++ * Interrupts to the processor are enabled.
++ * DPC_PROC executes in a critical section.
++ * Ensures:
++ * This DPC will not be reenterred on the same thread.
++ * However, the DPC may take hardware interrupts during execution.
++ * Interrupts to the processor are enabled.
++ */
++ typedef void(*DPC_PROC) (void *pRefData);
++
++/*
++ * ======== DPC_Cancel ========
++ * Purpose:
++ * Cancel a DPC previously scheduled by DPC_Schedule.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Scheduled DPC, if any, is cancelled.
++ * DSP_SFALSE: No DPC is currently scheduled for execution.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * Ensures:
++ * If the DPC has already executed, is executing, or was not yet
++ * scheduled, this function will have no effect.
++ */
++ extern DSP_STATUS DPC_Cancel(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ * Parameters:
++ * phDPC: Pointer to location to store DPC object.
++ * pfnDPC: Client's DPC procedure.
++ * pRefData: Pointer to user-defined reference data.
++ * Returns:
++ * DSP_SOK: DPC object created.
++ * DSP_EPOINTER: phDPC == NULL or pfnDPC == NULL.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Must not be called at interrupt time.
++ * Ensures:
++ * DSP_SOK: DPC object is created;
++ * else: *phDPC is set to NULL.
++ */
++ extern DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC,
++ IN DPC_PROC pfnDPC,
++ IN void *pRefData);
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create().Frees the Object only if the thread and
++ * the events are terminated successfuly.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * All DPC's scheduled for the DPC object must have completed their
++ * processing.
++ * Ensures:
++ * (SUCCESS && hDPC is NULL) or DSP_EFAILED status
++ */
++ extern DSP_STATUS DPC_Destroy(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DPC_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in DPC_Init(void) are freed.
++ */
++ extern void DPC_Exit(void);
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public DPC functions.
++ */
++ extern bool DPC_Init(void);
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: An event is scheduled for deferred processing.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * See requirements for DPC_PROC.
++ * Ensures:
++ * DSP_SOK: The DPC will not be called before this function returns.
++ */
++ extern DSP_STATUS DPC_Schedule(IN struct DPC_OBJECT *hDPC);
++
++#endif /* DPC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
+new file mode 100644
+index 0000000..c468461
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drv.h
+@@ -0,0 +1,449 @@
++/*
++ * drv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.h ========
++ * Purpose:
++ * DRV Resource allocation module. Driver Object gets Created
++ * at the time of Loading. It holds the List of Device Objects
++ * in the Syste,
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ================
++ *! 10-Feb-2004 vp: Added OMAP24xx specific definitions.
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 27-Jul-2000 rr: DRV_RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 12-Nov-1999 rr: New Flag defines for DRV_ASSIGN and DRV_RELEASE
++ *! 25-Oct-1999 rr: Resource Structure removed.
++ *! 15-Oct-1999 rr: New Resource structure created.
++ *! 05-Oct-1999 rr: Added DRV_RequestResources
++ *! Removed fxn'sDRV_RegisterMiniDriver(),
++ *! DRV_UnRegisterMiniDriver()
++ *! Removed Structures DSP_DRIVER & DRV_EXTENSION.
++ *!
++ *! 24-Sep-1999 rr: Added DRV_EXTENSION and DSP_DRIVER structures.
++ *!
++ */
++
++#ifndef DRV_
++#define DRV_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/drvdefs.h>
++
++#define DRV_ASSIGN 1
++#define DRV_RELEASE 0
++
++/* Provide the DSP Internal memory windows that can be accessed from L3 address
++ * space */
++
++#define OMAP_GEM_BASE 0x107F8000
++#define OMAP_DSP_SIZE 0x00720000
++
++/* MEM1 is L2 RAM + L2 Cache space */
++#define OMAP_DSP_MEM1_BASE 0x5C7F8000
++#define OMAP_DSP_MEM1_SIZE 0x18000
++#define OMAP_DSP_GEM1_BASE 0x107F8000
++
++
++/* MEM2 is L1P RAM/CACHE space */
++#define OMAP_DSP_MEM2_BASE 0x5CE00000
++#define OMAP_DSP_MEM2_SIZE 0x8000
++#define OMAP_DSP_GEM2_BASE 0x10E00000
++
++/* MEM3 is L1D RAM/CACHE space */
++#define OMAP_DSP_MEM3_BASE 0x5CF04000
++#define OMAP_DSP_MEM3_SIZE 0x14000
++#define OMAP_DSP_GEM3_BASE 0x10F04000
++
++
++#define OMAP_IVA2_PRM_BASE 0x48306000
++#define OMAP_IVA2_PRM_SIZE 0x1000
++
++#define OMAP_IVA2_CM_BASE 0x48004000
++#define OMAP_IVA2_CM_SIZE 0x1000
++
++#define OMAP_PER_CM_BASE 0x48005000
++#define OMAP_PER_CM_SIZE 0x1000
++
++#define OMAP_PER_PRM_BASE 0x48307000
++#define OMAP_PER_PRM_SIZE 0x1000
++
++#define OMAP_CORE_PRM_BASE 0x48306A00
++#define OMAP_CORE_PRM_SIZE 0x1000
++
++#define OMAP_SYSC_BASE 0x48002000
++#define OMAP_SYSC_SIZE 0x1000
++
++#define OMAP_MBOX_BASE 0x48094000
++#define OMAP_MBOX_SIZE 0x1000
++
++#define OMAP_DMMU_BASE 0x5D000000
++#define OMAP_DMMU_SIZE 0x1000
++
++#define OMAP_PRCM_VDD1_DOMAIN 1
++#define OMAP_PRCM_VDD2_DOMAIN 2
++
++#ifndef RES_CLEANUP_DISABLE
++
++/* GPP PROCESS CLEANUP Data structures */
++
++/* New structure (member of process context) abstracts NODE resource info */
++struct NODE_RES_OBJECT {
++ DSP_HNODE hNode;
++ s32 nodeAllocated; /* Node status */
++ s32 heapAllocated; /* Heap status */
++ s32 streamsAllocated; /* Streams status */
++ struct NODE_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DMM_RES_OBJECT {
++ s32 dmmAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 dmmSize;
++ HANDLE hProcessor;
++ struct DMM_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DSPHEAP_RES_OBJECT {
++ s32 heapAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 heapSize;
++ HANDLE hProcessor;
++ struct DSPHEAP_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts stream resource info */
++struct STRM_RES_OBJECT {
++ s32 streamAllocated; /* Stream status */
++ DSP_HSTREAM hStream;
++ u32 uNumBufs;
++ u32 uDir;
++ struct STRM_RES_OBJECT *next;
++} ;
++
++/* Overall Bridge process resource usage state */
++enum GPP_PROC_RES_STATE {
++ PROC_RES_ALLOCATED,
++ PROC_RES_FREED
++} ;
++
++/* Process Context */
++struct PROCESS_CONTEXT{
++ /* Process State */
++ enum GPP_PROC_RES_STATE resState;
++
++ /* Process ID (Same as UNIX process ID) */
++ u32 pid;
++
++ /* Pointer to next process context
++ * (To maintain a linked list of process contexts) */
++ struct PROCESS_CONTEXT *next;
++
++ /* Processor info to which the process is related */
++ DSP_HPROCESSOR hProcessor;
++
++ /* DSP Node resources */
++ struct NODE_RES_OBJECT *pNodeList;
++
++ /* DMM resources */
++ struct DMM_RES_OBJECT *pDMMList;
++
++ /* DSP Heap resources */
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
++
++ /* Stream resources */
++ struct STRM_RES_OBJECT *pSTRMList;
++} ;
++#endif
++
++/*
++ * ======== DRV_Create ========
++ * Purpose:
++ * Creates the Driver Object. This is done during the driver loading.
++ * There is only one Driver Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phDrvObject: Location to store created DRV Object handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EMEMORY: Failed in Memory allocation
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * DRV Initialized (cRefs > 0 )
++ * phDrvObject != NULL.
++ * Ensures:
++ * DSP_SOK: - *phDrvObject is a valid DRV interface to the device.
++ * - List of DevObject Created and Initialized.
++ * - List of DevNode String created and intialized.
++ * - Registry is updated with the DRV Object.
++ * !DSP_SOK: DRV Object not created
++ * Details:
++ * There is one Driver Object for the Driver representing
++ * the driver itself. It contains the list of device
++ * Objects and the list of Device Extensions in the system.
++ * Also it can hold other neccessary
++ * information in its storage area.
++ */
++ extern DSP_STATUS DRV_Create(struct DRV_OBJECT **phDrvObject);
++
++/*
++ * ======== DRV_Destroy ========
++ * Purpose:
++ * destroys the Dev Object list, DrvExt list
++ * and destroy the DRV object
++ * Called upon driver unLoading.or unsuccesful loading of the driver.
++ * Parameters:
++ * hDrvObject: Handle to Driver object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to destroy DRV Object
++ * Requires:
++ * DRV Initialized (cRegs > 0 )
++ * hDrvObject is not NULL and a valid DRV handle .
++ * List of DevObject is Empty.
++ * List of DrvExt is Empty
++ * Ensures:
++ * DSP_SOK: - DRV Object destroyed and hDrvObject is not a valid
++ * DRV handle.
++ * - Registry is updated with "0" as the DRV Object.
++ */
++ extern DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Exit the DRV module, freeing any modules initialized in DRV_Init.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern void DRV_Exit(void);
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Returns the Ptr to the FirstDev Object in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevObject: Ptr to the First Dev Object as a u32
++ * 0 if it fails to retrieve the First Dev Object
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevObject(void);
++
++/*
++ * ======== DRV_GetFirstDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the First Device Extension in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevExtension: Ptr to the First Device Extension as a u32
++ * 0: Failed to Get the Device Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevExtension(void);
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list
++ * Parameters:
++ * hDrvObject: Handle to the Manager
++ * phDevObject: Location to store the Dev Handle
++ * Requires:
++ * DRV Initialized
++ * uIndex >= 0
++ * hDrvObject is not NULL and Valid DRV Object
++ * phDevObject is not NULL
++ * Device Object List not Empty
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Failed to Get the Dev Object
++ * Ensures:
++ * DSP_SOK: *phDevObject != NULL
++ * DSP_EFAIL: *phDevObject = NULL
++ */
++ extern DSP_STATUS DRV_GetDevObject(u32 uIndex,
++ struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Object from the the List
++ * Parameters:
++ * hDevObject: Handle to the Device Object
++ * Requires:
++ * DRV Initialized
++ * hDevObject != 0
++ * Returns:
++ * dwDevObject: Ptr to the Next Dev Object as a u32
++ * 0: If it fail to get the next Dev Object.
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevObject(u32 hDevObject);
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Extension from the the List
++ * Parameters:
++ * hDevExtension: Handle to the Device Extension
++ * Requires:
++ * DRV Initialized
++ * hDevExtension != 0.
++ * Returns:
++ * dwDevExtension: Ptr to the Next Dev Extension
++ * 0: If it fail to Get the next Dev Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevExtension(u32 hDevExtension);
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize the DRV module.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DRV_Init(void);
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DeviceObject into the list of Driver object.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DeviceObject to insert.
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL: General Failure:
++ * Requires:
++ * hDrvObject != NULL and Valid DRV Handle.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Device Object is inserted and the List is not empty.
++ */
++ extern DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a Device object from the given list of Device Obj
++ * objects.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DevObject to Remove
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to find pDevObject.
++ * Requires:
++ * hDrvObject != NULL and a Valid DRV Handle.
++ * hDevObject != NULL.
++ * List exists and is not empty.
++ * Ensures:
++ * List either does not exist (NULL), or is not empty if it does exist.
++*/
++ extern DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * pDevNodeString: Ptr to DevNode String stored in the Device Ext.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are assigned based on Bus type.
++ * The hardware is initialized. Resource information is
++ * gathered from the Registry(ISA, PCMCIA)or scanned(PCI)
++ * Resource structure is stored in the registry which will be
++ * later used by the CFG module.
++ */
++ extern DSP_STATUS DRV_RequestResources(IN u32 dwContext,
++ OUT u32 *pDevNodeString);
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * hDrvObject: Handle to the Driver Object.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are released based on Bus type.
++ * Resource structure is deleted from the registry
++ */
++ extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
++ struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_ProcFreeDMMRes ========
++ * Purpose:
++ * Actual DMM De-Allocation.
++ * Parameters:
++ * hPCtxt: Path to the driver Registry Key.
++ * Returns:
++ * DSP_SOK if success;
++ */
++
++
++ extern DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt);
++
++#endif /* DRV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drvdefs.h b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+new file mode 100644
+index 0000000..ed86010
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+@@ -0,0 +1,34 @@
++/*
++ * drvdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drvdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and drv.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Jul-2000 rr: Created
++ */
++
++#ifndef DRVDEFS_
++#define DRVDEFS_
++
++/* WCD Driver Object */
++ struct DRV_OBJECT;
++
++#endif /* DRVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dspdrv.h b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+new file mode 100644
+index 0000000..f500ffb
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+@@ -0,0 +1,106 @@
++/*
++ * dspdrv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.h ========
++ * Purpose:
++ * This is the Stream Interface for the DDSP Class driver.
++ * All Device operations are performed via DeviceIOControl.
++ * Read, Seek and Write not used.
++ *
++ * Public Functions
++ * DSP_Close
++ * DSP_Deinit
++ * DSP_Init
++ * DSP_IOControl
++ * DSP_Open
++ * DSP_PowerUp
++ * DSP_PowerDown
++ *
++ *! Revision History
++ *! ================
++ *! 28-Jan-2000 rr: Type void changed to Void.
++ *! 02-Dec-1999 rr: MAX_DEV define moved from wcdce.c file.Code cleaned up.
++ *! 12-Nov-1999 rr: "#include<wncnxerr.h> removed.
++ *! 05-Oct-1999 rr Renamed the file name to wcdce.h Removed Bus Specific
++ *! code and #defines to PCCARD.h.
++ *! 24-Sep-1999 rr Changed the DSP_COMMON_WINDOW_SIZE to 0x4000(16k) for the
++ *! Memory windows.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet driver.
++ *!
++ */
++
++#if !defined __DSPDRV_h__
++#define __DSPDRV_h__
++
++#define MAX_DEV 10 /* Max support of 10 devices */
++
++/*
++ * ======== DSP_Close ========
++ * Purpose:
++ * Called when the client application/driver unloads the DDSP DLL. Upon
++ * unloading, the DDSP DLL will call CloseFile().
++ * Parameters:
++ * dwDeviceContext: Handle returned by XXX_Open used to identify
++ * the open context of the device
++ * Returns:
++ * TRUE indicates the device is successfully closed. FALSE indicates
++ * otherwise.
++ * Requires:
++ * dwOpenContext!= NULL.
++ * Ensures:The Application instance owned objects are cleaned up.
++ */
++extern bool DSP_Close(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Deinit ========
++ * Purpose:
++ * This function is called by Device Manager to de-initialize a device.
++ * This function is not called by applications.
++ * Parameters:
++ * dwDeviceContext:Handle to the device context. The XXX_Init function
++ * creates and returns this identifier.
++ * Returns:
++ * TRUE indicates the device successfully de-initialized. Otherwise it
++ * returns FALSE.
++ * Requires:
++ * dwDeviceContext!= NULL. For a built in device this should never
++ * get called.
++ * Ensures:
++ */
++extern bool DSP_Deinit(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Init ========
++ * Purpose:
++ * This function is called by Device Manager to initialize a device.
++ * This function is not called by applications
++ * Parameters:
++ * dwContext: Specifies a pointer to a string containing the registry
++ * path to the active key for the stream interface driver.
++ * HKEY_LOCAL_MACHINE\Drivers\Active
++ * Returns:
++ * Returns a handle to the device context created. This is the our actual
++ * Device Object representing the DSP Device instance.
++ * Requires:
++ * Ensures:
++ * Succeeded: device context > 0
++ * Failed: device Context = 0
++ */
++extern u32 DSP_Init(OUT u32 *initStatus);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+new file mode 100644
+index 0000000..ea5f77f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+@@ -0,0 +1,505 @@
++/*
++ * dynamic_loader.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DYNAMIC_LOADER_H_
++#define _DYNAMIC_LOADER_H_
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++/*
++ * Dynamic Loader
++ *
++ * The function of the dynamic loader is to load a "module" containing
++ * instructions for a "target" processor into that processor. In the process
++ * it assigns memory for the module, resolves symbol references made by the
++ * module, and remembers symbols defined by the module.
++ *
++ * The dynamic loader is parameterized for a particular system by 4 classes
++ * that supply the module and system specific functions it requires
++ */
++ /* The read functions for the module image to be loaded */
++ struct Dynamic_Loader_Stream;
++
++ /* This class defines "host" symbol and support functions */
++ struct Dynamic_Loader_Sym;
++
++ /* This class defines the allocator for "target" memory */
++ struct Dynamic_Loader_Allocate;
++
++ /* This class defines the copy-into-target-memory functions */
++ struct Dynamic_Loader_Initialize;
++
++/*
++ * Option flags to modify the behavior of module loading
++ */
++#define DLOAD_INITBSS 0x1 /* initialize BSS sections to zero */
++#define DLOAD_BIGEND 0x2 /* require big-endian load module */
++#define DLOAD_LITTLE 0x4 /* require little-endian load module */
++
++ typedef void *DLOAD_mhandle; /* module handle for loaded modules */
++
++/*****************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Load_Module(
++ /* the source for the module image*/
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage*/
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags*/
++ /* the returned module handle*/
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Open_Module(
++ /* the source for the module image */
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator */
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer */
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags */
++ /* the returned module handle */
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Unload_Module(DLOAD_mhandle mhandle, /* the module
++ * handle*/
++ /* host support for symbols and
++ * storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init
++ );
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for input of the module image
++ *****************************************************************************
++ *****************************************************************************/
++ struct Dynamic_Loader_Stream {
++/* public: */
++ /*************************************************************************
++ * read_buffer
++ *
++ * PARAMETERS :
++ * buffer Pointer to the buffer to fill
++ * bufsiz Amount of data desired in sizeof() units
++ *
++ * EFFECT :
++ * Reads the specified amount of data from the module input stream
++ * into the specified buffer. Returns the amount of data read in sizeof()
++ * units (which if less than the specification, represents an error).
++ *
++ * NOTES:
++ * In release 1 increments the file position by the number of bytes read
++ *
++ *************************************************************************/
++ int (*read_buffer) (struct Dynamic_Loader_Stream *thisptr,
++ void *buffer, unsigned bufsiz);
++
++ /*************************************************************************
++ * set_file_posn (release 1 only)
++ *
++ * PARAMETERS :
++ * posn Desired file position relative to start of file in sizeof() units.
++ *
++ * EFFECT :
++ * Adjusts the internal state of the stream object so that the next
++ * read_buffer call will begin to read at the specified offset from
++ * the beginning of the input module. Returns 0 for success, non-zero
++ * for failure.
++ *
++ *************************************************************************/
++ int (*set_file_posn) (struct Dynamic_Loader_Stream *thisptr,
++ /* to be eliminated in release 2*/
++ unsigned int posn);
++
++ };
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for symbol table support and
++ * miscellaneous host-side functions
++ *****************************************************************************
++ *****************************************************************************/
++
++ typedef u32 LDR_ADDR;
++
++/*
++ * the structure of a symbol known to the dynamic loader
++ */
++ struct dynload_symbol {
++ LDR_ADDR value;
++ } ;
++
++ struct Dynamic_Loader_Sym {
++/* public: */
++ /*************************************************************************
++ * Find_Matching_Symbol
++ *
++ * PARAMETERS :
++ * name The name of the desired symbol
++ *
++ * EFFECT :
++ * Locates a symbol matching the name specified. A pointer to the
++ * symbol is returned if it exists; 0 is returned if no such symbol is
++ * found.
++ *
++ *************************************************************************/
++ struct dynload_symbol *(*Find_Matching_Symbol)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *name);
++
++ /*************************************************************************
++ * Add_To_Symbol_Table
++ *
++ * PARAMETERS :
++ * nname Pointer to the name of the new symbol
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * The new symbol is added to the table. A pointer to the symbol is
++ * returned, or NULL is returned for failure.
++ *
++ * NOTES:
++ * It is permissible for this function to return NULL; the effect is that
++ * the named symbol will not be available to resolve references in
++ * subsequent loads. Returning NULL will not cause the current load
++ * to fail.
++ *************************************************************************/
++ struct dynload_symbol *(*Add_To_Symbol_Table)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *nname,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Purge_Symbol_Table
++ *
++ * PARAMETERS :
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * Each symbol in the symbol table whose moduleid matches the argument
++ * is removed from the table.
++ *************************************************************************/
++ void (*Purge_Symbol_Table) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Allocate
++ *
++ * PARAMETERS :
++ * memsiz size of desired memory in sizeof() units
++ *
++ * EFFECT :
++ * Returns a pointer to some "host" memory for use by the dynamic
++ * loader, or NULL for failure.
++ * This function is serves as a replaceable form of "malloc" to
++ * allow the user to configure the memory usage of the dynamic loader.
++ *************************************************************************/
++ void *(*Allocate) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned memsiz);
++
++ /*************************************************************************
++ * Deallocate
++ *
++ * PARAMETERS :
++ * memptr pointer to previously allocated memory
++ *
++ * EFFECT :
++ * Releases the previously allocated "host" memory.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Sym *thisptr,
++ void *memptr);
++
++ /*************************************************************************
++ * Error_Report
++ *
++ * PARAMETERS :
++ * errstr pointer to an error string
++ * args additional arguments
++ *
++ * EFFECT :
++ * This function provides an error reporting interface for the dynamic
++ * loader. The error string and arguments are designed as for the
++ * library function vprintf.
++ *************************************************************************/
++ void (*Error_Report) (struct Dynamic_Loader_Sym *thisptr,
++ const char *errstr, va_list args);
++
++ }; /* class Dynamic_Loader_Sym */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to allocate and deallocate target memory.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct LDR_SECTION_INFO {
++ /* Name of the memory section assigned at build time */
++ const char *name;
++ LDR_ADDR run_addr; /* execution address of the section */
++ LDR_ADDR load_addr; /* load address of the section */
++ LDR_ADDR size; /* size of the section in addressable units */
++#ifndef _BIG_ENDIAN
++ u16 page; /* memory page or view */
++ u16 type; /* one of the section types below */
++#else
++ u16 type; /* one of the section types below */
++ u16 page; /* memory page or view */
++#endif
++ /* a context field for use by Dynamic_Loader_Allocate;
++ * ignored but maintained by the dynamic loader */
++ u32 context;
++ } ;
++
++/* use this macro to extract type of section from LDR_SECTION_INFO.type field */
++#define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
++
++/* type of section to be allocated */
++#define DLOAD_TEXT 0
++#define DLOAD_DATA 1
++#define DLOAD_BSS 2
++ /* internal use only, run-time cinit will be of type DLOAD_DATA */
++#define DLOAD_CINIT 3
++
++ struct Dynamic_Loader_Allocate {
++/* public: */
++
++ /*************************************************************************
++ * Function allocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ * align The alignment of the storage in target AUs
++ *
++ * Effect:
++ * Allocates target memory for the specified section and fills in the
++ * load_addr and run_addr fields of the section info structure. Returns TRUE
++ * for success, FALSE for failure.
++ *
++ * Notes:
++ * Frequently load_addr and run_addr are the same, but if they are not
++ * load_addr is used with Dynamic_Loader_Initialize, and run_addr is
++ * used for almost all relocations. This function should always initialize
++ * both fields.
++ *************************************************************************/
++ int (*Allocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info, unsigned align);
++
++ /*************************************************************************
++ * Function deallocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ *
++ * Effect:
++ * Releases the target memory previously allocated.
++ *
++ * Notes:
++ * The content of the info->name field is undefined on call to this function.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info);
++
++ }; /* class Dynamic_Loader_Allocate */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to load data into a target. This class
++ * provides the interface-specific functions needed to load data.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct Dynamic_Loader_Initialize {
++/* public: */
++ /*************************************************************************
++ * Function connect
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Connect to the initialization interface. Returns TRUE for success,
++ * FALSE for failure.
++ *
++ * Notes:
++ * This function is called prior to use of any other functions in
++ * this interface.
++ *************************************************************************/
++ int (*connect) (struct Dynamic_Loader_Initialize *thisptr);
++
++ /*************************************************************************
++ * Function readmem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer for the result
++ * locn Target address of first data element
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be read in sizeof() units
++ *
++ * Effect:
++ * Fills the specified buffer with data from the target. Returns TRUE for
++ * success, FALSE for failure.
++ *************************************************************************/
++ int (*readmem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function writemem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer of data
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ *
++ * Effect:
++ * Writes the specified buffer to the target. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*writemem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function fillmem
++ *
++ * Parameters:
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ * val Value to be written in each byte
++ * Effect:
++ * Fills the specified area of target memory. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*fillmem) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info,
++ unsigned bytsiz, unsigned val);
++
++ /*************************************************************************
++ * Function execute
++ *
++ * Parameters:
++ * start Starting address
++ *
++ * Effect:
++ * The target code at the specified starting address is executed.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process
++ * if the input module has specified a starting address.
++ *************************************************************************/
++ int (*execute) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR start);
++
++ /*************************************************************************
++ * Function release
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Releases the connection to the load interface.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process.
++ *************************************************************************/
++ void (*release) (struct Dynamic_Loader_Initialize *thisptr);
++
++ }; /* class Dynamic_Loader_Initialize */
++
++#endif /* _DYNAMIC_LOADER_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/errbase.h b/arch/arm/plat-omap/include/dspbridge/errbase.h
+new file mode 100644
+index 0000000..f04c005
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/errbase.h
+@@ -0,0 +1,509 @@
++/*
++ * errbase.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== errbase.h ========
++ * Description:
++ * Central repository for DSP/BIOS Bridge error and status code.
++ *
++ * Error codes are of the form:
++ * [<MODULE>]_E<ERRORCODE>
++ *
++ * Success codes are of the form:
++ * [<MODULE>]_S<SUCCESSCODE>
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Jan-2003 map Added DSP_SALREADYLOADED for persistent library checking
++ *! 23-Nov-2002 gp: Minor comment cleanup.
++ *! 13-May-2002 sg Added DSP_SALREADYASLEEP and DSP_SALREADYWAKE.
++ *! 18-Feb-2002 mk: Added DSP_EOVERLAYMEMORY, EFWRITE, ENOSECT.
++ *! 31-Jan-2002 mk: Added definitions of DSP_STRUE and DSP_SFALSE.
++ *! 29-Jan-2002 mk: Added definition of CFG_E_INSUFFICIENTBUFSIZE.
++ *! 24-Oct-2001 sp: Consolidated all the error codes into this file.
++ *! 24-Jul-2001 mk: Type-casted all definitions of WSX_STATUS types for
++ *! removal of compile warnings.
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 18-Aug-1999 rr: Ported From WSX.
++ *! 29-May-1996 gp: Removed WCD_ and WMD_ error ranges. Redefined format of
++ *! error codes.
++ *! 10-May-1996 gp: Created.
++ */
++
++#ifndef ERRBASE_
++#define ERRBASE_
++
++/* Base of generic errors and component errors */
++#define DSP_SBASE (DSP_STATUS)0x00008000
++#define DSP_EBASE (DSP_STATUS)0x80008000
++
++#define DSP_COMP_EBASE (DSP_STATUS)0x80040200
++#define DSP_COMP_ELAST (DSP_STATUS)0x80047fff
++
++/* SUCCESS Codes */
++
++/* Generic success code */
++#define DSP_SOK (DSP_SBASE + 0)
++
++/* GPP is already attached to this DSP processor */
++#define DSP_SALREADYATTACHED (DSP_SBASE + 1)
++
++/* This is the last object available for enumeration. */
++#define DSP_SENUMCOMPLETE (DSP_SBASE + 2)
++
++/* The DSP is already asleep. */
++#define DSP_SALREADYASLEEP (DSP_SBASE + 3)
++
++/* The DSP is already awake. */
++#define DSP_SALREADYAWAKE (DSP_SBASE + 4)
++
++/* TRUE */
++#define DSP_STRUE (DSP_SBASE + 5)
++
++/* FALSE */
++#define DSP_SFALSE (DSP_SBASE + 6)
++
++/* A library contains no dependent library references */
++#define DSP_SNODEPENDENTLIBS (DSP_SBASE + 7)
++
++/* A persistent library is already loaded by the dynamic loader */
++#define DSP_SALREADYLOADED (DSP_SBASE + 8)
++
++/* Some error occured, but it is OK to continue */
++#define DSP_OKTO_CONTINUE (DSP_SBASE + 9)
++
++/* FAILURE Codes */
++
++/* The caller does not have access privileges to call this function */
++#define DSP_EACCESSDENIED (DSP_EBASE + 0)
++
++/* The Specified Connection already exists */
++#define DSP_EALREADYCONNECTED (DSP_EBASE + 1)
++
++/* The GPP must be detached from the DSP before this function is called */
++#define DSP_EATTACHED (DSP_EBASE + 2)
++
++/* During enumeration a change in the number or properties of the objects
++ * has occurred. */
++#define DSP_ECHANGEDURINGENUM (DSP_EBASE + 3)
++
++/* An error occurred while parsing the DSP executable file */
++#define DSP_ECORRUPTFILE (DSP_EBASE + 4)
++
++/* A failure occurred during a delete operation */
++#define DSP_EDELETE (DSP_EBASE + 5)
++
++/* The specified direction is invalid */
++#define DSP_EDIRECTION (DSP_EBASE + 6)
++
++/* A stream has been issued the maximum number of buffers allowed in the
++ * stream at once ; buffers must be reclaimed from the stream before any
++ * more can be issued. */
++#define DSP_ESTREAMFULL (DSP_EBASE + 7)
++
++/* A general failure occurred */
++#define DSP_EFAIL (DSP_EBASE + 8)
++
++/* The specified executable file could not be found. */
++#define DSP_EFILE (DSP_EBASE + 9)
++
++/* The specified handle is invalid. */
++#define DSP_EHANDLE (DSP_EBASE + 0xa)
++
++/* An invalid argument was specified. */
++#define DSP_EINVALIDARG (DSP_EBASE + 0xb)
++
++/* A memory allocation failure occurred. */
++#define DSP_EMEMORY (DSP_EBASE + 0xc)
++
++/* The requested operation is invalid for this node type. */
++#define DSP_ENODETYPE (DSP_EBASE + 0xd)
++
++/* No error text was found for the specified error code. */
++#define DSP_ENOERRTEXT (DSP_EBASE + 0xe)
++
++/* No more connections can be made for this node. */
++#define DSP_ENOMORECONNECTIONS (DSP_EBASE + 0xf)
++
++/* The indicated operation is not supported. */
++#define DSP_ENOTIMPL (DSP_EBASE + 0x10)
++
++/* I/O is currently pending. */
++#define DSP_EPENDING (DSP_EBASE + 0x11)
++
++/* An invalid pointer was specified. */
++#define DSP_EPOINTER (DSP_EBASE + 0x12)
++
++/* A parameter is specified outside its valid range. */
++#define DSP_ERANGE (DSP_EBASE + 0x13)
++
++/* An invalid size parameter was specified. */
++#define DSP_ESIZE (DSP_EBASE + 0x14)
++
++/* A stream creation failure occurred on the DSP. */
++#define DSP_ESTREAM (DSP_EBASE + 0x15)
++
++/* A task creation failure occurred on the DSP. */
++#define DSP_ETASK (DSP_EBASE + 0x16)
++
++/* A timeout occurred before the requested operation could complete. */
++
++#define DSP_ETIMEOUT (DSP_EBASE + 0x17)
++
++/* A data truncation occurred, e.g., when requesting a descriptive error
++ * string, not enough space was allocated for the complete error message. */
++
++#define DSP_ETRUNCATED (DSP_EBASE + 0x18)
++
++/* A parameter is invalid. */
++#define DSP_EVALUE (DSP_EBASE + 0x1a)
++
++/* The state of the specified object is incorrect for the requested
++ * operation. */
++#define DSP_EWRONGSTATE (DSP_EBASE + 0x1b)
++
++/* Symbol not found in the COFF file. DSPNode_Create will return this if
++ * the iAlg function table for an xDAIS socket is not found in the COFF file.
++ * In this case, force the symbol to be linked into the COFF file.
++ * DSPNode_Create, DSPNode_Execute, and DSPNode_Delete will return this if
++ * the create, execute, or delete phase function, respectively, could not be
++ * found in the COFF file. */
++#define DSP_ESYMBOL (DSP_EBASE + 0x1c)
++
++/* UUID not found in registry. */
++#define DSP_EUUID (DSP_EBASE + 0x1d)
++
++/* Unable to read content of DCD data section ; this is typically caused by
++ * improperly configured nodes. */
++#define DSP_EDCDREADSECT (DSP_EBASE + 0x1e)
++
++/* Unable to decode DCD data section content ; this is typically caused by
++ * changes to DSP/BIOS Bridge data structures. */
++#define DSP_EDCDPARSESECT (DSP_EBASE + 0x1f)
++
++/* Unable to get pointer to DCD data section ; this is typically caused by
++ * improperly configured UUIDs. */
++#define DSP_EDCDGETSECT (DSP_EBASE + 0x20)
++
++/* Unable to load file containing DCD data section ; this is typically
++ * caused by a missing COFF file. */
++#define DSP_EDCDLOADBASE (DSP_EBASE + 0x21)
++
++/* The specified COFF file does not contain a valid node registration
++ * section. */
++#define DSP_EDCDNOAUTOREGISTER (DSP_EBASE + 0x22)
++
++/* A requested resource is not available. */
++#define DSP_ERESOURCE (DSP_EBASE + 0x28)
++
++/* A critical error has occurred, and the DSP is being re-started. */
++#define DSP_ERESTART (DSP_EBASE + 0x29)
++
++/* A DSP memory free operation failed. */
++#define DSP_EFREE (DSP_EBASE + 0x2a)
++
++/* A DSP I/O free operation failed. */
++#define DSP_EIOFREE (DSP_EBASE + 0x2b)
++
++/* Multiple instances are not allowed. */
++#define DSP_EMULINST (DSP_EBASE + 0x2c)
++
++/* A specified entity was not found. */
++#define DSP_ENOTFOUND (DSP_EBASE + 0x2d)
++
++/* A DSP I/O resource is not available. */
++#define DSP_EOUTOFIO (DSP_EBASE + 0x2e)
++
++/* A shared memory buffer contained in a message or stream could not be
++ * mapped to the GPP client process's virtual space. */
++#define DSP_ETRANSLATE (DSP_EBASE + 0x2f)
++
++/* File or section load write function failed to write to DSP */
++#define DSP_EFWRITE (DSP_EBASE + 0x31)
++
++/* Unable to find a named section in DSP executable */
++#define DSP_ENOSECT (DSP_EBASE + 0x32)
++
++/* Unable to open file */
++#define DSP_EFOPEN (DSP_EBASE + 0x33)
++
++/* Unable to read file */
++#define DSP_EFREAD (DSP_EBASE + 0x34)
++
++/* A non-existent memory segment identifier was specified */
++#define DSP_EOVERLAYMEMORY (DSP_EBASE + 0x37)
++
++/* Invalid segment ID */
++#define DSP_EBADSEGID (DSP_EBASE + 0x38)
++
++/* Invalid alignment */
++#define DSP_EALIGNMENT (DSP_EBASE + 0x39)
++
++/* Invalid stream mode */
++#define DSP_ESTRMMODE (DSP_EBASE + 0x3a)
++
++/* Nodes not connected */
++#define DSP_ENOTCONNECTED (DSP_EBASE + 0x3b)
++
++/* Not shared memory */
++#define DSP_ENOTSHAREDMEM (DSP_EBASE + 0x3c)
++
++/* Error occurred in a dynamic loader library function */
++#define DSP_EDYNLOAD (DSP_EBASE + 0x3d)
++
++/* Device in 'sleep/suspend' mode due to DPM */
++#define DSP_EDPMSUSPEND (DSP_EBASE + 0x3e)
++
++/* A node-specific error has occurred. */
++#define DSP_EUSER1 (DSP_EBASE + 0x40)
++#define DSP_EUSER2 (DSP_EBASE + 0x41)
++#define DSP_EUSER3 (DSP_EBASE + 0x42)
++#define DSP_EUSER4 (DSP_EBASE + 0x43)
++#define DSP_EUSER5 (DSP_EBASE + 0x44)
++#define DSP_EUSER6 (DSP_EBASE + 0x45)
++#define DSP_EUSER7 (DSP_EBASE + 0x46)
++#define DSP_EUSER8 (DSP_EBASE + 0x47)
++#define DSP_EUSER9 (DSP_EBASE + 0x48)
++#define DSP_EUSER10 (DSP_EBASE + 0x49)
++#define DSP_EUSER11 (DSP_EBASE + 0x4a)
++#define DSP_EUSER12 (DSP_EBASE + 0x4b)
++#define DSP_EUSER13 (DSP_EBASE + 0x4c)
++#define DSP_EUSER14 (DSP_EBASE + 0x4d)
++#define DSP_EUSER15 (DSP_EBASE + 0x4e)
++#define DSP_EUSER16 (DSP_EBASE + 0x4f)
++
++/* FAILURE Codes : DEV */
++#define DEV_EBASE (DSP_COMP_EBASE + 0x000)
++
++/* The mini-driver expected a newer version of the class driver. */
++#define DEV_E_NEWWMD (DEV_EBASE + 0x00)
++
++/* WMD_DRV_Entry function returned a NULL function interface table. */
++#define DEV_E_NULLWMDINTF (DEV_EBASE + 0x01)
++
++/* FAILURE Codes : LDR */
++#define LDR_EBASE (DSP_COMP_EBASE + 0x100)
++
++/* Insufficient memory to export class driver services. */
++#define LDR_E_NOMEMORY (LDR_EBASE + 0x00)
++
++/* Unable to find WMD file in system directory. */
++#define LDR_E_FILEUNABLETOOPEN (LDR_EBASE + 0x01)
++
++/* FAILURE Codes : CFG */
++#define CFG_EBASE (DSP_COMP_EBASE + 0x200)
++
++/* Invalid pointer passed into a configuration module function */
++#define CFG_E_INVALIDPOINTER (CFG_EBASE + 0x00)
++
++/* Invalid device node handle passed into a configuration module function. */
++#define CFG_E_INVALIDHDEVNODE (CFG_EBASE + 0x01)
++
++/* Unable to retrieve resource information from the registry. */
++#define CFG_E_RESOURCENOTAVAIL (CFG_EBASE + 0x02)
++
++/* Unable to find board name key in registry. */
++#define CFG_E_INVALIDBOARDNAME (CFG_EBASE + 0x03)
++
++/* Unable to find a device node in registry with given unit number. */
++#define CFG_E_INVALIDUNITNUM (CFG_EBASE + 0x04)
++
++/* Insufficient buffer size */
++#define CFG_E_INSUFFICIENTBUFSIZE (CFG_EBASE + 0x05)
++
++/* FAILURE Codes : BRD */
++#define BRD_EBASE (DSP_COMP_EBASE + 0x300)
++
++/* Board client does not have sufficient access rights for this operation. */
++#define BRD_E_ACCESSDENIED (BRD_EBASE + 0x00)
++
++/* Unable to find trace buffer symbols in the DSP executable COFF file. */
++#define BRD_E_NOTRACEBUFFER (BRD_EBASE + 0x01)
++
++/* Attempted to auto-start board, but no default DSP executable configured. */
++#define BRD_E_NOEXEC (BRD_EBASE + 0x02)
++
++/* The operation failed because it was started from a wrong state */
++#define BRD_E_WRONGSTATE (BRD_EBASE + 0x03)
++
++/* FAILURE Codes : COD */
++#define COD_EBASE (DSP_COMP_EBASE + 0x400)
++
++/* No symbol table is loaded for this board. */
++#define COD_E_NOSYMBOLSLOADED (COD_EBASE + 0x00)
++
++/* Symbol not found in for this board. */
++#define COD_E_SYMBOLNOTFOUND (COD_EBASE + 0x01)
++
++/* ZL DLL module is not exporting the correct function interface. */
++#define COD_E_NOZLFUNCTIONS (COD_EBASE + 0x02)
++
++/* Unable to initialize the ZL COFF parsing module. */
++#define COD_E_ZLCREATEFAILED (COD_EBASE + 0x03)
++
++/* Unable to open DSP executable COFF file. */
++#define COD_E_OPENFAILED (COD_EBASE + 0x04)
++
++/* Unable to parse DSP executable COFF file. */
++#define COD_E_LOADFAILED (COD_EBASE + 0x05)
++
++/* Unable to read DSP executable COFF file. */
++#define COD_E_READFAILED (COD_EBASE + 0x06)
++
++/* FAILURE Codes : CHNL */
++#define CHNL_EBASE (DSP_COMP_EBASE + 0x500)
++
++/* Attempt to created channel manager with too many channels. */
++#define CHNL_E_MAXCHANNELS (CHNL_EBASE + 0x00)
++
++/* No channel manager exists for this mini-driver. */
++#define CHNL_E_NOMGR (CHNL_EBASE + 0x01)
++
++/* No free channels are available. */
++#define CHNL_E_OUTOFSTREAMS (CHNL_EBASE + 0x02)
++
++/* Channel ID is out of range. */
++#define CHNL_E_BADCHANID (CHNL_EBASE + 0x03)
++
++/* Channel is already in use. */
++#define CHNL_E_CHANBUSY (CHNL_EBASE + 0x04)
++
++/* Invalid channel mode argument. */
++#define CHNL_E_BADMODE (CHNL_EBASE + 0x05)
++
++/* dwTimeOut parameter was CHNL_IOCNOWAIT, yet no I/O completions were
++ * queued. */
++#define CHNL_E_NOIOC (CHNL_EBASE + 0x06)
++
++/* I/O has been cancelled on this channel. */
++#define CHNL_E_CANCELLED (CHNL_EBASE + 0x07)
++
++/* End of stream was already requested on this output channel. */
++#define CHNL_E_EOS (CHNL_EBASE + 0x09)
++
++/* Unable to create the channel event object. */
++#define CHNL_E_CREATEEVENT (CHNL_EBASE + 0x0A)
++
++/* Board name and unit number do not identify a valid board name. */
++#define CHNL_E_BRDID (CHNL_EBASE + 0x0B)
++
++/* Invalid IRQ configured for this WMD for this system. */
++#define CHNL_E_INVALIDIRQ (CHNL_EBASE + 0x0C)
++
++/* DSP word size of zero configured for this device. */
++#define CHNL_E_INVALIDWORDSIZE (CHNL_EBASE + 0x0D)
++
++/* A zero length memory base was specified for a shared memory class driver. */
++#define CHNL_E_INVALIDMEMBASE (CHNL_EBASE + 0x0E)
++
++/* Memory map is not configured, or unable to map physical to linear
++ * address. */
++#define CHNL_E_NOMEMMAP (CHNL_EBASE + 0x0F)
++
++/* Attempted to create a channel manager when one already exists. */
++#define CHNL_E_MGREXISTS (CHNL_EBASE + 0x10)
++
++/* Unable to plug channel ISR for configured IRQ. */
++#define CHNL_E_ISR (CHNL_EBASE + 0x11)
++
++/* No free I/O request packets are available. */
++#define CHNL_E_NOIORPS (CHNL_EBASE + 0x12)
++
++/* Buffer size is larger than the size of physical channel. */
++#define CHNL_E_BUFSIZE (CHNL_EBASE + 0x13)
++
++/* User cannot mark end of stream on an input channel. */
++#define CHNL_E_NOEOS (CHNL_EBASE + 0x14)
++
++/* Wait for flush operation on an output channel timed out. */
++#define CHNL_E_WAITTIMEOUT (CHNL_EBASE + 0x15)
++
++/* User supplied hEvent must be specified with pstrEventName attribute */
++#define CHNL_E_BADUSEREVENT (CHNL_EBASE + 0x16)
++
++/* Illegal user event name specified */
++#define CHNL_E_USEREVENTNAME (CHNL_EBASE + 0x17)
++
++/* Unable to prepare buffer specified */
++#define CHNL_E_PREPFAILED (CHNL_EBASE + 0x18)
++
++/* Unable to Unprepare buffer specified */
++#define CHNL_E_UNPREPFAILED (CHNL_EBASE + 0x19)
++
++/* FAILURE Codes : SYNC */
++#define SYNC_EBASE (DSP_COMP_EBASE + 0x600)
++
++/* Wait on a kernel event failed. */
++#define SYNC_E_FAIL (SYNC_EBASE + 0x00)
++
++/* Timeout expired while waiting for event to be signalled. */
++#define SYNC_E_TIMEOUT (SYNC_EBASE + 0x01)
++
++/* FAILURE Codes : WMD */
++#define WMD_EBASE (DSP_COMP_EBASE + 0x700)
++
++/* A test of hardware assumptions or integrity failed. */
++#define WMD_E_HARDWARE (WMD_EBASE + 0x00)
++
++/* One or more configuration parameters violated WMD hardware assumptions. */
++#define WMD_E_BADCONFIG (WMD_EBASE + 0x01)
++
++/* Timeout occurred waiting for a response from the hardware. */
++#define WMD_E_TIMEOUT (WMD_EBASE + 0x02)
++
++/* FAILURE Codes : REG */
++#define REG_EBASE (DSP_COMP_EBASE + 0x800)
++
++/* Invalid subkey parameter. */
++#define REG_E_INVALIDSUBKEY (REG_EBASE + 0x00)
++
++/* Invalid entry parameter. */
++#define REG_E_INVALIDENTRY (REG_EBASE + 0x01)
++
++/* No more registry values. */
++#define REG_E_NOMOREITEMS (REG_EBASE + 0x02)
++
++/* Insufficient space to hold data in registry value. */
++#define REG_E_MOREDATA (REG_EBASE + 0x03)
++
++/* FAILURE Codes : KFILE */
++#define KFILE_EBASE (DSP_COMP_EBASE + 0x900)
++
++/* Invalid file handle. */
++#define E_KFILE_INVALIDHANDLE (KFILE_EBASE + 0x01)
++
++/* Bad file name. */
++#define E_KFILE_BADFILENAME (KFILE_EBASE + 0x02)
++
++/* Invalid file mode. */
++#define E_KFILE_INVALIDMODE (KFILE_EBASE + 0x03)
++
++/* No resources available. */
++#define E_KFILE_NORESOURCES (KFILE_EBASE + 0x04)
++
++/* Invalid file buffer . */
++#define E_KFILE_INVALIDBUFFER (KFILE_EBASE + 0x05)
++
++/* Bad origin argument. */
++#define E_KFILE_BADORIGINFLAG (KFILE_EBASE + 0x06)
++
++/* Invalid file offset value. */
++#define E_KFILE_INVALIDOFFSET (KFILE_EBASE + 0x07)
++
++/* General KFILE error condition */
++#define E_KFILE_ERROR (KFILE_EBASE + 0x08)
++
++#endif /* ERRBASE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gb.h b/arch/arm/plat-omap/include/dspbridge/gb.h
+new file mode 100644
+index 0000000..f147751
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gb.h
+@@ -0,0 +1,85 @@
++/*
++ * gb.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gb.h ========
++ * Generic bitmap manager.
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GB_
++#define GB_
++
++#define GB_NOBITS (~0)
++#include <dspbridge/host_os.h>
++typedef s32 GB_BitNum;
++struct GB_TMap;
++
++/*
++ * ======== GB_clear ========
++ * Clear the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_clear(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_create ========
++ * Create a bit map with len bits. Initially all bits are cleared.
++ */
++
++extern struct GB_TMap *GB_create(GB_BitNum len);
++
++/*
++ * ======== GB_delete ========
++ * Delete previously created bit map
++ */
++
++extern void GB_delete(struct GB_TMap *map);
++
++/*
++ * ======== GB_findandset ========
++ * Finds a clear bit, sets it, and returns the position
++ */
++
++extern GB_BitNum GB_findandset(struct GB_TMap *map);
++
++/*
++ * ======== GB_minclear ========
++ * GB_minclear returns the minimum clear bit position. If no bit is
++ * clear, GB_minclear returns -1.
++ */
++extern GB_BitNum GB_minclear(struct GB_TMap *map);
++
++/*
++ * ======== GB_set ========
++ * Set the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_set(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_test ========
++ * Returns TRUE if the bit in position bitn is set in map; otherwise
++ * GB_test returns FALSE. Bit positions are zero based.
++ */
++
++extern bool GB_test(struct GB_TMap *map, GB_BitNum bitn);
++
++#endif /*GB_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/getsection.h b/arch/arm/plat-omap/include/dspbridge/getsection.h
+new file mode 100644
+index 0000000..33ff50d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/getsection.h
+@@ -0,0 +1,118 @@
++/*
++ * getsection.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _GETSECTION_H_
++#define _GETSECTION_H_
++
++
++#include "dynamic_loader.h"
++
++/*
++ * Get Section Information
++ *
++ * This file provides an API add-on to the dynamic loader that allows the user
++ * to query section information and extract section data from dynamic load
++ * modules.
++ *
++ * NOTE:
++ * Functions in this API assume that the supplied Dynamic_Loader_Stream object
++ * supports the set_file_posn method.
++ */
++
++ /* opaque handle for module information */
++ typedef void *DLOAD_module_info;
++
++/*
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ */
++ extern DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream
++ *module,
++ struct Dynamic_Loader_Sym
++ *syms);
++
++/*
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and fills in
++ * the provided LDR_SECTION_INFO structure.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSectionInfo(DLOAD_module_info minfo,
++ const char *sectionName,
++ const struct LDR_SECTION_INFO
++ ** const sectionInfo);
++
++/*
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo,
++ void *sectionData);
++
++/*
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ */
++ extern void DLOAD_module_close(DLOAD_module_info minfo);
++
++#endif /* _GETSECTION_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gh.h b/arch/arm/plat-omap/include/dspbridge/gh.h
+new file mode 100644
+index 0000000..089a042
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gh.h
+@@ -0,0 +1,37 @@
++/*
++ * gh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GH_
++#define GH_
++#include <dspbridge/host_os.h>
++
++extern struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash) (void *, u16), bool(*match) (void *, void *),
++ void(*delete) (void *));
++extern void GH_delete(struct GH_THashTab *hashTab);
++extern void GH_exit(void);
++extern void *GH_find(struct GH_THashTab *hashTab, void *key);
++extern void GH_init(void);
++extern void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value);
++#endif /* GH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gs.h b/arch/arm/plat-omap/include/dspbridge/gs.h
+new file mode 100644
+index 0000000..fd5ef27
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gs.h
+@@ -0,0 +1,64 @@
++/*
++ * gs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gs.h ========
++ * Memory allocation/release wrappers. This module allows clients to
++ * avoid OS spacific issues related to memory allocation. It also provides
++ * simple diagnostic capabilities to assist in the detection of memory
++ * leaks.
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GS_
++#define GS_
++
++/*
++ * ======== GS_alloc ========
++ * Alloc size bytes of space. Returns pointer to space
++ * allocated, otherwise NULL.
++ */
++extern void *GS_alloc(u32 size);
++
++/*
++ * ======== GS_exit ========
++ * Module exit. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_exit(void);
++
++/*
++ * ======== GS_free ========
++ * Free space allocated by GS_alloc() or GS_calloc().
++ */
++extern void GS_free(void *ptr);
++
++/*
++ * ======== GS_frees ========
++ * Free space allocated by GS_alloc() or GS_calloc() and assert that
++ * the size of the allocation is size bytes.
++ */
++extern void GS_frees(void *ptr, u32 size);
++
++/*
++ * ======== GS_init ========
++ * Module initialization. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_init(void);
++
++#endif /*GS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gt.h b/arch/arm/plat-omap/include/dspbridge/gt.h
+new file mode 100644
+index 0000000..456c866
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gt.h
+@@ -0,0 +1,315 @@
++/*
++ * gt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.h ========
++ * Purpose:
++ * There are two definitions that affect which portions of trace
++ * are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
++ * GT_TRACE is set to 0 then all trace statements (except for assertions)
++ * will be compiled out of the client. If GT_ASSERT is set to 0 then
++ * assertions will be compiled out of the client. GT_ASSERT can not be
++ * set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
++ * GT_ASSERT == 1).
++ *
++ *! Revision History
++ *! ================
++ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace definitions
++ *! are WinCE Specific.
++ *! 03-Jan-1997 ge Replaced "GT_" prefix to GT_Config structure members
++ *! to eliminate preprocessor confusion with other macros.
++ */
++#include <linux/types.h>
++#ifndef GT_
++#define GT_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++#include <dspbridge/host_os.h>
++
++#if !defined(GT_ASSERT) || GT_TRACE
++#define GT_ASSERT 1
++#endif
++
++struct GT_Config {
++ Fxn PRINTFXN;
++ Fxn PIDFXN;
++ Fxn TIDFXN;
++ Fxn ERRORFXN;
++};
++
++extern struct GT_Config *GT;
++
++struct GT_Mask {
++ char *modName;
++ u8 *flags;
++} ;
++
++/*
++ * New GT Class defenitions.
++ *
++ * The following are the explanations and how it could be used in the code
++ *
++ * - GT_ENTER On Entry to Functions
++ *
++ * - GT_1CLASS Display level of debugging status- Object/Automatic
++ * variables
++ * - GT_2CLASS ---- do ----
++ *
++ * - GT_3CLASS ---- do ---- + It can be used(recommended) for debug
++ * status in the ISR, IST
++ * - GT_4CLASS ---- do ----
++ *
++ * - GT_5CLASS Display entry for module init/exit functions
++ *
++ * - GT_6CLASS Warn whenever SERVICES function fails
++ *
++ * - GT_7CLASS Warn failure of Critical failures
++ *
++ */
++
++#define GT_ENTER ((u8)0x01)
++#define GT_1CLASS ((u8)0x02)
++#define GT_2CLASS ((u8)0x04)
++#define GT_3CLASS ((u8)0x08)
++#define GT_4CLASS ((u8)0x10)
++#define GT_5CLASS ((u8)0x20)
++#define GT_6CLASS ((u8)0x40)
++#define GT_7CLASS ((u8)0x80)
++
++#ifdef _LINT_
++
++/* LINTLIBRARY */
++
++/*
++ * ======== GT_assert ========
++ */
++/* ARGSUSED */
++void GT_assert(struct GT_Mask mask, s32 expr)
++{
++}
++
++/*
++ * ======== GT_config ========
++ */
++/* ARGSUSED */
++void GT_config(struct GT_Config config)
++{
++}
++
++/*
++ * ======== GT_create ========
++ */
++/* ARGSUSED */
++void GT_create(struct GT_Mask *mask, char *modName)
++{
++}
++
++/*
++ * ======== GT_curLine ========
++ * Purpose:
++ * Returns the current source code line number. Is useful for performing
++ * branch testing using trace. For example,
++ *
++ * GT_1trace(curTrace, GT_1CLASS,
++ * "in module XX_mod, executing line %u\n", GT_curLine());
++ */
++/* ARGSUSED */
++u16 GT_curLine(void)
++{
++ return (u16)NULL;
++}
++
++/*
++ * ======== GT_exit ========
++ */
++/* ARGSUSED */
++void GT_exit(void)
++{
++}
++
++/*
++ * ======== GT_init ========
++ */
++/* ARGSUSED */
++void GT_init(void)
++{
++}
++
++/*
++ * ======== GT_query ========
++ */
++/* ARGSUSED */
++bool GT_query(struct GT_Mask mask, u8 class)
++{
++ return false;
++}
++
++/*
++ * ======== GT_set ========
++ * sets trace mask according to settings
++ */
++
++/* ARGSUSED */
++void GT_set(char *settings)
++{
++}
++
++/*
++ * ======== GT_setprintf ========
++ * sets printf function
++ */
++
++/* ARGSUSED */
++void GT_setprintf(Fxn fxn)
++{
++}
++
++/* ARGSUSED */
++void GT_0trace(struct GT_Mask mask, u8 class, char *format)
++{
++}
++
++/* ARGSUSED */
++void GT_1trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_2trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_3trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_4trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_5trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_6trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++#else
++
++#define GT_BOUND 26 /* 26 letters in alphabet */
++
++extern void _GT_create(struct GT_Mask *mask, char *modName);
++
++#define GT_exit()
++
++extern void GT_init(void);
++extern void _GT_set(char *str);
++extern s32 _GT_trace(struct GT_Mask *mask, char *format, ...);
++
++#if GT_ASSERT == 0
++
++#define GT_assert(mask, expr)
++#define GT_config(config)
++#define GT_configInit(config)
++#define GT_seterror(fxn)
++
++#else
++
++extern struct GT_Config _GT_params;
++
++#define GT_assert(mask, expr) \
++ (!(expr) ? \
++ printk("assertion violation: %s, line %d\n", \
++ __FILE__, __LINE__), NULL : NULL)
++
++#define GT_config(config) (_GT_params = *(config))
++#define GT_configInit(config) (*(config) = _GT_params)
++#define GT_seterror(fxn) (_GT_params.ERRORFXN = (Fxn)(fxn))
++
++#endif
++
++#if GT_TRACE == 0
++
++#define GT_curLine() ((u16)__LINE__)
++#define GT_create(mask, modName)
++#define GT_exit()
++#define GT_init()
++#define GT_set(settings)
++#define GT_setprintf(fxn)
++
++#define GT_query(mask, class) false
++
++#define GT_0trace(mask, class, format)
++#define GT_1trace(mask, class, format, arg1)
++#define GT_2trace(mask, class, format, arg1, arg2)
++#define GT_3trace(mask, class, format, arg1, arg2, arg3)
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4)
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
++
++#else /* GT_TRACE == 1 */
++
++
++#define GT_create(mask, modName) _GT_create((mask), (modName))
++#define GT_curLine() ((u16)__LINE__)
++#define GT_set(settings) _GT_set(settings)
++#define GT_setprintf(fxn) (_GT_params.PRINTFXN = (Fxn)(fxn))
++
++#define GT_query(mask, class) ((*(mask).flags & (class)))
++
++#define GT_0trace(mask, class, format) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format)) : 0)
++
++#define GT_1trace(mask, class, format, arg1) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1)) : 0)
++
++#define GT_2trace(mask, class, format, arg1, arg2) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
++
++#define GT_3trace(mask, class, format, arg1, arg2, arg3) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
++
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
++
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) : 0)
++
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
++ (arg6)) : 0)
++
++#endif /* GT_TRACE */
++
++#endif /* _LINT_ */
++
++#endif /* GTCE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/host_os.h b/arch/arm/plat-omap/include/dspbridge/host_os.h
+new file mode 100644
+index 0000000..f539bd0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/host_os.h
+@@ -0,0 +1,96 @@
++/*
++ * host_os.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== windows.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
++ *! 16-Feb-2004 sb Added headers required for consistent_alloc
++ */
++
++#ifndef _HOST_OS_H_
++#define _HOST_OS_H_
++
++#include <linux/autoconf.h>
++#include <asm/system.h>
++#include <asm/atomic.h>
++#include <linux/semaphore.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/syscalls.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/device.h>
++#include <linux/vmalloc.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <dspbridge/dbtype.h>
++#include <mach/clock.h>
++#include <linux/clk.h>
++#include <linux/pagemap.h>
++#include <asm/cacheflush.h>
++#include <linux/dma-mapping.h>
++
++/* ----------------------------------- Macros */
++
++#define SEEK_SET 0 /* Seek from beginning of file. */
++#define SEEK_CUR 1 /* Seek from current position. */
++#define SEEK_END 2 /* Seek from end of file. */
++
++/* TODO -- Remove, once BP defines them */
++#define INT_MAIL_MPU_IRQ 26
++#define INT_DSP_MMU_IRQ 28
++
++struct dspbridge_platform_data {
++ void (*dsp_set_min_opp)(u8 opp_id);
++ u8 (*dsp_get_opp)(void);
++ void (*cpu_set_freq)(unsigned long f);
++ unsigned long (*cpu_get_freq)(void);
++ unsigned long mpu_speed[6];
++
++ u32 phys_mempool_base;
++ u32 phys_mempool_size;
++};
++
++#define PRCM_VDD1 1
++
++extern struct platform_device *omap_dspbridge_dev;
++
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++extern void dspbridge_reserve_sdram(void);
++#else
++static inline void dspbridge_reserve_sdram(void) {}
++#endif
++
++extern unsigned long dspbridge_get_mempool_base(void);
++#endif
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/io.h b/arch/arm/plat-omap/include/dspbridge/io.h
+new file mode 100644
+index 0000000..6dc63f2
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io.h
+@@ -0,0 +1,132 @@
++/*
++ * io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.h ========
++ * Description:
++ * The io module manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IO_
++#define IO_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/iodefs.h>
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on
++ * output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: IO manager attributes.
++ * pMgrAttrs->bIRQ: I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * Requires:
++ * IO_Init(void) called.
++ * phIOMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Destroy the IO manager.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr);
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * IO_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in IO_Init(void), are freed when the last
++ * client of IO calls IO_Exit(void).
++ */
++ extern void IO_Exit(void);
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool IO_Init(void);
++
++/*
++ * ======== IO_OnLoaded ========
++ * Purpose:
++ * Called when a program is loaded so IO manager can update its
++ * internal state.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/io_sm.h b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+new file mode 100644
+index 0000000..3dcbf74
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+@@ -0,0 +1,335 @@
++/*
++ * io_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io_sm.h ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ * Also, includes macros to simulate SHM via port io calls.
++ *
++ * Public Functions:
++ * IO_Dispatch
++ * IO_DPC
++ * IO_ISR
++ * IO_RequestChnl
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Mar-2004 vp: Added IVA releated functions.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 06-Feb-2003 kc Added IO_DDMAClearChnlDesc and IO_DDZCClearChnlDesc.
++ *! 21-Dec-2001 ag Removed unused param in IO_DDMAInitChnlDesc().
++ * Updated comments. Removed #ifdef CHNL_NOIPCINTR.
++ *! 05-Nov-2001 kc Updated IO_CALLISR macro.
++ *! 01-May-2001 jeh Removed IO_RequestMsg.
++ *! 29-Mar-2001 ag Added #ifdef CHNL_NOIPCINTR.
++ *! 04-Dec-2000 jeh Added IO_RequestMsg.
++ *! 26-Oct-2000 jeh Added IO_GetLong, IO_SetLong, IO_ReadValueLong, and
++ *! IO_WriteValueLong, for passing arg in SHM structure.
++ *! 20-Jan-2000 ag: Updated header comments per code review.
++ *! 05-Jan-2000 ag: Text format clean-up.
++ *! 02-Nov-1999 ag: Updated header descriptions.
++ *! 25-May-1999 jg: Removed assumption of 4 bytes / word.
++ *! 12-Aug-1996 gp: Created.
++ */
++
++#ifndef IOSM_
++#define IOSM_
++
++#include <dspbridge/_chnl_sm.h>
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/iodefs.h>
++
++#define IO_INPUT 0
++#define IO_OUTPUT 1
++#define IO_SERVICE 2
++#define IO_MAXSERVICE IO_SERVICE
++
++#define IO_MGRSIGNATURE 0x494f4D43 /* "IOGR" */
++
++#define DSPFieldAddr(type, field, base, wordsize) \
++ ((((s32)&(((type *)0)->field)) / wordsize) + (u32)base)
++
++/* Access can be different SM access word size (e.g. 16/32 bit words) */
++#define IO_SetValue(pContext, type, base, field, value) (base->field = value)
++#define IO_GetValue(pContext, type, base, field) (base->field)
++#define IO_OrValue(pContext, type, base, field, value) (base->field |= value)
++#define IO_AndValue(pContext, type, base, field, value) (base->field &= value)
++#define IO_SetLong(pContext, type, base, field, value) (base->field = value)
++#define IO_GetLong(pContext, type, base, field) (base->field)
++
++#define IO_DisableInterrupt(h) CHNLSM_DisableInterrupt(h)
++#define IO_EnableInterrupt(h) CHNLSM_EnableInterrupt(h)
++#define IO_CALLISR(h, pFlag, pwMBRegVal) CHNLSM_ISR(h, pFlag, pwMBRegVal)
++
++/*
++ * ======== IO_CancelChnl ========
++ * Purpose:
++ * Cancel IO on a given channel.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * ulChnl: Index of channel to cancel IO on.
++ * Returns:
++ * Requires:
++ * Valid hIOMgr.
++ * Ensures:
++ */
++ extern void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl);
++
++/*
++ * ======== IO_DPC ========
++ * Purpose:
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O.
++ * Parameters:
++ * pRefData: Pointer to reference data registered via a call to
++ * DPC_Create().
++ * Returns:
++ * Requires:
++ * Must not block.
++ * Must not acquire resources.
++ * All data touched must be locked in memory if running in kernel mode.
++ * Ensures:
++ * Non-preemptible (but interruptible).
++ */
++ extern void IO_DPC(IN OUT void *pRefData);
++
++/*
++ * ======== IO_ISR ========
++ * Purpose:
++ * Main interrupt handler for the shared memory WMD channel manager.
++ * Calls the WMD's CHNLSM_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O..
++ * Parameters:
++ * pRefData: Pointer to the channel manager object for this board.
++ * Set in an initial call to ISR_Install().
++ * Returns:
++ * TRUE if interrupt handled; FALSE otherwise.
++ * Requires:
++ * Must be in locked memory if executing in kernel mode.
++ * Must only call functions which are in locked memory if Kernel mode.
++ * Must only call asynchronous services.
++ * Interrupts are disabled and EOI for this interrupt has been sent.
++ * Ensures:
++ */
++ irqreturn_t IO_ISR(int irq, IN void *pRefData);
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request I/O from the DSP. Sets flags in shared memory, then interrupts
++ * the DSP.
++ * Parameters:
++ * hIOMgr: IO manager handle.
++ * pChnl: Ptr to the channel requesting I/O.
++ * iMode: Mode of channel: {IO_INPUT | IO_OUTPUT}.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_RequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_Schedule ========
++ * Purpose:
++ * Schedule DPC for IO.
++ * Parameters:
++ * pIOMgr: Ptr to a I/O manager.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_Schedule(struct IO_MGR *hIOMgr);
++
++/*
++ * DSP-DMA IO functions
++ */
++
++/*
++ * ======== IO_DDMAInitChnlDesc ========
++ * Purpose:
++ * Initialize DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * uNumDesc: Number of buffer descriptors(equals # of IOReqs &
++ * Chirps)
++ * pDsp: Dsp address;
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * uNumDesc > 0
++ * pVa != NULL
++ * pDspPa != NULL
++ *
++ * Ensures:
++ */
++ extern void IO_DDMAInitChnlDesc(struct IO_MGR *hIOMgr, u32 uDDMAChnlId,
++ u32 uNumDesc, void *pDsp);
++
++/*
++ * ======== IO_DDMAClearChnlDesc ========
++ * Purpose:
++ * Clear DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * Ensures:
++ */
++ extern void IO_DDMAClearChnlDesc(struct IO_MGR *hIOMgr,
++ u32 uDDMAChnlId);
++
++/*
++ * ======== IO_DDMARequestChnl ========
++ * Purpose:
++ * Request channel DSP-DMA from the DSP. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDMARequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * Zero-copy IO functions
++ */
++
++/*
++ * ======== IO_DDZCInitChnlDesc ========
++ * Purpose:
++ * Initialize ZCPY channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uZId: zero-copy channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXZCPYCHNLS
++ * hIOMgr != Null
++ * Ensures:
++ */
++ extern void IO_DDZCInitChnlDesc(struct IO_MGR *hIOMgr, u32 uZId);
++
++/*
++ * ======== IO_DDZCClearChnlDesc ========
++ * Purpose:
++ * Clear DSP ZC channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uChnlId: ZC channel identifier.
++ * Returns:
++ * Requires:
++ * hIOMgr is valid
++ * uChnlId < DDMA_MAXZCPYCHNLS
++ * Ensures:
++ */
++ extern void IO_DDZCClearChnlDesc(struct IO_MGR *hIOMgr, u32 uChnlId);
++
++/*
++ * ======== IO_DDZCRequestChnl ========
++ * Purpose:
++ * Request zero-copy channel transfer. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDZCRequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_SHMsetting ========
++ * Purpose:
++ * Sets the shared memory setting
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * desc: Shared memory type
++ * pArgs: Ptr to SHM setting
++ * Returns:
++ * Requires:
++ * hIOMgr != NULL
++ * pArgs != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr,
++ IN enum SHM_DESCTYPE desc,
++ IN void *pArgs);
++
++/*
++ * Misc functions for the CHNL_IO shared memory library:
++ */
++
++/* Maximum channel bufsize that can be used. */
++ extern u32 IO_BufSize(struct IO_MGR *hIOMgr);
++
++ extern u32 IO_ReadValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern u32 IO_ReadValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_OrSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_AndSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal);
++
++ extern void IO_SM_init(void);
++
++/*
++ * ========PrintDspTraceBuffer ========
++ * Print DSP tracebuffer.
++ */
++ extern DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT
++ *hWmdContext);
++
++#endif /* IOSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/iodefs.h b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+new file mode 100644
+index 0000000..f45890a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+@@ -0,0 +1,45 @@
++/*
++ * iodefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== iodefs.h ========
++ * Description:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IODEFS_
++#define IODEFS_
++
++#define IO_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* IO Objects: */
++ struct IO_MGR;
++
++/* IO manager attributes: */
++ struct IO_ATTRS {
++ u8 bIRQ; /* Channel's I/O IRQ number. */
++ bool fShared; /* TRUE if the IRQ is shareable. */
++ u32 uWordSize; /* DSP Word size. */
++ u32 dwSMBase; /* Physical base address of shared memory. */
++ u32 uSMLength; /* Size (in bytes) of shared memory. */
++ } ;
++
++#endif /* IODEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/kfile.h b/arch/arm/plat-omap/include/dspbridge/kfile.h
+new file mode 100644
+index 0000000..23c89b0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/kfile.h
+@@ -0,0 +1,216 @@
++/*
++ * kfile.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfile.h ========
++ * Purpose:
++ * Provide file I/O management capabilities.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ * KFILE_Write
++ *
++ * Notes:
++ * The KFILE module is not like most of the other DSP/BIOS Bridge modules
++ * in that it doesn't return WSX_STATUS type values. Rather, it's
++ * prototypes are meant to match the stdio file prototypes
++ * (ie, fopen, fclose, etc.).
++ *
++ *! Revision History
++ *! ================
++ *! 29-Oct-1999 kc: Clean up for code review.
++ *! 07-Jan-1998 cr: Clean up for code review.
++ *! 15-Aug-1997 cr: Added E_KFILE_ERROR for general error condition.
++ *! 04-Aug-1997 cr: Added explicit CDECL descriptions.
++ *! 11-Nov-1996 cr: Implemented changes based on code review.
++ *! 05-Nov-1996 cr: Cleaned up for code review.
++ *! 29-May-1996 gp: Added requirement that size != 0 in _Write() and _Read().
++ *! 28-May-1996 mg: Changed return values for Read/Write.
++ *! 14-Dec-1995 cr: Created.
++ */
++
++#ifndef KFILE_
++#define KFILE_
++
++/*
++ * Constants for KFILE_Seek. Note that these MUST be the same definitions as
++ * those defined for fseek.
++ */
++#define KFILE_SEEK_SET 0x00 /* seek from beginning of file */
++#define KFILE_SEEK_CUR 0x01 /* seek from current position */
++#define KFILE_SEEK_END 0x02 /* seek from end of file */
++
++ struct KFILE_FileObj;
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * 0: success.
++ * E_KFILE_ERROR: unable to close specified handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Close(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void KFILE_Exit(void);
++
++/*
++ * ======== KFILE_Init ========
++ * Purpose:
++ * Initializes private state of KFILE module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * KFILE initialized.
++ */
++ extern bool KFILE_Init(void);
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Opens a file for use.
++ * Parameters:
++ * pszFileName: Full path to name of the file to open.
++ * pszMode: String containing open status. Only the first
++ * character of the string is examined, for either
++ * "r" (read) or "w" (write) mode.
++ * Returns:
++ * A valid file handle if success, else NULL.
++ * Requires:
++ * - KFILE initialized.
++ * - pszMode != NULL.
++ * - pszFileName != NULL.
++ * Ensures:
++ */
++ extern struct KFILE_FileObj *KFILE_Open(IN CONST char *filename,
++ IN CONST char *mode);
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * This function reads a specified number of bytes into a buffer.
++ * Parameters:
++ * pBuffer: Array to which the file data is copied.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to read in.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects read from file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer is a valid pointer.
++ * Ensures:
++ */
++ extern s32 KFILE_Read(OUT void __user*buffer,
++ IN s32 size, IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * This function sets the file position indicator. NOTE: we don't
++ * support seeking beyond the boundaries of a file.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * offset: Number of bytes from the origin to move.
++ * origin: File reference point, one of the following values:
++ * KFILE_SEEK_SET: Seek from beginning of file.
++ * KFILE_SEEK_CUR: Seek from current position.
++ * KFILE_SEEK_END: Seek from end of file.
++ * Returns:
++ * 0: success.
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * E_KFILE_BADORIGIN: invalid origin paramater.
++ * E_KFILE_ERROR: general failure.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Seek(IN struct KFILE_FileObj *hFile,
++ IN s32 offset, IN s32 origin);
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * This function reports the current value of the position indicator.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Return value:
++ * > 0: success; returns # of bytes the position indicator is from
++ * beginning of file.
++ * E_KFILE_ERROR: general failure.
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Tell(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Write ========
++ * Purpose:
++ * This function writes a number of objects to the stream.
++ * Parameters:
++ * pBuffer: Array from which the file data is written.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to write out.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects written to file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer != NULL.
++ * Postcondition:
++ * The file position indicator is advanced by the number of
++ * characters written.
++ */
++ extern s32 KFILE_Write(OUT void *buffer,
++ IN s32 size,
++ IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++#endif /* KFILE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ldr.h b/arch/arm/plat-omap/include/dspbridge/ldr.h
+new file mode 100644
+index 0000000..7e13c93
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ldr.h
+@@ -0,0 +1,51 @@
++/*
++ * ldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ldr.h ========
++ * Purpose:
++ * Provide module loading services and symbol export services.
++ *
++ * Public Functions:
++ * LDR_Exit
++ * LDR_FreeModule
++ * LDR_GetProcAddress
++ * LDR_Init
++ * LDR_LoadModule
++ *
++ * Notes:
++ * This service is meant to be used by modules of the DSP/BIOS Bridge
++ * class driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 12-Nov-1999 kc: Removed declaration of unused loader object.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 12-Jan-1998 cr: Cleaned up for code review.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 11-Nov-1996 cr: Cleaned up for code review.
++ *! 16-May-1996 gp: Created.
++ */
++
++#ifndef LDR_
++#define LDR_
++
++/* Loader objects: */
++ struct LDR_MODULE;
++
++#endif /* LDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/list.h b/arch/arm/plat-omap/include/dspbridge/list.h
+new file mode 100644
+index 0000000..2e3f995
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/list.h
+@@ -0,0 +1,296 @@
++/*
++ * list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== list.h ========
++ * Purpose:
++ * Declarations of list management control structures and definitions
++ * of inline list management functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_InitElem
++ * LST_Init
++ * LST_InsertBefore
++ * LST_IsEmpty
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 16-Aug-1997 cr: added explicit identifiers.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v.1.1; renamed identifiers.
++ *! 21-Oct-1994 dh4: Cleaned / commented for code review.
++ *! 08-Jun-1994 dh4: Converted to SPM (added extern "C").
++ */
++
++#ifndef LIST_
++#define LIST_
++
++#include <dspbridge/host_os.h>
++
++#define LST_IsEmpty(l) (((l)->head.next == &(l)->head))
++
++ struct LST_ELEM {
++ struct LST_ELEM *next;
++ struct LST_ELEM *prev;
++ struct LST_ELEM *self;
++ } ;
++
++ struct LST_LIST {
++ struct LST_ELEM head;
++ } ;
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ * Details:
++ * Uses portable MEM_Calloc() function to allocate a list containing
++ * a single element and initializes that element to indicate that it
++ * is the "end of the list" (i.e., the list is empty).
++ * An empty list is indicated by the "next" pointer in the element
++ * at the head of the list pointing to the head of the list, itself.
++ * Parameters:
++ * Returns:
++ * Pointer to beginning of created list (success)
++ * NULL --> Allocation failed
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * The created list contains a single element. This element is the
++ * "empty" element, because its "next" and "prev" pointers point at
++ * the same location (the element itself).
++ */
++ extern struct LST_LIST *LST_Create(void);
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ * Details:
++ * Uses portable MEM_Free() function to deallocate the memory
++ * block pointed at by the input parameter.
++ * Parameters:
++ * pList: Pointer to list control structure of list to be deleted
++ * Returns:
++ * Void
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Must ONLY be used for empty lists, because it does not walk the
++ * chain of list elements. Calling this function on a non-empty list
++ * will cause a memory leak.
++ */
++ extern void LST_Delete(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void LST_Exit(void);
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the list
++ * is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * Returns:
++ * Pointer to first list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_First(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * Pops the head off the list and returns a pointer to it.
++ * Details:
++ * If the list is empty, returns NULL.
++ * Else, removes the element at the head of the list, making the next
++ * element the head of the list.
++ * The head is removed by making the tail element of the list point its
++ * "next" pointer at the next element after the head, and by making the
++ * "prev" pointer of the next element after the head point at the tail
++ * element. So the next element after the head becomes the new head of
++ * the list.
++ * Parameters:
++ * pList: Pointer to list control structure of list whose head
++ * element is to be removed
++ * Returns:
++ * Pointer to element that was at the head of the list (success)
++ * NULL No elements in list
++ * Requires:
++ * - head.self must be correctly set to &head.
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Because the tail of the list points forward (its "next" pointer) to
++ * the head of the list, and the head of the list points backward (its
++ * "prev" pointer) to the tail of the list, this list is circular.
++ */
++ extern struct LST_ELEM *LST_GetHead(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initializes private state of LST module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * LST initialized.
++ */
++ extern bool LST_Init(void);
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ * Details:
++ * Parameters:
++ * pElem: Pointer to list element to be reset
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * This function must not be called to "reset" an element in the middle
++ * of a list chain -- that would break the chain.
++ *
++ */
++ extern void LST_InitElem(IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pElem: Pointer to element in list to insert.
++ * pElemExisting: Pointer to existing list element.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pElem != NULL.
++ * - pElemExisting != NULL.
++ * Ensures:
++ */
++ extern void LST_InsertBefore(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pElem,
++ IN struct LST_ELEM *pElemExisting);
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the next
++ * element is the head of the list or the list is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Pointer to list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_Next(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ * Details:
++ * Sets new element's "prev" pointer to the address previously held by
++ * the head element's prev pointer. This is the previous tail member of
++ * the list.
++ * Sets the new head's prev pointer to the address of the element.
++ * Sets next pointer of the previous tail member of the list to point to
++ * the new element (rather than the head, which it had been pointing at).
++ * Sets new element's next pointer to the address of the head element.
++ * Sets head's prev pointer to the address of the new element.
++ * Parameters:
++ * pList: Pointer to list control structure to which *pElem will be
++ * added
++ * pElem: Pointer to list element to be added
++ * Returns:
++ * Void
++ * Requires:
++ * *pElem and *pList must both exist.
++ * pElem->self = pElem before pElem is passed to this function.
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * Because the tail is always "just before" the head of the list (the
++ * tail's "next" pointer points at the head of the list, and the head's
++ * "prev" pointer points at the tail of the list), the list is circular.
++ * Warning: if pElem->self is not set beforehand, LST_GetHead() will
++ * return an erroneous pointer when it is called for this element.
++ */
++ extern void LST_PutTail(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++extern void LST_RemoveElem(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++#endif /* LIST_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mbx_sh.h b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+new file mode 100644
+index 0000000..be0909e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+@@ -0,0 +1,213 @@
++/*
++ * mbx_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mbx_sh.h ========
++ * Definitions for shared mailbox cmd/data values.(used on both
++ * the GPP and DSP sides).
++ *
++ * Bridge usage of OMAP mailbox 1 is determined by the "class" of the
++ * mailbox interrupt's cmd value received. The class value are defined
++ * as a bit (10 thru 15) being set.
++ *
++ * Note: Only 16 bits of each is used. Other 16 bit data reg available.
++ *
++ * 16 bit Mbx bit defns:
++ *
++ * A). Exception/Error handling (Module DEH) : class = 0.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ *
++ * B: DSP-DMA link driver channels (DDMA) : class = 1.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|1|b|b|b|b|b|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where b -> buffer index (32 DDMA buffers/chnl max)
++ * c -> channel Id (32 DDMA chnls max)
++ *
++ *
++ *
++ *
++ * C: Proc-copy link driver channels (PCPY) : class = 2.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|1|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ * D: Zero-copy link driver channels (DDZC) : class = 4.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|1|0|0|x|x|x|x|x|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> channel Id (32 ZCPY chnls max)
++ *
++ *
++ * E: Power management : class = 8.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|x|x|x|x|x|c|c|c|c|c|
++
++ * 0010 00xx xxxc cccc
++ * 0010 00nn pppp qqqq
++ * nn:
++ * 00 = reserved
++ * 01 = pwr state change
++ * 10 = opp pre-change
++ * 11 = opp post-change
++ *
++ * if nn = pwr state change:
++ * pppp = don't care
++ * qqqq:
++ * 0010 = hibernate
++ * 0010 0001 0000 0010
++ * 0110 = retention
++ * 0010 0001 0000 0110
++ * others reserved
++ *
++ * if nn = opp pre-change:
++ * pppp = current opp
++ * qqqq = next opp
++ *
++ * if nn = opp post-change:
++ * pppp = prev opp
++ * qqqq = current opp
++ *
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> Power management command
++ *
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Sep-2002 mr Added DEH reset const
++ *! 24-Apr-2002 sg Added more PM commands.
++ *! 04-Mar-2002 gv Added MBX_PM_CLASS
++ *! 22-Jan-2002 ag Bug fix in MBX_SETZCPYVAL(x) macro.
++ *! 21-Dec-2001 ag Added bit masks defns.
++ *! 17-Dec-2001 ag: created.
++ */
++
++#ifndef _MBX_SH_H
++#define _MBX_SH_H
++
++#define MBX_CLASS_MSK 0xFC00 /* Class bits are 10 thru 15 */
++#define MBX_VALUE_MSK 0x03FF /* Value is 0 thru 9 */
++
++#define MBX_DEH_CLASS 0x0000 /* DEH owns Mbx INTR */
++#define MBX_DDMA_CLASS 0x0400 /* DSP-DMA link drvr chnls owns INTR */
++#define MBX_PCPY_CLASS 0x0800 /* PROC-COPY " */
++#define MBX_ZCPY_CLASS 0x1000 /* ZERO-COPY " */
++#define MBX_PM_CLASS 0x2000 /* Power Management */
++#define MBX_DBG_CLASS 0x4000 /* For debugging purpose */
++
++/*
++ * Exception Handler codes
++ * Magic code used to determine if DSP signaled exception.
++ */
++#define MBX_DEH_BASE 0x0
++#define MBX_DEH_USERS_BASE 0x100 /* 256 */
++#define MBX_DEH_LIMIT 0x3FF /* 1023 */
++#define MBX_DEH_RESET 0x101 /* DSP RESET (DEH) */
++#define MBX_DEH_EMMU 0X103 /*DSP MMU FAULT RECOVERY*/
++
++/*
++ * Link driver command/status codes.
++ */
++/* DSP-DMA */
++#define MBX_DDMA_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_DDMA_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_DDMA_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++#define MBX_DDMA_NUMBUFBITS 5 /* buffer index: # of bits avail */
++#define MBX_DDMA_BUFSHIFT (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
++#define MBX_DDMA_BUFMSK 0x3E0 /* bits 5 thru 9 */
++
++/* Zero-Copy */
++#define MBX_ZCPY_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_ZCPY_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_ZCPY_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++/* Power Management Commands */
++#define MBX_PM_DSPIDLE (MBX_PM_CLASS + 0x0)
++#define MBX_PM_DSPWAKEUP (MBX_PM_CLASS + 0x1)
++#define MBX_PM_EMERGENCYSLEEP (MBX_PM_CLASS + 0x2)
++#define MBX_PM_SLEEPUNTILRESTART (MBX_PM_CLASS + 0x3)
++#define MBX_PM_DSPGLOBALIDLE_OFF (MBX_PM_CLASS + 0x4)
++#define MBX_PM_DSPGLOBALIDLE_ON (MBX_PM_CLASS + 0x5)
++#define MBX_PM_SETPOINT_PRENOTIFY (MBX_PM_CLASS + 0x6)
++#define MBX_PM_SETPOINT_POSTNOTIFY (MBX_PM_CLASS + 0x7)
++#define MBX_PM_DSPRETN (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPRETENTION (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPHIBERNATE (MBX_PM_CLASS + 0x9)
++#define MBX_PM_HIBERNATE_EN (MBX_PM_CLASS + 0xA)
++#define MBX_PM_OPP_REQ (MBX_PM_CLASS + 0xB)
++#define MBX_PM_OPP_CHG (MBX_PM_CLASS + 0xC)
++
++#define MBX_PM_TYPE_MASK 0x0300
++#define MBX_PM_TYPE_PWR_CHNG 0x0100
++#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
++#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
++#define MBX_PM_TYPE_OPP_MASK 0x0300
++#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
++/* DSP to MPU */
++#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
++#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
++#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
++#define MBX_PM_OPP_1 0
++#define MBX_PM_OPP_2 1
++#define MBX_PM_OPP_3 2
++#define MBX_PM_OPP_4 3
++#define MBX_OLDOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_NEWOPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++#define MBX_PREVOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_CUROPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++
++/* Bridge Debug Commands */
++#define MBX_DBG_SYSPRINTF (MBX_DBG_CLASS + 0x0)
++
++/*
++ * Useful macros
++ */
++/* DSP-DMA channel */
++#define MBX_SETDDMAVAL(x, y) (MBX_DDMA_CLASS | (x << MBX_DDMA_BUFSHIFT) | \
++ (y << MBX_DDMA_CHNLSHIFT))
++
++/* Zero-Copy channel */
++#define MBX_SETZCPYVAL(x) (MBX_ZCPY_CLASS | (x << MBX_ZCPY_CHNLSHIFT))
++
++#endif /* _MBX_SH_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mem.h b/arch/arm/plat-omap/include/dspbridge/mem.h
+new file mode 100644
+index 0000000..535ac3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mem.h
+@@ -0,0 +1,340 @@
++/*
++ * mem.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.h ========
++ * Purpose:
++ * Memory management and address mapping services for the DSP/BIOS Bridge
++ * class driver and mini-driver.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocObject
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreeObject
++ * MEM_FreePhysMem
++ * MEM_GetNumPages
++ * MEM_Init
++ * MEM_IsValidHandle
++ * MEM_LinearAddress
++ * MEM_PageLock
++ * MEM_PageUnlock
++ * MEM_UnMapLinearAddress
++ * MEM_VirtualToPhysical
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Cleaned up notes for MEM_LinearAddress() does not
++ *! require phys address to be page aligned!
++ *! 02-Dec-1999 rr: stdwin.h included for retail build
++ *! 12-Nov-1999 kc: Added warning about use of MEM_LinearAddress.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 07-Jan-1998 gp: Added MEM_AllocUMB and MEM_UMBFree for User Mapped Buffers
++ *! used by WMD_CHNL.
++ *! 23-Dec-1997 cr: Code review cleanup, removed dead Ring 3 code.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 01-Nov-1996 gp: Updated based on code review.
++ *! 04-Sep-1996 gp: Added MEM_PageLock() and MEM_PageUnlock() services.
++ *! 14-Aug-1996 mg: Added MEM_GetPhysAddr() and MEM_GetNumPages()
++ *! 25-Jul-1996 gp: Added MEM_IsValidHandle() macro.
++ *! 10-May-1996 gp: Added MEM_Calloc().
++ *! 25-Apr-1996 gp: Added MEM_PhysicalAddress()
++ *! 17-Apr-1996 gp: Added MEM_Exit function; updated to latest naming standard.
++ *! 08-Apr-1996 gp: Created.
++ */
++
++#ifndef MEM_
++#define MEM_
++
++#include <dspbridge/host_os.h>
++#include <dspbridge/memdefs.h>
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ */
++ extern void *MEM_Alloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_AllocObject ========
++ * Purpose:
++ * Allocate an object, and set it's signature.
++ * Parameters:
++ * pObj: Pointer to the new object.
++ * Obj: Type of the object to allocate.
++ * Signature: Magic field value. Must be non-zero.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Calloc(); and
++ * The object structure has a dwSignature field. The compiler ensures
++ * this requirement.
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will succeed for this object.
++ */
++#define MEM_AllocObject(pObj, Obj, Signature) \
++{ \
++ pObj = MEM_Calloc(sizeof(Obj), MEM_NONPAGED); \
++ if (pObj) { \
++ pObj->dwSignature = Signature; \
++ } \
++}
++
++/* ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * ulAlign: Alignment Mask.
++ * pPhysicalAddress: Physical address of allocated memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, or if cBytes == 0.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested. Returned physical address refers to physical
++ * location of memory.
++ */
++ extern void *MEM_AllocPhysMem(IN u32 cBytes,
++ IN u32 ulAlign,
++ OUT u32 *pPhysicalAddress);
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of zeroed memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block
++ * of the size requested.
++ */
++ extern void *MEM_Calloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void MEM_Exit(void);
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Performs system cache sync with discard
++ * Parameters:
++ * pMemBuf: Pointer to memory region to be flushed.
++ * pMemBuf: Size of the memory region to be flushed.
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Cache is synchronized
++ */
++ extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ * Parameters:
++ * pMemBuf: Pointer to memory allocated by MEM_Calloc/Alloc().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pMemBuf is a valid memory address returned by MEM_Calloc/Alloc().
++ * Ensures:
++ * pMemBuf is no longer a valid pointer to memory.
++ */
++ extern void MEM_Free(IN void *pMemBuf);
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ * Parameters:
++ * pVirtualAddress: Pointer to virtual memory region allocated
++ * by MEM_AllocPhysMem().
++ * pPhysicalAddress: Pointer to physical memory region allocated
++ * by MEM_AllocPhysMem().
++ * cBytes: Size of the memory region allocated by MEM_AllocPhysMem().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pVirtualAddress is a valid memory address returned by
++ * MEM_AllocPhysMem()
++ * Ensures:
++ * pVirtualAddress is no longer a valid pointer to memory.
++ */
++ extern void MEM_FreePhysMem(void *pVirtualAddress,
++ u32 pPhysicalAddress, u32 cBytes);
++
++/*
++ * ======== MEM_FreeObject ========
++ * Purpose:
++ * Utility macro to invalidate an object's signature, and deallocate it.
++ * Parameters:
++ * pObj: Pointer to the object to free.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Free().
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will fail for this object.
++ */
++#define MEM_FreeObject(pObj) \
++{ \
++ pObj->dwSignature = 0x00; \
++ MEM_Free(pObj); \
++}
++
++/*
++ * ======== MEM_GetNumPages ========
++ * Purpose:
++ * Calculate the number of pages corresponding to the supplied buffer.
++ * Parameters:
++ * pAddr: Linear (virtual) address of the buffer.
++ * cBytes: Number of bytes in the buffer.
++ * Returns:
++ * Number of pages.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * If cBytes > 0, number of pages returned > 0.
++ */
++ extern s32 MEM_GetNumPages(IN void *pAddr, IN u32 cBytes);
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initializes private state of MEM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * MEM initialized.
++ */
++ extern bool MEM_Init(void);
++
++/*
++ * ======== MEM_IsValidHandle ========
++ * Purpose:
++ * Validate the object handle.
++ * Parameters:
++ * hObj: Handle to object created with MEM_AllocObject().
++ * Sig: Expected signature u32.
++ * Returns:
++ * TRUE if handle is valid; FALSE otherwise.
++ * Requires:
++ * The object structure has a dwSignature field. Ensured by compiler.
++ * Ensures:
++ */
++#define MEM_IsValidHandle(hObj, Sig) \
++ ((hObj != NULL) && (hObj->dwSignature == Sig))
++
++/*
++ * ======== MEM_LinearAddress ========
++ * Purpose:
++ * Get the linear address corresponding to the given physical address.
++ * Parameters:
++ * pPhysAddr: Physical address to be mapped.
++ * cBytes: Number of bytes in physical range to map.
++ * Returns:
++ * The corresponding linear address, or NULL if unsuccessful.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * Notes:
++ * If valid linear address is returned, be sure to call
++ * MEM_UnmapLinearAddress().
++ */
++#define MEM_LinearAddress(pPhyAddr, cBytes) pPhyAddr
++
++/*
++ * ======== MEM_UnmapLinearAddress ========
++ * Purpose:
++ * Unmap the linear address mapped in MEM_LinearAddress.
++ * Parameters:
++ * pBaseAddr: Ptr to mapped memory (as returned by MEM_LinearAddress()).
++ * Returns:
++ * Requires:
++ * - MEM initialized.
++ * - pBaseAddr is a valid linear address mapped in MEM_LinearAddress.
++ * Ensures:
++ * - pBaseAddr no longer points to a valid linear address.
++ */
++#define MEM_UnmapLinearAddress(pBaseAddr)
++
++/*
++ * ======== MEM_ExtPhysPoolInit ========
++ * Purpose:
++ * Uses the physical memory chunk passed for internal consitent memory
++ * allocations.
++ * physical address based on the page frame address.
++ * Parameters:
++ * poolPhysBase starting address of the physical memory pool.
++ * poolSize size of the physical memory pool.
++ * Returns:
++ * none.
++ * Requires:
++ * - MEM initialized.
++ * - valid physical address for the base and size > 0
++ */
++ extern void MEM_ExtPhysPoolInit(IN u32 poolPhysBase,
++ IN u32 poolSize);
++
++#endif /* MEM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/memdefs.h b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+new file mode 100644
+index 0000000..a5bb259
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+@@ -0,0 +1,52 @@
++/*
++ * memdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== memdefs.h ========
++ * Purpose:
++ * Global MEM constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Aug-2001 ag: Added MEM_[SET][GET]VIRTUALSEGID.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 15-Nov-1996 gp: Renamed from wsxmem.h and moved to kwinos.
++ *! 21-Aug-1996 cr: Created from mem.h.
++ */
++
++#ifndef MEMDEFS_
++#define MEMDEFS_
++
++/* Memory Pool Attributes: */
++ enum MEM_POOLATTRS {
++ MEM_PAGED = 0,
++ MEM_NONPAGED = 1,
++ MEM_LARGEVIRTMEM = 2
++ } ;
++
++/*
++ * MEM_VIRTUALSEGID is used by Node & Strm to access virtual address space in
++ * the correct client process context.
++ */
++#define MEM_SETVIRTUALSEGID 0x10000000
++#define MEM_GETVIRTUALSEGID 0x20000000
++#define MEM_MASKVIRTUALSEGID (MEM_SETVIRTUALSEGID | MEM_GETVIRTUALSEGID)
++
++#define TO_VIRTUAL_UNCACHED(x) x
++#define INTREG_TO_VIRTUAL_UNCACHED(x) x
++
++#endif /* MEMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgr.h b/arch/arm/plat-omap/include/dspbridge/mgr.h
+new file mode 100644
+index 0000000..24c4472
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgr.h
+@@ -0,0 +1,234 @@
++/*
++ * mgr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * MGR_Create
++ * MGR_Destroy
++ * MGR_EnumNodeInfo
++ * MGR_EnumProcessorInfo
++ * MGR_Exit
++ * MGR_GetDCDHandle
++ * MGR_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc: Removed legacy PERF definitions.
++ *! 11-Jul-2001 jeh Added CFG_HDEVNODE parameter to MGR_Create().
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData for acquiring PERF stats.
++ *! 03-Nov-2000 rr: Added MGR_GetDCDHandle. Modified after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types).
++ *! 20-Jun-2000 rr: Created.
++ */
++
++#ifndef MGR_
++#define MGR_
++
++#include <dspbridge/mgrpriv.h>
++
++#define MAX_EVENTS 32
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Purpose:
++ * Block on any Bridge event(s)
++ * Parameters:
++ * aNotifications : array of pointers to notification objects.
++ * uCount : number of elements in above array
++ * puIndex : index of signaled event object
++ * uTimeout : timeout interval in milliseocnds
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_ETIMEOUT : Wait timed out. *puIndex is undetermined.
++ * Details:
++ */
++
++ DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION
++ **aNotifications,
++ u32 uCount, OUT u32 *puIndex,
++ u32 uTimeout);
++
++/*
++ * ======== MGR_Create ========
++ * Purpose:
++ * Creates the Manager Object. This is done during the driver loading.
++ * There is only one Manager Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phMgrObject: Location to store created MGR Object handle.
++ * hDevNode: Device object as known to Windows system.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EMEMORY: Failed to Create the Object
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * phMgrObject != NULL.
++ * Ensures:
++ * DSP_SOK: *phMgrObject is a valid MGR interface to the device.
++ * MGR Object stores the DCD Manager Handle.
++ * MGR Object stored in the Regsitry.
++ * !DSP_SOK: MGR Object not created
++ * Details:
++ * DCD Dll is loaded and MGR Object stores the handle of the DLL.
++ */
++ extern DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **hMgrObject,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== MGR_Destroy ========
++ * Purpose:
++ * Destroys the MGR object. Called upon driver unloading.
++ * Parameters:
++ * hMgrObject: Handle to Manager object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DCD Manager freed; MGR Object destroyed;
++ * MGR Object deleted from the Registry.
++ * DSP_EFAIL: Failed to destroy MGR Object
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * hMgrObject is a valid MGR handle .
++ * Ensures:
++ * DSP_SOK: MGR Object destroyed and hMgrObject is Invalid MGR
++ * Handle.
++ */
++ extern DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject);
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ * Parameters:
++ * uNode: The node index (base 0).
++ * pNDBProps: Ptr to the DSP_NDBPROPS structure for output.
++ * uNDBPropsSize: Size of the DSP_NDBPROPS structure.
++ * puNumNodes: Location where the number of nodes configured
++ * in the database will be returned.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uNode is > than the number of nodes.
++ * configutred in the system
++ * DSP_ECHANGEDURINGENUM: During Enumeration there has been a change in
++ * the number of nodes configured or in the
++ * the properties of the enumerated nodes.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pNDBPROPS is not null
++ * uNDBPropsSize >= sizeof(DSP_NDBPROPS)
++ * puNumNodes is not null
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumNodes > 0 OR
++ * DSP_FAILED && *puNumNodes == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumNodeInfo(u32 uNode,
++ OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize,
++ OUT u32 *puNumNodes);
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about available DSP
++ * processors
++ * Parameters:
++ * uProcessor: The processor index (zero-based).
++ * pProcessorInfo: Ptr to the DSP_PROCESSORINFO structure .
++ * uProcessorInfoSize: Size of DSP_PROCESSORINFO structure.
++ * puNumProcs: Location where the number of DSPs configured
++ * in the database will be returned
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uProcessor is > than the number of
++ * DSP Processors in the system.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pProcessorInfo is not null
++ * puNumProcs is not null
++ * uProcessorInfoSize >= sizeof(DSP_PROCESSORINFO)
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumProcs > 0 OR
++ * DSP_FAILED && *puNumProcs == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *
++ pProcessorInfo,
++ u32 uProcessorInfoSize,
++ OUT u32 *puNumProcs);
++/*
++ * ======== MGR_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MGR is initialized.
++ * Ensures:
++ * When reference count == 0, MGR's private resources are freed.
++ */
++ extern void MGR_Exit(void);
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Purpose:
++ * Retrieves the MGR handle. Accessor Function
++ * Parameters:
++ * hMGRHandle: Handle to the Manager Object
++ * phDCDHandle: Ptr to receive the DCD Handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EFAIL: Failure to get the Handle
++ * Requires:
++ * MGR is initialized.
++ * phDCDHandle != NULL
++ * Ensures:
++ * DSP_SOK and *phDCDHandle != NULL ||
++ * DSP_EFAIL and *phDCDHandle == NULL
++ */
++ extern DSP_STATUS MGR_GetDCDHandle(IN struct MGR_OBJECT
++ *hMGRHandle,
++ OUT u32 *phDCDHandle);
++
++/*
++ * ======== MGR_Init ========
++ * Purpose:
++ * Initialize MGR's private state, keeping a reference count on each
++ * call. Intializes the DCD.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public MGR functions.
++ */
++ extern bool MGR_Init(void);
++
++#endif /* MGR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgrpriv.h b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+new file mode 100644
+index 0000000..4a34086
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+@@ -0,0 +1,55 @@
++/*
++ * mgrpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgrpriv.h ========
++ * Description:
++ * Global MGR constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 29-July-2001 ag: added MGR_PROCESSOREXTINFO.
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef MGRPRIV_
++#define MGRPRIV_
++
++/*
++ * OMAP1510 specific
++ */
++#define MGR_MAXTLBENTRIES 32
++
++/* RM MGR Object */
++ struct MGR_OBJECT;
++
++ struct MGR_TLBENTRY {
++ u32 ulDspVirt; /* DSP virtual address */
++ u32 ulGppPhys; /* GPP physical address */
++ } ;
++
++/*
++ * The DSP_PROCESSOREXTINFO structure describes additional extended
++ * capabilities of a DSP processor not exposed to user.
++ */
++ struct MGR_PROCESSOREXTINFO {
++ struct DSP_PROCESSORINFO tyBasic; /* user processor info */
++ /* private dsp mmu entries */
++ struct MGR_TLBENTRY tyTlb[MGR_MAXTLBENTRIES];
++ } ;
++
++#endif /* MGRPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msg.h b/arch/arm/plat-omap/include/dspbridge/msg.h
+new file mode 100644
+index 0000000..f2872cc
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msg.h
+@@ -0,0 +1,106 @@
++/*
++ * msg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.h ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 17-Nov-2000 jeh Removed MSG_Get, MSG_Put, MSG_CreateQueue,
++ *! MSG_DeleteQueue, and MSG_RegisterNotify, since these
++ *! are now part of mini-driver.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSG_
++#define MSG_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object. The MSG manager must be created before
++ * the IO Manager.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager handle on output.
++ * hDevObject: The device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * phMsgMgr != NULL.
++ * hDevObject != NULL.
++ * msgCallback != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from MSG_Create().
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ extern void MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== MSG_Exit ========
++ * Purpose:
++ * Discontinue usage of MSG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MSG_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in MSG_Init(void) will be freed when last MSG
++ * client calls MSG_Exit(void).
++ */
++ extern void MSG_Exit(void);
++
++/*
++ * ======== MSG_Init ========
++ * Purpose:
++ * Initialize the MSG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool MSG_Init(void);
++
++#endif /* MSG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msgdefs.h b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+new file mode 100644
+index 0000000..8ea4551
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+@@ -0,0 +1,43 @@
++/*
++ * msgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgdefs.h ========
++ * Description:
++ * Global MSG constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 09-May-2001 jeh Removed MSG_TODSP, MSG_FROMDSP.
++ *! 17-Nov-2000 jeh Added MSGMGR_SIGNATURE.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSGDEFS_
++#define MSGDEFS_
++
++#define MSGMGR_SIGNATURE 0x4d47534d /* "MGSM" */
++
++/* MSG Objects: */
++ struct MSG_MGR;
++ struct MSG_QUEUE;
++
++/* Function prototype for callback to be called on RMS_EXIT message received */
++ typedef void(*MSG_ONEXIT) (HANDLE h, s32 nStatus);
++
++#endif /* MSGDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldr.h b/arch/arm/plat-omap/include/dspbridge/nldr.h
+new file mode 100644
+index 0000000..0915846
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldr.h
+@@ -0,0 +1,81 @@
++/*
++ * nldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge dynamic loader interface. See the file dldrdefs.h
++ * for a description of these functions.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function header comments.
++ *! 17-Apr-2002 jeh Created.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/nldrdefs.h>
++
++#ifndef NLDR_
++#define NLDR_
++
++ extern DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit);
++
++ extern DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs);
++
++ extern void NLDR_Delete(struct NLDR_OBJECT *hNldr);
++ extern void NLDR_Exit(void);
++ extern void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode);
++
++ extern DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++ extern DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj
++ **phRmmMgr);
++
++ extern bool NLDR_Init(void);
++ extern DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++ extern DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++#endif /* NLDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldrdefs.h b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+new file mode 100644
+index 0000000..84b36a3
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+@@ -0,0 +1,307 @@
++/*
++ * nldrdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldrdefs.h ========
++ * Description:
++ * Global Dynamic + static/overlay Node loader (NLDR) constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Consolidated dldrdefs.h into nldrdefs.h
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#ifndef NLDRDEFS_
++#define NLDRDEFS_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/devdefs.h>
++
++#define NLDR_MAXPATHLENGTH 255
++/* NLDR Objects: */
++ struct NLDR_OBJECT;
++ struct NLDR_NODEOBJECT;
++
++/*
++ * ======== NLDR_LOADTYPE ========
++ * Load types for a node. Must match values in node.h55.
++ */
++ enum NLDR_LOADTYPE {
++ NLDR_STATICLOAD, /* Linked in base image, not overlay */
++ NLDR_DYNAMICLOAD, /* Dynamically loaded node */
++ NLDR_OVLYLOAD /* Linked in base image, overlay node */
++ } ;
++
++/*
++ * ======== NLDR_OVLYFXN ========
++ * Causes code or data to be copied from load address to run address. This
++ * is the "COD_WRITEFXN" that gets passed to the DBLL_Library and is used as
++ * the ZL write function.
++ *
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspRunAddr: Run address of code or data.
++ * ulDspLoadAddr: Load address of code or data.
++ * ulNumBytes: Number of (GPP) bytes to copy.
++ * nMemSpace: RMS_CODE or RMS_DATA.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_OVLYFXN) (void *pPrivRef, u32 ulDspRunAddr,
++ u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_WRITEFXN ========
++ * Write memory function. Used for dynamic load writes.
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspAddr: Address of code or data.
++ * pBuf: Code or data to be written
++ * ulNumBytes: Number of (GPP) bytes to write.
++ * nMemSpace: DBLL_DATA or DBLL_CODE.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_WRITEFXN) (void *pPrivRef,
++ u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_ATTRS ========
++ * Attributes passed to NLDR_Create function.
++ */
++ struct NLDR_ATTRS {
++ NLDR_OVLYFXN pfnOvly;
++ NLDR_WRITEFXN pfnWrite;
++ u16 usDSPWordSize;
++ u16 usDSPMauSize;
++ } ;
++
++/*
++ * ======== NLDR_PHASE ========
++ * Indicates node create, delete, or execute phase function.
++ */
++ enum NLDR_PHASE {
++ NLDR_CREATE,
++ NLDR_DELETE,
++ NLDR_EXECUTE,
++ NLDR_NOPHASE
++ } ;
++
++/*
++ * Typedefs of loader functions imported from a DLL, or defined in a
++ * function table.
++ */
++
++/*
++ * ======== NLDR_Allocate ========
++ * Allocate resources to manage the loading of a node on the DSP.
++ *
++ * Parameters:
++ * hNldr: Handle of loader that will load the node.
++ * pPrivRef: Handle to identify the node.
++ * pNodeProps: Pointer to a DCD_NODEPROPS for the node.
++ * phNldrNode: Location to store node handle on output. This handle
++ * will be passed to NLDR_Load/NLDR_Unload.
++ * pfPhaseSplit: pointer to boolean variable referenced in node.c
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * pNodeProps != NULL.
++ * phNldrNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNldrNode).
++ * error: *phNldrNode == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_ALLOCATEFXN) (struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT
++ **phNldrNode,
++ OUT bool *pfPhaseSplit);
++
++/*
++ * ======== NLDR_Create ========
++ * Create a loader object. This object handles the loading and unloading of
++ * create, delete, and execute phase functions of nodes on the DSP target.
++ *
++ * Parameters:
++ * phNldr: Location to store loader handle on output.
++ * hDevObject: Device for this processor.
++ * pAttrs: Loader attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * Requires:
++ * NLDR_Init(void) called.
++ * phNldr != NULL.
++ * hDevObject != NULL.
++ * pAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phNldr.
++ * error: *phNldr == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_CREATEFXN) (OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS
++ *pAttrs);
++
++/*
++ * ======== NLDR_Delete ========
++ * Delete the NLDR loader.
++ *
++ * Parameters:
++ * hNldr: Node manager object.
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * Ensures:
++ * hNldr invalid
++ */
++ typedef void(*NLDR_DELETEFXN) (struct NLDR_OBJECT *hNldr);
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NLDR_Init(void) will be freed when last NLDR
++ * client calls NLDR_Exit(void).
++ */
++ typedef void(*NLDR_EXITFXN) (void);
++
++/*
++ * ======== NLDR_Free ========
++ * Free resources allocated in NLDR_Allocate.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef void(*NLDR_FREEFXN) (struct NLDR_NODEOBJECT *hNldrNode);
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ * Get address of create, delete, or execute phase function of a node on
++ * the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * pstrFxn: Name of function.
++ * pulAddr: Location to store function address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESYMBOL: Address of function not found.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * pulAddr != NULL;
++ * pstrFxn != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_GETFXNADDRFXN) (struct NLDR_NODEOBJECT
++ *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ typedef bool(*NLDR_INITFXN) (void);
++
++/*
++ * ======== NLDR_Load ========
++ * Load create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Type of function to load (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EOVERLAYMEMORY: Can't overlay phase because overlay memory
++ * is already in use.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * DSP_EFWRITE: Failed to write phase's code or date to target.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_LOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_Unload ========
++ * Unload create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Node function to unload (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_UNLOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_FXNS ========
++ */
++ struct NLDR_FXNS {
++ NLDR_ALLOCATEFXN pfnAllocate;
++ NLDR_CREATEFXN pfnCreate;
++ NLDR_DELETEFXN pfnDelete;
++ NLDR_EXITFXN pfnExit;
++ NLDR_FREEFXN pfnFree;
++ NLDR_GETFXNADDRFXN pfnGetFxnAddr;
++ NLDR_INITFXN pfnInit;
++ NLDR_LOADFXN pfnLoad;
++ NLDR_UNLOADFXN pfnUnload;
++ } ;
++
++#endif /* NLDRDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/node.h b/arch/arm/plat-omap/include/dspbridge/node.h
+new file mode 100644
+index 0000000..d253962
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/node.h
+@@ -0,0 +1,619 @@
++/*
++ * node.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== node.h ========
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetMessage
++ * NODE_GetProcessor
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Apr-2001 jeh Updated with code review changes.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID to return codes.
++ *! 17-Nov-2000 jeh Added NODE_OnExit().
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GetMessage, NODE_PutMessage.
++ *! 12-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Removed
++ *! NODE_RegisterAllNodes().
++ *! 07-Sep-2000 jeh Changed type HANDLE in NODE_RegisterNotify to
++ *! DSP_HNOTIFICATION. Added DSP_STRMATTR param to
++ *! NODE_Connect(). Removed NODE_GetMessageStream().
++ *! 17-Jul-2000 jeh Updated function header descriptions.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef NODE_
++#define NODE_
++
++#include <dspbridge/procpriv.h>
++
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ * Parameters:
++ * hProcessor: Handle of processor that is allocating the node.
++ * pNodeId: Pointer to a DSP_UUID for the node.
++ * pArgs: Optional arguments to be passed to the node.
++ * pAttrIn: Optional pointer to node attributes (priority,
++ * timeout...)
++ * phNode: Location to store node handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EUUID: Node UUID has not been registered.
++ * DSP_ESYMBOL: iAlg functions not found for a DAIS node.
++ * DSP_ERANGE: pAttrIn != NULL and pAttrIn->iPriority out of
++ * range.
++ * DSP_EFAIL: A failure occured, unable to allocate node.
++ * DSP_EWRONGSTATE: Proccessor is not in the running state.
++ * Requires:
++ * NODE_Init(void) called.
++ * hProcessor != NULL.
++ * pNodeId != NULL.
++ * phNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNode).
++ * error: *phNode == NULL.
++ */
++ extern DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA
++ *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN
++ *pAttrIn,
++ OUT struct NODE_OBJECT **phNode);
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocate and Prepare a buffer whose descriptor will be passed to a
++ * Node within a (DSP_MSG)message
++ * Parameters:
++ * hNode: The node handle.
++ * uSize: The size of the buffer to be allocated.
++ * pAttr: Pointer to a DSP_BUFFERATTR structure.
++ * pBuffer: Location to store the address of the allocated
++ * buffer on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EMEMORY: Insufficent memory.
++ * DSP_EFAIL: General Failure.
++ * DSP_ESIZE: Invalid Size.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_AllocMsgBuf(struct NODE_OBJECT *hNode,
++ u32 uSize,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr,
++ OUT u8 **pBuffer);
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of an allocated node.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ERANGE: nPriority is out of range.
++ * DSP_ENODETYPE: The specified node is not a task node.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED, NODE_PAUSED,
++ * or NODE_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ERESTART: A critical error has occurred and the DSP is
++ * being restarted.
++ * DSP_EFAIL: Unable to change node's runtime priority level.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK && (Node's current priority == nPriority)
++ */
++ extern DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode,
++ s32 nPriority);
++
++/*
++ * ======== NODE_CloseOrphans ========
++ * Purpose:
++ * Delete all nodes whose owning processor is being destroyed.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * hProc: Handle to processor object being destroyed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to delete all nodes belonging to hProc.
++ * Requires:
++ * Valid hNodeMgr.
++ * hProc != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_CloseOrphans(struct NODE_MGR *hNodeMgr,
++ struct PROC_OBJECT *hProc);
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
++ * case that the connnection is being made between a node on the DSP and
++ * the GPP, one of the node handles (either hNode1 or hNode2) must be
++ * the constant NODE_HGPPNODE.
++ * Parameters:
++ * hNode1: Handle of first node to connect to second node. If
++ * this is a connection from the GPP to hNode2, hNode1
++ * must be the constant NODE_HGPPNODE. Otherwise, hNode1
++ * must be a node handle returned from a successful call
++ * to Node_Allocate().
++ * hNode2: Handle of second node. Must be either NODE_HGPPNODE
++ * if this is a connection from DSP node to GPP, or a
++ * node handle returned from a successful call to
++ * NODE_Allocate().
++ * uStream1: Output stream index on first node, to be connected
++ * to second node's input stream. Value must range from
++ * 0 <= uStream1 < number of output streams.
++ * uStream2: Input stream index on second node. Value must range
++ * from 0 <= uStream2 < number of input streams.
++ * pAttrs: Stream attributes (NULL ==> use defaults).
++ * pConnParam: A pointer to a DSP_CBDATA structure that defines
++ * connection parameter for device nodes to pass to DSP
++ * side.
++ * If the value of this parameter is NULL, then this API
++ * behaves like DSPNode_Connect. This parameter will have
++ * length of the string and the null terminated string in
++ * DSP_CBDATA struct. This can be extended in future tp
++ * pass binary data.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode1 or hNode2.
++ * DSP_EMEMORY: Insufficient host memory.
++ * DSP_EVALUE: A stream index parameter is invalid.
++ * DSP_EALREADYCONNECTED: A connection already exists for one of the
++ * indices uStream1 or uStream2.
++ * DSP_EWRONGSTATE: Either hNode1 or hNode2 is not in the
++ * NODE_ALLOCATED state.
++ * DSP_ENOMORECONNECTIONS: No more connections available.
++ * DSP_EFAIL: Attempt to make an illegal connection (eg,
++ * Device node to device node, or device node to
++ * GPP), the two nodes are on different DSPs.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1,
++ u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2,
++ OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA
++ *pConnParam);
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create
++ * function. If necessary, load code that contains the node's create
++ * function.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ESYMBOL: Create function not found in the COFF file.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED state.
++ * DSP_EMEMORY: Memory allocation failure on the DSP.
++ * DSP_ETASK: Unable to create node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER1-16: A user-defined failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target. The NODE Manager
++ * also maintains a pipe map of used and available node connections.
++ * Each DEV object should have exactly one NODE Manager object.
++ *
++ * Parameters:
++ * phNodeMgr: Location to store node manager handle on output.
++ * hDevObject: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * NODE_Init(void) called.
++ * phNodeMgr != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Valide *phNodeMgr.
++ * error: *phNodeMgr == NULL.
++ */
++ extern DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete resources allocated in NODE_Allocate(). If the node was
++ * created, delete the node on the DSP by remotely calling the node's
++ * delete function. Loads the node's delete function if necessary.
++ * GPP side resources are freed after node's delete function returns.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EDELETE: A deletion failure occurred.
++ * DSP_EUSER1-16: Node specific failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred in deleting the node.
++ * DSP_ESYMBOL: Delete function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK: hNode is invalid.
++ */
++ extern DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid hNodeMgr.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr);
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated for the DSP.
++ * Parameters:
++ * hNodeMgr: Node manager returned from NODE_CreateMgr().
++ * aNodeTab: Array to copy node handles into.
++ * uNodeTabSize: Number of handles that can be written to aNodeTab.
++ * puNumNodes: Location where number of node handles written to
++ * aNodeTab will be written.
++ * puAllocated: Location to write total number of allocated nodes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESIZE: aNodeTab is too small to hold all node handles.
++ * Requires:
++ * Valid hNodeMgr.
++ * aNodeTab != NULL || uNodeTabSize == 0.
++ * puNumNodes != NULL.
++ * puAllocated != NULL.
++ * Ensures:
++ * - (DSP_ESIZE && *puNumNodes == 0)
++ * - || (DSP_SOK && *puNumNodes <= uNodeTabSize) &&
++ * (*puAllocated == *puNumNodes)
++ */
++ extern DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr,
++ IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NODE_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NODE_Init(void) will be freed when last NODE
++ * client calls NODE_Exit(void).
++ */
++ extern void NODE_Exit(void);
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Free a message buffer previously allocated with NODE_AllocMsgBuf.
++ * Parameters:
++ * hNode: The node handle.
++ * pBuffer: (Address) Buffer allocated by NODE_AllocMsgBuf.
++ * pAttr: Same buffer attributes passed to NODE_AllocMsgBuf.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EFAIL: Failure to free the buffer.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode,
++ IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr);
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * pAttr: Pointer to DSP_NODEATTR structure to copy node's
++ * attributes.
++ * uAttrSize: Size of pAttr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * NODE_Init(void) called.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *pAttrs contains the node's current attributes.
++ */
++ extern DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr,
++ u32 uAttrSize);
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP. The node must be either a
++ * message node, task node, or XDAIS socket node.
++ * If a message is not available, this function will block until a
++ * message is available, or the node's timeout value is reached.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * pMessage: Pointer to DSP_MSG structure to copy the
++ * message into.
++ * uTimeout: Timeout in milliseconds to wait for message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Cannot retrieve messages from this type of node.
++ * DSP_ETIMEOUT: Timeout occurred and no message is available.
++ * DSP_EFAIL: Error occurred while trying to retrieve a message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMessage != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode,
++ OUT struct DSP_MSG *pMessage,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_GetNldrObj ========
++ * Purpose:
++ * Retrieve the Nldr manager
++ * Parameters:
++ * hNodeMgr: Node Manager
++ * phNldrObj: Pointer to a Nldr manager handle
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ OUT struct NLDR_OBJECT **phNldrObj);
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NODE_Init(void);
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node. PROC needs to pass
++ * this function as a parameter to MSG_Create(). This function then gets
++ * called by the mini-driver when an exit message for a node is received.
++ * Parameters:
++ * hNode: Handle of the node that the exit message is for.
++ * nStatus: Return status of the node's execute phase.
++ * Returns:
++ * Ensures:
++ */
++ void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus);
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Node is not a task or socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_RUNNING state.
++ * DSP_EFAIL: Failed to pause node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node.
++ * This function will block until the message stream can accommodate
++ * the message, or a timeout occurs. The message will be copied, so Msg
++ * can be re-used immediately after return.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * pMsg: Location of message to be sent to the node.
++ * uTimeout: Timeout in msecs to wait.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Messages can't be sent to this type of node.
++ * DSP_ETIMEOUT: Timeout occurred before message could be set.
++ * DSP_EWRONGSTATE: Node is in invalid state for sending messages.
++ * DSP_EFAIL: Unable to send message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * NODE_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of
++ * a node that has been suspended (via NODE_Pause()) on the DSP. Load
++ * the node's execute function if necessary.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: hNode doesn't represent a message, task or dais
++ * socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_PAUSED or NODE_CREATED state.
++ * DSP_EFAIL: Unable to start or resume execution.
++ * DSP_ESYMBOL: Execute function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute
++ * phase function.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * pStatus: Location to store execute-phase function return
++ * value (DSP_EUSER1-16).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ENODETYPE: Type of node specified cannot be terminated.
++ * DSP_EWRONGSTATE: Operation not valid for the current node state.
++ * DSP_EFAIL: Unable to terminate the node.
++ * Requires:
++ * NODE_Init(void) called.
++ * pStatus != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode,
++ OUT DSP_STATUS *pStatus);
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node properties given the UUID
++ * Parameters:
++ *
++ */
++ extern DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS
++ *pNodeProps);
++
++#endif /* NODE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodedefs.h b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+new file mode 100644
+index 0000000..cdc0c4b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+@@ -0,0 +1,40 @@
++/*
++ * nodedefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nodedefs.h ========
++ * Description:
++ * Global NODE constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Apr-2001 jeh Removed NODE_MGRATTRS.
++ *! 21-Sep-2000 jeh Removed NODE_TYPE enum.
++ *! 17-Jul-2000 jeh Changed order of node types to match rms_sh.h.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEDEFS_
++#define NODEDEFS_
++
++#define NODE_SUSPENDEDPRI -1
++
++/* NODE Objects: */
++ struct NODE_MGR;
++ struct NODE_OBJECT;
++
++#endif /* NODEDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodepriv.h b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+new file mode 100644
+index 0000000..d28b29b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+@@ -0,0 +1,202 @@
++/*
++ * nodepriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== nodepriv.h ========
++ * Description:
++ * Private node header shared by NODE and DISP.
++ *
++ * Public Functions:
++ * NODE_GetChannelId
++ * NODE_GetStrmMgr
++ * NODE_GetTimeout
++ * NODE_GetType
++ * NODE_GetLoadType
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2002 map Added NODE_GetLoadType
++ *! 13-Feb-2002 jeh Added uSysStackSize to NODE_TASKARGS.
++ *! 23-Apr-2001 jeh Removed unused typedefs, defines.
++ *! 10-Oct-2000 jeh Added alignment to NODE_STRMDEF.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEPRIV_
++#define NODEPRIV_
++
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/* DSP address of node environment structure */
++ typedef u32 NODE_ENV;
++
++/*
++ * Node create structures
++ */
++
++/* Message node */
++ struct NODE_MSGARGS {
++ u32 uMaxMessages; /* Max # of simultaneous messages for node */
++ u32 uSegid; /* Segment for allocating message buffers */
++ u32 uNotifyType; /* Notify type (SEM_post, SWI_post, etc.) */
++ u32 uArgLength; /* Length in 32-bit words of arg data block */
++ u8 *pData; /* Argument data for node */
++ } ;
++
++ struct NODE_STRMDEF {
++ u32 uBufsize; /* Size of buffers for SIO stream */
++ u32 uNumBufs; /* max # of buffers in SIO stream at once */
++ u32 uSegid; /* Memory segment id to allocate buffers */
++ u32 uTimeout; /* Timeout for blocking SIO calls */
++ u32 uAlignment; /* Buffer alignment */
++ char *szDevice; /* Device name for stream */
++ } ;
++
++/* Task node */
++ struct NODE_TASKARGS {
++ struct NODE_MSGARGS msgArgs;
++ s32 nPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uDSPHeapResAddr; /* DSP virtual heap address */
++ u32 uDSPHeapAddr; /* DSP virtual heap address */
++ u32 uHeapSize; /* Heap size */
++ u32 uGPPHeapAddr; /* GPP virtual heap address */
++ u32 uProfileID; /* Profile ID */
++ u32 uNumInputs;
++ u32 uNumOutputs;
++ u32 ulDaisArg; /* Address of iAlg object */
++ struct NODE_STRMDEF *strmInDef;
++ struct NODE_STRMDEF *strmOutDef;
++ } ;
++
++/*
++ * ======== NODE_CREATEARGS ========
++ */
++ struct NODE_CREATEARGS {
++ union {
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ } asa;
++ } ;
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node. This index is reserved when NODE_Connect() is called
++ * to connect the node with the host. This index should be passed to
++ * the CHNL_Open function when the stream is actually opened.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * uDir: Input (DSP_TONODE) or output (DSP_FROMNODE).
++ * uIndex: Stream index.
++ * pulId: Location to store channel index.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Not a task or DAIS socket node.
++ * DSP_EVALUE: The node's stream corresponding to uIndex and uDir
++ * is not a stream to or from the host.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid uDir.
++ * pulId != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode,
++ u32 uDir,
++ u32 uIndex, OUT u32 *pulId);
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Get the STRM manager for a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate().
++ * phStrmMgr: Location to store STRM manager on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * phStrmMgr != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr);
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Get the timeout value of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node's timeout value.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern u32 NODE_GetTimeout(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Get the type (device, message, task, or XDAIS socket) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NODE_DEVICE, NODE_TASK, NODE_XDAIS, or NODE_GPP.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Get node information without holding semaphore.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node info: priority, device owner, no. of streams, execution state
++ * NDB properties.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern void GetNodeInfo(struct NODE_OBJECT *hNode,
++ struct DSP_NODEINFO *pNodeInfo);
++
++/*
++ * ======== NODE_GetLoadType ========
++ * Purpose:
++ * Get the load type (dynamic, overlay, static) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NLDR_DYNAMICLOAD, NLDR_OVLYLOAD, NLDR_STATICLOAD
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode);
++
++#endif /* NODEPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+new file mode 100644
+index 0000000..5a0992a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+@@ -0,0 +1,146 @@
++/*
++ * ntfy.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfy.h ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 05-Nov-2001 kc: Updated NTFY_Register.
++ *! 07-Sep-2000 jeh Created.
++ */
++
++#ifndef NTFY_
++#define NTFY_
++
++ struct NTFY_OBJECT;
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ * Parameters:
++ * phNtfy: Location to store handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * Requires:
++ * NTFY_Init(void) called.
++ * phNtfy != NULL.
++ * Ensures:
++ * DSP_SUCCEEDED(status) <==> IsValid(*phNtfy).
++ */
++ extern DSP_STATUS NTFY_Create(OUT struct NTFY_OBJECT **phNtfy);
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Delete(IN struct NTFY_OBJECT *hNtfy);
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void NTFY_Exit(void);
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NTFY_Init(void);
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event or post message) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * uEventMask: The type of event that has occurred.
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Notify(IN struct NTFY_OBJECT *hNtfy,
++ IN u32 uEventMask);
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * hNotification: Handle to a DSP_NOTIFICATION object.
++ * uEventMask: Events to be notified about.
++ * uNotifyType: Type of notification: DSP_SIGNALEVENT.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * hNotification != NULL.
++ * uNotifyType is DSP_SIGNALEVENT
++ * Ensures:
++ */
++ extern DSP_STATUS NTFY_Register(IN struct NTFY_OBJECT *hNtfy,
++ IN struct DSP_NOTIFICATION
++ *hNotification,
++ IN u32 uEventMask,
++ IN u32 uNotifyType);
++
++#endif /* NTFY_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/proc.h b/arch/arm/plat-omap/include/dspbridge/proc.h
+new file mode 100644
+index 0000000..486652e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/proc.h
+@@ -0,0 +1,648 @@
++/*
++ * proc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Create
++ * PROC_Ctrl (OEM-function)
++ * PROC_Destroy
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetDevObject (OEM-function)
++ * PROC_GetResourceInfo
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace (OEM-function)
++ * PROC_Init
++ * PROC_Load (OEM-function)
++ * PROC_Map
++ * PROC_NotifyAllclients
++ * PROC_NotifyClients (OEM-function)
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start (OEM-function)
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 09-Feb-2003 vp: Added PROC_GetProcessorID function
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 28-Sep-2000 rr: Updated to Version 0.9.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types). GetTrace added.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef PROC_
++#define PROC_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object. The PROC Object gets created
++ * Parameters:
++ * uProcessor : The processor index (zero-based).
++ * hMgrObject : Handle to the Manager Object
++ * pAttrIn : Ptr to the DSP_PROCESSORATTRIN structure.
++ * A NULL value means use default values.
++ * phProcessor : Ptr to location to store processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFAIL : General failure.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_SALREADYATTACHED: Success; Processor already attached.
++ * Requires:
++ * phProcessor != NULL.
++ * PROC Initialized.
++ * Ensures:
++ * DSP_EFAIL, and *phProcessor == NULL, OR
++ * Success and *phProcessor is a Valid Processor handle OR
++ * DSP_SALREADYATTACHED and *phProcessor is a Valid Processor.
++ * Details:
++ * When pAttrIn is NULL, the default timeout value is 10 seconds.
++ */
++ extern DSP_STATUS PROC_Attach(u32 uProcessor,
++ OPTIONAL CONST struct DSP_PROCESSORATTRIN
++ *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor);
++
++/*
++ * ======== PROC_AutoStart =========
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject : Handle to the Device
++ * Returns:
++ * DSP_SOK : On Successful Loading
++ * DSP_EFILE : No DSP exec file found.
++ * DSP_EFAIL : General Failure
++ * Requires:
++ * hDevObject != NULL.
++ * hDevNode != NULL.
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the DSP
++ * processor. This will be an OEM-only function, and not part of the
++ * 'Bridge application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * dwCmd : Private driver IOCTL cmd ID.
++ * pArgs : Ptr to an driver defined argument structure.
++ * Returns:
++ * DSP_SOK : SUCCESS
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ETIMEOUT: A Timeout Occured before the Control information
++ * could be sent.
++ * DSP_EACCESSDENIED: Client does not have the access rights required
++ * to call this function.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : General Failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures
++ * Details:
++ * This function Calls WMD_BRD_Ioctl.
++ */
++ extern DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor,
++ u32 dwCmd, IN struct DSP_CBDATA *pArgs);
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Close a DSP processor and de-allocate all (GPP) resources reserved
++ * for it. The Processor Object is deleted.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : InValid Handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * PROC Object is destroyed.
++ */
++ extern DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * aNodeTab : The first Location of an array allocated for node
++ * handles.
++ * uNodeTabSize: The number of (DSP_HNODE) handles that can be held
++ * to the memory the client has allocated for aNodeTab
++ * puNumNodes : Location where DSPProcessor_EnumNodes will return
++ * the number of valid handles written to aNodeTab
++ * puAllocated : Location where DSPProcessor_EnumNodes will return
++ * the number of nodes that are allocated on the DSP.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ESIZE : The amount of memory allocated for aNodeTab is
++ * insufficent. That is the number of nodes actually
++ * allocated on the DSP is greater than the value
++ * specified for uNodeTabSize.
++ * DSP_EFAIL : Unable to get Resource Information.
++ * Details:
++ * Requires
++ * puNumNodes is not NULL.
++ * puAllocated is not NULL.
++ * aNodeTab is not NULL.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor,
++ IN DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uResourceType: Type of resource .
++ * pResourceInfo: Ptr to the DSP_RESOURCEINFO structure.
++ * uResourceInfoSize: Size of the structure.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: The processor is not in the PROC_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occured before the DSP responded to the
++ * querry.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : Unable to get Resource Information
++ * Requires:
++ * pResourceInfo is not NULL.
++ * Parameter uResourceType is Valid.[TBD]
++ * uResourceInfoSize is >= sizeof DSP_RESOURCEINFO struct.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * This function currently returns
++ * DSP_ENOTIMPL, and does not write any data to the pResourceInfo struct.
++ */
++ extern DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor,
++ u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *
++ pResourceInfo,
++ u32 uResourceInfoSize);
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * PROC is initialized.
++ * Ensures:
++ * When reference count == 0, PROC's private resources are freed.
++ */
++ extern void PROC_Exit(void);
++
++/*
++ * ======== PROC_GetDevObject =========
++ * Purpose:
++ * Returns the DEV Hanlde for a given Processor handle
++ * Parameters:
++ * hProcessor : Processor Handle
++ * phDevObject : Location to store the DEV Handle.
++ * Returns:
++ * DSP_SOK : Success; *phDevObject has Dev handle
++ * DSP_EFAIL : Failure; *phDevObject is zero.
++ * Requires:
++ * phDevObject is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * DSP_SOK : *phDevObject is not NULL
++ * DSP_EFAIL : *phDevObject is NULL.
++ */
++ extern DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each
++ * call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public PROC functions.
++ */
++ extern bool PROC_Init(void);
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pProcStatus : Ptr to location to store the DSP_PROCESSORSTATE
++ * structure.
++ * uStateInfoSize: Size of DSP_PROCESSORSTATE.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE
++ *pProcStatus,
++ u32 uStateInfoSize);
++
++/*
++ * ======== PROC_GetProcessorID ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * procID : Processor ID
++ *
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProcessor,
++ u32 *procID);
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the trace buffer from the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pBuf : Ptr to buffer to hold trace output.
++ * uMaxSize : Maximum size of the output buffer.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while retireving processor trace
++ * Buffer.
++ * Requires:
++ * pBuf is not NULL
++ * uMaxSize is > 0.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf,
++ u32 uMaxSize);
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * iArgc : The number of Arguments(strings)in the aArgV[]
++ * aArgv : An Array of Arguments(Unicode Strings)
++ * aEnvp : An Array of Environment settings(Unicode Strings)
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFILE : The DSP Execuetable was not found.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ECORRUTFILE: Unable to Parse the DSP Execuetable
++ * DSP_EATTACHED: Abort because a GPP Client is attached to the
++ * specified Processor
++ * DSP_EACCESSDENIED: Client does not have the required access rights
++ * to reset and load the Processor
++ * DSP_EFAIL : Unable to Load the Processor
++ * Requires:
++ * aArgv is not NULL
++ * iArgc is > 0
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_LOADED
++ * or DSP_FAILED status.
++ * Details:
++ * Does not implement access rights to control which GPP application
++ * can load the processor.
++ */
++ extern DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor,
++ IN CONST s32 iArgc, IN CONST char **aArgv,
++ IN CONST char **aEnvp);
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uEventMask : Mask of types of events to be notified about.
++ * uNotifyType : Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle or hNotification.
++ * DSP_EVALUE : Parameter uEventMask is Invalid
++ * DSP_ENOTIMP : The notification type specified in uNotifyMask
++ * is not supported.
++ * DSP_EFAIL : Unable to register for notification.
++ * Requires:
++ * hNotification is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * NODE And STRM would use this function to notify their clients
++ * about the state changes in NODE or STRM.
++ */
++ extern DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flushes a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * ulFlags : Reserved.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize, u32 ulFlags);
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize);
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Starting address of the memory region to map.
++ * ulSize : Size of the memory region to map.
++ * pReqAddr : Requested DSP start address. Offset-adjusted actual
++ * mapped address is in the last argument.
++ * ppMapAddr : Ptr to DSP side mapped u8 address.
++ * ulMapAttr : Optional endianness attributes, virt to phys flag.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : MPU side memory allocation error.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pMpuAddr is not NULL
++ * ulSize is not zero
++ * ppMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize,
++ void *pReqAddr,
++ void **ppMapAddr, u32 ulMapAttr);
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * ulSize : Size of the address space to reserve.
++ * ppRsvAddr : Ptr to DSP side reserved u8 address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : Cannot reserve chunk of this size.
++ * Requires:
++ * ppRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
++ u32 ulSize, void **ppRsvAddr);
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMapAddr : Starting address of the mapped memory region.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a mapped region starting with this
++ * : address.
++ * Requires:
++ * pMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr);
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pRsvAddr : Ptr to DSP side reservedBYTE address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
++ void *pRsvAddr);
++
++#endif /* PROC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/procpriv.h b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+new file mode 100644
+index 0000000..21d4b3e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+@@ -0,0 +1,35 @@
++/*
++ * procpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== procpriv.h ========
++ * Description:
++ * Global PROC constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef PROCPRIV_
++#define PROCPRIV_
++
++/* RM PROC Object */
++ struct PROC_OBJECT;
++
++#endif /* PROCPRIV_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr.h b/arch/arm/plat-omap/include/dspbridge/pwr.h
+new file mode 100644
+index 0000000..a6645ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr.h
+@@ -0,0 +1,129 @@
++/*
++ * pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== pwr.h ========
++ *
++ * Public Functions:
++ *
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Jun-2002 sg Replaced dspdefs.h with includes of dbdefs.h and errbase.h.
++ *! 13-May-2002 sg Added DSP_SAREADYASLEEP and DSP_SALREADYAWAKE.
++ *! 09-May-2002 sg Updated, added timeouts.
++ *! 02-May-2002 sg Initial.
++ */
++
++#ifndef PWR_
++#define PWR_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/pwr_sh.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Signal the DSP to go to sleep.
++ *
++ * Parameters:
++ * sleepCode: New sleep state for DSP. (Initially, valid codes
++ * are PWR_DEEPSLEEP or PWR_EMERGENCYDEEPSLEEP; both of
++ * these codes will simply put the DSP in deep sleep.)
++ *
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP sleep state has been
++ * reached. If PWR should simply send the command to
++ * the DSP to go to sleep and then return (i.e.,
++ * asynchrounous sleep), the timeout should be
++ * specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYASLEEP: Success, but the DSP was already asleep.
++ * DSP_EINVALIDARG: The specified sleepCode is not supported.
++ * DSP_ETIMEOUT: A timeout occured while waiting for DSP sleep
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send sleep command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode,
++ IN CONST u32 timeout);
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Signal the DSP to wake from sleep.
++ *
++ * Parameters:
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP is awake. If PWR should
++ * simply send a command to the DSP to wake and then
++ * return (i.e., asynchrounous wake), timeout should
++ * be specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout);
++
++/*
++ * ======== PWR_PM_PreScale ========
++ * Prescale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level);
++
++/*
++ * ======== PWR_PM_PostScale ========
++ * PostScale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain,
++ u32 level);
++
++#endif /* PWR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr_sh.h b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+new file mode 100644
+index 0000000..40f1b84
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+@@ -0,0 +1,41 @@
++/*
++ * pwr_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== pwr_sh.h ========
++ *
++ * Power Manager shared definitions (used on both GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 17-Apr-2002 sg: Initial.
++ */
++
++#ifndef PWR_SH_
++#define PWR_SH_
++
++#include <dspbridge/mbx_sh.h>
++
++/* valid sleep command codes that can be sent by GPP via mailbox: */
++#define PWR_DEEPSLEEP MBX_PM_DSPIDLE
++#define PWR_EMERGENCYDEEPSLEEP MBX_PM_EMERGENCYSLEEP
++#define PWR_SLEEPUNTILRESTART MBX_PM_SLEEPUNTILRESTART
++#define PWR_WAKEUP MBX_PM_DSPWAKEUP
++#define PWR_AUTOENABLE MBX_PM_PWRENABLE
++#define PWR_AUTODISABLE MBX_PM_PWRDISABLE
++#define PWR_RETENTION MBX_PM_DSPRETN
++
++#endif /* PWR_SH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/reg.h b/arch/arm/plat-omap/include/dspbridge/reg.h
+new file mode 100644
+index 0000000..5b34952
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/reg.h
+@@ -0,0 +1,257 @@
++/*
++ * reg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== reg.h ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumKey
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! =================
++ *! 30-Oct-2000 kc: Updated REG_SetValue & REG_GetValue; renamed
++ *! REG_DeleteEntry to REG_DeleteValue.
++ *! 29-Sep-2000 kc: Updated a REG functions for code review.
++ *! 12-Aug-2000 kc: Renamed REG_EnumValue to REG_EnumKey. Re-implemented
++ *! REG_EnumValue.
++ *! 03-Feb-2000 rr: REG_EnumValue Fxn Added
++ *! 13-Dec-1999 rr: windows.h removed
++ *! 02-Dec-1999 rr: windows.h included for retail build
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 29-Dec-1997 cr: Changes from code review.
++ *! 27-Oct-1997 cr: Added REG_DeleteValue.
++ *! 20-Oct-1997 cr: Added ability to pass bValue = NULL to REG_GetValue
++ *! and return size of reg entry in pdwValueSize.
++ *! 29-Sep-1997 cr: Added REG_SetValue
++ *! 29-Aug-1997 cr: Created.
++ */
++
++#ifndef _REG_H
++#define _REG_H
++
++#include <linux/types.h>
++
++/* ------------------------- Defines, Data Structures, Typedefs for Linux */
++#ifndef UNDER_CE
++
++#ifndef REG_SZ
++#define REG_SZ 1
++#endif
++
++#ifndef REG_BINARY
++#define REG_BINARY 3
++#endif
++
++#ifndef REG_DWORD
++#define REG_DWORD 4
++#endif
++
++#endif /* UNDER_CE */
++
++#define REG_MAXREGPATHLENGTH 255
++
++/*
++ * ======== REG_DeleteValue ========
++ * Purpose:
++ * Deletes a registry entry. NOTE: A registry entry is not the same as
++ * a registry key.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrValue: Name of entry to delete.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrValue are non-NULL values.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrValue < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++
++/*
++ * ======== REG_EnumKey ========
++ * Purpose:
++ * Enumerates subkeys of the specified path to the registry key
++ * Retrieves the name of the subkey(given the index) and
++ * appends with the orignal path to form the full path.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrKey The name of the registry key to be enumerated.
++ * dwIndex Specifies the index of the subkey to retrieve.
++ * pstrSubkey: Pointer to buffer that receives full path name of the
++ * specified key + the sub-key
++ * pdwValueSize: Specifies bytes of memory pstrSubkey points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If there is no sub key,pdwValueSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrKey is non-NULL value.
++ * - pdwValueSize is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrKey < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * - strlen(pstrSubkey) is > strlen(pstrKey) &&
++ * - strlen(pstrSubkey) is < REG_MAXREGPATHLENGTH
++ */
++ extern DSP_STATUS REG_EnumKey(OPTIONAL IN HANDLE *phKey,
++ IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrSubkey,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_EnumValue ========
++ * Purpose:
++ * Enumerates values of a specified key. Retrieves each value name and
++ * the data associated with the value.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * dwIndex: Specifies the index of the value to retrieve.
++ * pstrKey: The name of the registry key to be enumerated.
++ * pstrValue: Pointer to buffer that receives the name of the value.
++ * pdwValueSize: Specifies bytes of memory pstrValue points to on input,
++ * On output, specifies actual memory bytes written into.
++ * If there is no value, pdwValueSize returns NULL
++ * pstrData: Pointer to buffer that receives the data of a value.
++ * pdwDataSize: Specifies bytes of memory in pstrData on input and
++ * bytes of memory written into pstrData on output.
++ * If there is no data, pdwDataSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * REG initialized.
++ * phKey is NULL.
++ * pstrKey is a non-NULL value.
++ * pstrValue, pstrData, pdwValueSize and pdwDataSize are valid pointers.
++ * Length of pstrKey is less than REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_EnumValue(IN HANDLE *phKey,
++ IN u32 dwIndex,
++ IN CONST char *pstrKey,
++ IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize);
++
++/*
++ * ======== REG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * REG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void REG_Exit(void);
++
++/*
++ * ======== REG_GetValue ========
++ * Purpose:
++ * Retrieve a value from the registry.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrEntry: Name of entry to retrieve.
++ * pbValue: Upon return, points to retrieved value.
++ * pdwValueSize: Specifies bytes of memory pbValue points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If pbValue is NULL, pdwValueSize reports the size of
++ * the entry in pstrEntry.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrEntry,
++ OUT u8 *pbValue,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_Init ========
++ * Purpose:
++ * Initializes private state of REG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * REG initialized.
++ */
++ extern bool REG_Init(void);
++
++/*
++ * ======== REG_SetValue ========
++ * Purpose:
++ * Set a value in the registry.
++ * Parameters:
++ * phKey: Handle to open reg key, or NULL if pSubkey is full path.
++ * pstrSubkey: Path to key to open, could be based on phKey.
++ * pstrEntry: Name of entry to set.
++ * dwType: Data type of new registry value.
++ * pbValue: Points to buffer containing new data.
++ * dwValueSize: Specifies bytes of memory bValue points to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - dwValuSize > 0.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubKey,
++ IN CONST char *pstrEntry,
++ IN CONST u32 dwType,
++ IN u8 *pbValue, IN u32 dwValueSize);
++
++#endif /* _REG_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+new file mode 100644
+index 0000000..b43fa16
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+@@ -0,0 +1,88 @@
++/*
++ * resourcecleanup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef RES_CLEANUP_DISABLE
++
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/drv.h>
++
++
++extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject);
++
++extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
++ HANDLE hPCtxt);
++
++extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdatestate(HANDLE pCtxt,
++ enum GPP_PROC_RES_STATE resState);
++
++extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
++
++extern DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr);
++
++extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
++
++extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess);
++
++extern DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_RemoveNodeResElement(HANDLE nodeRes, HANDLE status);
++
++extern void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_UpdateDMMResElement(HANDLE dmmRes, u32 pMpuAddr,
++ u32 ulSize, u32 pReqAddr,
++ u32 ppMapAddr, HANDLE hProcesso);
++
++extern DSP_STATUS DRV_InsertDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE dmmRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pPctxt);
++
++extern DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE STRMRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf, u32 *pSize);
++
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmm.h b/arch/arm/plat-omap/include/dspbridge/rmm.h
+new file mode 100644
+index 0000000..5b14b8f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmm.h
+@@ -0,0 +1,199 @@
++/*
++ * rmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.h ========
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments, and management of overlay
++ * memory.
++ *
++ * Public functions:
++ * RMM_alloc
++ * RMM_create
++ * RMM_delete
++ * RMM_exit
++ * RMM_free
++ * RMM_init
++ *
++ *! Revision History
++ *! ================
++ *! 25-Jun-2002 jeh Added RMM_Addr. Removed RMM_reserve, RMM_stat.
++ *! 15-Oct-2001 jeh Based on rm.h in gen tree.
++ */
++
++#ifndef RMM_
++#define RMM_
++
++/*
++ * ======== RMM_Addr ========
++ * DSP address + segid
++ */
++struct RMM_Addr {
++ u32 addr;
++ s32 segid;
++} ;
++
++/*
++ * ======== RMM_Segment ========
++ * Memory segment on the DSP available for remote allocations.
++ */
++struct RMM_Segment {
++ u32 base; /* Base of the segment */
++ u32 length; /* Size of the segment (target MAUs) */
++ s32 space; /* Code or data */
++ u32 number; /* Number of Allocated Blocks */
++} ;
++
++/*
++ * ======== RMM_Target ========
++ */
++struct RMM_TargetObj;
++
++/*
++ * ======== RMM_alloc ========
++ *
++ * RMM_alloc is used to remotely allocate or reserve memory on the DSP.
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * segid - Memory segment to allocate from.
++ * size - Size (target MAUS) to allocate.
++ * align - alignment.
++ * dspAddr - If reserve is FALSE, the location to store allocated
++ * address on output, otherwise, the DSP address to
++ * reserve.
++ * reserve - If TRUE, reserve the memory specified by dspAddr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation on GPP failed.
++ * DSP_EOVERLAYMEMORY: Cannot "allocate" overlay memory because it's
++ * already in use.
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * dspAddr != NULL.
++ * size > 0
++ * reserve || target->numSegs > 0.
++ * Ensures:
++ */
++extern DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAdr, bool reserve);
++
++/*
++ * ======== RMM_create ========
++ * Create a target object with memory segments for remote allocation. If
++ * segTab == NULL or numSegs == 0, memory can only be reserved through
++ * RMM_alloc().
++ *
++ * Parameters:
++ * pTarget: - Location to store target on output.
++ * segTab: - Table of memory segments.
++ * numSegs: - Number of memory segments.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * RMM initialized.
++ * pTarget != NULL.
++ * numSegs == 0 || segTab != NULL.
++ * Ensures:
++ * Success: Valid *pTarget.
++ * Failure: *pTarget == NULL.
++ */
++extern DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs);
++
++/*
++ * ======== RMM_delete ========
++ * Delete target allocated in RMM_create().
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * Ensures:
++ */
++extern void RMM_delete(struct RMM_TargetObj *target);
++
++/*
++ * ======== RMM_exit ========
++ * Exit the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * RMM_init successfully called.
++ * Ensures:
++ */
++extern void RMM_exit(void);
++
++/*
++ * ======== RMM_free ========
++ * Free or unreserve memory allocated through RMM_alloc().
++ *
++ * Parameters:
++ * target: - Target returned from RMM_create().
++ * segid: - Segment of memory to free.
++ * dspAddr: - Address to free or unreserve.
++ * size: - Size of memory to free or unreserve.
++ * reserved: - TRUE if memory was reserved only, otherwise FALSE.
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * reserved || segid < target->numSegs.
++ * reserve || [dspAddr, dspAddr + size] is a valid memory range.
++ * Ensures:
++ */
++extern bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 dspAddr,
++ u32 size, bool reserved);
++
++/*
++ * ======== RMM_init ========
++ * Initialize the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * Ensures:
++ */
++extern bool RMM_init(void);
++
++/*
++ * ======== RMM_stat ========
++ * Obtain memory segment status
++ *
++ * Parameters:
++ * segid: Segment ID of the dynamic loading segment.
++ * pMemStatBuf: Pointer to allocated buffer into which memory stats are
++ * placed.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * segid < target->numSegs
++ * Ensures:
++ */
++extern bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf);
++
++#endif /* RMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/rms_sh.h b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+new file mode 100644
+index 0000000..5d4b49a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+@@ -0,0 +1,125 @@
++/*
++ * rms_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rms_sh.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared definitions (used on both
++ * GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Merged updates required for CCS2.2 transition.
++ *! 24-Feb-2003 kc Rearranged order of node types to temporarily support
++ *! legacy message node code
++ *! 23-Nov-2002 gp Converted tabs -> spaces, to fix formatting.
++ *! 13-Feb-2002 jeh Added sysstacksize element to RMS_MoreTaskArgs.
++ *! 11-Dec-2000 sg Added 'misc' element to RMS_MoreTaskArgs.
++ *! 04-Dec-2000 ag Added RMS_BUFDESC command code.
++ *! C/R code value changed to allow ORing of system/user codes.
++ *! 10-Oct-2000 sg Added 'align' field to RMS_StrmDef.
++ *! 09-Oct-2000 sg Moved pre-defined message codes here from rmsdefs.h.
++ *! 02-Oct-2000 sg Changed ticks to msec.
++ *! 24-Aug-2000 sg Moved definitions that will be exposed to app developers
++ *! to a separate file, rmsdefs.h.
++ *! 10-Aug-2000 sg Added RMS_COMMANDBUFSIZE and RMS_RESPONSEBUFSIZE; added
++ *! pre-defined command/response codes; more comments.
++ *! 09-Aug-2000 sg Added RMS_ETASK.
++ *! 08-Aug-2000 jeh Define RMS_WORD for GPP, rename DSP_MSG to RMS_DSPMSG.
++ *! Added RMS_MsgArgs, RMS_MoreTaskArgs.
++ *! 25-Jul-2000 sg: Changed SIO to STRM.
++ *! 30-Jun-2000 sg: Initial.
++ */
++
++#ifndef RMS_SH_
++#define RMS_SH_
++
++#include <dspbridge/rmstypes.h>
++
++/* Node Types: */
++#define RMS_TASK 1 /* Task node */
++#define RMS_DAIS 2 /* xDAIS socket node */
++#define RMS_MSG 3 /* Message node */
++
++/* Memory Types: */
++#define RMS_CODE 0 /* Program space */
++#define RMS_DATA 1 /* Data space */
++#define RMS_IO 2 /* I/O space */
++
++/* RM Server Command and Response Buffer Sizes: */
++#define RMS_COMMANDBUFSIZE 256 /* Size of command buffer */
++#define RMS_RESPONSEBUFSIZE 16 /* Size of response buffer */
++
++/* Pre-Defined Command/Response Codes: */
++#define RMS_EXIT 0x80000000 /* GPP->Node: shutdown */
++#define RMS_EXITACK 0x40000000 /* Node->GPP: ack shutdown */
++#define RMS_BUFDESC 0x20000000 /* Arg1 SM buf, Arg2 is SM size */
++#define RMS_KILLTASK 0x10000000 /* GPP->Node: Kill Task */
++#define RMS_USER 0x0 /* Start of user-defined msg codes */
++#define RMS_MAXUSERCODES 0xfff /* Maximum user defined C/R Codes */
++
++
++/* RM Server RPC Command Structure: */
++ struct RMS_Command {
++ RMS_WORD fxn; /* Server function address */
++ RMS_WORD arg1; /* First argument */
++ RMS_WORD arg2; /* Second argument */
++ RMS_WORD data; /* Function-specific data array */
++ } ;
++
++/*
++ * The RMS_StrmDef structure defines the parameters for both input and output
++ * streams, and is passed to a node's create function.
++ */
++ struct RMS_StrmDef {
++ RMS_WORD bufsize; /* Buffer size (in DSP words) */
++ RMS_WORD nbufs; /* Max number of bufs in stream */
++ RMS_WORD segid; /* Segment to allocate buffers */
++ RMS_WORD align; /* Alignment for allocated buffers */
++ RMS_WORD timeout; /* Timeout (msec) for blocking calls */
++ RMS_CHAR name[1]; /* Device Name (terminated by '\0') */
++ } ;
++
++/* Message node create args structure: */
++ struct RMS_MsgArgs {
++ RMS_WORD maxMessages; /* Max # simultaneous msgs to node */
++ RMS_WORD segid; /* Mem segment for NODE_allocMsgBuf */
++ RMS_WORD notifyType; /* Type of message notification */
++ RMS_WORD argLength; /* Length (in DSP chars) of arg data */
++ RMS_WORD argData; /* Arg data for node */
++ } ;
++
++/* Partial task create args structure */
++ struct RMS_MoreTaskArgs {
++ RMS_WORD priority; /* Task's runtime priority level */
++ RMS_WORD stackSize; /* Task's stack size */
++ RMS_WORD sysstackSize; /* Task's system stack size (55x) */
++ RMS_WORD stackSeg; /* Memory segment for task's stack */
++ RMS_WORD heapAddr; /* base address of the node memory heap in
++ * external memory (DSP virtual address) */
++ RMS_WORD heapSize; /* size in MAUs of the node memory heap in
++ * external memory */
++ RMS_WORD misc; /* Misc field. Not used for 'normal'
++ * task nodes; for xDAIS socket nodes
++ * specifies the IALG_Fxn pointer.
++ */
++ /* # input STRM definition structures */
++ RMS_WORD numInputStreams;
++ } ;
++
++#endif /* RMS_SH_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmstypes.h b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+new file mode 100644
+index 0000000..13d752e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+@@ -0,0 +1,40 @@
++/*
++ * rmstypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== rmstypes.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared data type definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 06-Oct-2000 sg Added LgFxn type.
++ *! 05-Oct-2000 sg Changed RMS_STATUS to LgUns.
++ *! 31-Aug-2000 sg Added RMS_DSPMSG.
++ *! 25-Aug-2000 sg Initial.
++ */
++
++#ifndef RMSTYPES_
++#define RMSTYPES_
++#include <linux/types.h>
++/*
++ * DSP-side definitions.
++ */
++#include <dspbridge/std.h>
++typedef u32 RMS_WORD;
++typedef char RMS_CHAR;
++
++#endif /* RMSTYPES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/services.h b/arch/arm/plat-omap/include/dspbridge/services.h
+new file mode 100644
+index 0000000..35bab0d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/services.h
+@@ -0,0 +1,63 @@
++/*
++ * services.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.h ========
++ * Purpose:
++ * Provide loading and unloading of SERVICES modules.
++ *
++ * Public Functions:
++ * SERVICES_Exit(void)
++ * SERVICES_Init(void)
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#ifndef SERVICES_
++#define SERVICES_
++
++#include <dspbridge/host_os.h>
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SERVICES initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SERVICES_Exit(void);
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ * Parameters:
++ * Returns:
++ * TRUE if all modules initialized; otherwise FALSE.
++ * Requires:
++ * Ensures:
++ * SERVICES modules initialized.
++ */
++ extern bool SERVICES_Init(void);
++
++#endif /* SERVICES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/std.h b/arch/arm/plat-omap/include/dspbridge/std.h
+new file mode 100644
+index 0000000..ec849f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/std.h
+@@ -0,0 +1,143 @@
++/*
++ * std.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== std.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp GNU compiler 3.x defines inline keyword. Added
++ *! appropriate macros not to redefine inline keyword in
++ *! this file.
++ *! 24-Oct-2002 ashu defined _TI_ and _FIXED_ symbols for 28x.
++ *! 24-Oct-2002 ashu defined _TI_ for 24x.
++ *! 01-Mar-2002 kln changed LARGE_MODEL and Arg definition for 28x
++ *! 01-Feb-2002 kln added definitions for 28x
++ *! 08-Dec-2000 kw: added 'ArgToInt' and 'ArgToPtr' macros
++ *! 30-Nov-2000 mf: Added _64_, _6x_; removed _7d_
++ *! 30-May-2000 srid: Added __TMS320C55X__ for 55x; Arg is void * for 55 .
++ *! 18-Jun-1999 dr: Added '_TI_', fixed __inline for SUN4, added inline
++ *! 10-Feb-1999 rt: Added '55' support, changed 54's symbol to _TMS320C5XX
++ *! 29-Aug-1998 mf: fixed typo, removed obsolete targets
++ *! 08-Jun-1998 mf: _67_ is synonym for _7d_
++ *! 10-Oct-1997 rt; added _7d_ for Raytheon C7DSP triggered by _TMS320C6700
++ *! 04-Aug-1997 cc: added _29_ for _TMS320C2XX
++ *! 11-Jul-1997 dlr: _5t_, and STD_SPOXTASK keyword for Tasking
++ *! 12-Jun-1997 mf: _TMS320C60 -> _TMS320C6200
++ *! 13-Feb-1997 mf: _62_, with 32-bit LgInt
++ *! 26-Nov-1996 kw: merged bios-c00's and wsx-a27's <dspbridge/std.h> changes
++ *! *and* revision history
++ *! 12-Sep-1996 kw: added C54x #ifdef's
++ *! 21-Aug-1996 mf: removed #define main smain for _21_
++ *! 14-May-1996 gp: def'd out INT, FLOAT, and COMPLEX defines for WSX.
++ *! 11-Apr-1996 kw: define _W32_ based on _WIN32 (defined by MS compiler)
++ *! 07-Mar-1996 mg: added Win32 support
++ *! 06-Sep-1995 dh: added _77_ dynamic stack support via fxns77.h
++ *! 27-Jun-1995 dh: added _77_ support
++ *! 16-Mar-1995 mf: for _21_: #define main smain
++ *! 01-Mar-1995 mf: set _20_ and _60_ (as well as _21_ for both)
++ *! 22-Feb-1995 mf: Float is float for _SUN_ and _80_
++ *! 22-Dec-1994 mf: Added _80_ definition, for PP or MP.
++ *! 09-Dec-1994 mf: Added _53_ definition.
++ *! Added definitions of _30_, etc.
++ *! 23-Aug-1994 dh removed _21_ special case (kw)
++ *! 17-Aug-1994 dh added _51_ support
++ *! 03-Aug-1994 kw updated _80_ support
++ *! 30-Jun-1994 kw added _80_ support
++ *! 05-Apr-1994 kw: Added _SUN_ to _FLOAT_ definition
++ *! 01-Mar-1994 kw: Made Bool an int (was u16) for _56_ (more efficient).
++ *! Added _53_ support.
++ */
++
++#ifndef STD_
++#define STD_
++
++#include <linux/types.h>
++
++/*
++ * ======== _TI_ ========
++ * _TI_ is defined for all TI targets
++ */
++#if defined(_29_) || defined(_30_) || defined(_40_) || defined(_50_) || \
++ defined(_54_) || defined(_55_) || defined(_6x_) || defined(_80_) || \
++ defined(_28_) || defined(_24_)
++#define _TI_ 1
++#endif
++
++/*
++ * ======== _FLOAT_ ========
++ * _FLOAT_ is defined for all targets that natively support floating point
++ */
++#if defined(_SUN_) || defined(_30_) || defined(_40_) || defined(_67_) || \
++ defined(_80_)
++#define _FLOAT_ 1
++#endif
++
++/*
++ * ======== _FIXED_ ========
++ * _FIXED_ is defined for all fixed point target architectures
++ */
++#if defined(_29_) || defined(_50_) || defined(_54_) || defined(_55_) || \
++ defined(_62_) || defined(_64_) || defined(_28_)
++#define _FIXED_ 1
++#endif
++
++/*
++ * ======== _TARGET_ ========
++ * _TARGET_ is defined for all target architectures (as opposed to
++ * host-side software)
++ */
++#if defined(_FIXED_) || defined(_FLOAT_)
++#define _TARGET_ 1
++#endif
++
++/*
++ * 8, 16, 32-bit type definitions
++ *
++ * Sm* - 8-bit type
++ * Md* - 16-bit type
++ * Lg* - 32-bit type
++ *
++ * *s32 - signed type
++ * *u32 - unsigned type
++ * *Bits - unsigned type (bit-maps)
++ */
++
++/*
++ * Aliases for standard C types
++ */
++
++typedef s32(*Fxn) (void); /* generic function type */
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++
++/*
++ * These macros are used to cast 'Arg' types to 's32' or 'Ptr'.
++ * These macros were added for the 55x since Arg is not the same
++ * size as s32 and Ptr in 55x large model.
++ */
++#if defined(_28l_) || defined(_55l_)
++#define ArgToInt(A) ((s32)((long)(A) & 0xffff))
++#define ArgToPtr(A) ((Ptr)(A))
++#else
++#define ArgToInt(A) ((s32)(A))
++#define ArgToPtr(A) ((Ptr)(A))
++#endif
++
++#endif /* STD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strm.h b/arch/arm/plat-omap/include/dspbridge/strm.h
+new file mode 100644
+index 0000000..5825615
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strm.h
+@@ -0,0 +1,441 @@
++/*
++ * strm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.h ========
++ * Description:
++ * DSPBridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 15-Nov-2001 ag Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Added DSP_ESIZE error to STRM_AllocateBuffer().
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 06-Feb-2001 kc Updated DBC_Ensure for STRM_Select().
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open().
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRM_
++#define STRM_
++
++#include <dspbridge/dev.h>
++
++#include <dspbridge/strmdefs.h>
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocate data buffer(s) for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer(s).
++ * uNumBufs: Number of buffers to allocate.
++ * apBuffer: Array to hold buffer addresses.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EFAIL: Failure occurred, unable to allocate buffers.
++ * DSP_ESIZE: uSize must be > 0 bytes.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ OUT u8 **apBuffer,
++ u32 uNumBufs);
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EPENDING: Some data buffers issued to the stream have not
++ * been reclaimed.
++ * DSP_EFAIL: Failure to close stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm);
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object. This object holds information about the
++ * device needed to open streams.
++ * Parameters:
++ * phStrmMgr: Location to store handle to STRM manager object on
++ * output.
++ * hDev: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrmMgr != NULL.
++ * hDev != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phStrmMgr.
++ * error: *phStrmMgr == NULL.
++ */
++ extern DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr,
++ struct DEV_OBJECT *hDev);
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Object.
++ * Parameters:
++ * hStrmMgr: Handle to STRM manager object from STRM_Create.
++ * Returns:
++ * Requires:
++ * STRM_Init(void) called.
++ * Valid hStrmMgr.
++ * Ensures:
++ * hStrmMgr is not valid.
++ */
++ extern void STRM_Delete(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * STRM_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void STRM_Exit(void);
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Free buffer(s) allocated with STRM_AllocateBuffer.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * apBuffer: Array containing buffer addresses.
++ * uNumBufs: Number of buffers to be freed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid stream handle.
++ * DSP_EFAIL: Failure occurred, unable to free buffers.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm,
++ u8 **apBuffer, u32 uNumBufs);
++
++/*
++ * ======== STRM_GetEventHandle ========
++ * Purpose:
++ * Get stream's user event handle. This function is used when closing
++ * a stream, so the event can be closed.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * phEvent: Location to store event handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * Requires:
++ * STRM_Init(void) called.
++ * phEvent != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetEventHandle(struct STRM_OBJECT *hStrm,
++ OUT HANDLE *phEvent);
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Get information about a stream. User's DSP_STREAMINFO is contained
++ * in STRM_INFO struct. STRM_INFO also contains Bridge private info.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pStreamInfo: Location to store stream info on output.
++ * uSteamInfoSize: Size of user's DSP_STREAMINFO structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESIZE: uStreamInfoSize < sizeof(DSP_STREAMINFO).
++ * DSP_EFAIL: Unable to get stream info.
++ * Requires:
++ * STRM_Init(void) called.
++ * pStreamInfo != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize);
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idle a stream and optionally flush output data buffers.
++ * If this is an output stream and fFlush is TRUE, all data currently
++ * enqueued will be discarded.
++ * If this is an output stream and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ * After a successful call to STRM_Idle(), all buffers can immediately
++ * be reclaimed.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * fFlush: If TRUE, discard output buffers.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before the stream could be idled.
++ * DSP_ERESTART: A critical error occurred, DSP is being restarted.
++ * DSP_EFAIL: Unable to idle stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush);
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool STRM_Init(void);
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Send a buffer of data to a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBuf: Pointer to buffer of data to be sent to the stream.
++ * ulBytes: Number of bytes of data in the buffer.
++ * ulBufSize: Actual buffer size in bytes.
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESTREAMFULL: The stream is full.
++ * DSP_EFAIL: Failure occurred, unable to issue buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuf != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf,
++ u32 ulBytes, u32 ulBufSize,
++ IN u32 dwArg);
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task of
++ * DAIS socket node on the DSP.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * uDir: DSP_TONODE or DSP_FROMNODE.
++ * uIndex: Stream index.
++ * pAttr: Pointer to structure containing attributes to be
++ * applied to stream. Cannot be NULL.
++ * phStrm: Location to store stream handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EDIRECTION: Invalid uDir.
++ * DSP_EVALUE: Invalid uIndex.
++ * DSP_ENODETYPE: hNode is not a task or DAIS socket node.
++ * DSP_EFAIL: Unable to open stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrm != NULL.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *phStrm is valid.
++ * error: *phStrm == NULL.
++ */
++ extern DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir,
++ u32 uIndex, IN struct STRM_ATTR *pAttr,
++ OUT struct STRM_OBJECT **phStrm);
++
++/*
++ * ======== STRM_PrepareBuffer ========
++ * Purpose:
++ * Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
++ * for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to prepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_PrepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Request a buffer back from a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBufPtr: Location to store pointer to reclaimed buffer.
++ * pulBytes: Location where number of bytes of data in the
++ * buffer will be written.
++ * pulBufSize: Location where actual buffer size will be written.
++ * pdwArg: Location where user argument that travels with
++ * the buffer will be written.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before a buffer could be
++ * retrieved.
++ * DSP_EFAIL: Failure occurred, unable to reclaim buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBufPtr != NULL.
++ * pulBytes != NULL.
++ * pdwArg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm,
++ OUT u8 **pBufPtr, u32 *pulBytes,
++ u32 *pulBufSize, u32 *pdwArg);
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ * Parameters:
++ * hStrm: Stream handle returned by STRM_Open().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * STRM_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Select a ready stream.
++ * Parameters:
++ * aStrmTab: Array of stream handles returned from STRM_Open().
++ * nStrms: Number of stream handles in array.
++ * pMask: Location to store mask of ready streams on output.
++ * uTimeout: Timeout value (milliseconds).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ERANGE: nStrms out of range.
++
++ * DSP_EHANDLE: Invalid stream handle in array.
++ * DSP_ETIMEOUT: A timeout occurred before a stream became ready.
++ * DSP_EFAIL: Failure occurred, unable to select a stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * aStrmTab != NULL.
++ * nStrms > 0.
++ * pMask != NULL.
++ * Ensures:
++ * DSP_SOK: *pMask != 0 || uTimeout == 0.
++ * Error: *pMask == 0.
++ */
++ extern DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab,
++ u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout);
++
++/*
++ * ======== STRM_UnprepareBuffer ========
++ * Purpose:
++ * Unprepare a data buffer that was previously prepared for a stream
++ * with DSPStream_PrepareBuffer(), and that will no longer be used with
++ * the stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to unprepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_UnprepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++#endif /* STRM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strmdefs.h b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+new file mode 100644
+index 0000000..44d217a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+@@ -0,0 +1,57 @@
++/*
++ * strmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strmdefs.h ========
++ * Purpose:
++ * Global STRM constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2001 ag Added STRM_INFO..
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRMDEFS_
++#define STRMDEFS_
++
++#define STRM_MAXEVTNAMELEN 32
++
++ struct STRM_MGR;
++
++ struct STRM_OBJECT;
++
++ struct STRM_ATTR {
++ HANDLE hUserEvent;
++ char *pstrEventName;
++ void *pVirtBase; /* Process virtual base address of
++ * mapped SM */
++ u32 ulVirtSize; /* Size of virtual space in bytes */
++ struct DSP_STREAMATTRIN *pStreamAttrIn;
++ } ;
++
++ struct STRM_INFO {
++ enum DSP_STRMMODE lMode; /* transport mode of
++ * stream(DMA, ZEROCOPY..) */
++ u32 uSegment; /* Segment strm allocs from. 0 is local mem */
++ void *pVirtBase; /* " " Stream'process virt base */
++ struct DSP_STREAMINFO *pUser; /* User's stream information
++ * returned */
++ } ;
++
++#endif /* STRMDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/sync.h b/arch/arm/plat-omap/include/dspbridge/sync.h
+new file mode 100644
+index 0000000..fa3ff8d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/sync.h
+@@ -0,0 +1,340 @@
++/*
++ * sync.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.h ========
++ * Purpose:
++ * Provide synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_PostMessage
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 01-Dec-1999 ag: Added #define SYNC_MAXNAMELENGTH.
++ *! 04-Nov-1999 kc: Added critical section functions and objects to SYNC.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 24-Sep-1999 kc: Added WinCE notes.
++ *! 20-Oct-1997 gp: Removed unused SYNC_ critical section and must complete fxns
++ *! Added SYNC_HOBJECT, SYNC_ATTRS, and object validation, and
++ *! merged SYNC_DestroyEvent into SYNC_CloseEvent, and merged
++ *! SYNC_CreateEvent into SYNC_OpenEvent.
++ *! 07-Oct-1997 gp: Added SYNC_Create/DestroyEvent (for NT testing).
++ *! 06-Oct-1997 gp: Added SYNC_OpenEvent.
++ *! 03-Jun-1997 gp: Added SYNC_{Begin|End}CritSection() functions.
++ *! 03-Jan-1997 gp: Added SYNC_INFINITE define.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++#ifndef _SYNC_H
++#define _SYNC_H
++
++#define SIGNATURECS 0x53435953 /* "SYCS" (in reverse) */
++#define SIGNATUREDPCCS 0x53445953 /* "SYDS" (in reverse) */
++
++/* Special timeout value indicating an infinite wait: */
++#define SYNC_INFINITE 0xffffffff
++
++/* Maximum string length of a named event */
++#define SYNC_MAXNAMELENGTH 32
++
++/* Generic SYNC object: */
++ struct SYNC_OBJECT;
++
++/* Generic SYNC CS object: */
++struct SYNC_CSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ struct semaphore sem;
++} ;
++
++/* SYNC object attributes: */
++ struct SYNC_ATTRS {
++ HANDLE hUserEvent; /* Platform's User Mode synch. object. */
++ HANDLE hKernelEvent; /* Platform's Kernel Mode sync. object. */
++ u32 dwReserved1; /* For future expansion. */
++ u32 dwReserved2; /* For future expansion. */
++ } ;
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close this event handle, freeing resources allocated in SYNC_OpenEvent
++ * if necessary.
++ * Parameters:
++ * hEvent: Handle to a synchronization event, created/opened in
++ * SYNC_OpenEvent.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to close event handle.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Any subsequent usage of hEvent would be invalid.
++ */
++ extern DSP_STATUS SYNC_CloseEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_DeleteCS ========
++ * Purpose:
++ * Delete a critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_DeleteCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_EnterCS ========
++ * Purpose:
++ * Enter the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_EnterCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SYNC_Exit(void);
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initializes private state of SYNC module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * SYNC initialized.
++ */
++ extern bool SYNC_Init(void);
++
++/*
++ * ======== SYNC_InitializeCS ========
++ * Purpose:
++ * Initialize the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj);
++
++/*
++ * ======== SYNC_InitializeDPCCS ========
++ * Purpose:
++ * Initialize the critical section between process context and DPC.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT
++ **phCSObj);
++
++/*
++ * ======== SYNC_LeaveCS ========
++ * Purpose:
++ * Leave the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_LeaveCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Create/open and initialize an event object for thread synchronization,
++ * which is initially in the non-signalled state.
++ * Parameters:
++ * phEvent: Pointer to location to receive the event object handle.
++ * pAttrs: Pointer to SYNC_ATTRS object containing initial SYNC
++ * SYNC_OBJECT attributes. If this pointer is NULL, then
++ * SYNC_OpenEvent will create and manage an OS specific
++ * syncronization object.
++ * pAttrs->hUserEvent: Platform's User Mode synchronization object.
++ *
++ * The behaviour of the SYNC methods depend on the value of
++ * the hUserEvent attr:
++ *
++ * 1. (hUserEvent == NULL):
++ * A user mode event is created.
++ * 2. (hUserEvent != NULL):
++ * A user mode event is supplied by the caller of SYNC_OpenEvent().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to create user mode event.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EINVALIDARG SYNC_ATTRS values are invalid.
++ * Requires:
++ * - SYNC initialized.
++ * - phEvent != NULL.
++ * Ensures:
++ * If function succeeded, pEvent->hEvent must be a valid event handle.
++ */
++ extern DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS
++ *pAttrs);
++
++/*
++ * ========= SYNC_PostMessage ========
++ * Purpose:
++ * To post a windows message
++ * Parameters:
++ * hWindow: Handle to the window
++ * uMsg: Message to be posted
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Post message failed
++ * DSP_EHANDLE: Invalid Window handle
++ * Requires:
++ * SYNC initialized
++ * Ensures
++ */
++ extern DSP_STATUS SYNC_PostMessage(IN HANDLE hWindow, IN u32 uMsg);
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset a syncronization event object state to non-signalled.
++ * Parameters:
++ * hEvent: Handle to a sync event.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to reset event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_ResetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Signal the event. Will unblock one waiting thread.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to signal event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_SetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * the object's state is nonsignaled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * DSP_EHANDLE: Invalid handle.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired while waiting for event to be signalled.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnEvent(IN struct SYNC_OBJECT *hEvent,
++ IN u32 dwTimeOut);
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ * Note: dwTimeOut must be SYNC_INFINITE to signal infinite wait.
++ * Parameters:
++ * hSyncEvents: Array of handles to event objects.
++ * uCount: Number of event handles.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * no event is signalled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * puIndex: Location to store index of event that was signalled.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired before event was signalled.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnMultipleEvents(IN struct SYNC_OBJECT
++ **hSyncEvents,
++ IN u32 uCount,
++ IN u32 dwTimeout,
++ OUT u32 *puIndex);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/util.h b/arch/arm/plat-omap/include/dspbridge/util.h
+new file mode 100644
+index 0000000..e6815ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/util.h
+@@ -0,0 +1,122 @@
++/*
++ * util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== util.h ========
++ * Purpose:
++ * Provide general purpose utility functions.
++ *
++ * Public Functions:
++ * UTIL_CDTestDll
++ * UTIL_CmdLineToArgs
++ * UTIL_Exit
++ * UTIL_GetSysInfo
++ * UTIL_Init
++ */
++
++#ifndef _UTIL_H
++#define _UTIL_H
++
++#include <linux/delay.h>
++#include <linux/sched.h>
++
++#include <dspbridge/utildefs.h>
++
++/*
++ * ======== UTIL_CDTestDll ========
++ * Purpose:
++ * Provides test entry point in class driver context.
++ * Parameters:
++ * cArgc: test module command line input count.
++ * ppArgv: test module command line args.
++ * Returns:
++ * 0 if successful, a negative value otherwise.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern u32 UTIL_CDTestDll(IN s32 cArgc, IN char **ppArgv);
++
++/*
++ * ======== UTIL_CmdLineToArgs ========
++ * Purpose:
++ * This function re-creates C-style cmd line argc & argv from WinMain()
++ * cmd line args.
++ * Parameters:
++ * s8 *pszProgName - The name of the program currently being executed.
++ * s8 *argv[] - The argument vector.
++ * s8 *pCmdLine - The pointer to the command line.
++ * bool fHasProgName - Indicats whether a program name is supplied.
++ * Returns:
++ * Returns the number of arguments found.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern s32 UTIL_CmdLineToArgs(IN char *pszProgName,
++ IN char *argv[UTIL_MAXARGVS],
++ IN char *pCmdLine, IN bool fHasProgName);
++
++/*
++ * ======== UTIL_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern inline void UTIL_Exit(void)
++ {
++ }
++/*
++ * ======== UTIL_GetSysInfo ========
++ * Purpose:
++ * This function return platform specific system information.
++ *
++ * Parameters:
++ * pSysInfo - address to store the system information.
++ * Returns:
++ * DSP_SOK
++ * S_FAIL
++ * Requires:
++ * UTIL initialized.
++ * pSysInfo != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS UTIL_GetSysInfo(OUT struct UTIL_SYSINFO *pSysInfo);
++
++/*
++ * ======== UTIL_Init ========
++ * Purpose:
++ * Initializes private state of UTIL module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * UTIL initialized.
++ */
++ extern inline bool UTIL_Init(void)
++ {
++ return true;
++ }
++
++#endif /* _UTIL_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/utildefs.h b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+new file mode 100644
+index 0000000..bd53a5a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+@@ -0,0 +1,51 @@
++/*
++ * utildefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== utildefs.h ========
++ * Purpose:
++ * Global UTIL constants and types, shared between WCD and DSPSYS.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* entries from UTIL_HOSTCONFIG.
++ *! 12-Aug-2000 ag Added UTIL_SYSINFO typedef.
++ *! 08-Oct-1999 rr Adopted for WinCE where test fxns will be added in util.h
++ *! 26-Dec-1996 cr Created.
++ */
++
++#ifndef UTILDEFS_
++#define UTILDEFS_
++
++/* constants taken from configmg.h */
++#define UTIL_MAXMEMREGS 9
++#define UTIL_MAXIOPORTS 20
++#define UTIL_MAXIRQS 7
++#define UTIL_MAXDMACHNLS 7
++
++/* misc. constants */
++#define UTIL_MAXARGVS 10
++
++/* Platform specific important info */
++ struct UTIL_SYSINFO {
++ /* Granularity of page protection; usually 1k or 4k */
++ u32 dwPageSize;
++ u32 dwAllocationGranularity; /* VM granularity, usually 64K */
++ u32 dwNumberOfProcessors; /* Used as sanity check */
++ } ;
++
++#endif /* UTILDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/uuidutil.h b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+new file mode 100644
+index 0000000..af4aaec
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+@@ -0,0 +1,74 @@
++/*
++ * uuidutil.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.h ========
++ * Description:
++ * This file contains the specification of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 09-Nov-2000 kc: Modified description of UUID utility functions.
++ *! 29-Sep-2000 kc: Appended "UUID_" prefix to UUID helper functions.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++#ifndef UUIDUTIL_
++#define UUIDUTIL_
++
++#define MAXUUIDLEN 37
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a DSP_UUID to an ANSI string.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID object.
++ * pszUuid: Pointer to a buffer to receive a NULL-terminated UUID
++ * string.
++ * size: Maximum size of the pszUuid string.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Lenghth of pszUuid is less than MAXUUIDLEN.
++ * Details:
++ * UUID string limit currently set at MAXUUIDLEN.
++ */
++ void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ s32 size);
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts an ANSI string to a DSP_UUID.
++ * Parameters:
++ * pszUuid: Pointer to a string that represents a DSP_UUID object.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Details:
++ * We assume the string representation of a UUID has the following format:
++ * "12345678_1234_1234_1234_123456789abc".
++ */
++ extern void UUID_UuidFromString(IN char *pszUuid,
++ OUT struct DSP_UUID *pUuid);
++
++#endif /* UUIDUTIL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcd.h b/arch/arm/plat-omap/include/dspbridge/wcd.h
+new file mode 100644
+index 0000000..5a7d47a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcd.h
+@@ -0,0 +1,61 @@
++/*
++ * wcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcd.h ========
++ * Description:
++ * 'Bridge class driver library functions, object definitions, and
++ * return error/status codes. To be included by 'Bridge mini drivers.
++ *
++ * Public Functions:
++ * See mem.h and dbg.h.
++ *
++ * Notes:
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD. WMD's must not call module Init/Exit
++ * functions.
++ *
++ * To ensure WMD binary compatibility across different platforms,
++ * for the same processor, a WMD must restrict its usage of system
++ * services to those exported by the 'Bridge class library.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jun-2000 jeh Added dev.h
++ *! 01-Nov-1999 ag: #WINCE# WCD_MAJOR_VERSION=8 & WCD_MINOR_VERSION=0 to match
++ *! dll stamps.
++ *! 0.80 - 0.89 Alpha, 0.90 - 0.99 Beta, 1.00 - 1.10 FCS.
++ *! 17-Sep-1997 gp: Changed size of CFG_HOSTRES structure; and ISR_Install API;
++ *! Changed WCD_MINOR_VERSION 3 -> 4.
++ *! 15-Sep-1997 gp: Moved WCD_(Un)registerMinidriver to drv.
++ *! 25-Jul-1997 cr: Added WCD_UnregisterMinidriver.
++ *! 22-Jul-1997 cr: Added WCD_RegisterMinidriver, WCD_MINOR_VERSION 2 -> 3.
++ *! 12-Nov-1996 gp: Defined port io macros.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 16-Jul-1996 gp: Added CHNL fxns; updated WCD lib version to 2.
++ *! 10-May-1996 gp: Separated WMD def.s' into wmd.h.
++ *! 03-May-1996 gp: Created.
++ */
++
++#ifndef WCD_
++#define WCD_
++
++/* This WCD Library Version: */
++#define WCD_MAJOR_VERSION (u32)8 /* .8x - Alpha, .9x - Beta, 1.x FCS */
++#define WCD_MINOR_VERSION (u32)0
++
++#endif /* WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcdioctl.h b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+new file mode 100644
+index 0000000..04b13ab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+@@ -0,0 +1,519 @@
++/*
++ * wcdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcdioctl.h ========
++ * Purpose:
++ * Contains structures and commands that are used for interaction
++ * between the DDSP API and class driver.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping structs & offsets
++ *! 15-Oct-2002 kc Updated definitions for private PERF module.
++ *! 16-Aug-2002 map Added ARGS_MGR_REGISTEROBJECT & ARGS_MGR_UNREGISTEROBJECT
++ *! Added CMD_MGR_REGISTEROBJECT_OFFSET &
++ *! CMD_MGR_UNREGISTEROBJECT_OFFSET
++ *! 15-Jan-2002 ag Added actaul bufSize to ARGS_STRM_[RECLAIM][ISSUE].
++ *! 15-Nov-2001 ag change to STRMINFO in ARGS_STRM_GETINFO.
++ *! 11-Sep-2001 ag ARGS_CMM_GETHANDLE defn uses DSP_HPROCESSOR.
++ *! 23-Apr-2001 jeh Added pStatus to NODE_TERMINATE args.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added CMD_MGR_GETPERF_DATA_OFFSET for acquiring PERF stats.
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GETMESSAGE, NODE_PUTMESSAGE args.
++ *! Removed NODE_GETMESSAGESTRM args.
++ *! 11-Oct-2000 ag: Added SM mgr(CMM) args.
++ *! 27-Sep-2000 jeh Removed struct DSP_BUFFERATTR param from
++ *! ARGS_STRM_ALLOCATEBUFFER.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 07-Sep-2000 jeh Changed HANDLE to DSP_HNOTIFICATION in RegisterNotify args.
++ *! Added DSP_STRMATTR to DSPNode_Connect args.
++ *! 04-Aug-2000 rr: MEM and UTIL added to RM.
++ *! 27-Jul-2000 rr: NODE, MGR,STRM and PROC added
++ *! 27-Jun-2000 rr: Modifed to Use either PM or DSP/BIOS Bridge
++ *! IFDEF to build for PM or DSP/BIOS Bridge
++ *! 28-Jan-2000 rr: NT_CMD_FROM_OFFSET moved out to dsptrap.h
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-2000 sg: In ARGS_CHNL_GETMODE changed mode to be u32 to be
++ *! consistent with chnldefs.h.
++ *! 11-Jan-2000 rr: CMD_CFG_GETCDVERSION_OFFSET added.
++ *! 12-Nov-1999 rr: CMD_BRD_MONITOR_OFFSET added
++ *! 09-Nov-1999 kc: Added MEMRY and enabled CMD_BRD_IOCTL_OFFSET.
++ *! 05-Nov-1999 ag: Added CHNL.
++ *! 02-Nov-1999 kc: Removed field from ARGS_UTIL_TESTDLL.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 08-Oct-1999 rr: Util control offsets added.
++ *! 13-Sep-1999 kc: Added ARGS_UTIL_TESTDLL for PM test infrastructure.
++ *! 19-Aug-1999 rr: Created from WSX. Minimal Implementaion of BRD_Start and BRD
++ *! and BRD_Stop. IOCTL Offsets and CTRL Code.
++ */
++
++#ifndef WCDIOCTL_
++#define WCDIOCTL_
++
++#include <dspbridge/mem.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/dbdcd.h>
++
++union Trapped_Args {
++
++ /* MGR Module */
++ struct {
++ u32 uNode;
++ struct DSP_NDBPROPS __user *pNDBProps;
++ u32 uNDBPropsSize;
++ u32 __user *puNumNodes;
++ } ARGS_MGR_ENUMNODE_INFO;
++
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORINFO __user *pProcessorInfo;
++ u32 uProcessorInfoSize;
++ u32 __user *puNumProcs;
++ } ARGS_MGR_ENUMPROC_INFO;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ char *pszPathName;
++ } ARGS_MGR_REGISTEROBJECT;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ } ARGS_MGR_UNREGISTEROBJECT;
++
++ struct {
++ struct DSP_NOTIFICATION __user*__user *aNotifications;
++ u32 uCount;
++ u32 __user *puIndex;
++ u32 uTimeout;
++ } ARGS_MGR_WAIT;
++
++ /* PROC Module */
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORATTRIN __user *pAttrIn;
++ DSP_HPROCESSOR __user *phProcessor;
++ } ARGS_PROC_ATTACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 dwCmd;
++ struct DSP_CBDATA __user *pArgs;
++ } ARGS_PROC_CTRL;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_DETACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ DSP_HNODE __user *aNodeTab;
++ u32 uNodeTabSize;
++ u32 __user *puNumNodes;
++ u32 __user *puAllocated;
++ } ARGS_PROC_ENUMNODE_INFO;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uResourceType;
++ struct DSP_RESOURCEINFO *pResourceInfo;
++ u32 uResourceInfoSize;
++ } ARGS_PROC_ENUMRESOURCES;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_PROCESSORSTATE __user *pProcStatus;
++ u32 uStateInfoSize;
++ } ARGS_PROC_GETSTATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u8 __user *pBuf;
++
++ #ifndef RES_CLEANUP_DISABLE
++ u8 __user *pSize;
++ #endif
++ u32 uMaxSize;
++ } ARGS_PROC_GETTRACE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ s32 iArgc;
++ char __user*__user *aArgv;
++ char *__user *aEnvp;
++ } ARGS_PROC_LOAD;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_PROC_REGISTER_NOTIFY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_START;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *__user *ppRsvAddr;
++ } ARGS_PROC_RSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pRsvAddr;
++ } ARGS_PROC_UNRSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ void *pReqAddr;
++ void *__user *ppMapAddr;
++ u32 ulMapAttr;
++ } ARGS_PROC_MAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pMapAddr;
++ } ARGS_PROC_UNMAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ u32 ulFlags;
++ } ARGS_PROC_FLUSHMEMORY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_STOP;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ } ARGS_PROC_INVALIDATEMEMORY;
++
++
++ /* NODE Module */
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_CBDATA __user *pArgs;
++ struct DSP_NODEATTRIN __user *pAttrIn;
++ DSP_HNODE __user *phNode;
++ } ARGS_NODE_ALLOCATE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uSize;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *__user *pBuffer;
++ } ARGS_NODE_ALLOCMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ s32 iPriority;
++ } ARGS_NODE_CHANGEPRIORITY;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uStream;
++ DSP_HNODE hOtherNode;
++ u32 uOtherStream;
++ struct DSP_STRMATTR __user *pAttrs;
++ struct DSP_CBDATA __user *pConnParam;
++ } ARGS_NODE_CONNECT;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_CREATE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_DELETE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *pBuffer;
++ } ARGS_NODE_FREEMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_NODEATTR __user *pAttr;
++ u32 uAttrSize;
++ } ARGS_NODE_GETATTR;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_GETMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_PAUSE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_PUTMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_NODE_REGISTERNOTIFY;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_RUN;
++
++ struct {
++ DSP_HNODE hNode;
++ DSP_STATUS __user *pStatus;
++ } ARGS_NODE_TERMINATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_NDBPROPS __user *pNodeProps;
++ } ARGS_NODE_GETUUIDPROPS;
++
++ /* STRM module */
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uSize;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_ALLOCATEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ } ARGS_STRM_CLOSE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_FREEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ HANDLE *phEvent;
++ } ARGS_STRM_GETEVENTHANDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ struct STRM_INFO __user *pStreamInfo;
++ u32 uStreamInfoSize;
++ } ARGS_STRM_GETINFO;
++
++ struct {
++ DSP_HSTREAM hStream;
++ bool bFlush;
++ } ARGS_STRM_IDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *pBuffer;
++ u32 dwBytes;
++ u32 dwBufSize;
++ u32 dwArg;
++ } ARGS_STRM_ISSUE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uDirection;
++ u32 uIndex;
++ struct STRM_ATTR __user *pAttrIn;
++ DSP_HSTREAM __user *phStream;
++ } ARGS_STRM_OPEN;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *pBufPtr;
++ u32 __user *pBytes;
++ u32 __user *pBufSize;
++ u32 __user *pdwArg;
++ } ARGS_STRM_RECLAIM;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_STRM_REGISTERNOTIFY;
++
++ struct {
++ DSP_HSTREAM __user *aStreamTab;
++ u32 nStreams;
++ u32 __user *pMask;
++ u32 uTimeout;
++ } ARGS_STRM_SELECT;
++
++ /* CMM Module */
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ u32 uSize;
++ struct CMM_ATTRS *pAttrs;
++ OUT void **ppBufVA;
++ } ARGS_CMM_ALLOCBUF;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ void *pBufPA;
++ u32 ulSegId;
++ } ARGS_CMM_FREEBUF;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct CMM_OBJECT *__user *phCmmMgr;
++ } ARGS_CMM_GETHANDLE;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ struct CMM_INFO __user *pCmmInfo;
++ } ARGS_CMM_GETINFO;
++
++ /* MEM Module */
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_ALLOC;
++
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_CALLOC;
++
++ struct {
++ void *pMem;
++ } ARGS_MEM_FREE;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ void *pLockedBuffer;
++ } ARGS_MEM_PAGELOCK;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ } ARGS_MEM_PAGEUNLOCK;
++
++ /* UTIL module */
++ struct {
++ s32 cArgc;
++ char **ppArgv;
++ } ARGS_UTIL_TESTDLL;
++} ;
++
++#define CMD_BASE 1
++
++/* MGR module offsets */
++#define CMD_MGR_BASE_OFFSET CMD_BASE
++#define CMD_MGR_ENUMNODE_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 0)
++#define CMD_MGR_ENUMPROC_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 1)
++#define CMD_MGR_REGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 2)
++#define CMD_MGR_UNREGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 3)
++#define CMD_MGR_WAIT_OFFSET (CMD_MGR_BASE_OFFSET + 4)
++
++#ifndef RES_CLEANUP_DISABLE
++#define CMD_MGR_RESOUCES_OFFSET (CMD_MGR_BASE_OFFSET + 5)
++#define CMD_MGR_END_OFFSET CMD_MGR_RESOUCES_OFFSET
++#else
++#define CMD_MGR_END_OFFSET CMD_MGR_WAIT_OFFSET
++#endif
++
++#define CMD_PROC_BASE_OFFSET (CMD_MGR_END_OFFSET + 1)
++#define CMD_PROC_ATTACH_OFFSET (CMD_PROC_BASE_OFFSET + 0)
++#define CMD_PROC_CTRL_OFFSET (CMD_PROC_BASE_OFFSET + 1)
++#define CMD_PROC_DETACH_OFFSET (CMD_PROC_BASE_OFFSET + 2)
++#define CMD_PROC_ENUMNODE_OFFSET (CMD_PROC_BASE_OFFSET + 3)
++#define CMD_PROC_ENUMRESOURCES_OFFSET (CMD_PROC_BASE_OFFSET + 4)
++#define CMD_PROC_GETSTATE_OFFSET (CMD_PROC_BASE_OFFSET + 5)
++#define CMD_PROC_GETTRACE_OFFSET (CMD_PROC_BASE_OFFSET + 6)
++#define CMD_PROC_LOAD_OFFSET (CMD_PROC_BASE_OFFSET + 7)
++#define CMD_PROC_REGISTERNOTIFY_OFFSET (CMD_PROC_BASE_OFFSET + 8)
++#define CMD_PROC_START_OFFSET (CMD_PROC_BASE_OFFSET + 9)
++#define CMD_PROC_RSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 10)
++#define CMD_PROC_UNRSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 11)
++#define CMD_PROC_MAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 12)
++#define CMD_PROC_UNMAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 13)
++#define CMD_PROC_FLUSHMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 14)
++#define CMD_PROC_STOP_OFFSET (CMD_PROC_BASE_OFFSET + 15)
++#define CMD_PROC_INVALIDATEMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 16)
++#define CMD_PROC_END_OFFSET CMD_PROC_INVALIDATEMEMORY_OFFSET
++
++
++#define CMD_NODE_BASE_OFFSET (CMD_PROC_END_OFFSET + 1)
++#define CMD_NODE_ALLOCATE_OFFSET (CMD_NODE_BASE_OFFSET + 0)
++#define CMD_NODE_ALLOCMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 1)
++#define CMD_NODE_CHANGEPRIORITY_OFFSET (CMD_NODE_BASE_OFFSET + 2)
++#define CMD_NODE_CONNECT_OFFSET (CMD_NODE_BASE_OFFSET + 3)
++#define CMD_NODE_CREATE_OFFSET (CMD_NODE_BASE_OFFSET + 4)
++#define CMD_NODE_DELETE_OFFSET (CMD_NODE_BASE_OFFSET + 5)
++#define CMD_NODE_FREEMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 6)
++#define CMD_NODE_GETATTR_OFFSET (CMD_NODE_BASE_OFFSET + 7)
++#define CMD_NODE_GETMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 8)
++#define CMD_NODE_PAUSE_OFFSET (CMD_NODE_BASE_OFFSET + 9)
++#define CMD_NODE_PUTMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 10)
++#define CMD_NODE_REGISTERNOTIFY_OFFSET (CMD_NODE_BASE_OFFSET + 11)
++#define CMD_NODE_RUN_OFFSET (CMD_NODE_BASE_OFFSET + 12)
++#define CMD_NODE_TERMINATE_OFFSET (CMD_NODE_BASE_OFFSET + 13)
++#define CMD_NODE_GETUUIDPROPS_OFFSET (CMD_NODE_BASE_OFFSET + 14)
++#define CMD_NODE_END_OFFSET CMD_NODE_GETUUIDPROPS_OFFSET
++
++#define CMD_STRM_BASE_OFFSET (CMD_NODE_END_OFFSET + 1)
++#define CMD_STRM_ALLOCATEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 0)
++#define CMD_STRM_CLOSE_OFFSET (CMD_STRM_BASE_OFFSET + 1)
++#define CMD_STRM_FREEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 2)
++#define CMD_STRM_GETEVENTHANDLE_OFFSET (CMD_STRM_BASE_OFFSET + 3)
++#define CMD_STRM_GETINFO_OFFSET (CMD_STRM_BASE_OFFSET + 4)
++#define CMD_STRM_IDLE_OFFSET (CMD_STRM_BASE_OFFSET + 5)
++#define CMD_STRM_ISSUE_OFFSET (CMD_STRM_BASE_OFFSET + 6)
++#define CMD_STRM_OPEN_OFFSET (CMD_STRM_BASE_OFFSET + 7)
++#define CMD_STRM_RECLAIM_OFFSET (CMD_STRM_BASE_OFFSET + 8)
++#define CMD_STRM_REGISTERNOTIFY_OFFSET (CMD_STRM_BASE_OFFSET + 9)
++#define CMD_STRM_SELECT_OFFSET (CMD_STRM_BASE_OFFSET + 10)
++#define CMD_STRM_END_OFFSET CMD_STRM_SELECT_OFFSET
++
++/* Communication Memory Manager (UCMM) */
++#define CMD_CMM_BASE_OFFSET (CMD_STRM_END_OFFSET + 1)
++#define CMD_CMM_ALLOCBUF_OFFSET (CMD_CMM_BASE_OFFSET + 0)
++#define CMD_CMM_FREEBUF_OFFSET (CMD_CMM_BASE_OFFSET + 1)
++#define CMD_CMM_GETHANDLE_OFFSET (CMD_CMM_BASE_OFFSET + 2)
++#define CMD_CMM_GETINFO_OFFSET (CMD_CMM_BASE_OFFSET + 3)
++#define CMD_CMM_END_OFFSET CMD_CMM_GETINFO_OFFSET
++
++#define CMD_BASE_END_OFFSET CMD_CMM_END_OFFSET
++#endif /* WCDIOCTL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmd.h b/arch/arm/plat-omap/include/dspbridge/wmd.h
+new file mode 100644
+index 0000000..f584038
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmd.h
+@@ -0,0 +1,1193 @@
++/*
++ * wmd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmd.h ========
++ * Purpose:
++ * 'Bridge mini driver entry point and interface function declarations.
++ *
++ * Public Functions:
++ * WMD_DRV_Entry
++ *
++ * Notes:
++ * The 'Bridge class driver obtains it's function interface to
++ * the 'Bridge mini driver via a call to WMD_DRV_Entry().
++ *
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD.
++ *
++ * WMD function DBC Requires and Ensures are also made by the WCD on
++ * behalf of the WMD, to simplify the WMD code.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs - WMD_BRD_MemMap/UnMap
++ *! 01-Mar-2004 vp Added filename argument to WMD_DRV_Entry function.
++ *! 29-Aug-2002 map Added WMD_BRD_MemWrite()
++ *! 26-Aug-2002 map Added WMD_BRD_MemCopy()
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 05-Nov-2001 kc: Added error handling DEH functions.
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify().
++ *! 17-Nov-2000 jeh Added WMD_MSG and WMD_IO definitions.
++ *! 01-Nov-2000 jeh Added more error codes to WMD_CHNL_RegisterNotify().
++ *! 13-Oct-2000 jeh Added dwArg to WMD_CHNL_AddIOReq(), added WMD_CHNL_IDLE
++ *! and WMD_CHNL_RegisterNotify for DSPStream support.
++ *! 17-Jan-2000 rr: WMD_BRD_SETSTATE Added.
++ *! 30-Jul-1997 gp: Split wmd IOCTL space into reserved and private.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 18-Oct-1996 gp: Added WMD_E_HARDWARE return code from WMD_BRD_Monitor.
++ *! 09-Sep-1996 gp: Subtly altered the semantics of WMD_CHNL_GetInfo().
++ *! 02-Aug-1996 gp: Ensured on BRD_Start that interrupts to the PC are enabled.
++ *! 11-Jul-1996 gp: Added CHNL interface. Note stronger DBC_Require conditions.
++ *! 29-May-1996 gp: Removed WCD_ prefix from functions imported from WCD.LIB.
++ *! 29-May-1996 gp: Made OUT param first in WMD_DEV_Create().
++ *! 09-May-1996 gp: Created.
++ */
++
++#ifndef WMD_
++#define WMD_
++
++#include <dspbridge/brddefs.h>
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/chnlpriv.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * Any IOCTLS at or above this value are reserved for standard WMD
++ * interfaces.
++ */
++#define WMD_RESERVEDIOCTLBASE 0x8000
++
++/* Handle to mini-driver's private device context. */
++ struct WMD_DEV_CONTEXT;
++
++/*---------------------------------------------------------------------------*/
++/* 'Bridge MINI DRIVER FUNCTION TYPES */
++/*---------------------------------------------------------------------------*/
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * Purpose:
++ * Bring the board to the BRD_IDLE (monitor) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_HARDWARE: A test of hardware assumptions/integrity failed.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_IDLE state;
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_MONITOR) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_SETSTATE ========
++ * Purpose:
++ * Sets the Mini driver state
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulBrdState: Board state
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * ulBrdState <= BRD_LASTSTATE.
++ * Ensures:
++ * ulBrdState <= BRD_LASTSTATE.
++ * Update the Board state to the specified state.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_SETSTATE) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulBrdState);
++
++/*
++ * ======== WMD_BRD_Start ========
++ * Purpose:
++ * Bring board to the BRD_RUNNING (start) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * dwDSPAddr: DSP address at which to start execution.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Board is in monitor (BRD_IDLE) state.
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_START) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 dwDSPAddr);
++
++/*
++ * ======== WMD_BRD_MemCopy ========
++ * Purpose:
++ * Copy memory from one DSP address to another
++ * Parameters:
++ * pDevContext: Pointer to context handle
++ * ulDspDestAddr: DSP address to copy to
++ * ulDspSrcAddr: DSP address to copy from
++ * ulNumBytes: Number of bytes to copy
++ * ulMemType: What section of memory to copy to
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * pDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMCOPY) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulDspDestAddr,
++ u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++/*
++ * ======== WMD_BRD_MemWrite ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space. Unlike WMD_BRD_Write, this API does reset the DSP
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMWRITE) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * Purpose:
++ * Map a MPU memory region to a DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulMpuAddr: MPU memory region start address.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to map.
++ * mapAttrs: Mapping attributes (e.g. endianness).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulMpuAddr,
++ u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttrs);
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Purpose:
++ * UnMap an MPU memory region from DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to unmap.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMUNMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulVirtAddr,
++ u32 ulNumBytes);
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * Purpose:
++ * Bring board to the BRD_STOPPED state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_STOPPED (stop) state;
++ * Interrupts to the PC are disabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_STOP) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Purpose:
++ * Report the current state of the board.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * pdwState: Ptr to BRD status variable.
++ * Returns:
++ * DSP_SOK:
++ * Requires:
++ * pdwState != NULL;
++ * hDevContext != NULL
++ * Ensures:
++ * *pdwState is one of {BRD_STOPPED, BRD_IDLE, BRD_RUNNING, BRD_UNKNOWN};
++ */
++ typedef DSP_STATUS(*
++ WMD_BRD_STATUS) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS * pdwState);
++
++/*
++ * ======== WMD_BRD_Read ========
++ * Purpose:
++ * Read a block of DSP memory, from a given memory space, into a host
++ * buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP from which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ * Will not write more than ulNumBytes bytes into pHostBuf.
++ */
++typedef DSP_STATUS(*WMD_BRD_READ) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_BRD_WRITE)(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * pMgrAttrs->dwSMBase: Base physical address of shared memory, if any.
++ * pMgrAttrs->uSMLength: Bytes of shared memory block.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug ISR for given IRQ.
++ * CHNL_E_NOMEMMAP: Couldn't map physical address to a virtual one.
++ * Requires:
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL
++ * pMgrAttrs field are all valid:
++ * 0 < cChannels <= CHNL_MAXCHANNELS.
++ * bIRQ <= 15.
++ * uWordSize > 0.
++ * IsValidHandle(hDevObject)
++ * No channel manager exists for this board.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CREATE)(OUT struct CHNL_MGR
++ **phChnlMgr,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct
++ CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel. Closes each open channel.
++ * CHNL_Create may subsequently be called for the same device.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_DESTROY) (struct CHNL_MGR
++ *hChnlMgr);
++/*
++ * ======== WMD_DEH_Notify ========
++ * Purpose:
++ * When notified of DSP error, take appropriate action.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * ulEventMask: Indicate the type of exception
++ * dwErrInfo: Error information
++ * Returns:
++ *
++ * Requires:
++ * hDehMgr != NULL;
++ * ulEventMask with a valid exception
++ * Ensures:
++ */
++ typedef void (*WMD_DEH_NOTIFY)(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Purpose:
++ * Open a new half-duplex channel to the DSP board.
++ * Parameters:
++ * phChnl: Location to store a channel object handle.
++ * hChnlMgr: Handle to channel manager, as returned by CHNL_GetMgr().
++ * uMode: One of {CHNL_MODETODSP, CHNL_MODEFROMDSP} specifies
++ * direction of data transfer.
++ * uChnlId: If CHNL_PICKFREE is specified, the channel manager will
++ * select a free channel id (default);
++ * otherwise this field specifies the id of the channel.
++ * pAttrs: Channel attributes. Attribute fields are as follows:
++ * pAttrs->uIOReqs: Specifies the maximum number of I/O requests which can
++ * be pending at any given time. All request packets are
++ * preallocated when the channel is opened.
++ * pAttrs->hEvent: This field allows the user to supply an auto reset
++ * event object for channel I/O completion notifications.
++ * It is the responsibility of the user to destroy this
++ * object AFTER closing the channel.
++ * This channel event object can be retrieved using
++ * CHNL_GetEventHandle().
++ * pAttrs->hReserved: The kernel mode handle of this event object.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr is invalid.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EINVALIDARG: Invalid number of IOReqs.
++ * CHNL_E_OUTOFSTREAMS: No free channels available.
++ * CHNL_E_BADCHANID: Channel ID is out of range.
++ * CHNL_E_CHANBUSY: Channel is in use.
++ * CHNL_E_NOIORPS: No free IO request packets available for
++ * queuing.
++ * Requires:
++ * phChnl != NULL.
++ * pAttrs != NULL.
++ * pAttrs->hEvent is a valid event handle.
++ * pAttrs->hReserved is the kernel mode handle for pAttrs->hEvent.
++ * Ensures:
++ * DSP_SOK: *phChnl is a valid channel.
++ * else: *phChnl is set to NULL if (phChnl != NULL);
++ */
++ typedef DSP_STATUS(*WMD_CHNL_OPEN) (OUT struct CHNL_OBJECT
++ **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct
++ CHNL_ATTRS *pAttrs);
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Handle to a channel object.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: hChnl is no longer valid.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CLOSE) (struct CHNL_OBJECT *hChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Purpose:
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * pHostBuf: Host buffer address source.
++ * cBytes: Number of PC bytes to transfer. A zero value indicates
++ * that this buffer is the last in the output channel.
++ * A zero value is invalid for an input channel.
++ *! cBufSize: Actual buffer size in host bytes.
++ * dwDspAddr: DSP address for transfer. (Currently ignored).
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pHostBuf is invalid.
++ * CHNL_E_NOEOS: User cannot mark EOS on an input channel.
++ * CHNL_E_CANCELLED: I/O has been cancelled on this channel. No further
++ * I/O is allowed.
++ * CHNL_E_EOS: End of stream was already marked on a previous
++ * IORequest on this channel. No further I/O is expected.
++ * CHNL_E_BUFSIZE: Buffer submitted to this output channel is larger than
++ * the size of the physical shared memory output window.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: The buffer will be transferred if the channel is ready;
++ * otherwise, will be queued for transfer when the channel becomes
++ * ready. In any case, notifications of I/O completion are
++ * asynchronous.
++ * If cBytes is 0 for an output channel, subsequent CHNL_AddIOReq's
++ * on this channel will fail with error code CHNL_E_EOS. The
++ * corresponding IOC for this I/O request will have its status flag
++ * set to CHNL_IOCSTATEOS.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_ADDIOREQ) (struct CHNL_OBJECT
++ *hChnl,
++ void *pHostBuf,
++ u32 cBytes,
++ u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Purpose:
++ * Dequeue an I/O completion record, which contains information about the
++ * completed I/O request.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: A value of CHNL_IOCNOWAIT will simply dequeue the
++ * first available IOC.
++ * pIOC: On output, contains host buffer address, bytes
++ * transferred, and status of I/O completion.
++ * pIOC->status: See chnldefs.h.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pIOC is invalid.
++ * CHNL_E_NOIOC: CHNL_IOCNOWAIT was specified as the dwTimeOut parameter
++ * yet no I/O completions were queued.
++ * Requires:
++ * dwTimeOut == CHNL_IOCNOWAIT.
++ * Ensures:
++ * DSP_SOK: if there are any remaining IOC's queued before this call
++ * returns, the channel event object will be left in a signalled
++ * state.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETIOC) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Purpose:
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * Subsequent I/O requests to this channel will not be accepted.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CANCELIO) (struct CHNL_OBJECT
++ *hChnl);
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * Purpose:
++ * For an output stream (to the DSP), indicates if any IO requests are in
++ * the output request queue. For input streams (from the DSP), will
++ * cancel all pending IO requests.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: Timeout value for flush operation.
++ * Returns:
++ * DSP_SOK: Success;
++ * S_CHNLIOREQUEST: Returned if any IORequests are in the output queue.
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: No I/O requests will be pending on this channel.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_FLUSHIO) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ * Parameters:
++ * hChnl: Handle to a valid channel object, or NULL.
++ * pInfo: Location to store channel info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pInfo == NULL.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pInfo points to a filled in CHNL_INFO struct,
++ * if (pInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETINFO) (struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO
++ *pChnlInfo);
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Purpose:
++ * Retrieve information related to the channel manager.
++ * Parameters:
++ * hChnlMgr: Handle to a valid channel manager, or NULL.
++ * uChnlID: Channel ID.
++ * pMgrInfo: Location to store channel manager info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnlMgr.
++ * DSP_EPOINTER: pMgrInfo == NULL.
++ * CHNL_E_BADCHANID: Invalid channel ID.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pMgrInfo points to a filled in CHNL_MGRINFO
++ * struct, if (pMgrInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETMGRINFO) (struct CHNL_MGR
++ *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Purpose:
++ * Idle a channel. If this is an input channel, or if this is an output
++ * channel and fFlush is TRUE, all currently enqueued buffers will be
++ * dequeued (data discarded for output channel).
++ * If this is an output channel and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ *
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: If output channel and fFlush is FALSE, timeout value
++ * to wait for buffers to be output. (Not used for
++ * input channel).
++ * fFlush: If output channel and fFlush is TRUE, discard any
++ * currently buffered data. If FALSE, wait for currently
++ * buffered data to be output, or timeout, whichever
++ * occurs first. fFlush is ignored for input channel.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * CHNL_E_WAITTIMEOUT: Timeout occured before channel could be idled.
++ * Requires:
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_IDLE) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ bool fFlush);
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Purpose:
++ * Register for notification of events on a channel.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * uEventMask: Type of events to be notified about: IO completion
++ * (DSP_STREAMIOCOMPLETION) or end of stream
++ * (DSP_STREAMDONE).
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of a DSP_NOTIFICATION object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * Valid hChnl.
++ * hNotification != NULL.
++ * (uEventMask & ~(DSP_STREAMIOCOMPLETION | DSP_STREAMDONE)) == 0.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_REGISTERNOTIFY)
++ (struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Purpose:
++ * Complete creation of the device object for this board.
++ * Parameters:
++ * phDevContext: Ptr to location to store a WMD device context.
++ * hDevObject: Handle to a Device Object, created and managed by WCD.
++ * pConfig: Ptr to configuration parameters provided by the Windows
++ * Configuration Manager during device loading.
++ * pDspConfig: DSP resources, as specified in the registry key for this
++ * device.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for device context.
++ * WMD_E_BADCONFIG: One or more of the host or DSP configuration
++ * parameters did not satisfy hardware assumptions
++ * made by this WMD.
++ * Requires:
++ * phDevContext != NULL;
++ * hDevObject != NULL;
++ * pConfig != NULL;
++ * pDspConfig != NULL;
++ * Fields in pConfig and pDspConfig contain valid values.
++ * Ensures:
++ * DSP_SOK: All mini-driver specific DSP resource and other
++ * board context has been allocated.
++ * DSP_EMEMORY: WMD failed to allocate resources.
++ * Any acquired resources have been freed. The WCD will
++ * not call WMD_DEV_Destroy() if WMD_DEV_Create() fails.
++ * Details:
++ * Called during the CONFIGMG's Device_Init phase. Based on host and
++ * DSP configuration information, create a board context, a handle to
++ * which is passed into other WMD BRD and CHNL functions. The
++ * board context contains state information for the device. Since the
++ * addresses of all IN pointer parameters may be invalid when this
++ * function returns, they must not be stored into the device context
++ * structure.
++ */
++ typedef DSP_STATUS(*WMD_DEV_CREATE) (OUT struct WMD_DEV_CONTEXT
++ **phDevContext,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct CFG_HOSTRES
++ *pConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig);
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Purpose:
++ * Mini-driver specific interface.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwCmd: WMD defined command code.
++ * pArgs: Pointer to an arbitrary argument structure.
++ * Returns:
++ * DSP_SOK or DSP_EFAIL. Actual command error codes should be passed back
++ * in the pArgs structure, and are defined by the WMD implementor.
++ * Requires:
++ * All calls are currently assumed to be synchronous. There are no
++ * IOCTL completion routines provided.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_DEV_CTRL)(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwCmd,
++ IN OUT void *pArgs);
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Purpose:
++ * Deallocate WMD device extension structures and all other resources
++ * acquired by the mini-driver.
++ * No calls to other mini driver functions may subsequently
++ * occur, except for WMD_DEV_Create().
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device information.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to release a resource previously acquired.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ * DSP_SOK: Device context is freed.
++ */
++ typedef DSP_STATUS(*WMD_DEV_DESTROY) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_DEH_Create ========
++ * Purpose:
++ * Create an object that manages DSP exceptions from the GPP.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * hDevObject: Handle to DEV object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * phDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_CREATE) (OUT struct DEH_MGR
++ **phDehMgr,
++ struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Purpose:
++ * Destroy the DEH object.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_DESTROY) (struct DEH_MGR *hDehMgr);
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Purpose:
++ * Register for DEH event notification.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_REGISTERNOTIFY)
++ (struct DEH_MGR *hDehMgr,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Purpose:
++ * Get DSP exception info.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * pErrInfo: Ptr to error info structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * phDehMgr != NULL;
++ * pErrorInfo != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_GETINFO) (struct DEH_MGR *phDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++/*
++ * ======== WMD_IO_Create ========
++ * Purpose:
++ * Create an object that manages I/O between CHNL and MSG.
++ * Parameters:
++ * phIOMgr: Location to store IO manager on output.
++ * hChnlMgr: Handle to channel manager.
++ * hMsgMgr: Handle to message manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * Channel manager already created;
++ * Message manager already created;
++ * pMgrAttrs != NULL;
++ * phIOMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_CREATE) (OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Destroy object created in WMD_IO_Create.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_DESTROY) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called whenever a program is loaded to update internal data. For
++ * example, if shared memory is used, this function would update the
++ * shared memory location and address.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_ONLOADED) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_GETPROCLOAD ========
++ * Purpose:
++ * Called to get the Processor's current and predicted load
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * pProcLoadStat Processor Load statistics
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_GETPROCLOAD)(struct IO_MGR *hIOMgr,
++ struct DSP_PROCLOADSTAT *pProcLoadStat);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager on output.
++ * hDevObject: Handle to a device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgMgr != NULL.
++ * msgCallback != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATE)
++ (OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Purpose:
++ * Create a MSG queue for sending or receiving messages from a Message
++ * node on the DSP.
++ * Parameters:
++ * hMsgMgr: MSG queue manager handle returned from
++ * WMD_MSG_Create.
++ * phMsgQueue: Location to store MSG queue on output.
++ * dwId: Identifier for messages (node environment pointer).
++ * uMaxMsgs: Max number of simultaneous messages for the node.
++ * h: Handle passed to hMsgMgr->msgCallback().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgQueue != NULL.
++ * h != NULL.
++ * uMaxMsgs > 0.
++ * Ensures:
++ * phMsgQueue !=NULL <==> DSP_SOK.
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATEQUEUE)
++ (struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE h);
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from WMD_MSG_Create().
++ * Returns:
++ * Requires:
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETE) (struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Purpose:
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETEQUEUE) (struct MSG_QUEUE *hMsgQueue);
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Purpose:
++ * Get a message from a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Location to copy message into.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_GET) (struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Purpose:
++ * Put a message onto a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Pointer to message.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_PUT) (struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ * Purpose:
++ * Register notification for when a message is ready.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * uEventMask: Type of events to be notified about: Must be
++ * DSP_NODEMESSAGEREADY, or 0 to unregister.
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of notification object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Valid hMsgQueue.
++ * hNotification != NULL.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_REGISTERNOTIFY)
++ (struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ * Purpose:
++ * Set message queue id to node environment. Allows WMD_MSG_CreateQueue
++ * to be called in NODE_Allocate, before the node environment is known.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * dwId: Node environment pointer.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * dwId != 0.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_SETQUEUEID) (struct MSG_QUEUE *hMsgQueue,
++ u32 dwId);
++
++/*
++ * 'Bridge Mini Driver (WMD) interface function table.
++ *
++ * The information in this table is filled in by the specific mini-driver,
++ * and copied into the 'Bridge class driver's own space. If any interface
++ * function field is set to a value of NULL, then the class driver will
++ * consider that function not implemented, and return the error code
++ * DSP_ENOTIMPL when a WMD client attempts to call that function.
++ *
++ * This function table contains WCD version numbers, which are used by the
++ * WMD loader to help ensure backwards compatility between older WMD's and a
++ * newer 'Bridge Class Driver. These must be set to WCD_MAJOR_VERSION
++ * and WCD_MINOR_VERSION, respectively.
++ *
++ * A mini-driver need not export a CHNL interface. In this case, *all* of
++ * the WMD_CHNL_* entries must be set to NULL.
++ */
++ struct WMD_DRV_INTERFACE {
++ u32 dwWCDMajorVersion; /* Set to WCD_MAJOR_VERSION. */
++ u32 dwWCDMinorVersion; /* Set to WCD_MINOR_VERSION. */
++ WMD_DEV_CREATE pfnDevCreate; /* Create device context */
++ WMD_DEV_DESTROY pfnDevDestroy; /* Destroy device context */
++ WMD_DEV_CTRL pfnDevCntrl; /* Optional vendor interface */
++ WMD_BRD_MONITOR pfnBrdMonitor; /* Load and/or start monitor */
++ WMD_BRD_START pfnBrdStart; /* Start DSP program. */
++ WMD_BRD_STOP pfnBrdStop; /* Stop/reset board. */
++ WMD_BRD_STATUS pfnBrdStatus; /* Get current board status. */
++ WMD_BRD_READ pfnBrdRead; /* Read board memory */
++ WMD_BRD_WRITE pfnBrdWrite; /* Write board memory. */
++ WMD_BRD_SETSTATE pfnBrdSetState; /* Sets the Board State */
++ WMD_BRD_MEMCOPY pfnBrdMemCopy; /* Copies DSP Memory */
++ WMD_BRD_MEMWRITE pfnBrdMemWrite; /* Write DSP Memory w/o halt */
++ WMD_BRD_MEMMAP pfnBrdMemMap; /* Maps MPU mem to DSP mem */
++ WMD_BRD_MEMUNMAP pfnBrdMemUnMap; /* Unmaps MPU mem to DSP mem */
++ WMD_CHNL_CREATE pfnChnlCreate; /* Create channel manager. */
++ WMD_CHNL_DESTROY pfnChnlDestroy; /* Destroy channel manager. */
++ WMD_CHNL_OPEN pfnChnlOpen; /* Create a new channel. */
++ WMD_CHNL_CLOSE pfnChnlClose; /* Close a channel. */
++ WMD_CHNL_ADDIOREQ pfnChnlAddIOReq; /* Req I/O on a channel. */
++ WMD_CHNL_GETIOC pfnChnlGetIOC; /* Wait for I/O completion. */
++ WMD_CHNL_CANCELIO pfnChnlCancelIO; /* Cancl I/O on a channel. */
++ WMD_CHNL_FLUSHIO pfnChnlFlushIO; /* Flush I/O. */
++ WMD_CHNL_GETINFO pfnChnlGetInfo; /* Get channel specific info */
++ /* Get channel manager info. */
++ WMD_CHNL_GETMGRINFO pfnChnlGetMgrInfo;
++ WMD_CHNL_IDLE pfnChnlIdle; /* Idle the channel */
++ /* Register for notif. */
++ WMD_CHNL_REGISTERNOTIFY pfnChnlRegisterNotify;
++ WMD_DEH_CREATE pfnDehCreate; /* Create DEH manager */
++ WMD_DEH_DESTROY pfnDehDestroy; /* Destroy DEH manager */
++ WMD_DEH_NOTIFY pfnDehNotify; /* Notify of DSP error */
++ /* register for deh notif. */
++ WMD_DEH_REGISTERNOTIFY pfnDehRegisterNotify;
++ WMD_DEH_GETINFO pfnDehGetInfo; /* register for deh notif. */
++ WMD_IO_CREATE pfnIOCreate; /* Create IO manager */
++ WMD_IO_DESTROY pfnIODestroy; /* Destroy IO manager */
++ WMD_IO_ONLOADED pfnIOOnLoaded; /* Notify of program loaded */
++ /* Get Processor's current and predicted load */
++ WMD_IO_GETPROCLOAD pfnIOGetProcLoad;
++ WMD_MSG_CREATE pfnMsgCreate; /* Create message manager */
++ /* Create message queue */
++ WMD_MSG_CREATEQUEUE pfnMsgCreateQueue;
++ WMD_MSG_DELETE pfnMsgDelete; /* Delete message manager */
++ /* Delete message queue */
++ WMD_MSG_DELETEQUEUE pfnMsgDeleteQueue;
++ WMD_MSG_GET pfnMsgGet; /* Get a message */
++ WMD_MSG_PUT pfnMsgPut; /* Send a message */
++ /* Register for notif. */
++ WMD_MSG_REGISTERNOTIFY pfnMsgRegisterNotify;
++ /* Set message queue id */
++ WMD_MSG_SETQUEUEID pfnMsgSetQueueId;
++ } ;
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * Purpose:
++ * Registers WMD functions with the class driver. Called only once
++ * by the WCD. The caller will first check WCD version compatibility, and
++ * then copy the interface functions into its own memory space.
++ * Parameters:
++ * ppDrvInterface Pointer to a location to receive a pointer to the
++ * mini driver interface.
++ * Returns:
++ * Requires:
++ * The code segment this function resides in must expect to be discarded
++ * after completion.
++ * Ensures:
++ * ppDrvInterface pointer initialized to WMD's function interface.
++ * No system resources are acquired by this function.
++ * Details:
++ * Win95: Called during the Device_Init phase.
++ */
++ void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName);
++
++#endif /* WMD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdchnl.h b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+new file mode 100644
+index 0000000..2c1f072
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+@@ -0,0 +1,90 @@
++/*
++ * wmdchnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdchnl.h ========
++ * Description:
++ * Declares the upper edge channel class library functions required by
++ * all WMD / WCD driver interface tables. These functions are implemented
++ * by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * The function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream
++ *! support.
++ *! 11-Jul-1996 gp: Created.
++ */
++
++#ifndef WMDCHNL_
++#define WMDCHNL_
++
++ extern DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS
++ *pMgrAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++ extern DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct CHNL_ATTRS
++ *pAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl,
++ void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++ extern DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++ extern DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++ extern DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo);
++
++ extern DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++ extern DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut, bool fFlush);
++
++ extern DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++#endif /* WMDCHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmddeh.h b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+new file mode 100644
+index 0000000..dd50a3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+@@ -0,0 +1,64 @@
++/*
++ * wmddeh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmddeh.h ========
++ * Description:
++ * Defines upper edge DEH functions required by all WMD/WCD driver
++ * interface tables.
++ *
++ * Public Functions:
++ * WMD_DEH_Create
++ * IVA_DEH_Create
++ * WMD_DEH_Destroy
++ * WMD_DEH_GetInfo
++ * WMD_DEH_RegisterNotify
++ * WMD_DEH_Notify
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: added IVA_DEH_Create.
++ *! 13-Sep-2001 kc: created.
++ */
++
++#ifndef WMDDEH_
++#define WMDDEH_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/dehdefs.h>
++
++ extern DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject);
++
++ extern DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr);
++
++ extern DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++ extern DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_DEH_Notify(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++#endif /* WMDDEH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdio.h b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+new file mode 100644
+index 0000000..8525474
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+@@ -0,0 +1,53 @@
++/*
++ * wmdio.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdio.h ========
++ * Description:
++ * Declares the upper edge IO functions required by
++ * all WMD / WCD driver interface tables.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 27-Feb-2004 vp Added IVA releated function.
++ *! 06-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDIO_
++#define WMDIO_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++
++ extern DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++ extern DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS IVA_IO_OnLoaded(struct IO_MGR *hIOMgr);
++ extern DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat);
++
++#endif /* WMDIO_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdioctl.h b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+new file mode 100644
+index 0000000..a41c61a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+@@ -0,0 +1,91 @@
++/*
++ * wmdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdioctl.h ========
++ * Description:
++ * BRIDGE Minidriver BRD_IOCtl reserved command definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Updated HW typedefs
++ *! 16-Feb-2004 vp Added MMU endianness attributes to WMDIOCTL_EXTPROC
++ *! 21-Mar-2003 sb Changed WMDIOCTL_NUMOFMMUTLB from 7 to 32
++ *! 14-May-2001 sg Added codes for PWR.
++ *! 10-Aug-2001 ag Added _SETMMUCONFIG ioctl used for DSP-MMU init.
++ *! 16-Nov-1999 rajesh ?
++ *! 18-Jun-1998 ag Moved EMIF, SDRAM_C, & CE space init to ENBLEXTMEM ioctl.
++ *! Added ENBLEXTMEM, RESETDSP, UNRESETDSP & ASSERTSIG ioctls.
++ *! 07-Jun-1998 ag Added JTAG_SELECT, MAP_TBC, GET_CONFIGURATION ioctls.
++ *! 26-Jan-1998 jeh: Added START, RECV, and SEND ioctls.
++ *! 07-Nov-1997 nn: Added command to interrupt DSP for interrupt test.
++ *! 20-Oct-1997 nn: Added commands for getting and resetting interrupt count.
++ *! 17-Oct-1997 gp: Moved to src/wmd. Standardized prefix.
++ *! 08-Oct-1997 nn: Created.
++ */
++
++#ifndef WMDIOCTL_
++#define WMDIOCTL_
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* Any IOCTLS at or above this value are reserved for standard WMD interfaces.*/
++#define WMDIOCTL_RESERVEDBASE 0x8000
++
++#define WMDIOCTL_CHNLREAD (WMDIOCTL_RESERVEDBASE + 0x10)
++#define WMDIOCTL_CHNLWRITE (WMDIOCTL_RESERVEDBASE + 0x20)
++#define WMDIOCTL_GETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x30)
++#define WMDIOCTL_RESETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x40)
++#define WMDIOCTL_INTERRUPTDSP (WMDIOCTL_RESERVEDBASE + 0x50)
++#define WMDIOCTL_SETMMUCONFIG (WMDIOCTL_RESERVEDBASE + 0x60) /* DMMU */
++#define WMDIOCTL_PWRCONTROL (WMDIOCTL_RESERVEDBASE + 0x70) /* PWR */
++
++/* attention, modifiers:
++ * Some of these control enumerations are made visible to user for power
++ * control, so any changes to this list, should also be updated in the user
++ * header file 'dbdefs.h' ***/
++/* These ioctls are reserved for PWR power commands for the DSP */
++#define WMDIOCTL_DEEPSLEEP (WMDIOCTL_PWRCONTROL + 0x0)
++#define WMDIOCTL_EMERGENCYSLEEP (WMDIOCTL_PWRCONTROL + 0x1)
++#define WMDIOCTL_WAKEUP (WMDIOCTL_PWRCONTROL + 0x2)
++#define WMDIOCTL_PWRENABLE (WMDIOCTL_PWRCONTROL + 0x3)
++#define WMDIOCTL_PWRDISABLE (WMDIOCTL_PWRCONTROL + 0x4)
++#define WMDIOCTL_CLK_CTRL (WMDIOCTL_PWRCONTROL + 0x7)
++#define WMDIOCTL_PWR_HIBERNATE (WMDIOCTL_PWRCONTROL + 0x8) /*DSP Initiated
++ * Hibernate*/
++#define WMDIOCTL_PRESCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0x9)
++#define WMDIOCTL_POSTSCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0xA)
++#define WMDIOCTL_CONSTRAINT_REQUEST (WMDIOCTL_PWRCONTROL + 0xB)
++
++/* Number of actual DSP-MMU TLB entrries */
++#define WMDIOCTL_NUMOFMMUTLB 32
++
++struct WMDIOCTL_EXTPROC {
++ u32 ulDspVa; /* DSP virtual address */
++ u32 ulGppPa; /* GPP physical address */
++ /* GPP virtual address. __va does not work for ioremapped addresses */
++ u32 ulGppVa;
++ u32 ulSize; /* Size of the mapped memory in bytes */
++ enum HW_Endianism_t endianism;
++ enum HW_MMUMixedSize_t mixedMode;
++ enum HW_ElementSize_t elemSize;
++};
++
++#endif /* WMDIOCTL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdmsg.h b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+new file mode 100644
+index 0000000..81198d4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+@@ -0,0 +1,70 @@
++/*
++ * wmdmsg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdmsg.h ========
++ * Description:
++ * Declares the upper edge message class library functions required by
++ * all WMD / WCD driver interface tables. These functions are
++ * implemented by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify(). Added
++ *! WMD_MSG_SetQueueId().
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDMSG_
++#define WMDMSG_
++
++#include <dspbridge/msgdefs.h>
++
++ extern DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++ extern DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs,
++ HANDLE h);
++
++ extern void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++ extern void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue);
++
++ extern DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId);
++
++#endif /* WMDMSG_ */
+diff --git a/drivers/Makefile b/drivers/Makefile
+index fec4d8e..6fcee09 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_PARPORT) += parport/
+ obj-y += base/ block/ misc/ mfd/ net/ media/
+ obj-y += i2c/
+ obj-y += cbus/
++obj-$(CONFIG_MPU_BRIDGE) += dsp/bridge/
+ obj-$(CONFIG_NUBUS) += nubus/
+ obj-$(CONFIG_ATM) += atm/
+ obj-y += macintosh/
+diff --git a/drivers/dsp/bridge/Kbuild b/drivers/dsp/bridge/Kbuild
+new file mode 100644
+index 0000000..3432ff2
+--- /dev/null
++++ b/drivers/dsp/bridge/Kbuild
+@@ -0,0 +1,39 @@
++obj-$(CONFIG_MPU_BRIDGE) += bridgedriver.o
++
++libgen = gen/gb.o gen/gt.o gen/gs.o gen/gh.o gen/_gt_para.o gen/uuidutil.o
++libservices = services/csl.o services/mem.o services/list.o services/dpc.o \
++ services/kfile.o services/sync.o \
++ services/clk.o services/cfg.o services/reg.o \
++ services/regsup.o services/ntfy.o \
++ services/dbg.o services/services.o
++libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \
++ wmd/tiomap3430_pwr.o wmd/tiomap_sm.o wmd/tiomap_io.o \
++ wmd/mmu_fault.o wmd/ue_deh.o
++libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/wcd.o \
++ pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
++librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
++ rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
++ rmgr/nldr.o rmgr/drv_interface.o
++libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o
++libhw = hw/hw_prcm.o hw/hw_dspssC64P.o hw/hw_mmu.o hw/hw_mbox.o
++
++bridgedriver-objs = $(libgen) $(libservices) $(libwmd) $(libpmgr) $(librmgr) \
++ $(libdload) $(libhw)
++
++# Debug
++ifeq ($(CONFIG_BRIDGE_DEBUG),y)
++ccflags-y += -DGT_TRACE -DDEBUG
++endif
++
++#Machine dependent
++ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
++ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
++ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS
++
++#Header files
++ccflags-y += -Idrivers/dsp/bridge/services
++ccflags-y += -Idrivers/dsp/bridge/wmd
++ccflags-y += -Idrivers/dsp/bridge/pmgr
++ccflags-y += -Idrivers/dsp/bridge/rmgr
++ccflags-y += -Idrivers/dsp/bridge/hw
++ccflags-y += -Iarch/arm
+diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig
+new file mode 100644
+index 0000000..2fed82c
+--- /dev/null
++++ b/drivers/dsp/bridge/Kconfig
+@@ -0,0 +1,36 @@
++#
++# DSP Bridge Driver Support
++#
++
++menuconfig MPU_BRIDGE
++ tristate "DSP Bridge driver"
++ default n
++ help
++ DSP/BIOS Bridge is designed for platforms that contain a GPP and
++ one or more attached DSPs. The GPP is considered the master or
++ "host" processor, and the attached DSPs are processing resources
++ that can be utilized by applications and drivers running on the GPP.
++
++config BRIDGE_DVFS
++ bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
++ depends on MPU_BRIDGE && OMAP_PM_SRF
++ default n
++ help
++ DVFS allows DSP Bridge to initiate the operating point change to
++ scale the chip voltage and frequency in order to match the
++ performance and power consumption to the current processing
++ requirements.
++
++config BRIDGE_MEMPOOL_SIZE
++ hex "Physical memory pool size (Byte)"
++ depends on MPU_BRIDGE
++ default 0x600000
++ help
++ Allocate specified size of memory at booting time to avoid allocation
++ failure under heavy memory fragmentation after some use time.
++
++config BRIDGE_DEBUG
++ bool "DSP Bridge Debug Support"
++ depends on MPU_BRIDGE
++ help
++ Say Y to enable Bridge debugging capabilities
+diff --git a/drivers/dsp/bridge/dynload/cload.c b/drivers/dsp/bridge/dynload/cload.c
+new file mode 100644
+index 0000000..271ab81
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/cload.c
+@@ -0,0 +1,1854 @@
++/*
++ * cload.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#include "module_list.h"
++#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. This macro marks
++ * the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++
++/*
++ * forward references
++ */
++static void dload_symbols(struct dload_state *dlthis);
++static void dload_data(struct dload_state *dlthis);
++static void allocate_sections(struct dload_state *dlthis);
++static void string_table_free(struct dload_state *dlthis);
++static void symbol_table_free(struct dload_state *dlthis);
++static void section_table_free(struct dload_state *dlthis);
++static void init_module_handle(struct dload_state *dlthis);
++#if BITS_PER_AU > BITS_PER_BYTE
++static char *unpack_name(struct dload_state *dlthis, u32 soffset);
++#endif
++
++static const char CINITNAME[] = { ".cinit" };
++static const char LOADER_DLLVIEW_ROOT[] = { "?DLModules?" };
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_TGTALLOC[] =
++ { "Target memory allocate failed, section %s size " FMT_UI32 };
++static const char E_INITFAIL[] = { "%s to target address " FMT_UI32 " failed" };
++static const char E_DLVWRITE[] = { "Write to DLLview list failed" };
++static const char E_ICONNECT[] = { "Connect call to init interface failed" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++
++/*************************************************************************
++ * Procedure dload_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ dlthis->mysym->Error_Report(dlthis->mysym, errtxt, args);
++ va_end(args);
++ dlthis->dload_errcount += 1;
++
++} /* dload_error */
++
++#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
++
++/*************************************************************************
++ * Procedure dload_syms_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_syms_error(struct Dynamic_Loader_Sym *syms, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ syms->Error_Report(syms, errtxt, args);
++ va_end(args);
++}
++
++/*************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int Dynamic_Load_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms ,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ if (init && !dl_state.dload_errcount)
++ dload_data(&dl_state);
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount) &&
++ (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF)) {
++ if (init != NULL) {
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ } else {
++ dload_error(&dl_state, "init is NULL");
++ }
++ }
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int
++Dynamic_Open_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount)
++ && (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF))
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure dload_headers
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the DOFF header and verify record. Deals with any byte-order
++ * issues and checks them for validity.
++ ************************************************************************/
++#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
++ sizeof(struct doff_verify_rec_t))
++
++void dload_headers(struct dload_state *dlthis)
++{
++ u32 map;
++
++ /* Read the header and the verify record as one. If we don't get it
++ all, we're done */
++ if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
++ COMBINED_HEADER_SIZE) != COMBINED_HEADER_SIZE) {
++ DL_ERROR(E_READSTRM, "File Headers");
++ return;
++ }
++ /*
++ * Verify that we have the byte order of the file correct.
++ * If not, must fix it before we can continue
++ */
++ map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
++ if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
++ /* input is either byte-shuffled or bad */
++ if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
++ dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
++ map);
++ }
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ BYTE_RESHUFFLE_VALUE) {
++ /* didn't fix the problem, the byte swap map is bad */
++ dload_error(dlthis,
++ "Bad byte swap map " FMT_UI32 " in header",
++ dlthis->dfile_hdr.df_byte_reshuffle);
++ return;
++ }
++ dlthis->reorder_map = map; /* keep map for future use */
++ }
++
++ /*
++ * Verify checksum of header and verify record
++ */
++ if (~dload_checksum(&dlthis->dfile_hdr,
++ sizeof(struct doff_filehdr_t)) ||
++ ~dload_checksum(&dlthis->verify,
++ sizeof(struct doff_verify_rec_t))) {
++ DL_ERROR(E_CHECKSUM, "header or verify record");
++ return;
++ }
++#if HOST_ENDIANNESS
++ dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
++#endif
++
++ /* Check for valid target ID */
++ if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
++ -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
++ dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
++ dlthis->dfile_hdr.df_target_id, TARGET_ID);
++ return;
++ }
++ /* Check for valid file format */
++ if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
++ dload_error(dlthis, "Bad DOFF version 0x%x",
++ dlthis->dfile_hdr.df_doff_version);
++ return;
++ }
++
++ /*
++ * Apply reasonableness checks to count fields
++ */
++ if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
++ dload_error(dlthis, "Excessive string table size " FMT_UI32,
++ dlthis->dfile_hdr.df_strtab_size);
++ return;
++ }
++ if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
++ dload_error(dlthis, "Excessive section count 0x%x",
++ dlthis->dfile_hdr.df_no_scns);
++ return;
++ }
++#ifndef TARGET_ENDIANNESS
++ /*
++ * Check that endianness does not disagree with explicit specification
++ */
++ if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
++ dlthis->myoptions & ENDIANNESS_MASK) {
++ dload_error(dlthis,
++ "Input endianness disagrees with specified option");
++ return;
++ }
++ dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
++#endif
++
++} /* dload_headers */
++
++/* COFF Section Processing
++ *
++ * COFF sections are read in and retained intact. Each record is embedded
++ * in a new structure that records the updated load and
++ * run addresses of the section */
++
++static const char SECN_ERRID[] = { "section" };
++
++/*************************************************************************
++ * Procedure dload_sections
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the section records into an internal table.
++ ************************************************************************/
++void
++dload_sections(struct dload_state *dlthis)
++{
++ s16 siz;
++ struct doff_scnhdr_t *shp;
++ unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
++
++ /* allocate space for the DOFF section records */
++ siz = nsecs * sizeof(struct doff_scnhdr_t);
++ shp = (struct doff_scnhdr_t *)dlthis->mysym->Allocate(dlthis->mysym,
++ siz);
++ if (!shp) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->sect_hdrs = shp;
++
++ /* read in the section records */
++ if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
++ DL_ERROR(E_READSTRM, SECN_ERRID);
++ return;
++ }
++
++ /* if we need to fix up byte order, do it now */
++ if (dlthis->reorder_map)
++ dload_reorder(shp, siz, dlthis->reorder_map);
++
++ /* check for validity */
++ if (~dload_checksum(dlthis->sect_hdrs, siz) !=
++ dlthis->verify.dv_scn_rec_checksum) {
++ DL_ERROR(E_CHECKSUM, SECN_ERRID);
++ return;
++ }
++
++} /* dload_sections */
++
++/*****************************************************************************
++ * Procedure allocate_sections
++ *
++ * Parameters:
++ * alloc target memory allocator class
++ *
++ * Effect:
++ * Assigns new (target) addresses for sections
++ *****************************************************************************/
++static void allocate_sections(struct dload_state *dlthis)
++{
++ u16 curr_sect, nsecs, siz;
++ struct doff_scnhdr_t *shp;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ nsecs = dlthis->dfile_hdr.df_no_scns;
++ if (!nsecs)
++ return;
++ if ((dlthis->myalloc == NULL) &&
++ (dlthis->dfile_hdr.df_target_scns > 0)) {
++ DL_ERROR("Arg 3 (alloc) required but NULL", 0);
++ return;
++ }
++ /* allocate space for the module handle, which we will
++ * keep for unload purposes */
++ siz = dlthis->dfile_hdr.df_target_scns *
++ sizeof(struct LDR_SECTION_INFO) + MY_HANDLE_SIZE;
++ hndl = (struct my_handle *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!hndl) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ /* initialize the handle header */
++ hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
++ hndl->dm.hroot = NULL;
++ hndl->dm.dbthis = 0;
++ dlthis->myhandle = hndl; /* save away for return */
++ /* pointer to the section list of allocated sections */
++ dlthis->ldr_sections = asecs = hndl->secns;
++ /* * Insert names into all sections, make copies of
++ the sections we allocate */
++ shp = dlthis->sect_hdrs;
++ for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
++ u32 soffset = shp->ds_offset;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ /* attempt to insert the name of this section */
++ if (soffset < dlthis->dfile_hdr.df_strtab_size)
++ DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
++ soffset;
++ else {
++ dload_error(dlthis, "Bad name offset in section %d",
++ curr_sect);
++ DOFFSEC_IS_LDRSEC(shp)->name = NULL;
++ }
++#endif
++ /* allocate target storage for sections that require it */
++ if (DS_NEEDS_ALLOCATION(shp)) {
++ *asecs = *DOFFSEC_IS_LDRSEC(shp);
++ asecs->context = 0; /* zero the context field */
++#if BITS_PER_AU > BITS_PER_BYTE
++ asecs->name = unpack_name(dlthis, soffset);
++ dlthis->debug_string_size = soffset + dlthis->temp_len;
++#else
++ dlthis->debug_string_size = soffset;
++#endif
++ if (dlthis->myalloc != NULL) {
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, asecs,
++ DS_ALIGNMENT(asecs->type))) {
++ dload_error(dlthis, E_TGTALLOC, asecs->name,
++ asecs->size);
++ return;
++ }
++ }
++ /* keep address deltas in original section table */
++ shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
++ shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
++ dlthis->allocated_secn_count += 1;
++ } /* allocate target storage */
++ shp += 1;
++ asecs += 1;
++ }
++#if BITS_PER_AU <= BITS_PER_BYTE
++ dlthis->debug_string_size +=
++ strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
++#endif
++} /* allocate sections */
++
++/*************************************************************************
++ * Procedure section_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ ************************************************************************/
++static void section_table_free(struct dload_state *dlthis)
++{
++ struct doff_scnhdr_t *shp;
++
++ shp = dlthis->sect_hdrs;
++ if (shp)
++ dlthis->mysym->Deallocate(dlthis->mysym, shp);
++
++} /* section_table_free */
++
++/*************************************************************************
++ * Procedure dload_strings
++ *
++ * Parameters:
++ * sec_names_only If true only read in the "section names"
++ * portion of the string table
++ *
++ * Effect:
++ * Loads the DOFF string table into memory. DOFF keeps all strings in a
++ * big unsorted array. We just read that array into memory in bulk.
++ ************************************************************************/
++static const char S_STRINGTBL[] = { "string table" };
++void dload_strings(struct dload_state *dlthis, boolean sec_names_only)
++{
++ u32 ssiz;
++ char *strbuf;
++
++ if (sec_names_only) {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_scn_name_size));
++ } else {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_strtab_size));
++ }
++ if (ssiz == 0)
++ return;
++
++ /* get some memory for the string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz +
++ dlthis->dfile_hdr.df_max_str_len);
++#else
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz);
++#endif
++ if (strbuf == NULL) {
++ DL_ERROR(E_ALLOC, ssiz);
++ return;
++ }
++ dlthis->str_head = strbuf;
++#if BITS_PER_AU > BITS_PER_BYTE
++ dlthis->str_temp = strbuf + ssiz;
++#endif
++ /* read in the strings and verify them */
++ if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
++ ssiz)) != ssiz) {
++ DL_ERROR(E_READSTRM, S_STRINGTBL);
++ }
++ /* if we need to fix up byte order, do it now */
++#ifndef _BIG_ENDIAN
++ if (dlthis->reorder_map)
++ dload_reorder(strbuf, ssiz, dlthis->reorder_map);
++
++ if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put strings in big-endian order, not in PC order */
++ dload_reorder(strbuf, ssiz, HOST_BYTE_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++ if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#endif
++} /* dload_strings */
++
++/*************************************************************************
++ * Procedure string_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the string table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *************************************************************************/
++static void string_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++} /* string_table_free */
++
++/*
++ * Symbol Table Maintenance Functions
++ *
++ * COFF symbols are read by dload_symbols(), which is called after
++ * sections have been allocated. Symbols which might be used in
++ * relocation (ie, not debug info) are retained in an internal temporary
++ * compressed table (type Local_Symbol). A particular symbol is recovered
++ * by index by calling dload_find_symbol(). dload_find_symbol
++ * reconstructs a more explicit representation (type SLOTVEC) which is
++ * used by reloc.c
++ */
++/* real size of debug header */
++#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
++
++static const char SYM_ERRID[] = { "symbol" };
++
++/**************************************************************************
++ * Procedure dload_symbols
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Reads in symbols and retains ones that might be needed for relocation
++ * purposes.
++ ************************************************************************/
++/* size of symbol buffer no bigger than target data buffer, to limit stack
++ * usage*/
++#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
++ sizeof(struct doff_syment_t))
++
++static void dload_symbols(struct dload_state *dlthis)
++{
++ u32 s_count, siz, dsiz, symbols_left;
++ u32 checks;
++ struct Local_Symbol *sp;
++ struct dynload_symbol *symp;
++ struct dynload_symbol *newsym;
++
++ s_count = dlthis->dfile_hdr.df_no_syms;
++ if (s_count == 0)
++ return;
++
++ /* We keep a local symbol table for all of the symbols in the input.
++ * This table contains only section & value info, as we do not have
++ * to do any name processing for locals. We reuse this storage
++ * as a temporary for .dllview record construction.
++ * Allocate storage for the whole table.*/
++ siz = s_count * sizeof(struct Local_Symbol);
++ dsiz = DBG_HDR_SIZE +
++ (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
++ BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
++ if (dsiz > siz)
++ siz = dsiz; /* larger of symbols and .dllview temp */
++ sp = (struct Local_Symbol *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!sp) {
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->local_symtab = sp;
++ /* Read the symbols in the input, store them in the table, and post any
++ * globals to the global symbol table. In the process, externals
++ become defined from the global symbol table */
++ checks = dlthis->verify.dv_sym_tab_checksum;
++ symbols_left = s_count;
++ do { /* read all symbols */
++ char *sname;
++ u32 val;
++ s32 delta;
++ struct doff_syment_t *input_sym;
++ unsigned syms_in_buf;
++ struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
++ input_sym = my_sym_buf;
++ syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
++ MY_SYM_BUF_SIZ : symbols_left;
++ siz = syms_in_buf * sizeof(struct doff_syment_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
++ siz) {
++ DL_ERROR(E_READSTRM, SYM_ERRID);
++ return;
++ }
++ if (dlthis->reorder_map)
++ dload_reorder(input_sym, siz, dlthis->reorder_map);
++
++ checks += dload_checksum(input_sym, siz);
++ do { /* process symbols in buffer */
++ symbols_left -= 1;
++ /* attempt to derive the name of this symbol */
++ sname = NULL;
++ if (input_sym->dn_offset > 0) {
++#if BITS_PER_AU <= BITS_PER_BYTE
++ if ((u32) input_sym->dn_offset <
++ dlthis->dfile_hdr.df_strtab_size)
++ sname = dlthis->str_head +
++ BYTE_TO_HOST(input_sym->dn_offset);
++ else
++ dload_error(dlthis,
++ "Bad name offset in symbol %d",
++ symbols_left);
++#else
++ sname = unpack_name(dlthis,
++ input_sym->dn_offset);
++#endif
++ }
++ val = input_sym->dn_value;
++ delta = 0;
++ sp->sclass = input_sym->dn_sclass;
++ sp->secnn = input_sym->dn_scnum;
++ /* if this is an undefined symbol,
++ * define it (or fail) now */
++ if (sp->secnn == DN_UNDEF) {
++ /* pointless for static undefined */
++ if (input_sym->dn_sclass != DN_EXT)
++ goto loop_cont;
++
++ /* try to define symbol from previously
++ * loaded images */
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp) {
++ DL_ERROR
++ ("Undefined external symbol %s",
++ sname);
++ goto loop_cont;
++ }
++ val = delta = symp->value;
++ goto loop_cont;
++ }
++ /* symbol defined by this module */
++ if (sp->secnn > 0) { /* symbol references a section */
++ if ((unsigned)sp->secnn <=
++ dlthis->allocated_secn_count) {
++ /* section was allocated */
++ struct doff_scnhdr_t *srefp =
++ &dlthis->sect_hdrs
++ [sp->secnn - 1];
++
++ if (input_sym->dn_sclass ==
++ DN_STATLAB ||
++ input_sym->dn_sclass == DN_EXTLAB){
++ /* load */
++ delta = srefp->ds_vaddr;
++ } else {
++ /* run */
++ delta = srefp->ds_paddr;
++ }
++ val += delta;
++ }
++ goto loop_itr;
++ }
++ /* This symbol is an absolute symbol */
++ if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
++ (sp->sclass == DN_EXTLAB))) {
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp)
++ goto loop_itr;
++ /* This absolute symbol is already defined. */
++ if (symp->value == input_sym->dn_value) {
++ /* If symbol values are equal, continue
++ * but don't add to the global symbol
++ * table */
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ continue;
++ } else {
++ /* If symbol values are not equal,
++ * return with redefinition error */
++ DL_ERROR("Absolute symbol %s is "
++ "defined multiple times with "
++ "different values", sname);
++ return;
++ }
++ }
++loop_itr:
++ /* if this is a global symbol, post it to the
++ * global table */
++ if (input_sym->dn_sclass == DN_EXT ||
++ input_sym->dn_sclass == DN_EXTLAB) {
++ /* Keep this global symbol for subsequent
++ * modules. Don't complain on error, to allow
++ * symbol API to suppress global symbols */
++ if (!sname)
++ goto loop_cont;
++
++ newsym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, sname,
++ (unsigned)dlthis->myhandle);
++ if (newsym)
++ newsym->value = val;
++
++ } /* global */
++loop_cont:
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ } while ((syms_in_buf -= 1) > 0); /* process sym in buffer */
++ } while (symbols_left > 0); /* read all symbols */
++ if (~checks)
++ dload_error(dlthis, "Checksum of symbols failed");
++
++} /* dload_symbols */
++
++/*****************************************************************************
++ * Procedure symbol_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *****************************************************************************/
++static void symbol_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->local_symtab) {
++ if (dlthis->dload_errcount) { /* blow off our symbols */
++ dlthis->mysym->Purge_Symbol_Table(dlthis->mysym,
++ (unsigned)dlthis->myhandle);
++ }
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->local_symtab);
++ }
++} /* symbol_table_free */
++
++/* .cinit Processing
++ *
++ * The dynamic loader does .cinit interpretation. cload_cinit()
++ * acts as a special write-to-target function, in that it takes relocated
++ * data from the normal data flow, and interprets it as .cinit actions.
++ * Because the normal data flow does not necessarily process the whole
++ * .cinit section in one buffer, cload_cinit() must be prepared to
++ * interpret the data piecemeal. A state machine is used for this
++ * purpose.
++ */
++
++/* The following are only for use by reloc.c and things it calls */
++static const struct LDR_SECTION_INFO CINIT_INFO_INIT = { CINITNAME, 0, 0,
++ (LDR_ADDR) -1, 0, DLOAD_BSS, 0 };
++
++/*************************************************************************
++ * Procedure cload_cinit
++ *
++ * Parameters:
++ * ipacket Pointer to data packet to be loaded
++ *
++ * Effect:
++ * Interprets the data in the buffer as .cinit data, and performs the
++ * appropriate initializations.
++ ************************************************************************/
++static void cload_cinit(struct dload_state *dlthis,
++ struct image_packet_t *ipacket)
++{
++#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
++ s32 init_count, left;
++#else
++ s16 init_count, left;
++#endif
++ unsigned char *pktp = ipacket->i_bits;
++ unsigned char *pktend = pktp +
++ BYTE_TO_HOST_ROUND(ipacket->i_packet_size);
++ int temp;
++ LDR_ADDR atmp;
++ struct LDR_SECTION_INFO cinit_info;
++
++ /* PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
++ while (true) {
++ left = pktend - pktp;
++ switch (dlthis->cinit_state) {
++ case CI_count: /* count field */
++ if (left < TDATA_TO_HOST(CINIT_COUNT))
++ goto loopexit;
++ temp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_COUNT * TDATA_AU_BITS, 0,
++ ROP_SGN);
++ pktp += TDATA_TO_HOST(CINIT_COUNT);
++ /* negative signifies BSS table, zero means done */
++ if (temp <= 0) {
++ dlthis->cinit_state = CI_done;
++ break;
++ }
++ dlthis->cinit_count = temp;
++ dlthis->cinit_state = CI_address;
++ break;
++#if CINIT_ALIGN < CINIT_ADDRESS
++ case CI_partaddress:
++ pktp -= TDATA_TO_HOST(CINIT_ALIGN);
++ /* back up pointer into space courtesy of caller */
++ *(uint16_t *)pktp = dlthis->cinit_addr;
++ /* stuff in saved bits !! FALL THRU !! */
++#endif
++ case CI_address: /* Address field for a copy packet */
++ if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
++#if CINIT_ALIGN < CINIT_ADDRESS
++ if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
++ /* address broken into halves */
++ dlthis->cinit_addr = *(uint16_t *)pktp;
++ /* remember 1st half */
++ dlthis->cinit_state = CI_partaddress;
++ left = 0;
++ }
++#endif
++ goto loopexit;
++ }
++ atmp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_ADDRESS * TDATA_AU_BITS, 0,
++ ROP_UNS);
++ pktp += TDATA_TO_HOST(CINIT_ADDRESS);
++#if CINIT_PAGE_BITS > 0
++ dlthis->cinit_page = atmp &
++ ((1 << CINIT_PAGE_BITS) - 1);
++ atmp >>= CINIT_PAGE_BITS;
++#else
++ dlthis->cinit_page = CINIT_DEFAULT_PAGE;
++#endif
++ dlthis->cinit_addr = atmp;
++ dlthis->cinit_state = CI_copy;
++ break;
++ case CI_copy: /* copy bits to the target */
++ init_count = HOST_TO_TDATA(left);
++ if (init_count > dlthis->cinit_count)
++ init_count = dlthis->cinit_count;
++ if (init_count == 0)
++ goto loopexit; /* get more bits */
++ cinit_info = CINIT_INFO_INIT;
++ cinit_info.page = dlthis->cinit_page;
++ if (!dlthis->myio->writemem(dlthis->myio, pktp,
++ TDATA_TO_TADDR(dlthis->cinit_addr),
++ &cinit_info,
++ TDATA_TO_HOST(init_count))) {
++ dload_error(dlthis, E_INITFAIL, "write",
++ dlthis->cinit_addr);
++ }
++ dlthis->cinit_count -= init_count;
++ if (dlthis->cinit_count <= 0) {
++ dlthis->cinit_state = CI_count;
++ init_count = (init_count + CINIT_ALIGN - 1) &
++ -CINIT_ALIGN;
++ /* align to next init */
++ }
++ pktp += TDATA_TO_HOST(init_count);
++ dlthis->cinit_addr += init_count;
++ break;
++ case CI_done: /* no more .cinit to do */
++ return;
++ } /* switch (cinit_state) */
++ } /* while */
++
++loopexit:
++ if (left > 0) {
++ dload_error(dlthis, "%d bytes left over in cinit packet", left);
++ dlthis->cinit_state = CI_done; /* left over bytes are bad */
++ }
++} /* cload_cinit */
++
++/* Functions to interface to reloc.c
++ *
++ * reloc.c is the relocation module borrowed from the linker, with
++ * minimal (we hope) changes for our purposes. cload_sect_data() invokes
++ * this module on a section to relocate and load the image data for that
++ * section. The actual read and write actions are supplied by the global
++ * routines below.
++ */
++
++/************************************************************************
++ * Procedure relocate_packet
++ *
++ * Parameters:
++ * ipacket Pointer to an image packet to relocate
++ *
++ * Effect:
++ * Performs the required relocations on the packet. Returns a checksum
++ * of the relocation operations.
++ ************************************************************************/
++#define MY_RELOC_BUF_SIZ 8
++/* careful! exists at the same time as the image buffer*/
++static int relocate_packet(struct dload_state *dlthis,
++ struct image_packet_t *ipacket, u32 *checks)
++{
++ u32 rnum;
++
++ rnum = ipacket->i_num_relocs;
++ do { /* all relocs */
++ unsigned rinbuf;
++ int siz;
++ struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
++ rp = rrec;
++ rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
++ siz = rinbuf * sizeof(struct reloc_record_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
++ DL_ERROR(E_READSTRM, "relocation");
++ return 0;
++ }
++ /* reorder the bytes if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(rp, siz, dlthis->reorder_map);
++
++ *checks += dload_checksum(rp, siz);
++ do {
++ /* perform the relocation operation */
++ dload_relocate(dlthis, (TgtAU_t *) ipacket->i_bits, rp);
++ rp += 1;
++ rnum -= 1;
++ } while ((rinbuf -= 1) > 0);
++ } while (rnum > 0); /* all relocs */
++ return 1;
++} /* dload_read_reloc */
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++
++/* VERY dangerous */
++static const char IMAGEPAK[] = { "image packet" };
++
++/*************************************************************************
++ * Procedure dload_data
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Read image data from input file, relocate it, and download it to the
++ * target.
++ ************************************************************************/
++static void dload_data(struct dload_state *dlthis)
++{
++ u16 curr_sect;
++ struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
++ struct LDR_SECTION_INFO *lptr = dlthis->ldr_sections;
++#ifdef OPT_ZERO_COPY_LOADER
++ boolean bZeroCopy = false;
++#endif
++ u8 *pDest;
++
++ struct {
++ struct image_packet_t ipacket;
++ u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
++ } ibuf;
++
++ /* Indicates whether CINIT processing has occurred */
++ boolean cinit_processed = false;
++
++ /* Loop through the sections and load them one at a time.
++ */
++ for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
++ curr_sect += 1) {
++ if (DS_NEEDS_DOWNLOAD(sptr)) {
++ s32 nip;
++ LDR_ADDR image_offset = 0;
++ /* set relocation info for this section */
++ if (curr_sect < dlthis->allocated_secn_count)
++ dlthis->delta_runaddr = sptr->ds_paddr;
++ else {
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++ dlthis->delta_runaddr = 0;
++ }
++ dlthis->image_secn = lptr;
++#if BITS_PER_AU > BITS_PER_BYTE
++ lptr->name = unpack_name(dlthis, sptr->ds_offset);
++#endif
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* process packets */
++
++ s32 ipsize;
++ u32 checks;
++ /* get the fixed header bits */
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ &ibuf.ipacket, IPH_SIZE) != IPH_SIZE) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map) {
++ dload_reorder(&ibuf.ipacket, IPH_SIZE,
++ dlthis->reorder_map);
++ }
++ /* now read the rest of the packet */
++ ipsize =
++ BYTE_TO_HOST(DOFF_ALIGN
++ (ibuf.ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ DL_ERROR("Bad image packet size %d",
++ ipsize);
++ return;
++ }
++ pDest = ibuf.bufr;
++#ifdef OPT_ZERO_COPY_LOADER
++ bZeroCopy = false;
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
++ dlthis->myio->writemem(dlthis->myio,
++ &pDest, lptr->load_addr +
++ image_offset, lptr, 0);
++ bZeroCopy = (pDest != ibuf.bufr);
++ }
++#endif
++ /* End of determination */
++
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ ibuf.bufr, ipsize) != ipsize) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ ibuf.ipacket.i_bits = pDest;
++
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map) {
++ dload_reorder(pDest, ipsize,
++ dlthis->reorder_map);
++ }
++ checks = dload_checksum(pDest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP
++ (BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order,
++ * not PC order */
++ dload_reorder(pDest, ipsize,
++ TARGET_ORDER
++ (dlthis->dfile_hdr.df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(pDest,
++ ipsize);
++#else
++ checks = dload_reverse_checksum(pDest,
++ ipsize);
++#endif
++#endif
++
++ checks += dload_checksum(&ibuf.ipacket,
++ IPH_SIZE);
++ /* relocate the image bits as needed */
++ if (ibuf.ipacket.i_num_relocs) {
++ dlthis->image_offset = image_offset;
++ if (!relocate_packet(dlthis,
++ &ibuf.ipacket, &checks))
++ return; /* serious error */
++ }
++ if (~checks)
++ DL_ERROR(E_CHECKSUM, IMAGEPAK);
++ /* stuff the result into target memory */
++ if (DLOAD_SECT_TYPE(sptr) == DLOAD_CINIT) {
++ cload_cinit(dlthis, &ibuf.ipacket);
++ cinit_processed = true;
++ } else {
++#ifdef OPT_ZERO_COPY_LOADER
++ if (!bZeroCopy) {
++#endif
++
++ if (!dlthis->myio->writemem
++ (dlthis->myio, ibuf.bufr,
++ lptr->load_addr + image_offset, lptr,
++ BYTE_TO_HOST
++ (ibuf.ipacket.i_packet_size))) {
++ DL_ERROR(
++ "Write to " FMT_UI32 " failed",
++ lptr->load_addr + image_offset);
++ }
++#ifdef OPT_ZERO_COPY_LOADER
++ }
++#endif
++
++ }
++ image_offset +=
++ BYTE_TO_TADDR(ibuf.ipacket.i_packet_size);
++ } /* process packets */
++ /* if this is a BSS section, we may want to fill it */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (cinit_processed) {
++ /* Don't clear BSS after load-time
++ * initialization */
++ DL_ERROR
++ ("Zero-initialization at " FMT_UI32 " after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr),
++ lptr, TADDR_TO_HOST(lptr->size),
++ dload_fill_bss);
++ goto loop_cont;
++ } /* if DS_DOWNLOAD_MASK */
++ /* If not loading, but BSS, zero initialize */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (curr_sect >= dlthis->allocated_secn_count)
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++
++ if (cinit_processed) {
++ /*Don't clear BSS after load-time initialization */
++ DL_ERROR(
++ "Zero-initialization at " FMT_UI32 " attempted after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr), lptr,
++ TADDR_TO_HOST(lptr->size), dload_fill_bss);
++loop_cont:
++ sptr += 1;
++ lptr += 1;
++ } /* load sections */
++} /* dload_data */
++
++/*************************************************************************
++ * Procedure dload_reorder
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be byte-swapped
++ * dsiz size of the data to be reordered in sizeof() units.
++ * map 32-bit map defining how to reorder the data. Value
++ * must be REORDER_MAP() of some permutation
++ * of 0x00 01 02 03
++ *
++ * Effect:
++ * Re-arranges the bytes in each word according to the map specified.
++ *
++ ************************************************************************/
++/* mask for byte shift count */
++#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
++
++void dload_reorder(void *data, int dsiz, unsigned int map)
++{
++ register u32 tmp, tmap, datv;
++ u32 *dp = (u32 *)data;
++
++ map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
++ do {
++ tmp = 0;
++ datv = *dp;
++ tmap = map;
++ do {
++ tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
++ tmap >>= BITS_PER_BYTE;
++ } while (datv >>= BITS_PER_BYTE);
++ *dp++ = tmp;
++ } while ((dsiz -= sizeof(u32)) > 0);
++} /* dload_reorder */
++
++/*************************************************************************
++ * Procedure dload_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block
++ *
++ ************************************************************************/
++u32 dload_checksum(void *data, unsigned siz)
++{
++ u32 sum;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++ for (left = siz; left > 0; left -= sizeof(u32))
++ sum += *dp++;
++ return sum;
++} /* dload_checksum */
++
++#if HOST_ENDIANNESS
++/*************************************************************************
++ * Procedure dload_reverse_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block, which is assumed to be bytes
++ * in big-endian order.
++ *
++ * Notes:
++ * In a big-endian host, things like the string table are stored as bytes
++ * in host order. But dllcreate always checksums in little-endian order.
++ * It is most efficient to just handle the difference a word at a time.
++ *
++ ***********************************************************************/
++u32 dload_reverse_checksum(void *data, unsigned siz)
++{
++ u32 sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 3;
++ sum += temp >> BITS_PER_BYTE * 3;
++ sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
++ sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
++ }
++
++ return sum;
++} /* dload_reverse_checksum */
++
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++u32 dload_reverse_checksum_16(void *data, unsigned siz)
++{
++ uint_fast32_t sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 2;
++ sum += temp >> BITS_PER_BYTE * 2;
++ }
++
++ return sum;
++} /* dload_reverse_checksum_16 */
++#endif
++#endif
++
++/*************************************************************************
++ * Procedure swap_words
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be swapped
++ * siz size of the data to be swapped.
++ * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
++ * 0 => 1 long
++ *
++ * Effect:
++ * Swaps the specified data according to the specified map
++ *
++ ************************************************************************/
++static void swap_words(void *data, unsigned siz, unsigned bitmap)
++{
++ register int i;
++#if TARGET_AU_BITS < 16
++ register u16 *sp;
++#endif
++ register u32 *lp;
++
++ siz /= sizeof(u16);
++
++#if TARGET_AU_BITS < 16
++ /* pass 1: do all the bytes */
++ i = siz;
++ sp = (u16 *) data;
++ do {
++ register u16 tmp;
++ tmp = *sp;
++ *sp++ = SWAP16BY8(tmp);
++ } while ((i -= 1) > 0);
++#endif
++
++#if TARGET_AU_BITS < 32
++ /* pass 2: fixup the 32-bit words */
++ i = siz >> 1;
++ lp = (u32 *) data;
++ do {
++ if ((bitmap & 1) == 0) {
++ register u32 tmp;
++ tmp = *lp;
++ *lp = SWAP32BY16(tmp);
++ }
++ lp += 1;
++ bitmap >>= 1;
++ } while ((i -= 1) > 0);
++#endif
++} /* swap_words */
++
++/*************************************************************************
++ * Procedure copy_tgt_strings
++ *
++ * Parameters:
++ * dstp Destination address. Assumed to be 32-bit aligned
++ * srcp Source address. Assumed to be 32-bit aligned
++ * charcount Number of characters to copy.
++ *
++ * Effect:
++ * Copies strings from the source (which is in usual .dof file order on
++ * the loading processor) to the destination buffer (which should be in proper
++ * target addressable unit order). Makes sure the last string in the
++ * buffer is NULL terminated (for safety).
++ * Returns the first unused destination address.
++ ************************************************************************/
++static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
++{
++ register TgtAU_t *src = (TgtAU_t *)srcp;
++ register TgtAU_t *dst = (TgtAU_t *)dstp;
++ register int cnt = charcount;
++ do {
++#if TARGET_AU_BITS <= BITS_PER_AU
++ /* byte-swapping issues may exist for strings on target */
++ *dst++ = *src++;
++#elif TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)
++ register TgtAU_t tmp;
++ tmp = *src++;
++ *dst++ = SWAP16BY8(tmp); /* right for TARGET_AU_BITS == 16 */
++#else
++ *dst++ = *src++;
++#endif
++ } while ((cnt -= (sizeof(TgtAU_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
++ /*apply force to make sure that the string table has null terminator */
++#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
++ dst[-1] = 0;
++#elif TARGET_BIG_ENDIAN
++ dst[-1] &= ~BYTE_MASK; /* big-endian */
++#else
++ dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1; /* little endian */
++#endif
++ return (char *)dst;
++} /* copy_tgt_strings */
++
++/*************************************************************************
++ * Procedure init_module_handle
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Initializes the module handle we use to enable unloading, and installs
++ * the debug information required by the target.
++ *
++ * Notes:
++ * The handle returned from Dynamic_Load_Module needs to encapsulate all the
++ * allocations done for the module, and enable them plus the modules symbols to
++ * be deallocated.
++ *
++ ************************************************************************/
++#ifndef _BIG_ENDIAN
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DBG_LIST_PAGE, DLOAD_DATA, 0 };
++#else
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DLOAD_DATA, DBG_LIST_PAGE, 0 };
++#endif
++static void init_module_handle(struct dload_state *dlthis)
++{
++ struct my_handle *hndl;
++ u16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct dll_module *dbmod;
++ struct dll_sect *dbsec;
++ struct dbg_mirror_root *mlist;
++ register char *cp;
++ struct modules_header mhdr;
++ struct LDR_SECTION_INFO dllview_info;
++ struct dynload_symbol *debug_mirror_sym;
++ hndl = dlthis->myhandle;
++ if (!hndl)
++ return; /* must be errors detected, so forget it */
++ hndl->secn_count = dlthis->allocated_secn_count << 1;
++#ifndef TARGET_ENDIANNESS
++ if (dlthis->big_e_target)
++ hndl->secn_count += 1; /* flag for big-endian */
++#endif
++ if (dlthis->dload_errcount)
++ return; /* abandon if errors detected */
++ /* Locate the symbol that names the header for the CCS debug list
++ of modules. If not found, we just don't generate the debug record.
++ If found, we create our modules list. We make sure to create the
++ LOADER_DLLVIEW_ROOT even if there is no relocation info to record,
++ just to try to put both symbols in the same symbol table and
++ module.*/
++ debug_mirror_sym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LOADER_DLLVIEW_ROOT);
++ if (!debug_mirror_sym) {
++ struct dynload_symbol *dlmodsym;
++ struct dbg_mirror_root *mlst;
++
++ /* our root symbol is not yet present;
++ check if we have DLModules defined */
++ dlmodsym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LINKER_MODULES_HEADER);
++ if (!dlmodsym)
++ return; /* no DLModules list so no debug info */
++ /* if we have DLModules defined, construct our header */
++ mlst = (struct dbg_mirror_root *)
++ dlthis->mysym->Allocate(dlthis->mysym,
++ sizeof(struct dbg_mirror_root));
++ if (!mlst) {
++ DL_ERROR(E_ALLOC, sizeof(struct dbg_mirror_root));
++ return;
++ }
++ mlst->hnext = NULL;
++ mlst->changes = 0;
++ mlst->refcount = 0;
++ mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
++ /* add our root symbol */
++ debug_mirror_sym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, LOADER_DLLVIEW_ROOT,
++ (unsigned)dlthis->myhandle);
++ if (!debug_mirror_sym) {
++ /* failed, recover memory */
++ dlthis->mysym->Deallocate(dlthis->mysym, mlst);
++ return;
++ }
++ debug_mirror_sym->value = (u32)mlst;
++ }
++ /* First create the DLLview record and stuff it into the buffer.
++ Then write it to the DSP. Record pertinent locations in our hndl,
++ and add it to the per-processor list of handles with debug info.*/
++#ifndef DEBUG_HEADER_IN_LOADER
++ mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
++ if (!mlist)
++ return;
++#else
++ mlist = (struct dbg_mirror_root *)&debug_list_header;
++#endif
++ hndl->dm.hroot = mlist; /* set pointer to root into our handle */
++ if (!dlthis->allocated_secn_count)
++ return; /* no load addresses to be recorded */
++ /* reuse temporary symbol storage */
++ dbmod = (struct dll_module *) dlthis->local_symtab;
++ /* Create the DLLview record in the memory we retain for our handle*/
++ dbmod->num_sects = dlthis->allocated_secn_count;
++ dbmod->timestamp = dlthis->verify.dv_timdat;
++ dbmod->version = INIT_VERSION;
++ dbmod->verification = VERIFICATION;
++ asecs = dlthis->ldr_sections;
++ dbsec = dbmod->sects;
++ for (curr_sect = dlthis->allocated_secn_count;
++ curr_sect > 0; curr_sect -= 1) {
++ dbsec->sect_load_adr = asecs->load_addr;
++ dbsec->sect_run_adr = asecs->run_addr;
++ dbsec += 1;
++ asecs += 1;
++ }
++ /* now cram in the names */
++ cp = copy_tgt_strings(dbsec, dlthis->str_head,
++ dlthis->debug_string_size);
++
++ /* round off the size of the debug record, and remember same */
++ hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
++ *cp = 0; /* strictly to make our test harness happy */
++ dllview_info = DLLVIEW_INFO_INIT;
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ /* Initialize memory context to default heap */
++ dllview_info.context = 0;
++ hndl->dm.context = 0;
++ /* fill in next pointer and size */
++ if (mlist->hnext) {
++ dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
++ dbmod->next_module_size = mlist->hnext->dm.dbsiz;
++ } else {
++ dbmod->next_module_size = 0;
++ dbmod->next_module = 0;
++ }
++ /* allocate memory for on-DSP DLLview debug record */
++ if (!dlthis->myalloc)
++ return;
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, &dllview_info,
++ HOST_TO_TADDR(sizeof(u32)))) {
++ return;
++ }
++ /* Store load address of .dllview section */
++ hndl->dm.dbthis = dllview_info.load_addr;
++ /* Store memory context (segid) in which .dllview section
++ * was allocated */
++ hndl->dm.context = dllview_info.context;
++ mlist->refcount += 1;
++ /* swap bytes in the entire debug record, but not the string table */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(dbmod, (char *)dbsec - (char *)dbmod,
++ DLL_MODULE_BITMAP);
++ }
++ /* Update the DLLview list on the DSP write new record */
++ if (!dlthis->myio->writemem(dlthis->myio, dbmod,
++ dllview_info.load_addr, &dllview_info,
++ TADDR_TO_HOST(dllview_info.size))) {
++ return;
++ }
++ /* write new header */
++ mhdr.first_module_size = hndl->dm.dbsiz;
++ mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ dllview_info = DLLVIEW_INFO_INIT;
++ if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(u16))) {
++ return;
++ }
++ /* Add the module handle to this processor's list
++ of handles with debug info */
++ hndl->dm.hnext = mlist->hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl;
++ hndl->dm.hprev = (struct my_handle *) mlist;
++ mlist->hnext = hndl; /* insert after root*/
++} /* init_module_handle */
++
++/*************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ ************************************************************************/
++int Dynamic_Unload_Module(DLOAD_mhandle mhandle,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init)
++{
++ s16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ struct dbg_mirror_root *root;
++ unsigned errcount = 0;
++ struct LDR_SECTION_INFO dllview_info = DLLVIEW_INFO_INIT;
++ struct modules_header mhdr;
++
++ hndl = (struct my_handle *)mhandle;
++ if (!hndl)
++ return 0; /* if handle is null, nothing to do */
++ /* Clear out the module symbols
++ * Note that if this is the module that defined MODULES_HEADER
++ (the head of the target debug list)
++ * then this operation will blow away that symbol.
++ It will therefore be impossible for subsequent
++ * operations to add entries to this un-referenceable list.*/
++ if (!syms)
++ return 1;
++ syms->Purge_Symbol_Table(syms, (unsigned) hndl);
++ /* Deallocate target memory for sections */
++ asecs = hndl->secns;
++ if (alloc)
++ for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
++ curr_sect -= 1) {
++ asecs->name = NULL;
++ alloc->Deallocate(alloc, asecs++);
++ }
++ root = hndl->dm.hroot;
++ if (!root) {
++ /* there is a debug list containing this module */
++ goto func_end;
++ }
++ if (!hndl->dm.dbthis) { /* target-side dllview record exists */
++ goto loop_end;
++ }
++ /* Retrieve memory context in which .dllview was allocated */
++ dllview_info.context = hndl->dm.context;
++ if (hndl->dm.hprev == hndl)
++ goto exitunltgt;
++
++ /* target-side dllview record is in list */
++ /* dequeue this record from our GPP-side mirror list */
++ hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
++ /* Update next_module of previous entry in target list
++ * We are using mhdr here as a surrogate for either a
++ struct modules_header or a dll_module */
++ if (hndl->dm.hnext) {
++ mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
++ mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
++ } else {
++ mhdr.first_module = 0;
++ mhdr.first_module_size = 0;
++ }
++ if (!init)
++ goto exitunltgt;
++
++ if (!init->connect(init)) {
++ dload_syms_error(syms, E_ICONNECT);
++ errcount += 1;
++ goto exitunltgt;
++ }
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ /* update change counter */
++ root->changes += 1;
++ if (!init->writemem(init, &(root->changes),
++ root->dbthis + HOST_TO_TADDR
++ (sizeof(mhdr.first_module) +
++ sizeof(mhdr.first_module_size)),
++ &dllview_info,
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ init->release(init);
++exitunltgt:
++ /* release target storage */
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ dllview_info.load_addr = hndl->dm.dbthis;
++ if (alloc)
++ alloc->Deallocate(alloc, &dllview_info);
++ root->refcount -= 1;
++ /* target-side dllview record exists */
++loop_end:
++#ifndef DEBUG_HEADER_IN_LOADER
++ if (root->refcount <= 0) {
++ /* if all references gone, blow off the header */
++ /* our root symbol may be gone due to the Purge above,
++ but if not, do not destroy the root */
++ if (syms->Find_Matching_Symbol
++ (syms, LOADER_DLLVIEW_ROOT) == NULL)
++ syms->Deallocate(syms, root);
++ }
++#endif
++func_end:
++ /* there is a debug list containing this module */
++ syms->Deallocate(syms, mhandle); /* release our storage */
++ return errcount;
++} /* Dynamic_Unload_Module */
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/*************************************************************************
++ * Procedure unpack_name
++ *
++ * Parameters:
++ * soffset Byte offset into the string table
++ *
++ * Effect:
++ * Returns a pointer to the string specified by the offset supplied, or
++ * NULL for error.
++ *
++ ************************************************************************/
++static char *unpack_name(struct dload_state *dlthis, u32 soffset)
++{
++ u8 tmp, *src;
++ char *dst;
++
++ if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
++ dload_error(dlthis, "Bad string table offset " FMT_UI32,
++ soffset);
++ return NULL;
++ }
++ src = (uint_least8_t *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ dst = dlthis->str_temp;
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE);
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++ dlthis->temp_len = dst - dlthis->str_temp;
++ /* squirrel away length including terminating null */
++ return dlthis->str_temp;
++} /* unpack_name */
++#endif
+diff --git a/drivers/dsp/bridge/dynload/dlclasses_hdr.h b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+new file mode 100644
+index 0000000..04f136e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+@@ -0,0 +1,41 @@
++/*
++ * dlclasses_hdr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DLCLASSES_HDR_H
++#define _DLCLASSES_HDR_H
++
++/*****************************************************************************
++ *****************************************************************************
++ *
++ * DLCLASSES_HDR.H
++ *
++ * Sample classes in support of the dynamic loader
++ *
++ * These are just concrete derivations of the virtual ones in dynamic_loader.h
++ * with a few additional interfaces for init, etc.
++ *****************************************************************************
++ *****************************************************************************/
++
++#include <dspbridge/dynamic_loader.h>
++
++#include "DLstream.h"
++#include "DLsymtab.h"
++#include "DLalloc.h"
++#include "DLinit.h"
++
++#endif /* _DLCLASSES_HDR_H */
+diff --git a/drivers/dsp/bridge/dynload/dload_internal.h b/drivers/dsp/bridge/dynload/dload_internal.h
+new file mode 100644
+index 0000000..78f5058
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dload_internal.h
+@@ -0,0 +1,237 @@
++/*
++ * dload_internal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __DLOAD_INTERNAL__
++#define __DLOAD_INTERNAL__
++
++#include <linux/types.h>
++
++/*
++ * Internal state definitions for the dynamic loader
++ */
++
++#define TRUE 1
++#define FALSE 0
++typedef int boolean;
++
++
++/* type used for relocation intermediate results */
++typedef s32 RVALUE;
++
++/* unsigned version of same; must have at least as many bits */
++typedef u32 URVALUE;
++
++/*
++ * Dynamic loader configuration constants
++ */
++/* error issued if input has more sections than this limit */
++#define REASONABLE_SECTION_LIMIT 100
++
++/* (Addressable unit) value used to clear BSS section */
++#define dload_fill_bss 0
++
++/*
++ * Reorder maps explained (?)
++ *
++ * The doff file format defines a 32-bit pattern used to determine the
++ * byte order of an image being read. That value is
++ * BYTE_RESHUFFLE_VALUE == 0x00010203
++ * For purposes of the reorder routine, we would rather have the all-is-OK
++ * for 32-bits pattern be 0x03020100. This first macro makes the
++ * translation from doff file header value to MAP value: */
++#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++/* This translation is made in dload_headers. Thereafter, the all-is-OK
++ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
++ * But sadly, not all bits of the doff file are 32-bit integers.
++ * The notable exceptions are strings and image bits.
++ * Strings obey host byte order: */
++#if defined(_BIG_ENDIAN)
++#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#else
++#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
++#endif
++/* Target bits consist of target AUs (could be bytes, or 16-bits,
++ * or 32-bits) stored as an array in host order. A target order
++ * map is defined by: */
++#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
++#define TARGET_ORDER(cookedmap) (cookedmap)
++#elif TARGET_AU_BITS > 8
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
++#else
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#endif
++
++/* forward declaration for handle returned by dynamic loader */
++struct my_handle;
++
++/*
++ * a list of module handles, which mirrors the debug list on the target
++ */
++struct dbg_mirror_root {
++ /* must be same as dbg_mirror_list; __DLModules address on target */
++ u32 dbthis;
++ struct my_handle *hnext; /* must be same as dbg_mirror_list */
++ u16 changes; /* change counter */
++ u16 refcount; /* number of modules referencing this root */
++} ;
++
++struct dbg_mirror_list {
++ u32 dbthis;
++ struct my_handle *hnext, *hprev;
++ struct dbg_mirror_root *hroot;
++ u16 dbsiz;
++ u32 context; /* Save context for .dllview memory allocation */
++} ;
++
++#define VARIABLE_SIZE 1
++/*
++ * the structure we actually return as an opaque module handle
++ */
++struct my_handle {
++ struct dbg_mirror_list dm; /* !!! must be first !!! */
++ /* sections following << 1, LSB is set for big-endian target */
++ u16 secn_count;
++ struct LDR_SECTION_INFO secns[VARIABLE_SIZE];
++} ;
++#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
++ sizeof(struct LDR_SECTION_INFO))
++/* real size of my_handle */
++
++/*
++ * reduced symbol structure used for symbols during relocation
++ */
++struct Local_Symbol {
++ s32 value; /* Relocated symbol value */
++ s32 delta; /* Original value in input file */
++ s16 secnn; /* section number */
++ s16 sclass; /* symbol class */
++} ;
++
++/*
++ * States of the .cinit state machine
++ */
++enum cinit_mode {
++ CI_count = 0, /* expecting a count */
++ CI_address, /* expecting an address */
++#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
++ CI_partaddress, /* have only part of the address */
++#endif
++ CI_copy, /* in the middle of copying data */
++ CI_done /* end of .cinit table */
++};
++
++/*
++ * The internal state of the dynamic loader, which is passed around as
++ * an object
++ */
++struct dload_state {
++ struct Dynamic_Loader_Stream *strm; /* The module input stream */
++ struct Dynamic_Loader_Sym *mysym; /* Symbols for this session */
++ struct Dynamic_Loader_Allocate *myalloc; /* target memory allocator */
++ struct Dynamic_Loader_Initialize *myio; /* target memory initializer */
++ unsigned myoptions; /* Options parameter Dynamic_Load_Module */
++
++ char *str_head; /* Pointer to string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ char *str_temp; /* Pointer to temporary buffer for strings */
++ /* big enough to hold longest string */
++ unsigned temp_len; /* length of last temporary string */
++ char *xstrings; /* Pointer to buffer for expanded */
++ /* strings for sec names */
++#endif
++ /* Total size of strings for DLLView section names */
++ unsigned debug_string_size;
++ /* Pointer to parallel section info for allocated sections only */
++ struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
++ struct LDR_SECTION_INFO *ldr_sections;
++#if TMS32060
++ /* The address of the start of the .bss section */
++ LDR_ADDR bss_run_base;
++#endif
++ struct Local_Symbol *local_symtab; /* Relocation symbol table */
++
++ /* pointer to DL section info for the section being relocated */
++ struct LDR_SECTION_INFO *image_secn;
++ /* change in run address for current section during relocation */
++ LDR_ADDR delta_runaddr;
++ LDR_ADDR image_offset; /* offset of current packet in section */
++ enum cinit_mode cinit_state; /* current state of cload_cinit() */
++ int cinit_count; /* the current count */
++ LDR_ADDR cinit_addr; /* the current address */
++ s16 cinit_page; /* the current page */
++ /* Handle to be returned by Dynamic_Load_Module */
++ struct my_handle *myhandle;
++ unsigned dload_errcount; /* Total # of errors reported so far */
++ /* Number of target sections that require allocation and relocation */
++ unsigned allocated_secn_count;
++#ifndef TARGET_ENDIANNESS
++ boolean big_e_target; /* Target data in big-endian format */
++#endif
++ /* map for reordering bytes, 0 if not needed */
++ u32 reorder_map;
++ struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
++ struct doff_verify_rec_t verify; /* Verify record */
++
++ int relstkidx; /* index into relocation value stack */
++ /* relocation value stack used in relexp.c */
++ RVALUE relstk[STATIC_EXPR_STK_SIZE];
++
++} ;
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
++#else
++#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
++#endif
++
++/*
++ * Exports from cload.c to rest of the world
++ */
++extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
++extern void dload_syms_error(struct Dynamic_Loader_Sym *syms,
++ const char *errtxt, ...);
++extern void dload_headers(struct dload_state *dlthis);
++extern void dload_strings(struct dload_state *dlthis, boolean sec_names_only);
++extern void dload_sections(struct dload_state *dlthis);
++extern void dload_reorder(void *data, int dsiz, u32 map);
++extern u32 dload_checksum(void *data, unsigned siz);
++
++#if HOST_ENDIANNESS
++extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++extern uint32_t dload_reverse_checksum_16(void *data, unsigned siz);
++#endif
++#endif
++
++#define is_data_scn(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
++#define is_data_scn_num(zzz) \
++ (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
++
++/*
++ * exported by reloc.c
++ */
++extern void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp);
++
++extern RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++extern int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++#endif /* __DLOAD_INTERNAL__ */
+diff --git a/drivers/dsp/bridge/dynload/doff.h b/drivers/dsp/bridge/dynload/doff.h
+new file mode 100644
+index 0000000..2b8fc37
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/doff.h
+@@ -0,0 +1,347 @@
++/*
++ * doff.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*****************************************************************************/
++/* DOFF.H - Structures & definitions used for dynamically */
++/* loaded modules file format. This format is a reformatted */
++/* version of COFF.(see coff.h for details) It optimizes the */
++/* layout for the dynamic loader. */
++/* */
++/* .dof files, when viewed as a sequence of 32-bit integers, look the same */
++/* on big-endian and little-endian machines. */
++/*****************************************************************************/
++#ifndef _DOFF_H
++#define _DOFF_H
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((u32)zzz)
++#endif
++
++#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
++
++/* DOFF file header containing fields categorizing the remainder of the file */
++struct doff_filehdr_t {
++
++ /* string table size, including filename, in bytes */
++ u32 df_strtab_size;
++
++ /* entry point if one exists */
++ u32 df_entrypt;
++
++ /* identifies byte ordering of file;
++ * always set to BYTE_RESHUFFLE_VALUE */
++ u32 df_byte_reshuffle;
++
++ /* Size of the string table up to and including the last section name */
++ /* Size includes the name of the COFF file also */
++ u32 df_scn_name_size;
++
++#ifndef _BIG_ENDIAN
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* length in bytes of the longest string, including terminating NULL */
++ /* excludes the name of the file */
++ u16 df_max_str_len;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* useful file flags */
++ u16 df_flags;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++#else
++ /* length of the longest string, including terminating NULL */
++ u16 df_max_str_len;
++
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++
++ /* useful file flags */
++ u16 df_flags;
++#endif
++ /* checksum for file header record */
++ u32 df_checksum;
++
++} ;
++
++/* flags in the df_flags field */
++#define DF_LITTLE 0x100
++#define DF_BIG 0x200
++#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
++
++/* Supported processors */
++#define TMS470_ID 0x97
++#define LEAD_ID 0x98
++#define TMS32060_ID 0x99
++#define LEAD3_ID 0x9c
++
++/* Primary processor for loading */
++#if TMS32060
++#define TARGET_ID TMS32060_ID
++#endif
++
++/* Verification record containing values used to test integrity of the bits */
++struct doff_verify_rec_t {
++
++ /* time and date stamp */
++ u32 dv_timdat;
++
++ /* checksum for all section records */
++ u32 dv_scn_rec_checksum;
++
++ /* checksum for string table */
++ u32 dv_str_tab_checksum;
++
++ /* checksum for symbol table */
++ u32 dv_sym_tab_checksum;
++
++ /* checksum for verification record */
++ u32 dv_verify_rec_checksum;
++
++} ;
++
++/* String table is an array of null-terminated strings. The first entry is
++ * the filename, which is added by DLLcreate. No new structure definitions
++ * are required.
++ */
++
++/* Section Records including information on the corresponding image packets */
++/*
++ * !!WARNING!!
++ *
++ * This structure is expected to match in form LDR_SECTION_INFO in
++ * dynamic_loader.h
++ */
++
++struct doff_scnhdr_t {
++
++ s32 ds_offset; /* offset into string table of name */
++ s32 ds_paddr; /* RUN address, in target AU */
++ s32 ds_vaddr; /* LOAD address, in target AU */
++ s32 ds_size; /* section size, in target AU */
++#ifndef _BIG_ENDIAN
++ u16 ds_page; /* memory page id */
++ u16 ds_flags; /* section flags */
++#else
++ u16 ds_flags; /* section flags */
++ u16 ds_page; /* memory page id */
++#endif
++ u32 ds_first_pkt_offset;
++ /* Absolute byte offset into the file */
++ /* where the first image record resides */
++
++ s32 ds_nipacks; /* number of image packets */
++
++};
++
++/* Symbol table entry */
++struct doff_syment_t {
++
++ s32 dn_offset; /* offset into string table of name */
++ s32 dn_value; /* value of symbol */
++#ifndef _BIG_ENDIAN
++ s16 dn_scnum; /* section number */
++ s16 dn_sclass; /* storage class */
++#else
++ s16 dn_sclass; /* storage class */
++ s16 dn_scnum; /* section number, 1-based */
++#endif
++
++} ;
++
++/* special values for dn_scnum */
++#define DN_UNDEF 0 /* undefined symbol */
++#define DN_ABS (-1) /* value of symbol is absolute */
++/* special values for dn_sclass */
++#define DN_EXT 2
++#define DN_STATLAB 20
++#define DN_EXTLAB 21
++
++/* Default value of image bits in packet */
++/* Configurable by user on the command line */
++#define IMAGE_PACKET_SIZE 1024
++
++/* An image packet contains a chunk of data from a section along with */
++/* information necessary for its processing. */
++struct image_packet_t {
++
++ s32 i_num_relocs; /* number of relocations for */
++ /* this packet */
++
++ s32 i_packet_size; /* number of bytes in array */
++ /* "bits" occupied by */
++ /* valid data. Could be */
++ /* < IMAGE_PACKET_SIZE to */
++ /* prevent splitting a */
++ /* relocation across packets. */
++ /* Last packet of a section */
++ /* will most likely contain */
++ /* < IMAGE_PACKET_SIZE bytes */
++ /* of valid data */
++
++ s32 i_checksum; /* Checksum for image packet */
++ /* and the corresponding */
++ /* relocation records */
++
++ u8 *i_bits; /* Actual data in section */
++
++};
++
++/* The relocation structure definition matches the COFF version. Offsets */
++/* however are relative to the image packet base not the section base. */
++struct reloc_record_t {
++
++ s32 r_vaddr;
++
++ /* expressed in target AUs */
++
++ union {
++ struct {
++#ifndef _BIG_ENDIAN
++ u8 _offset; /* bit offset of rel fld */
++ u8 _fieldsz; /* size of rel fld */
++ u8 _wordsz; /* # bytes containing rel fld */
++ u8 _dum1;
++ u16 _dum2;
++ u16 _type;
++#else
++ unsigned _dum1:8;
++ unsigned _wordsz:8; /* # bytes containing rel fld */
++ unsigned _fieldsz:8; /* size of rel fld */
++ unsigned _offset:8; /* bit offset of rel fld */
++ u16 _type;
++ u16 _dum2;
++#endif
++ } _r_field;
++
++ struct {
++ u32 _spc; /* image packet relative PC */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_spc;
++
++ struct {
++ u32 _uval; /* constant value */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_uval;
++
++ struct {
++ s32 _symndx; /* 32-bit sym tbl index */
++#ifndef _BIG_ENDIAN
++ u16 _disp; /* extra addr encode data */
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _disp; /* extra addr encode data */
++#endif
++ } _r_sym;
++ } _u_reloc;
++
++} ;
++
++/* abbreviations for convenience */
++#ifndef r_type
++#define r_type _u_reloc._r_sym._type
++#define r_uval _u_reloc._r_uval._uval
++#define r_symndx _u_reloc._r_sym._symndx
++#define r_offset _u_reloc._r_field._offset
++#define r_fieldsz _u_reloc._r_field._fieldsz
++#define r_wordsz _u_reloc._r_field._wordsz
++#define r_disp _u_reloc._r_sym._disp
++#endif
++
++/*****************************************************************************/
++/* */
++/* Important DOFF macros used for file processing */
++/* */
++/*****************************************************************************/
++
++/* DOFF Versions */
++#define DOFF0 0
++
++/* Return the address/size >= to addr that is at a 32-bit boundary */
++/* This assumes that a byte is 8 bits */
++#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
++
++/*****************************************************************************/
++/* */
++/* The DOFF section header flags field is laid out as follows: */
++/* */
++/* Bits 0-3 : Section Type */
++/* Bit 4 : Set when section requires target memory to be allocated by DL */
++/* Bit 5 : Set when section requires downloading */
++/* Bits 8-11: Alignment, same as COFF */
++/* */
++/*****************************************************************************/
++
++/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
++
++/* Macros to help processing of sections */
++#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
++
++/* DS_ALLOCATE indicates whether a section needs space on the target */
++#define DS_ALLOCATE_MASK 0x10
++#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
++
++/* DS_DOWNLOAD indicates that the loader needs to copy bits */
++#define DS_DOWNLOAD_MASK 0x20
++#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
++
++/* Section alignment requirement in AUs */
++#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
++
++#endif /* _DOFF_H */
+diff --git a/drivers/dsp/bridge/dynload/getsection.c b/drivers/dsp/bridge/dynload/getsection.c
+new file mode 100644
+index 0000000..78a301a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/getsection.c
+@@ -0,0 +1,412 @@
++/*
++ * getsection.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#include <dspbridge/getsection.h>
++#include "header.h"
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_SEEK[] = { "Set file position to %d failed" };
++static const char E_ISIZ[] = { "Bad image packet size %d" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++static const char E_RELOC[] = { "DLOAD_GetSection unable to read"
++ "sections containing relocation entries"};
++#if BITS_PER_AU > BITS_PER_BYTE
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_STBL[] = { "Bad string table offset " FMT_UI32 };
++#endif
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. These macros
++ * marks the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
++
++/***************************************************************/
++/********************* SUPPORT FUNCTIONS ***********************/
++/***************************************************************/
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/**************************************************************************
++ * Procedure unpack_sec_name
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ * soffset Byte offset into the string table
++ * dst Place to store the expanded string
++ *
++ * Effect:
++ * Stores a string from the string table into the destination, expanding
++ * it in the process. Returns a pointer just past the end of the stored
++ * string on success, or NULL on failure.
++ *
++ *************************************************************************/
++static char *unpack_sec_name(struct dload_state *dlthis,
++ u32 soffset, char *dst)
++{
++ u8 tmp, *src;
++
++ if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
++ dload_error(dlthis, E_STBL, soffset);
++ return NULL;
++ }
++ src = (u8 *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE)
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++
++ return dst;
++}
++
++/**************************************************************************
++ * Procedure expand_sec_names
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Allocates a buffer, unpacks and copies strings from string table into it.
++ * Stores a pointer to the buffer into a state variable.
++ **************************************************************************/
++static void expand_sec_names(struct dload_state *dlthis)
++{
++ char *xstrings, *curr, *next;
++ u32 xsize;
++ u16 sec;
++ struct LDR_SECTION_INFO *shp;
++ /* assume worst-case size requirement */
++ xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
++ xstrings = (char *)dlthis->mysym->Allocate(dlthis->mysym, xsize);
++ if (xstrings == NULL) {
++ dload_error(dlthis, E_ALLOC, xsize);
++ return;
++ }
++ dlthis->xstrings = xstrings;
++ /* For each sec, copy and expand its name */
++ curr = xstrings;
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
++ if (next == NULL)
++ break; /* error */
++ shp->name = curr;
++ curr = next;
++ }
++}
++
++#endif
++
++/***************************************************************/
++/********************* EXPORTED FUNCTIONS **********************/
++/***************************************************************/
++
++/**************************************************************************
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the
++ specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ **************************************************************************/
++DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms)
++{
++ struct dload_state *dlthis; /* internal state for this call */
++ unsigned *dp, sz;
++ u32 sec_start;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ u16 sec;
++#endif
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ if (syms != NULL)
++ dload_syms_error(syms, "Required parameter is NULL");
++
++ return NULL;
++ }
++
++ dlthis = (struct dload_state *)
++ syms->Allocate(syms, sizeof(struct dload_state));
++ if (!dlthis) {
++ /* not enough storage */
++ dload_syms_error(syms, "Can't allocate module info");
++ return NULL;
++ }
++
++ /* clear our internal state */
++ dp = (unsigned *)dlthis;
++ for (sz = sizeof(struct dload_state) / sizeof(unsigned);
++ sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ dlthis->strm = module;
++ dlthis->mysym = syms;
++
++ /* read in the doff image and store in our state variable */
++ dload_headers(dlthis);
++
++ if (!dlthis->dload_errcount)
++ dload_strings(dlthis, true);
++
++ /* skip ahead past the unread portion of the string table */
++ sec_start = sizeof(struct doff_filehdr_t) +
++ sizeof(struct doff_verify_rec_t) +
++ BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
++
++ if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
++ dload_error(dlthis, E_SEEK, sec_start);
++ return NULL;
++ }
++
++ if (!dlthis->dload_errcount)
++ dload_sections(dlthis);
++
++ if (dlthis->dload_errcount) {
++ DLOAD_module_close(dlthis); /* errors, blow off our state */
++ dlthis = NULL;
++ return NULL;
++ }
++#if BITS_PER_AU > BITS_PER_BYTE
++ /* Expand all section names from the string table into the */
++ /* state variable, and convert section names from a relative */
++ /* string table offset to a pointers to the expanded string. */
++ expand_sec_names(dlthis);
++#else
++ /* Convert section names from a relative string table offset */
++ /* to a pointer into the string table. */
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ struct LDR_SECTION_INFO *shp =
++ DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ shp->name = dlthis->str_head + *(u32 *)&shp->name;
++ }
++#endif
++
++ return dlthis;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be
++ * initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and initializes
++ * the provided struct LDR_SECTION_INFO pointer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSectionInfo(DLOAD_module_info minfo, const char *sectionName,
++ const struct LDR_SECTION_INFO **const sectionInfo)
++{
++ struct dload_state *dlthis;
++ struct LDR_SECTION_INFO *shp;
++ u16 sec;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ if (strcmp(sectionName, shp->name) == 0) {
++ *sectionInfo = shp;
++ return true;
++ }
++ }
++
++ return false;
++}
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++
++/**************************************************************************
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired
++ * section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo, void *sectionData)
++{
++ struct dload_state *dlthis;
++ u32 pos;
++ struct doff_scnhdr_t *sptr = NULL;
++ s32 nip;
++ struct image_packet_t ipacket;
++ s32 ipsize;
++ u32 checks;
++ s8 *dest = (s8 *)sectionData;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++ sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
++ if (sptr == NULL)
++ return false;
++
++ /* skip ahead to the start of the first packet */
++ pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
++ if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
++ dload_error(dlthis, E_SEEK, pos);
++ return false;
++ }
++
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* for each packet */
++ /* get the fixed header bits */
++ if (dlthis->strm->
++ read_buffer(dlthis->strm, &ipacket, IPH_SIZE) != IPH_SIZE) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
++
++ /* Now read the packet image bits. Note: round the size up to
++ * the next multiple of 4 bytes; this is what checksum
++ * routines want. */
++ ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ dload_error(dlthis, E_ISIZ, ipsize);
++ return false;
++ }
++ if (dlthis->strm->read_buffer
++ (dlthis->strm, dest, ipsize) != ipsize) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map)
++ dload_reorder(dest, ipsize, dlthis->reorder_map);
++
++ checks = dload_checksum(dest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order, not PC order */
++ dload_reorder(dest, ipsize,
++ TARGET_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(dest, ipsize);
++#else
++ checks = dload_reverse_checksum(dest, ipsize);
++#endif
++#endif
++ checks += dload_checksum(&ipacket, IPH_SIZE);
++
++ /* NYI: unable to handle relocation entries here. Reloc
++ * entries referring to fields that span the packet boundaries
++ * may result in packets of sizes that are not multiple of
++ * 4 bytes. Our checksum implementation works on 32-bit words
++ * only. */
++ if (ipacket.i_num_relocs != 0) {
++ dload_error(dlthis, E_RELOC, ipsize);
++ return false;
++ }
++
++ if (~checks) {
++ dload_error(dlthis, E_CHECKSUM, "image packet");
++ return false;
++ }
++
++ /*Advance destination ptr by the size of the just-read packet*/
++ dest += ipsize;
++ }
++
++ return true;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ **************************************************************************/
++void DLOAD_module_close(DLOAD_module_info minfo)
++{
++ struct dload_state *dlthis;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return;
++
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++ if (dlthis->sect_hdrs)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->sect_hdrs);
++
++#if BITS_PER_AU > BITS_PER_BYTE
++ if (dlthis->xstrings)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->xstrings);
++
++#endif
++
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis);
++}
+diff --git a/drivers/dsp/bridge/dynload/header.h b/drivers/dsp/bridge/dynload/header.h
+new file mode 100644
+index 0000000..0de744b
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/header.h
+@@ -0,0 +1,59 @@
++/*
++ * header.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#define TRUE 1
++#define FALSE 0
++#ifndef NULL
++#define NULL 0
++#endif
++
++#include <linux/string.h>
++#define DL_STRCMP strcmp
++
++/* maximum parenthesis nesting in relocation stack expressions */
++#define STATIC_EXPR_STK_SIZE 10
++
++#include <linux/types.h>
++typedef unsigned int uint_least32_t;
++typedef unsigned short int uint_least16_t;
++
++#include "doff.h"
++#include <dspbridge/dynamic_loader.h>
++#include "params.h"
++#include "dload_internal.h"
++#include "reloc_table.h"
++
++/*
++ * Plausibility limits
++ *
++ * These limits are imposed upon the input DOFF file as a check for validity.
++ * They are hard limits, in that the load will fail if they are exceeded.
++ * The numbers selected are arbitrary, in that the loader implementation does
++ * not require these limits.
++ */
++
++/* maximum number of bytes in string table */
++#define MAX_REASONABLE_STRINGTAB (0x100000)
++/* maximum number of code,data,etc. sections */
++#define MAX_REASONABLE_SECTIONS (200)
++/* maximum number of linker symbols */
++#define MAX_REASONABLE_SYMBOLS (100000)
++
++/* shift count to align F_BIG with DLOAD_LITTLE */
++#define ALIGN_COFF_ENDIANNESS 7
++#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
+diff --git a/drivers/dsp/bridge/dynload/module_list.h b/drivers/dsp/bridge/dynload/module_list.h
+new file mode 100644
+index 0000000..9c4876a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/module_list.h
+@@ -0,0 +1,161 @@
++/*
++ * dspbridge/mpu_driver/src/dynload/module_list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*============================================================================
++ Filename: module_list.h
++
++ Copyright (C) 2002 Texas Instruments Incorporated
++
++
++ This C header file gives the layout of the data structure created by the
++ dynamic loader to describe the set of modules loaded into the DSP.
++
++ Linked List Structure:
++ ----------------------
++ The data structure defined here is a singly-linked list. The list
++ represents the set of modules which are currently loaded in the DSP memory.
++ The first entry in the list is a header record which contains a flag
++ representing the state of the list. The rest of the entries in the list
++ are module records.
++
++ Global symbol _DLModules designates the first record in the list (i.e. the
++ header record). This symbol must be defined in any program that wishes to
++ use DLLview plug-in.
++
++ String Representation:
++ ----------------------
++ The string names of the module and its sections are stored in a block of
++ memory which follows the module record itself. The strings are ordered:
++ module name first, followed by section names in order from the first
++ section to the last. String names are tightly packed arrays of 8-bit
++ characters (two characters per 16-bit word on the C55x). Strings are
++ zero-byte-terminated.
++
++ Creating and updating the list:
++-------------------------------
++ Upon loading a new module into the DSP memory the dynamic loader inserts a
++new module record as the first module record in the list. The fields of
++ this module record are initialized to reflect the properties of the module.
++ The dynamic loader does NOT increment the flag/counter in the list's header
++ record.
++
++ Upon unloading a module from the DSP memory the dynamic loader removes the
++module's record from this list. The dynamic loader also increments the
++ flag/counter in the list's header record to indicate that the list has been
++ changed.
++
++============================================================================*/
++
++#ifndef _MODULE_LIST_H_
++#define _MODULE_LIST_H_
++
++#include <linux/types.h>
++
++/* Global pointer to the modules_header structure*/
++#define MODULES_HEADER "_DLModules"
++#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
++
++/* Initial version number*/
++#define INIT_VERSION 1
++
++/* Verification number -- to be recorded in each module record */
++#define VERIFICATION 0x79
++
++/* forward declarations */
++struct dll_module;
++struct dll_sect;
++
++/* the first entry in the list is the modules_header record;
++ * its address is contained in the global _DLModules pointer */
++struct modules_header {
++
++ /* Address of the first dll_module record in the list or NULL.
++ Note: for C55x this is a word address (C55x data is word-addressable)*/
++ u32 first_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this header record, or zero
++ * if the list is empty. This size includes the module's string table.
++ * Note: for C55x the unit is a 16-bit word */
++ u16 first_module_size;
++
++ /* Counter is incremented whenever a module record is removed from
++ * the list */
++ u16 update_flag;
++
++} ;
++
++/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define MODULES_HEADER_BITMAP 0x2 /* swapping bitmap for type modules_header */
++
++/* information recorded about each section in a module */
++struct dll_sect {
++
++ /* Load-time address of the section.
++ * Note: for C55x this is a byte address for program sections, and
++ * a word address for data sections. C55x program memory is
++ * byte-addressable, while data memory is word-addressable. */
++ u32 sect_load_adr;
++
++ /* Run-time address of the section.
++ * Note 1: for C55x this is a byte address for program sections, and
++ * a word address for data sections.
++ * Note 2: for C55x two most significant bits of this field indicate
++ * the section type: '00' for a code section, '11' for a data section
++ * (C55 addresses are really only 24-bits wide). */
++ u32 sect_run_adr;
++
++} ;
++
++/* the rest of the entries in the list are module records */
++struct dll_module {
++
++ /* Address of the next dll_module record in the list, or 0 if this is
++ * the last record in the list.
++ * Note: for C55x this is a word address (C55x data is
++ * word-addressable) */
++ u32 next_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this one, or zero if this is the
++ * last record in the list. This size includes the module's string
++ * table.
++ * Note: for C55x the unit is a 16-bit word. */
++ u16 next_module_size;
++
++ /* version number of the tooling; set to INIT_VERSION for Phase 1 */
++ u16 version;
++
++ /* the verification word; set to VERIFICATION */
++ u16 verification;
++
++ /* Number of sections in the sects array */
++ u16 num_sects;
++
++ /* Module's "unique" id; copy of the timestamp from the host
++ * COFF file */
++ u32 timestamp;
++
++ /* Array of num_sects elements of the module's section records */
++ struct dll_sect sects[1];
++} ;
++
++/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
++
++#endif /* _MODULE_LIST_H_ */
+diff --git a/drivers/dsp/bridge/dynload/params.h b/drivers/dsp/bridge/dynload/params.h
+new file mode 100644
+index 0000000..ade430d
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/params.h
+@@ -0,0 +1,231 @@
++/*
++ * params.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++/******************************************************************************
++ *
++ * This file defines host and target properties for all machines
++ * supported by the dynamic loader. To be tedious...
++ *
++ * host == the machine on which the dynamic loader runs
++ * target == the machine that the dynamic loader is loading
++ *
++ * Host and target may or may not be the same, depending upon the particular
++ * use.
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ * Host Properties
++ *
++ *****************************************************************************/
++
++#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
++#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
++#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
++
++#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
++#define BITS_PER_AU 16
++#define LOG_BITS_PER_AU 4
++ /* use this print string in error messages for uint32_t */
++#define FMT_UI32 "0x%lx"
++#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
++#else
++#define BITS_PER_AU 8 /* bits in the smallest addressable data storage unit */
++#define LOG_BITS_PER_AU 3 /* log base 2 of the same; useful for shift counts */
++#define FMT_UI32 "0x%x"
++#define FMT8_UI32 "%08x"
++#endif
++
++/* generic fastest method for swapping bytes and shorts */
++#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
++#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
++
++/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
++
++/******************************************************************************
++ *
++ * Target Properties
++ *
++ *****************************************************************************/
++
++
++/*--------------------------------------------------------------------------*/
++/* TMS320C6x Target Specific Parameters (byte-addressable) */
++/*--------------------------------------------------------------------------*/
++#if TMS32060
++#define MEMORG 0x0L /* Size of configured memory */
++#define MEMSIZE 0x0L /* (full address space) */
++
++#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
++#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
++#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
++#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
++ * are page number */
++
++#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
++
++#undef TARGET_ENDIANNESS /* may be big or little endian */
++
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
++#endif
++
++
++/*--------------------------------------------------------------------------
++ *
++ * DEFAULT SETTINGS and DERIVED PROPERTIES
++ *
++ * This section establishes defaults for values not specified above
++ *--------------------------------------------------------------------------*/
++#ifndef TARGET_AU_BITS
++#define TARGET_AU_BITS 8 /* width of the target addressable unit */
++#define LOG_TARGET_AU_BITS 3 /* log2 of same */
++#endif
++
++#ifndef CINIT_DEFAULT_PAGE
++#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
++#endif
++
++#ifndef DATA_RUN2LOAD
++#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
++#endif
++
++#ifndef DBG_LIST_PAGE
++#define DBG_LIST_PAGE 0 /* page number for .dllview section */
++#endif
++
++#ifndef TARGET_WORD_ALIGN
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (zz)
++#endif
++
++#ifndef TDATA_TO_TADDR
++#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
++#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
++#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
++#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
++#endif
++
++/*
++ *
++ * Useful properties and conversions derived from the above
++ *
++ */
++
++/*
++ * Conversions between host and target addresses
++ */
++#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
++/* translate target addressable unit to host address */
++#define TADDR_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TADDR(x) (x)
++#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
++#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#else
++#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#endif
++
++#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
++/* translate target addressable unit to host address */
++#define TDATA_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TDATA(x) (x)
++/* translate host address to target addressable unit, round up */
++#define HOST_TO_TDATA_ROUND(x) (x)
++/* byte offset to host offset, rounded up for TDATA size */
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
++#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#else
++#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA_ROUND(x) (((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
++ (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
++ -(TDATA_AU_BITS/BITS_PER_AU))
++#endif
++
++/*
++ * Input in DOFF format is always expresed in bytes, regardless of loading host
++ * so we wind up converting from bytes to target and host units even when the
++ * host is not a byte machine.
++ */
++#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) (x)
++#define BYTE_TO_HOST_ROUND(x) (x)
++#define HOST_TO_BYTE(x) (x)
++#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
++ (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
++/* translate target addressable unit to byte address */
++#define TADDR_TO_BYTE(x) (x)
++/* translate byte address to target addressable unit */
++#define BYTE_TO_TADDR(x) (x)
++#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
++#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#ifdef _BIG_ENDIAN
++#define HOST_ENDIANNESS 1
++#else
++#define HOST_ENDIANNESS 0
++#endif
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
++#elif HOST_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
++#else
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
++#endif
++
++/* the unit in which we process target image data */
++#if TARGET_AU_BITS <= 8
++typedef u8 TgtAU_t;
++#elif TARGET_AU_BITS <= 16
++typedef u16 TgtAU_t;
++#else
++typedef u32 TgtAU_t;
++#endif
++
++/* size of that unit */
++#if TARGET_AU_BITS < BITS_PER_AU
++#define TGTAU_BITS BITS_PER_AU
++#define LOG_TGTAU_BITS LOG_BITS_PER_AU
++#else
++#define TGTAU_BITS TARGET_AU_BITS
++#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
++#endif
+diff --git a/drivers/dsp/bridge/dynload/reloc.c b/drivers/dsp/bridge/dynload/reloc.c
+new file mode 100644
+index 0000000..54e460e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc.c
+@@ -0,0 +1,425 @@
++/*
++ * reloc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#if TMS32060
++/* the magic symbol for the start of BSS */
++static const char BSSSYMBOL[] = {".bss"};
++#endif
++
++#if TMS32060
++#include "reloc_table_c6000.c"
++#endif
++
++#if TMS32060
++/* From coff.h - ignore these relocation operations */
++#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
++#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
++#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
++#endif
++
++/**************************************************************************
++ * Procedure dload_unpack
++ *
++ * Parameters:
++ * data pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Extracts the specified field and returns it.
++ **************************************************************************/
++RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data, int fieldsz,
++ int offset, unsigned sgn)
++{
++ register RVALUE objval;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value*/
++ /* * collect up enough bits to contain the desired field */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++ objval = *dp >> offset;
++ shift = TGTAU_BITS - offset;
++ while (shift <= fieldsz) {
++ dp += direction;
++ objval += (RVALUE)*dp << shift;
++ shift += TGTAU_BITS;
++ }
++
++ /* * sign or zero extend the value appropriately */
++ if (sgn == ROP_UNS)
++ objval &= (2 << fieldsz) - 1;
++ else {
++ shift = sizeof(RVALUE) * BITS_PER_AU-1 - fieldsz;
++ objval = (objval << shift) >> shift;
++ }
++
++ return objval;
++
++} /* dload_unpack */
++
++
++/**************************************************************************
++ * Procedure dload_repack
++ *
++ * Parameters:
++ * val Value to insert
++ * data Pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Stuffs the specified value in the specified field. Returns 0 for
++ * success
++ * or 1 if the value will not fit in the specified field according to the
++ * specified signedness rule.
++ **************************************************************************/
++static const unsigned char ovf_limit[] = {1, 2, 2};
++int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn)
++{
++ register URVALUE objval, mask;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
++ /* clip the bits */
++ mask = ((UINT32_C(2) << fieldsz) - 1);
++ objval = (val & mask);
++ /* * store the bits through the specified mask */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++
++ /* insert LSBs */
++ *dp = (*dp & ~(mask << offset)) + (objval << offset);
++ shift = TGTAU_BITS-offset;
++ /* align mask and objval with AU boundary */
++ objval >>= shift;
++ mask >>= shift;
++
++ while (mask) {
++ dp += direction;
++ *dp = (*dp & ~mask) + objval;
++ objval >>= TGTAU_BITS;
++ mask >>= TGTAU_BITS;
++ }
++
++ /*
++ * check for overflow
++ */
++ if (sgn) {
++ unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
++ if (tmp > ovf_limit[sgn-1])
++ return 1;
++ }
++ return 0;
++
++} /* dload_repack */
++
++/* lookup table for the scaling amount in a C6x instruction */
++#if TMS32060
++#define SCALE_BITS 4 /* there are 4 bits in the scale field */
++#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
++static const u8 C60_Scale[SCALE_MASK+1] = {
++ 1, 0, 0, 0, 1, 1, 2, 2
++};
++#endif
++
++/**************************************************************************
++ * Procedure dload_relocate
++ *
++ * Parameters:
++ * data Pointer to base of image data
++ * rp Pointer to relocation operation
++ *
++ * Effect:
++ * Performs the specified relocation operation
++ **************************************************************************/
++void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp)
++{
++ RVALUE val = 0;
++ RVALUE reloc_amt = 0;
++ unsigned int fieldsz = 0;
++ unsigned int offset = 0;
++ unsigned int reloc_info = 0;
++ unsigned int reloc_action = 0;
++ register int rx = 0;
++ RVALUE *stackp = NULL;
++ int top;
++ struct Local_Symbol *svp = NULL;
++#ifdef RFV_SCALE
++ unsigned int scale = 0;
++#endif
++
++ rx = HASH_FUNC(rp->r_type);
++ while (rop_map1[rx] != rp->r_type) {
++ rx = HASH_L(rop_map2[rx]);
++ if (rx < 0) {
++#if TMS32060
++ switch (rp->r_type) {
++ case R_C60ALIGN:
++ case R_C60NOCMP:
++ case R_C60FPHEAD:
++ /* Ignore these reloc types and return */
++ break;
++ default:
++ /* Unknown reloc type, print error and return */
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++ }
++#else
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++#endif
++ return;
++ }
++ }
++ rx = HASH_I(rop_map2[rx]);
++ if ((rx < (sizeof(rop_action)/sizeof(uint_least16_t)))
++ && (rx < (sizeof(rop_info)/sizeof(uint_least16_t))) && (rx > 0)) {
++ reloc_action = rop_action[rx]; reloc_info = rop_info[rx];
++ } else {
++ dload_error(dlthis, "Buffer Overflow - Array Index Out of Bounds");
++ }
++
++ /* Compute the relocation amount for the referenced symbol, if any */
++ reloc_amt = rp->r_uval;
++ if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
++ if ((u32)rp->r_symndx < dlthis->dfile_hdr.df_no_syms) {
++ /* real symbol reference */
++ svp = &dlthis->local_symtab[rp->r_symndx];
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ svp->delta : svp->value;
++ }
++ /* reloc references current section */
++ else if (rp->r_symndx == -1)
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ dlthis->delta_runaddr : dlthis->image_secn->run_addr;
++ } /* relocation uses a symbol reference */
++ /* Handle stack adjustment */
++ val = 0;
++ top = RFV_STK(reloc_info);
++ if (top) {
++ top += dlthis->relstkidx - RSTK_UOP;
++ if (top >= STATIC_EXPR_STK_SIZE) {
++ dload_error(dlthis,
++ "Expression stack overflow in %s at offset "
++ FMT_UI32, dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ return;
++ }
++ val = dlthis->relstk[dlthis->relstkidx];
++ dlthis->relstkidx = top;
++ stackp = &dlthis->relstk[top];
++ }
++ /* Derive field position and size, if we need them */
++ if (reloc_info & ROP_RW) { /* read or write action in our future */
++ fieldsz = RFV_WIDTH(reloc_action);
++ if (fieldsz) { /* field info from table */
++ offset = RFV_POSN(reloc_action);
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ * address containing bits */
++ rp->r_vaddr += RFV_BIGOFF(reloc_info);
++ } else { /* field info from relocation op */
++ fieldsz = rp->r_fieldsz; offset = rp->r_offset;
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ address containing bits */
++ rp->r_vaddr += (rp->r_wordsz - offset - fieldsz)
++ >> LOG_TARGET_AU_BITS;
++ }
++ data = (TgtAU_t *)((char *)data + TADDR_TO_HOST(rp->r_vaddr));
++ /* compute lowest host location of referenced data */
++#if BITS_PER_AU > TARGET_AU_BITS
++ /* conversion from target address to host address may lose
++ address bits; add loss to offset */
++ if (TARGET_BIG_ENDIAN) {
++ offset += -((rp->r_vaddr << LOG_TARGET_AU_BITS) +
++ offset + fieldsz) &
++ (BITS_PER_AU-TARGET_AU_BITS);
++ } else {
++ offset += (rp->r_vaddr << LOG_TARGET_AU_BITS) &
++ (BITS_PER_AU-1);
++ }
++#endif
++#ifdef RFV_SCALE
++ scale = RFV_SCALE(reloc_info);
++#endif
++ }
++ /* read the object value from the current image, if so ordered */
++ if (reloc_info & ROP_R) { /* relocation reads current image value */
++ val = dload_unpack(dlthis, data, fieldsz, offset,
++ RFV_SIGN(reloc_info));
++#ifdef RFV_SCALE
++ val <<= scale;
++#endif
++ }
++ /* perform the necessary arithmetic */
++ switch (RFV_ACTION(reloc_action)) { /* relocation actions */
++ case RACT_VAL:
++ break;
++ case RACT_ASGN:
++ val = reloc_amt;
++ break;
++ case RACT_ADD:
++ val += reloc_amt;
++ break;
++ case RACT_PCR:
++ /*-----------------------------------------------------------
++ * Handle special cases of jumping from absolute sections
++ * (special reloc type) or to absolute destination
++ * (symndx == -1). In either case, set the appropriate
++ * relocation amount to 0.
++ *-----------------------------------------------------------*/
++ if (rp->r_symndx == -1)
++ reloc_amt = 0;
++ val += reloc_amt - dlthis->delta_runaddr;
++ break;
++ case RACT_ADDISP:
++ val += rp->r_disp + reloc_amt;
++ break;
++ case RACT_ASGPC:
++ val = dlthis->image_secn->run_addr + reloc_amt;
++ break;
++ case RACT_PLUS:
++ if (stackp != NULL)
++ val += *stackp;
++ break;
++ case RACT_SUB:
++ if (stackp != NULL)
++ val = *stackp - val;
++ break;
++ case RACT_NEG:
++ val = -val;
++ break;
++ case RACT_MPY:
++ if (stackp != NULL)
++ val *= *stackp;
++ break;
++ case RACT_DIV:
++ if (stackp != NULL)
++ val = *stackp / val;
++ break;
++ case RACT_MOD:
++ if (stackp != NULL)
++ val = *stackp % val;
++ break;
++ case RACT_SR:
++ if (val >= sizeof(RVALUE) * BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = (URVALUE)*stackp >> val;
++ break;
++ case RACT_ASR:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = sizeof(RVALUE)*BITS_PER_AU - 1;
++ else if (stackp != NULL)
++ val = *stackp >> val;
++ break;
++ case RACT_SL:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = *stackp << val;
++ break;
++ case RACT_AND:
++ if (stackp != NULL)
++ val &= *stackp;
++ break;
++ case RACT_OR:
++ if (stackp != NULL)
++ val |= *stackp;
++ break;
++ case RACT_XOR:
++ if (stackp != NULL)
++ val ^= *stackp;
++ break;
++ case RACT_NOT:
++ val = ~val;
++ break;
++#if TMS32060
++ case RACT_C6SECT:
++ /* actually needed address of secn containing symbol */
++ if (svp != NULL) {
++ if (rp->r_symndx >= 0)
++ if (svp->secnn > 0)
++ reloc_amt = dlthis->ldr_sections
++ [svp->secnn-1].run_addr;
++ }
++ /* !!! FALL THRU !!! */
++ case RACT_C6BASE:
++ if (dlthis->bss_run_base == 0) {
++ struct dynload_symbol *symp;
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, BSSSYMBOL);
++ /* lookup value of global BSS base */
++ if (symp)
++ dlthis->bss_run_base = symp->value;
++ else
++ dload_error(dlthis,
++ "Global BSS base referenced in %s offset"\
++ FMT_UI32 " but not defined",
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ }
++ reloc_amt -= dlthis->bss_run_base;
++ /* !!! FALL THRU !!! */
++ case RACT_C6DSPL:
++ /* scale factor determined by 3 LSBs of field */
++ scale = C60_Scale[val & SCALE_MASK];
++ offset += SCALE_BITS;
++ fieldsz -= SCALE_BITS;
++ val >>= SCALE_BITS; /* ignore the scale field hereafter */
++ val <<= scale;
++ val += reloc_amt; /* do the usual relocation */
++ if (((1 << scale)-1) & val)
++ dload_error(dlthis,
++ "Unaligned reference in %s offset " FMT_UI32,
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ break;
++#endif
++ } /* relocation actions */
++ /* * Put back result as required */
++ if (reloc_info & ROP_W) { /* relocation writes image value */
++#ifdef RFV_SCALE
++ val >>= scale;
++#endif
++ if (dload_repack(dlthis, val, data, fieldsz, offset,
++ RFV_SIGN(reloc_info))) {
++ dload_error(dlthis, "Relocation value " FMT_UI32
++ " overflows %d bits in %s offset " FMT_UI32, val,
++ fieldsz, dlthis->image_secn->name,
++ dlthis->image_offset + rp->r_vaddr);
++ }
++ } else if (top)
++ *stackp = val;
++} /* reloc_value */
++
+diff --git a/drivers/dsp/bridge/dynload/reloc_table.h b/drivers/dsp/bridge/dynload/reloc_table.h
+new file mode 100644
+index 0000000..6326146
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table.h
+@@ -0,0 +1,102 @@
++/*
++ * reloc_table.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __RELOC_TABLE_H__
++#define __RELOC_TABLE_H__
++/*
++ * Table of relocation operator properties
++ */
++#include <linux/types.h>
++
++/* How does this relocation operation access the program image? */
++#define ROP_N 0 /* does not access image */
++#define ROP_R 1 /* read from image */
++#define ROP_W 2 /* write to image */
++#define ROP_RW 3 /* read from and write to image */
++
++/* For program image access, what are the overflow rules for the bit field? */
++/* Beware! Procedure repack depends on this encoding */
++#define ROP_ANY 0 /* no overflow ever, just truncate the value */
++#define ROP_SGN 1 /* signed field */
++#define ROP_UNS 2 /* unsigned field */
++#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
++
++/* How does the relocation operation use the symbol reference */
++#define ROP_IGN 0 /* no symbol is referenced */
++#define ROP_LIT 0 /* use rp->r_uval literal field */
++#define ROP_SYM 1 /* symbol value is used in relocation */
++#define ROP_SYMD 2 /* delta value vs last link is used */
++
++/* How does the reloc op use the stack? */
++#define RSTK_N 0 /* Does not use */
++#define RSTK_POP 1 /* Does a POP */
++#define RSTK_UOP 2 /* Unary op, stack position unaffected */
++#define RSTK_PSH 3 /* Does a push */
++
++/*
++ * Computational actions performed by the dynamic loader
++ */
++enum Dload_Actions {
++ RACT_VAL, /* don't alter the current val (from stack or mem fetch) */
++ RACT_ASGN, /* set value to reference amount (from symbol reference) */
++ RACT_ADD, /* add reference to value */
++ RACT_PCR, /* add reference minus PC delta to value */
++ RACT_ADDISP, /* add reference plus r_disp */
++ RACT_ASGPC, /* set value to section address plus reference */
++
++ RACT_PLUS, /* stack + */
++ RACT_SUB, /* stack - */
++ RACT_NEG, /* stack unary - */
++
++ RACT_MPY, /* stack * */
++ RACT_DIV, /* stack / */
++ RACT_MOD, /* stack % */
++
++ RACT_SR, /* stack unsigned >> */
++ RACT_ASR, /* stack signed >> */
++ RACT_SL, /* stack << */
++ RACT_AND, /* stack & */
++ RACT_OR, /* stack | */
++ RACT_XOR, /* stack ^ */
++ RACT_NOT, /* stack ~ */
++ RACT_C6SECT, /* for C60 R_SECT op */
++ RACT_C6BASE, /* for C60 R_BASE op */
++ RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
++ RACT_PCR23T /* for ARM Thumb long branch */
++};
++
++/*
++ * macros used to extract values
++ */
++#define RFV_POSN(aaa) ((aaa) & 0xF)
++#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
++#define RFV_ACTION(aaa) ((aaa) >> 10)
++
++#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
++#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
++#define RFV_STK(iii) (((iii) >> 6) & 0x3)
++#define RFV_ACCS(iii) ((iii) & 0x3)
++
++#if (TMS32060)
++#define RFV_SCALE(iii) ((iii) >> 11)
++#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
++#else
++#define RFV_BIGOFF(iii) ((iii) >> 8)
++#endif
++
++#endif /* __RELOC_TABLE_H__ */
+diff --git a/drivers/dsp/bridge/dynload/reloc_table_c6000.c b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+new file mode 100644
+index 0000000..978834c
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+@@ -0,0 +1,258 @@
++/*
++ * reloc_table_c6000.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/* Tables generated for c6000 */
++
++#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
++#define HASH_L(zz) ((zz) >> 8)
++#define HASH_I(zz) ((zz) & 0xFF)
++
++static const u16 rop_map1[] = {
++ 0,
++ 1,
++ 2,
++ 20,
++ 4,
++ 5,
++ 6,
++ 15,
++ 80,
++ 81,
++ 82,
++ 83,
++ 84,
++ 85,
++ 86,
++ 87,
++ 17,
++ 18,
++ 19,
++ 21,
++ 16,
++ 16394,
++ 16404,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 32,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 40,
++ 112,
++ 113,
++ 65535,
++ 16384,
++ 16385,
++ 16386,
++ 16387,
++ 16388,
++ 16389,
++ 16390,
++ 16391,
++ 16392,
++ 16393,
++ 16395,
++ 16396,
++ 16397,
++ 16398,
++ 16399,
++ 16400,
++ 16401,
++ 16402,
++ 16403,
++ 16405,
++ 16406,
++ 65535,
++ 65535,
++ 65535
++};
++
++static const s16 rop_map2[] = {
++ -256,
++ -255,
++ -254,
++ -245,
++ -253,
++ -252,
++ -251,
++ -250,
++ -241,
++ -240,
++ -239,
++ -238,
++ -237,
++ -236,
++ 1813,
++ 5142,
++ -248,
++ -247,
++ 778,
++ -244,
++ -249,
++ -221,
++ -211,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -243,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -242,
++ -233,
++ -232,
++ -1,
++ -231,
++ -230,
++ -229,
++ -228,
++ -227,
++ -226,
++ -225,
++ -224,
++ -223,
++ 5410,
++ -220,
++ -219,
++ -218,
++ -217,
++ -216,
++ -215,
++ -214,
++ -213,
++ 5676,
++ -210,
++ -209,
++ -1,
++ -1,
++ -1
++};
++
++static const u16 rop_action[] = {
++ 2560,
++ 2304,
++ 2304,
++ 2432,
++ 2432,
++ 2560,
++ 2176,
++ 2304,
++ 2560,
++ 3200,
++ 3328,
++ 3584,
++ 3456,
++ 2304,
++ 4208,
++ 20788,
++ 21812,
++ 3415,
++ 3245,
++ 2311,
++ 4359,
++ 19764,
++ 2311,
++ 3191,
++ 3280,
++ 6656,
++ 7680,
++ 8704,
++ 9728,
++ 10752,
++ 11776,
++ 12800,
++ 13824,
++ 14848,
++ 15872,
++ 16896,
++ 17920,
++ 18944,
++ 0,
++ 0,
++ 0,
++ 0,
++ 1536,
++ 1536,
++ 1536,
++ 5632,
++ 512,
++ 0
++};
++
++static const u16 rop_info[] = {
++ 0,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 39,
++ 39,
++ 39,
++ 39,
++ 35,
++ 34,
++ 283,
++ 299,
++ 4135,
++ 4391,
++ 291,
++ 33059,
++ 283,
++ 295,
++ 4647,
++ 4135,
++ 64,
++ 64,
++ 128,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 128,
++ 201,
++ 197,
++ 74,
++ 70,
++ 208,
++ 196,
++ 200,
++ 192,
++ 192,
++ 66
++};
+diff --git a/drivers/dsp/bridge/gen/_gt_para.c b/drivers/dsp/bridge/gen/_gt_para.c
+new file mode 100644
+index 0000000..181fe41
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/_gt_para.c
+@@ -0,0 +1,107 @@
++/*
++ * _gt_para.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _gt_para.c ========
++ * Description:
++ * Configuration parameters for GT. This file is separated from
++ * gt.c so that GT_assert() can reference the error function without
++ * forcing the linker to include all the code for GT_set(), GT_init(),
++ * etc. into a fully bound image. Thus, GT_assert() can be retained in
++ * a program for which GT_?trace() has been compiled out.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 03-Jul-2001 rr: Removed kfuncs.h because of build errors.
++ *! 07-Dec-1999 ag: Fxn error now causes a WinCE DebugBreak;
++ *! 30-Aug-1999 ag: Now uses GP_printf for printf and error.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Function Prototypes */
++static void error(char *msg, ...);
++static s32 GT_nop(void);
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++struct GT_Config _GT_params = {
++ (Fxn) printk, /* printf */
++ (Fxn) NULL, /* procid */
++ (Fxn) GT_nop, /* taskid */
++ (Fxn) error, /* error */
++};
++
++/* ----------------------------------- Globals */
++struct GT_Config *GT = &_GT_params;
++
++/*
++ * ======== GT_nop ========
++ */
++static s32 GT_nop(void)
++{
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints error onto the standard output.
++ */
++static void error(char *fmt, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++
++ va_list va;
++
++ va_start(va, fmt);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ printk("ERROR: ");
++ printk(fmt, arg1, arg2, arg3, arg4, arg5, arg6);
++
++#if defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)
++ if (in_interrupt()) {
++ printk(KERN_INFO "Not stopping after error since ISR/DPC "
++ "are disabled\n");
++ } else {
++ set_current_state(TASK_INTERRUPTIBLE);
++ flush_signals(current);
++ schedule();
++ flush_signals(current);
++ printk(KERN_INFO "Signaled in error function\n");
++ }
++#endif
++}
+diff --git a/drivers/dsp/bridge/gen/gb.c b/drivers/dsp/bridge/gen/gb.c
+new file mode 100644
+index 0000000..1d21e97
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gb.c
+@@ -0,0 +1,182 @@
++/*
++ * gb.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gb.c ========
++ * Description: Generic bitmap operations.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 vp Code review updates.
++ *! 17-Dec-2002 map Fixed GB_minset(), GB_empty(), and GB_full(),
++ *! to ensure only 'len' bits are considered in the map
++ *! 18-Oct-2002 sb Ported to Linux platform.
++ *! 06-Dec-2001 jeh Fixed bug in GB_minclear().
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <linux/types.h>
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++#include <dspbridge/gb.h>
++
++typedef GB_BitNum GB_WordNum;
++
++struct GB_TMap {
++ GB_BitNum len;
++ GB_WordNum wcnt;
++ u32 *words;
++};
++
++/*
++ * ======== GB_clear ========
++ * purpose:
++ * Clears a bit in the bit map.
++ */
++
++void GB_clear(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] &= ~mask;
++}
++
++/*
++ * ======== GB_create ========
++ * purpose:
++ * Creates a bit map.
++ */
++
++struct GB_TMap *GB_create(GB_BitNum len)
++{
++ struct GB_TMap *map;
++ GB_WordNum i;
++ map = (struct GB_TMap *)GS_alloc(sizeof(struct GB_TMap));
++ if (map != NULL) {
++ map->len = len;
++ map->wcnt = len / BITS_PER_LONG + 1;
++ map->words = (u32 *)GS_alloc(map->wcnt * sizeof(u32));
++ if (map->words != NULL) {
++ for (i = 0; i < map->wcnt; i++)
++ map->words[i] = 0L;
++
++ } else {
++ GS_frees(map, sizeof(struct GB_TMap));
++ map = NULL;
++ }
++ }
++
++ return map;
++}
++
++/*
++ * ======== GB_delete ========
++ * purpose:
++ * Frees a bit map.
++ */
++
++void GB_delete(struct GB_TMap *map)
++{
++ GS_frees(map->words, map->wcnt * sizeof(u32));
++ GS_frees(map, sizeof(struct GB_TMap));
++}
++
++/*
++ * ======== GB_findandset ========
++ * purpose:
++ * Finds a free bit and sets it.
++ */
++GB_BitNum GB_findandset(struct GB_TMap *map)
++{
++ GB_BitNum bitn;
++
++ bitn = GB_minclear(map);
++
++ if (bitn != GB_NOBITS)
++ GB_set(map, bitn);
++
++ return bitn;
++}
++
++/*
++ * ======== GB_minclear ========
++ * purpose:
++ * returns the location of the first unset bit in the bit map.
++ */
++GB_BitNum GB_minclear(struct GB_TMap *map)
++{
++ GB_BitNum bit_location = 0;
++ GB_BitNum bitAcc = 0;
++ GB_WordNum i;
++ GB_BitNum bit;
++ u32 *word;
++
++ for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
++ if (~*word) {
++ for (bit = 0; bit < BITS_PER_LONG; bit++, bitAcc++) {
++ if (bitAcc == map->len)
++ return GB_NOBITS;
++
++ if (~*word & (1L << bit)) {
++ bit_location = i * BITS_PER_LONG + bit;
++ return bit_location;
++ }
++
++ }
++ } else {
++ bitAcc += BITS_PER_LONG;
++ }
++ }
++
++ return GB_NOBITS;
++}
++
++/*
++ * ======== GB_set ========
++ * purpose:
++ * Sets a bit in the bit map.
++ */
++
++void GB_set(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] |= mask;
++}
++
++/*
++ * ======== GB_test ========
++ * purpose:
++ * Returns true if the bit is set in the specified location.
++ */
++
++bool GB_test(struct GB_TMap *map, GB_BitNum bitn)
++{
++ bool state;
++ u32 mask;
++ u32 word;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ word = map->words[bitn / BITS_PER_LONG];
++ state = word & mask ? TRUE : FALSE;
++
++ return state;
++}
+diff --git a/drivers/dsp/bridge/gen/gh.c b/drivers/dsp/bridge/gen/gh.c
+new file mode 100644
+index 0000000..a20ae16
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gh.c
+@@ -0,0 +1,191 @@
++/*
++ * gh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.c ========
++ */
++
++#include <dspbridge/std.h>
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/gs.h>
++
++#include <dspbridge/gh.h>
++
++struct Elem {
++ struct Elem *next;
++ u8 data[1];
++};
++
++struct GH_THashTab {
++ u16 maxBucket;
++ u16 valSize;
++ struct Elem **buckets;
++ u16(*hash) (void *, u16);
++ bool(*match) (void *, void *);
++ void(*delete) (void *);
++};
++
++static void Nop(void *p);
++static s32 curInit;
++static void myfree(void *ptr, s32 size);
++
++/*
++ * ======== GH_create ========
++ */
++
++struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash)(void *, u16), bool(*match)(void *, void *),
++ void(*delete)(void *))
++{
++ struct GH_THashTab *hashTab;
++ u16 i;
++ hashTab = (struct GH_THashTab *)GS_alloc(sizeof(struct GH_THashTab));
++ if (hashTab == NULL)
++ return NULL;
++ hashTab->maxBucket = maxBucket;
++ hashTab->valSize = valSize;
++ hashTab->hash = hash;
++ hashTab->match = match;
++ hashTab->delete = delete == NULL ? Nop : delete;
++
++ hashTab->buckets = (struct Elem **)
++ GS_alloc(sizeof(struct Elem *) * maxBucket);
++ if (hashTab->buckets == NULL) {
++ GH_delete(hashTab);
++ return NULL;
++ }
++
++ for (i = 0; i < maxBucket; i++)
++ hashTab->buckets[i] = NULL;
++
++ return hashTab;
++}
++
++/*
++ * ======== GH_delete ========
++ */
++void GH_delete(struct GH_THashTab *hashTab)
++{
++ struct Elem *elem, *next;
++ u16 i;
++
++ if (hashTab != NULL) {
++ if (hashTab->buckets != NULL) {
++ for (i = 0; i < hashTab->maxBucket; i++) {
++ for (elem = hashTab->buckets[i]; elem != NULL;
++ elem = next) {
++ next = elem->next;
++ (*hashTab->delete) (elem->data);
++ myfree(elem, sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ }
++ }
++
++ myfree(hashTab->buckets, sizeof(struct Elem *)
++ * hashTab->maxBucket);
++ }
++
++ myfree(hashTab, sizeof(struct GH_THashTab));
++ }
++}
++
++/*
++ * ======== GH_exit ========
++ */
++
++void GH_exit(void)
++{
++ if (curInit-- == 1)
++ GS_exit();
++
++}
++
++/*
++ * ======== GH_find ========
++ */
++
++void *GH_find(struct GH_THashTab *hashTab, void *key)
++{
++ struct Elem *elem;
++
++ elem = hashTab->buckets[(*hashTab->hash)(key, hashTab->maxBucket)];
++
++ for (; elem; elem = elem->next) {
++ if ((*hashTab->match)(key, elem->data))
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== GH_init ========
++ */
++
++void GH_init(void)
++{
++ if (curInit++ == 0)
++ GS_init();
++}
++
++/*
++ * ======== GH_insert ========
++ */
++
++void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value)
++{
++ struct Elem *elem;
++ u16 i;
++ char *src, *dst;
++
++ elem = (struct Elem *)GS_alloc(sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ if (elem != NULL) {
++
++ dst = (char *)elem->data;
++ src = (char *)value;
++ for (i = 0; i < hashTab->valSize; i++)
++ *dst++ = *src++;
++
++ i = (*hashTab->hash)(key, hashTab->maxBucket);
++ elem->next = hashTab->buckets[i];
++ hashTab->buckets[i] = elem;
++
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== Nop ========
++ */
++/* ARGSUSED */
++static void Nop(void *p)
++{
++ p = p; /* stifle compiler warning */
++}
++
++/*
++ * ======== myfree ========
++ */
++static void myfree(void *ptr, s32 size)
++{
++ GS_free(ptr);
++}
+diff --git a/drivers/dsp/bridge/gen/gs.c b/drivers/dsp/bridge/gen/gs.c
+new file mode 100644
+index 0000000..ef5f923
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gs.c
+@@ -0,0 +1,108 @@
++/*
++ * gs.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gs.c ========
++ * Description:
++ * General storage memory allocator services.
++ *
++ *! Revision History
++ *! ================
++ *! 29-Sep-1999 ag: Un-commented MEM_Init in GS_init().
++ *! 14-May-1997 mg: Modified to use new GS API for GS_free() and GS_frees().
++ *! 06-Nov-1996 gp: Re-commented MEM_Init in GS_init(). GS needs GS_Exit().
++ *! 21-Oct-1996 db: Un-commented MEM_Init in GS_init().
++ *! 21-May-1996 mg: Created from original stdlib implementation.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <linux/types.h>
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++
++/* ----------------------------------- Globals */
++static u32 cumsize;
++
++/*
++ * ======== GS_alloc ========
++ * purpose:
++ * Allocates memory of the specified size.
++ */
++void *GS_alloc(u32 size)
++{
++ void *p;
++
++ p = MEM_Calloc(size, MEM_PAGED);
++ if (p == NULL)
++ return NULL;
++ cumsize += size;
++ return p;
++}
++
++/*
++ * ======== GS_exit ========
++ * purpose:
++ * Discontinue the usage of the GS module.
++ */
++void GS_exit(void)
++{
++ MEM_Exit();
++}
++
++/*
++ * ======== GS_free ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_free(void *ptr)
++{
++ MEM_Free(ptr);
++ /* ack! no size info */
++ /* cumsize -= size; */
++}
++
++/*
++ * ======== GS_frees ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_frees(void *ptr, u32 size)
++{
++ MEM_Free(ptr);
++ cumsize -= size;
++}
++
++/*
++ * ======== GS_init ========
++ * purpose:
++ * Initializes the GS module.
++ */
++void GS_init(void)
++{
++ static bool curInit;
++
++ if (curInit == false) {
++ curInit = true;
++
++ MEM_Init();
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/gt.c b/drivers/dsp/bridge/gen/gt.c
+new file mode 100644
+index 0000000..452d6e6
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gt.c
+@@ -0,0 +1,348 @@
++/*
++ * gt.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.c ========
++ * Description: This module implements the trace mechanism for bridge.
++ *
++ *! Revision History
++ *! ================
++ *! 16-May-1997 dr Changed GT_Config member names to conform to coding
++ *! standards.
++ *! 23-Apr-1997 ge Check for GT->TIDFXN for NULL before calling it.
++ *! 03-Jan-1997 ge Changed GT_Config structure member names to eliminate
++ *! preprocessor confusion with other macros.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gt.h>
++
++#define GT_WILD '*'
++
++#define GT_CLEAR '='
++#define GT_ON '+'
++#define GT_OFF '-'
++
++enum GT_State {
++ GT_SEP,
++ GT_FIRST,
++ GT_SECOND,
++ GT_OP,
++ GT_DIGITS
++} ;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_1format = "%s - %d: ";
++static char *GT_2format = "%s - %d(%d): ";
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static unsigned char *GT_tMask[GT_BOUND];
++
++static bool curInit;
++static char *separator;
++static unsigned char tabMem[GT_BOUND][sizeof(unsigned char) * GT_BOUND];
++
++static void error(char *string);
++static void setMask(s16 index1, s16 index2, char op, unsigned char mask);
++
++/*
++ * ======== _GT_create ========
++ * purpose:
++ * Creates GT mask.
++ */
++void _GT_create(struct GT_Mask *mask, char *modName)
++{
++ mask->modName = modName;
++ mask->flags = &(GT_tMask[modName[0] - 'A'][modName[1] - 'A']);
++}
++
++/*
++ * ======== GT_init ========
++ * purpose:
++ * Initializes GT module.
++ */
++#ifdef GT_init
++#undef GT_init
++#endif
++void GT_init(void)
++{
++ register unsigned char index1;
++ register unsigned char index2;
++
++ if (!curInit) {
++ curInit = true;
++
++ separator = " ,;/";
++
++ for (index1 = 0; index1 < GT_BOUND; index1++) {
++ GT_tMask[index1] = tabMem[index1];
++ for (index2 = 0; index2 < GT_BOUND; index2++) {
++ /* no tracing */
++ GT_tMask[index1][index2] = 0x00;
++ }
++ }
++ }
++}
++
++/*
++ * ======== _GT_set ========
++ * purpose:
++ * Sets the trace string format.
++ */
++
++void _GT_set(char *str)
++{
++ enum GT_State state;
++ char *sep;
++ s16 index1 = GT_BOUND; /* indicates all values */
++ s16 index2 = GT_BOUND; /* indicates all values */
++ char op = GT_CLEAR;
++ bool maskValid;
++ s16 digit;
++ register unsigned char mask = 0x0; /* no tracing */
++
++ if (str == NULL)
++ return;
++
++ maskValid = false;
++ state = GT_SEP;
++ while (*str != '\0') {
++ switch ((s32) state) {
++ case (s32) GT_SEP:
++ maskValid = false;
++ sep = separator;
++ while (*sep != '\0') {
++ if (*str == *sep) {
++ str++;
++ break;
++ } else {
++ sep++;
++ }
++ }
++ if (*sep == '\0')
++ state = GT_FIRST;
++
++ break;
++ case (s32) GT_FIRST:
++ if (*str == GT_WILD) {
++ /* indicates all values */
++ index1 = GT_BOUND;
++ /* indicates all values */
++ index2 = GT_BOUND;
++ state = GT_OP;
++ } else {
++ if (*str >= 'a')
++ index1 = (s16) (*str - 'a');
++ else
++ index1 = (s16) (*str - 'A');
++ if ((index1 >= 0) && (index1 < GT_BOUND))
++ state = GT_SECOND;
++ else
++ state = GT_SEP;
++ }
++ str++;
++ break;
++ case (s32) GT_SECOND:
++ if (*str == GT_WILD) {
++ index2 = GT_BOUND; /* indicates all values */
++ state = GT_OP;
++ str++;
++ } else {
++ if (*str >= 'a')
++ index2 = (s16) (*str - 'a');
++ else
++ index2 = (s16) (*str - 'A');
++ if ((index2 >= 0) && (index2 < GT_BOUND)) {
++ state = GT_OP;
++ str++;
++ } else {
++ state = GT_SEP;
++ }
++ }
++ break;
++ case (s32) GT_OP:
++ op = *str;
++ mask = 0x0; /* no tracing */
++ switch (op) {
++ case (s32) GT_CLEAR:
++ maskValid = true;
++ case (s32) GT_ON:
++ case (s32) GT_OFF:
++ state = GT_DIGITS;
++ str++;
++ break;
++ default:
++ state = GT_SEP;
++ break;
++ }
++ break;
++ case (s32) GT_DIGITS:
++ digit = (s16) (*str - '0');
++ if ((digit >= 0) && (digit <= 7)) {
++ mask |= (0x01 << digit);
++ maskValid = true;
++ str++;
++ } else {
++ if (maskValid == true) {
++ setMask(index1, index2, op, mask);
++ maskValid = false;
++ }
++ state = GT_SEP;
++ }
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++
++ if (maskValid)
++ setMask(index1, index2, op, mask);
++}
++
++/*
++ * ======== _GT_trace ========
++ * purpose:
++ * Prints the input string onto standard output
++ */
++
++s32 _GT_trace(struct GT_Mask *mask, char *format, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, format);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++#ifdef DEBUG
++ if (GT->PIDFXN == NULL) {
++ printk(GT_1format, mask->modName, GT->TIDFXN ?
++ (*GT->TIDFXN)() : 0);
++ } else {
++ printk(GT_2format, mask->modName, (*GT->PIDFXN)(),
++ GT->TIDFXN ? (*GT->TIDFXN)() : 0);
++ }
++#endif
++ printk(format, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints errors onto the standard output.
++ */
++static void error(char *string)
++{
++ printk("GT: %s", string);
++}
++
++/*
++ * ======== setmask ========
++ * purpose:
++ * Sets mask for the GT module.
++ */
++
++static void setMask(s16 index1, s16 index2, char op, u8 mask)
++{
++ register s16 index;
++
++ if (index1 < GT_BOUND) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ for (index2--; index2 >= 0; index2--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ } else {
++ for (index1--; index1 >= 0; index1--) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ index = GT_BOUND;
++ for (index--; index >= 0; index--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index] &=
++ ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ }
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/uuidutil.c b/drivers/dsp/bridge/gen/uuidutil.c
+new file mode 100644
+index 0000000..a45f448
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/uuidutil.c
+@@ -0,0 +1,238 @@
++/*
++ * uuidutil.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.c ========
++ * Description:
++ * This file contains the implementation of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2003 vp: Ported to Linux platform.
++ *! 31-Aug-2000 rr: UUID_UuidFromString bug fixed.
++ *! 29-Aug-2000 rr: Modified UUID_UuidFromString.
++ *! 09-Nov-2000 kc: Modified UUID_UuidFromString to simplify implementation.
++ *! 30-Oct-2000 kc: Modified UUID utility module function prefix.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/uuidutil.h>
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a struct DSP_UUID to a string.
++ * Note: snprintf format specifier is:
++ * %[flags] [width] [.precision] [{h | l | I64 | L}]type
++ */
++void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ IN s32 size)
++{
++ s32 i; /* return result from snprintf. */
++
++ DBC_Require(pUuid && pszUuid);
++
++ i = snprintf(pszUuid, size,
++ "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
++ pUuid->ulData1, pUuid->usData2, pUuid->usData3,
++ pUuid->ucData4, pUuid->ucData5, pUuid->ucData6[0],
++ pUuid->ucData6[1], pUuid->ucData6[2], pUuid->ucData6[3],
++ pUuid->ucData6[4], pUuid->ucData6[5]);
++
++ DBC_Ensure(i != -1);
++}
++
++/*
++ * ======== htoi ========
++ * Purpose:
++ * Converts a hex value to a decimal integer.
++ */
++
++static int htoi(char c)
++{
++ switch (c) {
++ case '0':
++ return 0;
++ case '1':
++ return 1;
++ case '2':
++ return 2;
++ case '3':
++ return 3;
++ case '4':
++ return 4;
++ case '5':
++ return 5;
++ case '6':
++ return 6;
++ case '7':
++ return 7;
++ case '8':
++ return 8;
++ case '9':
++ return 9;
++ case 'A':
++ return 10;
++ case 'B':
++ return 11;
++ case 'C':
++ return 12;
++ case 'D':
++ return 13;
++ case 'E':
++ return 14;
++ case 'F':
++ return 15;
++ case 'a':
++ return 10;
++ case 'b':
++ return 11;
++ case 'c':
++ return 12;
++ case 'd':
++ return 13;
++ case 'e':
++ return 14;
++ case 'f':
++ return 15;
++ }
++ return 0;
++}
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts a string to a struct DSP_UUID.
++ */
++void UUID_UuidFromString(IN char *pszUuid, OUT struct DSP_UUID *pUuid)
++{
++ char c;
++ s32 i, j;
++ s32 result;
++ char *temp = pszUuid;
++
++ result = 0;
++ for (i = 0; i < 8; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ulData1 = result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData2 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData3 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData4 = (u8)result;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData5 = (u8)result;
++
++ /* Step over underscore */
++ temp++;
++
++ for (j = 0; j < 6; j++) {
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData6[j] = (u8)result;
++ }
++}
+diff --git a/drivers/dsp/bridge/hw/EasiGlobal.h b/drivers/dsp/bridge/hw/EasiGlobal.h
+new file mode 100644
+index 0000000..b023826
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/EasiGlobal.h
+@@ -0,0 +1,42 @@
++/*
++ * EasiGlobal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef __EASIGLOBAL_H
++#define __EASIGLOBAL_H
++#include <linux/types.h>
++
++/*
++ * DEFINE: READ_ONLY, WRITE_ONLY & READ_WRITE
++ *
++ * DESCRIPTION: Defines used to describe register types for EASI-checker tests.
++ */
++
++#define READ_ONLY 1
++#define WRITE_ONLY 2
++#define READ_WRITE 3
++
++/*
++ * MACRO: _DEBUG_LEVEL_1_EASI
++ *
++ * DESCRIPTION: A MACRO which can be used to indicate that a particular beach
++ * register access function was called.
++ *
++ * NOTE: We currently dont use this functionality.
++ */
++#define _DEBUG_LEVEL_1_EASI(easiNum) ((void)0)
++
++#endif /* __EASIGLOBAL_H */
++
+diff --git a/drivers/dsp/bridge/hw/GlobalTypes.h b/drivers/dsp/bridge/hw/GlobalTypes.h
+new file mode 100644
+index 0000000..9004a37
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/GlobalTypes.h
+@@ -0,0 +1,325 @@
++/*
++ * GlobalTypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== GlobalTypes.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __GLOBALTYPES_H
++#define __GLOBALTYPES_H
++
++/*
++ * Definition: TRUE, FALSE
++ *
++ * DESCRIPTION: Boolean Definitions
++ */
++#ifndef TRUE
++#define FALSE 0
++#define TRUE (!(FALSE))
++#endif
++
++/*
++ * Definition: NULL
++ *
++ * DESCRIPTION: Invalid pointer
++ */
++#ifndef NULL
++#define NULL (void *)0
++#endif
++
++/*
++ * Definition: RET_CODE_BASE
++ *
++ * DESCRIPTION: Base value for return code offsets
++ */
++#define RET_CODE_BASE 0
++
++/*
++ * Definition: *BIT_OFFSET
++ *
++ * DESCRIPTION: offset in bytes from start of 32-bit word.
++ */
++#define LOWER_16BIT_OFFSET 0
++#define UPPER_16BIT_OFFSET 2
++
++#define LOWER_8BIT_OFFSET 0
++#define LOWER_MIDDLE_8BIT_OFFSET 1
++#define UPPER_MIDDLE_8BIT_OFFSET 2
++#define UPPER_8BIT_OFFSET 3
++
++#define LOWER_8BIT_OF16_OFFSET 0
++#define UPPER_8BIT_OF16_OFFSET 1
++
++/*
++ * Definition: *BIT_SHIFT
++ *
++ * DESCRIPTION: offset in bits from start of 32-bit word.
++ */
++#define LOWER_16BIT_SHIFT 0
++#define UPPER_16BIT_SHIFT 16
++
++#define LOWER_8BIT_SHIFT 0
++#define LOWER_MIDDLE_8BIT_SHIFT 8
++#define UPPER_MIDDLE_8BIT_SHIFT 16
++#define UPPER_8BIT_SHIFT 24
++
++#define LOWER_8BIT_OF16_SHIFT 0
++#define UPPER_8BIT_OF16_SHIFT 8
++
++
++/*
++ * Definition: LOWER_16BIT_MASK
++ *
++ * DESCRIPTION: 16 bit mask used for inclusion of lower 16 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_16BIT_MASK 0x0000FFFF
++
++
++/*
++ * Definition: LOWER_8BIT_MASK
++ *
++ * DESCRIPTION: 8 bit masks used for inclusion of 8 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_8BIT_MASK 0x000000FF
++
++/*
++ * Definition: RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given a 16 bit lower value and a 16
++ * bit upper value
++ */
++#define RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits,upper16Bits)\
++ (((((u32)lower16Bits) & LOWER_16BIT_MASK)) | \
++ (((((u32)upper16Bits) & LOWER_16BIT_MASK) << UPPER_16BIT_SHIFT)))
++
++/*
++ * Definition: RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 16 bit value given a 8 bit lower value and a 8
++ * bit upper value
++ */
++#define RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower8Bits,upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) << UPPER_8BIT_OF16_SHIFT)))
++
++/*
++ * Definition: RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,
++ * lowerUpper8Bits, upper8Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given four 8 bit values
++ */
++#define RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,\
++ lowerUpper8Bits, upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)lowerMiddle8Bits) & LOWER_8BIT_MASK) <<\
++ LOWER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)lowerUpper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_8BIT_SHIFT)))
++
++/*
++ * Definition: READ_LOWER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_LOWER_16BITS_OF_32(value32bits)\
++ ((u16)((u32)(value32bits) & LOWER_16BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_UPPER_16BITS_OF_32(value32bits)\
++ (((u16)((u32)(value32bits) >> UPPER_16BIT_SHIFT)) &\
++ LOWER_16BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 32bit value
++ */
++#define READ_LOWER_8BITS_OF_32(value32bits)\
++ ((u8)((u32)(value32bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_UPPER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 32bit value
++ */
++#define READ_UPPER_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_16(value16bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 16bit value
++ */
++#define READ_LOWER_8BITS_OF_16(value16bits)\
++ ((u8)((u16)(value16bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_16(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 16bit value
++ */
++#define READ_UPPER_8BITS_OF_16(value16bits)\
++ (((u8)((u32)(value16bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++
++/* UWORD16: 16 bit tpyes */
++
++
++/* REG_UWORD8, REG_WORD8: 8 bit register types */
++typedef volatile unsigned char REG_UWORD8;
++typedef volatile signed char REG_WORD8;
++
++/* REG_UWORD16, REG_WORD16: 16 bit register types */
++#ifndef OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++typedef volatile short REG_WORD16;
++
++/* REG_UWORD32, REG_WORD32: 32 bit register types */
++typedef volatile unsigned long REG_UWORD32;
++
++/* FLOAT
++ *
++ * Type to be used for floating point calculation. Note that floating point
++ * calculation is very CPU expensive, and you should only use if you
++ * absolutely need this. */
++
++
++/* boolean_t: Boolean Type True, False */
++/* ReturnCode_t: Return codes to be returned by all library functions */
++typedef enum ReturnCode_label {
++ RET_OK = 0,
++ RET_FAIL = -1,
++ RET_BAD_NULL_PARAM = -2,
++ RET_PARAM_OUT_OF_RANGE = -3,
++ RET_INVALID_ID = -4,
++ RET_EMPTY = -5,
++ RET_FULL = -6,
++ RET_TIMEOUT = -7,
++ RET_INVALID_OPERATION = -8,
++
++ /* Add new error codes at end of above list */
++
++ RET_NUM_RET_CODES /* this should ALWAYS be LAST entry */
++} ReturnCode_t, *pReturnCode_t;
++
++/* MACRO: RD_MEM_8, WR_MEM_8
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_8(addr) ((u8)(*((u8 *)(addr))))
++#define WR_MEM_8(addr, data) (*((u8 *)(addr)) = (u8)(data))
++
++/* MACRO: RD_MEM_8_VOLATILE, WR_MEM_8_VOLATILE
++ *
++ * DESCRIPTION: 8 bit register access macros
++ */
++#define RD_MEM_8_VOLATILE(addr) ((u8)(*((REG_UWORD8 *)(addr))))
++#define WR_MEM_8_VOLATILE(addr, data) (*((REG_UWORD8 *)(addr)) = (u8)(data))
++
++
++/*
++ * MACRO: RD_MEM_16, WR_MEM_16
++ *
++ * DESCRIPTION: 16 bit memory access macros
++ */
++#define RD_MEM_16(addr) ((u16)(*((u16 *)(addr))))
++#define WR_MEM_16(addr, data) (*((u16 *)(addr)) = (u16)(data))
++
++/*
++ * MACRO: RD_MEM_16_VOLATILE, WR_MEM_16_VOLATILE
++ *
++ * DESCRIPTION: 16 bit register access macros
++ */
++#define RD_MEM_16_VOLATILE(addr) ((u16)(*((REG_UWORD16 *)(addr))))
++#define WR_MEM_16_VOLATILE(addr, data) (*((REG_UWORD16 *)(addr)) =\
++ (u16)(data))
++
++/*
++ * MACRO: RD_MEM_32, WR_MEM_32
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_32(addr) ((u32)(*((u32 *)(addr))))
++#define WR_MEM_32(addr, data) (*((u32 *)(addr)) = (u32)(data))
++
++/*
++ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
++ *
++ * DESCRIPTION: 32 bit register access macros
++ */
++#define RD_MEM_32_VOLATILE(addr) ((u32)(*((REG_UWORD32 *)(addr))))
++#define WR_MEM_32_VOLATILE(addr, data) (*((REG_UWORD32 *)(addr)) =\
++ (u32)(data))
++
++/* Not sure if this all belongs here */
++
++#define CHECK_RETURN_VALUE(actualValue, expectedValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET(actualValue, expectedValue, returnCodeIfMismatch)
++#define CHECK_RETURN_VALUE_RES(actualValue, expectedValue, spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET_VOID(actualValue, expectedValue,\
++ spyCodeIfMisMatch)
++
++#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch)
++
++#endif /* __GLOBALTYPES_H */
+diff --git a/drivers/dsp/bridge/hw/IPIAccInt.h b/drivers/dsp/bridge/hw/IPIAccInt.h
+new file mode 100644
+index 0000000..b88a58c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IPIAccInt.h
+@@ -0,0 +1,41 @@
++/*
++ * IPIAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _IPI_ACC_INT_H
++#define _IPI_ACC_INT_H
++
++/* Bitfield mask and offset declarations */
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++#define SYSC_IVA2BOOTADDR_MASK 0xfffffc00
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum IPIIPI_SYSCONFIGAutoIdleE {
++ IPIIPI_SYSCONFIGAutoIdleclkfree = 0x0000,
++ IPIIPI_SYSCONFIGAutoIdleautoclkgate = 0x0001
++} ;
++
++enum IPIIPI_ENTRYElemSizeValueE {
++ IPIIPI_ENTRYElemSizeValueElemSz8b = 0x0000,
++ IPIIPI_ENTRYElemSizeValueElemSz16b = 0x0001,
++ IPIIPI_ENTRYElemSizeValueElemSz32b = 0x0002,
++ IPIIPI_ENTRYElemSizeValueReserved = 0x0003
++} ;
++
++#endif /* _IPI_ACC_INT_H */
++/* EOF */
+diff --git a/drivers/dsp/bridge/hw/IVA2RegAcM.h b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+new file mode 100644
+index 0000000..6c1e300
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+@@ -0,0 +1,28 @@
++/*
++ * IVA1RegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _IVA2_REG_ACM_H
++#define _IVA2_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++
++#endif
+diff --git a/drivers/dsp/bridge/hw/MLBAccInt.h b/drivers/dsp/bridge/hw/MLBAccInt.h
+new file mode 100644
+index 0000000..7a03c6a
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBAccInt.h
+@@ -0,0 +1,132 @@
++/*
++ * MLBAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MLB_ACC_INT_H
++#define _MLB_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32 (MLB_BASE_EASIL1 + 3)
++#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32 (MLB_BASE_EASIL1 + 4)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32 (MLB_BASE_EASIL1 + 7)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32 (MLB_BASE_EASIL1 + 17)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
++ (MLB_BASE_EASIL1 + 33)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32 (MLB_BASE_EASIL1 + 39)
++#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32 (MLB_BASE_EASIL1 + 44)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 50)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32 \
++ (MLB_BASE_EASIL1 + 51)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 56)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
++ (MLB_BASE_EASIL1 + 57)
++#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32 \
++ (MLB_BASE_EASIL1 + 60)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 62)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 63)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 192)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 193)
++
++/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (u32)(0x0040)
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MESSAGE___REGSET_0_15 */
++
++#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (u32)(0x0080)
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (u32)(0x00c0)
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MSGSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (u32)(0x0100)
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQSTATUS___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (u32)(0x0104)
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQENABLE___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (u32)(0x0)
++
++
++/* Register offset address definitions */
++
++#define MLB_MAILBOX_SYSCONFIG_OFFSET (u32)(0x10)
++#define MLB_MAILBOX_SYSSTATUS_OFFSET (u32)(0x14)
++
++
++/* Bitfield mask and offset declarations */
++
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (u32)(0x18)
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (u32)(3)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (u32)(0x2)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (u32)(1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (u32)(0)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (u32)(0)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (u32)(0x1)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (u32)(0)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (u32)(0x7f)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (u32)(0)
++
++#endif /* _MLB_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MLBRegAcM.h b/drivers/dsp/bridge/hw/MLBRegAcM.h
+new file mode 100644
+index 0000000..747a2e1
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBRegAcM.h
+@@ -0,0 +1,200 @@
++/*
++ * MLBRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MLB_REG_ACM_H
++#define _MLB_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++#include "MLBAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+ \
++ MLB_MAILBOX_SYSCONFIG_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress)) +\
++ offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSSTATUSResetDoneRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
++
++
++#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
++ (bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
++ ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
++
++
++#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MLB_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/MMUAccInt.h b/drivers/dsp/bridge/hw/MMUAccInt.h
+new file mode 100644
+index 0000000..6ca1573
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMUAccInt.h
+@@ -0,0 +1,76 @@
++/*
++ * MMUAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MMU_ACC_INT_H
++#define _MMU_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MMUMMU_SYSCONFIGReadRegister32 (MMU_BASE_EASIL1 + 3)
++#define EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32 (MMU_BASE_EASIL1 + 17)
++#define EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32 (MMU_BASE_EASIL1 + 39)
++#define EASIL1_MMUMMU_IRQSTATUSWriteRegister32 (MMU_BASE_EASIL1 + 51)
++#define EASIL1_MMUMMU_IRQENABLEReadRegister32 (MMU_BASE_EASIL1 + 102)
++#define EASIL1_MMUMMU_IRQENABLEWriteRegister32 (MMU_BASE_EASIL1 + 103)
++#define EASIL1_MMUMMU_WALKING_STTWLRunningRead32 (MMU_BASE_EASIL1 + 156)
++#define EASIL1_MMUMMU_CNTLTWLEnableRead32 (MMU_BASE_EASIL1 + 174)
++#define EASIL1_MMUMMU_CNTLTWLEnableWrite32 (MMU_BASE_EASIL1 + 180)
++#define EASIL1_MMUMMU_CNTLMMUEnableWrite32 (MMU_BASE_EASIL1 + 190)
++#define EASIL1_MMUMMU_FAULT_ADReadRegister32 (MMU_BASE_EASIL1 + 194)
++#define EASIL1_MMUMMU_TTBWriteRegister32 (MMU_BASE_EASIL1 + 198)
++#define EASIL1_MMUMMU_LOCKReadRegister32 (MMU_BASE_EASIL1 + 203)
++#define EASIL1_MMUMMU_LOCKWriteRegister32 (MMU_BASE_EASIL1 + 204)
++#define EASIL1_MMUMMU_LOCKBaseValueRead32 (MMU_BASE_EASIL1 + 205)
++#define EASIL1_MMUMMU_LOCKCurrentVictimRead32 (MMU_BASE_EASIL1 + 209)
++#define EASIL1_MMUMMU_LOCKCurrentVictimWrite32 (MMU_BASE_EASIL1 + 211)
++#define EASIL1_MMUMMU_LOCKCurrentVictimSet32 (MMU_BASE_EASIL1 + 212)
++#define EASIL1_MMUMMU_LD_TLBReadRegister32 (MMU_BASE_EASIL1 + 213)
++#define EASIL1_MMUMMU_LD_TLBWriteRegister32 (MMU_BASE_EASIL1 + 214)
++#define EASIL1_MMUMMU_CAMWriteRegister32 (MMU_BASE_EASIL1 + 226)
++#define EASIL1_MMUMMU_RAMWriteRegister32 (MMU_BASE_EASIL1 + 268)
++#define EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32 (MMU_BASE_EASIL1 + 322)
++
++/* Register offset address definitions */
++#define MMU_MMU_SYSCONFIG_OFFSET 0x10
++#define MMU_MMU_IRQSTATUS_OFFSET 0x18
++#define MMU_MMU_IRQENABLE_OFFSET 0x1c
++#define MMU_MMU_WALKING_ST_OFFSET 0x40
++#define MMU_MMU_CNTL_OFFSET 0x44
++#define MMU_MMU_FAULT_AD_OFFSET 0x48
++#define MMU_MMU_TTB_OFFSET 0x4c
++#define MMU_MMU_LOCK_OFFSET 0x50
++#define MMU_MMU_LD_TLB_OFFSET 0x54
++#define MMU_MMU_CAM_OFFSET 0x58
++#define MMU_MMU_RAM_OFFSET 0x5c
++#define MMU_MMU_GFLUSH_OFFSET 0x60
++#define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64
++/* Bitfield mask and offset declarations */
++#define MMU_MMU_SYSCONFIG_IdleMode_MASK 0x18
++#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET 3
++#define MMU_MMU_SYSCONFIG_AutoIdle_MASK 0x1
++#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET 0
++#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
++#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET 0
++#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
++#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
++#define MMU_MMU_CNTL_MMUEnable_MASK 0x2
++#define MMU_MMU_CNTL_MMUEnable_OFFSET 1
++#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
++#define MMU_MMU_LOCK_BaseValue_OFFSET 10
++#define MMU_MMU_LOCK_CurrentVictim_MASK 0x3f0
++#define MMU_MMU_LOCK_CurrentVictim_OFFSET 4
++
++#endif /* _MMU_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MMURegAcM.h b/drivers/dsp/bridge/hw/MMURegAcM.h
+new file mode 100644
+index 0000000..e46fdcb
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMURegAcM.h
+@@ -0,0 +1,253 @@
++/*
++ * MMURegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MMU_REG_ACM_H
++#define _MMU_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "MMUAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++
++#define MMUMMU_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_SYSCONFIG_OFFSET))
++
++
++#define MMUMMU_SYSCONFIGIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_IdleMode_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_IdleMode_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_IdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQSTATUSReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQSTATUS_OFFSET))
++
++
++#define MMUMMU_IRQSTATUSWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQENABLEReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQENABLE_OFFSET))
++
++
++#define MMUMMU_IRQENABLEWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_WALKING_STTWLRunningRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_WALKING_STTWLRunningRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_WALKING_ST_OFFSET))))\
++ & MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
++ MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_CNTL_OFFSET)))) &\
++ MMU_MMU_CNTL_TWLEnable_MASK) >>\
++ MMU_MMU_CNTL_TWLEnable_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_CNTLMMUEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLMMUEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_FAULT_ADReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FAULT_ADReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_FAULT_AD_OFFSET))
++
++
++#define MMUMMU_TTBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_TTB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_TTBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LOCK_OFFSET))
++
++
++#define MMUMMU_LOCKWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKBaseValueRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_BaseValue_MASK) >>\
++ MMU_MMU_LOCK_BaseValue_OFFSET))
++
++
++#define MMUMMU_LOCKBaseValueWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueWrite32);\
++ data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
++ newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
++ newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK) >>\
++ MMU_MMU_LOCK_CurrentVictim_OFFSET))
++
++
++#define MMUMMU_LOCKCurrentVictimWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimWrite32);\
++ data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
++ newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
++ newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimSet32),\
++ (((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
++ (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK)))
++
++
++#define MMUMMU_LD_TLBReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LD_TLB_OFFSET))
++
++
++#define MMUMMU_LD_TLBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_CAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_RAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_RAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_RAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MMU_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMAccInt.h b/drivers/dsp/bridge/hw/PRCMAccInt.h
+new file mode 100644
+index 0000000..42baa68
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMAccInt.h
+@@ -0,0 +1,300 @@
++/*
++ * PRCMAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_ACC_INT_H
++#define _PRCM_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32 \
++ (PRCM_BASE_EASIL1 + 349)
++#define EASIL1_PRCMCM_FCLKEN1_COREReadRegister32 (PRCM_BASE_EASIL1 + 743)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32 (PRCM_BASE_EASIL1 + 951)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32 (PRCM_BASE_EASIL1 + 961)
++#define EASIL1_PRCMCM_ICLKEN1_COREReadRegister32 \
++ (PRCM_BASE_EASIL1 + 1087)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32 \
++ (PRCM_BASE_EASIL1 + 1105)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32 \
++ (PRCM_BASE_EASIL1 + 1305)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32 \
++ (PRCM_BASE_EASIL1 + 1315)
++#define EASIL1_PRCMCM_CLKSEL1_CORECLKSEL_L3ReadIssel132 \
++ (PRCM_BASE_EASIL1 + 2261)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32 \
++ (PRCM_BASE_EASIL1 + 2364)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2365)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2366)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32 \
++ (PRCM_BASE_EASIL1 + 2380)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2381)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2382)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2397)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2398)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2413)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2414)
++#define EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32 \
++ (PRCM_BASE_EASIL1 + 3747)
++#define EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32 (PRCM_BASE_EASIL1 + 3834)
++#define EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3846)
++#define EASIL1_PRCMCM_IDLEST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3850)
++#define EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32 (PRCM_BASE_EASIL1 + 3857)
++#define EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32 (PRCM_BASE_EASIL1 + 3863)
++#define EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3877)
++#define EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32 (PRCM_BASE_EASIL1 + 3927)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32 \
++ (PRCM_BASE_EASIL1 + 3941)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3965)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32 \
++ (PRCM_BASE_EASIL1 + 3987)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3993)
++#define EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3997)
++#define EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 4025)
++#define EASIL1_PRCMRM_RSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4029)
++#define EASIL1_PRCMRM_RSTST_DSPWriteRegister32 (PRCM_BASE_EASIL1 + 4030)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32 \
++ (PRCM_BASE_EASIL1 + 4165)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32 \
++ (PRCM_BASE_EASIL1 + 4193)
++#define EASIL1_PRCMPM_PWSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4197)
++#define EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4198)
++#define EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4235)
++#define EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4368)
++#define EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4370)
++#define EASIL1_CM_CLKSEL_PER_GPT5Write32k32 (PRCM_BASE_EASIL1 + 4372)
++#define EASIL1_CM_CLKSEL_PER_GPT6Write32k32 (PRCM_BASE_EASIL1 + 4373)
++#define EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4374)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32 \
++ (PRCM_BASE_EASIL1 + 4375)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32 \
++ (PRCM_BASE_EASIL1 + 4376)
++#define EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4377)
++#define EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4378)
++#define EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32 (PRCM_BASE_EASIL1 + 4379)
++
++/* Register offset address definitions */
++
++#define PRCM_PRCM_CLKCFG_CTRL_OFFSET (u32)(0x80)
++#define PRCM_CM_FCLKEN1_CORE_OFFSET (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_OFFSET (u32)(0x210)
++#define PRCM_CM_CLKSEL2_CORE_OFFSET (u32)(0x244)
++#define PRCM_CM_CLKSEL1_PLL_OFFSET (u32)(0x540)
++#define PRCM_CM_ICLKEN_DSP_OFFSET (u32)(0x810)
++#define PRCM_CM_IDLEST_DSP_OFFSET (u32)(0x820)
++#define PRCM_CM_AUTOIDLE_DSP_OFFSET (u32)(0x830)
++#define PRCM_CM_CLKSEL_DSP_OFFSET (u32)(0x840)
++#define PRCM_CM_CLKSTCTRL_DSP_OFFSET (u32)(0x848)
++#define PRCM_RM_RSTCTRL_DSP_OFFSET (u32)(0x850)
++#define PRCM_RM_RSTST_DSP_OFFSET (u32)(0x858)
++#define PRCM_PM_PWSTCTRL_DSP_OFFSET (u32)(0x8e0)
++#define PRCM_PM_PWSTST_DSP_OFFSET (u32)(0x8e4)
++#define PRCM_PM_PWSTST_IVA2_OFFSET (u32)(0xE4)
++#define PRCM_PM_PWSTCTRL_IVA2_OFFSET (u32)(0xE0)
++#define PRCM_CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x48)
++#define CM_CLKSEL_PER_OFFSET (u32)(0x40)
++
++/* Bitfield mask and offset declarations */
++
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK (u32)(0x1)
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET (u32)(0)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK (u32)(0xc000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET (u32)(14)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK (u32)(0x3000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET (u32)(12)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK (u32)(0xc00)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET (u32)(10)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK (u32)(0x300)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET (u32)(8)
++
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK (u32)(0x3800000)
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET (u32)(23)
++
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_IDLEST_DSP_ST_IPI_MASK (u32)(0x2)
++#define PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK (u32)(0x80)
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET (u32)(7)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK (u32)(0x60)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET (u32)(5)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK (u32)(0x1f)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET (u32)(0)
++
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK (u32)(0x1)
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_MASK (u32)(0x40000)
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET (u32)(18)
++
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_DSP_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_DSP_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_IVA2_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_IVA2_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET (u32)(0)
++
++#define CM_FCLKEN_PER_OFFSET (u32)(0x0)
++#define CM_FCLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_FCLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_FCLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_FCLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_ICLKEN_PER_OFFSET (u32)(0x10)
++#define CM_ICLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_ICLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_ICLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_ICLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_CLKSEL_PER_GPT5_OFFSET (u32)(3)
++#define CM_CLKSEL_PER_GPT5_MASK (u32)(0x8)
++
++#define CM_CLKSEL_PER_GPT6_OFFSET (u32)(4)
++#define CM_CLKSEL_PER_GPT6_MASK (u32)(0x10)
++
++
++#define CM_FCLKEN_IVA2_OFFSET (u32)(0x0)
++#define CM_FCLKEN_IVA2_EN_MASK (u32)(0x1)
++#define CM_FCLKEN_IVA2_EN_OFFSET (u32)(0x0)
++
++#define CM_IDLEST_IVA2_OFFSET (u32)(0x20)
++#define CM_IDLEST_IVA2_ST_IVA2_MASK (u32) (0x01)
++#define CM_IDLEST_IVA2_ST_IVA2_OFFSET (u32) (0x00)
++
++#define CM_FCLKEN1_CORE_OFFSET (u32)(0xA00)
++
++#define CM_ICLKEN1_CORE_OFFSET (u32)(0xA10)
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_MASK (u32)(0x00000080) /* bit 7 */
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET (u32)(7)
++
++#define CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x0)
++#define CM_CLKSTCTRL_IVA2_MASK (u32)(0x3)
++
++
++#define PRM_RSTCTRL_IVA2_OFFSET (u32)(0x50)
++#define PRM_RSTCTRL_IVA2_RST1_MASK (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST1_OFFSET (u32)(0x0)
++#define PRM_RSTCTRL_IVA2_RST2_MASK (u32)(0x2)
++#define PRM_RSTCTRL_IVA2_RST2_OFFSET (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST3_MASK (u32)(0x4)
++#define PRM_RSTCTRL_IVA2_RST3_OFFSET (u32)(0x2)
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum PRCMPRCM_CLKCFG_CTRLValid_configE {
++ PRCMPRCM_CLKCFG_CTRLValid_configUpdated = 0x0000,
++ PRCMPRCM_CLKCFG_CTRLValid_configClk_valid = 0x0001
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT8E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT832k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT7E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT732k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT6E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT632k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT5E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT532k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Reserved = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_DSPPowerStateE {
++ PRCMPM_PWSTCTRL_DSPPowerStateON = 0x0000,
++ PRCMPM_PWSTCTRL_DSPPowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_DSPPowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_DSPPowerStateOFF = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_IVA2PowerStateE {
++ PRCMPM_PWSTCTRL_IVA2PowerStateON = 0x0003,
++ PRCMPM_PWSTCTRL_IVA2PowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_IVA2PowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_IVA2PowerStateOFF = 0x0000
++} ;
++
++#endif /* _PRCM_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMRegAcM.h b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+new file mode 100644
+index 0000000..91cb33c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+@@ -0,0 +1,669 @@
++/*
++ * PRCMRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_REG_ACM_H
++#define _PRCM_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "PRCMAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32(baseAddress)\
++{\
++ const u32 offset = PRCM_PRCM_CLKCFG_CTRL_OFFSET;\
++ const u32 newValue = \
++ (u32)PRCMPRCM_CLKCFG_CTRLValid_configClk_valid <<\
++ PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(\
++ EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32);\
++ data &= ~(PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_FCLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN_PER_OFFSET))
++
++
++#define CM_ICLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN_PER_OFFSET))
++
++
++#define CM_FCLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN1_CORE_OFFSET))
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT8Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT7Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define CM_ICLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN1_CORE_OFFSET))
++
++
++#define CM_ICLKEN1_COREEN_MAILBOXESWrite32(baseAddress, value)\
++{\
++ const u32 offset = CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32);\
++ data &= ~(CM_ICLKEN1_CORE_EN_MAILBOXES_MASK);\
++ newValue <<= CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET;\
++ newValue &= CM_ICLKEN1_CORE_EN_MAILBOXES_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT8Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT7Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT832k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT732k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT5Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT5Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT6Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT6Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSEL1_PLL_OFFSET)))) &\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK) >>\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET))
++
++
++#define CM_FCLKEN_IVA2EN_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32);\
++ data &= ~(CM_FCLKEN_IVA2_EN_MASK);\
++ newValue <<= CM_FCLKEN_IVA2_EN_OFFSET;\
++ newValue &= CM_FCLKEN_IVA2_EN_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_IDLEST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_CM_IDLEST_DSP_OFFSET))
++
++
++#define PRCMCM_IDLEST_DSPST_IPIRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_IDLEST_DSP_OFFSET)))) &\
++ PRCM_CM_IDLEST_DSP_ST_IPI_MASK) >>\
++ PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET))
++
++
++#define PRM_IDLEST_IVA2ST_IVA2Read32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (CM_IDLEST_IVA2_OFFSET)))) &\
++ CM_IDLEST_IVA2_ST_IVA2_MASK) >>\
++ CM_IDLEST_IVA2_ST_IVA2_OFFSET))
++
++
++#define PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_AUTOIDLE_DSP_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPSYNC_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32);\
++ data &= ~(CM_CLKSTCTRL_IVA2_MASK);\
++ newValue <<= CM_CLKSTCTRL_IVA2_OFFSET;\
++ newValue &= CM_CLKSTCTRL_IVA2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSTCTRL_DSP_OFFSET)))) &\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK) >>\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET))
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTCTRL_DSP_OFFSET))
++
++
++#define PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST1_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST1_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST1_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST2_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST2_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST3_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST3_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST3_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTST_DSP_OFFSET))
++
++
++#define PRCMRM_RSTST_DSPWriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_RM_RSTST_DSP_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPForceStateWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_ForceState_MASK);\
++ newValue <<= PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET;\
++ newValue &= PRCM_PM_PWSTCTRL_DSP_ForceState_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateON <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateOFF <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_DSPPowerStateRET <<\
++ PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_DSP_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_IVA2_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPInTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_DSP_OFFSET)))) &\
++ PRCM_PM_PWSTST_DSP_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_DSP_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2InTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_IVA2_OFFSET)))) &\
++ PRCM_PM_PWSTST_IVA2_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPPowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_DSP_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2PowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET))
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _PRCM_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/hw_defs.h b/drivers/dsp/bridge/hw/hw_defs.h
+new file mode 100644
+index 0000000..a973f5c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_defs.h
+@@ -0,0 +1,73 @@
++/*
++ * hw_defs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_defs.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Added generic page size, endianness and element size defns
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_DEFS_H
++#define __HW_DEFS_H
++
++#include <GlobalTypes.h>
++
++/* Page size */
++#define HW_PAGE_SIZE_4KB 0x1000
++#define HW_PAGE_SIZE_64KB 0x10000
++#define HW_PAGE_SIZE_1MB 0x100000
++#define HW_PAGE_SIZE_16MB 0x1000000
++
++/* HW_STATUS: return type for HW API */
++typedef long HW_STATUS;
++
++/* HW_SetClear_t: Enumerated Type used to set and clear any bit */
++enum HW_SetClear_t {
++ HW_CLEAR,
++ HW_SET
++} ;
++
++/* HW_Endianism_t: Enumerated Type used to specify the endianism
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_Endianism_t {
++ HW_LITTLE_ENDIAN,
++ HW_BIG_ENDIAN
++
++} ;
++
++/* HW_ElementSize_t: Enumerated Type used to specify the element size
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_ElementSize_t {
++ HW_ELEM_SIZE_8BIT,
++ HW_ELEM_SIZE_16BIT,
++ HW_ELEM_SIZE_32BIT,
++ HW_ELEM_SIZE_64BIT
++
++} ;
++
++/* HW_IdleMode_t: Enumerated Type used to specify Idle modes */
++ enum HW_IdleMode_t {
++ HW_FORCE_IDLE,
++ HW_NO_IDLE,
++ HW_SMART_IDLE
++ } ;
++
++#endif /* __HW_DEFS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.c b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+new file mode 100644
+index 0000000..a4b7c30
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+@@ -0,0 +1,55 @@
++/*
++ * hw_dspss64P.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_dspss64P.c ========
++ * Description:
++ * API definitions to configure DSP Subsystem modules like IPI
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Implemented HW_DSPSS_IPIEndianismSet
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++/* PROJECT SPECIFIC INCLUDE FILES */
++#include <GlobalTypes.h>
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <IVA2RegAcM.h>
++#include <IPIAccInt.h>
++
++/* HW FUNCTIONS */
++HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 offset = SYSC_IVA2BOOTMOD_OFFSET;
++ u32 alignedBootAddr;
++
++ /* if Boot mode it DIRECT BOOT, check that the bootAddress is
++ * aligned to atleast 1K :: TODO */
++ WR_MEM_32_VOLATILE((baseAddress) + offset, bootMode);
++
++ offset = SYSC_IVA2BOOTADDR_OFFSET;
++
++ alignedBootAddr = bootAddress & SYSC_IVA2BOOTADDR_MASK;
++
++ WR_MEM_32_VOLATILE((baseAddress) + offset, alignedBootAddr);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.h b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+new file mode 100644
+index 0000000..493effd
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+@@ -0,0 +1,48 @@
++/*
++ * hw_dspssC64P.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_dspss.h ========
++ * Description:
++ * DSP Subsystem API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Removed redundant argument from HW_DSPSS_IPIEndianismSet
++ *! Moved endianness and element size to generic hw_defs.h
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_DSPSS_H
++#define __HW_DSPSS_H
++#include <linux/types.h>
++
++ enum HW_DSPSYSC_BootMode_t {
++ HW_DSPSYSC_DIRECTBOOT = 0x0,
++ HW_DSPSYSC_IDLEBOOT = 0x1,
++ HW_DSPSYSC_SELFLOOPBOOT = 0x2,
++ HW_DSPSYSC_USRBOOTSTRAP = 0x3,
++ HW_DSPSYSC_DEFAULTRESTORE = 0x4
++ } ;
++
++#define HW_DSP_IDLEBOOT_ADDR 0x007E0000
++
++ extern HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress);
++
++#endif /* __HW_DSPSS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c
+new file mode 100644
+index 0000000..9f14f34
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.c
+@@ -0,0 +1,244 @@
++/*
++ * hw_mbox.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mbox.c ========
++ * Description:
++ * Mailbox messaging & configuration API definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MLBRegAcM.h"
++#include <hw_defs.h>
++#include <hw_mbox.h>
++
++/* width in bits of MBOX Id */
++#define HW_MBOX_ID_WIDTH 2
++
++struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1};
++
++/* Saves the mailbox context */
++HW_STATUS HW_MBOX_saveSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Restores the mailbox context */
++HW_STATUS HW_MBOX_restoreSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ /* Restor IRQ enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U0_ARM,
++ mboxsetting.irqEnable0);
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U1_DSP1,
++ mboxsetting.irqEnable1);
++ /* Restore Sysconfig register */
++ MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, mboxsetting.sysconfig);
++ return status;
++}
++
++/* Reads a u32 from the sub module message box Specified. if there are no
++ * messages in the mailbox then and error is returned. */
++HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pReadValue, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Read 32-bit message in mail box */
++ *pReadValue = MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Writes a u32 from the sub module message box Specified. */
++HW_STATUS HW_MBOX_MsgWrite(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Write 32-bit value to mailbox */
++ MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, (u32)mailBoxId,
++ (u32)writeValue);
++
++ return status;
++}
++
++/* Gets number of messages in a specified mailbox. */
++HW_STATUS HW_MBOX_NumMsgGet(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pNumMsg, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get number of messages available for MailBox */
++ *pNumMsg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Enables the specified IRQ. */
++HW_STATUS HW_MBOX_EventEnable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqEnableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(enableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqEnableReg |= ((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqEnableReg);
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Disables the specified IRQ. */
++HW_STATUS HW_MBOX_EventDisable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqDisableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(disableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqDisableReg &= ~(((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH));
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqDisableReg);
++
++ return status;
++}
++
++/* Sets the status of the specified IRQ. */
++HW_STATUS HW_MBOX_EventAck(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId, const u32 event)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqStatusReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(irqStatus, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* calculate status to write */
++ irqStatusReg = ((u32)event) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* clear Irq Status for specified mailbox/User Id */
++ MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqStatusReg);
++
++ /*
++ * FIXME: Replace all this custom register access with standard
++ * __raw_read/write().
++ *
++ * FIXME: Replace all interrupt handlers with standard linux style
++ * interrupt handlers.
++ *
++ * FIXME: Replace direct access to PRCM registers with omap standard
++ * PRCM register access.
++ *
++ * Flush posted write for the irq status to avoid spurious interrupts.
++ */
++ MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, (u32)userId);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.h b/drivers/dsp/bridge/hw/hw_mbox.h
+new file mode 100644
+index 0000000..d2981d3
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.h
+@@ -0,0 +1,323 @@
++/*
++ * hw_mbox.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mbox.h ========
++ * Description:
++ * HW Mailbox API and types definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __MBOX_H
++#define __MBOX_H
++
++/* Bitmasks for Mailbox interrupt sources */
++#define HW_MBOX_INT_NEW_MSG 0x1
++#define HW_MBOX_INT_NOT_FULL 0x2
++#define HW_MBOX_INT_ALL 0x3
++
++/* Maximum number of messages that mailbox can hald at a time. */
++#define HW_MBOX_MAX_NUM_MESSAGES 4
++
++/* HW_MBOX_Id_t: Enumerated Type used to specify Mailbox Sub Module Id Number */
++typedef enum HW_MBOX_Id_label {
++ HW_MBOX_ID_0,
++ HW_MBOX_ID_1,
++ HW_MBOX_ID_2,
++ HW_MBOX_ID_3,
++ HW_MBOX_ID_4,
++ HW_MBOX_ID_5
++
++} HW_MBOX_Id_t, *pHW_MBOX_Id_t;
++
++/* HW_MBOX_UserId_t: Enumerated Type used to specify Mail box User Id */
++typedef enum HW_MBOX_UserId_label {
++ HW_MBOX_U0_ARM,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_U2_DSP2,
++ HW_MBOX_U3_ARM
++
++} HW_MBOX_UserId_t, *pHW_MBOX_UserId_t;
++
++/* Mailbox context settings */
++struct MAILBOX_CONTEXT {
++ u32 sysconfig;
++ u32 irqEnable0;
++ u32 irqEnable1;
++};
++
++/*
++* FUNCTION : HW_MBOX_MsgRead
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to read
++*
++* OUTPUTS:
++*
++* Identifier : pReadValue
++* Type : u32 *const
++* Description : Value read from MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/ptr Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function reads a u32 from the sub module message
++* box Specified. if there are no messages in the mailbox
++* then and error is returned.
++*/
++extern HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue);
++
++/*
++* FUNCTION : HW_MBOX_MsgWrite
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to write
++*
++* Identifier : writeValue
++* Type : const u32
++* Description : Value to write to MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function writes a u32 from the sub module message
++* box Specified.
++*/
++extern HW_STATUS HW_MBOX_MsgWrite(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue
++ );
++
++/*
++* FUNCTION : HW_MBOX_NumMsgGet
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to get num messages
++*
++* OUTPUTS:
++*
++* Identifier : pNumMsg
++* Type : u32 *const
++* Description : Number of messages in mailbox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Inavlid ID input at parameter
++*
++* PURPOSE: : this function gets number of messages in a specified mailbox.
++*/
++extern HW_STATUS HW_MBOX_NumMsgGet(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventEnable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to enable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to enable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to enable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function enables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventEnable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventDisable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to disable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to disable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to disable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function disables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventDisable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventAck
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to set
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to set
++*
++* Identifier : irqStatus
++* Type : const u32
++* Description : The value to write IRQ status
++*
++* OUTPUTS:
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address Paramater was set to 0
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function sets the status of the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventAck(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 event
++ );
++
++/*
++* FUNCTION : HW_MBOX_saveSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function saves the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_saveSettings(u32 baseAddres);
++
++/*
++* FUNCTION : HW_MBOX_restoreSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function restores the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_restoreSettings(u32 baseAddres);
++
++#endif /* __MBOX_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.c b/drivers/dsp/bridge/hw/hw_mmu.c
+new file mode 100644
+index 0000000..ab65de0
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.c
+@@ -0,0 +1,598 @@
++/*
++ * hw_mmu.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mmu.c ========
++ * Description:
++ * API definitions to setup MMU TLB and PTE
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb TLBAdd and TLBFlush input the page size in bytes instead
++ of an enum. TLBAdd inputs mapping attributes struct instead
++ of individual arguments.
++ Removed MMU.h and other cosmetic updates.
++ *! 08-Mar-2004 sb Added the Page Table Management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MMURegAcM.h"
++#include <hw_defs.h>
++#include <hw_mmu.h>
++#include <linux/types.h>
++
++#define MMU_BASE_VAL_MASK 0xFC00
++#define MMU_PAGE_MAX 3
++#define MMU_ELEMENTSIZE_MAX 3
++#define MMU_ADDR_MASK 0xFFFFF000
++#define MMU_TTB_MASK 0xFFFFC000
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++
++#define MMU_LOAD_TLB 0x00000001
++
++/* HW_MMUPageSize_t: Enumerated Type used to specify the MMU Page Size(SLSS) */
++enum HW_MMUPageSize_t {
++ HW_MMU_SECTION,
++ HW_MMU_LARGE_PAGE,
++ HW_MMU_SMALL_PAGE,
++ HW_MMU_SUPERSECTION
++} ;
++
++/*
++* FUNCTION : MMU_FlushEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer
++* Paramater was set to NULL
++*
++* PURPOSE: : Flush the TLB entry pointed by the
++* lock counter register
++* even if this entry is set protected
++*
++* METHOD: : Check the Input parameter and Flush a
++* single entry in the TLB.
++*/
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress);
++
++/*
++* FUNCTION : MMU_SetCAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* TypE : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : pageSize
++* TypE : const u32
++* Description : It indicates the page size
++*
++* Identifier : preservedBit
++* Type : const u32
++* Description : It indicates the TLB entry is preserved entry
++* or not
++*
++* Identifier : validBit
++* Type : const u32
++* Description : It indicates the TLB entry is valid entry or not
++*
++*
++* Identifier : virtualAddrTag
++* Type : const u32
++* Description : virtual Address
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter out
++* of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the CAM entry.
++*/
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag);
++
++/*
++* FUNCTION : MMU_SetRAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : physicalAddr
++* Type : const u32
++* Description : Physical Address to which the corresponding
++* virtual Address shouldpoint
++*
++* Identifier : endianism
++* Type : HW_Endianism_t
++* Description : endianism for the given page
++*
++* Identifier : elementSize
++* Type : HW_ElementSize_t
++* Description : The element size ( 8,16, 32 or 64 bit)
++*
++* Identifier : mixedSize
++* Type : HW_MMUMixedSize_t
++* Description : Element Size to follow CPU or TLB
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter
++* out of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the RAM entry.
++*/
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++/* HW FUNCTIONS */
++
++HW_STATUS HW_MMU_Enable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_Disable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKBaseValueWrite32(baseAddress, numLockedEntries);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, victimEntryNum);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventAck(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_IRQSTATUSWriteRegister32(baseAddress, irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg & ~irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventEnable(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg | irqMask);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_EventStatus(const u32 baseAddress, u32 *irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ *irqMask = MMUMMU_IRQSTATUSReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress, u32 *addr)
++{
++ HW_STATUS status = RET_OK;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* read values from register */
++ *addr = MMUMMU_FAULT_ADReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TTBSet(const u32 baseAddress, u32 TTBPhysAddr)
++{
++ HW_STATUS status = RET_OK;
++ u32 loadTTB;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ loadTTB = TTBPhysAddr & ~0x7FUL;
++ /* write values to register */
++ MMUMMU_TTBWriteRegister32(baseAddress, loadTTB);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress, u32 virtualAddr,
++ u32 pageSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t pgSizeBits;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pgSizeBits = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ pgSizeBits = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pgSizeBits = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ pgSizeBits = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ MMU_SetCAMEntry(baseAddress, pgSizeBits, 0, 0, virtualAddrTag);
++
++ MMU_FlushEntry(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit)
++{
++ HW_STATUS status = RET_OK;
++ u32 lockReg;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t mmuPgSize;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(pageSize, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mapAttrs->elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ mmuPgSize = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ mmuPgSize = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ mmuPgSize = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ mmuPgSize = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ lockReg = MMUMMU_LOCKReadRegister32(baseAddress);
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ /* Write the fields in the CAM Entry Register */
++ MMU_SetCAMEntry(baseAddress, mmuPgSize, preservedBit, validBit,
++ virtualAddrTag);
++
++ /* Write the different fields of the RAM Entry Register */
++ /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit)*/
++ MMU_SetRAMEntry(baseAddress, physicalAddr, mapAttrs->endianism,
++ mapAttrs->elementSize, mapAttrs->mixedSize);
++
++ /* Update the MMU Lock Register */
++ /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1)*/
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, entryNum);
++
++ /* Enable loading of an entry in TLB by writing 1
++ into LD_TLB_REG register */
++ MMUMMU_LD_TLBWriteRegister32(baseAddress, MMU_LOAD_TLB);
++
++
++ MMUMMU_LOCKWriteRegister32(baseAddress, lockReg);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr, pteVal;
++ s32 numEntries = 1;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_SMALL_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 2
++ );
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_LARGE_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 1
++ );
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = ((((physicalAddr & MMU_SECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)) &
++ ~0x40000) | 0x2
++ );
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ pteVal = (((physicalAddr & MMU_SSECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)
++ ) | 0x40000 | 0x2
++ );
++ break;
++
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = (physicalAddr & MMU_PAGE_TABLE_MASK) | 1;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = pteVal;
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 virtualAddr,
++ u32 pgSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr;
++ s32 numEntries = 1;
++
++ switch (pgSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = 0;
++
++ return status;
++}
++
++/* MMU_FlushEntry */
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 flushEntryData = 0x1;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* write values to register */
++ MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, flushEntryData);
++
++ return status;
++}
++
++/* MMU_SetCAMEntry */
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuCamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ mmuCamReg = (virtualAddrTag << 12);
++ mmuCamReg = (mmuCamReg) | (pageSize) | (validBit << 2) |
++ (preservedBit << 3) ;
++
++ /* write values to register */
++ MMUMMU_CAMWriteRegister32(baseAddress, mmuCamReg);
++
++ return status;
++}
++
++/* MMU_SetRAMEntry */
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuRamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++
++ mmuRamReg = (physicalAddr & MMU_ADDR_MASK);
++ mmuRamReg = (mmuRamReg) | ((endianism << 9) | (elementSize << 7) |
++ (mixedSize << 6));
++
++ /* write values to register */
++ MMUMMU_RAMWriteRegister32(baseAddress, mmuRamReg);
++
++ return status;
++
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h
+new file mode 100644
+index 0000000..a3dd2a8
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.h
+@@ -0,0 +1,177 @@
++/*
++ * hw_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mmu.h ========
++ * Description:
++ * MMU types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Moved & renamed endianness, page size, element size
++ TLBAdd takes in MMUMapAttrs instead of separate arguments
++ *! 08-Mar-2004 sb Added the Page Table management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_MMU_H
++#define __HW_MMU_H
++
++#include <linux/types.h>
++
++/* Bitmasks for interrupt sources */
++#define HW_MMU_TRANSLATION_FAULT 0x2
++#define HW_MMU_ALL_INTERRUPTS 0x1F
++
++#define HW_MMU_COARSE_PAGE_SIZE 0x400
++
++/* HW_MMUMixedSize_t: Enumerated Type used to specify whether to follow
++ CPU/TLB Element size */
++enum HW_MMUMixedSize_t {
++ HW_MMU_TLBES,
++ HW_MMU_CPUES
++
++} ;
++
++/* HW_MMUMapAttrs_t: Struct containing MMU mapping attributes */
++struct HW_MMUMapAttrs_t {
++ enum HW_Endianism_t endianism;
++ enum HW_ElementSize_t elementSize;
++ enum HW_MMUMixedSize_t mixedSize;
++ bool donotlockmpupage;
++} ;
++
++extern HW_STATUS HW_MMU_Enable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_Disable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries);
++
++extern HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum);
++
++/* For MMU faults */
++extern HW_STATUS HW_MMU_EventAck(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventEnable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventStatus(const u32 baseAddress,
++ u32 *irqMask);
++
++extern HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress,
++ u32 *addr);
++
++/* Set the TT base address */
++extern HW_STATUS HW_MMU_TTBSet(const u32 baseAddress,
++ u32 TTBPhysAddr);
++
++extern HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress,
++ u32 virtualAddr,
++ u32 pageSize);
++
++extern HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit);
++
++
++/* For PTEs */
++extern HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++
++extern HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 pgSize,
++ u32 virtualAddr);
++
++static inline u32 HW_MMU_PteAddrL1(u32 L1_base, u32 va)
++{
++ u32 pteAddr;
++ u32 VA_31_to_20;
++
++ VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
++ VA_31_to_20 &= 0xFFFFFFFCUL;
++ pteAddr = L1_base + VA_31_to_20;
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteAddrL2(u32 L2_base, u32 va)
++{
++ u32 pteAddr;
++
++ pteAddr = (L2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteCoarseL1(u32 pteVal)
++{
++ u32 pteCoarse;
++
++ pteCoarse = pteVal & 0xFFFFFC00;
++
++ return pteCoarse;
++}
++
++static inline u32 HW_MMU_PteSizeL1(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if ((pteVal & 0x3) == 0x1) {
++ /* Points to L2 PT */
++ pteSize = HW_MMU_COARSE_PAGE_SIZE;
++ }
++
++ if ((pteVal & 0x3) == 0x2) {
++ if (pteVal & (1 << 18))
++ pteSize = HW_PAGE_SIZE_16MB;
++ else
++ pteSize = HW_PAGE_SIZE_1MB;
++ }
++
++ return pteSize;
++}
++
++static inline u32 HW_MMU_PteSizeL2(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if (pteVal & 0x2)
++ pteSize = HW_PAGE_SIZE_4KB;
++ else if (pteVal & 0x1)
++ pteSize = HW_PAGE_SIZE_64KB;
++
++ return pteSize;
++}
++
++#endif /* __HW_MMU_H */
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.c b/drivers/dsp/bridge/hw/hw_prcm.c
+new file mode 100644
+index 0000000..61ff08f
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.c
+@@ -0,0 +1,167 @@
++/*
++ * hw_prcm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.c ========
++ * Description:
++ * API definitions to configure PRCM (Power, Reset & Clocks Manager)
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "PRCMRegAcM.h"
++#include <hw_defs.h>
++#include <hw_prcm.h>
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val);
++
++HW_STATUS HW_RST_Reset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_SET);
++}
++
++HW_STATUS HW_RST_UnReset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_CLEAR);
++}
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (r) {
++ case HW_RST1_IVA2:
++ PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST2_IVA2:
++ PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST3_IVA2:
++ PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress, val);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress, enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value)
++{
++ HW_STATUS status = RET_OK;
++ u32 temp;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ /* wait until Transition is complete */
++ do {
++ /* mdelay(1); */
++ temp = PRCMPM_PWSTST_IVA2InTransitionRead32
++ (baseAddress);
++
++ } while (temp);
++
++ temp = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++ *value = PRCMPM_PWSTST_IVA2PowerStateStGet32(temp);
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ switch (value) {
++ case HW_PWR_STATE_ON:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress);
++ break;
++ case HW_PWR_STATE_RET:
++ PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress);
++ break;
++ case HW_PWR_STATE_OFF:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++
++ return status;
++}
++
++HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, val);
++
++ return status;
++
++}
++
++HW_STATUS HW_RSTST_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTST_DSPReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.h b/drivers/dsp/bridge/hw/hw_prcm.h
+new file mode 100644
+index 0000000..928486c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.h
+@@ -0,0 +1,168 @@
++/*
++ * hw_prcm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.h ========
++ * Description:
++ * PRCM types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_PRCM_H
++#define __HW_PRCM_H
++
++/* HW_ClkModule: Enumerated Type used to specify the clock domain */
++
++enum HW_ClkModule_t {
++/* DSP Domain */
++ HW_CLK_DSP_CPU,
++ HW_CLK_DSP_IPI_MMU,
++ HW_CLK_IVA_ARM,
++ HW_CLK_IVA_COP, /* IVA Coprocessor */
++
++/* Core Domain */
++ HW_CLK_FN_WDT4, /* Functional Clock */
++ HW_CLK_FN_WDT3,
++ HW_CLK_FN_UART2,
++ HW_CLK_FN_UART1,
++ HW_CLK_GPT5,
++ HW_CLK_GPT6,
++ HW_CLK_GPT7,
++ HW_CLK_GPT8,
++
++ HW_CLK_IF_WDT4, /* Interface Clock */
++ HW_CLK_IF_WDT3,
++ HW_CLK_IF_UART2,
++ HW_CLK_IF_UART1,
++ HW_CLK_IF_MBOX
++
++} ;
++
++enum HW_ClkSubsys_t {
++ HW_CLK_DSPSS,
++ HW_CLK_IVASS
++} ;
++
++/* HW_GPtimers: General purpose timers */
++enum HW_GPtimer_t {
++ HW_GPT5 = 5,
++ HW_GPT6 = 6,
++ HW_GPT7 = 7,
++ HW_GPT8 = 8
++} ;
++
++
++/* GP timers Input clock type: General purpose timers */
++enum HW_Clocktype_t {
++ HW_CLK_32KHz = 0,
++ HW_CLK_SYS = 1,
++ HW_CLK_EXT = 2
++} ;
++
++/* HW_ClkDiv: Clock divisors */
++enum HW_ClkDiv_t {
++ HW_CLK_DIV_1 = 0x1,
++ HW_CLK_DIV_2 = 0x2,
++ HW_CLK_DIV_3 = 0x3,
++ HW_CLK_DIV_4 = 0x4,
++ HW_CLK_DIV_6 = 0x6,
++ HW_CLK_DIV_8 = 0x8,
++ HW_CLK_DIV_12 = 0xC
++} ;
++
++/* HW_RstModule: Enumerated Type used to specify the module to be reset */
++enum HW_RstModule_t {
++ HW_RST1_IVA2, /* Reset the DSP */
++ HW_RST2_IVA2, /* Reset MMU and LEON HWa */
++ HW_RST3_IVA2 /* Reset LEON sequencer */
++} ;
++
++/* HW_PwrModule: Enumerated Type used to specify the power domain */
++enum HW_PwrModule_t {
++/* Domains */
++ HW_PWR_DOMAIN_CORE,
++ HW_PWR_DOMAIN_MPU,
++ HW_PWR_DOMAIN_WAKEUP,
++ HW_PWR_DOMAIN_DSP,
++
++/* Sub-domains */
++ HW_PWR_DSP_IPI, /* IPI = Intrusive Port Interface */
++ HW_PWR_IVA_ISP /* ISP = Intrusive Slave Port */
++} ;
++
++enum HW_PwrState_t {
++ HW_PWR_STATE_OFF,
++ HW_PWR_STATE_RET,
++ HW_PWR_STATE_INACT,
++ HW_PWR_STATE_ON = 3
++} ;
++
++enum HW_ForceState_t {
++ HW_FORCE_OFF,
++ HW_FORCE_ON
++} ;
++
++enum HW_IdleState_t {
++ HW_ACTIVE,
++ HW_STANDBY
++
++} ;
++
++enum HW_TransitionState_t {
++ HW_AUTOTRANS_DIS,
++ HW_SW_SUP_SLEEP,
++ HW_SW_SUP_WAKEUP,
++ HW_AUTOTRANS_EN
++} ;
++
++
++extern HW_STATUS HW_RST_Reset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RST_UnReset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p,
++ u32 *value);
++extern HW_STATUS HW_RSTST_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p, u32 *value);
++
++extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_CLK_SetInputClock(const u32 baseAddress,
++ enum HW_GPtimer_t gpt,
++ enum HW_Clocktype_t c);
++
++extern HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value);
++
++extern HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value);
++
++extern HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val);
++
++#endif /* __HW_PRCM_H */
+diff --git a/drivers/dsp/bridge/pmgr/chnl.c b/drivers/dsp/bridge/pmgr/chnl.c
+new file mode 100644
+index 0000000..6b5a0d9
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnl.c
+@@ -0,0 +1,260 @@
++/*
++ * chnl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.c ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a 'Bridge mini-driver.
++ *
++ * Public Functions:
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_GetHandle
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD CHNL functions,
++ * except for the CHNL_Get() accessor functions which call
++ * WMD_CHNL_GetInfo().
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 07-Jan-2002 ag CHNL_CloseOrphans() now closes supported # of channels.
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory stuff from CHNL_Create.
++ *! 28-Feb-2000 rr: New GT USage Implementation
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 21-Jan-2000 ag: Added code review comments.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! 08-Dec-1999 ag: CHNL_[Alloc|Free]Buffer bufs taken from client process heap.
++ *! 02-Dec-1999 ag: Implemented CHNL_GetEventHandle().
++ *! 17-Nov-1999 ag: CHNL_AllocBuffer() allocs extra word for process mapping.
++ *! 28-Oct-1999 ag: WinCE port. Search for "WinCE" for changes(TBR).
++ *! 07-Jan-1998 gp: CHNL_[Alloc|Free]Buffer now call MEM_UMB functions.
++ *! 22-Oct-1997 gp: Removed requirement in CHNL_Open that hReserved1 != NULL.
++ *! 30-Aug-1997 cr: Renamed cfg.h wbwcd.h b/c of WINNT file name collision.
++ *! 10-Mar-1997 gp: Added GT trace.
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Moved CHNL_AllocBuffer/CHNL_FreeBuffer code from udspsys.
++ *! 14-Dec-1996 gp: Added uChnlId parameter to CHNL_Open().
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessHandle().
++ *! 15-Jul-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/proc.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/chnlpriv.h>
++#include <chnlobj.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/chnl.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++#if GT_TRACE
++static struct GT_Mask CHNL_DebugMask = { NULL, NULL }; /* WCD CHNL Mask */
++#endif
++
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ */
++DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status;
++ struct CHNL_MGR *hChnlMgr;
++ struct CHNL_MGR_ *pChnlMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Create: phChnlMgr: 0x%x\t"
++ "hDevObject: 0x%x\tpMgrAttrs:0x%x\n",
++ phChnlMgr, hDevObject, pMgrAttrs);
++
++ *phChnlMgr = NULL;
++
++ /* Validate args: */
++ if ((0 < pMgrAttrs->cChannels) &&
++ (pMgrAttrs->cChannels <= CHNL_MAXCHANNELS)) {
++ status = DSP_SOK;
++ } else if (pMgrAttrs->cChannels == 0) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Args\n");
++ } else {
++ status = CHNL_E_MAXCHANNELS;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Error Max Channels\n");
++ }
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Word size\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ if (DSP_SUCCEEDED(status) && hChnlMgr != NULL)
++ status = CHNL_E_MGREXISTS;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnChnlCreate)(&hChnlMgr, hDevObject,
++ pMgrAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD channel module's fields of the
++ * CHNL_MGR structure */
++ pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ pChnlMgr->pIntfFxns = pIntfFxns;
++ /* Finally, return the new channel manager handle: */
++ *phChnlMgr = hChnlMgr;
++ GT_1trace(CHNL_DebugMask, GT_1CLASS,
++ "CHNL_Create: Success pChnlMgr:"
++ "0x%x\n", pChnlMgr);
++ }
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Create: pChnlMgr: 0x%x,"
++ "status: 0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ struct CHNL_MGR_ *pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Destroy: hChnlMgr: 0x%x\n", hChnlMgr);
++ if (CHNL_IsValidMgr(pChnlMgr)) {
++ pIntfFxns = pChnlMgr->pIntfFxns;
++ /* Let WMD channel module destroy the CHNL_MGR: */
++ status = (*pIntfFxns->pfnChnlDestroy)(hChnlMgr);
++ } else {
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Destroy:Invalid Handle\n");
++ status = DSP_EHANDLE;
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Destroy: pChnlMgr: 0x%x,"
++ " status:0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || !CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ */
++void CHNL_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ */
++bool CHNL_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!CHNL_DebugMask.flags);
++ GT_create(&CHNL_DebugMask, "CH"); /* "CH" for CHannel */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++
+diff --git a/drivers/dsp/bridge/pmgr/chnlobj.h b/drivers/dsp/bridge/pmgr/chnlobj.h
+new file mode 100644
+index 0000000..da74c96
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnlobj.h
+@@ -0,0 +1,71 @@
++/*
++ * chnlobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library channel objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Removed some fields from CHNL_MGR_ to match CHNL_MGR
++ *! structure defined in _chnl_sm.h.
++ *! 16-Jan-1997 gp: Created from chnlpriv.h
++ */
++
++#ifndef CHNLOBJ_
++#define CHNLOBJ_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/wmd.h>
++
++/* Object validateion macros: */
++#define CHNL_IsValidMgr(h) \
++ ((h != NULL) && ((h)->dwSignature == CHNL_MGRSIGNATURE))
++
++#define CHNL_IsValidChnl(h)\
++ ((h != NULL) && ((h)->dwSignature == CHNL_SIGNATURE))
++
++/*
++ * This struct is the first field in a CHNL_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_MGR_ {
++ /* These must be the first fields in a CHNL_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++} ;
++
++/*
++ * This struct is the first field in a CHNL_OBJECT struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_OBJECT_ {
++ /* These must be the first fields in a CHNL_OBJECT struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct CHNL_MGR_ *pChnlMgr; /* Pointer back to channel manager. */
++} ;
++
++#endif /* CHNLOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/cmm.c b/drivers/dsp/bridge/pmgr/cmm.c
+new file mode 100644
+index 0000000..99a2432
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cmm.c
+@@ -0,0 +1,1291 @@
++/*
++ * cmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmm.c ========
++ * Purpose:
++ * The Communication(Shared) Memory Management(CMM) module provides
++ * shared memory management services for DSP/BIOS Bridge data streaming
++ * and messaging.
++ *
++ * Multiple shared memory segments can be registered with CMM.
++ * Each registered SM segment is represented by a SM "allocator" that
++ * describes a block of physically contiguous shared memory used for
++ * future allocations by CMM.
++ *
++ * Memory is coelesced back to the appropriate heap when a buffer is
++ * freed.
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ *
++ * The CMM_Xlator[xxx] routines below are used by Node and Stream
++ * to perform SM address translation to the client process address space.
++ * A "translator" object is created by a node/stream for each SM seg used.
++ *
++ * Translator Routines:
++ * CMM_XlatorAllocBuf
++ * CMM_XlatorCreate
++ * CMM_XlatorDelete
++ * CMM_XlatorFreeBuf
++ * CMM_XlatorInfo
++ * CMM_XlatorTranslate
++ *
++ * Private Functions:
++ * AddToFreeList
++ * GetAllocator
++ * GetFreeBlock
++ * GetNode
++ * GetSlot
++ * UnRegisterGPPSMSeg
++ *
++ * Notes:
++ * Va: Virtual address.
++ * Pa: Physical or kernel system address.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 16-Feb-2002 ag Code review cleanup.
++ *! PreOMAP address translation no longner supported.
++ *! 30-Jan-2002 ag Updates to CMM_XlatorTranslate() per TII, ANSI C++
++ *! warnings.
++ *! 27-Jan-2002 ag Removed unused CMM_[Alloc][Free]Desc() & #ifdef USELOOKUP,
++ *! & unused VALIDATECMM and VaPaConvert().
++ *! Removed bFastXlate from CMM_XLATOR. Always fast lookup.
++ *! 03-Jan-2002 ag Clear SM in CMM_AllocBuf(). Renamed to CMM_CallocBuf().
++ *! 13-Nov-2001 ag Now delete pNodeFreeListHead and nodes in CMM_Destroy().
++ *! 28-Aug-2001 ag CMM_GetHandle() returns CMM Mgr hndle given HPROCESSOR.
++ *! Removed unused CMM_[Un]RegisterDSPSMSeg() &
++ * CMM_[Un}ReserveVirtSpace fxns. Some cleanup.
++ *! 12-Aug-2001 ag Exposed CMM_UnRegisterGPP[DSP]SMSeg.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name update.
++ *! 21-Dec-2000 rr GetFreeBlock checks for pAllocator.
++ *! 09-Dec-2000 ag Added GPPPA2DSPPA, DSPPA2GPPPA macros.
++ *! 05-Dec-2000 ag CMM_XlatorDelete() optionally frees SM bufs and descriptors.
++ *! 30-Oct-2000 ag Buf size bug fixed in CMM_AllocBuf() causing leak.
++ *! Revamped XlatorTranslate() routine.
++ *! 10-Oct-2000 ag Added CMM_Xlator[xxx] functions.
++ *! 02-Aug-2000 ag Created.
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define CMMSIGNATURE 0x004d4d43 /* "CMM" (in reverse) */
++#define SMEMSIGNATURE 0x4D454D53 /* "SMEM" SM space */
++#define CMMXLATESIGNATURE 0x584d4d43 /* "CMMX" CMM Xlator */
++
++#define NEXT_PA(pNode) (pNode->dwPA + pNode->ulSize)
++
++/* Other bus/platform translations */
++#define DSPPA2GPPPA(base, x, y) ((x)+(y))
++#define GPPPA2DSPPA(base, x, y) ((x)-(y))
++
++/*
++ * Allocators define a block of contiguous memory used for future allocations.
++ *
++ * sma - shared memory allocator.
++ * vma - virtual memory allocator.(not used).
++ */
++struct CMM_ALLOCATOR { /* sma */
++ u32 dwSignature; /* SMA allocator signature SMEMSIGNATURE */
++ unsigned int dwSmBase; /* Start of physical SM block */
++ u32 ulSmSize; /* Size of SM block in bytes */
++ unsigned int dwVmBase; /* Start of VM block. (Dev driver
++ * context for 'sma') */
++ u32 dwDSPPhysAddrOffset; /* DSP PA to GPP PA offset for this
++ * SM space */
++ /* CMM_ADDTO[SUBFROM]DSPPA, _POMAPEMIF2DSPBUS */
++ enum CMM_CNVTTYPE cFactor;
++ unsigned int dwDSPBase; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ struct CMM_OBJECT *hCmmMgr; /* back ref to parent mgr */
++ struct LST_LIST *pFreeListHead; /* node list of available memory */
++ struct LST_LIST *pInUseListHead; /* node list of memory in use */
++} ;
++
++struct CMM_XLATOR { /* Pa<->Va translator object */
++ u32 dwSignature; /* "CMMX" */
++ struct CMM_OBJECT *hCmmMgr; /* CMM object this translator associated */
++ /*
++ * Client process virtual base address that corresponds to phys SM
++ * base address for translator's ulSegId.
++ * Only 1 segment ID currently supported.
++ */
++ unsigned int dwVirtBase; /* virtual base address */
++ u32 ulVirtSize; /* size of virt space in bytes */
++ u32 ulSegId; /* Segment Id */
++} ;
++
++/* CMM Mgr */
++struct CMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /*
++ * Cmm Lock is used to serialize access mem manager for multi-threads.
++ */
++ struct SYNC_CSOBJECT *hCmmLock; /* Lock to access cmm mgr */
++ struct LST_LIST *pNodeFreeListHead; /* Free list of memory nodes */
++ u32 ulMinBlockSize; /* Min SM block; default 16 bytes */
++ u32 dwPageSize; /* Memory Page size (1k/4k) */
++ /* GPP SM segment ptrs */
++ struct CMM_ALLOCATOR *paGPPSMSegTab[CMM_MAXGPPSEGS];
++} ;
++
++/* Default CMM Mgr attributes */
++static struct CMM_MGRATTRS CMM_DFLTMGRATTRS = {
++ 16 /* ulMinBlockSize, min block size(bytes) allocated by cmm mgr */
++};
++
++/* Default allocation attributes */
++static struct CMM_ATTRS CMM_DFLTALCTATTRS = {
++ 1 /* ulSegId, default segment Id for allocator */
++};
++
++/* Address translator default attrs */
++static struct CMM_XLATORATTRS CMM_DFLTXLATORATTRS = {
++ 1, /* ulSegId, does not have to match CMM_DFLTALCTATTRS ulSegId */
++ 0, /* dwDSPBufs */
++ 0, /* dwDSPBufSize */
++ NULL, /* pVmBase */
++ 0, /* dwVmSize */
++};
++
++/* SM node representing a block of memory. */
++struct CMM_MNODE {
++ struct LST_ELEM link; /* must be 1st element */
++ u32 dwPA; /* Phys addr */
++ u32 dwVA; /* Virtual address in device process context */
++ u32 ulSize; /* SM block size in bytes */
++ u32 hClientProc; /* Process that allocated this mem block */
++} ;
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode);
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId);
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize);
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize);
++/* get available slot for new allocator */
++static s32 GetSlot(struct CMM_OBJECT *hCmmMgr);
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA);
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate a SM buffer, zero contents, and return the physical address
++ * and optional driver context virtual address(ppBufVA).
++ *
++ * The freelist is sorted in increasing size order. Get the first
++ * block that satifies the request and sort the remaining back on
++ * the freelist; if large enough. The kept block is placed on the
++ * inUseList.
++ */
++void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr, u32 uSize,
++ struct CMM_ATTRS *pAttrs, OUT void **ppBufVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ void *pBufPA = NULL;
++ struct CMM_MNODE *pNode = NULL;
++ struct CMM_MNODE *pNewNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ u32 uDeltaSize;
++ u8 *pByte = NULL;
++ s32 cnt;
++
++ if (pAttrs == NULL)
++ pAttrs = &CMM_DFLTALCTATTRS;
++
++ if (ppBufVA != NULL)
++ *ppBufVA = NULL;
++
++ if ((MEM_IsValidHandle(pCmmMgr, CMMSIGNATURE)) && (uSize != 0)) {
++ if (pAttrs->ulSegId > 0) {
++ /* SegId > 0 is SM */
++ /* get the allocator object for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, pAttrs->ulSegId);
++ /* keep block size a multiple of ulMinBlockSize */
++ uSize = ((uSize - 1) & ~(pCmmMgr->ulMinBlockSize - 1))
++ + pCmmMgr->ulMinBlockSize;
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pNode = GetFreeBlock(pAllocator, uSize);
++ }
++ if (pNode) {
++ uDeltaSize = (pNode->ulSize - uSize);
++ if (uDeltaSize >= pCmmMgr->ulMinBlockSize) {
++ /* create a new block with the leftovers and
++ * add to freelist */
++ pNewNode = GetNode(pCmmMgr, pNode->dwPA + uSize,
++ pNode->dwVA + uSize,
++ (u32)uDeltaSize);
++ /* leftovers go free */
++ AddToFreeList(pAllocator, pNewNode);
++ /* adjust our node's size */
++ pNode->ulSize = uSize;
++ }
++ /* Tag node with client process requesting allocation
++ * We'll need to free up a process's alloc'd SM if the
++ * client process goes away.
++ */
++ /* Return PID instead of process handle */
++ pNode->hClientProc = current->pid;
++
++ /* put our node on InUse list */
++ LST_PutTail(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pNode);
++ pBufPA = (void *)pNode->dwPA; /* physical address */
++ /* clear mem */
++ pByte = (u8 *)pNode->dwVA;
++ for (cnt = 0; cnt < (s32) uSize; cnt++, pByte++)
++ *pByte = 0;
++
++ if (ppBufVA != NULL) {
++ /* Virtual address */
++ *ppBufVA = (void *)pNode->dwVA;
++ }
++ }
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_CallocBuf dwPA %x, dwVA %x uSize"
++ "%x\n", pNode->dwPA, pNode->dwVA, uSize);
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return pBufPA;
++}
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ */
++DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs)
++{
++ struct CMM_OBJECT *pCmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct UTIL_SYSINFO sysInfo;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_Create: phCmmMgr: 0x%x\thDevObject: "
++ "0x%x\tpMgrAttrs: 0x%x\n", phCmmMgr, hDevObject, pMgrAttrs);
++ *phCmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pCmmObject, struct CMM_OBJECT, CMMSIGNATURE);
++ if (pCmmObject != NULL) {
++ if (pMgrAttrs == NULL)
++ pMgrAttrs = &CMM_DFLTMGRATTRS; /* set defaults */
++
++ /* 4 bytes minimum */
++ DBC_Assert(pMgrAttrs->ulMinBlockSize >= 4);
++ /* save away smallest block allocation for this cmm mgr */
++ pCmmObject->ulMinBlockSize = pMgrAttrs->ulMinBlockSize;
++ /* save away the systems memory page size */
++ sysInfo.dwPageSize = PAGE_SIZE;
++ sysInfo.dwAllocationGranularity = PAGE_SIZE;
++ sysInfo.dwNumberOfProcessors = 1;
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CMM_debugMask, GT_5CLASS,
++ "CMM_Create: Got system page size"
++ "= 0x%x\t\n", sysInfo.dwPageSize);
++ pCmmObject->dwPageSize = sysInfo.dwPageSize;
++ } else {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: failed to get system"
++ "page size\n");
++ pCmmObject->dwPageSize = 0;
++ status = DSP_EFAIL;
++ }
++ /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
++ * MEM_AllocObject */
++ if (DSP_SUCCEEDED(status)) {
++ /* create node free list */
++ pCmmObject->pNodeFreeListHead = LST_Create();
++ if (pCmmObject->pNodeFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: LST_Create() "
++ "failed \n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pCmmObject->hCmmLock);
++
++ if (DSP_SUCCEEDED(status))
++ *phCmmMgr = pCmmObject;
++ else
++ CMM_Destroy(pCmmObject, true);
++
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_Create: Object Allocation "
++ "Failure(CMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_INFO tempInfo;
++ DSP_STATUS status = DSP_SOK;
++ s32 nSlot;
++ struct CMM_MNODE *pNode;
++
++ DBC_Require(cRefs > 0);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* If not force then fail if outstanding allocations exist */
++ if (!bForce) {
++ /* Check for outstanding memory allocations */
++ status = CMM_GetInfo(hCmmMgr, &tempInfo);
++ if (DSP_SUCCEEDED(status)) {
++ if (tempInfo.ulTotalInUseCnt > 0) {
++ /* outstanding allocations */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* UnRegister SM allocator */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] != NULL) {
++ UnRegisterGPPSMSeg(pCmmMgr->
++ paGPPSMSegTab[nSlot]);
++ /* Set slot to NULL for future reuse */
++ pCmmMgr->paGPPSMSegTab[nSlot] = NULL;
++ }
++ }
++ }
++ if (pCmmMgr->pNodeFreeListHead != NULL) {
++ /* Free the free nodes */
++ while (!LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ /* (struct LST_ELEM*) pNode =
++ * LST_GetHead(pCmmMgr->pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ MEM_Free(pNode);
++ }
++ /* delete NodeFreeList list */
++ LST_Delete(pCmmMgr->pNodeFreeListHead);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (DSP_SUCCEEDED(status)) {
++ /* delete CS & cmm mgr object */
++ SYNC_DeleteCS(pCmmMgr->hCmmLock);
++ MEM_FreeObject(pCmmMgr);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void CMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "exiting CMM_Exit,ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ */
++DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr, void *pBufPA, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_EPOINTER;
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ struct CMM_ATTRS *pAttrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPA != NULL);
++ GT_1trace(CMM_debugMask, GT_ENTER, "CMM_FreeBuf pBufPA %x\n", pBufPA);
++ if (ulSegId == 0) {
++ pAttrs = &CMM_DFLTALCTATTRS;
++ ulSegId = pAttrs->ulSegId;
++ }
++ if (!(MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) || !(ulSegId > 0)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* get the allocator for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, ulSegId);
++ if (pAllocator != NULL) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->
++ pInUseListHead);
++ while (pCurNode) {
++ if ((u32)pBufPA == pCurNode->dwPA) {
++ /* Found it */
++ LST_RemoveElem(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ /* back to freelist */
++ AddToFreeList(pAllocator, pCurNode);
++ status = DSP_SOK; /* all right! */
++ break;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pInUseListHead, (struct LST_ELEM *)pCurNode);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the communication memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetCmmMgr(hDevObject, phCmmMgr);
++
++ return status;
++}
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current memory utilization information.
++ */
++DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ u32 ulSeg;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pAltr;
++ struct CMM_MNODE *pCurNode = NULL;
++
++ DBC_Require(pCmmInfo != NULL);
++
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCmmInfo->ulNumGPPSMSegs = 0; /* # of SM segments */
++ pCmmInfo->ulTotalInUseCnt = 0; /* Total # of outstanding alloc */
++ pCmmInfo->ulMinBlockSize = pCmmMgr->ulMinBlockSize; /* min block size */
++ /* check SM memory segments */
++ for (ulSeg = 1; ulSeg <= CMM_MAXGPPSEGS; ulSeg++) {
++ /* get the allocator object for this segment id */
++ pAltr = GetAllocator(pCmmMgr, ulSeg);
++ if (pAltr != NULL) {
++ pCmmInfo->ulNumGPPSMSegs++;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBasePa =
++ pAltr->dwSmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulTotalSegSize =
++ pAltr->ulDSPSize + pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwGPPBasePA =
++ pAltr->dwSmBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulGPPSize =
++ pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwDSPBaseVA =
++ pAltr->dwDSPBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulDSPSize =
++ pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBaseVa =
++ pAltr->dwVmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt = 0;
++ pCurNode = (struct CMM_MNODE *)LST_First(pAltr->
++ pInUseListHead);
++ /* Count inUse blocks */
++ while (pCurNode) {
++ pCmmInfo->ulTotalInUseCnt++;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt++;
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAltr->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ }
++ }
++ } /* end for */
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ */
++bool CMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /* "CM" for Comm Memory manager */
++ GT_create(&CMM_debugMask, "CM");
++ }
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "Entered CMM_Init,ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM to be used for later GPP SM
++ * allocations.
++ */
++DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 dwGPPBasePA,
++ u32 ulSize, u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor, u32 dwDSPBase,
++ u32 ulDSPSize, u32 *pulSegId,
++ u32 dwGPPBaseVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_ALLOCATOR *pSMA = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_MNODE *pNewNode;
++ s32 nSlot;
++
++ DBC_Require(ulSize > 0);
++ DBC_Require(pulSegId != NULL);
++ DBC_Require(dwGPPBasePA != 0);
++ DBC_Require(dwGPPBaseVA != 0);
++ DBC_Require((cFactor <= CMM_ADDTODSPPA) &&
++ (cFactor >= CMM_SUBFROMDSPPA));
++ GT_6trace(CMM_debugMask, GT_ENTER,
++ "CMM_RegisterGPPSMSeg dwGPPBasePA %x "
++ "ulSize %x dwDSPAddrOffset %x dwDSPBase %x ulDSPSize %x "
++ "dwGPPBaseVA %x\n", dwGPPBasePA, ulSize, dwDSPAddrOffset,
++ dwDSPBase, ulDSPSize, dwGPPBaseVA);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* make sure we have room for another allocator */
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ nSlot = GetSlot(pCmmMgr);
++ if (nSlot < 0) {
++ /* get a slot number */
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* Check if input ulSize is big enough to alloc at least one block */
++ if (DSP_SUCCEEDED(status)) {
++ if (ulSize < pCmmMgr->ulMinBlockSize) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "ulSize too small\n");
++ status = DSP_EINVALIDARG;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create, zero, and tag an SM allocator object */
++ MEM_AllocObject(pSMA, struct CMM_ALLOCATOR, SMEMSIGNATURE);
++ }
++ if (pSMA != NULL) {
++ pSMA->hCmmMgr = hCmmMgr; /* ref to parent */
++ pSMA->dwSmBase = dwGPPBasePA; /* SM Base phys */
++ pSMA->ulSmSize = ulSize; /* SM segment size in bytes */
++ pSMA->dwVmBase = dwGPPBaseVA;
++ pSMA->dwDSPPhysAddrOffset = dwDSPAddrOffset;
++ pSMA->cFactor = cFactor;
++ pSMA->dwDSPBase = dwDSPBase;
++ pSMA->ulDSPSize = ulDSPSize;
++ if (pSMA->dwVmBase == 0) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Error"
++ "MEM_LinearAddress()\n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* return the actual segment identifier */
++ *pulSegId = (u32) nSlot + 1;
++ /* create memory free list */
++ pSMA->pFreeListHead = LST_Create();
++ if (pSMA->pFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "Out Of Memory \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create memory in-use list */
++ pSMA->pInUseListHead = LST_Create();
++ if (pSMA->pInUseListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "LST_Create failed\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a mem node for this hunk-o-memory */
++ pNewNode = GetNode(pCmmMgr, dwGPPBasePA,
++ pSMA->dwVmBase, ulSize);
++ /* Place node on the SM allocator's free list */
++ if (pNewNode) {
++ LST_PutTail(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pNewNode);
++ } else {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Cleanup allocator */
++ UnRegisterGPPSMSeg(pSMA);
++ }
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_RegisterGPPSMSeg: SMA Object "
++ "Allocation Failure\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ /* make entry */
++ if (DSP_SUCCEEDED(status))
++ pCmmMgr->paGPPSMSegTab[nSlot] = pSMA;
++
++func_end:
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister GPP SM segments with the CMM.
++ */
++DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pSMA;
++ u32 ulId = ulSegId;
++
++ DBC_Require(ulSegId > 0);
++ if (MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ if (ulSegId == CMM_ALLSEGMENTS)
++ ulId = 1;
++
++ if ((ulId > 0) && (ulId <= CMM_MAXGPPSEGS)) {
++ while (ulId <= CMM_MAXGPPSEGS) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* slot = segId-1 */
++ pSMA = pCmmMgr->paGPPSMSegTab[ulId - 1];
++ if (pSMA != NULL) {
++ UnRegisterGPPSMSeg(pSMA);
++ /* Set alctr ptr to NULL for future
++ * reuse */
++ pCmmMgr->paGPPSMSegTab[ulId - 1] = NULL;
++ } else if (ulSegId != CMM_ALLSEGMENTS) {
++ status = DSP_EFAIL;
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (ulSegId != CMM_ALLSEGMENTS)
++ break;
++
++ ulId++;
++ } /* end while */
++ } else {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_UnRegisterGPPSMSeg: Bad "
++ "segment Id\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister the SM allocator by freeing all its resources and
++ * nulling cmm mgr table entry.
++ * Note:
++ * This routine is always called within cmm lock crit sect.
++ */
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA)
++{
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_MNODE *pNextNode = NULL;
++
++ DBC_Require(pSMA != NULL);
++ if (pSMA->pFreeListHead != NULL) {
++ /* free nodes on free list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pFreeListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pFreeListHead); /* delete freelist */
++ /* free nodes on InUse list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pInUseListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pInUseListHead); /* delete InUse list */
++ }
++ if ((void *) pSMA->dwVmBase != NULL)
++ MEM_UnmapLinearAddress((void *) pSMA->dwVmBase);
++
++ /* Free allocator itself */
++ MEM_FreeObject(pSMA);
++}
++
++/*
++ * ======== GetSlot ========
++ * Purpose:
++ * An available slot # is returned. Returns negative on failure.
++ */
++static s32 GetSlot(struct CMM_OBJECT *pCmmMgr)
++{
++ s32 nSlot = -1; /* neg on failure */
++ DBC_Require(pCmmMgr != NULL);
++ /* get first available slot in cmm mgr SMSegTab[] */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] == NULL)
++ break;
++
++ }
++ if (nSlot == CMM_MAXGPPSEGS) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Allocator "
++ "entry failure, max exceeded\n");
++ nSlot = -1; /* failed */
++ }
++ return nSlot;
++}
++
++/*
++ * ======== GetNode ========
++ * Purpose:
++ * Get a memory node from freelist or create a new one.
++ */
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize)
++{
++ struct CMM_MNODE *pNode = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require(dwPA != 0);
++ DBC_Require(dwVA != 0);
++ DBC_Require(ulSize != 0);
++ /* Check cmm mgr's node freelist */
++ if (LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ pNode = (struct CMM_MNODE *)MEM_Calloc(sizeof(struct CMM_MNODE),
++ MEM_PAGED);
++ } else {
++ /* surely a valid element */
++ /* (struct LST_ELEM*) pNode = LST_GetHead(pCmmMgr->
++ * pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ }
++ if (pNode == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS, "GetNode: Out Of Memory\n");
++ } else {
++ LST_InitElem((struct LST_ELEM *) pNode); /* set self */
++ pNode->dwPA = dwPA; /* Physical addr of start of block */
++ pNode->dwVA = dwVA; /* Virtual " " */
++ pNode->ulSize = ulSize; /* Size of block */
++ }
++ return pNode;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Put a memory node on the cmm nodelist for later use.
++ * Doesn't actually delete the node. Heap thrashing friendly.
++ */
++static void DeleteNode(struct CMM_OBJECT *pCmmMgr, struct CMM_MNODE *pNode)
++{
++ DBC_Require(pNode != NULL);
++ LST_InitElem((struct LST_ELEM *) pNode); /* init .self ptr */
++ LST_PutTail(pCmmMgr->pNodeFreeListHead, (struct LST_ELEM *) pNode);
++}
++
++/*
++ * ====== GetFreeBlock ========
++ * Purpose:
++ * Scan the free block list and return the first block that satisfies
++ * the size.
++ */
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize)
++{
++ if (pAllocator) {
++ struct CMM_MNODE *pCurNode = (struct CMM_MNODE *)
++ LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (uSize <= (u32) pCurNode->ulSize) {
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ return pCurNode;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ }
++ return NULL;
++}
++
++/*
++ * ======== AddToFreeList ========
++ * Purpose:
++ * Coelesce node into the freelist in ascending size order.
++ */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode)
++{
++ struct CMM_MNODE *pNodePrev = NULL;
++ struct CMM_MNODE *pNodeNext = NULL;
++ struct CMM_MNODE *pCurNode;
++ u32 dwThisPA;
++ u32 dwNextPA;
++
++ DBC_Require(pNode != NULL);
++ DBC_Require(pAllocator != NULL);
++ dwThisPA = pNode->dwPA;
++ dwNextPA = NEXT_PA(pNode);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (dwThisPA == NEXT_PA(pCurNode)) {
++ /* found the block ahead of this one */
++ pNodePrev = pCurNode;
++ } else if (dwNextPA == pCurNode->dwPA) {
++ pNodeNext = pCurNode;
++ }
++ if ((pNodePrev == NULL) || (pNodeNext == NULL)) {
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ } else {
++ /* got 'em */
++ break;
++ }
++ } /* while */
++ if (pNodePrev != NULL) {
++ /* combine with previous block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodePrev);
++ /* grow node to hold both */
++ pNode->ulSize += pNodePrev->ulSize;
++ pNode->dwPA = pNodePrev->dwPA;
++ pNode->dwVA = pNodePrev->dwVA;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodePrev);
++ }
++ if (pNodeNext != NULL) {
++ /* combine with next block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodeNext);
++ /* grow da node */
++ pNode->ulSize += pNodeNext->ulSize;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodeNext);
++ }
++ /* Now, let's add to freelist in increasing size order */
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (pNode->ulSize <= pCurNode->ulSize)
++ break;
++
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ /* if pCurNode is NULL then add our pNode to the end of the freelist */
++ if (pCurNode == NULL) {
++ LST_PutTail(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode);
++ } else {
++ /* insert our node before the current traversed node */
++ LST_InsertBefore(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode,
++ (struct LST_ELEM *)pCurNode);
++ }
++}
++
++/*
++ * ======== GetAllocator ========
++ * Purpose:
++ * Return the allocator for the given SM Segid.
++ * SegIds: 1,2,3..max.
++ */
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId)
++{
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require((ulSegId > 0) && (ulSegId <= CMM_MAXGPPSEGS));
++ pAllocator = pCmmMgr->paGPPSMSegTab[ulSegId - 1];
++ if (pAllocator != NULL) {
++ /* make sure it's for real */
++ if (!MEM_IsValidHandle(pAllocator, SMEMSIGNATURE)) {
++ pAllocator = NULL;
++ DBC_Assert(false);
++ }
++ }
++ return pAllocator;
++}
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create an address translator object.
++ */
++DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs)
++{
++ struct CMM_XLATOR *pXlatorObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phXlator != NULL);
++ DBC_Require(hCmmMgr != NULL);
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_XlatorCreate: phXlator: 0x%x\t"
++ "phCmmMgr: 0x%x\tpXlAttrs: 0x%x\n", phXlator,
++ hCmmMgr, pXlatorAttrs);
++ *phXlator = NULL;
++ if (pXlatorAttrs == NULL)
++ pXlatorAttrs = &CMM_DFLTXLATORATTRS; /* set defaults */
++
++ MEM_AllocObject(pXlatorObject, struct CMM_XLATOR, CMMXLATESIGNATURE);
++ if (pXlatorObject != NULL) {
++ pXlatorObject->hCmmMgr = hCmmMgr; /* ref back to CMM */
++ pXlatorObject->ulSegId = pXlatorAttrs->ulSegId; /* SM segId */
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_XlatorCreate: Object Allocation"
++ "Failure(CMM Xlator)\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status))
++ *phXlator = (struct CMM_XLATOROBJECT *) pXlatorObject;
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Free the Xlator resources.
++ * VM gets freed later.
++ */
++DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator, bool bForce)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ MEM_FreeObject(pXlator);
++ } else {
++ status = DSP_EHANDLE;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ */
++void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator, void *pVaBuf,
++ u32 uPaSize)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ void *pBuf = NULL;
++ struct CMM_ATTRS attrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hXlator != NULL);
++ DBC_Require(pXlator->hCmmMgr != NULL);
++ DBC_Require(pVaBuf != NULL);
++ DBC_Require(uPaSize > 0);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ attrs.ulSegId = pXlator->ulSegId;
++ *(volatile u32 *)pVaBuf = 0;
++ /* Alloc SM */
++ pBuf = CMM_CallocBuf(pXlator->hCmmMgr, uPaSize, &attrs, NULL);
++ if (pBuf) {
++ /* convert to translator(node/strm) process Virtual
++ * address */
++ *(volatile u32 **)pVaBuf =
++ (u32 *)CMM_XlatorTranslate(hXlator,
++ pBuf, CMM_PA2VA);
++ }
++ }
++ return pBuf;
++}
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free the given SM buffer and descriptor.
++ * Does not free virtual memory.
++ */
++DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator, void *pBufVa)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_EFAIL;
++ void *pBufPa = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufVa != NULL);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ /* convert Va to Pa so we can free it. */
++ pBufPa = CMM_XlatorTranslate(hXlator, pBufVa, CMM_VA2PA);
++ if (pBufPa) {
++ status = CMM_FreeBuf(pXlator->hCmmMgr, pBufPa,
++ pXlator->ulSegId);
++ if (DSP_FAILED(status)) {
++ /* Uh oh, this shouldn't happen. Descriptor
++ * gone! */
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "Cannot free DMA/ZCPY buffer"
++ "not allocated by MPU. PA %x, VA %x\n",
++ pBufPa, pBufVa);
++ DBC_Assert(false); /* CMM is leaking mem! */
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get translator info.
++ */
++DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator, IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId, bool bSetInfo)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((uSegId > 0) && (uSegId <= CMM_MAXGPPSEGS));
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ if (bSetInfo) {
++ /* set translators virtual address range */
++ pXlator->dwVirtBase = (u32)*pAddr;
++ pXlator->ulVirtSize = ulSize;
++ GT_2trace(CMM_debugMask, GT_3CLASS,
++ "pXlator->dwVirtBase %x, "
++ "ulVirtSize %x\n", pXlator->dwVirtBase,
++ pXlator->ulVirtSize);
++ } else { /* return virt base address */
++ *pAddr = (u8 *)pXlator->dwVirtBase;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ */
++void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator, void *pAddr,
++ enum CMM_XLATETYPE xType)
++{
++ u32 dwAddrXlate = 0;
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ struct CMM_OBJECT *pCmmMgr = NULL;
++ struct CMM_ALLOCATOR *pAlctr = NULL;
++ u32 dwOffset = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA));
++
++ if (!MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE))
++ goto loop_cont;
++
++ pCmmMgr = (struct CMM_OBJECT *)pXlator->hCmmMgr;
++ /* get this translator's default SM allocator */
++ DBC_Assert(pXlator->ulSegId > 0);
++ pAlctr = pCmmMgr->paGPPSMSegTab[pXlator->ulSegId - 1];
++ if (!MEM_IsValidHandle(pAlctr, SMEMSIGNATURE))
++ goto loop_cont;
++
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_VA2PA) ||
++ (xType == CMM_PA2VA)) {
++ if (xType == CMM_PA2VA) {
++ /* Gpp Va = Va Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)(pAlctr->dwSmBase -
++ pAlctr->ulDSPSize);
++ dwAddrXlate = pXlator->dwVirtBase + dwOffset;
++ /* Check if translated Va base is in range */
++ if ((dwAddrXlate < pXlator->dwVirtBase) ||
++ (dwAddrXlate >=
++ (pXlator->dwVirtBase + pXlator->ulVirtSize))) {
++ dwAddrXlate = 0; /* bad address */
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: "
++ "Virt addr out of range\n");
++ }
++ } else {
++ /* Gpp PA = Gpp Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)pXlator->dwVirtBase;
++ dwAddrXlate = pAlctr->dwSmBase - pAlctr->ulDSPSize +
++ dwOffset;
++ }
++ } else {
++ dwAddrXlate = (u32)pAddr;
++ }
++ /*Now convert address to proper target physical address if needed*/
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_PA2DSPPA)) {
++ /* Got Gpp Pa now, convert to DSP Pa */
++ dwAddrXlate = GPPPA2DSPPA((pAlctr->dwSmBase - pAlctr->
++ ulDSPSize), dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ } else if (xType == CMM_DSPPA2PA) {
++ /* Got DSP Pa, convert to GPP Pa */
++ dwAddrXlate = DSPPA2GPPPA(pAlctr->dwSmBase - pAlctr->ulDSPSize,
++ dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ }
++loop_cont:
++ if (!dwAddrXlate) {
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: Can't translate"
++ " address: 0x%x xType %x\n", pAddr, xType);
++ } else {
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_XlatorTranslate: pAddr %x, xType"
++ " %x, dwAddrXlate %x\n", pAddr, xType, dwAddrXlate);
++ }
++ return (void *)dwAddrXlate;
++}
+diff --git a/drivers/dsp/bridge/pmgr/cod.c b/drivers/dsp/bridge/pmgr/cod.c
+new file mode 100644
+index 0000000..6363f1e
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cod.c
+@@ -0,0 +1,683 @@
++/*
++ * cod.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.c ========
++ * This module implements DSP code management for the DSP/BIOS Bridge
++ * environment. It is mostly a thin wrapper.
++ *
++ * This module provides an interface for loading both static and
++ * dynamic code objects onto DSP systems.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Consolidated DBL to DBLL loader name
++ *! 24-Feb-2003 swa: PMGR Code review comments incorporated.
++ *! 18-Apr-2002 jeh: Added DBL function tables.
++ *! 20-Nov-2001 jeh: Removed call to ZL_loadArgs function.
++ *! 19-Oct-2001 jeh: Access DBL as a static library. Added COD_GetBaseLib,
++ *! COD_GetLoader, removed COD_LoadSection, COD_UnloadSection.
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 07-Aug-2001 rr: hMgr->baseLib is updated after zlopen in COD_LoadBase.
++ *! 18-Apr-2001 jeh: Check for fLoaded flag before ZL_unload, to allow
++ *! COD_OpenBase to be used.
++ *! 11-Jan-2001 jeh: Added COD_OpenBase (not used yet, since there is an
++ *! occasional crash).
++ *! 02-Aug-2000 kc: Added COD_ReadSection to COD module. Incorporates use
++ *! of ZL_readSect (new function in ZL module).
++ *! 28-Feb-2000 rr: New GT Usage Implementation
++ *! 08-Dec-1999 ag: Removed x86 specific __asm int 3.
++ *! 02-Oct-1999 ag: Added #ifdef DEBUGINT3COD for debug.
++ *! 20-Sep-1999 ag: Removed call to GT_set().
++ *! 04-Jun-1997 cr: Added validation of argc/argv pair in COD_LoadBase, as it
++ *! is a requirement to ZL_loadArgs.
++ *! 31-May-1997 cr: Changed COD_LoadBase argc value from u32 to int, added
++ *! DSP_ENOTIMPL return value to COD_Create when attrs != NULL.
++ *! 29-May-1997 cr: Added debugging support.
++ *! 24-Oct-1996 gp: Added COD_GetSection().
++ *! 18-Jun-1996 gp: Updated GetSymValue() to check for lib; updated E_ codes.
++ *! 12-Jun-1996 gp: Imported CSL_ services for strcpyn(); Added ref counting.
++ *! 20-May-1996 mg: Adapted for new MEM and LDR modules.
++ *! 08-May-1996 mg: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++/* Include appropriate loader header file */
++#include <dspbridge/dbll.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cod.h>
++
++/* magic number for handle validation */
++#define MAGIC 0xc001beef
++
++/* macro to validate COD manager handles */
++#define IsValid(h) ((h) != NULL && (h)->ulMagic == MAGIC)
++
++/*
++ * ======== COD_MANAGER ========
++ */
++struct COD_MANAGER {
++ struct DBLL_TarObj *target;
++ struct DBLL_LibraryObj *baseLib;
++ bool fLoaded; /* Base library loaded? */
++ u32 ulEntry;
++ struct LDR_MODULE *hDll;
++ struct DBLL_Fxns fxns;
++ struct DBLL_Attrs attrs;
++ char szZLFile[COD_MAXPATHLENGTH];
++ u32 ulMagic;
++} ;
++
++/*
++ * ======== COD_LIBRARYOBJ ========
++ */
++struct COD_LIBRARYOBJ {
++ struct DBLL_LibraryObj *dbllLib;
++ struct COD_MANAGER *hCodMgr;
++} ;
++
++static u32 cRefs = 0L;
++
++#if GT_TRACE
++static struct GT_Mask COD_debugMask = { NULL, NULL };
++#endif
++
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static bool NoOp(void);
++
++/*
++ * ======== COD_Close ========
++ */
++void COD_Close(struct COD_LIBRARYOBJ *lib)
++{
++ struct COD_MANAGER *hMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(((struct COD_LIBRARYOBJ *)lib)->hCodMgr));
++
++ hMgr = lib->hCodMgr;
++ hMgr->fxns.closeFxn(lib->dbllLib);
++
++ MEM_Free(lib);
++}
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system.
++ * This object can be used to load an initial program image with
++ * arguments that can later be expanded with
++ * dynamically loaded object files.
++ *
++ */
++DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs)
++{
++ struct COD_MANAGER *hMgrNew;
++ struct DBLL_Attrs zlAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Create, Args: \t\nphMgr: "
++ "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n",
++ phMgr, pstrDummyFile, attrs);
++ /* assume failure */
++ *phMgr = NULL;
++
++ /* we don't support non-default attrs yet */
++ if (attrs != NULL)
++ return DSP_ENOTIMPL;
++
++ hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED);
++ if (hMgrNew == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Create: Out Of Memory\n");
++ return DSP_EMEMORY;
++ }
++
++ hMgrNew->ulMagic = MAGIC;
++
++ /* Set up loader functions */
++ hMgrNew->fxns = dbllFxns;
++
++ /* initialize the ZL module */
++ hMgrNew->fxns.initFxn();
++
++ zlAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ zlAttrs.free = (DBLL_FreeFxn)NoOp;
++ zlAttrs.fread = (DBLL_ReadFxn)KFILE_Read;
++ zlAttrs.fseek = (DBLL_SeekFxn)KFILE_Seek;
++ zlAttrs.ftell = (DBLL_TellFxn)KFILE_Tell;
++ zlAttrs.fclose = (DBLL_FCloseFxn)KFILE_Close;
++ zlAttrs.fopen = (DBLL_FOpenFxn)KFILE_Open;
++ zlAttrs.symLookup = NULL;
++ zlAttrs.baseImage = true;
++ zlAttrs.logWrite = NULL;
++ zlAttrs.logWriteHandle = NULL;
++ zlAttrs.write = NULL;
++ zlAttrs.rmmHandle = NULL;
++ zlAttrs.wHandle = NULL;
++ zlAttrs.symHandle = NULL;
++ zlAttrs.symArg = NULL;
++
++ hMgrNew->attrs = zlAttrs;
++
++ status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs);
++
++ if (DSP_FAILED(status)) {
++ COD_Delete(hMgrNew);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Create:ZL Create Failed: 0x%x\n", status);
++ return COD_E_ZLCREATEFAILED;
++ }
++
++ /* return the new manager */
++ *phMgr = hMgrNew;
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "COD_Create: Success CodMgr: 0x%x\n", *phMgr);
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ */
++void COD_Delete(struct COD_MANAGER *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_Delete:hMgr 0x%x\n", hMgr);
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded)
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ }
++ if (hMgr->target) {
++ hMgr->fxns.deleteFxn(hMgr->target);
++ hMgr->fxns.exitFxn();
++ }
++ hMgr->ulMagic = ~MAGIC;
++ MEM_Free(hMgr);
++}
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ *
++ */
++void COD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ */
++DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(plib != NULL);
++
++ *plib = (struct DBLL_LibraryObj *) hManager->baseLib;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetBaseName ========
++ */
++DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager, char *pszName,
++ u32 uSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pszName != NULL);
++
++ if (uSize <= COD_MAXPATHLENGTH)
++ strncpy(pszName, hManager->szZLFile, uSize);
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ *
++ */
++DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager, u32 *pulEntry)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pulEntry != NULL);
++
++ *pulEntry = hManager->ulEntry;
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_GetEntry:ulEntr 0x%x\n",
++ *pulEntry);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBLL loader.
++ */
++DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(phLoader != NULL);
++
++ *phLoader = (struct DBLL_TarObj *)hManager->target;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ */
++DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT u32 *puAddr, OUT u32 *puLen)
++{
++ struct COD_MANAGER *hManager;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(puAddr != NULL);
++ DBC_Require(puLen != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER,
++ "Entered COD_GetSection Args \t\n lib: "
++ "0x%x\t\npstrsect: 0x%x\t\npuAddr: 0x%x\t\npuLen: 0x%x\n",
++ lib, pstrSect, puAddr, puLen);
++ *puAddr = 0;
++ *puLen = 0;
++ if (lib != NULL) {
++ hManager = lib->hCodMgr;
++ status = hManager->fxns.getSectFxn(lib->dbllLib, pstrSect,
++ puAddr, puLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection: Section %s not"
++ "found\n", pstrSect);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection:No Symbols loaded\n");
++ }
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ *
++ */
++DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hMgr, char *pstrSym,
++ u32 *pulValue)
++{
++ struct DBLL_Symbol *pSym;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pstrSym != NULL);
++ DBC_Require(pulValue != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_GetSymValue Args \t\n"
++ "hMgr: 0x%x\t\npstrSym: 0x%x\t\npulValue: 0x%x\n",
++ hMgr, pstrSym, pulValue);
++ if (hMgr->baseLib) {
++ if (!hMgr->fxns.getAddrFxn(hMgr->baseLib, pstrSym, &pSym)) {
++ if (!hMgr->fxns.getCAddrFxn(hMgr->baseLib, pstrSym,
++ &pSym)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSymValue: "
++ "Symbols not found\n");
++ return COD_E_SYMBOLNOTFOUND;
++ }
++ }
++ } else {
++ GT_0trace(COD_debugMask, GT_7CLASS, "COD_GetSymValue: "
++ "No Symbols loaded\n");
++ return COD_E_NOSYMBOLSLOADED;
++ }
++
++ *pulValue = pSym->value;
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ *
++ */
++bool COD_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!COD_debugMask.flags);
++ GT_create(&COD_debugMask, "CO");
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "Entered COD_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0));
++ return fRetVal;
++}
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Details:
++ * if nArgc doesn't match the number of arguments in the aArgs array, the
++ * aArgs array is searched for a NULL terminating entry, and argc is
++ * recalculated to reflect this. In this way, we can support NULL
++ * terminating aArgs arrays, if nArgc is very large.
++ */
++DSP_STATUS COD_LoadBase(struct COD_MANAGER *hMgr, u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb, char *envp[])
++{
++ DBLL_Flags flags;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DSP_STATUS status;
++ u32 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(nArgc > 0);
++ DBC_Require(aArgs != NULL);
++ DBC_Require(aArgs[0] != NULL);
++ DBC_Require(pfnWrite != NULL);
++ DBC_Require(hMgr->baseLib != NULL);
++
++ GT_6trace(COD_debugMask, GT_ENTER,
++ "Entered COD_LoadBase, hMgr: 0x%x\n \t"
++ "nArgc: 0x%x\n\taArgs: 0x%x\n\tpfnWrite: 0x%x\n\tpArb:"
++ " 0x%x\n \tenvp: 0x%x\n", hMgr, nArgc, aArgs, pfnWrite,
++ pArb, envp);
++ /*
++ * Make sure every argv[] stated in argc has a value, or change argc to
++ * reflect true number in NULL terminated argv array.
++ */
++ for (i = 0; i < nArgc; i++) {
++ if (aArgs[i] == NULL) {
++ nArgc = i;
++ break;
++ }
++ }
++
++ /* set the write function for this operation */
++ hMgr->fxns.getAttrsFxn(hMgr->target, &saveAttrs);
++
++ newAttrs = saveAttrs;
++ newAttrs.write = (DBLL_WriteFxn)pfnWrite;
++ newAttrs.wHandle = pArb;
++ newAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ newAttrs.free = (DBLL_FreeFxn)NoOp;
++ newAttrs.logWrite = NULL;
++ newAttrs.logWriteHandle = NULL;
++
++ /* Load the image */
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = hMgr->fxns.loadFxn(hMgr->baseLib, flags, &newAttrs,
++ &hMgr->ulEntry);
++ if (DSP_FAILED(status)) {
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_LoadBase: COD Load failed: "
++ "0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status))
++ hMgr->fLoaded = true;
++ else
++ hMgr->baseLib = NULL;
++
++ return status;
++}
++
++/*
++ * ======== COD_Open ========
++ * Open library for reading sections.
++ */
++DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_LIBRARYOBJ *lib = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++ DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB);
++ DBC_Require(pLib != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t "
++ "pszCoffPath: 0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr,
++ pszCoffPath, flags, pLib);
++
++ *pLib = NULL;
++
++ lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED);
++ if (lib == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Open: Out Of Memory\n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lib->hCodMgr = hMgr;
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags,
++ &lib->dbllLib);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Open failed: 0x%x\n", status);
++ } else {
++ *pLib = lib;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections.
++ */
++DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++
++ GT_2trace(COD_debugMask, GT_ENTER,
++ "Entered COD_OpenBase, hMgr: 0x%x\n\t"
++ "pszCoffPath: 0x%x\n", hMgr, pszCoffPath);
++
++ /* if we previously opened a base image, close it now */
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "Base Image is already loaded. "
++ "Unloading it...\n");
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++ hMgr->fLoaded = false;
++ }
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ hMgr->baseLib = NULL;
++ } else {
++ GT_0trace(COD_debugMask, GT_1CLASS,
++ "COD_OpenBase: Opening the base image ...\n");
++ }
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_OpenBase: COD Open failed\n");
++ } else {
++ /* hang onto the library for subsequent sym table usage */
++ hMgr->baseLib = lib;
++ strncpy(hMgr->szZLFile, pszCoffPath, COD_MAXPATHLENGTH);
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ */
++DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT char *pstrContent, IN u32 cContentSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(pstrContent != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_ReadSection Args: 0x%x,"
++ " 0x%x, 0x%x, 0x%x\n", lib, pstrSect, pstrContent,
++ cContentSize);
++
++ if (lib != NULL) {
++ status = lib->hCodMgr->fxns.readSectFxn(lib->dbllLib, pstrSect,
++ pstrContent,
++ cContentSize);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection failed: 0x%lx\n", status);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection: No Symbols loaded\n");
++ }
++ return status;
++}
++
++/*
++ * ======== NoOp ========
++ * Purpose:
++ * No Operation.
++ *
++ */
++static bool NoOp(void)
++{
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbl.c b/drivers/dsp/bridge/pmgr/dbl.c
+new file mode 100644
+index 0000000..641b011
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbl.c
+@@ -0,0 +1,1385 @@
++/*
++ * dbl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.c ========
++ * Dynamic BOF Loader library. Contains functions related to
++ * loading and unloading symbols/code/data on DSP.
++ * Also contains other support functions.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 24-May-2002 jeh Free DCD sects in DBL_close().
++ *! 19-Mar-2002 jeh Changes made to match dynamic loader (dbll.c): Pass
++ *! DBL_Library to DBL_getAddr() instead of DBL_Target,
++ *! eliminate scope param, use DBL_Symbol. Pass attrs to
++ *! DBL_load(), DBL_unload().
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 31-Jul-2001 jeh Include windows.h.
++ *! 06-Jun-2001 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbof.h>
++#include <dspbridge/dbl.h>
++
++#define DBL_TARGSIGNATURE 0x544c4244 /* "TLBD" */
++#define DBL_LIBSIGNATURE 0x4c4c4244 /* "LLBD" */
++
++#define C54TARG 0
++#define C55TARG 1
++#define NUMTARGS 2
++
++#define C54MAGIC 0x98 /* Magic number for TI C54 COF */
++#define C55MAGIC 0x9c /* Magic number for LEAD3 (C55) COF */
++
++/* Three task phases */
++#define CREATEPHASE 0
++#define DELETEPHASE 1
++#define EXECUTEPHASE 2
++#define NONE 3 /* For overlay section with phase not specified */
++
++/* Default load buffer size */
++#define LOADBUFSIZE 0x800
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++/*
++ * Macros for accessing the following types of overlay data within a
++ * structure of type OvlyData:
++ * - Overlay data not associated with a particular phase
++ * - Create phase overlay data
++ * - Delete phase overlay data
++ * - Execute phase overlay data
++ */
++#define numOtherSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define numCreateSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numCreateSects)
++#define numDeleteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numDeleteSects)
++#define numExecuteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numExecuteSects)
++#define otherOffset(pOvlyData) 0
++#define createOffset(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define deleteOffset(pOvlyData) (createOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numCreateSects))
++#define executeOffset(pOvlyData) (deleteOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numDeleteSects))
++/*
++ * ======== OvlyHdr ========
++ */
++struct OvlyHdr {
++ struct DBOF_OvlySectHdr dbofHdr;
++ char *pName; /* Name of overlay section */
++ u16 createRef; /* Reference count for create phase */
++ u16 deleteRef; /* Reference count for delete phase */
++ u16 executeRef; /* Execute phase ref count */
++ u16 otherRef; /* Unspecified phase ref count */
++} ;
++
++/*
++ * ======== OvlyData ========
++ */
++struct OvlyData {
++ struct OvlyHdr hdr;
++ struct DBOF_OvlySectData data[1];
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBL_Symbol sym;
++ char *pSymName;
++};
++
++/*
++ * ======== DCDSect ========
++ */
++struct DCDSect {
++ struct DBOF_DCDSectHdr sectHdr;
++ char *pData;
++} ;
++
++/*
++ * ======== DBL_TargetObj ========
++ */
++struct DBL_TargetObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_Attrs dblAttrs; /* file read, write, etc. functions */
++ char *pBuf; /* Load buffer */
++};
++
++/*
++ * ======== TargetInfo ========
++ */
++struct TargetInfo {
++ u16 dspType; /* eg, C54TARG, C55TARG */
++ u32 magic; /* COFF magic number, identifies target type */
++ u16 wordSize; /* Size of a DSP word */
++ u16 mauSize; /* Size of minimum addressable unit */
++ u16 charSize; /* For C55x, mausize = 1, but charsize = 2 */
++} ;
++
++/*
++ * ======== DBL_LibraryObj ========
++ * Represents a library loaded on a target.
++ */
++struct DBL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_TargetObj *pTarget; /* Target for this library */
++ struct KFILE_FileObj *file; /* DBOF file handle */
++ bool byteSwapped; /* Are bytes swapped? */
++ struct DBOF_FileHdr fileHdr; /* Header of DBOF file */
++ u16 nSymbols; /* Number of DSP/Bridge symbols */
++ struct Symbol *symbols; /* Table of DSP/Bridge symbols */
++ u16 nDCDSects; /* Number of DCD sections */
++ u16 nOvlySects; /* Number of overlay nodes */
++ struct DCDSect *dcdSects; /* DCD section data */
++ struct OvlyData **ppOvlyData; /* Array of overlay section data */
++ struct TargetInfo *pTargetInfo; /* Entry in targetTab[] below */
++} ;
++
++#if GT_TRACE
++static struct GT_Mask DBL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static u32 magicTab[NUMTARGS] = { C54MAGIC, C55MAGIC };
++
++static struct TargetInfo targetTab[] = {
++ /* targ magic wordsize mausize charsize */
++ {C54TARG, C54MAGIC, 2, 2, 2}, /* C54 */
++ {C55TARG, C55MAGIC, 2, 1, 2}, /* C55 */
++};
++
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects);
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++
++/*
++ * ======== DBL_close ========
++ * Purpose:
++ * Close library opened with DBL_open.
++ */
++void DBL_close(struct DBL_LibraryObj *lib)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_close: lib: 0x%x\n", lib);
++
++ /* Free symbols */
++ if (pdblLib->symbols) {
++ for (i = 0; i < pdblLib->nSymbols; i++) {
++ if (pdblLib->symbols[i].pSymName)
++ MEM_Free(pdblLib->symbols[i].pSymName);
++
++ }
++ MEM_Free(pdblLib->symbols);
++ }
++
++ /* Free DCD sects */
++ if (pdblLib->dcdSects) {
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (pdblLib->dcdSects[i].pData)
++ MEM_Free(pdblLib->dcdSects[i].pData);
++
++ }
++ MEM_Free(pdblLib->dcdSects);
++ }
++
++ /* Free overlay sects */
++ if (pdblLib->ppOvlyData) {
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (pdblLib->ppOvlyData[i]) {
++ if (pdblLib->ppOvlyData[i]->hdr.pName) {
++ MEM_Free(pdblLib->ppOvlyData[i]->
++ hdr.pName);
++ }
++ MEM_Free(pdblLib->ppOvlyData[i]);
++ }
++ }
++ MEM_Free(pdblLib->ppOvlyData);
++ }
++
++ /* Close the file */
++ if (pdblLib->file)
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++
++
++ MEM_FreeObject(pdblLib);
++}
++
++/*
++ * ======== DBL_create ========
++ * Purpose:
++ * Create a target object by specifying the alloc, free, and
++ * write functions for the target.
++ */
++DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget, struct DBL_Attrs *pAttrs)
++{
++ struct DBL_TargetObj *pdblTarget = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_create: pTarget: 0x%x pAttrs: 0x%x\n",
++ pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pdblTarget, struct DBL_TargetObj, DBL_TARGSIGNATURE);
++ if (pdblTarget == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pdblTarget->dblAttrs = *pAttrs;
++ /* Allocate buffer for loading target */
++ pdblTarget->pBuf = MEM_Calloc(LOADBUFSIZE, MEM_PAGED);
++ if (pdblTarget->pBuf == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = pdblTarget;
++ } else {
++ *pTarget = NULL;
++ if (pdblTarget)
++ DBL_delete(pdblTarget);
++
++ }
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ ((MEM_IsValidHandle((*pTarget), DBL_TARGSIGNATURE)) ||
++ (DSP_FAILED(status) && *pTarget == NULL)));
++ return status;
++}
++
++/*
++ * ======== DBL_delete ========
++ * Purpose:
++ * Delete target object and free resources for any loaded libraries.
++ */
++void DBL_delete(struct DBL_TargetObj *target)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "DBL_delete: target: 0x%x\n", target);
++
++ if (target->pBuf)
++ MEM_Free(target->pBuf);
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== DBL_exit ========
++ * Purpose
++ * Discontinue usage of DBL module.
++ */
++void DBL_exit()
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(DBL_debugMask, GT_5CLASS,
++ "DBL_exit() ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBL_getAddr ========
++ * Purpose:
++ * Get address of name in the specified library.
++ */
++bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getAddr: libt: 0x%x name: %s pAddr: "
++ "0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if (CSL_Strcmp(name, symbol->pSymName) == 0) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getAttrs ========
++ * Purpose:
++ * Retrieve the attributes of the target.
++ */
++void DBL_getAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_getAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ *pAttrs = target->dblAttrs;
++}
++
++/*
++ * ======== DBL_getCAddr ========
++ * Purpose:
++ * Get address of "C" name in the specified library.
++ */
++bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getCAddr: target: 0x%x name:%s pAddr:"
++ " 0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if ((CSL_Strcmp(name, symbol->pSymName) == 0) ||
++ (CSL_Strcmp(name, symbol->pSymName + 1) == 0 &&
++ symbol->pSymName[0] == '_')) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getEntry ========
++ * Purpose:
++ * Get program entry point.
++ *
++ */
++bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_getEntry: lib: 0x%x pEntry: 0x%x\n", lib, pEntry);
++ *pEntry = pdblLib->fileHdr.entry;
++
++ return true;
++}
++
++/*
++ * ======== DBL_getSect ========
++ * Purpose:
++ * Get address and size of a named section.
++ */
++DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_4trace(DBL_debugMask, GT_ENTER,
++ "DBL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++
++ /*
++ * Check for DCD and overlay sections. Overlay loader uses DBL_getSect
++ * to determine whether or not a node has overlay sections.
++ * DCD section names begin with '.'
++ */
++ if (name[0] == '.') {
++ /* Get DCD section size (address is 0, since it's a NOLOAD). */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name,
++ name) == 0) {
++ *pAddr = 0;
++ *pSize = pdblLib->dcdSects[i].sectHdr.size *
++ pdblLib->pTargetInfo->mauSize;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ } else {
++ /* Check for overlay section */
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (CSL_Strcmp(pdblLib->ppOvlyData[i]->hdr.pName,
++ name) == 0) {
++ /* Address and size are meaningless */
++ *pAddr = 0;
++ *pSize = 0;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_init ========
++ * Purpose:
++ * Initialize DBL module.
++ */
++bool DBL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBL_debugMask.flags);
++ GT_create(&DBL_debugMask, "BL"); /* "BL" for dBL */
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBL_debugMask, GT_5CLASS, "DBL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBL_load ========
++ * Purpose:
++ * Add symbols/code/data defined in file to that already present
++ * on the target.
++ */
++DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ struct DBL_TargetObj *dbl;
++ u16 i;
++ u16 nSects;
++ DSP_STATUS status = DSP_EFAIL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_load: lib: 0x%x flags: "
++ "0x%x attrs: 0x%x pEntry: 0x%x\n", lib, flags, attrs, pEntry);
++
++ dbl = pdblLib->pTarget;
++ *pEntry = pdblLib->fileHdr.entry;
++ nSects = pdblLib->fileHdr.numSects;
++ dbl->dblAttrs = *attrs;
++
++ for (i = 0; i < nSects; i++) {
++ /* Load the section at the current file offset */
++ status = loadSect(dbl, lib);
++ if (DSP_FAILED(status))
++ break;
++
++ }
++
++ /* Done with file, we can close it */
++ if (pdblLib->file) {
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++ pdblLib->file = NULL;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_loadSect ========
++ * Purpose:
++ * Load a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ s32 allocdSects = 0;
++ u32 loadAddr;
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ u32 ulBytes;
++ u16 mauSize;
++ u16 wordSize;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *name = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++ DBC_Require(attrs != NULL);
++ DBC_Require(attrs->write != NULL);
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_loadSect: lib: 0x%x sectName: %s "
++ "attrs: 0x%x\n", lib, sectName, attrs);
++ dbl = lib->pTarget;
++ mauSize = lib->pTargetInfo->mauSize;
++ wordSize = lib->pTargetInfo->wordSize;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ name = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(name, sectName, CSL_Strlen(name))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /*
++ * If node overlay, phase will be encoded in name. If not node
++ * overlay, set phase to NONE.
++ */
++ phase = (CSL_Strcmp(name, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ /* Get reference count of node phase to be loaded, offset into
++ * overlay data array, and number of sections to overlay. */
++ switch (phase) {
++ case NONE:
++ /* Not a node overlay */
++ phaseRef = &pOvlyData->hdr.otherRef;
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ phaseRef = &pOvlyData->hdr.createRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ if (*otherRef) {
++ /* The overlay sections where node phase was
++ * not specified, have already been loaded. */
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ } else {
++ /* Overlay sections where node phase was not
++ * specified get loaded at create time, along
++ * with create sects. */
++ nSects = numCreateSects(pOvlyData) +
++ numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ }
++ break;
++ case DELETEPHASE:
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ break;
++ case EXECUTEPHASE:
++ phaseRef = &pOvlyData->hdr.executeRef;
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ /* Do overlay if reference count is 0 */
++ if (!(*phaseRef)) {
++ /* "Allocate" all sections */
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ status = (dbl->dblAttrs.alloc)(dbl->dblAttrs.
++ rmmHandle, space, size, 0,
++ &runAddr, true);
++ if (DSP_FAILED(status))
++ break;
++
++ allocdSects++;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections */
++ for (i = 0; i < nSects; i++) {
++ loadAddr = pOvlyData->data[offset + i].
++ loadAddr;
++ runAddr = pOvlyData->data[offset + i].
++ runAddr;
++ size = pOvlyData->data[offset + i].
++ size;
++ space = pOvlyData->data[offset + i].
++ page;
++ /* Convert to word address, call
++ * write function */
++ loadAddr /= (wordSize / mauSize);
++ runAddr /= (wordSize / mauSize);
++ ulBytes = size * mauSize;
++ if ((*attrs->write)(attrs->wHandle,
++ runAddr, (void *)loadAddr, ulBytes,
++ space) != ulBytes) {
++ GT_0trace(DBL_debugMask,
++ GT_6CLASS,
++ "DBL_loadSect: write"
++ " failed\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ }
++ }
++ /* Free sections on failure */
++ if (DSP_FAILED(status))
++ freeSects(dbl, pOvlyData, offset, allocdSects);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Increment reference counts */
++ if (otherRef)
++ *otherRef = *otherRef + 1;
++
++ *phaseRef = *phaseRef + 1;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_open ========
++ * Purpose:
++ * DBL_open() returns a library handle that can be used to
++ * load/unload the symbols/code/data via DBL_load()/DBL_unload().
++ */
++DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file, DBL_Flags flags,
++ struct DBL_LibraryObj **pLib)
++{
++ struct DBL_LibraryObj *pdblLib = NULL;
++ u16 nSymbols;
++ u16 nDCDSects;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(target->dblAttrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER, "DBL_open: target: 0x%x file: %s "
++ "pLib: 0x%x\n", target, file, pLib);
++ /* Allocate DBL library object */
++ MEM_AllocObject(pdblLib, struct DBL_LibraryObj, DBL_LIBSIGNATURE);
++ if (pdblLib == NULL)
++ status = DSP_EMEMORY;
++
++ /* Open the file */
++ if (DSP_SUCCEEDED(status)) {
++ pdblLib->pTarget = target;
++ pdblLib->file = (*target->dblAttrs.fopen)(file, "rb");
++ if (pdblLib->file == NULL)
++ status = DSP_EFOPEN;
++
++ }
++ /* Read file header */
++ if (DSP_SUCCEEDED(status)) {
++ status = readHeader(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read file header\n");
++ }
++ }
++ /* Allocate symbol table */
++ if (DSP_SUCCEEDED(status)) {
++ nSymbols = pdblLib->nSymbols = pdblLib->fileHdr.numSymbols;
++ pdblLib->symbols = MEM_Calloc(nSymbols * sizeof(struct Symbol),
++ MEM_PAGED);
++ if (pdblLib->symbols == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read all the symbols */
++ if (DSP_SUCCEEDED(status)) {
++ status = readSymbols(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read symbols\n");
++ }
++ }
++ /* Allocate DCD sect table */
++ if (DSP_SUCCEEDED(status)) {
++ nDCDSects = pdblLib->nDCDSects = pdblLib->fileHdr.numDCDSects;
++ pdblLib->dcdSects = MEM_Calloc(nDCDSects *
++ sizeof(struct DCDSect), MEM_PAGED);
++ if (pdblLib->dcdSects == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read DCD sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readDCDSects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read DCD sections\n");
++ }
++ }
++ /* Read overlay sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readOvlySects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read "
++ "overlay sections\n");
++ }
++ }
++ if (DSP_FAILED(status)) {
++ *pLib = NULL;
++ if (pdblLib != NULL)
++ DBL_close((struct DBL_LibraryObj *) pdblLib);
++
++ } else {
++ *pLib = pdblLib;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*pLib), DBL_LIBSIGNATURE))) ||
++ (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBL_readSect ========
++ * Purpose:
++ * Read COFF section into a character buffer.
++ */
++DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name, char *pContent,
++ u32 size)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ u32 mauSize;
++ u32 max;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++
++ mauSize = pdblLib->pTargetInfo->mauSize;
++
++ /* Attempt to find match with DCD section names. */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name, name) == 0) {
++ /* Match found */
++ max = pdblLib->dcdSects[i].sectHdr.size * mauSize;
++ max = (max > size) ? size : max;
++ memcpy(pContent, pdblLib->dcdSects[i].pData, max);
++ status = DSP_SOK;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_setAttrs ========
++ * Purpose:
++ * Set the attributes of the target.
++ */
++void DBL_setAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++
++ target->dblAttrs = *pAttrs;
++}
++
++/*
++ * ======== DBL_unload ========
++ * Purpose:
++ * Remove the symbols/code/data corresponding to the library lib.
++ */
++void DBL_unload(struct DBL_LibraryObj *lib, struct DBL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_unload: lib: 0x%x\n", lib);
++
++ /* Nothing to do for static loading */
++}
++
++/*
++ * ======== DBL_unloadSect ========
++ * Purpose:
++ * Unload a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *pName = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_unloadSect: lib: 0x%x sectName: %s\n", lib, sectName);
++ dbl = lib->pTarget;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ pName = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(pName, sectName, CSL_Strlen(pName))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /* If node overlay, phase will be encoded in name. */
++ phase = (CSL_Strcmp(pName, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ switch (phase) {
++ case NONE:
++ nSects = numOtherSects(pOvlyData);
++ phaseRef = &pOvlyData->hdr.otherRef;
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.createRef;
++ break;
++ case DELETEPHASE:
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ break;
++ case EXECUTEPHASE:
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.executeRef;
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ if (*phaseRef) {
++ *phaseRef = *phaseRef - 1;
++ if (*phaseRef == 0) {
++ /* Unload overlay sections for phase */
++ freeSects(dbl, pOvlyData, offset, nSects);
++ }
++ if (phase == DELETEPHASE) {
++ DBC_Assert(*otherRef);
++ *otherRef = *otherRef - 1;
++ if (*otherRef == 0) {
++ /* Unload other overlay sections */
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ freeSects(dbl, pOvlyData, offset,
++ nSects);
++ }
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== freeSects ========
++ * Purpose:
++ * Free section
++ */
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects)
++{
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ s32 i;
++
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ if (!(dbl->dblAttrs.free)
++ (dbl->dblAttrs.rmmHandle, space, runAddr, size, true)) {
++ /*
++ * Free function will not fail for overlay, unless
++ * address passed in is bad.
++ */
++ DBC_Assert(false);
++ }
++ }
++}
++
++/*
++ * ======== loadSect ========
++ * Purpose:
++ * Load section to target
++ */
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SectHdr sectHdr;
++ char *pBuf;
++ struct KFILE_FileObj *file;
++ u32 space;
++ u32 addr;
++ u32 total;
++ u32 nWords = 0;
++ u32 nBytes = 0;
++ u16 mauSize;
++ u32 bufSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ bufSize = LOADBUFSIZE / mauSize;
++ pBuf = dbl->pBuf;
++
++ /* Read the section header */
++ if ((*dbl->dblAttrs.fread)(&sectHdr, sizeof(struct DBOF_SectHdr),
++ 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ } else {
++ if (pdblLib->byteSwapped) {
++ sectHdr.size = SWAPLONG(sectHdr.size);
++ sectHdr.addr = SWAPLONG(sectHdr.addr);
++ sectHdr.page = SWAPWORD(sectHdr.page);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ addr = sectHdr.addr;
++ space = sectHdr.page;
++ for (total = sectHdr.size; total > 0; total -= nWords) {
++ nWords = min(total, bufSize);
++ nBytes = nWords * mauSize;
++ /* Read section data */
++ if ((*dbl->dblAttrs.fread)(pBuf, nBytes, 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Write section to target */
++ if (!(*dbl->dblAttrs.write)(dbl->dblAttrs.wHandle,
++ addr, pBuf, nBytes, space)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to write section data\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ addr += nWords;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readDCDSects ========
++ * Purpose:
++ * Read DCD sections.
++ */
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_DCDSectHdr *pSectHdr;
++ struct DCDSect *pSect;
++ struct KFILE_FileObj *file;
++ u16 nSects;
++ u16 i;
++ u16 mauSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ nSects = pdblLib->fileHdr.numDCDSects;
++ for (i = 0; i < nSects; i++) {
++ pSect = &pdblLib->dcdSects[i];
++ pSectHdr = &pdblLib->dcdSects[i].sectHdr;
++ /* Read sect header */
++ if ((*dbl->dblAttrs.fread)(pSectHdr,
++ sizeof(struct DBOF_DCDSectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped)
++ pSectHdr->size = SWAPLONG(pSectHdr->size);
++
++ pSect->pData = (char *)MEM_Calloc(pSectHdr->size *
++ mauSize, MEM_PAGED);
++ if (pSect->pData == NULL) {
++ GT_2trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation for sect %s "
++ "data failed: Size: 0x%lx\n", pSectHdr->name,
++ pSectHdr->size);
++ status = DSP_EMEMORY;
++ break;
++ }
++ /* Read DCD sect data */
++ if ((*dbl->dblAttrs.fread)(pSect->pData, mauSize,
++ pSectHdr->size, file) != pSectHdr->size) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect data\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== readHeader ========
++ * Purpose:
++ * Read Header.
++ */
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct KFILE_FileObj *file;
++ s32 i;
++ struct DBOF_FileHdr *pHdr;
++ u32 swapMagic;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->byteSwapped = false;
++ file = pdblLib->file;
++ pHdr = &pdblLib->fileHdr;
++ if ((*dbl->dblAttrs.fread)(pHdr, sizeof(struct DBOF_FileHdr), 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to read file header\n");
++ status = DSP_EFREAD;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Determine if byte swapped */
++ for (i = 0; i < NUMTARGS; i++) {
++ swapMagic = SWAPLONG(pHdr->magic);
++ if (pHdr->magic == magicTab[i] || swapMagic ==
++ magicTab[i]) {
++ if (swapMagic == magicTab[i]) {
++ pdblLib->byteSwapped = true;
++ pHdr->magic = SWAPLONG(pHdr->magic);
++ pHdr->entry = SWAPLONG(pHdr->entry);
++ pHdr->symOffset = SWAPLONG(pHdr->
++ symOffset);
++ pHdr->dcdSectOffset = SWAPLONG(pHdr->
++ dcdSectOffset);
++ pHdr->loadSectOffset = SWAPLONG(pHdr->
++ loadSectOffset);
++ pHdr->ovlySectOffset = SWAPLONG(pHdr->
++ ovlySectOffset);
++ pHdr->numSymbols = SWAPWORD(pHdr->
++ numSymbols);
++ pHdr->numDCDSects = SWAPWORD(pHdr->
++ numDCDSects);
++ pHdr->numSects = SWAPWORD(pHdr->
++ numSects);
++ pHdr->numOvlySects = SWAPWORD(pHdr->
++ numOvlySects);
++ }
++ break;
++ }
++ }
++ if (i == NUMTARGS) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to determine"
++ " target type\n");
++ status = DSP_ECORRUPTFILE;
++ } else {
++ pdblLib->pTargetInfo = &targetTab[i];
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "COF type: 0x%lx\n", pHdr->magic);
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "Entry point:0x%lx\n", pHdr->entry);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readOvlySects ========
++ * Purpose:
++ * Read Overlay Sections
++ */
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_OvlySectHdr hdr;
++ struct DBOF_OvlySectData *pData;
++ struct OvlyData *pOvlyData;
++ char *pName;
++ struct KFILE_FileObj *file;
++ u16 i, j;
++ u16 nSects;
++ u16 n;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->nOvlySects = nSects = pdblLib->fileHdr.numOvlySects;
++ file = pdblLib->file;
++ if (nSects > 0) {
++ pdblLib->ppOvlyData = MEM_Calloc(nSects * sizeof(OvlyData *),
++ MEM_PAGED);
++ if (pdblLib->ppOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate overlay "
++ "data memory\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Read overlay data for each node */
++ for (i = 0; i < nSects; i++) {
++ /* Read overlay section header */
++ if ((*dbl->dblAttrs.fread)(&hdr,
++ sizeof(struct DBOF_OvlySectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read overlay sect"
++ " header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ hdr.nameLen = SWAPWORD(hdr.nameLen);
++ hdr.numCreateSects =
++ SWAPWORD(hdr.numCreateSects);
++ hdr.numDeleteSects =
++ SWAPWORD(hdr.numDeleteSects);
++ hdr.numExecuteSects =
++ SWAPWORD(hdr.numExecuteSects);
++ hdr.numOtherSects =
++ SWAPWORD(hdr.numOtherSects);
++ hdr.resvd = SWAPWORD(hdr.resvd);
++ }
++ n = hdr.numCreateSects + hdr.numDeleteSects +
++ hdr.numExecuteSects + hdr.numOtherSects;
++
++ /* Allocate memory for node's overlay data */
++ pOvlyData = (struct OvlyData *)MEM_Calloc
++ (sizeof(struct OvlyHdr) +
++ n * sizeof(struct DBOF_OvlySectData),
++ MEM_PAGED);
++ if (pOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " data memory\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.dbofHdr = hdr;
++ pdblLib->ppOvlyData[i] = pOvlyData;
++ /* Allocate memory for section name */
++ pName = (char *)MEM_Calloc(hdr.nameLen + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " section name\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.pName = pName;
++ /* Read the overlay section name */
++ if ((*dbl->dblAttrs.fread)(pName, sizeof(char),
++ hdr.nameLen, file) != hdr.nameLen) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay name.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Read the overlay section data */
++ pData = pOvlyData->data;
++ if ((*dbl->dblAttrs.fread)(pData,
++ sizeof(struct DBOF_OvlySectData), n, file) != n) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay data.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Swap overlay data, if necessary */
++ if (pdblLib->byteSwapped) {
++ for (j = 0; j < n; j++) {
++ pData[j].loadAddr =
++ SWAPLONG(pData[j].loadAddr);
++ pData[j].runAddr =
++ SWAPLONG(pData[j].runAddr);
++ pData[j].size =
++ SWAPLONG(pData[j].size);
++ pData[j].page =
++ SWAPWORD(pData[j].page);
++ }
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readSymbols ========
++ * Purpose:
++ * Read Symbols
++ */
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SymbolHdr symHdr;
++ struct KFILE_FileObj *file;
++ u16 i;
++ u16 nSymbols;
++ u16 len;
++ char *pName = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++
++ nSymbols = pdblLib->fileHdr.numSymbols;
++
++ for (i = 0; i < nSymbols; i++) {
++ /* Read symbol value */
++ if ((*dbl->dblAttrs.fread)(&symHdr,
++ sizeof(struct DBOF_SymbolHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ symHdr.nameLen = SWAPWORD(symHdr.nameLen);
++ symHdr.value = SWAPLONG(symHdr.value);
++ }
++ /* Allocate buffer for symbol name */
++ len = symHdr.nameLen;
++ pName = (char *)MEM_Calloc(len + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pdblLib->symbols[i].pSymName = pName;
++ pdblLib->symbols[i].sym.value = symHdr.value;
++ /* Read symbol name */
++ if ((*dbl->dblAttrs.fread) (pName, sizeof(char), len, file) !=
++ len) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ } else {
++ pName[len] = '\0';
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "Symbol: %s Value: 0x%lx\n",
++ pName, symHdr.value);
++ }
++ }
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbll.c b/drivers/dsp/bridge/pmgr/dbll.c
+new file mode 100644
+index 0000000..82430a3
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbll.c
+@@ -0,0 +1,1564 @@
++/*
++ * dbll.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbll.c ========
++ *
++ *! Revision History
++ *! ================
++ *! 25-Apr-2030 map: Fixed symbol redefinition bug + unload and return error
++ *! 08-Apr-2003 map: Consolidated DBL with DBLL loader name
++ *! 24-Mar-2003 map: Updated findSymbol to support dllview update
++ *! 23-Jan-2003 map: Updated rmmAlloc to support memory granularity
++ *! 21-Nov-2002 map: Combine fopen and DLOAD_module_open to increase
++ *! performance on start.
++ *! 04-Oct-2002 map: Integrated new TIP dynamic loader w/ DOF api.
++ *! 27-Sep-2002 map: Changed handle passed to RemoteFree, instead of
++ *! RMM_free; added GT_trace to rmmDealloc
++ *! 20-Sep-2002 map: Updated from Code Review
++ *! 08-Aug-2002 jeh: Updated to support overlays.
++ *! 25-Jun-2002 jeh: Pass RMM_Addr object to alloc function in rmmAlloc().
++ *! 20-Mar-2002 jeh: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/gh.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Dynamic loader library interface */
++#include <dspbridge/dynamic_loader.h>
++#include <dspbridge/getsection.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbll.h>
++#include <dspbridge/rmm.h>
++
++#define DBLL_TARGSIGNATURE 0x544c4c44 /* "TLLD" */
++#define DBLL_LIBSIGNATURE 0x4c4c4c44 /* "LLLD" */
++
++/* Number of buckets for symbol hash table */
++#define MAXBUCKETS 211
++
++/* Max buffer length */
++#define MAXEXPR 128
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((uint32_t)zzz)
++#endif
++#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
++
++/*
++ * ======== struct DBLL_TarObj* ========
++ * A target may have one or more libraries of symbols/code/data loaded
++ * onto it, where a library is simply the symbols/code/data contained
++ * in a DOFF file.
++ */
++/*
++ * ======== DBLL_TarObj ========
++ */
++struct DBLL_TarObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_Attrs attrs;
++ struct DBLL_LibraryObj *head; /* List of all opened libraries */
++} ;
++
++/*
++ * The following 4 typedefs are "super classes" of the dynamic loader
++ * library types used in dynamic loader functions (dynamic_loader.h).
++ */
++/*
++ * ======== DBLLStream ========
++ * Contains Dynamic_Loader_Stream
++ */
++struct DBLLStream {
++ struct Dynamic_Loader_Stream dlStream;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLSymbol ========
++ */
++struct DBLLSymbol {
++ struct Dynamic_Loader_Sym dlSymbol;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLAlloc ========
++ */
++ struct DBLLAlloc {
++ struct Dynamic_Loader_Allocate dlAlloc;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLInit ========
++ */
++struct DBLLInit {
++ struct Dynamic_Loader_Initialize dlInit;
++ struct DBLL_LibraryObj *lib;
++};
++
++/*
++ * ======== DBLL_Library ========
++ * A library handle is returned by DBLL_Open() and is passed to DBLL_load()
++ * to load symbols/code/data, and to DBLL_unload(), to remove the
++ * symbols/code/data loaded by DBLL_load().
++ */
++
++/*
++ * ======== DBLL_LibraryObj ========
++ */
++ struct DBLL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_LibraryObj *next; /* Next library in target's list */
++ struct DBLL_LibraryObj *prev; /* Previous in the list */
++ struct DBLL_TarObj *pTarget; /* target for this library */
++
++ /* Objects needed by dynamic loader */
++ struct DBLLStream stream;
++ struct DBLLSymbol symbol;
++ struct DBLLAlloc allocate;
++ struct DBLLInit init;
++ DLOAD_mhandle mHandle;
++
++ char *fileName; /* COFF file name */
++ void *fp; /* Opaque file handle */
++ u32 entry; /* Entry point */
++ DLOAD_mhandle desc; /* desc of DOFF file loaded */
++ u32 openRef; /* Number of times opened */
++ u32 loadRef; /* Number of times loaded */
++ struct GH_THashTab *symTab; /* Hash table of symbols */
++ u32 ulPos;
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBLL_Symbol value;
++ char *name;
++} ;
++extern bool bSymbolsReloaded;
++
++static void dofClose(struct DBLL_LibraryObj *zlLib);
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib);
++static s32 NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsiz);
++
++/*
++ * Functions called by dynamic loader
++ *
++ */
++/* Dynamic_Loader_Stream */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize);
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos);
++/* Dynamic_Loader_Sym */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name);
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId);
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid);
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this,
++ unsigned moduleId);
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize);
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr);
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args);
++/* Dynamic_Loader_Allocate */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align);
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info);
++
++/* Dynamic_Loader_Initialize */
++static int connect(struct Dynamic_Loader_Initialize *this);
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nbytes,
++ unsigned val);
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start);
++static void release(struct Dynamic_Loader_Initialize *this);
++
++/* symbol table hash functions */
++static u16 nameHash(void *name, u16 maxBucket);
++static bool nameMatch(void *name, void *sp);
++static void symDelete(void *sp);
++
++#if GT_TRACE
++static struct GT_Mask DBLL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Symbol Redefinition */
++static int bRedefinedSymbol;
++static int bGblSearch = 1;
++
++/*
++ * ======== DBLL_close ========
++ */
++void DBLL_close(struct DBLL_LibraryObj *zlLib)
++{
++ struct DBLL_TarObj *zlTarget;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->openRef > 0);
++ zlTarget = zlLib->pTarget;
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_close: lib: 0x%x\n", zlLib);
++ zlLib->openRef--;
++ if (zlLib->openRef == 0) {
++ /* Remove library from list */
++ if (zlTarget->head == zlLib)
++ zlTarget->head = zlLib->next;
++
++ if (zlLib->prev)
++ (zlLib->prev)->next = zlLib->next;
++
++ if (zlLib->next)
++ (zlLib->next)->prev = zlLib->prev;
++
++ /* Free DOF resources */
++ dofClose(zlLib);
++ if (zlLib->fileName)
++ MEM_Free(zlLib->fileName);
++
++ /* remove symbols from symbol table */
++ if (zlLib->symTab)
++ GH_delete(zlLib->symTab);
++
++ /* remove the library object itself */
++ MEM_FreeObject(zlLib);
++ zlLib = NULL;
++ }
++}
++
++/*
++ * ======== DBLL_create ========
++ */
++DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *pzlTarget;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_create: pTarget: 0x%x pAttrs: "
++ "0x%x\n", pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pzlTarget, struct DBLL_TarObj, DBLL_TARGSIGNATURE);
++ if (pTarget != NULL) {
++ if (pzlTarget == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_create: Memory allocation"
++ " failed\n");
++ *pTarget = NULL;
++ status = DSP_EMEMORY;
++ } else {
++ pzlTarget->attrs = *pAttrs;
++ *pTarget = (struct DBLL_TarObj *)pzlTarget;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct DBLL_TarObj *)(*pTarget)),
++ DBLL_TARGSIGNATURE)) || (DSP_FAILED(status) &&
++ *pTarget == NULL));
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_delete ========
++ */
++void DBLL_delete(struct DBLL_TarObj *target)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_delete: target: 0x%x\n",
++ target);
++
++ if (zlTarget != NULL)
++ MEM_FreeObject(zlTarget);
++
++}
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue usage of DBL module.
++ */
++void DBLL_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++ MEM_Exit();
++ CSL_Exit();
++ GH_exit();
++#if GT_TRACE
++ DBLL_debugMask.flags = NULL;
++#endif
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ */
++bool DBLL_getAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getAddr: lib: 0x%x name: %s pAddr:"
++ " 0x%x\n", zlLib, name, ppSym);
++ sym = (struct Symbol *)GH_find(zlLib->symTab, name);
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ */
++void DBLL_getAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ *pAttrs = zlTarget->attrs;
++
++}
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of a "C" name in the specified library.
++ */
++bool DBLL_getCAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ char cname[MAXEXPR + 1];
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++ DBC_Require(name != NULL);
++
++ cname[0] = '_';
++
++ strncpy(cname + 1, name, sizeof(cname) - 2);
++ cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
++
++ /* Check for C name, if not found */
++ sym = (struct Symbol *)GH_find(zlLib->symTab, cname);
++
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_getSect ========
++ * Get the base address and size (in bytes) of a COFF section.
++ */
++DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ u32 uByteSize;
++ bool fOpenedDoff = false;
++ const struct LDR_SECTION_INFO *sect = NULL;
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ uByteSize = 1;
++ if (DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ *pAddr = sect->load_addr;
++ *pSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (*pSize % 2)
++ (*pSize)++;
++
++ /* Align size */
++ *pSize = DOFF_ALIGN(*pSize);
++ } else {
++ status = DSP_ENOSECT;
++ }
++ }
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_init ========
++ */
++bool DBLL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBLL_debugMask.flags);
++ GT_create(&DBLL_debugMask, "DL"); /* "DL" for dbDL */
++ GH_init();
++ CSL_Init();
++ retVal = MEM_Init();
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBLL_load ========
++ */
++DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib, DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ struct DBLL_TarObj *dbzl;
++ bool gotSymbols = true;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++ bool fOpenedDoff = false;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_load: lib: 0x%x flags: 0x%x pEntry:"
++ " 0x%x\n", lib, flags, attrs, pEntry);
++ /*
++ * Load if not already loaded.
++ */
++ if (zlLib->loadRef == 0 || !(flags & DBLL_DYNAMIC)) {
++ dbzl = zlLib->pTarget;
++ dbzl->attrs = *attrs;
++ /* Create a hash table for symbols if not already created */
++ if (zlLib->symTab == NULL) {
++ gotSymbols = false;
++ zlLib->symTab = GH_create(MAXBUCKETS,
++ sizeof(struct Symbol),
++ nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ if (gotSymbols) {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ findInSymbolTable;
++ } else {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ addToSymbolTable;
++ }
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ /* If COFF file is not open, we open it. */
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell))
++ (zlLib->fp);
++ /* Reset file cursor */
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0,
++ SEEK_SET);
++ bSymbolsReloaded = true;
++ /* The 5th argument, DLOAD_INITBSS, tells the DLL
++ * module to zero-init all BSS sections. In general,
++ * this is not necessary and also increases load time.
++ * We may want to make this configurable by the user */
++ err = Dynamic_Load_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, DLOAD_INITBSS,
++ &zlLib->mHandle);
++
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_load: "
++ "Dynamic_Load_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ } else if (bRedefinedSymbol) {
++ zlLib->loadRef++;
++ DBLL_unload(zlLib, (struct DBLL_Attrs *) attrs);
++ bRedefinedSymbol = false;
++ status = DSP_EDYNLOAD;
++ } else {
++ *pEntry = zlLib->entry;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ zlLib->loadRef++;
++
++ /* Clean up DOFF resources */
++ if (fOpenedDoff)
++ dofClose(zlLib);
++
++ DBC_Ensure(DSP_FAILED(status) || zlLib->loadRef > 0);
++ return status;
++}
++
++/*
++ * ======== DBLL_loadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *zlLib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== DBLL_open ========
++ */
++DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ struct DBLL_LibraryObj *zlLib = NULL;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(zlTarget->attrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_open: target: 0x%x file: %s pLib:"
++ " 0x%x\n", target, file, pLib);
++ zlLib = zlTarget->head;
++ while (zlLib != NULL) {
++ if (strcmp(zlLib->fileName, file) == 0) {
++ /* Library is already opened */
++ zlLib->openRef++;
++ break;
++ }
++ zlLib = zlLib->next;
++ }
++ if (zlLib == NULL) {
++ /* Allocate DBL library object */
++ MEM_AllocObject(zlLib, struct DBLL_LibraryObj,
++ DBLL_LIBSIGNATURE);
++ if (zlLib == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ zlLib->ulPos = 0;
++ /* Increment ref count to allow close on failure
++ * later on */
++ zlLib->openRef++;
++ zlLib->pTarget = zlTarget;
++ /* Keep a copy of the file name */
++ zlLib->fileName = MEM_Calloc(strlen(file) + 1,
++ MEM_PAGED);
++ if (zlLib->fileName == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(zlLib->fileName, file,
++ strlen(file) + 1);
++ }
++ zlLib->symTab = NULL;
++ }
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable;
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ if (DSP_SUCCEEDED(status) && zlLib->fp == NULL)
++ status = dofOpen(zlLib);
++
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp);
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET);
++ /* Create a hash table for symbols if flag is set */
++ if (zlLib->symTab != NULL || !(flags & DBLL_SYMB))
++ goto func_cont;
++
++ zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Do a fake load to get symbols - set write function to NoOp */
++ zlLib->init.dlInit.writemem = NoOp;
++ err = Dynamic_Open_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, 0,
++ &zlLib->mHandle);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: "
++ "Dynamic_Load_Module failed: 0x%lx\n", err);
++ status = DSP_EDYNLOAD;
++ } else {
++ /* Now that we have the symbol table, we can unload */
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: "
++ "Dynamic_Unload_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ }
++ zlLib->mHandle = NULL;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ if (zlLib->openRef == 1) {
++ /* First time opened - insert in list */
++ if (zlTarget->head)
++ (zlTarget->head)->prev = zlLib;
++
++ zlLib->prev = NULL;
++ zlLib->next = zlTarget->head;
++ zlTarget->head = zlLib;
++ }
++ *pLib = (struct DBLL_LibraryObj *)zlLib;
++ } else {
++ *pLib = NULL;
++ if (zlLib != NULL)
++ DBLL_close((struct DBLL_LibraryObj *)zlLib);
++
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) &&
++ MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)),
++ DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBLL_readSect ========
++ * Get the content of a COFF section.
++ */
++DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib, char *name,
++ char *pContent, u32 size)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ bool fOpenedDoff = false;
++ u32 uByteSize; /* size of bytes */
++ u32 ulSectSize; /* size of section */
++ const struct LDR_SECTION_INFO *sect = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ uByteSize = 1;
++ if (!DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ status = DSP_ENOSECT;
++ goto func_cont;
++ }
++ /*
++ * Ensure the supplied buffer size is sufficient to store
++ * the section content to be read.
++ */
++ ulSectSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (ulSectSize % 2)
++ ulSectSize++;
++
++ /* Align size */
++ ulSectSize = DOFF_ALIGN(ulSectSize);
++ if (ulSectSize > size) {
++ status = DSP_EFAIL;
++ } else {
++ if (!DLOAD_GetSection(zlLib->desc, sect, pContent))
++ status = DSP_EFREAD;
++
++ }
++func_cont:
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ */
++void DBLL_setAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ zlTarget->attrs = *pAttrs;
++
++}
++
++/*
++ * ======== DBLL_unload ========
++ */
++void DBLL_unload(struct DBLL_LibraryObj *lib, struct DBLL_Attrs *attrs)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ s32 err = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->loadRef > 0);
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_unload: lib: 0x%x\n", lib);
++ zlLib->loadRef--;
++ /* Unload only if reference count is 0 */
++ if (zlLib->loadRef != 0)
++ goto func_end;
++
++ zlLib->pTarget->attrs = *attrs;
++ if (zlLib != NULL) {
++ if (zlLib->mHandle) {
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc, &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_5CLASS,
++ "Dynamic_Unload_Module "
++ "failed: 0x%x\n", err);
++ }
++ }
++ /* remove symbols from symbol table */
++ if (zlLib->symTab != NULL) {
++ GH_delete(zlLib->symTab);
++ zlLib->symTab = NULL;
++ }
++ /* delete DOFF desc since it holds *lots* of host OS
++ * resources */
++ dofClose(zlLib);
++ }
++func_end:
++ DBC_Ensure(zlLib->loadRef >= 0);
++}
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(sectName != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_unloadSect: lib: 0x%x sectName: "
++ "%s\n", lib, sectName);
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== dofClose ========
++ */
++static void dofClose(struct DBLL_LibraryObj *zlLib)
++{
++ if (zlLib->desc) {
++ DLOAD_module_close(zlLib->desc);
++ zlLib->desc = NULL;
++ }
++ /* close file */
++ if (zlLib->fp) {
++ (zlLib->pTarget->attrs.fclose) (zlLib->fp);
++ zlLib->fp = NULL;
++ }
++}
++
++/*
++ * ======== dofOpen ========
++ */
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib)
++{
++ void *open = *(zlLib->pTarget->attrs.fopen);
++ DSP_STATUS status = DSP_SOK;
++
++ /* First open the file for the dynamic loader, then open COF */
++ zlLib->fp = (void *)((DBLL_FOpenFxn)(open))(zlLib->fileName, "rb");
++
++ /* Open DOFF module */
++ if (zlLib->fp && zlLib->desc == NULL) {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0, SEEK_SET);
++ zlLib->desc = DLOAD_module_open(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol);
++ if (zlLib->desc == NULL) {
++ (zlLib->pTarget->attrs.fclose)(zlLib->fp);
++ zlLib->fp = NULL;
++ status = DSP_EFOPEN;
++ }
++ } else {
++ status = DSP_EFOPEN;
++ }
++
++ return status;
++}
++
++/*
++ * ======== nameHash ========
++ */
++static u16 nameHash(void *key, u16 maxBucket)
++{
++ u16 ret;
++ u16 hash;
++ char *name = (char *)key;
++
++ DBC_Require(name != NULL);
++
++ hash = 0;
++
++ while (*name) {
++ hash <<= 1;
++ hash ^= *name++;
++ }
++
++ ret = hash % maxBucket;
++
++ return ret;
++}
++
++/*
++ * ======== nameMatch ========
++ */
++static bool nameMatch(void *key, void *value)
++{
++ DBC_Require(key != NULL);
++ DBC_Require(value != NULL);
++
++ if ((key != NULL) && (value != NULL)) {
++ if (strcmp((char *)key, ((struct Symbol *)value)->name) == 0)
++ return true;
++ }
++ return false;
++}
++
++/*
++ * ======== NoOp ========
++ */
++static int NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsize)
++{
++ return 1;
++}
++
++/*
++ * ======== symDelete ========
++ */
++static void symDelete(void *value)
++{
++ struct Symbol *sp = (struct Symbol *)value;
++
++ MEM_Free(sp->name);
++}
++
++/*
++ * Dynamic Loader Functions
++ */
++
++/* Dynamic_Loader_Stream */
++/*
++ * ======== readBuffer ========
++ */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ bytesRead = (*(lib->pTarget->attrs.fread))(buffer, 1, bufsize,
++ lib->fp);
++ }
++ return bytesRead;
++}
++
++/*
++ * ======== setFilePosn ========
++ */
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int status = 0; /* Success */
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ status = (*(lib->pTarget->attrs.fseek))(lib->fp, (long)pos,
++ SEEK_SET);
++ }
++
++ return status;
++}
++
++/* Dynamic_Loader_Sym */
++
++/*
++ * ======== findSymbol ========
++ */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_Symbol *pSym = NULL;
++ bool status = false; /* Symbol not found yet */
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ if (lib->pTarget->attrs.symLookup) {
++ /* Check current lib + base lib + dep lib +
++ * persistent lib */
++ status = (*(lib->pTarget->attrs.symLookup))
++ (lib->pTarget->attrs.symHandle,
++ lib->pTarget->attrs.symArg,
++ lib->pTarget->attrs.rmmHandle, name, &pSym);
++ } else {
++ /* Just check current lib for symbol */
++ status = DBLL_getAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ if (!status) {
++ status =
++ DBLL_getCAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ }
++ }
++ }
++
++ if (!status && bGblSearch) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "findSymbol: Symbol not found: %s\n", name);
++ }
++
++ DBC_Assert((status && (pSym != NULL)) || (!status && (pSym == NULL)));
++
++ retSym = (struct dynload_symbol *)pSym;
++ return retSym;
++}
++
++/*
++ * ======== findInSymbolTable ========
++ */
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct Symbol *sym;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ DBC_Require(lib->symTab != NULL);
++
++ sym = (struct Symbol *)GH_find(lib->symTab, (char *) name);
++
++ retSym = (struct dynload_symbol *)&sym->value;
++ return retSym;
++}
++
++/*
++ * ======== addToSymbolTable ========
++ */
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId)
++{
++ struct Symbol *symPtr = NULL;
++ struct Symbol symbol;
++ struct dynload_symbol *pSym = NULL;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct dynload_symbol *retVal;
++
++ DBC_Require(this != NULL);
++ DBC_Require(name);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* Check to see if symbol is already defined in symbol table */
++ if (!(lib->pTarget->attrs.baseImage)) {
++ bGblSearch = false;
++ pSym = findSymbol(this, name);
++ bGblSearch = true;
++ if (pSym) {
++ bRedefinedSymbol = true;
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "Symbol already defined in "
++ "symbol table: %s\n", name);
++ return NULL;
++ }
++ }
++ /* Allocate string to copy symbol name */
++ symbol.name = (char *)MEM_Calloc(strlen((char *const)name) + 1,
++ MEM_PAGED);
++ if (symbol.name == NULL)
++ return NULL;
++
++ if (symbol.name != NULL) {
++ /* Just copy name (value will be filled in by dynamic loader) */
++ strncpy(symbol.name, (char *const)name,
++ strlen((char *const)name) + 1);
++
++ /* Add symbol to symbol table */
++ symPtr = (struct Symbol *)GH_insert(lib->symTab, (void *)name,
++ (void *)&symbol);
++ if (symPtr == NULL)
++ MEM_Free(symbol.name);
++
++ }
++ if (symPtr != NULL)
++ retVal = (struct dynload_symbol *)&symPtr->value;
++ else
++ retVal = NULL;
++
++ return retVal;
++}
++
++/*
++ * ======== purgeSymbolTable ========
++ */
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this, unsigned moduleId)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* May not need to do anything */
++}
++
++/*
++ * ======== allocate ========
++ */
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ void *buf;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ buf = MEM_Calloc(memsize, MEM_PAGED);
++
++ return buf;
++}
++
++/*
++ * ======== deallocate ========
++ */
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ MEM_Free(memPtr);
++}
++
++/*
++ * ======== errorReport ========
++ */
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ char tempBuf[MAXEXPR];
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ vsnprintf((char *)tempBuf, MAXEXPR, (char *)errstr, args);
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "%s\n", tempBuf);
++}
++
++/* Dynamic_Loader_Allocate */
++
++/*
++ * ======== rmmAlloc ========
++ */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ DSP_STATUS status = DSP_SOK;
++ u32 memType;
++ struct RMM_Addr rmmAddr;
++ s32 retVal = TRUE;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ char *pToken = NULL;
++ char *szSecLastToken = NULL;
++ char *szLastToken = NULL;
++ char *szSectName = NULL;
++ char *pszCur;
++ s32 tokenLen = 0;
++ s32 segId = -1;
++ s32 req = -1;
++ s32 count = 0;
++ u32 allocSize = 0;
++
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++
++ /* Attempt to extract the segment ID and requirement information from
++ the name of the section */
++ DBC_Require(info->name);
++ tokenLen = strlen((char *)(info->name)) + 1;
++
++ szSectName = MEM_Calloc(tokenLen, MEM_PAGED);
++ szLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++ szSecLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++
++ if (szSectName == NULL || szSecLastToken == NULL ||
++ szLastToken == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ strncpy(szSectName, (char *)(info->name), tokenLen);
++ pszCur = szSectName;
++ while ((pToken = strsep(&pszCur, ":")) && *pToken != '\0') {
++ strncpy(szSecLastToken, szLastToken, strlen(szLastToken) + 1);
++ strncpy(szLastToken, pToken, strlen(pToken) + 1);
++ pToken = strsep(&pszCur, ":");
++ count++; /* optimizes processing*/
++ }
++ /* If pToken is 0 or 1, and szSecLastToken is DYN_DARAM or DYN_SARAM,
++ or DYN_EXTERNAL, then mem granularity information is present
++ within the section name - only process if there are at least three
++ tokens within the section name (just a minor optimization)*/
++ if (count >= 3)
++ strict_strtol(szLastToken, 10, (long *)&req);
++
++ if ((req == 0) || (req == 1)) {
++ if (strcmp(szSecLastToken, "DYN_DARAM") == 0) {
++ segId = 0;
++ } else {
++ if (strcmp(szSecLastToken, "DYN_SARAM") == 0) {
++ segId = 1;
++ } else {
++ if (strcmp(szSecLastToken,
++ "DYN_EXTERNAL") == 0) {
++ segId = 2;
++ }
++ }
++ }
++ if (segId != -1) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Extracted values for memory"
++ " granularity req [%d] segId [%d]\n",
++ req, segId);
++ }
++ }
++ MEM_Free(szSectName);
++ szSectName = NULL;
++ MEM_Free(szLastToken);
++ szLastToken = NULL;
++ MEM_Free(szSecLastToken);
++ szSecLastToken = NULL;
++func_cont:
++ if (memType == DBLL_CODE)
++ allocSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ allocSize = info->size;
++ /* TODO - ideally, we can pass the alignment requirement also
++ * from here */
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.alloc)(lib->pTarget->
++ attrs.rmmHandle, memType, allocSize, align,
++ (u32 *)&rmmAddr, segId, req, FALSE);
++ }
++ if (DSP_FAILED(status)) {
++ retVal = false;
++ } else {
++ /* RMM gives word address. Need to convert to byte address */
++ info->load_addr = rmmAddr.addr * DSPWORDSIZE;
++ info->run_addr = info->load_addr;
++ info->context = (u32)rmmAddr.segid;
++ GT_3trace(DBLL_debugMask, GT_5CLASS,
++ "Remote alloc: %s base = 0x%lx len"
++ "= 0x%lx\n", info->name, info->load_addr / DSPWORDSIZE,
++ info->size / DSPWORDSIZE);
++ }
++ return retVal;
++}
++
++/*
++ * ======== rmmDealloc ========
++ */
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ u32 segid;
++ DSP_STATUS status = DSP_SOK;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ u32 memType;
++ u32 freeSize = 0;
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* segid was set by alloc function */
++ segid = (u32)info->context;
++ if (memType == DBLL_CODE)
++ freeSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ freeSize = info->size;
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.free)(lib->pTarget->
++ attrs.symHandle, segid, info->load_addr / DSPWORDSIZE,
++ freeSize, false);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Remote dealloc: base = 0x%lx len ="
++ "0x%lx\n", info->load_addr / DSPWORDSIZE,
++ freeSize / DSPWORDSIZE);
++ }
++}
++
++/* Dynamic_Loader_Initialize */
++/*
++ * ======== connect ========
++ */
++static int connect(struct Dynamic_Loader_Initialize *this)
++{
++ return true;
++}
++
++/*
++ * ======== readMem ========
++ * This function does not need to be implemented.
++ */
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Need WMD_BRD_Read function */
++ return bytesRead;
++}
++
++/*
++ * ======== writeMem ========
++ */
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nBytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_SectInfo sectInfo;
++ u32 memType;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (DLOAD_SECTION_TYPE(info->type) == DLOAD_TEXT) ? DBLL_CODE :
++ DBLL_DATA;
++ if (lib != NULL) {
++ retVal = (*lib->pTarget->attrs.write)(lib->pTarget->
++ attrs.wHandle, addr, buf, nBytes, memType);
++ }
++ if (lib->pTarget->attrs.logWrite) {
++ sectInfo.name = info->name;
++ sectInfo.runAddr = info->run_addr;
++ sectInfo.loadAddr = info->load_addr;
++ sectInfo.size = info->size;
++ sectInfo.type = memType;
++ /* Pass the information about what we've written to
++ * another module */
++ (*lib->pTarget->attrs.logWrite)(lib->pTarget->
++ attrs.logWriteHandle, &sectInfo, addr, nBytes);
++ }
++ return retVal;
++}
++
++/*
++ * ======== fillMem ========
++ * Fill nBytes of memory at a given address with a given value by
++ * writing from a buffer containing the given value. Write in
++ * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
++ */
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nBytes,
++ unsigned val)
++{
++ bool retVal = true;
++ char *pBuf;
++ struct DBLL_LibraryObj *lib;
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ pBuf = NULL;
++ /* Pass the NULL pointer to writeMem to get the start address of Shared
++ memory. This is a trick to just get the start address, there is no
++ writing taking place with this Writemem
++ */
++ if ((lib->pTarget->attrs.write) != (DBLL_WriteFxn)NoOp)
++ writeMem(this, &pBuf, addr, info, 0);
++ if (pBuf)
++ memset(pBuf, val, nBytes);
++
++ return retVal;
++}
++
++/*
++ * ======== execute ========
++ */
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Save entry point */
++ if (lib != NULL)
++ lib->entry = (u32)start;
++
++ return retVal;
++}
++
++/*
++ * ======== release ========
++ */
++static void release(struct Dynamic_Loader_Initialize *this)
++{
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dev.c b/drivers/dsp/bridge/pmgr/dev.c
+new file mode 100644
+index 0000000..1c2f7d5
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dev.c
+@@ -0,0 +1,1476 @@
++/*
++ * dev.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.c ========
++ * Description:
++ * Implementation of 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ * Private Functions:
++ * FxnNotImplemented
++ * InitCodMgr
++ * InsertDevObject
++ * IsValidHandle
++ * RemoveDevObject
++ * StoreInterfaceFxns
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn Support for IVA DEH
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 29-Nov-2001 jeh Check for DSP_ENOTIMPL status of DEH create function.
++ *! 05-Nov-2001 kc Added support for DEH module.
++ *! 05-Aug-2001 ag Shared memory registration moved to WMD_IO_OnLoaded().
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 11-Apr-2001 rr: Removed CMM_RegisterGPPSMSeg.
++ *! 02-Apr-2001 rr: CHNL_Create failure is printed out.
++ *! 15-Jan-2001 jeh Removed call to IO_OnLoaded() from DEV_Create2().
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name update.
++ *! 15-Dec-2000 rr: Dev_Create2 returns error if NODE_CreateMgr fails.
++ *! 05-Dec-2000 jeh Moved IO_OnLoaded() to PROC_Load. Added DEV_SetMsgMgr.
++ *! 05-Dev-2000 ag SM Heap for messaging registered via CMM_RegisterGPPSMSeg().
++ *! SM heap base and size currently taken from registry.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added calls to get IO manager (IO_Create), IO_OnLoaded().
++ *! 06-Oct-2000 rr: DEV_Destroy2 and DEV_Create2 added.
++ *! 02-Oct-2000 rr: DEV_GetNodeManager added.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr(), CMM_Init() & CMM_Exit().
++ *! Removed <dspbridge/std.h> & <stdwin.h>, added <dspbridge/dbtype.h>
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! DEV_Cleanup calls PROC_Detach if it is a matching process.
++ *! 27-Jul-2000 rr: DEV is in new directoy DEV and produces devlib.lib
++ *! 17-Jul-2000 rr: DRV Object holds the list of Dev Objects. DEV gets
++ *! the List and Next devices through DRV.
++ *! DEV object has a back pointer to DRV Object.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 09-May-2000 rr: dwMemBase has index for multiple windows need.
++ *! 28-Feb-2000 rr: New GT Usage implemented.
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 21-Jan-2000 rr: windows.h, tchar.h, HMODULE removed. FreeLibrary replaced
++ *! with LDR_FreeModule
++ *! 17-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! StoreInterfaceFxns stores the new fxn WMD_BRD_SETSTATE.
++ *! 20-Nov-1999 ag: Actual uSMLength = total - monitor offset.
++ *! 12-Nov-1999 rr: bIRQ and IRQAttrib taken from the struct CFG_HOSTRES.
++ *! dMemBase is added with offset for monitor taken from
++ *! registry.
++ *! 31-Oct-1999 ag: Added CHNL support.
++ *! 10-Sep-1999 rr: GT Enabled. DEV_Create will Load the Mini Driver and will
++ *! find its fxn table. Right now lot of things are hardcoded
++ *! as the REG is not ready.
++ *! 10-Jun-1996 rr: Created from WSX
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++#include <dspbridge/wcd.h> /* WCD version info. */
++
++#include <dspbridge/chnl.h>
++#include <dspbridge/io.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++#define SIGNATURE 0x5f564544 /* "DEV_" (in reverse) */
++#define MAKEVERSION(major, minor) (major * 10 + minor)
++#define WCDVERSION MAKEVERSION(WCD_MAJOR_VERSION, WCD_MINOR_VERSION)
++
++/* The WMD device object: */
++struct DEV_OBJECT {
++ /* LST requires "link" to be first field! */
++ struct LST_ELEM link; /* Link to next DEV_OBJECT. */
++ u32 devType; /* Device Type */
++ u32 dwSignature; /* Used for object validation. */
++ struct CFG_DEVNODE *hDevNode; /* Platform specific device id */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE intfFxns; /* Function interface to WMD. */
++ struct BRD_OBJECT *lockOwner; /* Client with exclusive access. */
++ struct COD_MANAGER *hCodMgr; /* Code manager handle. */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager. */
++ struct DEH_MGR *hDehMgr; /* DEH manager. */
++ struct MSG_MGR *hMsgMgr; /* Message manager. */
++ struct IO_MGR *hIOMgr; /* IO manager (CHNL, MSG) */
++ struct CMM_OBJECT *hCmmMgr; /* SM memory manager. */
++ struct DMM_OBJECT *hDmmMgr; /* Dynamic memory manager. */
++ struct LDR_MODULE *hModule; /* WMD Module handle. */
++ u32 uWordSize; /* DSP word size: quick access. */
++ struct DRV_OBJECT *hDrvObject; /* Driver Object */
++ struct LST_LIST *procList; /* List of Proceeosr attached to
++ * this device */
++ struct NODE_MGR *hNodeMgr;
++} ;
++
++/* ----------------------------------- Globals */
++static u32 cRefs; /* Module reference count */
++#if GT_TRACE
++static struct GT_Mask debugMask = { NULL, NULL }; /* For debugging */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS FxnNotImplemented(int arg, ...);
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject);
++static bool IsValidHandle(struct DEV_OBJECT *hObj);
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns);
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject, then calls the
++ * device's WMD_BRD_Write() function.
++ */
++u32 DEV_BrdWriteFxn(void *pArb, u32 ulDspAddr, void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)pArb;
++ u32 ulWritten = 0;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pHostBuf != NULL); /* Required of BrdWrite(). */
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_BrdWriteFxn, pArb: 0x%x\n\t\t"
++ "ulDspAddr: 0x%x\n\t\tpHostBuf: 0x%x\n \t\tulNumBytes: 0x%x\n"
++ "\t\tnMemSpace: 0x%x\n", pArb, ulDspAddr, pHostBuf,
++ ulNumBytes, nMemSpace);
++ if (IsValidHandle(pDevObject)) {
++ /* Require of BrdWrite() */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnBrdWrite)(pDevObject->
++ hWmdContext, pHostBuf, ulDspAddr, ulNumBytes,
++ nMemSpace);
++ /* Special case of getting the address only */
++ if (ulNumBytes == 0)
++ ulNumBytes = 1;
++ if (DSP_SUCCEEDED(status))
++ ulWritten = ulNumBytes;
++
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_BrdWriteFxn ulWritten: 0x%x\n",
++ ulWritten);
++ return ulWritten;
++}
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the PM Mini Driver for a
++ * PM board (device).
++ */
++DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode)
++{
++ struct LDR_MODULE *hModule = NULL;
++ struct WMD_DRV_INTERFACE *pDrvFxns = NULL;
++ struct DEV_OBJECT *pDevObject = NULL;
++ struct CHNL_MGRATTRS mgrAttrs;
++ struct IO_ATTRS ioMgrAttrs;
++ u32 uNumWindows;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(pstrWMDFileName != NULL);
++ DBC_Require(pHostConfig != NULL);
++ DBC_Require(pDspConfig != NULL);
++
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_CreateDevice, phDevObject: 0x%x\n"
++ "\t\tpstrWMDFileName: 0x%x\n\t\tpHostConfig:0x%x\n\t\t"
++ "pDspConfig: 0x%x\n\t\tnhDevNode: 0x%x\n", phDevObject,
++ pstrWMDFileName, pHostConfig, pDspConfig, hDevNode);
++ /* Get the WMD interface functions*/
++ WMD_DRV_Entry(&pDrvFxns, pstrWMDFileName);
++ if (DSP_FAILED(CFG_GetObject((u32 *) &hDrvObject, REG_DRV_OBJECT))) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_0trace(debugMask, GT_7CLASS,
++ "Failed to get the DRV Object \n");
++ status = DSP_EFAIL;
++ }
++ /* Create the device object, and pass a handle to the WMD for
++ * storage. */
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pDrvFxns);
++ MEM_AllocObject(pDevObject, struct DEV_OBJECT, SIGNATURE);
++ if (pDevObject) {
++ /* Fill out the rest of the Dev Object structure: */
++ pDevObject->hDevNode = hDevNode;
++ pDevObject->hModule = hModule;
++ pDevObject->hCodMgr = NULL;
++ pDevObject->hChnlMgr = NULL;
++ pDevObject->hDehMgr = NULL;
++ pDevObject->lockOwner = NULL;
++ pDevObject->uWordSize = pDspConfig->uWordSize;
++ pDevObject->hDrvObject = hDrvObject;
++ pDevObject->devType = DSP_UNIT;
++ /* Store this WMD's interface functions, based on its
++ * version. */
++ StoreInterfaceFxns(pDrvFxns, &pDevObject->intfFxns);
++ /* Call WMD_DEV_CREATE() to get the WMD's device
++ * context handle. */
++ status = (pDevObject->intfFxns.pfnDevCreate)
++ (&pDevObject->hWmdContext, pDevObject,
++ pHostConfig, pDspConfig);
++ /* Assert WMD_DEV_Create()'s ensure clause: */
++ DBC_Assert(DSP_FAILED(status) || (pDevObject->
++ hWmdContext != NULL));
++ } else {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Out Of Memory");
++ status = DSP_EMEMORY;
++ }
++ }
++ /* Attempt to create the COD manager for this device: */
++ if (DSP_SUCCEEDED(status))
++ status = InitCodMgr(pDevObject);
++
++ /* Attempt to create the channel manager for this device: */
++ if (DSP_SUCCEEDED(status)) {
++ mgrAttrs.cChannels = CHNL_MAXCHANNELS;
++ ioMgrAttrs.bIRQ = pHostConfig->bIRQRegisters;
++ ioMgrAttrs.fShared = (pHostConfig->bIRQAttrib & CFG_IRQSHARED);
++ ioMgrAttrs.uWordSize = pDspConfig->uWordSize;
++ mgrAttrs.uWordSize = pDspConfig->uWordSize;
++ uNumWindows = pHostConfig->wNumMemWindows;
++ if (uNumWindows) {
++ /* Assume last memory window is for CHNL */
++ ioMgrAttrs.dwSMBase = pHostConfig->dwMemBase[1] +
++ pHostConfig->dwOffsetForMonitor;
++ ioMgrAttrs.uSMLength = pHostConfig->dwMemLength[1] -
++ pHostConfig->dwOffsetForMonitor;
++ } else {
++ ioMgrAttrs.dwSMBase = 0;
++ ioMgrAttrs.uSMLength = 0;
++ GT_0trace(debugMask, GT_7CLASS,
++ "**There is no memory reserved for "
++ "shared structures**\n");
++ }
++ status = CHNL_Create(&pDevObject->hChnlMgr, pDevObject,
++ &mgrAttrs);
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK for a device not to have a channel
++ * manager: */
++ status = DSP_SOK;
++ }
++ /* Create CMM mgr even if Msg Mgr not impl. */
++ status = CMM_Create(&pDevObject->hCmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create SM "
++ "Manager\n");
++ }
++ /* Only create IO manager if we have a channel manager */
++ if (DSP_SUCCEEDED(status) && pDevObject->hChnlMgr) {
++ status = IO_Create(&pDevObject->hIOMgr, pDevObject,
++ &ioMgrAttrs);
++ }
++ /* Only create DEH manager if we have an IO manager */
++ if (DSP_SUCCEEDED(status)) {
++ /* Instantiate the DEH module */
++ status = (*pDevObject->intfFxns.pfnDehCreate)
++ (&pDevObject->hDehMgr, pDevObject);
++ }
++ /* Create DMM mgr . */
++ status = DMM_Create(&pDevObject->hDmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create DMM "
++ "Manager\n");
++ }
++ }
++ /* Add the new DEV_Object to the global list: */
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem(&pDevObject->link);
++ status = DRV_InsertDevObject(hDrvObject, pDevObject);
++ }
++ /* Create the Processor List */
++ if (DSP_SUCCEEDED(status)) {
++ pDevObject->procList = LST_Create();
++ if (!(pDevObject->procList)) {
++ status = DSP_EFAIL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create: "
++ "Failed to Create Proc List");
++ }
++ }
++ /* If all went well, return a handle to the dev object;
++ * else, cleanup and return NULL in the OUT parameter. */
++ if (DSP_SUCCEEDED(status)) {
++ *phDevObject = pDevObject;
++ GT_1trace(debugMask, GT_1CLASS,
++ "DEV_CreateDevice Succeeded \nDevObject "
++ "0x%x\n", pDevObject);
++ } else {
++ if (pDevObject && pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ if (pDevObject && pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject && pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ if (pDevObject)
++ MEM_FreeObject(pDevObject);
++
++ *phDevObject = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_CreateDevice Failed\n");
++ }
++ GT_1trace(debugMask, GT_1CLASS, "Exiting DEV_Create: DevObject 0x%x\n",
++ *phDevObject);
++ DBC_Ensure((DSP_SUCCEEDED(status) && IsValidHandle(*phDevObject)) ||
++ (DSP_FAILED(status) && !*phDevObject));
++ return status;
++}
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ */
++DSP_STATUS DEV_Create2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Create2, hDevObject: 0x%x\n", hDevObject);
++ /* There can be only one Node Manager per DEV object */
++ DBC_Assert(!pDevObject->hNodeMgr);
++ status = NODE_CreateMgr(&pDevObject->hNodeMgr, hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_Create2: NODE_CreateMgr failed, "
++ "0x%x!\n", status);
++ pDevObject->hNodeMgr = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create2: Failed!!\n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr != NULL)
++ || (DSP_FAILED(status) && pDevObject->hNodeMgr == NULL));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Create2, hNodeMgr: 0x%x, status:"
++ " 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ */
++DSP_STATUS DEV_Destroy2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Destroy2, hDevObject: 0x%x\n",
++ hDevObject);
++ if (pDevObject->hNodeMgr) {
++ if (DSP_FAILED(NODE_DeleteMgr(pDevObject->hNodeMgr)))
++ status = DSP_EFAIL;
++ else
++ pDevObject->hNodeMgr = NULL;
++
++ }
++ if (DSP_FAILED(status))
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy2 failed!!\n");
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr == NULL) ||
++ DSP_FAILED(status));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Destroy2, hNodeMgr: 0x%x, status"
++ " = 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ */
++DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER, "Entered DEV_DestroyDevice, hDevObject: "
++ "0x%x\n", hDevObject);
++ if (IsValidHandle(hDevObject)) {
++ if (pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject->hNodeMgr)
++ NODE_DeleteMgr(pDevObject->hNodeMgr);
++
++ /* Free the io, channel, and message managers for this board: */
++ if (pDevObject->hIOMgr) {
++ IO_Destroy(pDevObject->hIOMgr);
++ pDevObject->hIOMgr = NULL;
++ }
++ if (pDevObject->hChnlMgr) {
++ CHNL_Destroy(pDevObject->hChnlMgr);
++ pDevObject->hChnlMgr = NULL;
++ }
++ if (pDevObject->hMsgMgr)
++ MSG_Delete(pDevObject->hMsgMgr);
++
++ if (pDevObject->hDehMgr) {
++ /* Uninitialize DEH module. */
++ (*pDevObject->intfFxns.pfnDehDestroy)
++ (pDevObject->hDehMgr);
++ }
++ if (pDevObject->hCmmMgr)
++ CMM_Destroy(pDevObject->hCmmMgr, true);
++
++ if (pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ /* Call the driver's WMD_DEV_Destroy() function: */
++ /* Require of DevDestroy */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnDevDestroy)
++ (pDevObject->hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ if (pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ /* Remove this DEV_Object from the global list: */
++ DRV_RemoveDevObject(pDevObject->hDrvObject, pDevObject);
++ /* Free The library * LDR_FreeModule
++ * (pDevObject->hModule);*/
++ /* Free this dev object: */
++ MEM_FreeObject(pDevObject);
++ }
++ } else {
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy: Invlaid handle");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_destroy: status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager handle created for this
++ * device.
++ */
++DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetChnlMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hChnlMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetChnlMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetChnlMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCmmMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hCmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetCmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCmmMgr: status 0x%x\t\nhMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER, "Entered DEV_GetDmmMgr, hDevObject: "
++ "0x%x\n\t\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hDmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDmmMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ */
++DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCodMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCodMgr, hDevObject: 0x%x\n\t\t"
++ "phCodMgr: 0x%x\n", hDevObject, phCodMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phCodMgr = pDevObject->hCodMgr;
++ } else {
++ *phCodMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetCodMgr, invalid handle: 0x%x\n",
++ hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCodMgr: status 0x%x\t\n hCodMgr:"
++ " 0x%x\n", status, *phCodMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phCodMgr != NULL) &&
++ (*phCodMgr == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetDehMgr ========
++ */
++DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDehMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++ if (IsValidHandle(hDevObject)) {
++ *phDehMgr = hDevObject->hDehMgr;
++ } else {
++ *phDehMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDehMgr: Invalid handle");
++ }
++ return status;
++}
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ */
++DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevNode != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetDevNode, hDevObject: 0x%x\n\t"
++ "\tphDevNode: 0x%x\n", hDevObject, phDevNode);
++ if (IsValidHandle(hDevObject)) {
++ *phDevNode = pDevObject->hDevNode;
++ } else {
++ *phDevNode = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDevNode: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDevNode: status 0x%x\t\nhDevNode:"
++ "0x%x\n", status, *phDevNode);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phDevNode != NULL) &&
++ (*phDevNode == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list
++ * DEV_OBJECTs maintained by DEV.
++ */
++struct DEV_OBJECT *DEV_GetFirst(void)
++{
++ struct DEV_OBJECT *pDevObject = NULL;
++
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++
++ DBC_Ensure((pDevObject == NULL) || IsValidHandle(pDevObject));
++
++ return pDevObject;
++}
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * ppIntfFxns != NULL.
++ */
++DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(ppIntfFxns != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetIntfFxns, hDevObject: 0x%x\n\t"
++ "\tppIntfFxns: 0x%x\n", hDevObject, ppIntfFxns);
++ if (IsValidHandle(hDevObject)) {
++ *ppIntfFxns = &pDevObject->intfFxns;
++ } else {
++ *ppIntfFxns = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetIntDxns: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetIntFxns: status 0x%x\t\n"
++ "ppIntFxns: 0x%x\n", status, *ppIntfFxns);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((ppIntfFxns != NULL) &&
++ (*ppIntfFxns == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetIOMgr ========
++ */
++DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ if (IsValidHandle(hDevObject)) {
++ *phIOMgr = hDevObject->hIOMgr;
++ } else {
++ *phIOMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_GetIOMgr: Invalid handle");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ */
++struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT *hDevObject)
++{
++ struct DEV_OBJECT *pNextDevObject = NULL;
++
++ if (IsValidHandle(hDevObject)) {
++ pNextDevObject = (struct DEV_OBJECT *)
++ DRV_GetNextDevObject((u32)hDevObject);
++ }
++ DBC_Ensure((pNextDevObject == NULL) || IsValidHandle(pNextDevObject));
++ return pNextDevObject;
++}
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ */
++void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ *phMsgMgr = hDevObject->hMsgMgr;
++}
++
++/*
++ * ======== DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle
++ */
++DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetNodeManager, hDevObject: 0x%x"
++ "\n\t\tphNodeMgr: 0x%x\n", hDevObject, phNodeMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phNodeMgr = pDevObject->hNodeMgr;
++ } else {
++ *phNodeMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetNodeManager, invalid handle: 0x"
++ "%x\n", hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetNodeManager: status 0x%x\t\nhMgr:"
++ " 0x%x\n", status, *phNodeMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNodeMgr != NULL) &&
++ (*phNodeMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetSymbol ========
++ */
++DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym, OUT u32 *pulValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_MANAGER *hCodMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pstrSym != NULL && pulValue != NULL);
++
++ GT_3trace(debugMask, GT_ENTER,
++ "Entered DEV_GetSymbol, hDevObject: 0x%x\n\t\t"
++ "pstrSym: 0x%x\n\t\tpulValue: 0x%x\n", hDevObject, pstrSym,
++ pulValue);
++ if (IsValidHandle(hDevObject)) {
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(hCodMgr != NULL);
++ status = COD_GetSymValue(hCodMgr, (char *)pstrSym,
++ pulValue);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetSymbol: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetSymbol: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *pulValue);
++ return status;
++}
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ */
++DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phWmdContext != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetWMDContext, hDevObject: 0x%x\n"
++ "\t\tphWmdContext: 0x%x\n", hDevObject, phWmdContext);
++ if (IsValidHandle(hDevObject)) {
++ *phWmdContext = pDevObject->hWmdContext;
++ } else {
++ *phWmdContext = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetWMDContext: Invalid handle");
++ }
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetWMDContext: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *phWmdContext);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phWmdContext != NULL) &&
++ (*phWmdContext == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void DEV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ if (cRefs == 0) {
++ CMM_Exit();
++ DMM_Exit();
++ }
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Exit, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ */
++bool DEV_Init(void)
++{
++ bool fCmm, fDmm, fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!debugMask.flags);
++ GT_create(&debugMask, "DV"); /* "DV" for DeVice */
++ fCmm = CMM_Init();
++ fDmm = DMM_Init();
++
++ fRetval = fCmm && fDmm;
++
++ if (!fRetval) {
++ if (fCmm)
++ CMM_Exit();
++
++
++ if (fDmm)
++ DMM_Exit();
++
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ */
++DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject, u32 ulStatus)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ struct DEV_OBJECT *pDevObject = hDevObject;
++ DSP_HPROCESSOR hProcObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_NotifyClients, hDevObject: 0x%x\n"
++ "\t\tulStatus: 0x%x\n", hDevObject, ulStatus);
++ for (hProcObject = (DSP_HPROCESSOR)LST_First(pDevObject->procList);
++ hProcObject != NULL;
++ hProcObject = (DSP_HPROCESSOR)LST_Next(pDevObject->procList,
++ (struct LST_ELEM *)hProcObject))
++ PROC_NotifyClients(hProcObject, (u32) ulStatus);
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveDevice ========
++ */
++DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject; /* handle to device object */
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject;
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_RemoveDevice, hDevNode: 0x%x\n", hDevNode);
++ /* Retrieve the device object handle originaly stored with
++ * the DevNode: */
++ status = CFG_GetDevObject(hDevNode, (u32 *)&hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Remove the Processor List */
++ pDevObject = (struct DEV_OBJECT *)hDevObject;
++ /* Destroy the device object. */
++ status = DEV_DestroyDevice(hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Null out the handle stored with the DevNode. */
++ GT_0trace(debugMask, GT_1CLASS,
++ "DEV_RemoveDevice, success");
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_RemoveDevice, status: 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ */
++DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject, struct CHNL_MGR *hMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetChnlMgr, hDevObject: 0x%x\n\t"
++ "\thMgr:0x%x\n", hDevObject, hMgr);
++ if (IsValidHandle(hDevObject)) {
++ pDevObject->hChnlMgr = hMgr;
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_SetChnlMgr, Invalid handle\n");
++ }
++ DBC_Ensure(DSP_FAILED(status) || (pDevObject->hChnlMgr == hMgr));
++ return status;
++}
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the message manager for this device.
++ */
++void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject, struct MSG_MGR *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetMsgMgr, hDevObject: 0x%x\n\t\t"
++ "hMgr: 0x%x\n", hDevObject, hMgr);
++ hDevObject->hMsgMgr = hMgr;
++}
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the BRIDGE environment.
++ */
++DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject = NULL; /* handle to 'Bridge Device */
++ struct CFG_HOSTRES hostRes; /* resources struct. */
++ struct CFG_DSPRES dspRes; /* DSP resources struct */
++ char szWMDFileName[CFG_MAXSEARCHPATHLEN] = "UMA"; /* wmd filename */
++ DSP_STATUS status;
++ struct MGR_OBJECT *hMgrObject = NULL;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_StartDevice, hDevObject: 0x%x\n", hDevNode);
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++ if (DSP_SUCCEEDED(status)) {
++ /* Get DSP resources of device from Registry: */
++ status = CFG_GetDSPResources(hDevNode, &dspRes);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD DSP resources"
++ " from registry: 0x%x ", status);
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD Host resources "
++ "from registry: 0x%x ", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Given all resources, create a device object. */
++ status = DEV_CreateDevice(&hDevObject, szWMDFileName, &hostRes,
++ &dspRes, hDevNode);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store away the hDevObject with the DEVNODE */
++ status = CFG_SetDevObject(hDevNode, (u32)hDevObject);
++ if (DSP_FAILED(status)) {
++ /* Clean up */
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to set DevObject in the "
++ "Registry: 0x%x", status);
++ DEV_DestroyDevice(hDevObject);
++ hDevObject = NULL;
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to Create Device: 0x%x",
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the Manager Object */
++ status = MGR_Create(&hMgrObject, hDevNode);
++ }
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS, "Failed to MGR object: 0x%x",
++ status);
++ status = DSP_EFAIL;
++ }
++ if (DSP_FAILED(status)) {
++ if (hDevObject)
++ DEV_DestroyDevice(hDevObject);
++
++ /* Ensure the device extension is NULL */
++ CFG_SetDevObject(hDevNode, 0L);
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exiting DEV_StartDevice status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== FxnNotImplemented ========
++ * Purpose:
++ * Takes the place of a WMD Null Function.
++ * Parameters:
++ * Multiple, optional.
++ * Returns:
++ * DSP_ENOTIMPL: Always.
++ */
++static DSP_STATUS FxnNotImplemented(int arg, ...)
++{
++ DBG_Trace(DBG_LEVEL1,
++ "WARNING: Calling a non-implemented WMD function.\n");
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== IsValidHandle ========
++ * Purpose:
++ * Validate the device object handle.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * true if handle is valid; false otherwise.
++ * Requires:
++ * Ensures:
++ */
++static bool IsValidHandle(struct DEV_OBJECT *hObj)
++{
++ bool retVal;
++
++ retVal = (hObj != NULL) && (hObj->dwSignature == SIGNATURE);
++
++ return retVal;
++}
++
++/*
++ * ======== InitCodMgr ========
++ * Purpose:
++ * Create a COD manager for this device.
++ * Parameters:
++ * pDevObject: Pointer to device object created with
++ * DEV_CreateDevice()
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * Should only be called once by DEV_CreateDevice() for a given DevObject.
++ * Ensures:
++ */
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *szDummyFile = "dummy";
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(!IsValidHandle(pDevObject) ||
++ (pDevObject->hCodMgr == NULL));
++ GT_1trace(debugMask, GT_ENTER, "Entering InitCodMgr pDevObject: 0x%x",
++ pDevObject);
++ status = COD_Create(&pDevObject->hCodMgr, szDummyFile, NULL);
++ GT_1trace(debugMask, GT_ENTER, "Exiting InitCodMgr status 0x%x\n ",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Insert a ProcObject into the list maintained by DEV.
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List Exists
++ * hDevObject is Valid handle
++ * DEV Initialized
++ * pbAlreadyAttached != NULL
++ * hProcObject != 0
++ * Ensures:
++ * DSP_SOK and List is not Empty.
++ */
++DSP_STATUS DEV_InsertProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject,
++ OUT bool *pbAlreadyAttached)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entering DEV_InsetProcObject pProcObject 0x%x"
++ "pDevObject 0x%x\n", hProcObject, hDevObject);
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(pbAlreadyAttached != NULL);
++ if (!LST_IsEmpty(pDevObject->procList))
++ *pbAlreadyAttached = true;
++
++ /* Add DevObject to tail. */
++ LST_PutTail(pDevObject->procList, (struct LST_ELEM *)hProcObject);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Exiting DEV_InsetProcObject status 0x%x\n", status);
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDevObject->procList));
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject Ptr to Dev Object where the list is.
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List exists and is not empty
++ * hProcObject != 0
++ * hDevObject is a valid Dev handle.
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ */
++DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct LST_ELEM *pCurElem;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(!LST_IsEmpty(pDevObject->procList));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entering DEV_RemoveProcObject hDevObject "
++ "0x%x\n", hDevObject);
++ /* Search list for pDevObject: */
++ for (pCurElem = LST_First(pDevObject->procList); pCurElem != NULL;
++ pCurElem = LST_Next(pDevObject->procList, pCurElem)) {
++ /* If found, remove it. */
++ if ((u32)pCurElem == hProcObject) {
++ LST_RemoveElem(pDevObject->procList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "DEV_RemoveProcObject returning 0x%x\n",
++ status);
++ return status;
++}
++
++DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject, u32 *devType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hdevObject;
++
++ *devType = pDevObject->devType;
++
++ return status;
++}
++
++/*
++ * ======== StoreInterfaceFxns ========
++ * Purpose:
++ * Copy the WMD's interface functions into the device object,
++ * ensuring that FxnNotImplemented() is set for:
++ *
++ * 1. All WMD function pointers which are NULL; and
++ * 2. All function slots in the struct DEV_OBJECT structure which have no
++ * corresponding slots in the the WMD's interface, because the WMD
++ * is of an *older* version.
++ * Parameters:
++ * pIntfFxns: Interface Fxn Structure of the WCD's Dev Object.
++ * pDrvFxns: Interface Fxns offered by the WMD during DEV_Create().
++ * Returns:
++ * Requires:
++ * Input pointers are valid.
++ * WMD is *not* written for a newer WCD.
++ * Ensures:
++ * All function pointers in the dev object's Fxn interface are not NULL.
++ */
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns)
++{
++ u32 dwWMDVersion;
++
++ /* Local helper macro: */
++#define StoreFxn(cast, pfn) \
++ (pIntfFxns->pfn = ((pDrvFxns->pfn != NULL) ? pDrvFxns->pfn : \
++ (cast)FxnNotImplemented))
++
++ DBC_Require(pIntfFxns != NULL);
++ DBC_Require(pDrvFxns != NULL);
++ DBC_Require(MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion) <= WCDVERSION);
++ dwWMDVersion = MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion);
++ pIntfFxns->dwWCDMajorVersion = pDrvFxns->dwWCDMajorVersion;
++ pIntfFxns->dwWCDMinorVersion = pDrvFxns->dwWCDMinorVersion;
++ /* Install functions up to WCD version .80 (first alpha): */
++ if (dwWMDVersion > 0) {
++ StoreFxn(WMD_DEV_CREATE, pfnDevCreate);
++ StoreFxn(WMD_DEV_DESTROY, pfnDevDestroy);
++ StoreFxn(WMD_DEV_CTRL, pfnDevCntrl);
++ StoreFxn(WMD_BRD_MONITOR, pfnBrdMonitor);
++ StoreFxn(WMD_BRD_START, pfnBrdStart);
++ StoreFxn(WMD_BRD_STOP, pfnBrdStop);
++ StoreFxn(WMD_BRD_STATUS, pfnBrdStatus);
++ StoreFxn(WMD_BRD_READ, pfnBrdRead);
++ StoreFxn(WMD_BRD_WRITE, pfnBrdWrite);
++ StoreFxn(WMD_BRD_SETSTATE, pfnBrdSetState);
++ StoreFxn(WMD_BRD_MEMCOPY, pfnBrdMemCopy);
++ StoreFxn(WMD_BRD_MEMWRITE, pfnBrdMemWrite);
++ StoreFxn(WMD_BRD_MEMMAP, pfnBrdMemMap);
++ StoreFxn(WMD_BRD_MEMUNMAP, pfnBrdMemUnMap);
++ StoreFxn(WMD_CHNL_CREATE, pfnChnlCreate);
++ StoreFxn(WMD_CHNL_DESTROY, pfnChnlDestroy);
++ StoreFxn(WMD_CHNL_OPEN, pfnChnlOpen);
++ StoreFxn(WMD_CHNL_CLOSE, pfnChnlClose);
++ StoreFxn(WMD_CHNL_ADDIOREQ, pfnChnlAddIOReq);
++ StoreFxn(WMD_CHNL_GETIOC, pfnChnlGetIOC);
++ StoreFxn(WMD_CHNL_CANCELIO, pfnChnlCancelIO);
++ StoreFxn(WMD_CHNL_FLUSHIO, pfnChnlFlushIO);
++ StoreFxn(WMD_CHNL_GETINFO, pfnChnlGetInfo);
++ StoreFxn(WMD_CHNL_GETMGRINFO, pfnChnlGetMgrInfo);
++ StoreFxn(WMD_CHNL_IDLE, pfnChnlIdle);
++ StoreFxn(WMD_CHNL_REGISTERNOTIFY, pfnChnlRegisterNotify);
++ StoreFxn(WMD_DEH_CREATE, pfnDehCreate);
++ StoreFxn(WMD_DEH_DESTROY, pfnDehDestroy);
++ StoreFxn(WMD_DEH_NOTIFY, pfnDehNotify);
++ StoreFxn(WMD_DEH_REGISTERNOTIFY, pfnDehRegisterNotify);
++ StoreFxn(WMD_DEH_GETINFO, pfnDehGetInfo);
++ StoreFxn(WMD_IO_CREATE, pfnIOCreate);
++ StoreFxn(WMD_IO_DESTROY, pfnIODestroy);
++ StoreFxn(WMD_IO_ONLOADED, pfnIOOnLoaded);
++ StoreFxn(WMD_IO_GETPROCLOAD, pfnIOGetProcLoad);
++ StoreFxn(WMD_MSG_CREATE, pfnMsgCreate);
++ StoreFxn(WMD_MSG_CREATEQUEUE, pfnMsgCreateQueue);
++ StoreFxn(WMD_MSG_DELETE, pfnMsgDelete);
++ StoreFxn(WMD_MSG_DELETEQUEUE, pfnMsgDeleteQueue);
++ StoreFxn(WMD_MSG_GET, pfnMsgGet);
++ StoreFxn(WMD_MSG_PUT, pfnMsgPut);
++ StoreFxn(WMD_MSG_REGISTERNOTIFY, pfnMsgRegisterNotify);
++ StoreFxn(WMD_MSG_SETQUEUEID, pfnMsgSetQueueId);
++ }
++ /* Add code for any additional functions in newer WMD versions here: */
++ /* Ensure postcondition: */
++ DBC_Ensure(pIntfFxns->pfnDevCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevCntrl != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdMonitor != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStart != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStop != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStatus != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdRead != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdWrite != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlOpen != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlClose != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlAddIOReq != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetIOC != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCancelIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlFlushIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetMgrInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlIdle != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnIODestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOOnLoaded != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOGetProcLoad != NULL);
++ DBC_Ensure(pIntfFxns->pfnMsgSetQueueId != NULL);
++
++#undef StoreFxn
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dmm.c b/drivers/dsp/bridge/pmgr/dmm.c
+new file mode 100644
+index 0000000..803de93
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dmm.c
+@@ -0,0 +1,692 @@
++/*
++ * dmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dmm.c ========
++ * Purpose:
++ * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ * DMM_CreateTables
++ * DMM_Create
++ * DMM_Destroy
++ * DMM_Exit
++ * DMM_Init
++ * DMM_MapMemory
++ * DMM_Reset
++ * DMM_ReserveMemory
++ * DMM_UnMapMemory
++ * DMM_UnReserveMemory
++ *
++ * Private Functions:
++ * AddRegion
++ * CreateRegion
++ * GetRegion
++ * GetFreeRegion
++ * GetMappedRegion
++ *
++ * Notes:
++ * Region: Generic memory entitiy having a start address and a size
++ * Chunk: Reserved region
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 04-Jun-2008 Hari K : Optimized DMM implementation. Removed linked list
++ *! and instead used Table approach.
++ *! 19-Apr-2004 sb: Integrated Alan's code review updates.
++ *! 17-Mar-2004 ap: Fixed GetRegion for size=0 using tighter bound.
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define DMMSIGNATURE 0x004d4d44 /* "DMM" (in reverse) */
++
++#define DMM_ADDR_VIRTUAL(a) \
++ (((struct MapPage *)(a) - pVirtualMappingTable) * PG_SIZE_4K +\
++ dynMemMapBeg)
++#define DMM_ADDR_TO_INDEX(a) (((a) - dynMemMapBeg) / PG_SIZE_4K)
++
++/* DMM Mgr */
++struct DMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Dmm Lock is used to serialize access mem manager for
++ * multi-threads. */
++ struct SYNC_CSOBJECT *hDmmLock; /* Lock to access dmm mgr */
++};
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++struct MapPage {
++ u32 RegionSize:15;
++ u32 MappedSize:15;
++ u32 bReserved:1;
++ u32 bMapped:1;
++};
++
++/* Create the free list */
++static struct MapPage *pVirtualMappingTable;
++static u32 iFreeRegion; /* The index of free region */
++static u32 iFreeSize;
++static u32 *pPhysicalAddrTable; /* Physical address of MPU buffer */
++static u32 dynMemMapBeg; /* The Beginning of dynamic memory mapping */
++static u32 TableSize;/* The size of virtual and physical pages tables */
++
++/* ----------------------------------- Function Prototypes */
++static struct MapPage *GetRegion(u32 addr);
++static struct MapPage *GetFreeRegion(u32 aSize);
++static struct MapPage *GetMappedRegion(u32 aAddr);
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++/* ======== DMM_CreateTables ========
++ * Purpose:
++ * Create table to hold the information of physical address
++ * the buffer pages that is passed by the user, and the table
++ * to hold the information of the virtual memory that is reserved
++ * for DSP.
++ */
++DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_CreateTables () hDmmMgr %x, addr"
++ " %x, size %x\n", hDmmMgr, addr, size);
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ dynMemMapBeg = addr;
++ TableSize = (size/PG_SIZE_4K) + 1;
++ /* Create the free list */
++ pVirtualMappingTable = (struct MapPage *) MEM_Calloc
++ (TableSize*sizeof(struct MapPage), MEM_NONPAGED);
++ if (pVirtualMappingTable == NULL)
++ status = DSP_EMEMORY;
++ else {
++ /* This table will be used
++ * to store the virtual to physical
++ * address translations
++ */
++ pPhysicalAddrTable = (u32 *)MEM_Calloc
++ (TableSize*sizeof(u32), MEM_NONPAGED);
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "DMM_CreateTables: Allocate"
++ "memory for pPhysicalAddrTable=%d entries\n",
++ TableSize);
++ if (pPhysicalAddrTable == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: Memory allocation for "
++ "pPhysicalAddrTable failed\n");
++ } else {
++ /* On successful allocation,
++ * all entries are zero ('free') */
++ iFreeRegion = 0;
++ iFreeSize = TableSize*PG_SIZE_4K;
++ pVirtualMappingTable[0].RegionSize = TableSize;
++ }
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: DMM_DeleteTables"
++ "Failure\n");
++
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status"
++ "0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DMM_Create ========
++ * Purpose:
++ * Create a dynamic memory manager object.
++ */
++DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs)
++{
++ struct DMM_OBJECT *pDmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "DMM_Create: phDmmMgr: 0x%x hDevObject: "
++ "0x%x pMgrAttrs: 0x%x\n", phDmmMgr, hDevObject, pMgrAttrs);
++ *phDmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pDmmObject, struct DMM_OBJECT, DMMSIGNATURE);
++ if (pDmmObject != NULL) {
++ status = SYNC_InitializeCS(&pDmmObject->hDmmLock);
++ if (DSP_SUCCEEDED(status))
++ *phDmmMgr = pDmmObject;
++ else
++ DMM_Destroy(pDmmObject);
++ } else {
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Create: Object Allocation "
++ "Failure(DMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_Create status %x pDmmObject %x\n",
++ status, pDmmObject);
++
++ return status;
++}
++
++/*
++ * ======== DMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Destroy () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ /* Delete CS & dmm mgr object */
++ SYNC_DeleteCS(pDmmObj->hDmmLock);
++ MEM_FreeObject(pDmmObj);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Destroy: DMM_DeleteTables "
++ "Failure\n");
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_Destroy status %x\n",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== DMM_DeleteTables ========
++ * Purpose:
++ * Delete DMM Tables.
++ */
++DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_DeleteTables () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ /* Delete all DMM tables */
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ if (pVirtualMappingTable != NULL)
++ MEM_Free(pVirtualMappingTable);
++
++ if (pPhysicalAddrTable != NULL)
++ MEM_Free(pPhysicalAddrTable);
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_DeleteTables status %x\n", status);
++ return status;
++}
++
++
++
++
++/*
++ * ======== DMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void DMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "exiting DMM_Exit, ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "DMM_GetHandle: hProcessor %x, phDmmMgr"
++ "%x\n", hProcessor, phDmmMgr);
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDmmMgr(hDevObject, phDmmMgr);
++
++ GT_2trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_GetHandle status %x, "
++ "*phDmmMgr %x\n", status, phDmmMgr ? *phDmmMgr : NULL);
++ return status;
++}
++
++/*
++ * ======== DMM_Init ========
++ * Purpose:
++ * Initializes private state of DMM module.
++ */
++bool DMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /*"DM" for Dymanic Memory Manager */
++ GT_create(&DMM_debugMask, "DM");
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Init, ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ pVirtualMappingTable = NULL ;
++ pPhysicalAddrTable = NULL ;
++ TableSize = 0;
++
++ return fRetval;
++}
++
++/*
++ * ======== DMM_MapMemory ========
++ * Purpose:
++ * Add a mapping block to the reserved chunk. DMM assumes that this block
++ * will be mapped in the DSP/IVA's address space. DMM returns an error if a
++ * mapping overlaps another one. This function stores the info that will be
++ * required later while unmapping the block.
++ */
++DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_MapMemory () hDmmMgr %x, "
++ "addr %x, size %x\n", hDmmMgr, addr, size);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ /* Find the Reserved memory chunk containing the DSP block to
++ * be mapped */
++ chunk = (struct MapPage *)GetRegion(addr);
++ if (chunk != NULL) {
++ /* Mark the region 'mapped', leave the 'reserved' info as-is */
++ chunk->bMapped = true;
++ chunk->MappedSize = (size/PG_SIZE_4K);
++ } else
++ status = DSP_ENOTFOUND;
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_MapMemory status %x, chunk %x\n",
++ status, chunk);
++ return status;
++}
++
++/*
++ * ======== DMM_ReserveMemory ========
++ * Purpose:
++ * Reserve a chunk of virtually contiguous DSP/IVA address space.
++ */
++DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
++ u32 *pRsvAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *node;
++ u32 rsvAddr = 0;
++ u32 rsvSize = 0;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_ReserveMemory () hDmmMgr %x, "
++ "size %x, pRsvAddr %x\n", hDmmMgr, size, pRsvAddr);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Try to get a DSP chunk from the free list */
++ node = GetFreeRegion(size);
++ if (node != NULL) {
++ /* DSP chunk of given size is available. */
++ rsvAddr = DMM_ADDR_VIRTUAL(node);
++ /* Calculate the number entries to use */
++ rsvSize = size/PG_SIZE_4K;
++ if (rsvSize < node->RegionSize) {
++ /* Mark remainder of free region */
++ node[rsvSize].bMapped = false;
++ node[rsvSize].bReserved = false;
++ node[rsvSize].RegionSize = node->RegionSize - rsvSize;
++ node[rsvSize].MappedSize = 0;
++ }
++ /* GetRegion will return first fit chunk. But we only use what
++ is requested. */
++ node->bMapped = false;
++ node->bReserved = true;
++ node->RegionSize = rsvSize;
++ node->MappedSize = 0;
++ /* Return the chunk's starting address */
++ *pRsvAddr = rsvAddr;
++ } else
++ /*dSP chunk of given size is not available */
++ status = DSP_EMEMORY;
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving ReserveMemory status %x, rsvAddr"
++ " %x, rsvSize %x\n", status, rsvAddr, rsvSize);
++ return status;
++}
++
++
++/*
++ * ======== DMM_UnMapMemory ========
++ * Purpose:
++ * Remove the mapped block from the reserved chunk.
++ */
++DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 *pSize)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnMapMemory () hDmmMgr %x, "
++ "addr %x, pSize %x\n", hDmmMgr, addr, pSize);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ chunk = GetMappedRegion(addr) ;
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND ;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Unmap the region */
++ *pSize = chunk->MappedSize * PG_SIZE_4K;
++ chunk->bMapped = false;
++ chunk->MappedSize = 0;
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnMapMemory status %x, chunk"
++ " %x, *pSize %x\n", status, chunk, *pSize);
++
++ return status;
++}
++
++/*
++ * ======== DMM_UnReserveMemory ========
++ * Purpose:
++ * Free a chunk of reserved DSP/IVA address space.
++ */
++DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 rsvAddr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 chunkSize;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnReserveMemory () hDmmMgr "
++ "%x, rsvAddr %x\n", hDmmMgr, rsvAddr);
++
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Find the chunk containing the reserved address */
++ chunk = GetMappedRegion(rsvAddr);
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Free all the mapped pages for this reserved region */
++ i = 0;
++ while (i < chunk->RegionSize) {
++ if (chunk[i].bMapped) {
++ /* Remove mapping from the page tables. */
++ chunkSize = chunk[i].MappedSize;
++ /* Clear the mapping flags */
++ chunk[i].bMapped = false;
++ chunk[i].MappedSize = 0;
++ i += chunkSize;
++ } else
++ i++;
++ }
++ /* Clear the flags (mark the region 'free') */
++ chunk->bReserved = false;
++ /* NOTE: We do NOT coalesce free regions here.
++ * Free regions are coalesced in GetRegion(), as it traverses
++ *the whole mapping table
++ */
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnReserveMemory status %x"
++ " chunk %x\n", status, chunk);
++ return status;
++}
++
++
++/*
++ * ======== GetRegion ========
++ * Purpose:
++ * Returns a region containing the specified memory region
++ */
++static struct MapPage *GetRegion(u32 aAddr)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetRegion () "
++ " aAddr %x\n", aAddr);
++
++ if (pVirtualMappingTable != NULL) {
++ /* find page mapped by this address */
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize)
++ currRegion = pVirtualMappingTable + i;
++ }
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving GetRegion currRegion %x, iFreeRegion %d\n,"
++ "iFreeSize %d\n", currRegion, iFreeRegion, iFreeSize) ;
++ return currRegion;
++}
++
++/*
++ * ======== GetFreeRegion ========
++ * Purpose:
++ * Returns the requested free region
++ */
++static struct MapPage *GetFreeRegion(u32 aSize)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++ u32 RegionSize = 0;
++ u32 nextI = 0;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetFreeRegion () "
++ "aSize 0x%x\n", aSize);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++ if (aSize > iFreeSize) {
++ /* Find the largest free region
++ * (coalesce during the traversal) */
++ while (i < TableSize) {
++ RegionSize = pVirtualMappingTable[i].RegionSize;
++ nextI = i+RegionSize;
++ if (pVirtualMappingTable[i].bReserved == false) {
++ /* Coalesce, if possible */
++ if (nextI < TableSize &&
++ pVirtualMappingTable[nextI].bReserved
++ == false) {
++ pVirtualMappingTable[i].RegionSize +=
++ pVirtualMappingTable[nextI].RegionSize;
++ continue;
++ }
++ RegionSize *= PG_SIZE_4K;
++ if (RegionSize > iFreeSize) {
++ iFreeRegion = i;
++ iFreeSize = RegionSize;
++ }
++ }
++ i = nextI;
++ }
++ }
++ if (aSize <= iFreeSize) {
++ currRegion = pVirtualMappingTable + iFreeRegion;
++ iFreeRegion += (aSize / PG_SIZE_4K);
++ iFreeSize -= aSize;
++ }
++ return currRegion;
++}
++
++/*
++ * ======== GetMappedRegion ========
++ * Purpose:
++ * Returns the requestedmapped region
++ */
++static struct MapPage *GetMappedRegion(u32 aAddr)
++{
++ u32 i = 0;
++ struct MapPage *currRegion = NULL;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetMappedRegion () "
++ "aAddr 0x%x\n", aAddr);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize && (pVirtualMappingTable[i].bMapped ||
++ pVirtualMappingTable[i].bReserved))
++ currRegion = pVirtualMappingTable + i;
++ return currRegion;
++}
++
++/*
++ * ======== DMM_GetPhysicalAddrTable ========
++ * Purpose:
++ * Returns the physical table address
++ */
++u32 *DMM_GetPhysicalAddrTable(void)
++{
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered "
++ "DMM_GetPhysicalAddrTable()- pPhysicalAddrTable 0x%x\n",
++ pPhysicalAddrTable);
++ return pPhysicalAddrTable;
++}
++
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr)
++{
++ struct MapPage *curNode = NULL;
++ u32 i;
++ u32 freemem = 0;
++ u32 bigsize = 0;
++
++ SYNC_EnterCS(hDmmMgr->hDmmLock);
++
++ if (pVirtualMappingTable != NULL) {
++ for (i = 0; i < TableSize; i +=
++ pVirtualMappingTable[i].RegionSize) {
++ curNode = pVirtualMappingTable + i;
++ if (curNode->bReserved == TRUE) {
++ /*printk("RESERVED size = 0x%x, "
++ "Map size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K),
++ (curNode->bMapped == false) ? 0 :
++ (curNode->MappedSize * PG_SIZE_4K));
++*/
++ } else {
++/* printk("UNRESERVED size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K));
++*/
++ freemem += (curNode->RegionSize * PG_SIZE_4K);
++ if (curNode->RegionSize > bigsize)
++ bigsize = curNode->RegionSize;
++ }
++ }
++ }
++ printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
++ freemem/(1024*1024));
++ printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
++ (((TableSize * PG_SIZE_4K)-freemem))/(1024*1024));
++ printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
++ (bigsize*PG_SIZE_4K/(1024*1024)));
++ SYNC_LeaveCS(hDmmMgr->hDmmLock);
++
++ return 0;
++}
++#endif
+diff --git a/drivers/dsp/bridge/pmgr/io.c b/drivers/dsp/bridge/pmgr/io.c
+new file mode 100644
+index 0000000..cdfe0dc
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/io.c
+@@ -0,0 +1,205 @@
++/*
++ * io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.c ========
++ * Description:
++ * IO manager interface: Manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD IO functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 04-Apr-2001 rr WSX_STATUS initialized in IO_Create.
++ *! 07-Nov-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <ioobj.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++
++#if GT_TRACE
++static struct GT_Mask IO_DebugMask = { NULL, NULL }; /* WCD IO Mask */
++#endif
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG
++ */
++DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr, struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr = NULL;
++ struct IO_MGR_ *pIOMgr = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(IO_DebugMask, GT_ENTER, "Entered IO_Create: phIOMgr: 0x%x\t "
++ "hDevObject: 0x%x\tpMgrAttrs: 0x%x\n",
++ phIOMgr, hDevObject, pMgrAttrs);
++
++ *phIOMgr = NULL;
++
++ /* A memory base of 0 implies no memory base: */
++ if ((pMgrAttrs->dwSMBase != 0) && (pMgrAttrs->uSMLength == 0)) {
++ status = CHNL_E_INVALIDMEMBASE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Mem Base\n");
++ }
++
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Word size\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnIOCreate)(&hIOMgr, hDevObject,
++ pMgrAttrs);
++
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr = (struct IO_MGR_ *) hIOMgr;
++ pIOMgr->pIntfFxns = pIntfFxns;
++ pIOMgr->hDevObject = hDevObject;
++
++ /* Return the new channel manager handle: */
++ *phIOMgr = hIOMgr;
++ GT_1trace(IO_DebugMask, GT_1CLASS,
++ "IO_Create: Success hIOMgr: 0x%x\n",
++ hIOMgr);
++ }
++ }
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Create: hIOMgr: 0x%x, status:"
++ " 0x%x\n", hIOMgr, status);
++
++ return status;
++}
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Delete IO manager.
++ */
++DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR_ *pIOMgr = (struct IO_MGR_ *)hIOMgr;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(IO_DebugMask, GT_ENTER, "Entered IO_Destroy: hIOMgr: 0x%x\n",
++ hIOMgr);
++
++ pIntfFxns = pIOMgr->pIntfFxns;
++
++ /* Let WMD channel module destroy the IO_MGR: */
++ status = (*pIntfFxns->pfnIODestroy) (hIOMgr);
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Destroy: pIOMgr: 0x%x, status:"
++ " 0x%x\n", pIOMgr, status);
++ return status;
++}
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ */
++void IO_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ */
++bool IO_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!IO_DebugMask.flags);
++ GT_create(&IO_DebugMask, "IO"); /* "IO" for IO */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Init, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
+diff --git a/drivers/dsp/bridge/pmgr/ioobj.h b/drivers/dsp/bridge/pmgr/ioobj.h
+new file mode 100644
+index 0000000..f473a63
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/ioobj.h
+@@ -0,0 +1,52 @@
++/*
++ * ioobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ioobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library IO objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 01/16/97 gp: Created from chnlpriv.h
++ */
++
++#ifndef IOOBJ_
++#define IOOBJ_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/wmd.h>
++
++/*
++ * This struct is the first field in a IO_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct IO_MGR_ {
++ /* These must be the first fields in a IO_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents. */
++} ;
++
++#endif /* IOOBJ_ */
+diff --git a/drivers/dsp/bridge/pmgr/msg.c b/drivers/dsp/bridge/pmgr/msg.c
+new file mode 100644
+index 0000000..bbf5174
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msg.c
+@@ -0,0 +1,173 @@
++/*
++ * msg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.c ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 15-May-2001 ag Changed SUCCEEDED to DSP_SUCCEEDED.
++ *! 16-Feb-2001 jeh Fixed some comments.
++ *! 15-Dec-2000 rr MSG_Create returns DSP_EFAIL if pfnMsgCreate fails.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <msgobj.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MSG_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct MSG_MGR_ *pMsgMgr;
++ struct MSG_MGR *hMsgMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(MSG_debugMask, GT_ENTER, "MSG_Create: phMsgMgr: 0x%x\t"
++ "hDevObject: 0x%x\tmsgCallback: 0x%x\n",
++ phMsgMgr, hDevObject, msgCallback);
++
++ *phMsgMgr = NULL;
++
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD message module finish the create: */
++ status = (*pIntfFxns->pfnMsgCreate)(&hMsgMgr, hDevObject, msgCallback);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD message module's fields of the MSG_MGR
++ * structure */
++ pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ pMsgMgr->pIntfFxns = pIntfFxns;
++
++ /* Finally, return the new message manager handle: */
++ *phMsgMgr = hMsgMgr;
++ GT_1trace(MSG_debugMask, GT_1CLASS,
++ "MSG_Create: Success pMsgMgr: 0x%x\n", pMsgMgr);
++ } else {
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ */
++void MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ struct MSG_MGR_ *pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++
++ GT_1trace(MSG_debugMask, GT_ENTER, "MSG_Delete: hMsgMgr: 0x%x\n",
++ hMsgMgr);
++
++ pIntfFxns = pMsgMgr->pIntfFxns;
++
++ /* Let WMD message module destroy the MSG_MGR: */
++ (*pIntfFxns->pfnMsgDelete)(hMsgMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++}
++
++/*
++ * ======== MSG_Exit ========
++ */
++void MSG_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(MSG_debugMask, GT_5CLASS,
++ "Entered MSG_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MSG_Init ========
++ */
++bool MSG_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!MSG_debugMask.flags);
++ GT_create(&MSG_debugMask, "MG"); /* "MG" for MsG */
++ }
++
++ cRefs++;
++
++ GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/msgobj.h b/drivers/dsp/bridge/pmgr/msgobj.h
+new file mode 100644
+index 0000000..63d025b
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msgobj.h
+@@ -0,0 +1,52 @@
++/*
++ * msgobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library MSG objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef MSGOBJ_
++#define MSGOBJ_
++
++#include <dspbridge/wmd.h>
++
++#include <dspbridge/msgdefs.h>
++
++/*
++ * This struct is the first field in a MSG_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct MSG_MGR_ {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++};
++
++#endif /* MSGOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c
+new file mode 100644
+index 0000000..859043d
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/wcd.c
+@@ -0,0 +1,1647 @@
++/*
++ * wcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== wcd.c ========
++ * Description:
++ * Common WCD functions, also includes the wrapper
++ * functions called directly by the DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ *! Revision History:
++ *! ================
++ *! 29-Apr-2004 hp Call PROC_AutoStart only for DSP device
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 03-Apr-2003 sb Process environment pointer in PROCWRAP_Load
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 30-Jan-2002 ag CMMWRAP_AllocBuf name changed to CMMWRAP_CallocBuf
++ *! 15-Jan-2002 ag Added actual bufSize param to STRMWRAP_Reclaim[issue].
++ *! 14-Dec-2001 rr ARGS_NODE_CONNECT maps the pAttr.
++ *! 03-Oct-2001 rr ARGS_NODE_ALLOCMSGBUF/FREEMSGBUF maps the pAttr.
++ *! 10-Sep-2001 ag Added CMD_CMM_GETHANDLE.
++ *! 23-Apr-2001 jeh Pass pStatus to NODE_Terminate.
++ *! 11-Apr-2001 jeh STRMWRAP_Reclaim embedded pointer is mapped and unmapped.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 06-Dec-2000 jeh WRAP_MAP2CALLER pointers in RegisterNotify calls.
++ *! 05-Dec-2000 ag: Removed MAP2CALLER in NODEWRAP_FreeMsgBuf().
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data().
++ *! 20-Nov-2000 jeh Added MSG_Init()/MSG_Exit(), IO_Init()/IO_Exit().
++ *! WRAP pointers to handles for PROC_Attach, NODE_Allocate.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 12-Oct-2000 ag: Added user CMM wrappers.
++ *! 05-Oct-2000 rr: WcdInitComplete2 will fail even if one BRD or PROC
++ *! AutoStart fails.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 13-Sep-2000 jeh Pass ARGS_NODE_CONNECT.pAttrs to NODE_Connect().
++ *! 11-Aug-2000 rr: Part of node enabled.
++ *! 31-Jul-2000 rr: UTIL_Wrap and MEM_Wrap added to RM.
++ *! 27-Jul-2000 rr: PROCWRAP, NODEWRAP and STRMWRAP implemented.
++ *! STRM and some NODE Wrappers are not implemented.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 08-Feb-2000 rr File name changed to wcd.c
++ *! 03-Feb-2000 rr: Module initialization are done by SERVICES init. GT Class
++ *! changes for module init/exit fxns.
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-1999 sg: Changed ARGS_CHNL_GETMODE field name from pdwMode to pMode.
++ *! 17-Jan-2000 rr: BRD_GetStatus does WRAP_MAP2CALLER for state.
++ *! 14-Dec-1999 ag: Removed _MAP2CALLER in CHNL_GetMgr().
++ *! 13-Dec-1999 rr: BRDWRAP_GetSymbol, BRDWRAP_GetTrace uses WRAP_MAP2CALLER
++ *! macros.BRDWRAP_Load maps and unmaps embedded pointers.
++ *! 10-Dec-1999 ag: User CHNL bufs mapped in _AddIOReq & _GetIOCompletion.
++ *! 09-Dec-1999 rr: BRDWRAP_Open and CHNLWRAP_GetMgr does not map
++ *! pointer as there was a change in config.c
++ *! 06-Dec-1999 rr: BRD_Read and Write Maps the buf pointers.
++ *! 03-Dec-1999 rr: CHNLWRAP_GetMgr and BRDWRAP_Open maps hDevNode pointer.
++ *! WCD_InitComplete2 Included for BRD_AutoStart.
++ *! 16-Nov-1999 ag: Map buf to process in CHNLWRAP_AllocBuffer().
++ *! CHNL_GetMgr() Mapping Fix.
++ *! 10-Nov-1999 ag: Removed unnecessary calls to WRAP_MAP2CALLER.
++ *! 08-Nov-1999 kc: Added MEMRY & enabled BRD_IOCtl for tests.
++ *! 29-Oct-1999 ag: Added CHNL.
++ *! 29-Oct-1999 kc: Added trace statements; added ptr mapping; updated
++ *! use of UTIL module API.
++ *! 29-Oct-1999 rr: Wrapper functions does the Mapping of the Pointers.
++ *! in WinCE all the explicit pointers will be converted
++ *! by the OS during interprocess but not the embedded pointers.
++ *! 16-Oct-1999 kc: Code review cleanup.
++ *! 07-Oct-1999 kc: Added UTILWRAP_TestDll() to run PM test harness. See
++ *! /src/doc/pmtest.doc for more detail.
++ *! 09-Sep-1999 rr: After exactly two years(!). Adopted for WinCE. GT Enabled.
++ *! 09-Sep-1997 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/services.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/chnl.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/disp.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/rmm.h>
++
++
++/* ----------------------------------- Others */
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dbdcd.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MAX_TRACEBUFLEN 255
++#define MAX_LOADARGS 16
++#define MAX_NODES 64
++#define MAX_STREAMS 16
++#define MAX_BUFS 64
++
++/* Following two macros should ideally have do{}while(0) */
++
++#define cp_fm_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(src == NULL) || \
++ unlikely(copy_from_user(dest, src, elements * sizeof(*(dest))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_from_user failed, src=0x%x\n", src); \
++ status = DSP_EPOINTER ; \
++ } \
++ }
++
++#define cp_to_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(dest == NULL) || \
++ unlikely(copy_to_user(dest, src, elements * sizeof(*(src))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_to_user failed, dest=0x%x\n", dest); \
++ status = DSP_EPOINTER ;\
++ } \
++ }
++
++/* Device IOCtl function pointer */
++struct WCD_Cmd {
++ u32(*fxn)(union Trapped_Args *args);
++ u32 dwIndex;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask WCD_debugMask = { NULL, NULL }; /* Core VxD Mask */
++#endif
++static u32 WCD_cRefs;
++
++/*
++ * Function table.
++ * The order of these functions MUST be the same as the order of the command
++ * numbers defined in wcdioctl.h This is how an IOCTL number in user mode
++ * turns into a function call in kernel mode.
++ */
++static struct WCD_Cmd WCD_cmdTable[] = {
++ /* MGR module */
++ {MGRWRAP_EnumNode_Info, CMD_MGR_ENUMNODE_INFO_OFFSET},
++ {MGRWRAP_EnumProc_Info, CMD_MGR_ENUMPROC_INFO_OFFSET},
++ {MGRWRAP_RegisterObject, CMD_MGR_REGISTEROBJECT_OFFSET},
++ {MGRWRAP_UnregisterObject, CMD_MGR_UNREGISTEROBJECT_OFFSET},
++ {MGRWRAP_WaitForBridgeEvents, CMD_MGR_WAIT_OFFSET},
++#ifndef RES_CLEANUP_DISABLE
++ {MGRWRAP_GetProcessResourcesInfo, CMD_MGR_RESOUCES_OFFSET},
++#endif
++ /* PROC Module */
++ {PROCWRAP_Attach, CMD_PROC_ATTACH_OFFSET},
++ {PROCWRAP_Ctrl, CMD_PROC_CTRL_OFFSET},
++ {PROCWRAP_Detach, CMD_PROC_DETACH_OFFSET},
++ {PROCWRAP_EnumNode_Info, CMD_PROC_ENUMNODE_OFFSET},
++ {PROCWRAP_EnumResources, CMD_PROC_ENUMRESOURCES_OFFSET},
++ {PROCWRAP_GetState, CMD_PROC_GETSTATE_OFFSET},
++ {PROCWRAP_GetTrace, CMD_PROC_GETTRACE_OFFSET},
++ {PROCWRAP_Load, CMD_PROC_LOAD_OFFSET},
++ {PROCWRAP_RegisterNotify, CMD_PROC_REGISTERNOTIFY_OFFSET},
++ {PROCWRAP_Start, CMD_PROC_START_OFFSET},
++ {PROCWRAP_ReserveMemory, CMD_PROC_RSVMEM_OFFSET},
++ {PROCWRAP_UnReserveMemory, CMD_PROC_UNRSVMEM_OFFSET},
++ {PROCWRAP_Map, CMD_PROC_MAPMEM_OFFSET},
++ {PROCWRAP_UnMap, CMD_PROC_UNMAPMEM_OFFSET},
++ {PROCWRAP_FlushMemory, CMD_PROC_FLUSHMEMORY_OFFSET},
++ {PROCWRAP_Stop, CMD_PROC_STOP_OFFSET},
++ {PROCWRAP_InvalidateMemory, CMD_PROC_INVALIDATEMEMORY_OFFSET},
++ /* NODE Module */
++ {NODEWRAP_Allocate, CMD_NODE_ALLOCATE_OFFSET},
++ {NODEWRAP_AllocMsgBuf, CMD_NODE_ALLOCMSGBUF_OFFSET},
++ {NODEWRAP_ChangePriority, CMD_NODE_CHANGEPRIORITY_OFFSET},
++ {NODEWRAP_Connect, CMD_NODE_CONNECT_OFFSET},
++ {NODEWRAP_Create, CMD_NODE_CREATE_OFFSET},
++ {NODEWRAP_Delete, CMD_NODE_DELETE_OFFSET},
++ {NODEWRAP_FreeMsgBuf, CMD_NODE_FREEMSGBUF_OFFSET},
++ {NODEWRAP_GetAttr, CMD_NODE_GETATTR_OFFSET},
++ {NODEWRAP_GetMessage, CMD_NODE_GETMESSAGE_OFFSET},
++ {NODEWRAP_Pause, CMD_NODE_PAUSE_OFFSET},
++ {NODEWRAP_PutMessage, CMD_NODE_PUTMESSAGE_OFFSET},
++ {NODEWRAP_RegisterNotify, CMD_NODE_REGISTERNOTIFY_OFFSET},
++ {NODEWRAP_Run, CMD_NODE_RUN_OFFSET},
++ {NODEWRAP_Terminate, CMD_NODE_TERMINATE_OFFSET},
++ {NODEWRAP_GetUUIDProps, CMD_NODE_GETUUIDPROPS_OFFSET},
++ /* STRM wrapper functions */
++ {STRMWRAP_AllocateBuffer, CMD_STRM_ALLOCATEBUFFER_OFFSET},
++ {STRMWRAP_Close, CMD_STRM_CLOSE_OFFSET},
++ {STRMWRAP_FreeBuffer, CMD_STRM_FREEBUFFER_OFFSET},
++ {STRMWRAP_GetEventHandle, CMD_STRM_GETEVENTHANDLE_OFFSET},
++ {STRMWRAP_GetInfo, CMD_STRM_GETINFO_OFFSET},
++ {STRMWRAP_Idle, CMD_STRM_IDLE_OFFSET},
++ {STRMWRAP_Issue, CMD_STRM_ISSUE_OFFSET},
++ {STRMWRAP_Open, CMD_STRM_OPEN_OFFSET},
++ {STRMWRAP_Reclaim, CMD_STRM_RECLAIM_OFFSET},
++ {STRMWRAP_RegisterNotify, CMD_STRM_REGISTERNOTIFY_OFFSET},
++ {STRMWRAP_Select, CMD_STRM_SELECT_OFFSET},
++ /* CMM module */
++ {CMMWRAP_CallocBuf, CMD_CMM_ALLOCBUF_OFFSET},
++ {CMMWRAP_FreeBuf, CMD_CMM_FREEBUF_OFFSET},
++ {CMMWRAP_GetHandle, CMD_CMM_GETHANDLE_OFFSET},
++ {CMMWRAP_GetInfo, CMD_CMM_GETINFO_OFFSET}
++};
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ */
++inline DSP_STATUS WCD_CallDevIOCtl(u32 cmd, union Trapped_Args *args,
++ u32 *pResult)
++{
++ if ((cmd < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)))) {
++ /* make the fxn call via the cmd table */
++ *pResult = (*WCD_cmdTable[cmd].fxn) (args);
++ return DSP_SOK;
++ } else {
++ return DSP_EINVALIDARG;
++ }
++}
++
++/*
++ * ======== WCD_Exit ========
++ */
++void WCD_Exit(void)
++{
++ DBC_Require(WCD_cRefs > 0);
++ WCD_cRefs--;
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Exit, ref count: 0x%x\n", WCD_cRefs);
++ if (WCD_cRefs == 0) {
++ /* Release all WCD modules initialized in WCD_Init(). */
++ COD_Exit();
++ DEV_Exit();
++ CHNL_Exit();
++ MSG_Exit();
++ IO_Exit();
++ STRM_Exit();
++ NTFY_Exit();
++ DISP_Exit();
++ NODE_Exit();
++ PROC_Exit();
++ MGR_Exit();
++ RMM_exit();
++ DRV_Exit();
++ SERVICES_Exit();
++ }
++ DBC_Ensure(WCD_cRefs >= 0);
++}
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Module initialization is done by SERVICES Init.
++ */
++bool WCD_Init(void)
++{
++ bool fInit = true;
++ bool fDRV, fDEV, fCOD, fSERVICES, fCHNL, fMSG, fIO;
++ bool fMGR, fPROC, fNODE, fDISP, fNTFY, fSTRM, fRMM;
++#ifdef DEBUG
++ /* runtime check of Device IOCtl array. */
++ u32 i;
++ for (i = 1; i < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)); i++)
++ DBC_Assert(WCD_cmdTable[i - 1].dwIndex == i);
++
++#endif
++ if (WCD_cRefs == 0) {
++ /* initialize all SERVICES modules */
++ fSERVICES = SERVICES_Init();
++ /* initialize debugging module */
++ DBC_Assert(!WCD_debugMask.flags);
++ GT_create(&WCD_debugMask, "CD"); /* CD for class driver */
++ /* initialize class driver and other modules */
++ fDRV = DRV_Init();
++ fMGR = MGR_Init();
++ fPROC = PROC_Init();
++ fNODE = NODE_Init();
++ fDISP = DISP_Init();
++ fNTFY = NTFY_Init();
++ fSTRM = STRM_Init();
++ fRMM = RMM_init();
++ fCHNL = CHNL_Init();
++ fMSG = MSG_Init();
++ fIO = IO_Init();
++ fDEV = DEV_Init();
++ fCOD = COD_Init();
++ fInit = fSERVICES && fDRV && fDEV && fCHNL && fCOD &&
++ fMSG && fIO;
++ fInit = fInit && fMGR && fPROC && fRMM;
++ if (!fInit) {
++ if (fSERVICES)
++ SERVICES_Exit();
++
++ if (fDRV)
++ DRV_Exit();
++
++ if (fMGR)
++ MGR_Exit();
++
++ if (fSTRM)
++ STRM_Exit();
++
++ if (fPROC)
++ PROC_Exit();
++
++ if (fNODE)
++ NODE_Exit();
++
++ if (fDISP)
++ DISP_Exit();
++
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fCHNL)
++ CHNL_Exit();
++
++ if (fMSG)
++ MSG_Exit();
++
++ if (fIO)
++ IO_Exit();
++
++ if (fDEV)
++ DEV_Exit();
++
++ if (fCOD)
++ COD_Exit();
++
++ if (fRMM)
++ RMM_exit();
++
++ }
++ }
++ if (fInit)
++ WCD_cRefs++;
++
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Init, ref count: 0x%x\n", WCD_cRefs);
++ return fInit;
++}
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init() or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++DSP_STATUS WCD_InitComplete2(void)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_DEVNODE *DevNode;
++ struct DEV_OBJECT *hDevObject;
++ u32 devType;
++
++ DBC_Require(WCD_cRefs > 0);
++ GT_0trace(WCD_debugMask, GT_ENTER, "Entered WCD_InitComplete\n");
++ /* Walk the list of DevObjects, get each devnode, and attempting to
++ * autostart the board. Note that this requires COF loading, which
++ * requires KFILE. */
++ for (hDevObject = DEV_GetFirst(); hDevObject != NULL;
++ hDevObject = DEV_GetNext(hDevObject)) {
++ if (DSP_FAILED(DEV_GetDevNode(hDevObject, &DevNode)))
++ continue;
++
++ if (DSP_FAILED(DEV_GetDevType(hDevObject, &devType)))
++ continue;
++
++ if ((devType == DSP_UNIT) || (devType == IVA_UNIT)) {
++ if (DSP_FAILED(PROC_AutoStart(DevNode, hDevObject))) {
++ GT_0trace(WCD_debugMask, GT_1CLASS,
++ "WCD_InitComplete2 Failed\n");
++ status = DSP_EFAIL;
++ /* break; */
++ }
++ } else
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Ignoring PROC_AutoStart "
++ "for Device Type = 0x%x \n", devType);
++ } /* End For Loop */
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Exiting WCD_InitComplete status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumNode_Info ========
++ */
++u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ u8 *pNDBProps;
++ u32 uNumNodes;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGR_EnumNodeInfo: entered args:\n0x%x"
++ " uNode: 0x%x\tpNDBProps: 0x%x\tuNDBPropsSize: "
++ "0x%x\tpuNumNodes\n", args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ args->ARGS_MGR_ENUMNODE_INFO.pNDBProps,
++ args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize,
++ args->ARGS_MGR_ENUMNODE_INFO.puNumNodes);
++ pNDBProps = MEM_Alloc(size, MEM_NONPAGED);
++ if (pNDBProps == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumNodeInfo(args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ (struct DSP_NDBPROPS *)pNDBProps,
++ size, &uNumNodes);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.pNDBProps, pNDBProps, status,
++ size);
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.puNumNodes, &uNumNodes, status,
++ 1);
++ if (pNDBProps)
++ MEM_Free(pNDBProps);
++
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumProc_Info ========
++ */
++u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args)
++{
++ u8 *pProcessorInfo;
++ u32 uNumProcs;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_EnumProc_Info: entered args:\n"
++ "0x%x uProcessor: 0x%x\tpProcessorInfo: 0x%x\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs \n",
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo,
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize,
++ args->ARGS_MGR_ENUMPROC_INFO.puNumProcs);
++ pProcessorInfo = MEM_Alloc(size, MEM_NONPAGED);
++ if (pProcessorInfo == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumProcessorInfo(args->
++ ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ (struct DSP_PROCESSORINFO *)pProcessorInfo,
++ size, &uNumProcs);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo, pProcessorInfo,
++ status, size);
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.puNumProcs, &uNumProcs,
++ status, 1);
++ if (pProcessorInfo)
++ MEM_Free(pProcessorInfo);
++
++ return status;
++}
++
++#define WRAP_MAP2CALLER(x) x
++/*
++ * ======== MGRWRAP_RegisterObject ========
++ */
++u32 MGRWRAP_RegisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_RegisterObject: entered pg2hMsg "
++ "0x%x\n", args->ARGS_MGR_REGISTEROBJECT.pUuid);
++ retVal = DCD_RegisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_REGISTEROBJECT.pUuid),
++ args->ARGS_MGR_REGISTEROBJECT.objType,
++ WRAP_MAP2CALLER(args->ARGS_MGR_REGISTEROBJECT.pszPathName));
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_UnregisterObject ========
++ */
++u32 MGRWRAP_UnregisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_UnregisterObject: entered pg2hMsg"
++ " 0x%x\n", args->ARGS_MGR_UNREGISTEROBJECT.pUuid);
++ retVal = DCD_UnregisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_UNREGISTEROBJECT.pUuid),
++ args->ARGS_MGR_UNREGISTEROBJECT.objType);
++
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_WaitForBridgeEvents ========
++ */
++u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS];
++ struct DSP_NOTIFICATION notifications[MAX_EVENTS];
++ u32 uIndex, i;
++ u32 uCount = args->ARGS_MGR_WAIT.uCount;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_WaitForBridgeEvents: entered\n");
++
++ if (uCount > MAX_EVENTS)
++ status = DSP_EINVALIDARG;
++
++ /* get the array of pointers to user structures */
++ cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications,
++ status, uCount);
++ /* get the events */
++ for (i = 0; i < uCount; i++) {
++ cp_fm_usr(&notifications[i], aNotifications[i], status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the array of pointers to kernel structures*/
++ aNotifications[i] = &notifications[i];
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_WaitForBridgeEvents(aNotifications, uCount,
++ &uIndex, args->ARGS_MGR_WAIT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1);
++ return status;
++}
++
++
++#ifndef RES_CLEANUP_DISABLE
++/*
++ * ======== MGRWRAP_GetProcessResourceInfo ========
++ */
++u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uSize = 0;
++ u8 *pBuf = MEM_Alloc(8092, MEM_NONPAGED);
++ status = DRV_ProcDisplayResInfo(pBuf, &uSize);
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_GetProcessResourcesInfo:uSize=%d :\n", uSize);
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, uSize);
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "123MGRWRAP_GetProcessResourcesInfo:**************\n");
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "456MGRWRAP_GetProcessResourcesInfo:**************\n");
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pSize, &uSize, status, 1);
++ MEM_Free(pBuf);
++ return status;
++}
++#endif
++
++
++/*
++ * ======== PROCWRAP_Attach ========
++ */
++u32 PROCWRAP_Attach(union Trapped_Args *args)
++{
++ DSP_HPROCESSOR processor;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_PROCESSORATTRIN attrIn, *pAttrIn = NULL;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Attach: entered args:\n" "0x%x"
++ " uProcessor: 0x%x\tpAttrIn: 0x%x\tphProcessor \n",
++ args->ARGS_PROC_ATTACH.uProcessor,
++ args->ARGS_PROC_ATTACH.pAttrIn,
++ args->ARGS_PROC_ATTACH.phProcessor);
++ /* Optional argument */
++ if (args->ARGS_PROC_ATTACH.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_PROC_ATTACH.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ status = PROC_Attach(args->ARGS_PROC_ATTACH.uProcessor, pAttrIn,
++ &processor);
++ cp_to_usr(args->ARGS_PROC_ATTACH.phProcessor, &processor, status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Ctrl ========
++ */
++u32 PROCWRAP_Ctrl(union Trapped_Args *args)
++{
++ u32 cbDataSize, __user *pSize = (u32 __user *)
++ args->ARGS_PROC_CTRL.pArgs;
++ u8 *pArgs = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Ctrl: entered args:\n 0x%x"
++ " uProcessor: 0x%x\tdwCmd: 0x%x\tpArgs \n",
++ args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ args->ARGS_PROC_CTRL.pArgs);
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_PROC_CTRL.pArgs, status,
++ cbDataSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Ctrl(args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ (struct DSP_CBDATA *)pArgs);
++ }
++
++ /* cp_to_usr(args->ARGS_PROC_CTRL.pArgs, pArgs, status, 1);*/
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Detach ========
++ */
++u32 PROCWRAP_Detach(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Detach: entered args\n0x%x "
++ "hProceesor \n", args->ARGS_PROC_DETACH.hProcessor);
++ retVal = PROC_Detach(args->ARGS_PROC_DETACH.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_EnumNode_Info ========
++ */
++u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_HNODE aNodeTab[MAX_NODES];
++ u32 uNumNodes;
++ u32 uAllocated;
++
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumNode_Info:entered args:\n0x"
++ "%xhProcessor:0x%x\taNodeTab:0x%x\tuNodeTabSize:"
++ "%0x%x\tpuNumNodes%\n0x%x puAllocated: \n",
++ args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ args->ARGS_PROC_ENUMNODE_INFO.aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ args->ARGS_PROC_ENUMNODE_INFO.puNumNodes,
++ args->ARGS_PROC_ENUMNODE_INFO.puAllocated);
++ DBC_Require(args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize <= MAX_NODES);
++ status = PROC_EnumNodes(args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ &uNumNodes, &uAllocated);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.aNodeTab, aNodeTab, status,
++ uNumNodes);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puNumNodes, &uNumNodes,
++ status, 1);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puAllocated, &uAllocated,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_FlushMemory ========
++ */
++u32 PROCWRAP_FlushMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_FlushMemory: entered\n");
++
++ status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
++ args->ARGS_PROC_FLUSHMEMORY.pMpuAddr,
++ args->ARGS_PROC_FLUSHMEMORY.ulSize,
++ args->ARGS_PROC_FLUSHMEMORY.ulFlags);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_InvalidateMemory ========
++ */
++u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_InvalidateMemory:entered\n");
++
++ status = PROC_InvalidateMemory(
++ args->ARGS_PROC_INVALIDATEMEMORY.hProcessor,
++ args->ARGS_PROC_INVALIDATEMEMORY.pMpuAddr,
++ args->ARGS_PROC_INVALIDATEMEMORY.ulSize);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_EnumResources ========
++ */
++u32 PROCWRAP_EnumResources(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumResources: entered args:\n"
++ "0x%x hProcessor: 0x%x\tuResourceMask: 0x%x\tpResourceInfo"
++ " 0x%x\tuResourceInfoSixe \n",
++ args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ args->ARGS_PROC_ENUMRESOURCES.pResourceInfo,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceInfoSize);
++ retVal = PROC_GetResourceInfo(args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ WRAP_MAP2CALLER(args->ARGS_PROC_ENUMRESOURCES.
++ pResourceInfo), args->ARGS_PROC_ENUMRESOURCES.
++ uResourceInfoSize);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_GetState ========
++ */
++u32 PROCWRAP_GetState(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_PROCESSORSTATE procStatus;
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetState: entered\n");
++ status = PROC_GetState(args->ARGS_PROC_GETSTATE.hProcessor, &procStatus,
++ args->ARGS_PROC_GETSTATE.uStateInfoSize);
++ cp_to_usr(args->ARGS_PROC_GETSTATE.pProcStatus, &procStatus, status, 1);
++ return status;
++
++}
++
++/*
++ * ======== PROCWRAP_GetTrace ========
++ */
++u32 PROCWRAP_GetTrace(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 *pBuf;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n");
++
++ DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN);
++
++ pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED);
++ if (pBuf != NULL) {
++ status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor,
++ pBuf, args->ARGS_PROC_GETTRACE.uMaxSize);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status,
++ args->ARGS_PROC_GETTRACE.uMaxSize);
++ if (pBuf)
++ MEM_Free(pBuf);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Load ========
++ */
++u32 PROCWRAP_Load(union Trapped_Args *args)
++{
++ s32 i, len;
++ DSP_STATUS status = DSP_SOK;
++ char *temp;
++ s32 argc = args->ARGS_PROC_LOAD.iArgc;
++ u8 **argv, **envp = NULL;
++
++
++ DBC_Require(argc > 0);
++ DBC_Require(argc <= MAX_LOADARGS);
++
++ argv = MEM_Alloc(argc * sizeof(u8 *), MEM_NONPAGED);
++ if (argv == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(argv, args->ARGS_PROC_LOAD.aArgv, status, argc);
++ for (i = 0; DSP_SUCCEEDED(status) && (i < argc); i++) {
++ if (argv[i] != NULL) {
++ /* User space pointer to argument */
++ temp = (char *) argv[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ argv[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (argv[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(argv[i], temp, status, len);
++ }
++ }
++ /* TODO: validate this */
++ if (args->ARGS_PROC_LOAD.aEnvp != NULL) {
++ /* number of elements in the envp array including NULL */
++ len = 0;
++ do {
++ len++;
++ get_user(temp, args->ARGS_PROC_LOAD.aEnvp);
++ } while (temp);
++ envp = MEM_Alloc(len * sizeof(u8 *), MEM_NONPAGED);
++ if (envp == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(envp, args->ARGS_PROC_LOAD.aEnvp, status, len);
++ for (i = 0; DSP_SUCCEEDED(status) && (envp[i] != NULL); i++) {
++ /* User space pointer to argument */
++ temp = (char *)envp[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ envp[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (envp[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(envp[i], temp, status, len);
++ }
++ }
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Load, hProcessor: 0x%x\n\tiArgc:"
++ "0x%x\n\taArgv: 0x%x\n\taArgv[0]: %s\n\taEnvp: 0x%0x\n",
++ args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc, args->ARGS_PROC_LOAD.aArgv,
++ argv[0], args->ARGS_PROC_LOAD.aEnvp);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Load(args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc,
++ (CONST char **)argv, (CONST char **)envp);
++ }
++ if (envp != NULL) {
++ i = 0;
++ while (envp[i] != NULL)
++ MEM_Free(envp[i++]);
++
++ MEM_Free(envp);
++ }
++ if (argv != NULL) {
++ for (i = 0; i < argc; i++) {
++ if (argv[i] != NULL)
++ MEM_Free(argv[i]);
++
++ }
++ MEM_Free(argv);
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Map ========
++ */
++u32 PROCWRAP_Map(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pMapAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Map: entered\n");
++ status = PROC_Map(args->ARGS_PROC_MAPMEM.hProcessor,
++ args->ARGS_PROC_MAPMEM.pMpuAddr,
++ args->ARGS_PROC_MAPMEM.ulSize,
++ args->ARGS_PROC_MAPMEM.pReqAddr, &pMapAddr,
++ args->ARGS_PROC_MAPMEM.ulMapAttr);
++ if (DSP_SUCCEEDED(status)) {
++ if (put_user(pMapAddr, args->ARGS_PROC_MAPMEM.ppMapAddr))
++ status = DSP_EINVALIDARG;
++
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_RegisterNotify ========
++ */
++u32 PROCWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = PROC_RegisterNotify(args->ARGS_PROC_REGISTER_NOTIFY.hProcessor,
++ args->ARGS_PROC_REGISTER_NOTIFY.uEventMask,
++ args->ARGS_PROC_REGISTER_NOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_PROC_REGISTER_NOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_ReserveMemory ========
++ */
++u32 PROCWRAP_ReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pRsvAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
++ status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
++ args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
++ if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr))
++ status = DSP_EINVALIDARG;
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Start ========
++ */
++u32 PROCWRAP_Start(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Start: entered\n");
++ retVal = PROC_Start(args->ARGS_PROC_START.hProcessor);
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_UnMap ========
++ */
++u32 PROCWRAP_UnMap(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_UnMap: entered\n");
++ status = PROC_UnMap(args->ARGS_PROC_UNMAPMEM.hProcessor,
++ args->ARGS_PROC_UNMAPMEM.pMapAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_UnReserveMemory ========
++ */
++u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_UnReserveMemory: entered\n");
++ status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
++ args->ARGS_PROC_UNRSVMEM.pRsvAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Stop ========
++ */
++u32 PROCWRAP_Stop(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Stop: entered\n");
++ retVal = PROC_Stop(args->ARGS_PROC_STOP.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Allocate ========
++ */
++u32 NODEWRAP_Allocate(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs;
++ u8 *pArgs = NULL;
++ struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL;
++ struct NODE_OBJECT *hNode;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status,
++ cbDataSize);
++ }
++ cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1);
++ /* Optional argument */
++ if (args->ARGS_NODE_ALLOCATE.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor,
++ &nodeId, (struct DSP_CBDATA *)pArgs,
++ pAttrIn, &hNode);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1);
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_AllocMsgBuf ========
++ */
++u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ u8 *pBuffer = NULL;
++
++ if (args->ARGS_NODE_ALLOCMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_ALLOCMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ /* IN OUT argument */
++ cp_fm_usr(&pBuffer, args->ARGS_NODE_ALLOCMSGBUF.pBuffer, status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_AllocMsgBuf(args->ARGS_NODE_ALLOCMSGBUF.hNode,
++ args->ARGS_NODE_ALLOCMSGBUF.uSize,
++ pAttr, &pBuffer);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCMSGBUF.pBuffer, &pBuffer, status, 1)
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_ChangePriority ========
++ */
++u32 NODEWRAP_ChangePriority(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_ChangePriority: entered\n");
++ retVal = NODE_ChangePriority(args->ARGS_NODE_CHANGEPRIORITY.hNode,
++ args->ARGS_NODE_CHANGEPRIORITY.iPriority);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Connect ========
++ */
++u32 NODEWRAP_Connect(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_STRMATTR attrs;
++ struct DSP_STRMATTR *pAttrs = NULL;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam;
++ u8 *pArgs = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status,
++ cbDataSize);
++ }
++ if (args->ARGS_NODE_CONNECT.pAttrs) { /* Optional argument */
++ cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrs = &attrs;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode,
++ args->ARGS_NODE_CONNECT.uStream,
++ args->ARGS_NODE_CONNECT.hOtherNode,
++ args->ARGS_NODE_CONNECT.uOtherStream,
++ pAttrs, (struct DSP_CBDATA *)pArgs);
++ }
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Create ========
++ */
++u32 NODEWRAP_Create(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Create: entered\n");
++ retVal = NODE_Create(args->ARGS_NODE_CREATE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Delete ========
++ */
++u32 NODEWRAP_Delete(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Delete: entered\n");
++ retVal = NODE_Delete(args->ARGS_NODE_DELETE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_FreeMsgBuf ========
++ */
++u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ if (args->ARGS_NODE_FREEMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_FREEMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_FreeMsgBuf(args->ARGS_NODE_FREEMSGBUF.hNode,
++ args->ARGS_NODE_FREEMSGBUF.pBuffer,
++ pAttr);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetAttr ========
++ */
++u32 NODEWRAP_GetAttr(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEATTR attr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetAttr: entered\n");
++
++ status = NODE_GetAttr(args->ARGS_NODE_GETATTR.hNode, &attr,
++ args->ARGS_NODE_GETATTR.uAttrSize);
++ cp_to_usr(args->ARGS_NODE_GETATTR.pAttr, &attr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetMessage ========
++ */
++u32 NODEWRAP_GetMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetMessage: entered\n");
++
++ status = NODE_GetMessage(args->ARGS_NODE_GETMESSAGE.hNode, &msg,
++ args->ARGS_NODE_GETMESSAGE.uTimeout);
++
++ cp_to_usr(args->ARGS_NODE_GETMESSAGE.pMessage, &msg, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Pause ========
++ */
++u32 NODEWRAP_Pause(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Pause: entered\n");
++ retVal = NODE_Pause(args->ARGS_NODE_PAUSE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_PutMessage ========
++ */
++u32 NODEWRAP_PutMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_PutMessage: entered\n");
++
++ cp_fm_usr(&msg, args->ARGS_NODE_PUTMESSAGE.pMessage, status, 1);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_PutMessage(args->ARGS_NODE_PUTMESSAGE.hNode, &msg,
++ args->ARGS_NODE_PUTMESSAGE.uTimeout);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_RegisterNotify ========
++ */
++u32 NODEWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = NODE_RegisterNotify(args->ARGS_NODE_REGISTERNOTIFY.hNode,
++ args->ARGS_NODE_REGISTERNOTIFY.uEventMask,
++ args->ARGS_NODE_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_NODE_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Run ========
++ */
++u32 NODEWRAP_Run(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Run: entered\n");
++ retVal = NODE_Run(args->ARGS_NODE_RUN.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Terminate ========
++ */
++u32 NODEWRAP_Terminate(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_STATUS tempstatus;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Terminate: entered\n");
++
++ status = NODE_Terminate(args->ARGS_NODE_TERMINATE.hNode, &tempstatus);
++
++ cp_to_usr(args->ARGS_NODE_TERMINATE.pStatus, &tempstatus, status, 1);
++
++ return status;
++}
++
++
++/*
++ * ======== NODEWRAP_GetUUIDProps ========
++ */
++u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ struct DSP_NDBPROPS *pnodeProps = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_GetUUIDPropste: entered\n");
++
++
++ cp_fm_usr(&nodeId, args->ARGS_NODE_GETUUIDPROPS.pNodeID, status, 1);
++ pnodeProps = MEM_Alloc(sizeof(struct DSP_NDBPROPS), MEM_NONPAGED);
++ if (pnodeProps != NULL) {
++ status = NODE_GetUUIDProps(args->
++ ARGS_NODE_GETUUIDPROPS.hProcessor,
++ &nodeId, pnodeProps);
++ cp_to_usr(args->ARGS_NODE_GETUUIDPROPS.pNodeProps, pnodeProps,
++ status, 1);
++ } else
++ status = DSP_EMEMORY;
++ if (pnodeProps)
++ MEM_Free(pnodeProps);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_AllocateBuffer ========
++ */
++u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_ALLOCATEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ status = STRM_AllocateBuffer(args->ARGS_STRM_ALLOCATEBUFFER.hStream,
++ args->ARGS_STRM_ALLOCATEBUFFER.uSize,
++ apBuffer, uNumBufs);
++ cp_to_usr(args->ARGS_STRM_ALLOCATEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Close ========
++ */
++u32 STRMWRAP_Close(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Close(args->ARGS_STRM_CLOSE.hStream);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_FreeBuffer ========
++ */
++u32 STRMWRAP_FreeBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_FREEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ cp_fm_usr(apBuffer, args->ARGS_STRM_FREEBUFFER.apBuffer, status,
++ uNumBufs);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_FreeBuffer(args->ARGS_STRM_FREEBUFFER.hStream,
++ apBuffer, uNumBufs);
++ }
++ cp_to_usr(args->ARGS_STRM_FREEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_GetEventHandle ========
++ */
++u32 STRMWRAP_GetEventHandle(union Trapped_Args *args)
++{
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== STRMWRAP_GetInfo ========
++ */
++u32 STRMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_INFO strmInfo;
++ struct DSP_STREAMINFO user;
++ struct DSP_STREAMINFO *temp;
++
++ cp_fm_usr(&strmInfo, args->ARGS_STRM_GETINFO.pStreamInfo, status, 1);
++ temp = strmInfo.pUser;
++
++ strmInfo.pUser = &user;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_GetInfo(args->ARGS_STRM_GETINFO.hStream,
++ &strmInfo, args->ARGS_STRM_GETINFO.uStreamInfoSize);
++ }
++ cp_to_usr(temp, strmInfo.pUser, status, 1);
++ strmInfo.pUser = temp;
++ cp_to_usr(args->ARGS_STRM_GETINFO.pStreamInfo, &strmInfo, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Idle ========
++ */
++u32 STRMWRAP_Idle(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Idle(args->ARGS_STRM_IDLE.hStream,
++ args->ARGS_STRM_IDLE.bFlush);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Issue ========
++ */
++u32 STRMWRAP_Issue(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Issue(args->ARGS_STRM_ISSUE.hStream,
++ args->ARGS_STRM_ISSUE.pBuffer,
++ args->ARGS_STRM_ISSUE.dwBytes,
++ args->ARGS_STRM_ISSUE.dwBufSize,
++ args->ARGS_STRM_ISSUE.dwArg);
++
++ /* This is a user space pointer */
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Open ========
++ */
++u32 STRMWRAP_Open(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_ATTR attr;
++ struct STRM_OBJECT *pStrm;
++ struct DSP_STREAMATTRIN strmAttrIn;
++
++ cp_fm_usr(&attr, args->ARGS_STRM_OPEN.pAttrIn, status, 1);
++
++ if (attr.pStreamAttrIn != NULL) { /* Optional argument */
++ cp_fm_usr(&strmAttrIn, attr.pStreamAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ attr.pStreamAttrIn = &strmAttrIn;
++
++ }
++ status = STRM_Open(args->ARGS_STRM_OPEN.hNode,
++ args->ARGS_STRM_OPEN.uDirection,
++ args->ARGS_STRM_OPEN.uIndex, &attr, &pStrm);
++ cp_to_usr(args->ARGS_STRM_OPEN.phStream, &pStrm, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Reclaim ========
++ */
++u32 STRMWRAP_Reclaim(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ u32 ulBufSize;
++
++ status = STRM_Reclaim(args->ARGS_STRM_RECLAIM.hStream, &pBufPtr,
++ &ulBytes, &ulBufSize, &dwArg);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufPtr, &pBufPtr, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBytes, &ulBytes, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pdwArg, &dwArg, status, 1);
++
++ if (args->ARGS_STRM_RECLAIM.pBufSize != NULL) {
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufSize, &ulBufSize,
++ status, 1);
++ }
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_RegisterNotify ========
++ */
++u32 STRMWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = STRM_RegisterNotify(args->ARGS_STRM_REGISTERNOTIFY.hStream,
++ args->ARGS_STRM_REGISTERNOTIFY.uEventMask,
++ args->ARGS_STRM_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_STRM_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Select ========
++ */
++u32 STRMWRAP_Select(union Trapped_Args *args)
++{
++ u32 mask;
++ struct STRM_OBJECT *aStrmTab[MAX_STREAMS];
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(args->ARGS_STRM_SELECT.nStreams <= MAX_STREAMS);
++
++ cp_fm_usr(aStrmTab, args->ARGS_STRM_SELECT.aStreamTab, status,
++ args->ARGS_STRM_SELECT.nStreams);
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_Select(aStrmTab, args->ARGS_STRM_SELECT.nStreams,
++ &mask, args->ARGS_STRM_SELECT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_STRM_SELECT.pMask, &mask, status, 1);
++ return status;
++}
++
++/* CMM */
++
++/*
++ * ======== CMMWRAP_CallocBuf ========
++ */
++u32 CMMWRAP_CallocBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_FreeBuf ========
++ */
++u32 CMMWRAP_FreeBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_GetHandle ========
++ */
++u32 CMMWRAP_GetHandle(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr;
++
++ status = CMM_GetHandle(args->ARGS_CMM_GETHANDLE.hProcessor, &hCmmMgr);
++
++ cp_to_usr(args->ARGS_CMM_GETHANDLE.phCmmMgr, &hCmmMgr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== CMMWRAP_GetInfo ========
++ */
++u32 CMMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_INFO cmmInfo;
++
++ status = CMM_GetInfo(args->ARGS_CMM_GETINFO.hCmmMgr, &cmmInfo);
++
++ cp_to_usr(args->ARGS_CMM_GETINFO.pCmmInfo, &cmmInfo, status, 1);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
+new file mode 100644
+index 0000000..c5ec8f9
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dbdcd.c
+@@ -0,0 +1,1573 @@
++/*
++ * dbdcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcd.c ========
++ * Description:
++ * This file contains the implementation of the DSP/BIOS Bridge
++ * Configuration Database (DCD).
++ *
++ * Notes:
++ * The fxn DCD_GetObjects can apply a callback fxn to each DCD object
++ * that is located in a specified COFF file. At the moment,
++ * DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
++ * DCD_GetObjects.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
++ *! to include phase information
++ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
++ *! libraries
++ *! 26-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
++ *! data. Added DCD_GetLibraryName().
++ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
++ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
++ *! DSP-MMU setup. These are private attributes.
++ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
++ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
++ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
++ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
++ *! GetAttrsFromBuf
++ *! 22-Nov-2000 kc: Replaced sprintf() calls with strncat.
++ *! 09-Nov-2000 kc: Optimized DCD module.
++ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
++ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
++ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
++ *! to replace atoi(), until cdb generation can output in
++ *! decimal format.
++ *! 26-Jul-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/uuidutil.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbdcd.h>
++
++/* ----------------------------------- Global defines. */
++#define SIGNATURE 0x5f444344 /* "DCD_" (in reverse). */
++
++#define IsValidHandle(h) (((h) != NULL) && (h->dwSignature == SIGNATURE))
++
++#define MAX_INT2CHAR_LENGTH 16 /* Maximum int2char len of 32 bit int. */
++
++/* Name of section containing dependent libraries */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* DCD specific structures. */
++struct DCD_MANAGER {
++ u32 dwSignature; /* Used for object validation. */
++ struct COD_MANAGER *hCodMgr; /* Handle to COD manager object. */
++};
++
++/* Global reference variables. */
++static u32 cRefs;
++static u32 cEnumRefs;
++
++extern struct GT_Mask curTrace;
++
++/* helper function prototypes. */
++static s32 Atoi(char *pszBuf);
++
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj);
++
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
++
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
++
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * Parses the supplied image and resigsters with DCD.
++ */
++
++DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ (void *)pszCoffPath);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * Parses the supplied DSP image and unresiters from DCD.
++ */
++DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ NULL);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoUnregister: invalid DCD manager"
++ " handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * Creates DCD manager.
++ */
++DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager handle */
++ struct DCD_MANAGER *pDcdMgr = NULL; /* DCD Manager pointer */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(phDcdMgr);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
++ phDcdMgr);
++
++ status = COD_Create(&hCodMgr, pszZlDllName, NULL);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* Create a DCD object. */
++ MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
++ if (pDcdMgr != NULL) {
++
++ /* Fill out the object. */
++ pDcdMgr->hCodMgr = hCodMgr;
++
++ /* Return handle to this DCD interface. */
++ *phDcdMgr = pDcdMgr;
++
++ GT_2trace(curTrace, GT_5CLASS,
++ "DCD_CreateManager: pDcdMgr 0x%x, "
++ " hCodMgr 0x%x", pDcdMgr, hCodMgr);
++ } else {
++ status = DSP_EMEMORY;
++
++ /*
++ * If allocation of DcdManager object failed, delete the
++ * COD manager.
++ */
++ COD_Delete(hCodMgr);
++
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: MEM_AllocObject failed\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: COD_Create failed\n");
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
++ (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
++ (status == DSP_EMEMORY)));
++
++ return status;
++}
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * Frees DCD Manager object.
++ */
++DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr;
++ DSP_STATUS status = DSP_EHANDLE;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++
++ /* Delete the COD manager. */
++ COD_Delete(pDcdMgr->hCodMgr);
++
++ /* Deallocate a DCD manager object. */
++ MEM_FreeObject(pDcdMgr);
++
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_DestroyManager: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * Enumerates objects in the DCD.
++ */
++DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szValue[REG_MAXREGPATHLENGTH];
++ char szData[REG_MAXREGPATHLENGTH];
++ u32 dwValueSize;
++ u32 dwDataSize;
++ struct DSP_UUID dspUuid;
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ u32 dwKeyLen = 0;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(cIndex >= 0);
++ DBC_Require(pUuid != NULL);
++
++ GT_3trace(curTrace, GT_ENTER,
++ "DCD_EnumerateObject: cIndex %d, objType %d, "
++ " pUuid 0x%x\n", cIndex, objType, pUuid);
++
++ if ((cIndex != 0) && (cEnumRefs == 0)) {
++ /*
++ * If an enumeration is being performed on an index greater
++ * than zero, then the current cEnumRefs must have been
++ * incremented to greater than zero.
++ */
++ status = DSP_ECHANGEDURINGENUM;
++ } else {
++ /* Enumerate a specific key in the registry by index. */
++ dwValueSize = REG_MAXREGPATHLENGTH;
++ dwDataSize = REG_MAXREGPATHLENGTH;
++
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++
++ /* Create proper REG key; concatenate DCD_REGKEY with
++ * objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++
++ /* This snprintf is guaranteed not to exceed max size of an
++ * integer. */
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
++ objType);
++
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType,
++ strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
++ &dwValueSize, szData,
++ &dwDataSize);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create UUID value using string retrieved from
++ * registry. */
++ UUID_UuidFromString(szValue, &dspUuid);
++
++ *pUuid = dspUuid;
++
++ /* Increment cEnumRefs to update reference count. */
++ cEnumRefs++;
++
++ status = DSP_SOK;
++ } else if (status == REG_E_NOMOREITEMS) {
++ /* At the end of enumeration. Reset cEnumRefs. */
++ cEnumRefs = 0;
++
++ status = DSP_SENUMCOMPLETE;
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(curTrace, GT_6CLASS,
++ "DCD_EnumerateObject: REG_EnumValue"
++ " failed, status = 0x%x\n", status);
++ }
++ }
++
++ DBC_Ensure(pUuid || (status == DSP_EFAIL));
++
++ return status;
++}
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * Discontinue usage of the DCD module.
++ */
++void DCD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ REG_Exit();
++ COD_Exit();
++ MEM_Exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DCD_GetDepLibs ========
++ */
++DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pDepLibUuids != NULL);
++ DBC_Require(pPersistentDepLibs != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
++ pPersistentDepLibs, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ */
++DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pNumPersLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
++ NULL, NULL, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * Retrieves the properties of a node or processor based on the UUID and
++ * object type.
++ */
++DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ struct COD_LIBRARYOBJ *lib = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwBufSize; /* Used by REG functions */
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char *szUuid; /*[MAXUUIDLEN];*/
++ char szRegData[REG_MAXREGPATHLENGTH];
++ char szSectName[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
++ char *pszCoffBuf;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pObjDef != NULL);
++ DBC_Require(pObjUuid != NULL);
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
++ " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
++ objType, pObjDef);
++ szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
++ if (!szUuid)
++ return status = DSP_EMEMORY;
++
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
++ "DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
++
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ /* Retrieve paths from the registry based on struct DSP_UUID */
++ dwBufSize = REG_MAXREGPATHLENGTH;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
++ &dwBufSize);
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EUUID;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "REG_GetValue() failed\n");
++ goto func_end;
++ }
++ /* Open COFF file. */
++ status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_OpenBase() failed\n");
++ goto func_end;
++ }
++ /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
++ DBC_Assert((strlen(szUuid) + 1) < sizeof(szSectName));
++ /* Create section name based on node UUID. A period is
++ * pre-pended to the UUID string to form the section name.
++ * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
++ strncpy(szSectName, ".", 2);
++ strncat(szSectName, szUuid, strlen(szUuid));
++ /* Get section information. */
++ status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDGETSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
++ " COD_GetSection() failed\n");
++ goto func_end;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(szRegData, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ } else {
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ GT_0trace(curTrace, GT_4CLASS,
++ "Skipped Byte swap for IVA !!\n");
++ }
++#else
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compres DSP buffer to conform to PC format. */
++ if (strstr(szRegData, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
++ "COFF buffer by 1 for IVA !!\n");
++ }
++ /* Parse the content of the COFF buffer. */
++ status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDPARSESECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "GetAttrsFromBuf() failed\n");
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_end:
++ if (lib)
++ COD_Close(lib);
++
++ if (szUuid)
++ MEM_Free(szUuid);
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjects ========
++ */
++DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn, void *handle)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ DSP_STATUS status = DSP_SOK;
++ char *pszCoffBuf;
++ char *pszCur;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ char seps[] = ":, ";
++ char *pToken = NULL;
++ struct DSP_UUID dspUuid;
++ s32 cObjectType;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER,
++ "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: invalid DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Open DSP coff file, don't load symbols. */
++ status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: COD_Open() failed\n");
++ goto func_cont;
++ }
++ /* Get DCD_RESIGER_SECTION section information. */
++ status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
++ if (DSP_FAILED(status) || !(ulLen > 0)) {
++ status = DSP_EDCDNOAUTOREGISTER;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: COD_GetSection() "
++ "- no auto register section\n");
++ goto func_cont;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ }
++#else
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compress DSP buffer to conform to PC format. */
++ GT_0trace(curTrace, GT_4CLASS,
++ "Successfully read section !!\n");
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
++ "with 1 word for IVA !!\n");
++ }
++ /* Read from buffer and register object in buffer. */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken, &dspUuid);
++ /* Retrieve object type */
++ pToken = strsep(&pszCur, seps);
++ /* Retrieve object type */
++ cObjectType = Atoi(pToken);
++ /*
++ * Apply registerFxn to the found DCD object.
++ * Possible actions include:
++ *
++ * 1) Register found DCD object.
++ * 2) Unregister found DCD object (when handle == NULL)
++ * 3) Add overlay node.
++ */
++ GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
++ "%d \n", cObjectType);
++ status = registerFxn(&dspUuid, cObjectType, handle);
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "DCD_GetObjects: status 0x%x\n",
++ status);
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: "
++ "registration() failed\n");
++ /* if error occurs, break from while loop. */
++ break;
++ }
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * Retrieves the library name for the given UUID.
++ *
++ */
++DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
++ enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
++{
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN];
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pstrLibName != NULL);
++ DBC_Require(pdwSize != NULL);
++ DBC_Require(IsValidHandle(hDcdMgr));
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
++ " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
++ pstrLibName, pdwSize);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ switch (phase) {
++ case NLDR_CREATE:
++ /* create phase type */
++ sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
++ break;
++ case NLDR_EXECUTE:
++ /* execute phase type */
++ sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
++ break;
++ case NLDR_DELETE:
++ /* delete phase type */
++ sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
++ break;
++ case NLDR_NOPHASE:
++ /* known to be a dependent library */
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ break;
++ default:
++ status = -1;
++ DBC_Assert(false);
++ }
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to find match in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Retrieve path from the registry based on DSP_UUID */
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++ /* If can't find, phases might be registered as generic LIBRARYTYPE */
++ if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
++ if (fPhaseSplit)
++ *fPhaseSplit = false;
++
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * Initialize the DCD module.
++ */
++bool DCD_Init(void)
++{
++ bool fInitMEM;
++ bool fInitREG;
++ bool fInitCOD;
++ bool fInit = true;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++
++ /* Initialize required modules. */
++ fInitMEM = MEM_Init();
++ fInitCOD = COD_Init();
++ fInitREG = REG_Init();
++ if (!fInitMEM || !fInitCOD || !fInitREG) {
++ fInit = false;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
++ /* Exit initialized modules. */
++ if (fInitMEM)
++ MEM_Exit();
++
++ if (fInitCOD)
++ COD_Exit();
++
++ if (fInitREG)
++ REG_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
++
++ return fInit;
++}
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * Registers a node or a processor with the DCD.
++ * If pszPathName == NULL, unregister the specified DCD object.
++ */
++DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN + 1];
++ u32 dwPathSize = 0;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
++ "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * If pszPathName != NULL, perform registration, otherwise,
++ * perform unregistration.
++ */
++ if (pszPathName) {
++ /* Add new reg value (UUID+objType) with COFF path
++ * info. */
++ dwPathSize = strlen(pszPathName) + 1;
++ status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
++ (u8 *)pszPathName, dwPathSize);
++ GT_3trace(curTrace, GT_6CLASS,
++ "REG_SetValue REG_SZ=%d, "
++ "(u8 *)pszPathName=%s, dwPathSize=%d\n",
++ REG_SZ, pszPathName, dwPathSize);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_RegisterObject: REG_SetValue failed!\n");
++ }
++ } else {
++ /* Deregister an existing object. */
++ status = REG_DeleteValue(NULL, szRegKey, szRegKey);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_UnregisterObject: "
++ "REG_DeleteValue failed!\n");
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Because the node database has been updated through a
++ * successful object registration/de-registration operation,
++ * we need to reset the object enumeration counter to allow
++ * current enumerations to reflect this update in the node
++ * database.
++ */
++
++ cEnumRefs = 0;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Call DCD_Register object with pszPathName set to NULL to
++ * perform actual object de-registration.
++ */
++DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "DCD_UnregisterObject: object UUID 0x%x, "
++ "objType %d\n", pUuid, objType);
++
++ /*
++ * When DCD_RegisterObject is called with NULL as pathname,
++ * it indicates an unregister object operation.
++ */
++ status = DCD_RegisterObject(pUuid, objType, NULL);
++
++ return status;
++}
++
++/*
++ **********************************************************************
++ * DCD Helper Functions
++ **********************************************************************
++ */
++
++/*
++ * ======== Atoi ========
++ * Purpose:
++ * This function converts strings in decimal or hex format to integers.
++ */
++static s32 Atoi(char *pszBuf)
++{
++ s32 result = 0;
++ char *pch = pszBuf;
++ char c;
++ char first;
++ s32 base = 10;
++ s32 len;
++
++ while (isspace(*pch))
++ pch++;
++
++ first = *pch;
++ if (first == '-' || first == '+') {
++ pch++;
++ } else {
++ /* Determine if base 10 or base 16 */
++ len = strlen(pch);
++ if (len > 1) {
++ c = pch[1];
++ if ((*pch == '0' && (c == 'x' || c == 'X'))) {
++ base = 16;
++ pch += 2;
++ }
++ c = pch[len - 1];
++ if (c == 'h' || c == 'H')
++ base = 16;
++
++ }
++ }
++
++ while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
++ result *= base;
++ if ('A' <= c && c <= 'F') {
++ c = c - 'A' + 10;
++ } else {
++ if ('a' <= c && c <= 'f')
++ c = c - 'a' + 10;
++ else
++ c -= '0';
++
++ }
++ result += c;
++ ++pch;
++ }
++
++ return result;
++}
++
++/*
++ * ======== GetAttrsFromBuf ========
++ * Purpose:
++ * Parse the content of a buffer filled with DSP-side data and
++ * retrieve an object's attributes from it. IMPORTANT: Assume the
++ * buffer has been converted from DSP format to GPP format.
++ */
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ char seps[] = ", ";
++ char *pszCur;
++ char *token;
++ s32 cLen = 0;
++ u32 i = 0;
++#ifdef _DB_TIOMAP
++ s32 iEntry;
++#endif
++
++ DBC_Require(pszBuf != NULL);
++ DBC_Require(ulBufSize != 0);
++ DBC_Require((objType == DSP_DCDNODETYPE)
++ || (objType == DSP_DCDPROCESSORTYPE));
++ DBC_Require(pGenObj != NULL);
++
++
++ switch (objType) {
++ case DSP_DCDNODETYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ /* u32 cbStruct */
++ pGenObj->objData.nodeObj.ndbProps.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* DSP_UUID uiNodeID */
++ UUID_UuidFromString(token,
++ &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
++ token = strsep(&pszCur, seps);
++
++ /* acName */
++ DBC_Require(token);
++ cLen = strlen(token);
++ if (cLen > DSP_MAXNAMELEN - 1)
++ cLen = DSP_MAXNAMELEN - 1;
++
++ strncpy(pGenObj->objData.nodeObj.ndbProps.acName,
++ token, cLen);
++ pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ /* u32 uNodeType */
++ pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* u32 bCacheOnGPP */
++ pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* DSP_RESOURCEREQMTS dspResourceReqmts */
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uStaticDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uGlobalDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uProgramMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCExecutionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCDeadline = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uAvgExectionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uMinimumPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* s32 iPriority */
++ pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uSysStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSeg */
++ pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uMessageDepth */
++ pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumInputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumOutputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uTimeout */
++ pGenObj->objData.nodeObj.ndbProps.uTimeout =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrCreatePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrExecutePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrDeletePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* Segment id for message buffers */
++ pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* Message notification type */
++ pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrIAlgName */
++ if (token) {
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrIAlgName =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Load type (static, dynamic, or overlay) */
++ if (token) {
++ pGenObj->objData.nodeObj.usLoadType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load data requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load code requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Extract node profiles into node properties */
++ if (token) {
++
++ pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
++ Atoi(token);
++ for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
++ uCountProfiles; i++) {
++ token = strsep(&pszCur, seps);
++ if (token) {
++ /* Heap Size for the node */
++ pGenObj->objData.nodeObj.ndbProps.
++ aProfiles[i].ulHeapSize =
++ Atoi(token);
++ }
++ }
++ }
++ token = strsep(&pszCur, seps);
++ if (token) {
++ pGenObj->objData.nodeObj.ndbProps.uStackSegName =
++ (u32)(token);
++ }
++
++ break;
++
++ case DSP_DCDPROCESSORTYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.cbStruct = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uClockRate = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorID = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
++
++#ifdef _DB_TIOMAP
++ /* Proc object may contain additional(extended) attributes. */
++ /* attr must match proc.hxx */
++ for (iEntry = 0; iEntry < 7; iEntry++) {
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
++ Atoi(token);
++
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
++ Atoi(token);
++ }
++#endif
++
++ break;
++
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CompressBuffer ========
++ * Purpose:
++ * Compress the DSP buffer, if necessary, to conform to PC format.
++ */
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
++{
++ char *p;
++ char ch;
++ char *q;
++
++ p = pszBuf;
++ if (p == NULL)
++ return;
++
++ for (q = pszBuf; q < (pszBuf + ulBufSize);) {
++
++ ch = DspChar2GppChar(q, cCharSize);
++ if (ch == '\\') {
++ q += cCharSize;
++ ch = DspChar2GppChar(q, cCharSize);
++ switch (ch) {
++ case 't':
++ *p = '\t';
++ break;
++
++ case 'n':
++ *p = '\n';
++ break;
++
++ case 'r':
++ *p = '\r';
++ break;
++
++ case '0':
++ *p = '\0';
++ break;
++
++ default:
++ *p = ch;
++ break;
++ }
++ } else {
++ *p = ch;
++ }
++ p++;
++ q += cCharSize;
++ }
++
++ /* NULL out remainder of buffer. */
++ while (p < q)
++ *p++ = '\0';
++
++}
++
++/*
++ * ======== DspChar2GppChar ========
++ * Purpose:
++ * Convert DSP char to host GPP char in a portable manner
++ */
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
++{
++ char ch = '\0';
++ char *chSrc;
++ s32 i;
++
++ for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
++ ch |= *chSrc++;
++
++ return ch;
++}
++
++/*
++ * ======== GetDepLibInfo ========
++ */
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ enum NLDR_PHASE phase)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ char *pszCoffBuf = NULL;
++ char *pszCur;
++ char *pszFileName = NULL;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwDataSize = COD_MAXPATHLENGTH;
++ char seps[] = ", ";
++ char *pToken = NULL;
++ bool fGetUuids = (pDepLibUuids != NULL);
++ u16 nDepLibs = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ /* Initialize to 0 dependent libraries, if only counting number of
++ * dependent libraries */
++ if (!fGetUuids) {
++ *pNumLibs = 0;
++ *pNumPersLibs = 0;
++ }
++
++ /* Allocate a buffer for file name */
++ pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
++ if (pszFileName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Get the name of the library */
++ status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
++ &dwDataSize, phase, NULL);
++ }
++ /* Open the library */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
++ COD_NOLOAD, &lib);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get dependent library section information. */
++ status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
++
++ if (DSP_FAILED(status)) {
++ /* Ok, no dependent libraries */
++ ulLen = 0;
++ status = DSP_SNODEPENDENTLIBS;
++ }
++ }
++
++ if (DSP_FAILED(status) || !(ulLen > 0))
++ goto func_cont;
++
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
++ if (pszCoffBuf == NULL)
++ status = DSP_EMEMORY;
++
++ /* Read section contents. */
++ status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Compress and format DSP buffer to conform to PC format. */
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ /* Read from buffer */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ if (fGetUuids) {
++ if (nDepLibs >= *pNumLibs) {
++ /* Gone beyond the limit */
++ break;
++ } else {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken,
++ &(pDepLibUuids[nDepLibs]));
++ /* Is this library persistent? */
++ pToken = strsep(&pszCur, seps);
++ pPersistentDepLibs[nDepLibs] = Atoi(pToken);
++ nDepLibs++;
++ }
++ } else {
++ /* Advanc to next token */
++ pToken = strsep(&pszCur, seps);
++ if (Atoi(pToken))
++ (*pNumPersLibs)++;
++
++ /* Just counting number of dependent libraries */
++ (*pNumLibs)++;
++ }
++ }
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++ /* Free previously allocated dynamic buffers. */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
+new file mode 100644
+index 0000000..3fbbf01
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/disp.c
+@@ -0,0 +1,916 @@
++/*
++ * disp.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.c ========
++ *
++ * Description:
++ * Node Dispatcher interface. Communicates with Resource Manager Server
++ * (RMS) on DSP. Access to RMS is synchronized in NODE.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodePause
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 16-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 13-Feb-2002 jeh Pass system stack size to RMS.
++ *! 16-Jan-2002 ag Added bufsize param to _ChnlAddIOReq() fxn
++ *! 10-May-2001 jeh Code Review cleanup.
++ *! 26-Sep-2000 jeh Fixed status values in SendMessage().
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dev.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/chnldefs.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/disp.h>
++
++#define DISP_SIGNATURE 0x50534944 /* "PSID" */
++
++/* Size of a reply from RMS */
++#define REPLYSIZE (3 * sizeof(RMS_WORD))
++
++/* Reserved channel offsets for communication with RMS */
++#define CHNLTORMSOFFSET 0
++#define CHNLFROMRMSOFFSET 1
++
++#define CHNLIOREQS 1
++
++#define SwapWord(x) (((u32)(x) >> 16) | ((u32)(x) << 16))
++
++/*
++ * ======== DISP_OBJECT ========
++ */
++struct DISP_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device for this processor */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct CHNL_OBJECT *hChnlToDsp; /* Channel for commands to RMS */
++ struct CHNL_OBJECT *hChnlFromDsp; /* Channel for replies from RMS */
++ u8 *pBuf; /* Buffer for commands, replies */
++ u32 ulBufsize; /* pBuf size in bytes */
++ u32 ulBufsizeRMS; /* pBuf size in RMS words */
++ u32 uCharSize; /* Size of DSP character */
++ u32 uWordSize; /* Size of DSP word */
++ u32 uDataMauSize; /* Size of DSP Data MAU */
++};
++
++static u32 cRefs;
++
++/* Debug msgs: */
++#if GT_TRACE
++static struct GT_Mask DISP_DebugMask = { NULL, NULL };
++#endif
++
++static void DeleteDisp(struct DISP_OBJECT *hDisp);
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord);
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, OUT u32 *pdwArg);
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object.
++ */
++DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs)
++{
++ struct DISP_OBJECT *pDisp;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDispObject != NULL);
++ DBC_Require(pDispAttrs != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
++ "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
++ hDevObject, pDispAttrs);
++
++ *phDispObject = NULL;
++
++ /* Allocate Node Dispatcher object */
++ MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
++ if (pDisp == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: MEM_AllocObject() failed!\n");
++ } else {
++ pDisp->hDevObject = hDevObject;
++ }
++
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ pDisp->pIntfFxns = pIntfFxns;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed to get "
++ "channel manager! status = 0x%x\n", status);
++ }
++ }
++
++ /* check device type and decide if streams or messag'ing is used for
++ * RMS/EDS */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = DEV_GetDevType(hDevObject, &devType);
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
++ "device = 0x%x\n", devType);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if (devType != DSP_UNIT) {
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Unkown device "
++ "type in Device object !! \n");
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDisp->uCharSize = DSPWORDSIZE;
++ pDisp->uWordSize = DSPWORDSIZE;
++ pDisp->uDataMauSize = DSPWORDSIZE;
++ /* Open channels for communicating with the RMS */
++ chnlAttrs.uIOReqs = CHNLIOREQS;
++ chnlAttrs.hEvent = NULL;
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
++ pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel to RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
++ pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
++ &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel from RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate buffer for commands, replies */
++ pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
++ pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
++ pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
++ if (pDisp->pBuf == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed "
++ "to allocate channel buffer!\n");
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status))
++ *phDispObject = pDisp;
++ else
++ DeleteDisp(pDisp);
++
++ DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
++ ((DSP_SUCCEEDED(status)) &&
++ (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
++ return status;
++}
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ */
++void DISP_Delete(struct DISP_OBJECT *hDisp)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++
++ GT_1trace(DISP_DebugMask, GT_ENTER,
++ "DISP_Delete: hDisp: 0x%x\n", hDisp);
++
++ DeleteDisp(hDisp);
++
++ DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++}
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ */
++void DISP_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "Entered DISP_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ */
++bool DISP_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DISP_DebugMask.flags);
++ GT_create(&DISP_DebugMask, "DI"); /* "DI" for DIspatcher */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "DISP_Init(), ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ */
++DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
++ struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, NODE_ENV nodeEnv,
++ s32 nPriority)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
++ "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
++ hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
++
++ /* Send message to RMS to change priority */
++ pCommand = (struct RMS_Command *)(hDisp->pBuf);
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = nPriority;
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeChangePriority failed! "
++ "status = 0x%x\n", status);
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS *pArgs,
++ OUT NODE_ENV *pNodeEnv)
++{
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ struct RMS_Command *pCommand;
++ struct RMS_MsgArgs *pMsgArgs;
++ struct RMS_MoreTaskArgs *pMoreTaskArgs;
++ enum NODE_TYPE nodeType;
++ u32 dwLength;
++ RMS_WORD *pdwBuf = NULL;
++ u32 ulBytes;
++ u32 i;
++ u32 total;
++ u32 uCharsInRMSWord;
++ s32 taskArgsOffset;
++ s32 sioInDefOffset;
++ s32 sioOutDefOffset;
++ s32 sioDefsOffset;
++ s32 argsOffset = -1;
++ s32 offset;
++ struct NODE_STRMDEF strmDef;
++ u32 max;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEINFO nodeInfo;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++ DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
++ DBC_Require(pNodeEnv != NULL);
++
++ GT_6trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeCreate: hDisp: 0x%x\thNode:"
++ " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
++ " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
++ "for device = 0x%x\n", devType);
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (devType != DSP_UNIT) {
++ GT_1trace(DISP_DebugMask, GT_7CLASS,
++ "DISP_NodeCreate unknown device "
++ "type = 0x%x\n", devType);
++ goto func_end;
++ }
++ DBC_Require(pArgs != NULL);
++ nodeType = NODE_GetType(hNode);
++ msgArgs = pArgs->asa.msgArgs;
++ max = hDisp->ulBufsizeRMS; /*Max # of RMS words that can be sent */
++ DBC_Assert(max == RMS_COMMANDBUFSIZE);
++ uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
++ /* Number of RMS words needed to hold arg data */
++ dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++ /* Make sure msg args and command fit in buffer */
++ total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
++ sizeof(struct RMS_MsgArgs)
++ / sizeof(RMS_WORD) - 1 + dwLength;
++ if (total >= max) {
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args too"
++ " large for buffer! Message args size = %d, max = %d\n",
++ total, max);
++ }
++ /*
++ * Fill in buffer to send to RMS.
++ * The buffer will have the following format:
++ *
++ * RMS command:
++ * Address of RMS_CreateNode()
++ * Address of node's create function
++ * dummy argument
++ * node type
++ *
++ * Message Args:
++ * max number of messages
++ * segid for message buffer allocation
++ * notification type to use when message is received
++ * length of message arg data
++ * message args data
++ *
++ * Task Args (if task or socket node):
++ * priority
++ * stack size
++ * system stack size
++ * stack segment
++ * misc
++ * number of input streams
++ * pSTRMInDef[] - offsets of STRM definitions for input streams
++ * number of output streams
++ * pSTRMOutDef[] - offsets of STRM definitions for output
++ * streams
++ * STRMInDef[] - array of STRM definitions for input streams
++ * STRMOutDef[] - array of STRM definitions for output streams
++ *
++ * Socket Args (if DAIS socket node):
++ *
++ */
++ if (DSP_SUCCEEDED(status)) {
++ total = 0; /* Total number of words in buffer so far */
++ pdwBuf = (RMS_WORD *)hDisp->pBuf;
++ pCommand = (struct RMS_Command *)pdwBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
++ if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
++ /* Flush ICACHE on Load */
++ pCommand->arg2 = 1; /* dummy argument */
++ } else {
++ /* Do not flush ICACHE */
++ pCommand->arg2 = 0; /* dummy argument */
++ }
++ pCommand->data = NODE_GetType(hNode);
++ /*
++ * argsOffset is the offset of the data field in struct
++ * RMS_Command structure. We need this to calculate stream
++ * definition offsets.
++ */
++ argsOffset = 3;
++ total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
++ /* Message args */
++ pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
++ pMsgArgs->maxMessages = msgArgs.uMaxMessages;
++ pMsgArgs->segid = msgArgs.uSegid;
++ pMsgArgs->notifyType = msgArgs.uNotifyType;
++ pMsgArgs->argLength = msgArgs.uArgLength;
++ total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
++ memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
++ total += dwLength;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If node is a task node, copy task create arguments into buffer */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ taskArgs = pArgs->asa.taskArgs;
++ taskArgsOffset = total;
++ total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
++ 1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
++ /* Copy task arguments */
++ if (total < max) {
++ total = taskArgsOffset;
++ pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
++ total);
++ /*
++ * Get some important info about the node. Note that we
++ * don't just reach into the hNode struct because
++ * that would break the node object's abstraction.
++ */
++ GetNodeInfo(hNode, &nodeInfo);
++ GT_2trace(DISP_DebugMask, GT_ENTER,
++ "uExecutionPriority %x, nPriority %x\n",
++ nodeInfo.uExecutionPriority,
++ taskArgs.nPriority);
++ pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
++ pMoreTaskArgs->stackSize = taskArgs.uStackSize;
++ pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
++ pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
++ pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
++ pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
++ pMoreTaskArgs->misc = taskArgs.ulDaisArg;
++ pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
++ total +=
++ sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
++ GT_2trace(DISP_DebugMask, GT_7CLASS,
++ "DISP::::uDSPHeapAddr %x, "
++ "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
++ taskArgs.uHeapSize);
++ /* Keep track of pSIOInDef[] and pSIOOutDef[]
++ * positions in the buffer, since this needs to be
++ * filled in later. */
++ sioInDefOffset = total;
++ total += taskArgs.uNumInputs;
++ pdwBuf[total++] = taskArgs.uNumOutputs;
++ sioOutDefOffset = total;
++ total += taskArgs.uNumOutputs;
++ sioDefsOffset = total;
++ /* Fill SIO defs and offsets */
++ offset = sioDefsOffset;
++ for (i = 0; i < taskArgs.uNumInputs; i++) {
++ if (DSP_FAILED(status))
++ break;
++
++ pdwBuf[sioInDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmInDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ for (i = 0; (i < taskArgs.uNumOutputs) &&
++ (DSP_SUCCEEDED(status)); i++) {
++ pdwBuf[sioOutDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmOutDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message"
++ " args to large for buffer! Message args"
++ " size = %d, max = %d\n", total, max);
++ }
++ } else {
++ /* Args won't fit */
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args "
++ " too large for buffer! Message args size = %d"
++ ", max = %d\n", total, max);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulBytes = total * sizeof(RMS_WORD);
++ DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ ulBytes, pNodeEnv);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate failed! "
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's create function
++ * on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate, "
++ "DSP-side Node Create failed: 0x%x\n",
++ status);
++ }
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== DISP_NodeDelete ========
++ * purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ */
++DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeDelete: hDisp: 0x%xthNode: "
++ "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
++ hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS
++ */
++ pCommand = (struct RMS_Command *)hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's delete
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete, "
++ "DSP-side Node Delete failed: 0x%x\n",
++ status);
++ }
++ }
++
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeRun ========
++ * purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ */
++DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
++ 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
++ hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS.
++ */
++ pCommand = (struct RMS_Command *) hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD) (ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD) nodeEnv;
++ pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's execute
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun, DSP-side Node "
++ "Execute failed: 0x%x\n",
++ status);
++ }
++ }
++
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteDisp ========
++ * purpose:
++ * Frees the resources allocated for the dispatcher.
++ */
++static void DeleteDisp(struct DISP_OBJECT *hDisp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
++ pIntfFxns = hDisp->pIntfFxns;
++
++ /* Free Node Dispatcher resources */
++ if (hDisp->hChnlFromDsp) {
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose)
++ (hDisp->hChnlFromDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel from RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->hChnlToDsp) {
++ status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel to RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->pBuf)
++ MEM_Free(hDisp->pBuf);
++
++ MEM_FreeObject(hDisp);
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * purpose:
++ * Fills stream definitions.
++ */
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord)
++{
++ struct RMS_StrmDef *pStrmDef;
++ u32 total = *ptotal;
++ u32 uNameLen;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++
++ if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
++ status = DSP_EFAIL;
++ } else {
++ pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
++ pStrmDef->bufsize = strmDef.uBufsize;
++ pStrmDef->nbufs = strmDef.uNumBufs;
++ pStrmDef->segid = strmDef.uSegid;
++ pStrmDef->align = strmDef.uAlignment;
++ pStrmDef->timeout = strmDef.uTimeout;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Since we haven't added the device name yet, subtract
++ * 1 from total.
++ */
++ total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
++ DBC_Require(strmDef.szDevice);
++ dwLength = strlen(strmDef.szDevice) + 1;
++
++ /* Number of RMS_WORDS needed to hold device name */
++ uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++
++ if (total + uNameLen >= max) {
++ status = DSP_EFAIL;
++ } else {
++ /*
++ * Zero out last word, since the device name may not
++ * extend to completely fill this word.
++ */
++ pdwBuf[total + uNameLen - 1] = 0;
++ /** TODO USE SERVICES **/
++ memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
++ total += uNameLen;
++ *ptotal = total;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== SendMessage ======
++ * Send command message to RMS, get reply from RMS.
++ */
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_OBJECT *hChnl;
++ u32 dwArg = 0;
++ u8 *pBuf;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pdwArg != NULL);
++
++ *pdwArg = (u32) NULL;
++ pIntfFxns = hDisp->pIntfFxns;
++ hChnl = hDisp->hChnlToDsp;
++ pBuf = hDisp->pBuf;
++
++ /* Send the command */
++ status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
++ 0L, dwArg);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq to"
++ " RMS failed! Status = 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage failed! "
++ "Channel IOC status = 0x%x\n",
++ chnlIOC.status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel GetIOC to"
++ " RMS failed! Status = 0x%x\n", status);
++ }
++func_cont:
++ /* Get the reply */
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hChnl = hDisp->hChnlFromDsp;
++ ulBytes = REPLYSIZE;
++ status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
++ 0, 0L, dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq "
++ "from RMS failed! Status = 0x%x\n", status);
++ goto func_end;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else if (chnlIOC.cBytes < ulBytes) {
++ /* Did not get all of the reply from the RMS */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Did not get all"
++ "of reply from RMS! Bytes received: %d\n",
++ chnlIOC.cBytes);
++ status = DSP_EFAIL;
++ } else {
++ if (CHNL_IsIOComplete(chnlIOC)) {
++ DBC_Assert(chnlIOC.pBuf == pBuf);
++ status = (*((RMS_WORD *)chnlIOC.pBuf));
++ *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* GetIOC failed */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Failed to get "
++ "reply from RMS! Status = 0x%x\n", status);
++ }
++func_end:
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
+new file mode 100644
+index 0000000..256ce12
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv.c
+@@ -0,0 +1,1893 @@
++/*
++ * drv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.c ========
++ * Description:
++ * DSP/BIOS Bridge resource allocation module.
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ======== ========
++ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
++ MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
++ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
++ *! 05-Jan-2004 vp: Updated for 24xx platform
++ *! 21-Mar-2003 sb: Get SHM size from registry
++ *! 10-Feb-2003 vp: Code review updates
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
++ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
++ *! RequestISAResources()
++ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
++ *! RequestISAResources.
++ *! 07-Aug-2000 rr: static list of dev objects removed.
++ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
++ *! instead of MEM_Alloc.
++ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
++ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
++ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
++ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
++ *! struct CFG_HOSTRES Structure.
++ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
++ *! DBC_Ensure checks for sucess and pDevice != NULL
++ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
++ *! 09-Dec-1999 rr: windows.h included to remove warnings.
++ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
++ *! status while making call to Reg functions.
++ *! 23-Nov-1999 rr: windows.h included
++ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
++ *! fixed.
++ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
++ *! Hardcoded bIRQRegister define removed.
++ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
++ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
++ *! Resource structure directly.
++ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
++ *! dwBusType taken from the registry.Hard coded
++ *! registry entries removed.
++ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
++ *! MiniDriver has been renamed to DRV_RequestResources.
++ *! DRV_UnRegisterMiniDriver fxn removed.
++ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
++ *! Now it is simpler. IT stores the dev node in the
++ *! registry, assign resources and calls the DEV_Start.
++ *! 10-Sep-1999 rr: Register Minidriver modified.
++ *! - Resource structure follows the NT model
++ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/node.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f52474d /* "DRV_" (in reverse) */
++
++struct DRV_OBJECT {
++ u32 dwSignature;
++ struct LST_LIST *devList;
++ struct LST_LIST *devNodeString;
++#ifndef RES_CLEANUP_DISABLE
++ struct PROCESS_CONTEXT *procCtxtList;
++#endif
++};
++
++/*
++ * This is the Device Extension. Named with the Prefix
++ * DRV_ since it is living in this module
++ */
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++static s32 cRefs;
++
++#if GT_TRACE
++extern struct GT_Mask curTrace;
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
++
++#ifndef RES_CLEANUP_DISABLE
++/* GPP PROCESS CLEANUP CODE */
++
++static DSP_STATUS PrintProcessInformation(void);
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt);
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt);
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++/* Get the process context list from driver object */
++
++/* Set the Process ID */
++DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hPCtxt != NULL);
++
++ pCtxt->pid = hProcess;
++ return status;
++}
++
++
++/* Getting the head of the process context list */
++DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++
++ DBC_Assert(hDrvObject != NULL);
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ *pPctxt = pDrvObject->procCtxtList;
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ return status;
++}
++
++
++
++/* Get a particular process context based on process handle (phProcess) */
++DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++ s32 pCtxtFound = 0;
++
++ DBC_Assert(pDrvObject != NULL);
++ pCtxtList = pDrvObject->procCtxtList;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
++ while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
++ }
++ if (pCtxtList == NULL) {
++ if (hNode != NULL) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempNode = pCtxtList->pNodeList;
++ while ((pTempNode != NULL) &&
++ (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempDMM = pCtxtList->pDMMList;
++ while ((pTempDMM != NULL) &&
++ (pTempDMM->ulDSPAddr != pMapAddr)) {
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ if (pCtxtList == NULL)
++ status = DSP_ENOTFOUND;
++
++ }
++ } else{
++ status = DSP_SOK;
++ }
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
++ *pCtxt = pCtxtList;
++ return status;
++}
++
++
++/* Add a new process context to process context list */
++DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *hDRVObject;
++
++ GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
++ status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ DBC_Assert(hDRVObject != NULL);
++ *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext Calling "
++ "DRV_GetProcCtxtList\n");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext After Calling "
++ "DRV_GetProcCtxtList\n");
++ if (pCtxtList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and pCtxt is "
++ "not Null\n");
++ while (pCtxtList->next != NULL)
++ pCtxtList = pCtxtList->next;
++
++ pCtxtList->next = *pCtxt;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and "
++ "pCtxt is Null\n");
++ hDRVObject->procCtxtList = *pCtxt;
++ }
++ return status;
++}
++
++/* Delete a process context from process resource context list */
++DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt2 = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++
++ DBC_Assert(hDRVObject != NULL);
++ DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
++
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
++ pTmp = pCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
++ pTmp = pCtxtList;
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_RemoveProcContext: 2");
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
++ if (hDRVObject->procCtxtList == pCtxt2)
++ hDRVObject->procCtxtList = pCtxt2->next;
++
++ if (pCtxtList == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTmp->next != NULL)
++ pTmp->next = pTmp->next->next;
++
++ MEM_Free(pCtxt2);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
++
++ return status;
++}
++
++/* Update the state of process context */
++DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status1 = DSP_SOK;
++ if (pCtxt != NULL) {
++ pCtxt->resState = status;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_ProcUpdatestate: Failed to update "
++ "process state");
++ }
++ return status1;
++}
++
++/* Allocate and add a node resource element
++* This function is called from .Node_Allocate. */
++DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
++ HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNodeRes = NULL;
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
++ *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
++ (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pNodeRes)->hNode = hNode;
++ if (pCtxt->pNodeList != NULL) {
++ pTempNodeRes = pCtxt->pNodeList;
++ while (pTempNodeRes->next != NULL)
++ pTempNodeRes = pTempNodeRes->next;
++
++ pTempNodeRes->next = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 2");
++ } else {
++ pCtxt->pNodeList = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 3");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
++ return status;
++}
++
++/* Release all Node resources and its context
++* This is called from .Node_Delete. */
++DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
++ struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
++ while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pCtxt->pNodeList == pNodeRes)
++ pCtxt->pNodeList = pNodeRes->next;
++
++ if (pTempNode == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempNode2->next != NULL)
++ pTempNode2->next = pTempNode2->next->next;
++
++ MEM_Free(pTempNode);
++ return status;
++}
++
++/* Actual Node De-Allocation */
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pNodeList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ u32 nState;
++
++ DBC_Assert(hPCtxt != NULL);
++ pNodeList = pCtxt->pNodeList;
++ while (pNodeList != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
++ pNodeRes = pNodeList;
++ pNodeList = pNodeList->next;
++ if (pNodeRes->nodeAllocated) {
++ nState = NODE_GetState(pNodeRes->hNode) ;
++ GT_1trace(curTrace, GT_5CLASS,
++ "DRV_ProcFreeNodeRes: Node state %x\n", nState);
++ if (nState <= NODE_DELETING) {
++ if ((nState == NODE_RUNNING) ||
++ (nState == NODE_PAUSED) ||
++ (nState == NODE_TERMINATING)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Terminate for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Terminate
++ (pNodeRes->hNode, &status);
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Delete for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Delete(pNodeRes->hNode);
++ GT_1trace(curTrace, GT_5CLASS,
++ "the status after the NodeDelete %x\n",
++ status);
++ } else if ((nState == NODE_ALLOCATED)
++ || (nState == NODE_CREATED))
++ status = NODE_Delete(pNodeRes->hNode);
++ }
++ }
++ pNodeRes->nodeAllocated = 0;
++ }
++ return status;
++}
++
++/* Allocate the DMM resource element
++* This is called from Proc_Map. after the actual resource is allocated */
++DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ *pDMMRes = (struct DMM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
++ if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pCtxt->pDMMList != NULL) {
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 3");
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes->next != NULL)
++ pTempDMMRes = pTempDMMRes->next;
++
++ pTempDMMRes->next = *pDMMRes;
++ } else {
++ pCtxt->pDMMList = *pDMMRes;
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 4");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
++ return status;
++}
++
++
++
++/* Release DMM resource element context
++* This is called from Proc_UnMap. after the actual resource is freed */
++DSP_STATUS DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMMRes2 = pCtxt->pDMMList;
++ pTempDMMRes = pCtxt->pDMMList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
++ while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
++ if (pCtxt->pDMMList == pTempDMMRes)
++ pCtxt->pDMMList = pTempDMMRes->next;
++
++ if (pTempDMMRes == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempDMMRes2->next != NULL)
++ pTempDMMRes2->next = pTempDMMRes2->next->next;
++
++ MEM_Free(pDMMRes);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
++ return status;
++}
++
++/* Update DMM resource status */
++DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
++ u32 pReqAddr, u32 pMapAddr,
++ HANDLE hProcessor)
++{
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hDMMRes != NULL);
++ pDMMRes->ulMpuAddr = pMpuAddr;
++ pDMMRes->ulDSPAddr = pMapAddr;
++ pDMMRes->ulDSPResAddr = pReqAddr;
++ pDMMRes->dmmSize = ulSize;
++ pDMMRes->hProcessor = hProcessor;
++ pDMMRes->dmmAllocated = 1;
++
++ return status;
++}
++
++/* Actual DMM De-Allocation */
++DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
++ while (pDMMList != NULL) {
++ pDMMRes = pDMMList;
++ pDMMList = pDMMList->next;
++ if (pDMMRes->dmmAllocated) {
++ status = PROC_UnMap(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ status = PROC_UnReserveMemory(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ pDMMRes->dmmAllocated = 0;
++ }
++ }
++ return status;
++}
++
++
++/* Release all DMM resources and its context
++* This is called from .bridge_release. */
++DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(pCtxt != NULL);
++ DRV_ProcFreeDMMRes(pCtxt);
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes != NULL) {
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ MEM_Free(pTempDMMRes2);
++ }
++ pCtxt->pDMMList = NULL;
++ return status;
++}
++
++DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMM = pCtxt->pDMMList;
++ while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
++ GT_3trace(curTrace, GT_ENTER,
++ "DRV_GetDMMResElement: 2 pTempDMM:%x "
++ "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
++ pTempDMM->ulDSPAddr, pMapAddr);
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
++ *pDMMRes = pTempDMM;
++ } else {
++ status = DSP_ENOTFOUND;
++ } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
++ return status;
++}
++
++/* Update Node allocation status */
++void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->nodeAllocated = status;
++}
++
++/* Update Node Heap status */
++void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->heapAllocated = status;
++}
++
++/* Release all Node resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeNodeRes(pCtxt);
++ pTempNode = pCtxt->pNodeList;
++ while (pTempNode != NULL) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ MEM_Free(pTempNode2);
++ }
++ pCtxt->pNodeList = NULL;
++ return status;
++}
++
++/* Getting the node resource element */
++
++DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempNode = pCtxt->pNodeList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
++ while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL)
++ *nodeRes = pTempNode;
++ else
++ status = DSP_ENOTFOUND;
++
++ return status;
++}
++
++
++
++/* Allocate the STRM resource element
++* This is called after the actual resource is allocated
++*/
++DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
++ HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++ DBC_Assert(hPCtxt != NULL);
++
++ *pSTRMRes = (struct STRM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
++ if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pSTRMRes)->hStream = hStreamHandle;
++ if (pCtxt->pSTRMList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertiSTRMResElement: 3");
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes->next != NULL)
++ pTempSTRMRes = pTempSTRMRes->next;
++
++ pTempSTRMRes->next = *pSTRMRes;
++ } else {
++ pCtxt->pSTRMList = *pSTRMRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertSTRMResElement: 4");
++ }
++ }
++ return status;
++}
++
++
++
++/* Release Stream resource element context
++* This function called after the actual resource is freed
++*/
++DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
++ struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ }
++ if (pCtxt->pSTRMList == pTempSTRMRes)
++ pCtxt->pSTRMList = pTempSTRMRes->next;
++
++ if (pTempSTRMRes == NULL)
++ status = DSP_ENOTFOUND;
++ else if (pTempSTRMRes2->next != NULL)
++ pTempSTRMRes2->next = pTempSTRMRes2->next->next;
++
++ MEM_Free(pSTRMRes);
++ return status;
++}
++
++
++/* Actual Stream De-Allocation */
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ u8 **apBuffer = NULL;
++ struct STRM_RES_OBJECT *pSTRMList = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ s32 ulBufSize;
++
++
++ DBC_Assert(hPCtxt != NULL);
++ pSTRMList = pCtxt->pSTRMList;
++ while (pSTRMList != NULL) {
++ pSTRMRes = pSTRMList;
++ pSTRMList = pSTRMList->next;
++ if (pSTRMRes->uNumBufs != 0) {
++ apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
++ sizeof(u8 *)), MEM_NONPAGED);
++ status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
++ pSTRMRes->uNumBufs);
++ MEM_Free(apBuffer);
++ }
++ status = STRM_Close(pSTRMRes->hStream);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_EPENDING) {
++ status = STRM_Reclaim(pSTRMRes->hStream,
++ &pBufPtr, &ulBytes,
++ (u32 *)&ulBufSize, &dwArg);
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Close(pSTRMRes->hStream);
++
++ }
++ }
++ }
++ return status1;
++}
++
++/* Release all Stream resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeSTRMRes(pCtxt);
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes != NULL) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ MEM_Free(pTempSTRMRes2);
++ }
++ pCtxt->pSTRMList = NULL;
++ return status;
++}
++
++
++/* Getting the stream resource element */
++DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
++ pTempSTRM2 = pTempSTRM;
++ pTempSTRM = pTempSTRM->next;
++ }
++ if (pTempSTRM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
++ *STRMRes = pTempSTRM;
++ } else {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
++ status = DSP_ENOTFOUND;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
++ return status;
++}
++
++/* Updating the stream resource element */
++DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++
++ DBC_Assert(hPCtxt != NULL);
++ (*STRMRes)->uNumBufs = uNumBufs;
++ return status;
++}
++
++/* Displaying the resources allocated by a process */
++DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
++{
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ u32 tempCount = 1;
++ HANDLE hDrvObject = NULL;
++ void *pBuf = pBuf1;
++ u8 pTempBuf[250];
++ u32 tempStrLen = 0, tempStrLen2 = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxt, (struct DRV_OBJECT *)hDrvObject);
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:*\n");
++ while (pCtxt != NULL) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "-------------------------------------"
++ "-----------------------------------\n");
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ if (pCtxt->resState == PROC_RES_ALLOCATED) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Process Resource State: "
++ "pCtxt->resState = PROC_RES_ALLOCATED, "
++ " Process ID: %d\n", pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ } else {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Resource State: pCtxt->resState"
++ " = PROC_RES_DEALLOCATED, Process ID:%d\n",
++ pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ }
++ pNodeRes = pCtxt->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pNodeList->hNode:%x\n",
++ tempCount, pNodeRes->hNode);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Node Resource Information: Node #"
++ " %d Node Handle hNode:0X%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDSPHEAPRes = pCtxt->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
++ tempCount, pDSPHEAPRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DSP Heap Resource Info: HEAP # %d"
++ " Mapped GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ (u32)pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDMMRes = pCtxt->pDMMList;
++ while (pDMMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ " pCtxt->pDMMList->ulMpuAddr:%x\n",
++ tempCount,
++ pDMMRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DMM Resource Info: DMM # %d Mapped"
++ " GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDMMRes->ulMpuAddr,
++ (u32)pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pSTRMRes = pCtxt->pSTRMList;
++ while (pSTRMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pSTRMList->hStream:%x\n", tempCount,
++ pSTRMRes->hStream);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Stream Resource info: STRM # %d "
++ "Stream Handle: 0x%x \n",
++ tempCount, (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ pCtxt = pCtxt->next;
++ }
++ *pSize = tempStrLen;
++ status = PrintProcessInformation();
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:**\n");
++ return status;
++}
++
++/*
++ * ======== PrintProcessInformation ========
++ * Purpose:
++ * This function prints the Process's information stored in
++ * the process context list. Some of the information that
++ * it displays is Process's state, Node, Stream, DMM, and
++ * Heap information.
++ */
++static DSP_STATUS PrintProcessInformation(void)
++{
++ struct DRV_OBJECT *hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 tempCount;
++ u32 procID;
++
++ /* Get the Process context list */
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
++ GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
++ " for DSP bridge ##\n");
++ GT_0trace(curTrace, GT_4CLASS, " \n ###The processes"
++ " information is as follows ### \n") ;
++ GT_0trace(curTrace, GT_4CLASS, " ====================="
++ "============ \n");
++ /* Go through the entries in the Process context list */
++ while (pCtxtList != NULL) {
++ GT_1trace(curTrace, GT_4CLASS, "\nThe process"
++ " id is %d\n", pCtxtList->pid);
++ GT_0trace(curTrace, GT_4CLASS, " -------------------"
++ "---------\n");
++ if (pCtxtList->resState == PROC_RES_ALLOCATED) {
++ GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
++ " is in Allocated state\n");
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
++ " is in DeAllocated state\n");
++ }
++ GT_1trace(curTrace, GT_4CLASS, "\nThe hProcessor"
++ " handle is: 0X%x\n",
++ (u32)pCtxtList->hProcessor);
++ if (pCtxtList->hProcessor != NULL) {
++ PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
++ if (procID == DSP_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " DSP Processor\n");
++ } else if (procID == IVA_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " IVA Processor\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "\n***ERROR:Invalid Processor Id***\n");
++ }
++ }
++ pNodeRes = pCtxtList->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Nodes allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Node # %d Node Handle hNode:0x%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Nodes"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pDSPHEAPRes = pCtxtList->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Heaps allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DSP Heap Resource Info: HEAP # %d "
++ "Mapped GPP Address:0x%x, Size: 0x%lx\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Heaps allocated"
++ " by this Process***\n");
++ tempCount = 1;
++ pDMMRes = pCtxtList->pDMMList;
++ while (pDMMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***The DMM resources allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DMM Resource Info: DMM # %d "
++ "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
++ tempCount, pDMMRes->ulMpuAddr,
++ pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no DMM resources"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pSTRMRes = pCtxtList->pSTRMList;
++ while (pSTRMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Stream resources allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Stream Resource info: STRM # %d"
++ "Stream Handle:0X%x\n", tempCount,
++ (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Stream resources"
++ "allocated by this Process***\n");
++ pCtxtList = pCtxtList->next;
++ }
++ return status;
++}
++
++/* GPP PROCESS CLEANUP CODE END */
++#endif
++
++/*
++ * ======== = DRV_Create ======== =
++ * Purpose:
++ * DRV Object gets created only once during Driver Loading.
++ */
++DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = NULL;
++
++ DBC_Require(phDRVObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
++ " phDRVObject 0x%x\n", phDRVObject);
++ MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
++ if (pDRVObject) {
++ /* Create and Initialize List of device objects */
++ pDRVObject->devList = LST_Create();
++ if (pDRVObject->devList) {
++ /* Create and Initialize List of device Extension */
++ pDRVObject->devNodeString = LST_Create();
++ if (!(pDRVObject->devNodeString)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create DRV_EXT list ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create Dev List ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory for DRV Obj");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the DRV Object in the Registry */
++ if (DSP_SUCCEEDED
++ (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
++ GT_1trace(curTrace, GT_1CLASS,
++ "DRV Obj Created pDrvObject 0x%x\n ",
++ pDRVObject);
++ *phDRVObject = pDRVObject;
++ } else {
++ /* Free the DRV Object */
++ status = DSP_EFAIL;
++ MEM_Free(pDRVObject);
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to update the Registry with "
++ "DRV Object ");
++ }
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
++ "0x%x\n", phDRVObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Discontinue usage of the DRV module.
++ */
++void DRV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
++
++ cRefs--;
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== = DRV_Destroy ======== =
++ * purpose:
++ * Invoked during bridge de-initialization
++ */
++DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
++ " hDRVObject 0x%x\n", hDRVObject);
++ /*
++ * Delete the List if it exists.Should not come here
++ * as the DRV_RemoveDevObject and the Last DRV_RequestResources
++ * removes the list if the lists are empty.
++ */
++ if (pDRVObject->devList) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devList);
++ }
++ if (pDRVObject->devNodeString) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devNodeString);
++ }
++ MEM_FreeObject(pDRVObject);
++ /* Update the DRV Object in Registry to be 0 */
++ (void)CFG_SetObject(0, REG_DRV_OBJECT);
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
++ "0x%x\n", hDRVObject, status);
++ DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list.
++ */
++DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++#if GT_TRACE /* pDrvObject is used only for Assertions and debug messages.*/
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++#endif
++ struct DEV_OBJECT *pDevObject;
++ u32 i;
++ DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(uIndex >= 0);
++ DBC_Require(cRefs > 0);
++ DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
++ GT_3trace(curTrace, GT_ENTER,
++ "Entered DRV_GetDevObject, args:\n\tuIndex: "
++ "0x%x\n\thDrvObject: 0x%x\n\tphDevObject: 0x%x\n",
++ uIndex, hDrvObject, phDevObject);
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ for (i = 0; i < uIndex; i++) {
++ pDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
++ }
++ if (pDevObject) {
++ *phDevObject = (struct DEV_OBJECT *) pDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "DRV: Could not get the DevObject\n");
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
++ "hDevObject: 0x%x\n", status, *phDevObject);
++ return status;
++}
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV.
++ */
++u32 DRV_GetFirstDevObject(void)
++{
++ u32 dwDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList))
++ dwDevObject = (u32) LST_First(pDrvObject->devList);
++ }
++
++ return dwDevObject;
++}
++
++/*
++ * ======== DRV_GetFirstDevNodeString ========
++ * Purpose:
++ * Retrieve the first Device Extension from an internal linked list of
++ * of Pointer to DevNode Strings maintained by DRV.
++ */
++u32 DRV_GetFirstDevExtension(void)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_First(pDrvObject->
++ devNodeString);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV, after having previously called
++ * DRV_GetFirstDevObject() and zero or more DRV_GetNext.
++ */
++u32 DRV_GetNextDevObject(u32 hDevObject)
++{
++ u32 dwNextDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevObject != 0);
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList)) {
++ dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
++ (struct LST_ELEM *)hDevObject);
++ }
++ }
++ return dwNextDevObject;
++}
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Retrieve the next Device Extension from an internal linked list of
++ * of pointer to DevNodeString maintained by DRV, after having previously
++ * called DRV_GetFirstDevExtension() and zero or more
++ * DRV_GetNextDevExtension().
++ */
++u32 DRV_GetNextDevExtension(u32 hDevExtension)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevExtension != 0);
++
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
++ REG_DRV_OBJECT))) {
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_Next(pDrvObject->
++ devNodeString,
++ (struct LST_ELEM *)hDevExtension);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize DRV module private state.
++ */
++DSP_STATUS DRV_Init(void)
++{
++ s32 fRetval = 1; /* function return value */
++
++ DBC_Require(cRefs >= 0);
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry crefs 0x%x \n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DevObject into the list of Manager object.
++ */
++DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Assert(pDRVObject->devList);
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_InsertProcObject hDRVObject "
++ "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
++
++ LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
++
++ GT_1trace(curTrace, GT_ENTER,
++ "Exiting InsertDevObject status 0x%x\n", status);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
++
++ return status;
++}
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a DeviceObject from the given list of DRV
++ * objects.
++ */
++DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++ struct LST_ELEM *pCurElem;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Require(hDevObject != NULL);
++
++ DBC_Require(pDRVObject->devList != NULL);
++ DBC_Require(!LST_IsEmpty(pDRVObject->devList));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_RemoveDevObject hDevObject "
++ "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
++ /* Search list for pProcObject: */
++ for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
++ pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
++ /* If found, remove it. */
++ if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
++ LST_RemoveElem(pDRVObject->devList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ /* Remove list if empty. */
++ if (LST_IsEmpty(pDRVObject->devList)) {
++ LST_Delete(pDRVObject->devList);
++ pDRVObject->devList = NULL;
++ }
++ DBC_Ensure((pDRVObject->devList == NULL) ||
++ !LST_IsEmpty(pDRVObject->devList));
++ GT_1trace(curTrace, GT_ENTER,
++ "DRV_RemoveDevObject returning 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Requests resources from the OS.
++ */
++DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject;
++ struct DRV_EXT *pszdevNode;
++
++ DBC_Require(dwContext != 0);
++ DBC_Require(pDevNodeString != NULL);
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
++ /*
++ * Allocate memory to hold the string. This will live untill
++ * it is freed in the Release resources. Update the driver object
++ * list.
++ */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
++ REG_DRV_OBJECT))) {
++ pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
++ if (pszdevNode) {
++ LST_InitElem(&pszdevNode->link);
++ strncpy((char *) pszdevNode->szString,
++ (char *)dwContext, MAXREGPATHLENGTH);
++ /* Update the Driver Object List */
++ *pDevNodeString = (u32)pszdevNode->szString;
++ LST_PutTail(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory devNodeString ");
++ status = DSP_EFAIL;
++ *pDevNodeString = 0;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to get Driver Object from Registry");
++ *pDevNodeString = 0;
++ }
++
++ if (!(strcmp((char *) dwContext, "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Allocating resources for UMA \n");
++ status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
++ }
++
++ if (DSP_FAILED(status)) {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to reserve bridge resources ");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != NULL &&
++ !LST_IsEmpty(pDRVObject->devNodeString)) ||
++ (DSP_FAILED(status) && *pDevNodeString == 0));
++
++ return status;
++}
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Releases resources from the OS.
++ */
++DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
++ struct DRV_EXT *pszdevNode;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
++
++ if (!(strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Releasing DSP-Bridge resources \n");
++ status = RequestBridgeResources(dwContext, DRV_RELEASE);
++ } else {
++ GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ "Failed to relese bridge resources\n");
++ }
++
++ /*
++ * Irrespective of the status go ahead and clean it
++ * The following will over write the status.
++ */
++ for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
++ pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
++ DRV_GetNextDevExtension((u32)pszdevNode)) {
++ if ((u32)pszdevNode == dwContext) {
++ /* Found it */
++ /* Delete from the Driver object list */
++ LST_RemoveElem(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ MEM_Free((void *) pszdevNode);
++ break;
++ }
++ /* Delete the List if it is empty */
++ if (LST_IsEmpty(pDRVObject->devNodeString)) {
++ LST_Delete(pDRVObject->devNodeString);
++ pDRVObject->devNodeString = NULL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResources ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++
++ struct DRV_EXT *driverExt;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
++
++ if (!bRequest) {
++ driverExt = (struct DRV_EXT *)dwContext;
++ /* Releasing resources by deleting the registry key */
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Failed \n");
++ } else {
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Succeeded \n");
++ }
++
++ if (pResources != NULL) {
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ if ((pResources->dwMemBase[1]) &&
++ (pResources->dwMemPhys[1])) {
++ MEM_FreePhysMem((void *)pResources->
++ dwMemBase[1], pResources->dwMemPhys[1],
++ shm_size);
++ }
++ } else {
++ GT_1trace(curTrace, GT_7CLASS,
++ "Error getting SHM size from registry: "
++ "%x. Not calling MEM_FreePhysMem\n",
++ status);
++ }
++ pResources->dwMemBase[1] = 0;
++ pResources->dwMemPhys[1] = 0;
++
++ if (pResources->dwPrmBase)
++ iounmap((void *)pResources->dwPrmBase);
++ if (pResources->dwCmBase)
++ iounmap((void *)pResources->dwCmBase);
++ if (pResources->dwMboxBase)
++ iounmap((void *)pResources->dwMboxBase);
++ if (pResources->dwMemBase[0])
++ iounmap((void *)pResources->dwMemBase[0]);
++ if (pResources->dwMemBase[2])
++ iounmap((void *)pResources->dwMemBase[2]);
++ if (pResources->dwMemBase[3])
++ iounmap((void *)pResources->dwMemBase[3]);
++ if (pResources->dwMemBase[4])
++ iounmap((void *)pResources->dwMemBase[4]);
++ if (pResources->dwWdTimerDspBase)
++ iounmap((void *)pResources->dwWdTimerDspBase);
++ if (pResources->dwDmmuBase)
++ iounmap((void *)pResources->dwDmmuBase);
++ if (pResources->dwPerBase)
++ iounmap((void *)pResources->dwPerBase);
++ if (pResources->dwPerPmBase)
++ iounmap((void *)pResources->dwPerPmBase);
++ if (pResources->dwCorePmBase)
++ iounmap((void *)pResources->dwCorePmBase);
++ if (pResources->dwSysCtrlBase) {
++ iounmap((void *)pResources->dwSysCtrlBase);
++ /* don't set pResources->dwSysCtrlBase to null
++ * as it is used in BOARD_Stop */
++ }
++ pResources->dwPrmBase = (u32) NULL;
++ pResources->dwCmBase = (u32) NULL;
++ pResources->dwMboxBase = (u32) NULL;
++ pResources->dwMemBase[0] = (u32) NULL;
++ pResources->dwMemBase[2] = (u32) NULL;
++ pResources->dwMemBase[3] = (u32) NULL;
++ pResources->dwMemBase[4] = (u32) NULL;
++ pResources->dwWdTimerDspBase = (u32) NULL;
++ pResources->dwDmmuBase = (u32) NULL;
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
++ (u32)dwBuffSize);
++ /* Set all the other entries to NULL */
++ MEM_Free(pResources);
++ }
++ GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
++ return status;
++ }
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (pResources != NULL) {
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 2;
++ /* First window is for DSP internal memory */
++
++ pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
++ OMAP_IVA2_PRM_SIZE);
++ pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
++ OMAP_IVA2_CM_SIZE);
++ pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
++ OMAP_MBOX_SIZE);
++ pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
++ OMAP_SYSC_SIZE);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++
++ /* for 24xx base port is not mapping the mamory for DSP
++ * internal memory TODO Do a ioremap here */
++ /* Second window is for DSP external memory shared with MPU */
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *) dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry "
++ "value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry "
++ "value for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResourcesDSP ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++ u32 dmaAddr;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++
++ if (pResources != NULL) {
++ if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
++ dwContext, pResources))) {
++ /* Call CFG_GetHostResources to get reserve resouces */
++ status = RequestBridgeResources(dwContext, bRequest);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources
++ ((struct CFG_DEVNODE *) dwContext,
++ pResources);
++ }
++ }
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 4;
++
++ pResources->dwMemBase[0] = 0;
++ pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
++ OMAP_DSP_MEM1_SIZE);
++ pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
++ OMAP_DSP_MEM2_SIZE);
++ pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
++ OMAP_DSP_MEM3_SIZE);
++ pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
++ OMAP_PER_CM_SIZE);
++ pResources->dwPerPmBase = (u32)ioremap(OMAP_PER_PRM_BASE,
++ OMAP_PER_PRM_SIZE);
++ pResources->dwCorePmBase = (u32)ioremap(OMAP_CORE_PRM_BASE,
++ OMAP_CORE_PRM_SIZE);
++ pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
++ OMAP_DMMU_SIZE);
++ pResources->dwWdTimerDspBase = 0;
++
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
++ pResources->dwMemBase[1]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
++ pResources->dwMemBase[2]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
++ pResources->dwMemBase[4]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate Physically contiguous,
++ * non-cacheable memory */
++ pResources->dwMemBase[1] =
++ (u32)MEM_AllocPhysMem(shm_size, 0x100000,
++ &dmaAddr);
++ if (pResources->dwMemBase[1] == 0) {
++ status = DSP_EMEMORY;
++ GT_0trace(curTrace, GT_7CLASS,
++ "SHM reservation Failed\n");
++ } else {
++ pResources->dwMemLength[1] = shm_size;
++ pResources->dwMemPhys[1] = dmaAddr;
++
++ GT_3trace(curTrace, GT_1CLASS,
++ "Bridge SHM address 0x%x dmaAddr"
++ " %x size %x\n",
++ pResources->dwMemBase[1],
++ dmaAddr, shm_size);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry"
++ " value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry value"
++ " for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
+new file mode 100644
+index 0000000..4aa7de6
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.c
+@@ -0,0 +1,777 @@
++/*
++ * drv_interface.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== linux_driver.c ========
++ * Description:
++ * DSP/BIOS Bridge driver interface.
++ *
++ * Public Functions:
++ * driver_init
++ * driver_exit
++ * driver_open
++ * driver_release
++ * driver_ioctl
++ * driver_mmap
++ *
++ *! Revision History
++ *! ================
++ *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
++ *! greater than 2.5, use module_param.
++ *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
++ *! loop after image load and waits in a loop for DSP to start
++ *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
++ *! MOD_DEC_USE_COUNT
++ *! for kernel versions greater than 2.5
++ *! 20-May-2003 vp Added unregister functions for the DPM.
++ *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
++ *! 24-Mar-2003 vp Added Power Management support.
++ *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
++ *! 10-Feb-2003 vp Updated based on code review comments
++ *! 18-Oct-2002 sb Created initial version
++ */
++
++/* ----------------------------------- Host OS */
++
++#include <dspbridge/host_os.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++
++#ifdef MODULE
++#include <linux/module.h>
++#endif
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/cdev.h>
++
++#include <mach/board-3430sdp.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/services.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/wcdioctl.h>
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dspdrv.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- This */
++#include <drv_interface.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/resourcecleanup.h>
++#include <dspbridge/chnl.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dbreg.h>
++#endif
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++#include <mach-omap2/omap3-opp.h>
++#endif
++
++#define BRIDGE_NAME "C6410"
++/* ----------------------------------- Globals */
++#define DRIVER_NAME "DspBridge"
++#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
++#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
++s32 dsp_debug;
++
++struct platform_device *omap_dspbridge_dev;
++
++struct bridge_dev {
++ struct cdev cdev;
++};
++
++static struct bridge_dev *bridge_device;
++
++static struct class *bridge_class;
++
++static u32 driverContext;
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_str;
++#endif /* CONFIG_BRIDGE_DEBUG */
++static s32 driver_major = DRIVER_MAJOR;
++static s32 driver_minor = DRIVER_MINOR;
++static char *base_img;
++char *iva_img;
++static char *num_procs = "C55=1";
++static s32 shm_size = 0x400000; /* 4 MB */
++static u32 phys_mempool_base;
++static u32 phys_mempool_size;
++static int tc_wordswapon; /* Default value is always false */
++
++#ifdef CONFIG_PM
++struct omap34xx_bridge_suspend_data {
++ int suspended;
++ wait_queue_head_t suspend_wq;
++};
++
++static struct omap34xx_bridge_suspend_data bridge_suspend_data;
++
++static int omap34xxbridge_suspend_lockout(
++ struct omap34xx_bridge_suspend_data *s, struct file *f)
++{
++ if ((s)->suspended) {
++ if ((f)->f_flags & O_NONBLOCK)
++ return DSP_EDPMSUSPEND;
++ wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
++ }
++ return 0;
++}
++
++#endif
++
++#ifdef DEBUG
++module_param(GT_str, charp, 0);
++MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
++
++module_param(dsp_debug, int, 0);
++MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
++#endif
++
++module_param(driver_major, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
++
++module_param(driver_minor, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
++
++module_param(base_img, charp, 0);
++MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
++
++module_param(shm_size, int, 0);
++MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
++
++module_param(phys_mempool_base, uint, 0);
++MODULE_PARM_DESC(phys_mempool_base,
++ "Physical memory pool base passed to driver");
++
++module_param(phys_mempool_size, uint, 0);
++MODULE_PARM_DESC(phys_mempool_size,
++ "Physical memory pool size passed to driver");
++module_param(tc_wordswapon, int, 0);
++MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_LICENSE("GPL");
++
++static char *driver_name = DRIVER_NAME;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static struct GT_Mask driverTrace;
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static struct file_operations bridge_fops = {
++ .open = bridge_open,
++ .release = bridge_release,
++ .ioctl = bridge_ioctl,
++ .mmap = bridge_mmap,
++};
++
++#ifdef CONFIG_PM
++static u32 timeOut = 1000;
++#ifdef CONFIG_BRIDGE_DVFS
++static struct clk *clk_handle;
++s32 dsp_max_opps = VDD1_OPP3;
++#endif
++
++/* Maximum Opps that can be requested by IVA*/
++/*vdd1 rate table*/
++#ifdef CONFIG_BRIDGE_DVFS
++const struct omap_opp vdd1_rate_table_bridge[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S125M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S250M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S500M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S550M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S600M, VDD1_OPP5, 0},
++};
++#endif
++#endif
++
++struct dspbridge_platform_data *omap_dspbridge_pdata;
++
++u32 vdd1_dsp_freq[6][4] = {
++ {0, 0, 0, 0},
++ /*OPP1*/
++ {0, 90000, 0, 86000},
++ /*OPP2*/
++ {0, 180000, 80000, 170000},
++ /*OPP3*/
++ {0, 360000, 160000, 340000},
++ /*OPP4*/
++ {0, 396000, 325000, 376000},
++ /*OPP5*/
++ {0, 430000, 355000, 430000},
++};
++
++#ifdef CONFIG_BRIDGE_DVFS
++static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
++ void *ptr)
++{
++ PWR_PM_PostScale(PRCM_VDD1, level);
++ return 0;
++}
++
++static struct notifier_block iva_clk_notifier = {
++ .notifier_call = dspbridge_post_scale,
++ NULL,
++};
++#endif
++
++static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
++{
++ int status;
++ u32 initStatus;
++ u32 temp;
++ dev_t dev = 0 ;
++ int result;
++#ifdef CONFIG_BRIDGE_DVFS
++ int i = 0;
++#endif
++ struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
++
++ omap_dspbridge_dev = pdev;
++
++ /* use 2.6 device model */
++ if (driver_major) {
++ dev = MKDEV(driver_major, driver_minor);
++ result = register_chrdev_region(dev, 1, driver_name);
++ } else {
++ result = alloc_chrdev_region(&dev, driver_minor, 1,
++ driver_name);
++ driver_major = MAJOR(dev);
++ }
++
++ if (result < 0) {
++ GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
++ "Can't get Major %d \n", driver_major);
++ return result;
++ }
++
++ bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
++ if (!bridge_device) {
++ result = -ENOMEM;
++ unregister_chrdev_region(dev, 1);
++ return result;
++ }
++ memset(bridge_device, 0, sizeof(struct bridge_dev));
++ cdev_init(&bridge_device->cdev, &bridge_fops);
++ bridge_device->cdev.owner = THIS_MODULE;
++ bridge_device->cdev.ops = &bridge_fops;
++
++ status = cdev_add(&bridge_device->cdev, dev, 1);
++
++ if (status) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Failed to add the bridge device \n");
++ return status;
++ }
++
++ /* udev support */
++ bridge_class = class_create(THIS_MODULE, "ti_bridge");
++
++ if (IS_ERR(bridge_class))
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Error creating bridge class \n");
++
++ device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
++ NULL, "DspBridge");
++
++ GT_init();
++ GT_create(&driverTrace, "LD");
++
++#ifdef DEBUG
++ if (GT_str)
++ GT_set(GT_str);
++#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
++ GT_set("**=67");
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
++
++#ifdef CONFIG_PM
++ /* Initialize the wait queue */
++ if (!status) {
++ bridge_suspend_data.suspended = 0;
++ init_waitqueue_head(&bridge_suspend_data.suspend_wq);
++ }
++#endif
++
++ SERVICES_Init();
++
++ /* Autostart flag. This should be set to true if the DSP image should
++ * be loaded and run during bridge module initialization */
++
++ if (base_img) {
++ temp = true;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
++ strlen(base_img) + 1);
++ } else {
++ temp = false;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
++ }
++ REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
++ strlen(num_procs) + 1);
++
++ if (shm_size >= 0x10000) { /* 64 KB */
++ initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
++ (u8 *)&shm_size, sizeof(shm_size));
++ } else {
++ initStatus = DSP_EINVALIDARG;
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "SHM size must be at least 64 KB\n");
++ }
++ GT_1trace(driverTrace, GT_7CLASS,
++ "requested shm_size = 0x%x\n", shm_size);
++
++ if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
++ phys_mempool_base = pdata->phys_mempool_base;
++ phys_mempool_size = pdata->phys_mempool_size;
++ }
++
++ if (phys_mempool_base > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
++ REG_DWORD, (u8 *)&phys_mempool_base,
++ sizeof(phys_mempool_base));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
++ phys_mempool_base);
++
++ if (phys_mempool_size > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
++ REG_DWORD, (u8 *)&phys_mempool_size,
++ sizeof(phys_mempool_size));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
++ phys_mempool_base);
++ if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
++ MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
++ if (tc_wordswapon) {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
++ (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP,
++ REG_DWORD, (u8 *)&tc_wordswapon,
++ sizeof(tc_wordswapon));
++ }
++ if (DSP_SUCCEEDED(initStatus)) {
++#ifdef CONFIG_BRIDGE_DVFS
++ for (i = 0; i < 6; i++)
++ pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
++
++ clk_handle = clk_get(NULL, "iva2_ck");
++ if (!clk_handle) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get failed to get iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get PASS to get iva2_ck \n");
++ }
++ if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register FAIL for iva2_ck \n");
++ }
++#endif
++ driverContext = DSP_Init(&initStatus);
++ if (DSP_FAILED(initStatus)) {
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "DSP/BIOS Bridge initialization Failed\n");
++ } else {
++ GT_0trace(driverTrace, GT_5CLASS,
++ "DSP/BIOS Bridge driver loaded\n");
++ }
++ }
++
++ DBC_Assert(status == 0);
++ DBC_Assert(DSP_SUCCEEDED(initStatus));
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
++ return status;
++}
++
++static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
++{
++ dev_t devno;
++ bool ret;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
++
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ goto func_cont;
++ }
++ if ((pCtxtclosed->pid == pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse = pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid == pCtxttraverse->pid)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL)
++ PROC_Detach(pCtxtclosed->hProcessor);
++ }
++func_cont:
++ pTmp = pCtxtclosed->next;
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed, (void *)pCtxtclosed->pid);
++ pCtxtclosed = pTmp;
++ }
++
++ /* unregister the clock notifier */
++#ifdef CONFIG_BRIDGE_DVFS
++ if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ }
++
++ clk_put(clk_handle);
++ clk_handle = NULL;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++
++ if (driverContext) {
++ ret = DSP_Deinit(driverContext);
++ driverContext = 0;
++
++ DBC_Assert(ret == true);
++ }
++ SERVICES_Exit();
++ GT_exit();
++
++ devno = MKDEV(driver_major, driver_minor);
++ if (bridge_device) {
++ cdev_del(&bridge_device->cdev);
++ kfree(bridge_device);
++ }
++ unregister_chrdev_region(devno, 1);
++ if (bridge_class) {
++ /* remove the device from sysfs */
++ device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
++ class_destroy(bridge_class);
++
++ }
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ u32 status;
++ u32 command = PWR_EMERGENCYDEEPSLEEP;
++
++ status = PWR_SleepDSP(command, timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 1;
++ return 0;
++}
++
++static int bridge_resume(struct platform_device *pdev)
++{
++ u32 status;
++
++ status = PWR_WakeDSP(timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 0;
++ wake_up(&bridge_suspend_data.suspend_wq);
++ return 0;
++}
++#else
++#define bridge_suspend NULL
++#define bridge_resume NULL
++#endif
++
++static struct platform_driver bridge_driver = {
++ .driver = {
++ .name = BRIDGE_NAME,
++ },
++ .probe = omap34xx_bridge_probe,
++ .remove = __devexit_p(omap34xx_bridge_remove),
++ .suspend = bridge_suspend,
++ .resume = bridge_resume,
++};
++
++static int __init bridge_init(void)
++{
++ return platform_driver_register(&bridge_driver);
++}
++
++static void __exit bridge_exit(void)
++{
++ platform_driver_unregister(&bridge_driver);
++}
++
++/* This function is called when an application opens handle to the
++ * bridge driver. */
++
++static int bridge_open(struct inode *ip, struct file *filp)
++{
++ int status = 0;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ struct PROCESS_CONTEXT *next_node = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++ struct task_struct *tsk = NULL;
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++
++ /* Checking weather task structure for all process existing
++ * in the process context list If not removing those processes*/
++ if (DSP_FAILED(dsp_status))
++ goto func_cont;
++
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ tsk = find_task_by_vpid(pCtxtclosed->pid);
++ next_node = pCtxtclosed->next;
++
++ if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
++
++ GT_1trace(driverTrace, GT_5CLASS,
++ "***Task structure not existing for "
++ "process***%d\n", pCtxtclosed->pid);
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ } else {
++ if ((pCtxtclosed->pid ==
++ pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid ==
++ pCtxttraverse->pid)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL) {
++ PROC_Detach
++ (pCtxtclosed->hProcessor);
++ }
++ }
++ }
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed,
++ (void *)pCtxtclosed->pid);
++ }
++ pCtxtclosed = next_node;
++ }
++func_cont:
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(dsp_status))
++ dsp_status = DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject, &pPctxt);
++
++ if (pPctxt != NULL) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
++ return status;
++}
++
++/* This function is called when an application closes handle to the bridge
++ * driver. */
++static int bridge_release(struct inode *ip, struct file *filp)
++{
++ int status;
++ u32 pid;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
++
++ /* Return PID instead of process handle */
++ pid = current->pid;
++
++ status = DSP_Close(pid);
++
++
++ (status == true) ? (status = 0) : (status = -1);
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
++
++ return status;
++}
++
++/* This function provides IO interface to the bridge driver. */
++static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
++ unsigned long args)
++{
++ int status;
++ u32 retval = DSP_SOK;
++ union Trapped_Args pBufIn;
++
++ DBC_Require(filp != NULL);
++#ifdef CONFIG_PM
++ status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
++ if (status != 0)
++ return status;
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
++
++ /* Deduct one for the CMD_BASE. */
++ code = (code - 1);
++
++ status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
++ sizeof(union Trapped_Args));
++
++ if (status >= 0) {
++ status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = retval;
++ } else {
++ GT_1trace(driverTrace, GT_7CLASS,
++ "IOCTL Failed, code : 0x%x\n", code);
++ status = -1;
++ }
++
++ }
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
++
++ return status;
++}
++
++/* This function maps kernel space memory to user space memory. */
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++#if GT_TRACE
++ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
++#endif
++ u32 status;
++
++ DBC_Assert(vma->vm_start < vma->vm_end);
++
++ vma->vm_flags |= VM_RESERVED | VM_IO;
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++ GT_6trace(driverTrace, GT_3CLASS,
++ "vm filp %p offset %lx start %lx end %lx"
++ " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
++ vma->vm_end, vma->vm_page_prot, vma->vm_flags);
++
++ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot);
++ if (status != 0)
++ status = -EAGAIN;
++
++ return status;
++}
++
++#ifndef RES_CLEANUP_DISABLE
++/* To remove all process resources before removing the process from the
++ * process context list*/
++DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ if (pCtxt != NULL) {
++ DRV_RemoveAllSTRMResElements(pCtxt);
++ DRV_RemoveAllNodeResElements(pCtxt);
++ DRV_RemoveAllDMMResElements(pCtxt);
++ DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
++ }
++ return status;
++}
++#endif
++
++/* Bridge driver initialization and de-initialization functions */
++module_init(bridge_init);
++module_exit(bridge_exit);
++
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
+new file mode 100644
+index 0000000..f5b068e
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.h
+@@ -0,0 +1,40 @@
++/*
++ * drv_interface.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv_interface.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Added hooks for Power Management Test
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 sb Created initial version
++
++ */
++
++#ifndef _DRV_INTERFACE_H_
++#define _DRV_INTERFACE_H_
++
++/* Prototypes for all functions in this bridge */
++static int __init bridge_init(void); /* Initialize bridge */
++static void __exit bridge_exit(void); /* Opposite of initialize */
++static int bridge_open(struct inode *, struct file *); /* Open */
++static int bridge_release(struct inode *, struct file *); /* Release */
++static int bridge_ioctl(struct inode *, struct file *, unsigned int,
++ unsigned long);
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
++#endif /* ifndef _DRV_INTERFACE_H_ */
+diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
+new file mode 100644
+index 0000000..a7a74fc
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dspdrv.c
+@@ -0,0 +1,276 @@
++/*
++ * dspdrv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.c ========
++ * Description:
++ * Interface to allocate and free bridge resources.
++ *
++ *! Revision History
++ *! ================
++ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
++ *! 09-Feb-2004 vp: Updated to support IVA.
++ *! 10-Feb-2003 vp: Code review updates.
++ *! 18-oct-2002 vp: Ported to the Linux platform.
++ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
++ *! before calling MGR_Destroy.
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
++ *! sllowing the class driver to load irrespective of
++ *! the image load.
++ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
++ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
++ *! Failure in WCD_InitComplete2 will cause the
++ *! DSP_Init to fail.
++ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
++ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
++ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
++ *! DevObjects. Static variables removed. Returns
++ *! the Driver Object in DSP_Init.
++ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
++ *! the list of Device objects.
++ *! 07-Jul-2000 rr: RM implementaion started.
++ *! 24-May-2000 ag: Cleaned up debug msgs.
++ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
++ *! 03-Feb-2000 rr: GT Changes.
++ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
++ *! DSP_Deinit checks return values.dwCode in
++ *! DSP_IO_CONTROL is decoded(not hard coded)
++ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
++ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
++ *! 29-Dec-1999 rr: Code Cleaned up
++ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
++ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and ArrayofInstalledDev
++ *! is Global.DevObject stores this pointer as hDevNode.
++ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
++ *! Comments changed.Deinit handled.Code cleaned up.
++ *! DSP_IOControl, Close, Deinit returns bool values.
++ *! Calls WCD_InitComplete2 for Board AutoStart.
++ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
++ *! Global Arrays keeps track of installed devices.
++ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
++ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
++ *! for multiple mini driver support.PCCARD flag
++ *! checking to include PCMCIA related stuff.
++ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
++ *! return value initalized to S_OK upfront in the
++ *! Process Attach.
++ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
++ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
++ *! DRV_Request Resources is used instead of the
++ *! RegisterMiniDriver as it sounds close to what we are doing.
++ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
++ *! neccessaryPCMCIA fxns are here. Soon they will move out
++ *! either to a seperate file for bus specific inits.
++ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the driver structure as
++ *! - This is the Class driver. After successfully initialized
++ *! the Class driver will attempt to load the Mini driver.
++ *! - Need to seperate the PCMCIA stuff based on bus type.
++ *! - Changed the name of the file to wcdce.c
++ *! - Made the Media Handle as Global again
++ *!
++ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
++ *! Modified the DSP_Init, now three windows are opened.
++ *! Split the driver into PDD so that hardware dependent
++ *! functions will reside in PDD.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet card driver.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/_dcd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dspdrv.h>
++
++/* ----------------------------------- Globals */
++struct GT_Mask curTrace;
++
++/*
++ * ======== DSP_Init ========
++ * Allocates bridge resources. Loads a base image onto DSP, if specified.
++ */
++u32 DSP_Init(OUT u32 *initStatus)
++{
++ char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *drvObject = NULL;
++ u32 index = 0;
++ u32 deviceNode;
++ u32 deviceNodeString;
++
++ GT_create(&curTrace, "DD");
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
++
++ if (DSP_FAILED(WCD_Init())) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
++ goto func_cont;
++ } /* End WCD_Exit */
++ if (DSP_FAILED(DRV_Create(&drvObject))) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
++ WCD_Exit();
++ goto func_cont;
++ } /* End DRV_Create */
++ GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
++
++ /* Request Resources */
++ if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
++ &deviceNodeString))) {
++ /* Attempt to Start the Device */
++ if (DSP_SUCCEEDED(DEV_StartDevice(
++ (struct CFG_DEVNODE *)deviceNodeString))) {
++ /* Retreive the DevObject from the Registry */
++ GT_2trace(curTrace, GT_1CLASS,
++ "DSP_Init Succeeded for Device1:"
++ "%d: value: %x\n", index, deviceNodeString);
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DEV_StartDevice Failed\n");
++ (void)DRV_ReleaseResources
++ ((u32) deviceNodeString, drvObject);
++ status = DSP_EFAIL;
++ }
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DRV_RequestResources Failed \r\n");
++ status = DSP_EFAIL;
++ } /* DRV_RequestResources */
++ index++;
++
++ /* Unwind whatever was loaded */
++ if (DSP_FAILED(status)) {
++ /* irrespective of the status of DEV_RemoveDevice we conitinue
++ * unloading. Get the Driver Object iterate through and remove.
++ * Reset the status to E_FAIL to avoid going through
++ * WCD_InitComplete2. */
++ status = DSP_EFAIL;
++ for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
++ deviceNode = DRV_GetNextDevExtension(deviceNode)) {
++ (void)DEV_RemoveDevice
++ ((struct CFG_DEVNODE *)deviceNode);
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ drvObject);
++ }
++ /* Remove the Driver Object */
++ (void)DRV_Destroy(drvObject);
++ drvObject = NULL;
++ WCD_Exit();
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:Logical device Failed to Load\n");
++ } /* Unwinding the loaded drivers */
++func_cont:
++ /* Attempt to Start the Board */
++ if (DSP_SUCCEEDED(status)) {
++ /* BRD_AutoStart could fail if the dsp execuetable is not the
++ * correct one. We should not propagate that error
++ * into the device loader. */
++ (void)WCD_InitComplete2();
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
++ } /* End WCD_InitComplete2 */
++ DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) ||
++ (DSP_FAILED(status) && drvObject == NULL));
++ *initStatus = status;
++ /* Return the Driver Object */
++ return (u32)drvObject;
++}
++
++/*
++ * ======== DSP_Deinit ========
++ * Frees the resources allocated for bridge.
++ */
++bool DSP_Deinit(u32 deviceContext)
++{
++ bool retVal = true;
++ u32 deviceNode;
++ struct MGR_OBJECT *mgrObject = NULL;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
++
++ while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
++ (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
++
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ (struct DRV_OBJECT *)deviceContext);
++ }
++
++ (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
++
++ /* Get the Manager Object from Registry
++ * MGR Destroy will unload the DCD dll */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
++ (void)MGR_Destroy(mgrObject);
++
++ WCD_Exit();
++
++ return retVal;
++}
++
++/*
++ * ======== DSP_Close ========
++ * The Calling Process handle is passed to DEV_CleanupProcesState
++ * for cleaning up of any resources used by the application
++ */
++bool DSP_Close(u32 dwOpenContext)
++{
++ bool retVal = false;
++
++ DBC_Require(dwOpenContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
++
++#ifdef RES_CLEANUP_DISABLE
++
++ if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
++ retVal = true;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
++ }
++#endif
++
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
+new file mode 100644
+index 0000000..943cf93
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/mgr.c
+@@ -0,0 +1,491 @@
++/*
++ * mgr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.c ========
++ * Description:
++ * Implementation of Manager interface to the device object at the
++ * driver level. This queries the NDB data base and retrieves the
++ * data about Node and Processor.
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
++ *! 03-Nov-2000 rr: Updated after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
++ *! as it is taken care by MEM_AllocObject. stdwin.h added
++ *! for retail build to succeed.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
++ *! 20-Jun-2000 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define ZLDLLNAME ""
++#define SIGNATURE 0x5f52474d /* "MGR_" (in reverse) */
++
++struct MGR_OBJECT {
++ u32 dwSignature;
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MGR_DebugMask = { NULL, NULL };
++#endif
++
++static u32 cRefs;
++
++/*
++ * ========= MGR_Create =========
++ * Purpose:
++ * MGR Object gets created only once during driver Loading.
++ */
++DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
++ struct CFG_DEVNODE *hDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(phMgrObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Create phMgrObject 0x%x\n ",
++ phMgrObject);
++ MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
++ if (pMgrObject) {
++ if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
++ &pMgrObject->hDcdMgr))) {
++ /* If succeeded store the handle in the MGR Object */
++ if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
++ REG_MGR_OBJECT))) {
++ *phMgrObject = pMgrObject;
++ GT_0trace(MGR_DebugMask, GT_1CLASS,
++ "MGR_Create:MGR Created\r\n");
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:CFG_SetObject "
++ "Failed\r\n");
++ DCD_DestroyManager(pMgrObject->hDcdMgr);
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ /* failed to Create DCD Manager */
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:DCD_ManagerCreate Failed\r\n");
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create DSP_FAILED to allocate memory \n");
++ }
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Create: phMgrObject: 0x%x\t"
++ "status: 0x%x\n", phMgrObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ========= MGR_Destroy =========
++ * This function is invoked during bridge driver unloading.Frees MGR object.
++ */
++DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
++ /* Free resources */
++ if (hMgrObject->hDcdMgr)
++ DCD_DestroyManager(hMgrObject->hDcdMgr);
++
++ MEM_FreeObject(pMgrObject);
++ /* Update the Registry with NULL for MGR Object */
++ (void)CFG_SetObject(0, REG_MGR_OBJECT);
++
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
++ "status: 0x%x\n", hMgrObject, status);
++
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ */
++DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize, OUT u32 *puNumNodes)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_UUID Uuid, uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uNodeIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(pNDBProps != NULL);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
++ "args:\n\t uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, puNumNodes);
++ *puNumNodes = 0;
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo:Failed To Get"
++ " MGR Object from Registry\r\n");
++ goto func_cont;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit failed or no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status == DSP_SOK) {
++ status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
++ &uTempUuid);
++ if (status == DSP_SOK) {
++ uNodeIndex++;
++ if (uNode == (uNodeIndex - 1))
++ Uuid = uTempUuid;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uNode > (uNodeIndex - 1)) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: uNode"
++ " is Invalid \r\n");
++ } else {
++ status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&Uuid,
++ DSP_DCDNODETYPE, &GenObj);
++ if (DSP_SUCCEEDED(status1)) {
++ /* Get the Obj def */
++ *pNDBProps = GenObj.objData.nodeObj.ndbProps;
++ *puNumNodes = uNodeIndex;
++ status = DSP_SOK;
++ } else {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: "
++ "Failed to Get Node Info \r\n");
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* This could be changed during enum, EFAIL ... */
++ GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
++ "Enumeration failure\r\n");
++ status = DSP_EFAIL;
++ }
++func_cont:
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Exiting Manager_EnumNodeInfo, args:\n\t"
++ "uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, *puNumNodes);
++ DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
++ (DSP_FAILED(status) && *puNumNodes == 0));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Enumerate and get configuration information about available
++ * DSP processors.
++ */
++DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *pProcessorInfo,
++ u32 uProcessorInfoSize, OUT u32 *puNumProcs)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ DSP_STATUS status2 = DSP_SOK;
++ struct DSP_UUID uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uProcIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++ struct MGR_PROCESSOREXTINFO *pExtInfo;
++ struct DEV_OBJECT *hDevObject;
++ struct DRV_OBJECT *hDrvObject;
++ s32 devType;
++ struct CFG_DEVNODE *devNode;
++ struct CFG_DSPRES chipResources;
++ bool procDetect = false;
++
++ DBC_Require(pProcessorInfo != NULL);
++ DBC_Require(puNumProcs != NULL);
++ DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Entered Manager_EnumProcessorInfo, "
++ "args:\n\tuProcessor: 0x%x\n\tpProcessorInfo: 0x%x\n\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
++ pProcessorInfo, uProcessorInfoSize, puNumProcs);
++ *puNumProcs = 0;
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, (u32 *) &devType);
++ status = DEV_GetDevNode(hDevObject, &devNode);
++ if (devType == DSP_UNIT) {
++ status = CFG_GetDSPResources(devNode,
++ &chipResources);
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Unsupported dev type gotten"
++ "from device object %d\n", devType);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed To Get MGR Object from Registry\r\n");
++ goto func_end;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status1 == DSP_SOK) {
++ status1 = DCD_EnumerateObject(uTempIndex++,
++ DSP_DCDPROCESSORTYPE,
++ &uTempUuid);
++ if (status1 != DSP_SOK)
++ break;
++
++ uProcIndex++;
++ /* Get the Object properties to find the Device/Processor
++ * Type */
++ if (procDetect != false)
++ continue;
++
++ status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&uTempUuid,
++ DSP_DCDPROCESSORTYPE,
++ &GenObj);
++ if (DSP_SUCCEEDED(status2)) {
++ /* Get the Obj def */
++ if (uProcessorInfoSize <
++ sizeof(struct MGR_PROCESSOREXTINFO)) {
++ *pProcessorInfo = GenObj.objData.procObj;
++ } else {
++ /* extended info */
++ pExtInfo = (struct MGR_PROCESSOREXTINFO *)
++ pProcessorInfo;
++ *pExtInfo = GenObj.objData.extProcObj;
++ }
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Got"
++ " Proctype from DCD %x \r\n",
++ pProcessorInfo->uProcessorType);
++ /* See if we got the needed processor */
++ if (devType == DSP_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ DSPPROCTYPE_C64)
++ procDetect = true;
++ } else if (devType == IVA_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ IVAPROCTYPE_ARM7)
++ procDetect = true;
++ }
++ /* User applciatiuons aonly check for chip type, so
++ * this clumsy overwrite */
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ } else {
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed to Get DCD Processor Info %x \r\n",
++ status2);
++ status = DSP_EFAIL;
++ }
++ }
++ *puNumProcs = uProcIndex;
++ if (procDetect == false) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Failed"
++ " to get Proc info from DCD , so use CFG registry\n");
++ pProcessorInfo->uProcessorType = chipResources.uChipType;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== MGR_Exit ========
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void MGR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ if (cRefs == 0)
++ DCD_Exit();
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Retrieves the MGR handle. Accessor Function.
++ */
++DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
++ OUT u32 *phDCDHandle)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDCDHandle != NULL);
++
++ *phDCDHandle = (u32)NULL;
++ if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
++ *phDCDHandle = (u32) pMgrObject->hDcdMgr;
++ status = DSP_SOK;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
++ (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
++
++ return status;
++}
++
++/*
++ * ======== MGR_Init ========
++ * Initialize MGR's private state, keeping a reference count on each call.
++ */
++bool MGR_Init(void)
++{
++ bool fRetval = true;
++ bool fInitDCD = false;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ /* Set the Trace mask */
++ DBC_Assert(!MGR_DebugMask.flags);
++
++ GT_create(&MGR_DebugMask, "MG"); /* "MG" for Manager */
++ fInitDCD = DCD_Init(); /* DCD Module */
++
++ if (!fInitDCD) {
++ fRetval = false;
++ GT_0trace(MGR_DebugMask, GT_6CLASS,
++ "MGR_Init failed\n");
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Block on any Bridge event(s)
++ */
++DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
++ u32 uCount, OUT u32 *puIndex, u32 uTimeout)
++{
++ DSP_STATUS status;
++ struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
++ u32 i;
++
++ DBC_Require(uCount < MAX_EVENTS);
++
++ for (i = 0; i < uCount; i++)
++ hSyncEvents[i] = aNotifications[i]->handle;
++
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
++ puIndex);
++
++ return status;
++
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
+new file mode 100644
+index 0000000..f3c429c
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/nldr.c
+@@ -0,0 +1,1967 @@
++/*
++ * nldr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.c ========
++ * Description:
++ * DSP/BIOS Bridge dynamic + overlay Node loader.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Removed references to dead DLDR module
++ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
++ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
++ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
++ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
++ *! sections > 1024 bytes.
++ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
++ *! libs for symbols
++ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
++ *! correct deallocation
++ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
++ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++#ifdef DEBUG
++#include <dspbridge/dbg.h>
++#endif
++
++/* OS adaptation layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Platform manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++
++/* Resource manager */
++#include <dspbridge/dbll.h>
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/uuidutil.h>
++
++#include <dspbridge/nldr.h>
++
++#define NLDR_SIGNATURE 0x52444c4e /* "RDLN" */
++#define NLDR_NODESIGNATURE 0x4e444c4e /* "NDLN" */
++
++/* Name of section containing dynamic load mem */
++#define DYNMEMSECT ".dspbridge_mem"
++
++/* Name of section containing dependent library information */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* Max depth of recursion for loading node's dependent libraries */
++#define MAXDEPTH 5
++
++/* Max number of persistent libraries kept by a node */
++#define MAXLIBS 5
++
++/*
++ * Defines for extracting packed dynamic load memory requirements from two
++ * masks.
++ * These defines must match node.cdb and dynm.cdb
++ * Format of data/code mask is:
++ * uuuuuuuu|fueeeeee|fudddddd|fucccccc|
++ * where
++ * u = unused
++ * cccccc = prefered/required dynamic mem segid for create phase data/code
++ * dddddd = prefered/required dynamic mem segid for delete phase data/code
++ * eeeeee = prefered/req. dynamic mem segid for execute phase data/code
++ * f = flag indicating if memory is preferred or required:
++ * f = 1 if required, f = 0 if preferred.
++ *
++ * The 6 bits of the segid are interpreted as follows:
++ *
++ * If the 6th bit (bit 5) is not set, then this specifies a memory segment
++ * between 0 and 31 (a maximum of 32 dynamic loading memory segments).
++ * If the 6th bit (bit 5) is set, segid has the following interpretation:
++ * segid = 32 - Any internal memory segment can be used.
++ * segid = 33 - Any external memory segment can be used.
++ * segid = 63 - Any memory segment can be used (in this case the
++ * required/preferred flag is irrelevant).
++ *
++ */
++/* Maximum allowed dynamic loading memory segments */
++#define MAXMEMSEGS 32
++
++#define MAXSEGID 3 /* Largest possible (real) segid */
++#define MEMINTERNALID 32 /* Segid meaning use internal mem */
++#define MEMEXTERNALID 33 /* Segid meaning use external mem */
++#define NULLID 63 /* Segid meaning no memory req/pref */
++#define FLAGBIT 7 /* 7th bit is pref./req. flag */
++#define SEGMASK 0x3f /* Bits 0 - 5 */
++
++#define CREATEBIT 0 /* Create segid starts at bit 0 */
++#define DELETEBIT 8 /* Delete segid starts at bit 8 */
++#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */
++
++/*
++ * Masks that define memory type. Must match defines in dynm.cdb.
++ */
++#define DYNM_CODE 0x2
++#define DYNM_DATA 0x4
++#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
++#define DYNM_INTERNAL 0x8
++#define DYNM_EXTERNAL 0x10
++
++/*
++ * Defines for packing memory requirement/preference flags for code and
++ * data of each of the node's phases into one mask.
++ * The bit is set if the segid is required for loading code/data of the
++ * given phase. The bit is not set, if the segid is preferred only.
++ *
++ * These defines are also used as indeces into a segid array for the node.
++ * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
++ * create phase data is required or preferred to be loaded into.
++ */
++#define CREATEDATAFLAGBIT 0
++#define CREATECODEFLAGBIT 1
++#define EXECUTEDATAFLAGBIT 2
++#define EXECUTECODEFLAGBIT 3
++#define DELETEDATAFLAGBIT 4
++#define DELETECODEFLAGBIT 5
++#define MAXFLAGS 6
++
++#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
++ (segid) == MEMINTERNALID)
++
++#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
++ (segid) == MEMEXTERNALID)
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++ /*
++ * These names may be embedded in overlay sections to identify which
++ * node phase the section should be overlayed.
++ */
++#define PCREATE "create"
++#define PDELETE "delete"
++#define PEXECUTE "execute"
++
++#define IsEqualUUID(uuid1, uuid2) (\
++ ((uuid1).ulData1 == (uuid2).ulData1) && \
++ ((uuid1).usData2 == (uuid2).usData2) && \
++ ((uuid1).usData3 == (uuid2).usData3) && \
++ ((uuid1).ucData4 == (uuid2).ucData4) && \
++ ((uuid1).ucData5 == (uuid2).ucData5) && \
++ (strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
++
++ /*
++ * ======== MemInfo ========
++ * Format of dynamic loading memory segment info in coff file.
++ * Must match dynm.h55.
++ */
++struct MemInfo {
++ u32 segid; /* Dynamic loading memory segment number */
++ u32 base;
++ u32 len;
++ u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
++};
++
++/*
++ * ======== LibNode ========
++ * For maintaining a tree of library dependencies.
++ */
++struct LibNode {
++ struct DBLL_LibraryObj *lib; /* The library */
++ u16 nDepLibs; /* Number of dependent libraries */
++ struct LibNode *pDepLibs; /* Dependent libraries of lib */
++};
++
++/*
++ * ======== OvlySect ========
++ * Information needed to overlay a section.
++ */
++struct OvlySect {
++ struct OvlySect *pNextSect;
++ u32 loadAddr; /* Load address of section */
++ u32 runAddr; /* Run address of section */
++ u32 size; /* Size of section */
++ u16 page; /* DBL_CODE, DBL_DATA */
++};
++
++/*
++ * ======== OvlyNode ========
++ * For maintaining a list of overlay nodes, with sections that need to be
++ * overlayed for each of the nodes phases.
++ */
++struct OvlyNode {
++ struct DSP_UUID uuid;
++ char *pNodeName;
++ struct OvlySect *pCreateSects;
++ struct OvlySect *pDeleteSects;
++ struct OvlySect *pExecuteSects;
++ struct OvlySect *pOtherSects;
++ u16 nCreateSects;
++ u16 nDeleteSects;
++ u16 nExecuteSects;
++ u16 nOtherSects;
++ u16 createRef;
++ u16 deleteRef;
++ u16 executeRef;
++ u16 otherRef;
++};
++
++/*
++ * ======== NLDR_OBJECT ========
++ * Overlay loader object.
++ */
++struct NLDR_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DBLL_TarObj *dbll; /* The DBL loader */
++ struct DBLL_LibraryObj *baseLib; /* Base image library */
++ struct RMM_TargetObj *rmm; /* Remote memory manager for DSP */
++ struct DBLL_Fxns dbllFxns; /* Loader function table */
++ struct DBLL_Attrs dbllAttrs; /* attrs to pass to loader functions */
++ NLDR_OVLYFXN ovlyFxn; /* "write" for overlay nodes */
++ NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
++ struct OvlyNode *ovlyTable; /* Table of overlay nodes */
++ u16 nOvlyNodes; /* Number of overlay nodes in base */
++ u16 nNode; /* Index for tracking overlay nodes */
++ u16 nSegs; /* Number of dynamic load mem segs */
++ u32 *segTable; /* memtypes of dynamic memory segs
++ * indexed by segid
++ */
++ u16 usDSPMauSize; /* Size of DSP MAU */
++ u16 usDSPWordSize; /* Size of DSP word */
++};
++
++/*
++ * ======== NLDR_NODEOBJECT ========
++ * Dynamic node object. This object is created when a node is allocated.
++ */
++struct NLDR_NODEOBJECT {
++ u32 dwSignature; /* For object validation */
++ struct NLDR_OBJECT *pNldr; /* Dynamic loader handle */
++ void *pPrivRef; /* Handle to pass to DBL_WriteFxn */
++ struct DSP_UUID uuid; /* Node's UUID */
++ bool fDynamic; /* Dynamically loaded node? */
++ bool fOverlay; /* Overlay node? */
++ bool *pfPhaseSplit; /* Multiple phase libraries? */
++ struct LibNode root; /* Library containing node phase */
++ struct LibNode createLib; /* Library containing create phase lib */
++ struct LibNode executeLib; /* Library containing execute phase lib */
++ struct LibNode deleteLib; /* Library containing delete phase lib */
++ struct LibNode persLib[MAXLIBS]; /* libs remain loaded until Delete */
++ s32 nPersLib; /* Number of persistent libraries */
++ /* Path in lib dependency tree */
++ struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
++ enum NLDR_PHASE phase; /* Node phase currently being loaded */
++
++ /*
++ * Dynamic loading memory segments for data and code of each phase.
++ */
++ u16 segId[MAXFLAGS];
++
++ /*
++ * Mask indicating whether each mem segment specified in segId[]
++ * is preferred or required.
++ * For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
++ * then it is required to load execute phase data into the memory
++ * specified by segId[EXECUTEDATAFLAGBIT].
++ */
++ u32 codeDataFlagMask;
++};
++
++/* Dynamic loader function table */
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static struct GT_Mask NLDR_debugMask = { NULL, NULL }; /* GT trace variable */
++static u32 cRefs; /* module reference count */
++
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes);
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes);
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype);
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc);
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *symName, struct DBLL_Symbol **sym);
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth);
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve);
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve);
++
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib);
++static u32 findLcm(u32 a, u32 b);
++static u32 findGcf(u32 a, u32 b);
++
++/*
++ * ======== NLDR_Allocate ========
++ */
++DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit)
++{
++ struct NLDR_NODEOBJECT *pNldrNode = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pNodeProps != NULL);
++ DBC_Require(phNldrNode != NULL);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
++ "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
++ pfPhaseSplit);
++
++ /* Initialize handle in case of failure */
++ *phNldrNode = NULL;
++ /* Allocate node object */
++ MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
++
++ if (pNldrNode == NULL) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pNldrNode->pfPhaseSplit = pfPhaseSplit;
++ pNldrNode->nPersLib = 0;
++ pNldrNode->pNldr = hNldr;
++ pNldrNode->pPrivRef = pPrivRef;
++ /* Save node's UUID. */
++ pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
++ /*
++ * Determine if node is a dynamically loaded node from
++ * ndbProps.
++ */
++ if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
++ /* Dynamic node */
++ pNldrNode->fDynamic = true;
++ /*
++ * Extract memory requirements from ndbProps masks
++ */
++ /* Create phase */
++ pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATEDATAFLAGBIT;
++ pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ CREATEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATECODEFLAGBIT;
++ /* Execute phase */
++ pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTEDATAFLAGBIT;
++ pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTECODEFLAGBIT;
++ /* Delete phase */
++ pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETEDATAFLAGBIT;
++ pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ DELETEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETECODEFLAGBIT;
++ } else {
++ /* Non-dynamically loaded nodes are part of the
++ * base image */
++ pNldrNode->root.lib = hNldr->baseLib;
++ /* Check for overlay node */
++ if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
++ pNldrNode->fOverlay = true;
++
++ }
++ *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
++ }
++ /* Cleanup on failure */
++ if (DSP_FAILED(status) && pNldrNode)
++ NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
++ NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
++ *phNldrNode == NULL));
++ return status;
++}
++
++/*
++ * ======== NLDR_Create ========
++ */
++DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager */
++ char *pszCoffBuf = NULL;
++ char szZLFile[COD_MAXPATHLENGTH];
++ struct NLDR_OBJECT *pNldr = NULL;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DBLL_Flags flags;
++ u32 ulEntry;
++ u16 nSegs = 0;
++ struct MemInfo *pMemInfo;
++ u32 ulLen = 0;
++ u32 ulAddr;
++ struct RMM_Segment *rmmSegs = NULL;
++ u16 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNldr != NULL);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pAttrs->pfnOvly != NULL);
++ DBC_Require(pAttrs->pfnWrite != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
++ phNldr, hDevObject, pAttrs);
++ /* Allocate dynamic loader object */
++ MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
++ if (pNldr) {
++ pNldr->hDevObject = hDevObject;
++ /* warning, lazy status checking alert! */
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetLoader(hCodMgr, &pNldr->dbll);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = DSP_SOK;
++ /* end lazy status checking */
++ pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
++ pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
++ pNldr->dbllFxns = dbllFxns;
++ if (!(pNldr->dbllFxns.initFxn()))
++ status = DSP_EMEMORY;
++
++ } else {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status))
++ status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
++
++ /* Get dynamic loading memory sections from base lib */
++ if (DSP_SUCCEEDED(status)) {
++ status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
++ &ulAddr, &ulLen);
++ if (DSP_SUCCEEDED(status)) {
++ pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
++ MEM_PAGED);
++ if (!pszCoffBuf) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Ok to not have dynamic loading memory */
++ status = DSP_SOK;
++ ulLen = 0;
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_getSect "
++ "failed (no dynamic loading mem segments): "
++ "0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Read section containing dynamic load mem segments */
++ status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
++ pszCoffBuf, ulLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_read Section"
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Parse memory segment data */
++ nSegs = (u16)(*((u32 *)pszCoffBuf));
++ if (nSegs > MAXMEMSEGS) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Invalid number of "
++ "dynamic load mem segments: 0x%lx\n", nSegs);
++ status = DSP_ECORRUPTFILE;
++ }
++ }
++ /* Parse dynamic load memory segments */
++ if (DSP_SUCCEEDED(status) && nSegs > 0) {
++ rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
++ MEM_PAGED);
++ pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
++ if (rmmSegs == NULL || pNldr->segTable == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNldr->nSegs = nSegs;
++ pMemInfo = (struct MemInfo *)(pszCoffBuf +
++ sizeof(u32));
++ for (i = 0; i < nSegs; i++) {
++ rmmSegs[i].base = (pMemInfo + i)->base;
++ rmmSegs[i].length = (pMemInfo + i)->len;
++ rmmSegs[i].space = 0;
++ pNldr->segTable[i] = (pMemInfo + i)->type;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
++ "Length: 0x%x\n", i, rmmSegs[i].base,
++ rmmSegs[i].length);
++#endif
++ }
++ }
++ }
++ /* Create Remote memory manager */
++ if (DSP_SUCCEEDED(status))
++ status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* set the alloc, free, write functions for loader */
++ pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
++ newAttrs = saveAttrs;
++ newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
++ newAttrs.free = (DBLL_FreeFxn) RemoteFree;
++ newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
++ newAttrs.symHandle = pNldr;
++ newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
++ pNldr->ovlyFxn = pAttrs->pfnOvly;
++ pNldr->writeFxn = pAttrs->pfnWrite;
++ pNldr->dbllAttrs = newAttrs;
++ }
++ if (rmmSegs)
++ MEM_Free(rmmSegs);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ /* Get overlay nodes */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ /* lazy check */
++ DBC_Assert(DSP_SUCCEEDED(status));
++ /* First count number of overlay nodes */
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
++ (void *) pNldr);
++ /* Now build table of overlay nodes */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ /* Allocate table for overlay nodes */
++ pNldr->ovlyTable =
++ MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
++ MEM_PAGED);
++ /* Put overlay nodes in the table */
++ pNldr->nNode = 0;
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
++ AddOvlyNode,
++ (void *) pNldr);
++ }
++ }
++ /* Do a fake reload of the base image to get overlay section info */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ saveAttrs.write = fakeOvlyWrite;
++ saveAttrs.logWrite = AddOvlyInfo;
++ saveAttrs.logWriteHandle = pNldr;
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
++ &saveAttrs, &ulEntry);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phNldr = (struct NLDR_OBJECT *) pNldr;
++ } else {
++ if (pNldr)
++ NLDR_Delete((struct NLDR_OBJECT *) pNldr);
++
++ *phNldr = NULL;
++ }
++ /* FIXME:Temp. Fix. Must be removed */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
++ NLDR_SIGNATURE))
++ || (DSP_FAILED(status) && (*phNldr == NULL)));
++ return status;
++}
++
++/*
++ * ======== NLDR_Delete ========
++ */
++void NLDR_Delete(struct NLDR_OBJECT *hNldr)
++{
++ struct OvlySect *pSect;
++ struct OvlySect *pNext;
++ u16 i;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
++ hNldr->dbllFxns.exitFxn();
++ if (hNldr->rmm)
++ RMM_delete(hNldr->rmm);
++
++ if (hNldr->segTable)
++ MEM_Free(hNldr->segTable);
++
++ if (hNldr->hDcdMgr)
++ DCD_DestroyManager(hNldr->hDcdMgr);
++
++ /* Free overlay node information */
++ if (hNldr->ovlyTable) {
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pSect = hNldr->ovlyTable[i].pCreateSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pDeleteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pExecuteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pOtherSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ }
++ MEM_Free(hNldr->ovlyTable);
++ }
++ MEM_FreeObject(hNldr);
++ DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++}
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ */
++void NLDR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS,
++ "Entered NLDR_Exit, ref count: 0x%x\n", cRefs);
++
++ if (cRefs == 0) {
++ RMM_exit();
++ NLDR_debugMask.flags = NULL;
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NLDR_Free ========
++ */
++void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
++
++ MEM_FreeObject(hNldrNode);
++}
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ */
++DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
++ u32 *pulAddr)
++{
++ struct DBLL_Symbol *pSym;
++ struct NLDR_OBJECT *hNldr;
++ DSP_STATUS status = DSP_SOK;
++ bool status1 = false;
++ s32 i = 0;
++ struct LibNode root = { NULL, 0, NULL };
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ DBC_Require(pulAddr != NULL);
++ DBC_Require(pstrFxn != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
++ hNldrNode, pstrFxn, pulAddr);
++
++ hNldr = hNldrNode->pNldr;
++ /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
++ if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
++ switch (hNldrNode->phase) {
++ case NLDR_CREATE:
++ root = hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ root = hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ root = hNldrNode->deleteLib;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* for Overlay nodes or non-split Dynamic nodes */
++ root = hNldrNode->root;
++ }
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
++ if (!status1)
++ status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
++
++ /* If symbol not found, check dependent libraries */
++ if (!status1) {
++ for (i = 0; i < root.nDepLibs; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
++ lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.
++ pDepLibs[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /* Check persistent libraries */
++ if (!status1) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 =
++ hNldr->dbllFxns.getCAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ if (status1) {
++ *pulAddr = pSym->value;
++ } else {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_GetFxnAddr: Symbol not found: "
++ "%s\n", pstrFxn);
++ status = DSP_ESYMBOL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_GetRmmManager ========
++ * Given a NLDR object, retrieve RMM Manager Handle
++ */
++DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj **phRmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NLDR_OBJECT *pNldrObject = hNldrObject;
++ DBC_Require(phRmmMgr != NULL);
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
++ hNldrObject, phRmmMgr);
++ if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
++ *phRmmMgr = pNldrObject->rmm;
++ } else {
++ *phRmmMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(NLDR_debugMask, GT_7CLASS,
++ "NLDR_GetRmmManager:Invalid handle");
++ }
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
++ "0x%x\n\tphRmmMgr: 0x%x\n", status, *phRmmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
++ (*phRmmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ */
++bool NLDR_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NLDR_debugMask.flags);
++ GT_create(&NLDR_debugMask, "DL"); /* "DL" for DLdr */
++
++ RMM_init();
++ }
++
++ cRefs++;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs > 0);
++ return true;
++}
++
++/*
++ * ======== NLDR_Load ========
++ */
++DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr;
++ struct DSP_UUID libUUID;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ hNldr = hNldrNode->pNldr;
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++
++ if (hNldrNode->fDynamic) {
++ hNldrNode->phase = phase;
++
++ libUUID = hNldrNode->uuid;
++
++ /* At this point, we may not know if node is split into
++ * different libraries. So we'll go ahead and load the
++ * library, and then save the pointer to the appropriate
++ * location after we know. */
++
++ status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
++ hNldrNode->libPath, phase, 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ hNldrNode->createLib = hNldrNode->root;
++ break;
++
++ case NLDR_EXECUTE:
++ hNldrNode->executeLib = hNldrNode->root;
++ break;
++
++ case NLDR_DELETE:
++ hNldrNode->deleteLib = hNldrNode->root;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ }
++ }
++ } else {
++ if (hNldrNode->fOverlay)
++ status = LoadOvly(hNldrNode, phase);
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Unload ========
++ */
++DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct LibNode *pRootLib = NULL;
++ s32 i = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++ if (hNldrNode != NULL) {
++ if (hNldrNode->fDynamic) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ pRootLib = &hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ pRootLib = &hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ pRootLib = &hNldrNode->deleteLib;
++ /* Unload persistent libraries */
++ for (i = 0; i < hNldrNode->nPersLib;
++ i++) {
++ UnloadLib(hNldrNode,
++ &hNldrNode->persLib[i]);
++ }
++ hNldrNode->nPersLib = 0;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* Unload main library */
++ pRootLib = &hNldrNode->root;
++ }
++ UnloadLib(hNldrNode, pRootLib);
++ } else {
++ if (hNldrNode->fOverlay)
++ UnloadOvly(hNldrNode, phase);
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== AddOvlyInfo ========
++ */
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes)
++{
++ char *pNodeName;
++ char *pSectName = (char *)sectInfo->name;
++ bool fExists = false;
++ char seps = ':';
++ char *pch;
++ u16 i;
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Is this an overlay section (load address != run address)? */
++ if (sectInfo->loadAddr == sectInfo->runAddr)
++ goto func_end;
++
++ /* Find the node it belongs to */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pNodeName = hNldr->ovlyTable[i].pNodeName;
++ DBC_Require(pNodeName);
++ if (strncmp(pNodeName, pSectName + 1,
++ strlen(pNodeName)) == 0) {
++ /* Found the node */
++ break;
++ }
++ }
++ if (!(i < hNldr->nOvlyNodes))
++ goto func_end;
++
++ /* Determine which phase this section belongs to */
++ for (pch = pSectName + 1; *pch && *pch != seps; pch++)
++ ;;
++
++ if (*pch) {
++ pch++; /* Skip over the ':' */
++ if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pCreateSects, sectInfo, &fExists, addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nCreateSects++;
++
++ } else
++ if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pDeleteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nDeleteSects++;
++
++ } else
++ if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pExecuteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nExecuteSects++;
++
++ } else {
++ /* Put in "other" sectins */
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pOtherSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nOtherSects++;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlyNode =========
++ * Callback function passed to DCD_GetObjects.
++ */
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ char *pNodeName = NULL;
++ char *pBuf = NULL;
++ u32 uLen;
++ struct DCD_GENERICOBJ objDef;
++ DSP_STATUS status = DSP_SOK;
++
++ if (objType != DSP_DCDNODETYPE)
++ goto func_end;
++
++ status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If overlay node, add to the list */
++ if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
++ if (hNldr->ovlyTable == NULL) {
++ hNldr->nOvlyNodes++;
++ } else {
++ /* Add node to table */
++ hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
++ DBC_Require(objDef.objData.nodeObj.ndbProps.acName);
++ uLen = strlen(objDef.objData.nodeObj.ndbProps.acName);
++ pNodeName = objDef.objData.nodeObj.ndbProps.acName;
++ pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (pBuf == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(pBuf, pNodeName, uLen);
++ hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
++ hNldr->nNode++;
++ }
++ }
++ }
++ /* These were allocated in DCD_GetObjectDef */
++ if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrIAlgName)
++ MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlySect ========
++ */
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes)
++{
++ struct OvlySect *pNewSect = NULL;
++ struct OvlySect *pLastSect;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ pSect = pLastSect = *pList;
++ *pExists = false;
++ while (pSect) {
++ /*
++ * Make sure section has not already been added. Multiple
++ * 'write' calls may be made to load the section.
++ */
++ if (pSect->loadAddr == addr) {
++ /* Already added */
++ *pExists = true;
++ break;
++ }
++ pLastSect = pSect;
++ pSect = pSect->pNextSect;
++ }
++
++ if (!pSect) {
++ /* New section */
++ pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
++ if (pNewSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNewSect->loadAddr = addr;
++ pNewSect->runAddr = pSectInfo->runAddr +
++ (addr - pSectInfo->loadAddr);
++ pNewSect->size = nBytes;
++ pNewSect->page = pSectInfo->type;
++ }
++
++ /* Add to the list */
++ if (DSP_SUCCEEDED(status)) {
++ if (*pList == NULL) {
++ /* First in the list */
++ *pList = pNewSect;
++ } else {
++ pLastSect->pNextSect = pNewSect;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== fakeOvlyWrite ========
++ */
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype)
++{
++ return (s32)nBytes;
++}
++
++/*
++ * ======== FreeSects ========
++ */
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc)
++{
++ struct OvlySect *pSect = pPhaseSects;
++ u16 i = 0;
++ bool fRet;
++
++ while (pSect && i < nAlloc) {
++ /* 'Deallocate' */
++ /* segid - page not supported yet */
++ /* Reserved memory */
++ fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
++ true);
++ DBC_Assert(fRet);
++ pSect = pSect->pNextSect;
++ i++;
++ }
++}
++
++/*
++ * ======== GetSymbolValue ========
++ * Find symbol in library's base image. If not there, check dependent
++ * libraries.
++ */
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *name, struct DBLL_Symbol **sym)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
++ struct LibNode *root = (struct LibNode *)pArg;
++ u16 i;
++ bool status = false;
++
++ /* check the base image */
++ status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
++ if (!status)
++ status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
++
++ /*
++ * Check in root lib itself. If the library consists of
++ * multiple object files linked together, some symbols in the
++ * library may need to be resolved.
++ */
++ if (!status) {
++ status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
++ if (!status) {
++ status =
++ hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
++ }
++ }
++
++ /*
++ * Check in root lib's dependent libraries, but not dependent
++ * libraries' dependents.
++ */
++ if (!status) {
++ for (i = 0; i < root->nDepLibs; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
++ lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn(root->
++ pDepLibs[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /*
++ * Check in persistent libraries
++ */
++ if (!status) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn
++ (hNldrNode->persLib[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadLib ========
++ * Recursively load library and all its dependent libraries. The library
++ * we're loading is specified by a uuid.
++ */
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 nLibs = 0; /* Number of dependent libraries */
++ u16 nPLibs = 0; /* Number of persistent libraries */
++ u16 nLoaded = 0; /* Number of dep. libraries loaded */
++ u16 i;
++ u32 entry;
++ u32 dwBufSize = NLDR_MAXPATHLENGTH;
++ DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
++ struct DBLL_Attrs newAttrs;
++ char *pszFileName = NULL;
++ struct DSP_UUID *depLibUUIDs = NULL;
++ bool *persistentDepLibs = NULL;
++ DSP_STATUS status = DSP_SOK;
++ bool fStatus = false;
++ struct LibNode *pDepLib;
++
++ if (depth > MAXDEPTH) {
++ /* Error */
++ DBC_Assert(false);
++ }
++ root->lib = NULL;
++ /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
++ pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
++ if (pszFileName == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the name of the library */
++ if (depth == 0) {
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, phase,
++ hNldrNode->pfPhaseSplit);
++ } else {
++ /* Dependent libraries are registered with a phase */
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
++ NULL);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Open the library, don't load symbols */
++ status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
++ DBLL_NOLOAD, &root->lib);
++ }
++ /* Done with file name */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ /* Check to see if library not already loaded */
++ if (DSP_SUCCEEDED(status) && rootPersistent) {
++ fStatus = findInPersistentLibArray(hNldrNode, root->lib);
++ /* Close library */
++ if (fStatus) {
++ hNldr->dbllFxns.closeFxn(root->lib);
++ return DSP_SALREADYLOADED;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check for circular dependencies. */
++ for (i = 0; i < depth; i++) {
++ if (root->lib == libPath[i]) {
++ /* This condition could be checked by a
++ * tool at build time. */
++ status = DSP_EDYNLOAD;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Add library to current path in dependency tree */
++ libPath[depth] = root->lib;
++ depth++;
++ /* Get number of dependent libraries */
++ status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
++ &nLibs, &nPLibs, phase);
++ }
++ DBC_Assert(nLibs >= nPLibs);
++ if (DSP_SUCCEEDED(status)) {
++ if (!(*hNldrNode->pfPhaseSplit))
++ nPLibs = 0;
++
++ /* nLibs = #of dependent libraries */
++ root->nDepLibs = nLibs - nPLibs;
++ if (nLibs > 0) {
++ depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
++ nLibs, MEM_PAGED);
++ persistentDepLibs =
++ MEM_Calloc(sizeof(bool) * nLibs, MEM_PAGED);
++ if (!depLibUUIDs || !persistentDepLibs)
++ status = DSP_EMEMORY;
++
++ if (root->nDepLibs > 0) {
++ /* Allocate arrays for dependent lib UUIDs,
++ * lib nodes */
++ root->pDepLibs = MEM_Calloc
++ (sizeof(struct LibNode) *
++ (root->nDepLibs), MEM_PAGED);
++ if (!(root->pDepLibs))
++ status = DSP_EMEMORY;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the dependent library UUIDs */
++ status = DCD_GetDepLibs(hNldrNode->pNldr->
++ hDcdMgr, &uuid, nLibs, depLibUUIDs,
++ persistentDepLibs, phase);
++ }
++ }
++ }
++
++ /*
++ * Recursively load dependent libraries.
++ */
++ if (DSP_SUCCEEDED(status) && persistentDepLibs) {
++ for (i = 0; i < nLibs; i++) {
++ /* If root library is NOT persistent, and dep library
++ * is, then record it. If root library IS persistent,
++ * the deplib is already included */
++ if (!rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ if ((hNldrNode->nPersLib) > MAXLIBS) {
++ status = DSP_EDYNLOAD;
++ break;
++ }
++
++ /* Allocate library outside of phase */
++ pDepLib = &hNldrNode->persLib[hNldrNode->
++ nPersLib];
++ } else {
++ if (rootPersistent)
++ persistentDepLibs[i] = true;
++
++
++ /* Allocate library within phase */
++ pDepLib = &root->pDepLibs[nLoaded];
++ }
++
++ if (depLibUUIDs) {
++ status = LoadLib(hNldrNode, pDepLib,
++ depLibUUIDs[i],
++ persistentDepLibs[i], libPath,
++ phase,
++ depth);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((status != DSP_SALREADYLOADED) &&
++ !rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ (hNldrNode->nPersLib)++;
++ } else {
++ if (!persistentDepLibs[i] ||
++ !(*hNldrNode->pfPhaseSplit)) {
++ nLoaded++;
++ }
++ }
++ } else {
++ break;
++ }
++ }
++ }
++
++ /* Now we can load the root library */
++ if (DSP_SUCCEEDED(status)) {
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.symArg = root;
++ newAttrs.rmmHandle = hNldrNode;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++
++ status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
++ &entry);
++ }
++
++ /*
++ * In case of failure, unload any dependent libraries that
++ * were loaded, and close the root library.
++ * (Persistent libraries are unloaded from the very top)
++ */
++ if (DSP_FAILED(status)) {
++ if (phase != NLDR_EXECUTE) {
++ for (i = 0; i < hNldrNode->nPersLib; i++)
++ UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
++
++ hNldrNode->nPersLib = 0;
++ }
++ for (i = 0; i < nLoaded; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ if (root->lib)
++ hNldr->dbllFxns.closeFxn(root->lib);
++
++ }
++
++ /* Going up one node in the dependency tree */
++ depth--;
++
++ if (depLibUUIDs) {
++ MEM_Free(depLibUUIDs);
++ depLibUUIDs = NULL;
++ }
++
++ if (persistentDepLibs) {
++ MEM_Free(persistentDepLibs);
++ persistentDepLibs = NULL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadOvly ========
++ */
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ u32 nBytes;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pCreateSects;
++ pOtherSects = pONode->pOtherSects;
++ break;
++
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ break;
++
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pPhaseSects = pONode->pDeleteSects;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++
++ DBC_Assert(pRefCount != NULL);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pRefCount == NULL)
++ goto func_end;
++
++ if (*pRefCount != 0)
++ goto func_end;
++
++ /* 'Allocate' memory for overlay sections of this phase */
++ pSect = pPhaseSects;
++ while (pSect) {
++ /* allocate */ /* page not supported yet */
++ /* reserve */ /* align */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
++ &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nAlloc++;
++ } else {
++ break;
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ /* 'Allocate' memory for other overlay sections
++ * (create phase) */
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pOtherSects;
++ while (pSect) {
++ /* page not supported */ /* align */
++ /* reserve */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size,
++ 0, &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nOtherAlloc++;
++ } else {
++ break;
++ }
++ }
++ }
++ }
++ if (*pRefCount == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections for this phase */
++ pSect = pPhaseSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load other sections (create phase) */
++ pSect = pOtherSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++ }
++func_end:
++ if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
++ *pRefCount += 1;
++ if (pOtherRef)
++ *pOtherRef += 1;
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== RemoteAlloc ========
++ */
++static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve)
++{
++ struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
++ struct NLDR_OBJECT *hNldr;
++ struct RMM_TargetObj *rmm;
++ u16 memPhaseBit = MAXFLAGS;
++ u16 segid = 0;
++ u16 i;
++ u16 memType;
++ u32 nWords;
++ struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
++ bool fReq = false;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++ DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
++ DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
++ space == DBLL_BSS);
++ hNldr = hNode->pNldr;
++ rmm = hNldr->rmm;
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++ /* Modify memory 'align' to account for DSP cache line size */
++ align = findLcm(GEM_CACHE_LINE_SIZE, align);
++ GT_1trace(NLDR_debugMask, GT_7CLASS,
++ "RemoteAlloc: memory align to 0x%x \n", align);
++ if (segmentId != -1) {
++ pRmmAddr->segid = segmentId;
++ segid = segmentId;
++ fReq = req;
++ } else {
++ switch (hNode->phase) {
++ case NLDR_CREATE:
++ memPhaseBit = CREATEDATAFLAGBIT;
++ break;
++ case NLDR_DELETE:
++ memPhaseBit = DELETEDATAFLAGBIT;
++ break;
++ case NLDR_EXECUTE:
++ memPhaseBit = EXECUTEDATAFLAGBIT;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (space == DBLL_CODE)
++ memPhaseBit++;
++
++ if (memPhaseBit < MAXFLAGS)
++ segid = hNode->segId[memPhaseBit];
++
++ /* Determine if there is a memory loading requirement */
++ if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
++ fReq = true;
++
++ }
++ memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
++
++ /* Find an appropriate segment based on space */
++ if (segid == NULLID) {
++ /* No memory requirements of preferences */
++ DBC_Assert(!fReq);
++ goto func_cont;
++ }
++ if (segid <= MAXSEGID) {
++ DBC_Assert(segid < hNldr->nSegs);
++ /* Attempt to allocate from segid first. */
++ pRmmAddr->segid = segid;
++ status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc:Unable allocate "
++ "from segment %d.\n", segid);
++ }
++ } else {
++ /* segid > MAXSEGID ==> Internal or external memory */
++ DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
++ /* Check for any internal or external memory segment,
++ * depending on segid.*/
++ memType |= segid == MEMINTERNALID ?
++ DYNM_INTERNAL : DYNM_EXTERNAL;
++ for (i = 0; i < hNldr->nSegs; i++) {
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid for freeing later */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++func_cont:
++ /* Haven't found memory yet, attempt to find any segment that works */
++ if (status == DSP_EMEMORY && !fReq) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc: Preferred segment "
++ "unavailable, trying another segment.\n");
++ for (i = 0; i < hNldr->nSegs; i++) {
++ /* All bits of memType must be set */
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
++ struct RMM_TargetObj *rmm;
++ u32 nWords;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ rmm = hNldr->rmm;
++
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++
++ if (RMM_free(rmm, space, dspAddr, nWords, reserve))
++ status = DSP_SOK;
++
++ return status;
++}
++
++/*
++ * ======== UnloadLib ========
++ */
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
++{
++ struct DBLL_Attrs newAttrs;
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 i;
++
++ DBC_Assert(root != NULL);
++
++ /* Unload dependent libraries */
++ for (i = 0; i < root->nDepLibs; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ root->nDepLibs = 0;
++
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.rmmHandle = hNldr->rmm;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++ newAttrs.symArg = root;
++
++ if (root->lib) {
++ /* Unload the root library */
++ hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
++ hNldr->dbllFxns.closeFxn(root->lib);
++ }
++
++ /* Free dependent library list */
++ if (root->pDepLibs) {
++ MEM_Free(root->pDepLibs);
++ root->pDepLibs = NULL;
++ }
++}
++
++/*
++ * ======== UnloadOvly ========
++ */
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pPhaseSects = pONode->pCreateSects;
++ nAlloc = pONode->nCreateSects;
++ break;
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ nAlloc = pONode->nExecuteSects;
++ break;
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pDeleteSects;
++ /* 'Other' overlay sections are unloaded in the delete phase */
++ pOtherSects = pONode->pOtherSects;
++ nAlloc = pONode->nDeleteSects;
++ nOtherAlloc = pONode->nOtherSects;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pRefCount && (*pRefCount > 0));
++ if (pRefCount && (*pRefCount > 0)) {
++ *pRefCount -= 1;
++ if (pOtherRef) {
++ DBC_Assert(*pOtherRef > 0);
++ *pOtherRef -= 1;
++ }
++ }
++ }
++ if (pRefCount && (*pRefCount == 0)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ }
++ if (pOtherRef && *pOtherRef == 0)
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++
++}
++
++/*
++ * ======== findInPersistentLibArray ========
++ */
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib)
++{
++ s32 i = 0;
++
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ if (lib == hNldrNode->persLib[i].lib)
++ return true;
++
++ }
++
++ return false;
++}
++
++/*
++ * ================ Find LCM (Least Common Multiplier ===
++ */
++static u32 findLcm(u32 a, u32 b)
++{
++ u32 retVal;
++
++ retVal = a * b / findGcf(a, b);
++
++ return retVal;
++}
++
++/*
++ * ================ Find GCF (Greatest Common Factor ) ===
++ */
++static u32 findGcf(u32 a, u32 b)
++{
++ u32 c;
++
++ /* Get the GCF (Greatest common factor between the numbers,
++ * using Euclidian Algo */
++ while ((c = (a % b))) {
++ a = b;
++ b = c;
++ }
++ return b;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
+new file mode 100644
+index 0000000..178b802
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/node.c
+@@ -0,0 +1,3544 @@
++/*
++ * node.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== node.c ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetChannelId
++ * NODE_GetMessage
++ * NODE_GetStrmMgr
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ *! Revision History:
++ *! =================
++ *! 12-Apr-2004 hp Compile IVA only for 24xx
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 07-Apr-2003 map Eliminated references to old DLDR
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in Node_Delete
++ *! function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 06-Feb-2003 kc Fixed FreeStream to release streams correctly.
++ *! 23-Jan-2003 map Removed call to DISP_DoCinit within Write()
++ *! 03-Jan-2003 map Only unload code after phase has executed if
++ *! overlay or split dynload phases
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 06-Nov-2002 map Fixed NODE_Run on NODE_PAUSED bug
++ *! 12-Oct-2002 map Fixed DeleteNode bug in NODE_Create
++ *! 11-Sep-2002 rr DeleteNode frees the memory for strmConnect and dcd obj
++ *! 29-Aug-2002 map Modified Ovly and Write to use ARM-side copy
++ *! 22-May-2002 sg Changed use of cbData for PWR calls.
++ *! 17-May-2002 jeh Removed LoadLoaderFxns(). Get address of RMS_cinit()
++ *! function. Call DISP_DoCinit() from Write(), if .cinit.
++ *! 13-May-2002 sg Added timeout to wake/sleep calls.
++ *! 02-May-2002 sg Added wake/sleep of DSP to support "nap" mode.
++ *! 18-Apr-2002 jeh Use dynamic loader if compile flag is set.
++ *! 13-Feb-2002 jeh Get uSysStackSize from DSP_NDBPROPS.
++ *! 07-Jan-2002 ag STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
++ *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
++ *! 12-Dec-2001 ag Check for valid stream mode in NODE_Connect().
++ *! 04-Dec-2001 jeh Check for node sufficiently connected in NODE_Create().
++ *! 15-Nov-2001 jeh Removed DBC_Require(pNode->hXlator != NULL) from
++ *! NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
++ *! 11-Sep-2001 ag Zero-copy messaging support.
++ *! 28-Aug-2001 jeh Overlay/dynamic loader infrastructure added. Removed
++ *! NODE_GetDispatcher, excess node states.
++ *! 07-Aug-2001 jeh Removed critical section for dispatcher.
++ *! 26-Jul-2001 jeh Get ZL dll name through CFG.
++ *! 05-Jun-2001 jeh Assume DSP_STRMATTRS.uBufsize in GPP bytes.
++ *! 11-May-2001 jeh Some code review cleanup.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 15-Dec-2000 sg Convert IALG_Fxn address from byte addr to word addr.
++ *! 04-Dec-2000 jeh Call MSG Get and Put functions.
++ *! 04-Dec-2000 ag Added SM support for node messaging.
++ *! 10-Nov-2000 rr: NODE_MIN/MAX Priority is defined in dspdefs.h.
++ *! 27-Oct-2000 jeh Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
++ *! 11-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
++ *! NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/disp.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdioctl.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/gb.h>
++#ifdef DEBUG
++#include <dspbridge/uuidutil.h>
++#include <dspbridge/dbg.h>
++#endif
++
++/* ----------------------------------- This */
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/node.h>
++
++/* Static/Dynamic Loader includes */
++#include <dspbridge/dbll.h>
++#include <dspbridge/nldr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/drv.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++
++#define NODE_SIGNATURE 0x45444f4e /* "EDON" */
++#define NODEMGR_SIGNATURE 0x52474d4e /* "RGMN" */
++
++#define HOSTPREFIX "/host"
++#define PIPEPREFIX "/dbpipe"
++
++#define MaxInputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
++#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
++
++#define NODE_GetPriority(h) ((h)->nPriority)
++#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
++#define NODE_SetState(hNode, state) ((hNode)->nState = state)
++
++#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
++#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
++
++#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
++#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
++
++#define MAXDEVNAMELEN 32 /* DSP_NDBPROPS.acName size */
++#define CREATEPHASE 1
++#define EXECUTEPHASE 2
++#define DELETEPHASE 3
++
++/* Define default STRM parameters */
++/*
++ * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
++ * or make defaults configurable.
++ */
++#define DEFAULTBUFSIZE 32
++#define DEFAULTNBUFS 2
++#define DEFAULTSEGID 0
++#define DEFAULTALIGNMENT 0
++#define DEFAULTTIMEOUT 10000
++
++#define RMSQUERYSERVER 0
++#define RMSCONFIGURESERVER 1
++#define RMSCREATENODE 2
++#define RMSEXECUTENODE 3
++#define RMSDELETENODE 4
++#define RMSCHANGENODEPRIORITY 5
++#define RMSREADMEMORY 6
++#define RMSWRITEMEMORY 7
++#define RMSCOPY 8
++#define MAXTIMEOUT 2000
++
++#define NUMRMSFXNS 9
++
++#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
++
++#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Address */
++
++/*
++ * ======== NODE_MGR ========
++ */
++struct NODE_MGR {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DISP_OBJECT *hDisp; /* Node dispatcher */
++ struct LST_LIST *nodeList; /* List of all allocated nodes */
++ u32 uNumNodes; /* Number of nodes in nodeList */
++ u32 uNumCreated; /* Number of nodes *created* on DSP */
++ struct GB_TMap *pipeMap; /* Pipe connection bit map */
++ struct GB_TMap *pipeDoneMap; /* Pipes that are half free */
++ struct GB_TMap *chnlMap; /* Channel allocation bit map */
++ struct GB_TMap *dmaChnlMap; /* DMA Channel allocation bit map */
++ struct GB_TMap *zChnlMap; /* Zero-Copy Channel alloc bit map */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++ u32 ulFxnAddrs[NUMRMSFXNS]; /* RMS function addresses */
++ struct MSG_MGR *hMsg;
++
++ /* Processor properties needed by Node Dispatcher */
++ u32 ulNumChnls; /* Total number of channels */
++ u32 ulChnlOffset; /* Offset of chnl ids rsvd for RMS */
++ u32 ulChnlBufSize; /* Buffer size for data to RMS */
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ u32 uDSPWordSize; /* Size of DSP word on host bytes */
++ u32 uDSPDataMauSize; /* Size of DSP data MAU */
++ u32 uDSPMauSize; /* Size of MAU */
++ s32 nMinPri; /* Minimum runtime priority for node */
++ s32 nMaxPri; /* Maximum runtime priority for node */
++
++ struct STRM_MGR *hStrmMgr; /* STRM manager */
++
++ /* Loader properties */
++ struct NLDR_OBJECT *hNldr; /* Handle to loader */
++ struct NLDR_FXNS nldrFxns; /* Handle to loader functions */
++ bool fLoaderInit; /* Loader Init function succeeded? */
++};
++
++/*
++ * ======== CONNECTTYPE ========
++ */
++enum CONNECTTYPE {
++ NOTCONNECTED = 0,
++ NODECONNECT,
++ HOSTCONNECT,
++ DEVICECONNECT,
++} ;
++
++/*
++ * ======== STREAM ========
++ */
++struct STREAM {
++ enum CONNECTTYPE type; /* Type of stream connection */
++ u32 devId; /* pipe or channel id */
++};
++
++/*
++ * ======== NODE_OBJECT ========
++ */
++struct NODE_OBJECT {
++ struct LST_ELEM listElem;
++ u32 dwSignature; /* For object validation */
++ struct NODE_MGR *hNodeMgr; /* The manager of this node */
++ struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
++ struct DSP_UUID nodeId; /* Node's ID */
++ s32 nPriority; /* Node's current priority */
++ u32 uTimeout; /* Timeout for blocking NODE calls */
++ u32 uHeapSize; /* Heap Size */
++ u32 uDSPHeapVirtAddr; /* Heap Size */
++ u32 uGPPHeapVirtAddr; /* Heap Size */
++ enum NODE_TYPE nType; /* Type of node: message, task, etc */
++ enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
++ u32 uNumInputs; /* Current number of inputs */
++ u32 uNumOutputs; /* Current number of outputs */
++ u32 uMaxInputIndex; /* Current max input stream index */
++ u32 uMaxOutputIndex; /* Current max output stream index */
++ struct STREAM *inputs; /* Node's input streams */
++ struct STREAM *outputs; /* Node's output streams */
++ struct NODE_CREATEARGS createArgs; /* Args for node create function */
++ NODE_ENV nodeEnv; /* Environment returned by RMS */
++ struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
++ struct DSP_CBDATA *pArgs; /* Optional args to pass to node */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ char *pstrDevName; /* device name, if device node */
++ struct SYNC_OBJECT *hSyncDone; /* Synchronize NODE_Terminate */
++ s32 nExitStatus; /* execute function return status */
++
++ /* Information needed for NODE_GetAttr() */
++ DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
++ u32 uNumGPPInputs; /* Current # of from GPP streams */
++ u32 uNumGPPOutputs; /* Current # of to GPP streams */
++ /* Current stream connections */
++ struct DSP_STREAMCONNECT *streamConnect;
++
++ /* Message queue */
++ struct MSG_QUEUE *hMsgQueue;
++
++ /* These fields used for SM messaging */
++ struct CMM_XLATOROBJECT *hXlator; /* Node's SM address translator */
++
++ /* Handle to pass to dynamic loader */
++ struct NLDR_NODEOBJECT *hNldrNode;
++ bool fLoaded; /* Code is (dynamically) loaded */
++ bool fPhaseSplit; /* Phases split in many libs or ovly */
++
++} ;
++
++/* Default buffer attributes */
++static struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
++ 0, /* cbStruct */
++ 1, /* uSegment */
++ 0, /* uAlignment */
++};
++
++static void DeleteNode(struct NODE_OBJECT *hNode);
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2, u32 uStream1,
++ u32 uStream2);
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs);
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase);
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps);
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++#if GT_TRACE
++static struct GT_Mask NODE_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++#ifdef DSP_DMM_DEBUG
++extern u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Dynamic loader functions. */
++static struct NLDR_FXNS nldrFxns = {
++ NLDR_Allocate,
++ NLDR_Create,
++ NLDR_Delete,
++ NLDR_Exit,
++ NLDR_Free,
++ NLDR_GetFxnAddr,
++ NLDR_Init,
++ NLDR_Load,
++ NLDR_Unload,
++};
++
++enum NODE_STATE NODE_GetState(HANDLE hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetState:hNode 0x%x\n", pNode);
++ return -1;
++ } else
++ return pNode->nState;
++
++}
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ */
++DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
++ OUT struct NODE_OBJECT **phNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct DEV_OBJECT *hDevObject;
++ struct NODE_OBJECT *pNode = NULL;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct NODE_MSGARGS *pmsgArgs;
++ struct NODE_TASKARGS *ptaskArgs;
++ u32 uNumStreams;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++ u32 procId;
++ char *label;
++ u32 pulValue;
++ u32 dynextBase;
++ u32 offSet = 0;
++ u32 ulStackSegAddr, ulStackSegVal;
++ u32 ulGppMemBase;
++ struct CFG_HOSTRES hostRes;
++ u32 pMappedAddr = 0;
++ u32 mapAttrs = 0x0;
++ struct DSP_PROCESSORSTATE procStatus;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#endif
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDrvObject;
++ HANDLE nodeRes;
++ u32 hProcess;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(phNode != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
++ "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
++ "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
++ phNode);
++
++ *phNode = NULL;
++
++ status = PROC_GetProcessorId(hProcessor, &procId);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL)
++ status = DSP_EFAIL;
++
++ }
++ if (procId != DSP_UNIT)
++ goto func_cont;
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ /* Assuming that 0 is not a valid function address */
++ if (hNodeMgr->ulFxnAddrs[0] == 0) {
++ /* No RMS on target - we currently can't handle this */
++ GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
++ "image. Node allocation fails.\n");
++ status = DSP_EFAIL;
++ } else {
++ /* Validate pAttrIn fields, if non-NULL */
++ if (pAttrIn) {
++ /* Check if pAttrIn->iPriority is within range */
++ if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
++ pAttrIn->iPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ }
++func_cont:
++ /* Allocate node object and fill in */
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
++ if (pNode == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont1;
++ }
++ pNode->hNodeMgr = hNodeMgr;
++ /* This critical section protects GetNodeProps */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (procId != DSP_UNIT)
++ goto func_cont3;
++
++ /* Get DSP_NDBPROPS from node database */
++ status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
++ &(pNode->dcdProps));
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ pNode->nodeId = *pNodeId;
++ pNode->hProcessor = hProcessor;
++ pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
++ pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
++ pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
++
++ /* Currently only C64 DSP builds support Node Dynamic * heaps */
++ /* Allocate memory for node heap */
++ pNode->createArgs.asa.taskArgs.uHeapSize = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
++ if (!pAttrIn)
++ goto func_cont3;
++
++ /* Check if we have a user allocated node heap */
++ if (!(pAttrIn->pGPPVirtAddr))
++ goto func_cont3;
++
++ /* check for page aligned Heap size */
++ if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_Allocate: node heap page size"
++ " not aligned to 4K page, size=0x%x \n",
++ pAttrIn->uHeapSize);
++ status = DSP_EINVALIDARG;
++ } else {
++ pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
++ (u32)pAttrIn->pGPPVirtAddr;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ status = PROC_ReserveMemory(hProcessor,
++ pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
++ (void **)&(pNode->createArgs.asa.taskArgs.
++ uDSPHeapResAddr));
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:Failed to reserve "
++ "memory for Heap: 0x%x\n", status);
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: DSPProcessor_Reserve"
++ " Memory successful: 0x%x\n", status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ mapAttrs |= DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPVIRTUALADDR;
++ status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
++ pNode->createArgs.asa.taskArgs.uHeapSize,
++ (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
++ (void **)&pMappedAddr, mapAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to map memory"
++ " for Heap: 0x%x\n", status);
++ } else {
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
++ (u32) pMappedAddr;
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:DSPProcessor_Map"
++ " successful: 0x%x\n", status);
++ }
++
++func_cont3:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_cont1:
++ if (pAttrIn != NULL) {
++ /* Overrides of NBD properties */
++ pNode->uTimeout = pAttrIn->uTimeout;
++ pNode->nPriority = pAttrIn->iPriority;
++ }
++func_cont2:
++ /* Create object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pNode->hNtfy);
++
++ if (DSP_SUCCEEDED(status)) {
++ nodeType = NODE_GetType(pNode);
++ /* Allocate DSP_STREAMCONNECT array for device, task, and
++ * dais socket nodes. */
++ if (nodeType != NODE_MESSAGE) {
++ uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
++ pNode->streamConnect = MEM_Calloc(uNumStreams *
++ sizeof(struct DSP_STREAMCONNECT),
++ MEM_PAGED);
++ if (uNumStreams > 0 && pNode->streamConnect == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
++ nodeType == NODE_DAISSOCKET)) {
++ /* Allocate arrays for maintainig stream connections */
++ pNode->inputs =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ pNode->outputs =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ ptaskArgs = &(pNode->createArgs.asa.taskArgs);
++ ptaskArgs->strmInDef =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ ptaskArgs->strmOutDef =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
++ ptaskArgs->strmInDef == NULL)) ||
++ (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
++ ptaskArgs->strmOutDef == NULL)))
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
++ /* Create an event that will be posted when RMS_EXIT is
++ * received. */
++ status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ /*Get the shared mem mgr for this nodes dev object */
++ status = CMM_GetHandle(hProcessor, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to"
++ " get CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Allocate a SM addr translator for this node
++ * w/ deflt attr */
++ status = CMM_XlatorCreate(&pNode->hXlator,
++ hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed"
++ " to create SM translator: 0x%x\n",
++ status);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in message args */
++ if ((pArgs != NULL) && (pArgs->cbData > 0)) {
++ pmsgArgs = &(pNode->createArgs.asa.msgArgs);
++ pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
++ MEM_PAGED);
++ if (pmsgArgs->pData == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pmsgArgs->uArgLength = pArgs->cbData;
++ memcpy(pmsgArgs->pData, pArgs->cData,
++ pArgs->cbData);
++ }
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
++ /* Create a message queue for this node */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
++ &pNode->hMsgQueue, 0,
++ pNode->createArgs.asa.msgArgs.uMaxMessages,
++ pNode);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create object for dynamic loading */
++
++ status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
++ (void *) pNode,
++ &pNode->dcdProps.objData.nodeObj,
++ &pNode->hNldrNode,
++ &pNode->fPhaseSplit);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to "
++ "allocate NLDR node: 0x%x\n", status);
++ }
++ }
++
++ /* Comapare value read from Node Properties and check if it is same as
++ * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
++ * GPP Address, Read the value in that address and override the
++ * uStackSeg value in task args */
++ if (DSP_SUCCEEDED(status) &&
++ (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
++ NULL) {
++ label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
++ strncpy(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
++
++ if (strcmp((char *)pNode->dcdProps.objData.nodeObj.
++ ndbProps.uStackSegName, label) == 0) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "DYNEXT_BEG", &dynextBase);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "DYNEXT_BEG: 0x%x\n", status);
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "L1DSRAM_HEAP", &pulValue);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "L1DSRAM_HEAP: 0x%x\n", status);
++ }
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get host resource "
++ "0x%x\n", status);
++ }
++
++ ulGppMemBase = hostRes.dwMemBase[1];
++ offSet = pulValue - dynextBase;
++ ulStackSegAddr = ulGppMemBase + offSet;
++ ulStackSegVal = (u32)*((REG_UWORD32 *)
++ ((u32)(ulStackSegAddr)));
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "StackSegVal =0x%x\n", ulStackSegVal);
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
++
++ pNode->createArgs.asa.taskArgs.uStackSeg =
++ ulStackSegVal;
++
++ }
++
++ if (label)
++ MEM_Free(label);
++
++ }
++
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Add the node to the node manager's list of allocated
++ * nodes. */
++ LST_InitElem((struct LST_ELEM *)pNode);
++ NODE_SetState(pNode, NODE_ALLOCATED);
++
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ LST_PutTail(hNodeMgr->nodeList,
++ (struct LST_ELEM *) pNode);
++ ++(hNodeMgr->uNumNodes);
++ }
++
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hNodeMgr->hSync);
++
++ /* Preset this to assume phases are split
++ * (for overlay and dll) */
++ pNode->fPhaseSplit = true;
++
++ if (DSP_SUCCEEDED(status))
++ *phNode = pNode;
++
++
++ /* Notify all clients registered for DSP_NODESTATECHANGE. */
++ PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
++ } else {
++ /* Cleanup */
++ if (pNode)
++ DeleteNode(pNode);
++
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt,
++ PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ pPctxt->hProcessor =
++ (DSP_HPROCESSOR)hProcessor;
++ }
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt != NULL) {
++ DRV_InsertNodeResElement(*phNode, &nodeRes,
++ pPctxt);
++ DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
++ DRV_ProcNodeUpdateStatus(nodeRes, true);
++ }
++ }
++ }
++#endif
++ DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
++ (DSP_SUCCEEDED(status)
++ && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocates buffer for zero copy messaging.
++ */
++DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
++ OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
++ OUT u8 **pBuffer)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ bool bVirtAddr = false;
++ bool bSetInfo;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++
++ DBC_Require(uSize > 0);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
++ " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
++ pBuffer);
++
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (NODE_GetType(pNode) == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pAttr == NULL)
++ pAttr = &NODE_DFLTBUFATTRS; /* set defaults */
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId != DSP_UNIT) {
++ DBC_Assert(NULL);
++ goto func_end;
++ }
++ /* If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
++ * virt address, so set this info in this node's translator
++ * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
++ * virtual address from node's translator. */
++ if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
++ (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
++ bVirtAddr = true;
++ bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
++ true : false;
++ pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
++ /* Set/get this node's translators virtual address base/size */
++ status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
++ pAttr->uSegment, bSetInfo);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf "
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
++ if (pAttr->uSegment != 1) {
++ /* Node supports single SM segment only. */
++ status = DSP_EBADSEGID;
++ }
++ /* Arbitrary SM buffer alignment not supported for host side
++ * allocs, but guaranteed for the following alignment
++ * values. */
++ switch (pAttr->uAlignment) {
++ case 0:
++ case 1:
++ case 2:
++ case 4:
++ break;
++ default:
++ /* alignment value not suportted */
++ status = DSP_EALIGNMENT;
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* allocate physical buffer from segId in node's
++ * translator */
++ (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
++ uSize);
++ if (*pBuffer == NULL) {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf: "
++ "ERROR: Out of shared memory.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of a node in the allocated state, or that is
++ * currently running or paused on the target.
++ */
++DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
++ "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "Invalid NODE Handle: 0x%x\n", hNode);
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ else if (nPriority < hNodeMgr->nMinPri ||
++ nPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
++ NODE_SetPriority(hNode, nPriority);
++ } else {
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(pNode->hProcessor,
++ &procId);
++ if (procId == DSP_UNIT) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, nPriority);
++ }
++ if (DSP_SUCCEEDED(status))
++ NODE_SetPriority(hNode, nPriority);
++
++ }
++ }
++func_cont:
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP.
++ */
++DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA *pConnParam)
++{
++ struct NODE_MGR *hNodeMgr;
++ char *pstrDevName = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++ struct NODE_STRMDEF *pstrmDef;
++ struct NODE_STRMDEF *pInput = NULL;
++ struct NODE_STRMDEF *pOutput = NULL;
++ struct NODE_OBJECT *hDevNode;
++ struct NODE_OBJECT *hNode;
++ struct STREAM *pStream;
++ GB_BitNum pipeId = GB_NOBITS;
++ GB_BitNum chnlId = GB_NOBITS;
++ CHNL_MODE uMode;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ GT_5trace(NODE_debugMask, GT_ENTER,
++ "NODE_Connect: hNode1: 0x%x\tuStream1:"
++ " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
++ uStream1, hNode2, uStream2, pAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
++ (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* The two nodes must be on the same processor */
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode1->hNodeMgr != hNode2->hNodeMgr)
++ status = DSP_EFAIL;
++ /* Cannot connect a node to itself */
++ if (hNode1 == hNode2)
++ status = DSP_EFAIL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NODE_GetType() will return NODE_GPP if hNode =
++ * DSP_HGPPNODE. */
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ /* Check stream indices ranges */
++ if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
++ uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
++ node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Only the following types of connections are allowed:
++ * task/dais socket < == > task/dais socket
++ * task/dais socket < == > device
++ * task/dais socket < == > GPP
++ *
++ * ie, no message nodes, and at least one task or dais
++ * socket node.
++ */
++ if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
++ (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
++ node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
++ status = DSP_EFAIL;
++ }
++ /*
++ * Check stream mode. Default is STRMMODE_PROCCOPY.
++ */
++ if (DSP_SUCCEEDED(status) && pAttrs) {
++ if (pAttrs->lMode != STRMMODE_PROCCOPY)
++ status = DSP_ESTRMMODE; /* illegal stream mode */
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (node1Type != NODE_GPP) {
++ hNodeMgr = hNode1->hNodeMgr;
++ } else {
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ hNodeMgr = hNode2->hNodeMgr;
++ }
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Nodes must be in the allocated state */
++ if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Check that stream indices for task and dais socket nodes
++ * are not already be used. (Device nodes checked later) */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ pOutput = &(hNode1->createArgs.asa.taskArgs.
++ strmOutDef[uStream1]);
++ if (pOutput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ pInput = &(hNode2->createArgs.asa.taskArgs.
++ strmInDef[uStream2]);
++ if (pInput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ }
++ /* Connecting two task nodes? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
++ node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
++ node2Type == NODE_DAISSOCKET))) {
++ /* Find available pipe */
++ pipeId = GB_findandset(hNodeMgr->pipeMap);
++ if (pipeId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ } else {
++ hNode1->outputs[uStream1].type = NODECONNECT;
++ hNode2->inputs[uStream2].type = NODECONNECT;
++ hNode1->outputs[uStream1].devId = pipeId;
++ hNode2->inputs[uStream2].devId = pipeId;
++ pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ if (pOutput->szDevice == NULL ||
++ pInput->szDevice == NULL) {
++ /* Undo the connection */
++ if (pOutput->szDevice)
++ MEM_Free(pOutput->szDevice);
++
++ if (pInput->szDevice)
++ MEM_Free(pInput->szDevice);
++
++ pOutput->szDevice = NULL;
++ pInput->szDevice = NULL;
++ GB_clear(hNodeMgr->pipeMap, pipeId);
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy "/dbpipe<pipId>" name to device names */
++ sprintf(pOutput->szDevice, "%s%d",
++ PIPEPREFIX, pipeId);
++ strcpy(pInput->szDevice, pOutput->szDevice);
++ }
++ }
++ }
++ /* Connecting task node to host? */
++ if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
++ node2Type == NODE_GPP)) {
++ if (node1Type == NODE_GPP) {
++ uMode = CHNL_MODETODSP;
++ } else {
++ DBC_Assert(node2Type == NODE_GPP);
++ uMode = CHNL_MODEFROMDSP;
++ }
++ /* Reserve a channel id. We need to put the name "/host<id>"
++ * in the node's createArgs, but the host
++ * side channel will not be opened until DSPStream_Open is
++ * called for this node. */
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
++ /* dma chans are 2nd transport chnl set
++ * ids(e.g. 16-31)*/
++ (chnlId != GB_NOBITS) ?
++ (chnlId = chnlId + hNodeMgr->ulNumChnls) :
++ chnlId;
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ chnlId = GB_findandset(hNodeMgr->zChnlMap);
++ /* zero-copy chans are 3nd transport set
++ * (e.g. 32-47) */
++ (chnlId != GB_NOBITS) ? (chnlId = chnlId +
++ (2 * hNodeMgr->ulNumChnls)) : chnlId;
++ } else { /* must be PROCCOPY */
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ /* e.g. 0-15 */
++ }
++ } else {
++ /* default to PROCCOPY */
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ }
++ if (chnlId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ goto func_cont2;
++ }
++ pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
++ if (pstrDevName != NULL)
++ goto func_cont2;
++
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ GB_clear(hNodeMgr->dmaChnlMap, chnlId -
++ hNodeMgr->ulNumChnls);
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ GB_clear(hNodeMgr->zChnlMap, chnlId -
++ (2*hNodeMgr->ulNumChnls));
++ } else {
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ } else {
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ status = DSP_EMEMORY;
++func_cont2:
++ if (DSP_SUCCEEDED(status)) {
++ if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
++ hNode2->inputs[uStream2].type = HOSTCONNECT;
++ hNode2->inputs[uStream2].devId = chnlId;
++ pInput->szDevice = pstrDevName;
++ } else {
++ hNode1->outputs[uStream1].type = HOSTCONNECT;
++ hNode1->outputs[uStream1].devId = chnlId;
++ pOutput->szDevice = pstrDevName;
++ }
++ sprintf(pstrDevName, "%s%d", HOSTPREFIX, chnlId);
++ }
++ }
++ /* Connecting task node to device node? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
++ (node2Type == NODE_DEVICE))) {
++ if (node2Type == NODE_DEVICE) {
++ /* node1 == > device */
++ hDevNode = hNode2;
++ hNode = hNode1;
++ pStream = &(hNode1->outputs[uStream1]);
++ pstrmDef = pOutput;
++ } else {
++ /* device == > node2 */
++ hDevNode = hNode1;
++ hNode = hNode2;
++ pStream = &(hNode2->inputs[uStream2]);
++ pstrmDef = pInput;
++ }
++ /* Set up create args */
++ pStream->type = DEVICECONNECT;
++ dwLength = strlen(hDevNode->pstrDevName);
++ if (pConnParam != NULL) {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
++ (u32) pConnParam->cbData,
++ MEM_PAGED);
++ } else {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
++ MEM_PAGED);
++ }
++ if (pstrmDef->szDevice == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy device name */
++ strncpy(pstrmDef->szDevice, hDevNode->pstrDevName,
++ dwLength);
++ if (pConnParam != NULL) {
++ strncat(pstrmDef->szDevice,
++ (char *)pConnParam->cData,
++ (u32)pConnParam->cbData);
++ }
++ hDevNode->hDeviceOwner = hNode;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ hNode1->createArgs.asa.taskArgs.uNumOutputs++;
++ FillStreamDef(hNode1, pOutput, pAttrs);
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ hNode2->createArgs.asa.taskArgs.uNumInputs++;
++ FillStreamDef(hNode2, pInput, pAttrs);
++ }
++ /* Update hNode1 and hNode2 streamConnect */
++ if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
++ hNode1->uNumOutputs++;
++ if (uStream1 > hNode1->uMaxOutputIndex)
++ hNode1->uMaxOutputIndex = uStream1;
++
++ }
++ if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
++ hNode2->uNumInputs++;
++ if (uStream2 > hNode2->uMaxInputIndex)
++ hNode2->uMaxInputIndex = uStream2;
++
++ }
++ FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
++ }
++func_cont:
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulCreateFxn;
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ bool bJustWokeDSP = false;
++ struct DSP_CBDATA cbData;
++ u32 procId = 255;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
++ hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to create
++ new node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR calls */
++ cbData.cbData = PWR_TIMEOUT;
++ nodeType = NODE_GetType(hNode);
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Get access to node dispatcher */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Check node state */
++ if (NODE_GetState(hNode) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ if (procId != DSP_UNIT)
++ goto func_cont2;
++
++ /* Make sure streams are properly connected */
++ if ((hNode->uNumInputs && hNode->uMaxInputIndex >
++ hNode->uNumInputs - 1) ||
++ (hNode->uNumOutputs && hNode->uMaxOutputIndex >
++ hNode->uNumOutputs - 1))
++ status = DSP_ENOTCONNECTED;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* If node's create function is not loaded, load it */
++ /* Boost the OPP level to max level that DSP can be requested */
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP3]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP3 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_CREATE);
++ /* Get address of node's create function */
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ if (nodeType != NODE_DEVICE) {
++ status = GetFxnAddress(hNode, &ulCreateFxn,
++ CREATEPHASE);
++ }
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Create: failed to load"
++ " create code: 0x%x\n", status);
++ }
++ /* Request the lowest OPP level*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP1 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ /* Get address of iAlg functions, if socket node */
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType == NODE_DAISSOCKET) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr
++ (hNode->hNldrNode, hNode->dcdProps.
++ objData.nodeObj.pstrIAlgName,
++ &hNode->createArgs.asa.taskArgs.
++ ulDaisArg);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType != NODE_DEVICE) {
++ status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCREATENODE],
++ ulCreateFxn, &(hNode->createArgs),
++ &(hNode->nodeEnv));
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the message queue id to the node env
++ * pointer */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
++ hNode->nodeEnv);
++ }
++ }
++ }
++ /* Phase II/Overlays: Create, execute, delete phases possibly in
++ * different files/sections. */
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ /* If create code was dynamically loaded, we can now unload
++ * it. */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_CREATE);
++ hNode->fLoaded = false;
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Create: Failed to unload "
++ "create code: 0x%x\n", status1);
++ }
++func_cont2:
++ /* Update node state and node manager state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_CREATED);
++ hNodeMgr->uNumCreated++;
++ goto func_cont;
++ }
++ if (status != DSP_EWRONGSTATE) {
++ /* Put back in NODE_ALLOCATED state if error occurred */
++ NODE_SetState(hNode, NODE_ALLOCATED);
++ }
++ if (procId == DSP_UNIT) {
++ /* If node create failed, see if should sleep DSP now */
++ if (bJustWokeDSP == true) {
++ /* Check to see if partial create happened on DSP */
++ if (hNode->nodeEnv == (u32)NULL) {
++ /* No environment allocated on DSP, re-sleep
++ * DSP now */
++ PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
++ &cbData);
++ } else {
++ /* Increment count, sleep later when node fully
++ * deleted */
++ hNodeMgr->uNumCreated++;
++ }
++ }
++ }
++func_cont:
++ /* Free access to node dispatcher */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object.
++ */
++DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ u32 i;
++ struct NODE_MGR *pNodeMgr = NULL;
++ struct DISP_ATTRS dispAttrs;
++ char *szZLFile = "";
++ struct NLDR_ATTRS nldrAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++ DBC_Require(hDevObject != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
++ "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
++ *phNodeMgr = NULL;
++ /* Allocate Node manager object */
++ MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
++ if (pNodeMgr) {
++ pNodeMgr->hDevObject = hDevObject;
++ pNodeMgr->nodeList = LST_Create();
++ pNodeMgr->pipeMap = GB_create(MAXPIPES);
++ pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
++ if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
++ pNodeMgr->pipeDoneMap == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory "
++ "allocation failed\n");
++ } else {
++ status = NTFY_Create(&pNodeMgr->hNtfy);
++ }
++ pNodeMgr->uNumCreated = 0;
++ } else {
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* get devNodeType */
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevType(hDevObject, &devType);
++
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status)) {
++ status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
++ if (DSP_SUCCEEDED(status))
++ status = GetProcProps(pNodeMgr, hDevObject);
++
++ }
++ /* Create NODE Dispatcher */
++ if (DSP_SUCCEEDED(status)) {
++ dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
++ dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
++ dispAttrs.procFamily = pNodeMgr->procFamily;
++ dispAttrs.procType = pNodeMgr->procType;
++ status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
++ }
++ /* Create a STRM Manager */
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
++ /* Get MSG queue manager */
++ DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
++ status = SYNC_InitializeCS(&pNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
++ /* dma chnl map. ulNumChnls is # per transport */
++ pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ if ((pNodeMgr->chnlMap == NULL) ||
++ (pNodeMgr->dmaChnlMap == NULL) ||
++ (pNodeMgr->zChnlMap == NULL)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Block out reserved channels */
++ for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
++ GB_set(pNodeMgr->chnlMap, i);
++
++ /* Block out channels reserved for RMS */
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NO RM Server on the IVA */
++ if (devType != IVA_UNIT) {
++ /* Get addresses of any RMS functions loaded */
++ status = GetRMSFxns(pNodeMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to"
++ " get RMS functions: status = 0x%x", status);
++ }
++ }
++ }
++
++ /* Get loader functions and create loader */
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_1CLASS,
++ "NODE_CreateMgr: using dynamic loader\n");
++ pNodeMgr->nldrFxns = nldrFxns; /* Dynamic loader functions */
++ }
++ if (DSP_SUCCEEDED(status)) {
++ nldrAttrs.pfnOvly = Ovly;
++ nldrAttrs.pfnWrite = Write;
++ nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
++ nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
++ pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
++ status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
++ hDevObject, &nldrAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to "
++ "create loader: status = 0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phNodeMgr = pNodeMgr;
++ else
++ DeleteNodeMgr(pNodeMgr);
++
++ DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ * Loads the node's delete function if necessary. Free GPP side resources
++ * after node's delete function returns.
++ */
++DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct PROC_OBJECT *hProcessor;
++ struct DISP_OBJECT *hDisp;
++ u32 ulDeleteFxn;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_CBDATA cbData;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE nodeRes;
++ HANDLE hDrvObject;
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ struct DSP_PROCESSORSTATE procStatus;
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
++ hNode);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR call */
++ cbData.cbData = PWR_TIMEOUT;
++ hNodeMgr = hNode->hNodeMgr;
++ hProcessor = hNode->hProcessor;
++ hDisp = hNodeMgr->hDisp;
++ nodeType = NODE_GetType(hNode);
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ state = NODE_GetState(hNode);
++ /* Execute delete phase code for non-device node in all cases
++ * except when the node was only allocated. Delete phase must be
++ * executed even if create phase was executed, but failed.
++ * If the node environment pointer is non-NULL, the delete phase
++ * code must be executed. */
++ if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
++ nodeType != NODE_DEVICE) {
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if (procId == DSP_UNIT || procId == IVA_UNIT) {
++ /* If node has terminated, execute phase code will
++ * have already been unloaded in NODE_OnExit(). If the
++ * node is PAUSED, the execute phase is loaded, and it
++ * is now ok to unload it. If the node is running, we
++ * will unload the execute phase only after deleting
++ * the node. */
++ if (state == NODE_PAUSED && hNode->fLoaded &&
++ hNode->fPhaseSplit) {
++ /* Ok to unload execute code as long as node
++ * is not * running */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
++ hNldrNode, NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ NODE_SetState(hNode, NODE_DONE);
++ }
++ /* Load delete phase code if not loaded or if haven't
++ * * unloaded EXECUTE phase */
++ if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
++ hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->
++ hNldrNode, NLDR_DELETE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to "
++ "load delete code: 0x%x\n",
++ status);
++ }
++ }
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Unblock a thread trying to terminate the node */
++ (void)SYNC_SetEvent(hNode->hSyncDone);
++ if (procId == DSP_UNIT) {
++ /* ulDeleteFxn = address of node's delete
++ * function */
++ status = GetFxnAddress(hNode, &ulDeleteFxn,
++ DELETEPHASE);
++ } else if (procId == IVA_UNIT)
++ ulDeleteFxn = (u32)hNode->nodeEnv;
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Delete: proc Status "
++ "0x%x\n", procStatus.iState);
++ if (procStatus.iState != PROC_ERROR) {
++ status = DISP_NodeDelete(hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSDELETENODE],
++ ulDeleteFxn, hNode->nodeEnv);
++ } else
++ NODE_SetState(hNode, NODE_DONE);
++
++ /* Unload execute, if not unloaded, and delete
++ * function */
++ if (state == NODE_RUNNING &&
++ hNode->fPhaseSplit) {
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_EXECUTE);
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload execute code: 0x%x\n",
++ status1);
++ }
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_DELETE);
++ hNode->fLoaded = false;
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload delete code: 0x%x\n",
++ status1);
++ }
++ }
++ }
++ }
++ /* Free host side resources even if a failure occurred */
++ /* Remove node from hNodeMgr->nodeList */
++ LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
++ hNodeMgr->uNumNodes--;
++ /* Decrement count of nodes created on DSP */
++ if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
++ (hNode->nodeEnv != (u32) NULL)))
++ hNodeMgr->uNumCreated--;
++ /* Free host-side resources allocated by NODE_Create()
++ * DeleteNode() fails if SM buffers not freed by client! */
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++ DRV_GetProcContext(0, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, hNode, 0);
++ if (pCtxt == NULL)
++ goto func_cont;
++ if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
++ DRV_ProcNodeUpdateStatus(nodeRes, false);
++ }
++#endif
++func_cont:
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
++ DeleteNode(hNode);
++#ifndef RES_CLEANUP_DISABLE
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
++ if (pCtxt != NULL)
++ DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
++#endif
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ */
++DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
++ hNodeMgr);
++ DeleteNodeMgr(hNodeMgr);
++
++ return status;
++}
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate currently allocated nodes.
++ */
++DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ struct NODE_OBJECT *hNode;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
++ "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
++ "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ if (hNodeMgr->uNumNodes > uNodeTabSize) {
++ *puAllocated = hNodeMgr->uNumNodes;
++ *puNumNodes = 0;
++ status = DSP_ESIZE;
++ } else {
++ hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
++ nodeList);
++ for (i = 0; i < hNodeMgr->uNumNodes; i++) {
++ DBC_Assert(MEM_IsValidHandle(hNode,
++ NODE_SIGNATURE));
++ aNodeTab[i] = hNode;
++ hNode = (struct NODE_OBJECT *)LST_Next
++ (hNodeMgr->nodeList,
++ (struct LST_ELEM *)hNode);
++ }
++ *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
++ }
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ return status;
++}
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ */
++void NODE_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "Entered NODE_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Frees the message buffer.
++ */
++DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR *pAttr)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++ DBC_Require(pNode != NULL);
++ DBC_Require(pNode->hXlator != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
++ "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId == DSP_UNIT) {
++ if (DSP_SUCCEEDED(status)) {
++ if (pAttr == NULL) {
++ /* set defaults */
++ pAttr = &NODE_DFLTBUFATTRS;
++ }
++ /* Node supports single SM segment only */
++ if (pAttr->uSegment != 1)
++ status = DSP_EBADSEGID;
++
++ /* pBuffer is clients Va. */
++ status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++ else
++ status = DSP_SOK;
++
++ }
++ } else {
++ DBC_Assert(NULL); /* BUG */
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ */
++DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
++{
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttr != NULL);
++ DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
++ "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
++ uAttrSize);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ /* Enter hNodeMgr critical section (since we're accessing
++ * data that could be changed by NODE_ChangePriority() and
++ * NODE_Connect(). */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
++ /* DSP_NODEATTRIN */
++ pAttr->inNodeAttrIn.cbStruct =
++ sizeof(struct DSP_NODEATTRIN);
++ pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
++ pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
++ pAttr->inNodeAttrIn.uHeapSize =
++ hNode->createArgs.asa.taskArgs.uHeapSize;
++ pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
++ hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
++ pAttr->uInputs = hNode->uNumGPPInputs;
++ pAttr->uOutputs = hNode->uNumGPPOutputs;
++ /* DSP_NODEINFO */
++ GetNodeInfo(hNode, &(pAttr->iNodeInfo));
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node.
++ */
++DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ OUT u32 *pulId)
++{
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_EVALUE;
++ DBC_Require(cRefs > 0);
++ DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
++ DBC_Require(pulId != NULL);
++ GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
++ "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
++ uIndex, pulId);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ return status;
++ }
++ if (uDir == DSP_TONODE) {
++ if (uIndex < MaxInputs(hNode)) {
++ if (hNode->inputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->inputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ } else {
++ DBC_Assert(uDir == DSP_FROMNODE);
++ if (uIndex < MaxOutputs(hNode)) {
++ if (hNode->outputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->outputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP.
++ */
++DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
++ u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to get the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_GetMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ goto func_end;
++ }
++ /* This function will block unless a message is available. Since
++ * DSPNode_RegisterNotify() allows notification when a message
++ * is available, the system can be designed so that
++ * DSPNode_GetMessage() is only called when a message is
++ * available. */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
++ /* Check if message contains SM descriptor */
++ if (DSP_FAILED(status) || !(pMsg->dwCmd & DSP_RMSBUFDESC))
++ goto func_end;
++
++ /* Translate DSP byte addr to GPP Va. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
++ CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
++ CMM_PA2VA);
++ if (pTmpBuf != NULL) {
++ /* Adjust SM size in msg */
++ pMsg->dwArg1 = (u32) pTmpBuf;
++ pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
++ "Failed SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
++ "SM Pa/Pa translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_GetNldrObj ========
++ */
++DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ struct NLDR_OBJECT **phNldrObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_MGR *pNodeMgr = hNodeMgr;
++ DBC_Require(phNldrObj != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Entered NODE_GetNldrObj, hNodeMgr: "
++ "0x%x\n\tphNldrObj: 0x%x\n", hNodeMgr, phNldrObj);
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phNldrObj = pNodeMgr->hNldr;
++
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Exit NODE_GetNldrObj: status 0x%x\n\t"
++ "phNldrObj: 0x%x\n", status, *phNldrObj);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
++ (*phNldrObj == NULL)));
++ return status;
++}
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Returns the Stream manager.
++ */
++DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
++
++ return status;
++}
++
++/*
++ * ======== NODE_GetLoadType ========
++ */
++enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
++{
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetLoadType: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return -1;
++ } else
++ return hNode->dcdProps.objData.nodeObj.usLoadType;
++}
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Returns the timeout value for this node.
++ */
++u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetTimeout: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return 0;
++ } else
++ return hNode->uTimeout;
++}
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Returns the node type.
++ */
++enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
++{
++ enum NODE_TYPE nodeType;
++
++ if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
++ nodeType = NODE_GPP;
++ else {
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ nodeType = -1;
++ else
++ nodeType = hNode->nType;
++ }
++ return nodeType;
++}
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ */
++bool NODE_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NODE_debugMask.flags);
++ GT_create(&NODE_debugMask, "NO"); /* "NO" for NOde */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node.
++ */
++void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
++{
++ DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ /* Set node state to done */
++ NODE_SetState(hNode, NODE_DONE);
++ hNode->nExitStatus = nStatus;
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ }
++ /* Unblock call to NODE_Terminate */
++ (void) SYNC_SetEvent(hNode->hSyncDone);
++ /* Notify clients */
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++}
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ */
++DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++
++ }
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (procId == IVA_UNIT)
++ status = DSP_ENOTIMPL;
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ /* Check node state */
++ if (state != NODE_RUNNING)
++ status = DSP_EWRONGSTATE;
++
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Pause: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, NODE_SUSPENDEDPRI);
++ }
++
++ /* Update state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_PAUSED);
++ } else {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_Pause: Failed. hNode:"
++ " 0x%x\n", hNode);
++ }
++ }
++ /* End of SYNC_EnterCS */
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node. This
++ * function will block until the message stream can accommodate the
++ * message, or a timeout occurs.
++ */
++DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_MSG newMsg;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_PutMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in bad state then don't attempt sending the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_PutMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state. Can't send messages to a node after
++ * we've sent the RMS_EXIT command. There is still the
++ * possibility that NODE_Terminate can be called after we've
++ * checked the state. Could add another SYNC object to
++ * prevent this (can't use hNodeMgr->hSync, since we don't
++ * want to block other NODE functions). However, the node may
++ * still exit on its own, before this message is sent. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state == NODE_TERMINATING || state == NODE_DONE)
++ status = DSP_EWRONGSTATE;
++
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* assign pMsg values to new msg */
++ newMsg = *pMsg;
++ /* Now, check if message contains a SM buffer descriptor */
++ if (pMsg->dwCmd & DSP_RMSBUFDESC) {
++ /* Translate GPP Va to DSP physical buf Ptr. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)newMsg.dwArg1, CMM_VA2DSPPA);
++ if (pTmpBuf != NULL) {
++ /* got translation, convert to MAUs in msg */
++ if (hNode->hNodeMgr->uDSPWordSize != 0) {
++ newMsg.dwArg1 =
++ (u32)pTmpBuf /
++ hNode->hNodeMgr->uDSPWordSize;
++ /* MAUs */
++ newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: "
++ "uDSPWordSize is zero!\n");
++ status = DSP_EFAIL; /* bad DSPWordSize */
++ }
++ } else { /* failed to translate buffer address */
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: Failed to"
++ " translate SM address\n");
++ status = DSP_ETRANSLATE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
++ &newMsg, uTimeout);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ */
++DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_RegisterNotify: hNode: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hNode, uEventMask, uNotifyType, hNotification);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Check if event mask is a valid node related event */
++ if (uEventMask & ~(DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ /* Only one Notification can be registered at a
++ * time - Limitation */
++ if (uEventMask == (DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uEventMask == DSP_NODESTATECHANGE) {
++ status = NTFY_Register(hNode->hNtfy, hNotification,
++ uEventMask & DSP_NODESTATECHANGE, uNotifyType);
++ } else {
++ /* Send Message part of event mask to MSG */
++ pIntfFxns = hNode->hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgRegisterNotify)
++ (hNode->hMsgQueue,
++ uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
++ hNotification);
++ }
++
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via NODE_NodePause()) on the DSP. Load the
++ * node's execute function if necessary.
++ */
++DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ u32 ulExecuteFxn;
++ u32 ulFxnAddr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to run the node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Run:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state != NODE_CREATED && state != NODE_PAUSED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
++ goto func_cont1;
++
++ if (state == NODE_CREATED) {
++ /* If node's execute function is not loaded, load it */
++ if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Run: failed to load "
++ "execute code:0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get address of node's execute function */
++ if (procId == IVA_UNIT)
++ ulExecuteFxn = (u32) hNode->nodeEnv;
++ else {
++ status = GetFxnAddress(hNode, &ulExecuteFxn,
++ EXECUTEPHASE);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
++ status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
++ ulExecuteFxn, hNode->nodeEnv);
++ }
++ } else if (state == NODE_PAUSED) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
++ status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
++ ulFxnAddr, hNode->nodeEnv,
++ NODE_GetPriority(hNode));
++ } else {
++ /* We should never get here */
++ DBC_Assert(false);
++ }
++func_cont1:
++ /* Update node state. */
++ if (DSP_SUCCEEDED(status))
++ NODE_SetState(hNode, NODE_RUNNING);
++ else /* Set state back to previous value */
++ NODE_SetState(hNode, state);
++ /*End of SYNC_EnterCS */
++ /* Exit critical section */
++func_cont:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute phase
++ * function.
++ */
++DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ struct DSP_MSG msg, killmsg;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId, killTimeOut;
++ struct DEH_MGR *hDehMgr;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStatus != NULL);
++
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: hNode: 0x%x\n", hNode);
++
++ if (pNode->hProcessor == NULL) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Terminate: pNode->hProcessor = 0x%x\n",
++ pNode->hProcessor);
++ goto func_end;
++ }
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType !=
++ NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ /* Set the exit status if node terminated on
++ * its own. */
++ if (state == NODE_DONE)
++ *pStatus = hNode->nExitStatus;
++
++ } else {
++ NODE_SetState(hNode, NODE_TERMINATING);
++ }
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Send exit message. Do not change state to NODE_DONE
++ * here. That will be done in callback.
++ */
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
++
++ status = PROC_GetState(pNode->hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_cont;
++ /* If processor is in error state then don't attempt to send
++ * A kill task command */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Terminate:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++
++ msg.dwCmd = RMS_EXIT;
++ msg.dwArg1 = hNode->nodeEnv;
++ killmsg.dwCmd = RMS_KILLTASK;
++ killmsg.dwArg1 = hNode->nodeEnv;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++
++ if (hNode->uTimeout > MAXTIMEOUT)
++ killTimeOut = MAXTIMEOUT;
++ else
++ killTimeOut = (hNode->uTimeout)*2;
++
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait on synchronization object that will be
++ * posted in the callback on receiving RMS_EXIT
++ * message, or by NODE_Delete. Check for valid hNode,
++ * in case posted by NODE_Delete(). */
++ status = SYNC_WaitOnEvent(hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_ETIMEOUT) {
++ status = (*pIntfFxns->pfnMsgPut)
++ (hNode->hMsgQueue, &killmsg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnEvent
++ (hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ /* Here it goes the part
++ * of the simulation of
++ * the DSP exception */
++ DEV_GetDehMgr(hNodeMgr->
++ hDevObject, &hDehMgr);
++ if (hDehMgr) {
++ (*pIntfFxns->
++ pfnDehNotify)(hDehMgr,
++ DSP_SYSERROR,
++ DSP_EXCEPTIONABORT);
++ status = DSP_EFAIL;
++ }
++ } else
++ status = DSP_SOK;
++ }
++ } else
++ status = DSP_EFAIL;
++ } else /* Convert SYNC status to DSP status */
++ status = DSP_SOK;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Enter CS before getting exit status, in case node was
++ * deleted. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ /* Make sure node wasn't deleted while we blocked */
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EFAIL;
++ } else {
++ *pStatus = hNode->nExitStatus;
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: env = 0x%x "
++ "succeeded.\n", hNode->nodeEnv);
++ }
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ } /*End of SYNC_EnterCS */
++func_end:
++ return status;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
++ */
++static void DeleteNode(struct NODE_OBJECT *hNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct CMM_XLATOROBJECT *hXlator;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 i;
++ enum NODE_TYPE nodeType;
++ struct STREAM stream;
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject =
++ (struct PROC_OBJECT *)hNode->hProcessor;
++#endif
++ DSP_STATUS status;
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ hNodeMgr = hNode->hNodeMgr;
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ return;
++ hXlator = hNode->hXlator;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_DEVICE) {
++ msgArgs = hNode->createArgs.asa.msgArgs;
++ if (msgArgs.pData)
++ MEM_Free(msgArgs.pData);
++
++ /* Free MSG queue */
++ if (hNode->hMsgQueue) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
++ hNode->hMsgQueue = NULL;
++
++ }
++ if (hNode->hSyncDone)
++ (void) SYNC_CloseEvent(hNode->hSyncDone);
++
++ /* Free all stream info */
++ if (hNode->inputs) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ stream = hNode->inputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->inputs);
++ hNode->inputs = NULL;
++ }
++ if (hNode->outputs) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ stream = hNode->outputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->outputs);
++ hNode->outputs = NULL;
++ }
++ taskArgs = hNode->createArgs.asa.taskArgs;
++ if (taskArgs.strmInDef) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ if (taskArgs.strmInDef[i].szDevice) {
++ MEM_Free(taskArgs.strmInDef[i].
++ szDevice);
++ taskArgs.strmInDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmInDef);
++ taskArgs.strmInDef = NULL;
++ }
++ if (taskArgs.strmOutDef) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ if (taskArgs.strmOutDef[i].szDevice) {
++ MEM_Free(taskArgs.strmOutDef[i].
++ szDevice);
++ taskArgs.strmOutDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmOutDef);
++ taskArgs.strmOutDef = NULL;
++ }
++ if (taskArgs.uDSPHeapResAddr) {
++ status = PROC_UnMap(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap failed."
++ " Status = 0x%x\n", (u32)status);
++ }
++ status = PROC_UnReserveMemory(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapResAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "failed. Status = 0x%x\n",
++ (u32)status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ }
++ }
++ if (nodeType != NODE_MESSAGE) {
++ if (hNode->streamConnect) {
++ MEM_Free(hNode->streamConnect);
++ hNode->streamConnect = NULL;
++ }
++ }
++ if (hNode->pstrDevName) {
++ MEM_Free(hNode->pstrDevName);
++ hNode->pstrDevName = NULL;
++ }
++
++ if (hNode->hNtfy) {
++ NTFY_Delete(hNode->hNtfy);
++ hNode->hNtfy = NULL;
++ }
++
++ /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
++ if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrIAlgName) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
++ hNode->dcdProps.objData.nodeObj.pstrIAlgName = NULL;
++ }
++
++ /* Free all SM address translator resources */
++ if (hXlator) {
++ (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
++ hXlator = NULL;
++ }
++
++ if (hNode->hNldrNode) {
++ hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
++ hNode->hNldrNode = NULL;
++ }
++
++ MEM_FreeObject(hNode);
++ hNode = NULL;
++}
++
++/*
++ * ======== DeleteNodeMgr ========
++ * Purpose:
++ * Frees the node manager.
++ */
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
++{
++ struct NODE_OBJECT *hNode;
++
++ if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
++ /* Free resources */
++ if (hNodeMgr->hDcdMgr)
++ DCD_DestroyManager(hNodeMgr->hDcdMgr);
++
++ /* Remove any elements remaining in lists */
++ if (hNodeMgr->nodeList) {
++ while ((hNode =
++ (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
++ nodeList)))
++ DeleteNode(hNode);
++
++ DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
++ LST_Delete(hNodeMgr->nodeList);
++ }
++ if (hNodeMgr->hNtfy)
++ NTFY_Delete(hNodeMgr->hNtfy);
++
++ if (hNodeMgr->pipeMap)
++ GB_delete(hNodeMgr->pipeMap);
++
++ if (hNodeMgr->pipeDoneMap)
++ GB_delete(hNodeMgr->pipeDoneMap);
++
++ if (hNodeMgr->chnlMap)
++ GB_delete(hNodeMgr->chnlMap);
++
++ if (hNodeMgr->dmaChnlMap)
++ GB_delete(hNodeMgr->dmaChnlMap);
++
++ if (hNodeMgr->zChnlMap)
++ GB_delete(hNodeMgr->zChnlMap);
++
++ if (hNodeMgr->hDisp)
++ DISP_Delete(hNodeMgr->hDisp);
++
++ if (hNodeMgr->hSync)
++ SYNC_DeleteCS(hNodeMgr->hSync);
++
++ if (hNodeMgr->hStrmMgr)
++ STRM_Delete(hNodeMgr->hStrmMgr);
++
++ /* Delete the loader */
++ if (hNodeMgr->hNldr)
++ hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
++
++ if (hNodeMgr->fLoaderInit)
++ hNodeMgr->nldrFxns.pfnExit();
++
++ MEM_FreeObject(hNodeMgr);
++ }
++}
++
++/*
++ * ======== FillStreamConnect ========
++ * Purpose:
++ * Fills stream information.
++ */
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream1, u32 uStream2)
++{
++ u32 uStrmIndex;
++ struct DSP_STREAMCONNECT *pStrm1 = NULL;
++ struct DSP_STREAMCONNECT *pStrm2 = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++
++ if (node1Type != NODE_DEVICE) {
++ uStrmIndex = hNode1->uNumInputs +
++ hNode1->uNumOutputs - 1;
++ pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
++ pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm1->uThisNodeStreamIndex = uStream1;
++ }
++
++ if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++ /* NODE == > NODE */
++ if (node1Type != NODE_DEVICE) {
++ pStrm1->hConnectedNode = hNode2;
++ pStrm1->uiConnectedNodeID = hNode2->nodeId;
++ pStrm1->uConnectedNodeStreamIndex = uStream2;
++ pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
++ }
++ if (node2Type != NODE_DEVICE) {
++ uStrmIndex = hNode2->uNumInputs +
++ hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct =
++ sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->hConnectedNode = hNode1;
++ pStrm2->uiConnectedNodeID = hNode1->nodeId;
++ pStrm2->uConnectedNodeStreamIndex = uStream1;
++ pStrm2->lType = CONNECTTYPE_NODEINPUT;
++ }
++ } else if (node1Type != NODE_DEVICE)
++ pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
++ } else {
++ /* GPP == > NODE */
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->lType = CONNECTTYPE_GPPINPUT;
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * Purpose:
++ * Fills Stream attributes.
++ */
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs)
++{
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++
++ if (pAttrs != NULL) {
++ pstrmDef->uNumBufs = pAttrs->uNumBufs;
++ pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = pAttrs->uSegid;
++ pstrmDef->uAlignment = pAttrs->uAlignment;
++ pstrmDef->uTimeout = pAttrs->uTimeout;
++ } else {
++ pstrmDef->uNumBufs = DEFAULTNBUFS;
++ pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = DEFAULTSEGID;
++ pstrmDef->uAlignment = DEFAULTALIGNMENT;
++ pstrmDef->uTimeout = DEFAULTTIMEOUT;
++ }
++}
++
++/*
++ * ======== FreeStream ========
++ * Purpose:
++ * Updates the channel mask and frees the pipe id.
++ */
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
++{
++ /* Free up the pipe id unless other node has not yet been deleted. */
++ if (stream.type == NODECONNECT) {
++ if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
++ /* The other node has already been deleted */
++ GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
++ GB_clear(hNodeMgr->pipeMap, stream.devId);
++ } else {
++ /* The other node has not been deleted yet */
++ GB_set(hNodeMgr->pipeDoneMap, stream.devId);
++ }
++ } else if (stream.type == HOSTCONNECT) {
++ if (stream.devId < hNodeMgr->ulNumChnls) {
++ GB_clear(hNodeMgr->chnlMap, stream.devId);
++ } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
++ /* dsp-dma */
++ GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
++ (1 * hNodeMgr->ulNumChnls));
++ } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
++ /* zero-copy */
++ GB_clear(hNodeMgr->zChnlMap, stream.devId -
++ (2 * hNodeMgr->ulNumChnls));
++ }
++ }
++}
++
++/*
++ * ======== GetFxnAddress ========
++ * Purpose:
++ * Retrieves the address for create, execute or delete phase for a node.
++ */
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase)
++{
++ char *pstrFxnName = NULL;
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
++ NODE_GetType(hNode) == NODE_DAISSOCKET ||
++ NODE_GetType(hNode) == NODE_MESSAGE);
++
++ switch (uPhase) {
++ case CREATEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrCreatePhaseFxn;
++ break;
++ case EXECUTEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrExecutePhaseFxn;
++ break;
++ case DELETEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrDeletePhaseFxn;
++ break;
++ default:
++ /* Should never get here */
++ DBC_Assert(false);
++ break;
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
++ pulFxnAddr);
++
++ return status;
++}
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Retrieves the node information.
++ */
++void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
++{
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(pNodeInfo != NULL);
++
++ pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
++ pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
++ ndbProps;
++ pNodeInfo->uExecutionPriority = hNode->nPriority;
++ pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
++ pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
++ pNodeInfo->uNodeEnv = hNode->nodeEnv;
++
++ pNodeInfo->nsExecutionState = NODE_GetState(hNode);
++
++ /* Copy stream connect data */
++ for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
++ pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
++
++}
++
++/*
++ * ======== GetNodeProps ========
++ * Purpose:
++ * Retrieve node properties.
++ */
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps)
++{
++ u32 uLen;
++ struct NODE_MSGARGS *pMsgArgs;
++ struct NODE_TASKARGS *pTaskArgs;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
++ DSP_STATUS status = DSP_SOK;
++#ifdef DEBUG
++ char szUuid[MAXUUIDLEN];
++#endif
++
++ status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
++ DSP_DCDNODETYPE, pdcdProps);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNode->nType = nodeType = pndbProps->uNodeType;
++
++#ifdef DEBUG
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
++ MAXUUIDLEN);
++ DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
++#endif
++
++ /* Fill in message args that come from NDB */
++ if (nodeType != NODE_DEVICE) {
++ pMsgArgs = &(hNode->createArgs.asa.msgArgs);
++ pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
++ pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
++ uMsgNotifyType;
++ pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Max Number of Messages: 0x%x\n",
++ pMsgArgs->uMaxMessages);
++#endif
++ } else {
++ /* Copy device name */
++ DBC_Require(pndbProps->acName);
++ uLen = strlen(pndbProps->acName);
++ DBC_Assert(uLen < MAXDEVNAMELEN);
++ hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (hNode->pstrDevName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(hNode->pstrDevName,
++ pndbProps->acName, uLen);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args that come from NDB */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ pTaskArgs = &(hNode->createArgs.asa.taskArgs);
++ pTaskArgs->nPriority = pndbProps->iPriority;
++ pTaskArgs->uStackSize = pndbProps->uStackSize;
++ pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
++ pTaskArgs->uStackSeg = pndbProps->uStackSeg;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Priority: 0x%x\n" "** (node) Stack"
++ " Size: 0x%x words\n" "** (node) System Stack"
++ " Size: 0x%x words\n" "** (node) Stack"
++ " Segment: 0x%x\n\n",
++ "** (node) profile count : 0x%x \n \n",
++ pTaskArgs->nPriority, pTaskArgs->uStackSize,
++ pTaskArgs->uSysStackSize,
++ pTaskArgs->uStackSeg,
++ pndbProps->uCountProfiles);
++#endif
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== GetProcProps ========
++ * Purpose:
++ * Retrieve the processor properties.
++ */
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ struct CFG_DEVNODE *hDevNode;
++ struct CFG_HOSTRES hostRes;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
++ hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
++ hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
++
++ /*
++ * PROC will add an API to get DSP_PROCESSORINFO.
++ * Fill in default values for now.
++ */
++ /* TODO -- Instead of hard coding, take from registry */
++ hNodeMgr->procFamily = 6000;
++ hNodeMgr->procType = 6410;
++ hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
++ hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
++ hNodeMgr->uDSPWordSize = DSPWORDSIZE;
++ hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
++ hNodeMgr->uDSPMauSize = 1;
++
++ }
++ return status;
++}
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node UUID properties from DCD/DOF file.
++ */
++DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS *pNodeProps)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct DEV_OBJECT *hDevObject;
++ DSP_STATUS status = DSP_SOK;
++ struct DCD_NODEPROPS dcdNodeProps;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ if (hProcessor == NULL || pNodeId == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetUUIDProps: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetUUIDProps: " "\thProcessor: "
++ "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
++ pNodeId, pNodeProps);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status) && hDevObject != NULL) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ }
++
++ /*
++ * Enter the critical section. This is needed because
++ * DCD_GetObjectDef will ultimately end up calling DBLL_open/close,
++ * which needs to be protected in order to not corrupt the zlib manager
++ * (COD).
++ */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ dcdNodeProps.pstrCreatePhaseFxn = NULL;
++ dcdNodeProps.pstrExecutePhaseFxn = NULL;
++ dcdNodeProps.pstrDeletePhaseFxn = NULL;
++ dcdNodeProps.pstrIAlgName = NULL;
++
++ status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
++ (struct DSP_UUID *) pNodeId,
++ DSP_DCDNODETYPE,
++ (struct DCD_GENERICOBJ *) &dcdNodeProps);
++ if (DSP_SUCCEEDED(status)) {
++ *pNodeProps = dcdNodeProps.ndbProps;
++ if (dcdNodeProps.pstrCreatePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
++
++ if (dcdNodeProps.pstrExecutePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
++
++ if (dcdNodeProps.pstrDeletePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
++
++ if (dcdNodeProps.pstrIAlgName)
++ MEM_Free(dcdNodeProps.pstrIAlgName);
++ }
++ /* Leave the critical section, we're done. */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== GetRMSFxns ========
++ * Purpose:
++ * Retrieve the RMS functions.
++ */
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
++{
++ s32 i;
++ struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
++ DSP_STATUS status = DSP_SOK;
++
++ static char *pszFxns[NUMRMSFXNS] = {
++ "RMS_queryServer", /* RMSQUERYSERVER */
++ "RMS_configureServer", /* RMSCONFIGURESERVER */
++ "RMS_createNode", /* RMSCREATENODE */
++ "RMS_executeNode", /* RMSEXECUTENODE */
++ "RMS_deleteNode", /* RMSDELETENODE */
++ "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
++ "RMS_readMemory", /* RMSREADMEMORY */
++ "RMS_writeMemory", /* RMSWRITEMEMORY */
++ "RMS_copy", /* RMSCOPY */
++ };
++
++ for (i = 0; i < NUMRMSFXNS; i++) {
++ status = DEV_GetSymbol(hDev, pszFxns[i],
++ &(hNodeMgr->ulFxnAddrs[i]));
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ /*
++ * May be loaded dynamically (in the future),
++ * but return an error for now.
++ */
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "RMS function: %s "
++ "currently not loaded\n", pszFxns[i]);
++ } else {
++ GT_2trace(NODE_debugMask, GT_6CLASS,
++ "GetRMSFxns: Symbol not "
++ "found: %s\tstatus = 0x%x\n",
++ pszFxns[i], status);
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== Ovly ========
++ * Purpose:
++ * Called during overlay.Sends command to RMS to copy a block of data.
++ */
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u32 ulBytes = 0;
++ u32 ulSize;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
++ ulTimeout = hNode->uTimeout;
++
++ /* Call new MemCopy function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
++ ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
++
++ if (DSP_SUCCEEDED(status))
++ ulBytes = ulNumBytes;
++
++ return ulBytes;
++}
++
++/*
++ * ======== Write ========
++ */
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u16 memType;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulTimeout = hNode->uTimeout;
++ memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
++
++ /* Call new MemWrite function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
++ ulNumBytes, memType);
++
++ return ulNumBytes;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
+new file mode 100644
+index 0000000..332e01a
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/proc.c
+@@ -0,0 +1,1985 @@
++/*
++ * proc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.c ========
++ * Description:
++ * Processor interface at the driver level.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Ctrl
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_GetResourceInfo
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace
++ * PROC_Init
++ * PROC_Load
++ * PROC_Map
++ * PROC_NotifyClients
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ * PROC_InvalidateMemory
++
++ *! Revision History
++ *! ======== ========
++ *! 04-Apr-2007 sh Added PROC_InvalidateMemory API
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! Used MEM_FlushCache instead of OS specific API
++ *! Integrated Alan's code review updates
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 08-Mar-2004 vp Added g_pszLastCoff member to PROC_OBJECT.
++ *! This is required for multiprocessor environment.
++ *! 09-Feb-2004 vp Added PROC_GetProcessorID function
++ *! 22-Apr-2003 vp Fixed issue with the string that stores coff file name
++ *! 03-Apr-2003 sb Fix DEH deregistering bug
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in PROC_Start function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
++ *! 14-May-2002 sg Use CSL_Atoi() instead of atoi().
++ *! 13-May-2002 sg Propagate PWR return codes upwards.
++ *! 07-May-2002 sg Added check for, and call to PWR functions in PROC_Ctrl.
++ *! 02-May-2002 sg Added "nap" mode: put DSP to sleep once booted.
++ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
++ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
++ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
++ *! DEH module.
++ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
++ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
++ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
++ *! to facilitate the external loading.
++ *! 14-Aug-2001 ag DCD_AutoRegister() now called before IOOnLoaded() fxn.
++ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
++ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
++ *! error other than E_NOTIMPL.
++ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
++ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
++ *! if DEV_Create2 fails; ie, no non-RMS targets can be
++ *! loaded.
++ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
++ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
++ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
++ *! WMD_BRD_STOP is always followed by DEV_Destroy2.
++ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
++ *! different way.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! WMD fxns are checked for WSX_STATUS.
++ *! PROC_Attach does not alter the state of the BRD.
++ *! PROC_Run removed.
++ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
++ *! invalid
++ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
++ *! ver 0.8 API.
++ *! 06-Jul-2000 rr: Created.
++ */
++
++/* ------------------------------------ Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/procpriv.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/nldr.h>
++#include <dspbridge/rmm.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/wmdioctl.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/proc.h>
++#include <dspbridge/pwr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define PROC_SIGNATURE 0x434F5250 /* "PROC" (in reverse). */
++#define MAXCMDLINELEN 255
++#define PROC_ENVPROCID "PROC_ID=%d"
++#define MAXPROCIDLEN (8 + 5)
++#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
++#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
++#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
++
++extern char *iva_img;
++/* The PROC_OBJECT structure. */
++struct PROC_OBJECT {
++ struct LST_ELEM link; /* Link to next PROC_OBJECT */
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device this PROC represents */
++ u32 hProcess; /* Process owning this Processor */
++ struct MGR_OBJECT *hMgrObject; /* Manager Object Handle */
++ u32 uAttachCount; /* Processor attach count */
++ u32 uProcessor; /* Processor number */
++ u32 uTimeout; /* Time out count */
++ enum DSP_PROCSTATE sState; /* Processor state */
++ u32 ulUnit; /* DDSP unit number */
++ bool bIsAlreadyAttached; /*
++ * True if the Device below has
++ * GPP Client attached
++ */
++ struct NTFY_OBJECT *hNtfy; /* Manages notifications */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ char *g_pszLastCoff;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask PROC_DebugMask = { NULL, NULL }; /* WCD MGR Mask */
++#endif
++
++static u32 cRefs;
++
++struct SYNC_CSOBJECT *hProcLock; /* For critical sections */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
++static s32 GetEnvpCount(char **envp);
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar);
++
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object.
++ */
++DSP_STATUS
++PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++ struct PROC_OBJECT *pProcObject = NULL;
++ struct MGR_OBJECT *hMgrObject = NULL;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ u32 devType;
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phProcessor != NULL);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
++ "uProcessor: 0x%x\n\tpAttrIn: 0x%x\n\tphProcessor:"
++ "0x%x\n", uProcessor, pAttrIn, phProcessor);
++ /* Get the Driver and Manager Object Handles */
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
++ if (DSP_FAILED(status)) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: DSP_FAILED to get"
++ "the Manager Object.\n", status);
++ }
++ } else {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get the"
++ " DriverObject, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the Device Object */
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevObject, 0x%x!\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, &devType);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevType, 0x%x!\n", status);
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If we made it this far, create the Proceesor object: */
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ /* Fill out the Processor Object: */
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach:Out of memeory \n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ pProcObject->uProcessor = devType;
++ /* Get Caller Process and store it */
++ /* Return PID instead of process handle */
++ pProcObject->hProcess = current->pid;
++
++ if (pAttrIn)
++ pProcObject->uTimeout = pAttrIn->uTimeout;
++ else
++ pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
++
++ status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not"
++ " get the WMD Context.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not get"
++ " the DEV_ Interface fxns.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Create the Notification Object */
++ /* This is created with no event mask, no notify mask
++ * and no valid handle to the notification. They all get
++ * filled up when PROC_RegisterNotify is called */
++ status = NTFY_Create(&pProcObject->hNtfy);
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert the Processor Object into the DEV List.
++ * Return handle to this Processor Object:
++ * Find out if the Device is already attached to a
++ * Processor. If so, return AlreadyAttached status */
++ LST_InitElem(&pProcObject->link);
++ status = DEV_InsertProcObject(pProcObject->hDevObject,
++ (u32)pProcObject,
++ &pProcObject->bIsAlreadyAttached);
++ if (DSP_SUCCEEDED(status)) {
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_SALREADYATTACHED;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Already Attached!\n");
++ }
++ } else {
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ MEM_FreeObject(pProcObject);
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to insert "
++ "Proc Object into DEV, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phProcessor = (DSP_HPROCESSOR)pProcObject;
++ (void)PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORATTACH);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Attach Success!\n");
++ }
++ } else {
++ /* Don't leak memory if DSP_FAILED */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: Could not allocate "
++ "storage for notification \n");
++ MEM_FreeObject(pProcObject);
++ }
++func_end:
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDRVObject,
++ &pPctxt, NULL, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext((struct DRV_OBJECT *)hDRVObject, &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++ }
++func_cont:
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL)
++ pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
++
++ }
++#endif
++ DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
++ (status == DSP_SALREADYATTACHED &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
++ "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
++
++ return status;
++}
++
++static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject,
++ u32 size, char *execFile)
++{
++ s32 devType;
++ s32 len;
++
++ DEV_GetDevType(hDevObject, (u32 *) &devType);
++ if (devType == DSP_UNIT) {
++ return CFG_GetExecFile(hDevNode, size, execFile);
++ } else if (devType == IVA_UNIT) {
++ if (iva_img) {
++ len = strlen(iva_img);
++ strncpy(execFile, iva_img, len + 1);
++ return DSP_SOK;
++ }
++ }
++ return DSP_EFILE;
++}
++
++/*
++ * ======== PROC_AutoStart ======== =
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject: Handle to the Device
++ * Returns:
++ * DSP_SOK: On Successful Loading
++ * DSP_EFAIL General Failure
++ * Requires:
++ * hDevObject != NULL
++ * Ensures:
++ */
++DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ u32 dwAutoStart = 0; /* autostart flag */
++ struct PROC_OBJECT *pProcObject;
++ struct PROC_OBJECT *hProcObject;
++ char szExecFile[MAXCMDLINELEN];
++ char *argv[2];
++ struct MGR_OBJECT *hMgrObject = NULL;
++ s32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevNode != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_AutoStart, args:\n\t"
++ "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
++ /* Create a Dummy PROC Object */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to "
++ "Get MGR Object\n");
++ goto func_end;
++ }
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED "
++ "to Create a dummy Processor\n");
++ goto func_end;
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ hProcObject = pProcObject;
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ &pProcObject->pIntfFxns))) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed "
++ "to get WMD Context \n");
++ }
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed to "
++ "get IntFxns \n");
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Stop the Device, put it into standby mode */
++ status = PROC_Stop(hProcObject);
++ if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
++ !dwAutoStart) {
++ status = DSP_EFAIL;
++ /* DSP_FAILED to Get s32 Fxn or Wmd Context */
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
++ "CFG_GetAutoStart DSP_FAILED \n");
++ goto func_cont;
++ }
++ /* Get the default executable for this board... */
++ DEV_GetDevType(hDevObject, (u32 *)&devType);
++ pProcObject->uProcessor = devType;
++ if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
++ sizeof(szExecFile), szExecFile))) {
++ argv[0] = szExecFile;
++ argv[1] = NULL;
++ /* ...and try to load it: */
++ status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Start(hProcObject);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_AutoStart: Processor started "
++ "running\n");
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED To "
++ "Start \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to Load\n");
++ }
++ } else {
++ status = DSP_EFILE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
++ "No Exec file found \n");
++ }
++func_cont:
++ MEM_FreeObject(hProcObject);
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_AutoStart, status:0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the
++ * DSP processor.
++ *
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ * Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
++ * Operation. arg can be null.
++ */
++DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
++ IN struct DSP_CBDATA *arg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = hProcessor;
++ u32 timeout = 0;
++
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_Ctrl, args:\n\thProcessor:"
++ " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* intercept PWR deep sleep command */
++ if (dwCmd == WMDIOCTL_DEEPSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR emergency sleep command */
++ else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
++ } else if (dwCmd == PWR_DEEPSLEEP) {
++ /* timeout = arg->cbData; */
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR wake commands */
++ else if (dwCmd == WMDIOCTL_WAKEUP) {
++ timeout = arg->cbData;
++ status = PWR_WakeDSP(timeout);
++ } else if (dwCmd == PWR_WAKEUP) {
++ /* timeout = arg->cbData; */
++ status = PWR_WakeDSP(timeout);
++ } else
++ if (DSP_SUCCEEDED
++ ((*pProcObject->pIntfFxns->pfnDevCntrl)
++ (pProcObject->hWmdContext, dwCmd, arg))) {
++ status = DSP_SOK;
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: Failed \n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Destroys the Processor Object. Removes the notification from the Dev
++ * List.
++ */
++DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* Notify the Client */
++ NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
++ /* Remove the notification memory */
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ if (pProcObject->g_pszLastCoff) {
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL) {
++ DRV_ProcFreeDMMRes(pPctxt);
++ pPctxt->hProcessor = NULL;
++ }
++ }
++#endif
++
++ /* Remove the Proc from the DEV List */
++ (void)DEV_RemoveProcObject(pProcObject->hDevObject,
++ (u32)pProcObject);
++ /* Free the Processor Object */
++ MEM_FreeObject(pProcObject);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Detach: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes allocated
++ * on a DSP processor.
++ */
++DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++
++ GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
++ hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr))) {
++ if (hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, aNodeTab,
++ uNodeTabSize,
++ puNumNodes,
++ puAllocated);
++ }
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
++ "InValid Processor Handle \n");
++ }
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
++ "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
++ puNumNodes, puAllocated, status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flush cache
++ */
++DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize, u32 ulFlags)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_FlushMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
++ hProcessor, pMpuAddr, ulSize, ulFlags);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates the memory specified
++ */
++DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_InvalidateMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
++ pMpuAddr, ulSize);
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_InvalidateMemory [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ */
++DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *pResourceInfo,
++ u32 uResourceInfoSize)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct NLDR_OBJECT *hNldr = NULL;
++ struct RMM_TargetObj *rmm = NULL;
++ struct IO_MGR *hIOMgr = NULL; /* IO manager handle */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pResourceInfo != NULL);
++ DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
++
++ GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
++ "hProcessor: 0x%x\n\tuResourceType: 0x%x\n\tpResourceInfo:"
++ " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
++ uResourceType, pResourceInfo, uResourceInfoSize);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetResourceInfo: InValid "
++ "Processor Handle \n");
++ goto func_end;
++ }
++ switch (uResourceType) {
++ case DSP_RESOURCE_DYNDARAM:
++ case DSP_RESOURCE_DYNSARAM:
++ case DSP_RESOURCE_DYNEXTERNAL:
++ case DSP_RESOURCE_DYNSRAM:
++ if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr)))
++ goto func_end;
++
++ if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
++ if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
++ DBC_Assert(rmm != NULL);
++ status = DSP_EVALUE;
++ if (RMM_stat(rmm,
++ (enum DSP_MEMTYPE)uResourceType,
++ (struct DSP_MEMSTAT *)&(pResourceInfo->
++ result.memStat)))
++ status = DSP_SOK;
++ }
++ }
++ break;
++ case DSP_RESOURCE_PROCLOAD:
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
++ (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
++ result.procLoadStat));
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Error in procLoadStat function 0x%x\n", status);
++ }
++ break;
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
++ "status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void PROC_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ if (hProcLock)
++ (void)SYNC_DeleteCS(hProcLock);
++
++ cRefs--;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Exit, ref count:0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== PROC_GetDevObject ========
++ * Purpose:
++ * Return the Dev Object handle for a given Processor.
++ *
++ */
++DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ *phDevObject = pProcObject->hDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject != NULL) ||
++ (DSP_FAILED(status) && *phDevObject == NULL));
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ */
++DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE *pProcStatus,
++ u32 uStateInfoSize)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ BRD_STATUS brdStatus;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pProcStatus != NULL);
++ DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
++ "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
++ " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* First, retrieve BRD state information */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &brdStatus))) {
++ switch (brdStatus) {
++ case BRD_STOPPED:
++ pProcStatus->iState = PROC_STOPPED;
++ break;
++ case BRD_DSP_HIBERNATION:
++ /* Fall through */
++ case BRD_RUNNING:
++ pProcStatus->iState = PROC_RUNNING;
++ break;
++ case BRD_LOADED:
++ pProcStatus->iState = PROC_LOADED;
++ break;
++ case BRD_ERROR:
++ pProcStatus->iState = PROC_ERROR;
++ break;
++ default:
++ pProcStatus->iState = 0xFF;
++ status = DSP_EFAIL;
++ break;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: General Failure"
++ " to read the PROC Status \n");
++ }
++ /* Next, retrieve error information, if any */
++ status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
++ if (DSP_SUCCEEDED(status) && hDehMgr) {
++ status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
++ (hDehMgr, &(pProcStatus->errInfo));
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed "
++ "retrieve exception info.\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed to "
++ "retrieve DEH handle.\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState:InValid Processor Handle \n");
++ }
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_GetState, results:\n\t"
++ "status: 0x%x\n\tpProcStatus: 0x%x\n", status,
++ pProcStatus->iState);
++ return status;
++}
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the current contents of the trace buffer, located on the
++ * Processor. Predefined symbols for the trace buffer must have been
++ * configured into the DSP executable.
++ * Details:
++ * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
++ * trace buffer, only. Treat it as an undocumented feature.
++ * This call is destructive, meaning the processor is placed in the monitor
++ * state as a result of this function.
++ */
++DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
++{
++ DSP_STATUS status;
++ status = DSP_ENOTIMPL;
++ return status;
++}
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each call
++ */
++bool PROC_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!PROC_DebugMask.flags);
++ GT_create(&PROC_DebugMask, "PR"); /* "PR" for Processor */
++
++ (void)SYNC_InitializeCS(&hProcLock);
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Init, ref count:0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ */
++DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
++ IN CONST char **aArgv, IN CONST char **aEnvp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct IO_MGR *hIOMgr; /* IO manager handle */
++ struct MSG_MGR *hMsgMgr;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ char *pargv0; /* temp argv[0] ptr */
++ char **newEnvp; /* Updated envp[] array. */
++ char szProcID[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
++ s32 cEnvp; /* Num elements in envp[]. */
++ s32 cNewEnvp; /* " " in newEnvp[] */
++ s32 nProcID = 0; /* Anticipate MP version. */
++ struct DCD_MANAGER *hDCDHandle;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 dwExtEnd;
++ u32 uProcId;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ struct timeval tv1;
++ struct timeval tv2;
++#endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(iArgc > 0);
++ DBC_Require(aArgv != NULL);
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv1);
++#endif
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
++ "hProcessor: 0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
++ /* Call the WMD_BRD_Load Fxn */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Invalid Processor Handle..\n");
++ goto func_end;
++ }
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_EATTACHED;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load Abort becuase a GPP "
++ "Client is already attached status 0x%x \n", status);
++ goto func_end;
++ }
++ if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
++ "DEV_GetCodMgr status 0x%x \n", status);
++ goto func_end;
++ }
++ status = PROC_Stop(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
++ status);
++ goto func_end;
++ }
++ /* Place the board in the monitor state. */
++ status = PROC_Monitor(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
++ status);
++ goto func_end;
++ }
++ /* Save ptr to original argv[0]. */
++ pargv0 = (char *)aArgv[0];
++ /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
++ cEnvp = GetEnvpCount((char **)aEnvp);
++ cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
++ newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
++ if (newEnvp) {
++ status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
++ nProcID);
++ if (status == -1) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
++ "Proc ID string overflow \n");
++ status = DSP_EFAIL;
++ } else {
++ newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
++ cNewEnvp, szProcID);
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Before proceeding with new load,
++ * check if a previously registered COFF
++ * exists.
++ * If yes, unregister nodes in previously
++ * registered COFF. If any error occurred,
++ * set previously registered COFF to NULL. */
++ if (pProcObject->g_pszLastCoff != NULL) {
++ status = DCD_AutoUnregister(hDCDHandle,
++ pProcObject->g_pszLastCoff);
++ /* Regardless of auto unregister status,
++ * free previously allocated
++ * memory. */
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++ }
++ /* On success, do COD_OpenBase() */
++ status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
++ COD_SYMB);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: COD_OpenBase "
++ "failed (0x%x)\n", status);
++ }
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ " PROC_Load:Out of Memory \n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto-register data base */
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto register nodes in specified COFF
++ * file. If registration did not fail,
++ * (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
++ * save the name of the COFF file for
++ * de-registration in the future. */
++ status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
++ if (status == DSP_EDCDNOAUTOREGISTER) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: No Auto "
++ "Register section. Proceeding..\n");
++ status = DSP_SOK;
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to "
++ "Auto Register..\n");
++ } else {
++ DBC_Assert(pProcObject->g_pszLastCoff == NULL);
++ /* Allocate memory for pszLastCoff */
++ pProcObject->g_pszLastCoff = MEM_Calloc(
++ (strlen((char *)aArgv[0]) + 1),
++ MEM_PAGED);
++ /* If memory allocated, save COFF file name*/
++ if (pProcObject->g_pszLastCoff) {
++ strncpy(pProcObject->g_pszLastCoff,
++ (char *)aArgv[0],
++ (strlen((char *)aArgv[0]) + 1));
++ }
++ }
++ }
++ }
++ /* Update shared memory address and size */
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the message manager. This must be done
++ * before calling the IOOnLoaded function. */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (!hMsgMgr) {
++ status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
++ (MSG_ONEXIT)NODE_OnExit);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
++ }
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK not to have a message manager */
++ status = DSP_SOK;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Device object's message manager */
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
++ if (status == DSP_ENOTIMPL) {
++ /* Ok not to implement this function */
++ status = DSP_SOK;
++ } else {
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to get shared "
++ "memory or message buffer address "
++ "from COFF status 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "MSG_Create status 0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Now, attempt to load an exec: */
++
++ /* Boost the OPP level to Maximum level supported by baseport*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP5]);
++#endif
++ status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
++ DEV_BrdWriteFxn,
++ pProcObject->hDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_OPENFAILED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Failure to Load the EXE\n");
++ }
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Could not parse the file\n");
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "COD_Load status 0x%x \n", status);
++ }
++ }
++ /* Requesting the lowest opp supported*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++#endif
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Processor status to loaded */
++ status = (*pProcObject->pIntfFxns->pfnBrdSetState)
++ (pProcObject->hWmdContext, BRD_LOADED);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_LOADED;
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load, pfnBrdSetState "
++ "failed: 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(hProcessor, &uProcId);
++ if (uProcId == DSP_UNIT) {
++ /* Use all available DSP address space after EXTMEM
++ * for DMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, EXTEND,
++ &dwExtEnd);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed on "
++ "COD_GetSymValue %s.\n",
++ EXTEND);
++ }
++ }
++ /* Reset DMM structs and add an initial free chunk*/
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDmmMgr(pProcObject->hDevObject,
++ &hDmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ /* Set dwExtEnd to DMM START u8
++ * address */
++ dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
++ /* DMM memory is from EXT_END */
++ status = DMM_CreateTables(hDmmMgr,
++ dwExtEnd, DMMPOOLSIZE);
++ }
++ }
++ }
++ }
++ /* Restore the original argv[0] */
++ MEM_Free(newEnvp);
++ aArgv[0] = pargv0;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Processor Loaded\n");
++ DBC_Assert(uBrdState == BRD_LOADED);
++ }
++ }
++#endif
++func_end:
++#ifdef DEBUG
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
++ "Processor Load Failed.\n");
++
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Load, status: 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
++ || DSP_FAILED(status));
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv2);
++ if (tv2.tv_usec < tv1.tv_usec) {
++ tv2.tv_usec += 1000000;
++ tv2.tv_sec--;
++ }
++ GT_2trace(PROC_DebugMask, GT_1CLASS,
++ "Proc_Load: time to load %d sec and %d usec \n",
++ tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
++#endif
++ return status;
++}
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ */
++DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
++ void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
++{
++ u32 vaAlign;
++ u32 paAlign;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 sizeAlign;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
++ "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
++ "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
++ pReqAddr, ulMapAttr, ppMapAddr);
++ /* Calculate the page-aligned PA, VA and size */
++ vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
++ paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
++ sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
++ PG_SIZE_4K);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
++ "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
++
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Map: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ } else {
++ status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
++ }
++ /* Add mapping to the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++
++ status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
++ (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
++ ulMapAttr);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Mapped address = MSB of VA | LSB of PA */
++ *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
++ (PG_SIZE_4K - 1)));
++ } else {
++ DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ if (DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt, NULL,
++ (u32)pMpuAddr) != DSP_ENOTFOUND) {
++ DRV_InsertDMMResElement(&dmmRes, pCtxt);
++ DRV_UpdateDMMResElement(dmmRes, (u32)pMpuAddr,
++ ulSize, (u32)pReqAddr,
++ (u32)*ppMapAddr, hProcessor);
++ }
++ }
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events.
++ */
++DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(hNotification != NULL);
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_RegisterNotify, args:\n\t"
++ "hProcessor: 0x%x\n\tuEventMask: 0x%x\n\tuNotifyMask:"
++ " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
++ uNotifyType, hNotification);
++
++ /* Check processor handle */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_RegsiterNotify Invalid "
++ "ProcessorHandle 0x%x\n", hProcessor);
++ goto func_end;
++ }
++ /* Check if event mask is a valid processor related event */
++ if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
++ DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
++ DSP_SYSERROR))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
++ * then register event immediately. */
++ if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
++ status = NTFY_Register(pProcObject->hNtfy,
++ hNotification, uEventMask, uNotifyType);
++ /* * Special case alert, special case alert!
++ * If we're trying to *deregister* (i.e. uEventMask
++ * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
++ * we have to deregister with the DEH manager.
++ * There's no way to know, based on uEventMask which
++ * manager the notification event was registered with,
++ * so if we're trying to deregister and NTFY_Register
++ * failed, we'll give the deh manager a shot.
++ */
++ if ((uEventMask == 0) && DSP_FAILED(status)) {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->
++ pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ }
++ } else {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ */
++DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
++ void **ppRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_ReserveMemory, args:\n\t"
++ "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
++ ulSize, ppRsvAddr);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else
++ status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ */
++DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ u32 dwDspAddr; /* Loaded code's entry point. */
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :InValid Handle \n");
++ goto func_end;
++ }
++ /* Call the WMD_BRD_Start */
++ if (pProcObject->sState != PROC_LOADED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :Wrong state \n");
++ status = DSP_EWRONGSTATE;
++ goto func_end;
++ }
++ status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED "
++ "in Getting DEV_GetCodMgr status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = COD_GetEntry(hCodMgr, &dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED in "
++ "Getting COD_GetEntry status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pProcObject->pIntfFxns->pfnBrdStart)
++ (pProcObject->hWmdContext, dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start Failed to Start the board\n");
++ goto func_cont;
++ }
++ /* Call DEV_Create2 */
++ status = DEV_Create2(pProcObject->hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_RUNNING;
++ /* Deep sleep switces off the peripheral clocks.
++ * we just put the DSP CPU in idle in the idle loop.
++ * so there is no need to send a command to DSP */
++
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
++ "Started and running \n");
++ } else {
++ /* Failed to Create Node Manager and DISP Object
++ * Stop the Processor from running. Put it in STOPPED State */
++ (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ status = DSP_EFAIL;
++ pProcObject->sState = PROC_STOPPED;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
++ "Failed to Create the Node Manager\n");
++ }
++func_cont:
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Start: Processor State is RUNNING \n");
++ DBC_Assert(uBrdState != BRD_HIBERNATION);
++ }
++ }
++#endif
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Start, status 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
++ PROC_RUNNING) || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Stop a processor running.
++ */
++DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct MSG_MGR *hMsgMgr;
++ struct NODE_MGR *hNodeMgr;
++ DSP_HNODE hNode;
++ u32 uNodeTabSize = 1;
++ u32 uNumNodes = 0;
++ u32 uNodesAllocated = 0;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop :InValid Handle \n");
++ goto func_end;
++ }
++ /* check if there are any running nodes */
++ status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
++ if (DSP_SUCCEEDED(status) && hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
++ &uNumNodes, &uNodesAllocated);
++ if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Can't stop device, Active "
++ "nodes = 0x%x \n", uNodesAllocated);
++ return DSP_EWRONGSTATE;
++ }
++ }
++ /* Call the WMD_BRD_Stop */
++ /* It is OK to stop a device that does n't have nodes OR not started */
++ status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Stop: Processor Stopped, "
++ "i.e in standby mode \n");
++ pProcObject->sState = PROC_STOPPED;
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
++ pfnBrdStatus)(pProcObject->hWmdContext,
++ &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor Stopped \n");
++ DBC_Assert(uBrdState == BRD_STOPPED);
++ }
++#endif
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Couldn't delete node manager \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Failed to Stop the processor/device \n");
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status 0x%x\n",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ */
++DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 vaAlign;
++ u32 sizeAlign;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnMap, args:\n\thProcessor:"
++ "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
++
++ vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
++
++ status = DMM_GetHandle(hProcessor, &hDmmMgr);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Update DMM structures. Get the size to unmap.
++ This function returns error if the VA is not mapped */
++ status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
++ }
++ /* Remove mapping from the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
++ (pProcObject->hWmdContext, vaAlign, sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++#ifndef RES_CLEANUP_DISABLE
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "PROC_UnMap DRV_GetDMMResElement "
++ "pMapAddr:[0x%x]", pMapAddr);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, (u32)pMapAddr);
++ if (pCtxt != NULL) {
++ if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
++ DSP_ENOTFOUND)
++ DRV_RemoveDMMResElement(dmmRes, pCtxt);
++ }
++func_end:
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnMap [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ */
++DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnReserveMemory, args:\n\t"
++ "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
++
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status))
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_UnReserveMemory: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ else
++ status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnReserveMemory [0x%x]",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== = PROC_Monitor ======== ==
++ * Purpose:
++ * Place the Processor in Monitor State. This is an internal
++ * function and a requirement before Processor is loaded.
++ * This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
++ * In DEV_Destroy2 we delete the node manager.
++ * Parameters:
++ * hProcObject: Handle to Processor Object
++ * Returns:
++ * DSP_SOK: Processor placed in monitor mode.
++ * !DSP_SOK: Failed to place processor in monitor mode.
++ * Requires:
++ * Valid Processor Handle
++ * Ensures:
++ * Success: ProcObject state is PROC_IDLE
++ */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
++ struct MSG_MGR *hMsgMgr;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
++ "hProcessor: 0x%x\n", hProcObject);
++ /* This is needed only when Device is loaded when it is
++ * already 'ACTIVE' */
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++ }
++ /* Place the Board in the Monitor State */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
++ (pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor in "
++ "Monitor State\n");
++ DBC_Assert(uBrdState == BRD_IDLE);
++ }
++#endif
++ } else {
++ /* Monitor Failure */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Monitor: Processor Could not"
++ "be put in Monitor mode \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Monitor, status 0x%x\n",
++ status);
++#ifdef DEBUG
++ DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
++ DSP_FAILED(status));
++#endif
++ return status;
++}
++
++/*
++ * ======== GetEnvpCount ========
++ * Purpose:
++ * Return the number of elements in the envp array, including the
++ * terminating NULL element.
++ */
++static s32 GetEnvpCount(char **envp)
++{
++ s32 cRetval = 0;
++ if (envp) {
++ while (*envp++)
++ cRetval++;
++
++ cRetval += 1; /* Include the terminating NULL in the count. */
++ }
++
++ return cRetval;
++}
++
++/*
++ * ======== PrependEnvp ========
++ * Purpose:
++ * Prepend an environment variable=value pair to the new envp array, and
++ * copy in the existing var=value pairs in the old envp array.
++ */
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar)
++{
++ char **ppEnvp = newEnvp;
++
++ DBC_Require(newEnvp);
++
++ /* Prepend new environ var=value string */
++ *newEnvp++ = szVar;
++
++ /* Copy user's environment into our own. */
++ while (cEnvp--)
++ *newEnvp++ = *envp++;
++
++ /* Ensure NULL terminates the new environment strings array. */
++ if (cEnvp == 0)
++ *newEnvp = NULL;
++
++ return ppEnvp;
++}
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the processor the events.
++ */
++DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ NTFY_Notify(pProcObject->hNtfy, uEvents);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the processor the events. This includes notifying all clients
++ * attached to a particulat DSP.
++ */
++DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ DEV_NotifyClients(pProcObject->hDevObject, uEvents);
++
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyAllClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetProcessorId ========
++ * Purpose:
++ * Retrieves the processor ID.
++ */
++DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ *procID = pProcObject->uProcessor;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
+new file mode 100644
+index 0000000..50a3f79
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/pwr.c
+@@ -0,0 +1,184 @@
++/*
++ * pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== PWR.c ========
++ * PWR API for controlling DSP power states.
++ *
++ * Public Functions:
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
++ *! 29-Apr-2002 sg Initial.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/devdefs.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmdioctl.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Send command to DSP to enter sleep state.
++ */
++DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 ioctlcode = 0;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ continue;
++ }
++ if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ continue;
++ }
++ if (sleepCode == PWR_DEEPSLEEP)
++ ioctlcode = WMDIOCTL_DEEPSLEEP;
++ else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
++ ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
++ else
++ status = DSP_EINVALIDARG;
++
++ if (status != DSP_EINVALIDARG) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ ioctlcode, (void *)&arg);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Send command to DSP to wake it from sleep.
++ */
++DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_WAKEUP, (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PreScale========
++ * Sends pre-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_PRESCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PostScale========
++ * Sends post-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_POSTSCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++
++}
++
++
+diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
+new file mode 100644
+index 0000000..575f675
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/rmm.c
+@@ -0,0 +1,604 @@
++/*
++ * rmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.c ========
++ * Description:
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments.
++ *
++ * Notes:
++ *
++ * Memory blocks are allocated from the end of the first free memory
++ * block large enough to satisfy the request. Alignment requirements
++ * are satisfied by "sliding" the block forward until its base satisfies
++ * the alignment specification; if this is not possible then the next
++ * free block large enough to hold the request is tried.
++ *
++ * Since alignment can cause the creation of a new free block - the
++ * unused memory formed between the start of the original free block
++ * and the start of the allocated block - the memory manager must free
++ * this memory to prevent a memory leak.
++ *
++ * Overlay memory is managed by reserving through RMM_alloc, and freeing
++ * it through RMM_free. The memory manager prevents DSP code/data that is
++ * overlayed from being overwritten as long as the memory it runs at has
++ * been allocated, and not yet freed.
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux Platform.
++ *! 24-Sep-2002 map Updated from Code Review
++ *! 25-Jun-2002 jeh Free from segid passed to RMM_free().
++ *! 24-Apr-2002 jeh Determine segid based on address in RMM_free(). (No way
++ *! to keep track of segid with dynamic loader library.)
++ *! 16-Oct-2001 jeh Based on gen tree rm.c. Added support for overlays.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/rmm.h>
++
++#define RMM_TARGSIGNATURE 0x544d4d52 /* "TMMR" */
++
++/*
++ * ======== RMM_Header ========
++ * This header is used to maintain a list of free memory blocks.
++ */
++struct RMM_Header {
++ struct RMM_Header *next; /* form a free memory link list */
++ u32 size; /* size of the free memory */
++ u32 addr; /* DSP address of memory block */
++} ;
++
++/*
++ * ======== RMM_OvlySect ========
++ * Keeps track of memory occupied by overlay section.
++ */
++struct RMM_OvlySect {
++ struct LST_ELEM listElem;
++ u32 addr; /* Start of memory section */
++ u32 size; /* Length (target MAUs) of section */
++ s32 page; /* Memory page */
++};
++
++/*
++ * ======== RMM_TargetObj ========
++ */
++struct RMM_TargetObj {
++ u32 dwSignature;
++ struct RMM_Segment *segTab;
++ struct RMM_Header **freeList;
++ u32 numSegs;
++ struct LST_LIST *ovlyList; /* List of overlay memory in use */
++};
++
++#if GT_TRACE
++static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr);
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size);
++
++/*
++ * ======== RMM_alloc ========
++ */
++DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr, bool reserve)
++{
++ struct RMM_OvlySect *sect;
++ struct RMM_OvlySect *prevSect = NULL;
++ struct RMM_OvlySect *newSect;
++ u32 addr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++ DBC_Require(dspAddr != NULL);
++ DBC_Require(size > 0);
++ DBC_Require(reserve || (target->numSegs > 0));
++ DBC_Require(cRefs > 0);
++
++ GT_6trace(RMM_debugMask, GT_ENTER,
++ "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
++ reserve);
++ if (!reserve) {
++ if (!allocBlock(target, segid, size, align, dspAddr)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Increment the number of allocated blocks in this
++ * segment */
++ target->segTab[segid].number++;
++ }
++ goto func_end;
++ }
++ /* An overlay section - See if block is already in use. If not,
++ * insert into the list in ascending address size. */
++ addr = *dspAddr;
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ /* Find place to insert new list element. List is sorted from
++ * smallest to largest address. */
++ while (sect != NULL) {
++ if (addr <= sect->addr) {
++ /* Check for overlap with sect */
++ if ((addr + size > sect->addr) || (prevSect &&
++ (prevSect->addr + prevSect->size > addr))) {
++ status = DSP_EOVERLAYMEMORY;
++ }
++ break;
++ }
++ prevSect = sect;
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* No overlap - allocate list element for new section. */
++ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
++ if (newSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ LST_InitElem((struct LST_ELEM *)newSect);
++ newSect->addr = addr;
++ newSect->size = size;
++ newSect->page = segid;
++ if (sect == NULL) {
++ /* Put new section at the end of the list */
++ LST_PutTail(target->ovlyList,
++ (struct LST_ELEM *)newSect);
++ } else {
++ /* Put new section just before sect */
++ LST_InsertBefore(target->ovlyList,
++ (struct LST_ELEM *)newSect,
++ (struct LST_ELEM *)sect);
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== RMM_create ========
++ */
++DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs)
++{
++ struct RMM_Header *hptr;
++ struct RMM_Segment *sptr, *tmp;
++ struct RMM_TargetObj *target;
++ s32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pTarget != NULL);
++ DBC_Require(numSegs == 0 || segTab != NULL);
++
++ GT_3trace(RMM_debugMask, GT_ENTER,
++ "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
++ pTarget, segTab, numSegs);
++
++ /* Allocate DBL target object */
++ MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
++
++ if (target == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ target->numSegs = numSegs;
++ if (!(numSegs > 0))
++ goto func_cont;
++
++ /* Allocate the memory for freelist from host's memory */
++ target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
++ MEM_PAGED);
++ if (target->freeList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Allocate headers for each element on the free list */
++ for (i = 0; i < (s32) numSegs; i++) {
++ target->freeList[i] =
++ MEM_Calloc(sizeof(struct RMM_Header),
++ MEM_PAGED);
++ if (target->freeList[i] == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ }
++ /* Allocate memory for initial segment table */
++ target->segTab = MEM_Calloc(numSegs *
++ sizeof(struct RMM_Segment), MEM_PAGED);
++ if (target->segTab == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Initialize segment table and free list */
++ sptr = target->segTab;
++ for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
++ *sptr = *tmp;
++ hptr = target->freeList[i];
++ hptr->addr = tmp->base;
++ hptr->size = tmp->length;
++ hptr->next = NULL;
++ tmp++;
++ sptr++;
++ }
++ }
++ }
++func_cont:
++ /* Initialize overlay memory list */
++ if (DSP_SUCCEEDED(status)) {
++ target->ovlyList = LST_Create();
++ if (target->ovlyList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = target;
++ } else {
++ *pTarget = NULL;
++ if (target)
++ RMM_delete(target);
++
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
++ RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
++ NULL));
++
++ return status;
++}
++
++/*
++ * ======== RMM_delete ========
++ */
++void RMM_delete(struct RMM_TargetObj *target)
++{
++ struct RMM_OvlySect *pSect;
++ struct RMM_Header *hptr;
++ struct RMM_Header *next;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
++
++ if (target->segTab != NULL)
++ MEM_Free(target->segTab);
++
++ if (target->ovlyList) {
++ while ((pSect = (struct RMM_OvlySect *)LST_GetHead
++ (target->ovlyList))) {
++ MEM_Free(pSect);
++ }
++ DBC_Assert(LST_IsEmpty(target->ovlyList));
++ LST_Delete(target->ovlyList);
++ }
++
++ if (target->freeList != NULL) {
++ /* Free elements on freelist */
++ for (i = 0; i < target->numSegs; i++) {
++ hptr = next = target->freeList[i];
++ while (next) {
++ hptr = next;
++ next = hptr->next;
++ MEM_Free(hptr);
++ }
++ }
++ MEM_Free(target->freeList);
++ }
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== RMM_exit ========
++ */
++void RMM_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0)
++ MEM_Exit();
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== RMM_free ========
++ */
++bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
++ bool reserved)
++
++{
++ struct RMM_OvlySect *sect;
++ bool retVal = true;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ DBC_Require(reserved || segid < target->numSegs);
++ DBC_Require(reserved || (addr >= target->segTab[segid].base &&
++ (addr + size) <= (target->segTab[segid].base +
++ target->segTab[segid].length)));
++
++ GT_5trace(RMM_debugMask, GT_ENTER,
++ "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx)\n", target, segid, addr, size, reserved);
++ /*
++ * Free or unreserve memory.
++ */
++ if (!reserved) {
++ retVal = freeBlock(target, segid, addr, size);
++ if (retVal)
++ target->segTab[segid].number--;
++
++ } else {
++ /* Unreserve memory */
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ while (sect != NULL) {
++ if (addr == sect->addr) {
++ DBC_Assert(size == sect->size);
++ /* Remove from list */
++ LST_RemoveElem(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ MEM_Free(sect);
++ break;
++ }
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (sect == NULL)
++ retVal = false;
++
++ }
++ return retVal;
++}
++
++/*
++ * ======== RMM_init ========
++ */
++bool RMM_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!RMM_debugMask.flags);
++ GT_create(&RMM_debugMask, "RM"); /* "RM" for RMm */
++
++ retVal = MEM_Init();
++
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS,
++ "RMM_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== RMM_stat ========
++ */
++bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf)
++{
++ struct RMM_Header *head;
++ bool retVal = false;
++ u32 maxFreeSize = 0;
++ u32 totalFreeSize = 0;
++ u32 freeBlocks = 0;
++
++ DBC_Require(pMemStatBuf != NULL);
++ DBC_Assert(target != NULL);
++
++ if ((u32) segid < target->numSegs) {
++ head = target->freeList[segid];
++
++ /* Collect data from freeList */
++ while (head != NULL) {
++ maxFreeSize = max(maxFreeSize, head->size);
++ totalFreeSize += head->size;
++ freeBlocks++;
++ head = head->next;
++ }
++
++ /* ulSize */
++ pMemStatBuf->ulSize = target->segTab[segid].length;
++
++ /* ulNumFreeBlocks */
++ pMemStatBuf->ulNumFreeBlocks = freeBlocks;
++
++ /* ulTotalFreeSize */
++ pMemStatBuf->ulTotalFreeSize = totalFreeSize;
++
++ /* ulLenMaxFreeBlock */
++ pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
++
++ /* ulNumAllocBlocks */
++ pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
++
++ retVal = true;
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== balloc ========
++ * This allocation function allocates memory from the lowest addresses
++ * first.
++ */
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *prevhead = NULL;
++ struct RMM_Header *next;
++ u32 tmpalign;
++ u32 alignbytes;
++ u32 hsize;
++ u32 allocsize;
++ u32 addr;
++
++ alignbytes = (align == 0) ? 1 : align;
++ prevhead = NULL;
++ head = target->freeList[segid];
++
++ do {
++ hsize = head->size;
++ next = head->next;
++
++ addr = head->addr; /* alloc from the bottom */
++
++ /* align allocation */
++ (tmpalign = (u32) addr % alignbytes);
++ if (tmpalign != 0)
++ tmpalign = alignbytes - tmpalign;
++
++ allocsize = size + tmpalign;
++
++ if (hsize >= allocsize) { /* big enough */
++ if (hsize == allocsize && prevhead != NULL) {
++ prevhead->next = next;
++ MEM_Free(head);
++ } else {
++ head->size = hsize - allocsize;
++ head->addr += allocsize;
++ }
++
++ /* free up any hole created by alignment */
++ if (tmpalign)
++ freeBlock(target, segid, addr, tmpalign);
++
++ *dspAddr = addr + tmpalign;
++ return true;
++ }
++
++ prevhead = head;
++ head = next;
++
++ } while (head != NULL);
++
++ return false;
++}
++
++/*
++ * ======== freeBlock ========
++ * TO DO: freeBlock() allocates memory, which could result in failure.
++ * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
++ * freeBlock() could use an RMM_Header from the pool, freeing as blocks
++ * are coalesced.
++ */
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *thead;
++ struct RMM_Header *rhead;
++ bool retVal = true;
++
++ /* Create a memory header to hold the newly free'd block. */
++ rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
++ if (rhead == NULL) {
++ retVal = false;
++ } else {
++ /* search down the free list to find the right place for addr */
++ head = target->freeList[segid];
++
++ if (addr >= head->addr) {
++ while (head->next != NULL && addr > head->next->addr)
++ head = head->next;
++
++ thead = head->next;
++
++ head->next = rhead;
++ rhead->next = thead;
++ rhead->addr = addr;
++ rhead->size = size;
++ } else {
++ *rhead = *head;
++ head->next = rhead;
++ head->addr = addr;
++ head->size = size;
++ thead = rhead->next;
++ }
++
++ /* join with upper block, if possible */
++ if (thead != NULL && (rhead->addr + rhead->size) ==
++ thead->addr) {
++ head->next = rhead->next;
++ thead->size = size + thead->size;
++ thead->addr = addr;
++ MEM_Free(rhead);
++ rhead = thead;
++ }
++
++ /* join with the lower block, if possible */
++ if ((head->addr + head->size) == rhead->addr) {
++ head->next = rhead->next;
++ head->size = head->size + rhead->size;
++ MEM_Free(rhead);
++ }
++ }
++
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
+new file mode 100644
+index 0000000..bd55fd3
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/strm.c
+@@ -0,0 +1,1066 @@
++/*
++ * strm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.c ========
++ * Description:
++ * DSP/BIOS Bridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 13-Mar-2002 map pStrm init'd to NULL in STRM_Open to prevent error
++ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
++ *! in DEV and CMM function calls to avoid confusion.
++ *! Return DSP_SOK instead of S_OK from API fxns.
++ *! 12-Mar-2002 map Changed FAILED(..) to DSP_FAILED(..)
++ *! 25-Jan-2002 ag Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
++ *! 15-Nov-2001 ag Added STRMMODE & SM for DMA/ZCopy streaming.
++ *! Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Use strm timeout value for dma flush timeout.
++ *! 09-May-2001 jeh Code review cleanup.
++ *! 06-Feb-2001 kc Updated DBC_Ensure in STRM_Select to check timeout.
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
++ *! tests to pass.
++ *! 25-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodepriv.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/strm.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define STRM_SIGNATURE 0x4d525453 /* "MRTS" */
++#define STRMMGR_SIGNATURE 0x5254534d /* "RTSM" */
++
++#define DEFAULTTIMEOUT 10000
++#define DEFAULTNUMBUFS 2
++
++/*
++ * ======== STRM_MGR ========
++ * The STRM_MGR contains device information needed to open the underlying
++ * channels of a stream.
++ */
++struct STRM_MGR {
++ u32 dwSignature;
++ struct DEV_OBJECT *hDev; /* Device for this processor */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++} ;
++
++/*
++ * ======== STRM_OBJECT ========
++ * This object is allocated in STRM_Open().
++ */
++ struct STRM_OBJECT {
++ u32 dwSignature;
++ struct STRM_MGR *hStrmMgr;
++ struct CHNL_OBJECT *hChnl;
++ u32 uDir; /* DSP_TONODE or DSP_FROMNODE */
++ u32 uTimeout;
++ u32 uNumBufs; /* Max # of bufs allowed in stream */
++ u32 uNBufsInStrm; /* Current # of bufs in stream */
++ u32 ulNBytes; /* bytes transferred since idled */
++ enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
++ HANDLE hUserEvent; /* Saved for STRM_GetInfo() */
++ enum DSP_STRMMODE lMode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
++ u32 uDMAChnlId; /* DMA chnl id */
++ u32 uDMAPriority; /* DMA priority:DMAPRI_[LOW][HIGH] */
++ u32 uSegment; /* >0 is SM segment.=0 is local heap */
++ u32 uAlignment; /* Alignment for stream bufs */
++ struct CMM_XLATOROBJECT *hXlator; /* Stream's SM address translator */
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask STRM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocates buffers for a stream.
++ */
++DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
++ OUT u8 **apBuffer, u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uAllocated = 0;
++ u32 i;
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
++ "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
++ hStrm, uSize, apBuffer, uNumBufs);
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ /*
++ * Allocate from segment specified at time of stream open.
++ */
++ if (uSize == 0)
++ status = DSP_ESIZE;
++
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
++ if (apBuffer[i] == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_AllocateBuffer: "
++ "DSP_FAILED to alloc shared memory.\n");
++ status = DSP_EMEMORY;
++ uAllocated = i;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
++ }
++ }
++#endif
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ */
++DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Have all buffers been reclaimed? If not, return
++ * DSP_EPENDING */
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ DBC_Assert(DSP_SUCCEEDED(status));
++
++ if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
++ status = DSP_EPENDING;
++ } else {
++
++ status = DeleteStrm(hStrm);
++
++ if (DSP_FAILED(status)) {
++ /* we already validated the handle. */
++ DBC_Assert(status != DSP_EHANDLE);
++
++ /* make sure we return a documented result */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
++ }
++ }
++func_end:
++#endif
++ DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
++ status == DSP_EPENDING || status == DSP_EFAIL);
++
++ return status;
++}
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object.
++ */
++DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
++{
++ struct STRM_MGR *pStrmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrmMgr != NULL);
++ DBC_Require(hDev != NULL);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
++ "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
++ *phStrmMgr = NULL;
++ /* Allocate STRM manager object */
++ MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
++ if (pStrmMgr == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "MEM_AllocObject() failed!\n ");
++ } else {
++ pStrmMgr->hDev = hDev;
++ }
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
++ DBC_Assert(pStrmMgr->pIntfFxns != NULL);
++ } else {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "Failed to get channel manager! status = "
++ "0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pStrmMgr->hSync);
++
++ if (DSP_SUCCEEDED(status))
++ *phStrmMgr = pStrmMgr;
++ else
++ DeleteStrmMgr(pStrmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
++ (DSP_FAILED(status) && *phStrmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Manager Object.
++ */
++void STRM_Delete(struct STRM_MGR *hStrmMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
++ hStrmMgr);
++
++ DeleteStrmMgr(hStrmMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++}
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ */
++void STRM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS,
++ "Entered STRM_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Frees the buffers allocated for a stream.
++ */
++DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
++ u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 i = 0;
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes = NULL;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
++ "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
++ if (DSP_FAILED(status)) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_FreeBuffer: DSP_FAILED"
++ " to free shared memory.\n");
++ break;
++ }
++ apBuffer[i] = NULL;
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
++ pCtxt);
++ }
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Retrieves information about a stream.
++ */
++DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++ void *pVirtBase = NULL; /* NULL if no SM used */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStreamInfo != NULL);
++ DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
++ "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
++ pStreamInfo, uStreamInfoSize);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
++ /* size of users info */
++ status = DSP_ESIZE;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (hStrm->hXlator) {
++ /* We have a translator */
++ DBC_Assert(hStrm->uSegment > 0);
++ CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
++ hStrm->uSegment, false);
++ }
++ pStreamInfo->uSegment = hStrm->uSegment;
++ pStreamInfo->lMode = hStrm->lMode;
++ pStreamInfo->pVirtBase = pVirtBase;
++ pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
++ pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
++ chnlInfo.cIOReqs;
++ /* # of bytes transferred since last call to DSPStream_Idle() */
++ pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
++ pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
++ /* Determine stream state based on channel state and info */
++ if (chnlInfo.dwState & CHNL_STATEEOS) {
++ pStreamInfo->pUser->ssStreamState = STREAM_DONE;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_READY;
++ else if (chnlInfo.cIOReqs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
++ else
++ pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
++
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idles a particular stream.
++ */
++DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
++ "fFlush: 0x%x\n", hStrm, fFlush);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
++ hStrm->uTimeout, fFlush);
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ */
++bool STRM_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++#if GT_TRACE
++ DBC_Assert(!STRM_debugMask.flags);
++ GT_create(&STRM_debugMask, "ST"); /* "ST" for STrm */
++#endif
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++
++ return fRetVal;
++}
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Issues a buffer on a stream
++ */
++DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
++ u32 ulBufSize, u32 dwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuf != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
++ "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
++ dwArg);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ if (hStrm->uSegment != 0) {
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ (void *)pBuf, CMM_VA2DSPPA);
++ if (pTmpBuf == NULL)
++ status = DSP_ETRANSLATE;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pIntfFxns->pfnChnlAddIOReq)
++ (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
++ (u32) pTmpBuf, dwArg);
++ }
++ if (DSP_FAILED(status)) {
++ if (status == CHNL_E_NOIORPS)
++ status = DSP_ESTREAMFULL;
++ else
++ status = DSP_EFAIL;
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task or
++ * XDAIS socket node on the DSP.
++ */
++DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
++{
++ struct STRM_MGR *hStrmMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct STRM_OBJECT *pStrm = NULL;
++ CHNL_MODE uMode;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrm != NULL);
++ DBC_Require(pAttr != NULL);
++ GT_5trace(STRM_debugMask, GT_ENTER,
++ "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
++ "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
++ hNode, uDir, uIndex, pAttr, phStrm);
++ *phStrm = NULL;
++ if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
++ status = DSP_EDIRECTION;
++ } else {
++ /* Get the channel id from the node (set in NODE_Connect()) */
++ status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
++ }
++ if (DSP_SUCCEEDED(status))
++ status = NODE_GetStrmMgr(hNode, &hStrmMgr);
++
++ if (DSP_SUCCEEDED(status)) {
++ MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
++ if (pStrm == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: MEM_AllocObject() failed!\n ");
++ } else {
++ pStrm->hStrmMgr = hStrmMgr;
++ pStrm->uDir = uDir;
++ pStrm->strmState = STREAM_IDLE;
++ pStrm->hUserEvent = pAttr->hUserEvent;
++ if (pAttr->pStreamAttrIn != NULL) {
++ pStrm->uTimeout = pAttr->pStreamAttrIn->
++ uTimeout;
++ pStrm->uNumBufs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ pStrm->lMode = pAttr->pStreamAttrIn->lMode;
++ pStrm->uSegment = pAttr->pStreamAttrIn->
++ uSegment;
++ pStrm->uAlignment = pAttr->pStreamAttrIn->
++ uAlignment;
++ pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
++ uDMAChnlId;
++ pStrm->uDMAPriority = pAttr->pStreamAttrIn->
++ uDMAPriority;
++ chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ } else {
++ pStrm->uTimeout = DEFAULTTIMEOUT;
++ pStrm->uNumBufs = DEFAULTNUMBUFS;
++ pStrm->lMode = STRMMODE_PROCCOPY;
++ pStrm->uSegment = 0; /* local memory */
++ pStrm->uAlignment = 0;
++ pStrm->uDMAChnlId = 0;
++ pStrm->uDMAPriority = 0;
++ chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
++ }
++ chnlAttrs.hReserved1 = NULL;
++ /* DMA chnl flush timeout */
++ chnlAttrs.hReserved2 = pStrm->uTimeout;
++ chnlAttrs.hEvent = NULL;
++ if (pAttr->hUserEvent != NULL)
++ chnlAttrs.hEvent = pAttr->hUserEvent;
++
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
++ goto func_cont;
++
++ DBC_Assert(pStrm->lMode != STRMMODE_LDMA); /* no System DMA */
++ /* Get the shared mem mgr for this streams dev object */
++ status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
++ "CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /*Allocate a SM addr translator for this strm.*/
++ status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Failed to "
++ "create SM translator: 0x%x\n", status);
++ } else {
++ DBC_Assert(pStrm->uSegment > 0);
++ /* Set translators Virt Addr attributes */
++ status = CMM_XlatorInfo(pStrm->hXlator,
++ (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
++ pStrm->uSegment, true);
++ if (status != DSP_SOK) {
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: ERROR: "
++ "in setting CMM_XlatorInfo.\n");
++ }
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Open channel */
++ uMode = (uDir == DSP_TONODE) ?
++ CHNL_MODETODSP : CHNL_MODEFROMDSP;
++ pIntfFxns = hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
++ hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ /*
++ * over-ride non-returnable status codes so we return
++ * something documented
++ */
++ if (status != DSP_EMEMORY && status !=
++ DSP_EINVALIDARG && status != DSP_EFAIL) {
++ /*
++ * We got a status that's not return-able.
++ * Assert that we got something we were
++ * expecting (DSP_EHANDLE isn't acceptable,
++ * hStrmMgr->hChnlMgr better be valid or we
++ * assert here), and then return DSP_EFAIL.
++ */
++ DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
++ status == CHNL_E_BADCHANID ||
++ status == CHNL_E_CHANBUSY ||
++ status == CHNL_E_NOIORPS);
++ status = DSP_EFAIL;
++ }
++ GT_2trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Channel open failed, "
++ "chnl id = %d, status = 0x%x\n", ulChnlId,
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phStrm = pStrm;
++ else
++ (void)DeleteStrm(pStrm);
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ hNode, 0);
++ if (pCtxt != NULL)
++ DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
++
++ }
++#endif
++
++ /* ensure we return a documented error code */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
++ (*phStrm == NULL && (status == DSP_EHANDLE ||
++ status == DSP_EDIRECTION || status == DSP_EVALUE ||
++ status == DSP_EFAIL)));
++ return status;
++}
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Relcaims a buffer from a stream.
++ */
++DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
++ u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPtr != NULL);
++ DBC_Require(pulBytes != NULL);
++ DBC_Require(pdwArg != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
++ "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
++ pdwArg);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
++ &chnlIOC);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Reclaim: GetIOC failed! "
++ "Status = 0x%x\n", status);
++ } else {
++ *pulBytes = chnlIOC.cBytes;
++ if (pulBufSize)
++ *pulBufSize = chnlIOC.cBufSize;
++
++ *pdwArg = chnlIOC.dwArg;
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ /* Allow reclaims after idle to succeed */
++ if (!CHNL_IsIOCancelled(chnlIOC))
++ status = DSP_EFAIL;
++
++ }
++ }
++ /* Translate zerocopy buffer if channel not canceled. */
++ if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
++ (hStrm->lMode == STRMMODE_ZEROCOPY)) {
++ /*
++ * This is a zero-copy channel so chnlIOC.pBuf
++ * contains the DSP address of SM. We need to
++ * translate it to a virtual address for the user
++ * thread to access.
++ * Note: Could add CMM_DSPPA2VA to CMM in the future.
++ */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ chnlIOC.pBuf, CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ pTmpBuf, CMM_PA2VA);
++ }
++ if (pTmpBuf == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_Reclaim: Failed "
++ "SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ chnlIOC.pBuf = pTmpBuf;
++ }
++ *pBufPtr = chnlIOC.pBuf;
++ }
++func_end:
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ */
++DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_RegisterNotify: hStrm: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hStrm, uEventMask, uNotifyType, hNotification);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
++ DSP_STREAMDONE)) != 0) {
++ status = DSP_EVALUE;
++ } else {
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_ENOTIMPL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
++ uEventMask, uNotifyType, hNotification);
++ }
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_ENOTIMPL || status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Selects a ready stream.
++ */
++DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout)
++{
++ u32 uIndex;
++ struct CHNL_INFO chnlInfo;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct SYNC_OBJECT **hSyncEvents = NULL;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aStrmTab != NULL);
++ DBC_Require(pMask != NULL);
++ DBC_Require(nStrms > 0);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Select: aStrmTab: 0x%x \tnStrms: "
++ "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
++ nStrms, pMask, uTimeout);
++ *pMask = 0;
++ for (i = 0; i < nStrms; i++) {
++ if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Determine which channels have IO ready */
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
++ &chnlInfo);
++ if (DSP_FAILED(status)) {
++ break;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ *pMask |= (1 << i);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
++ /* Non-zero timeout */
++ hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
++ sizeof(struct SYNC_OBJECT *), MEM_PAGED);
++ if (hSyncEvents == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)
++ (aStrmTab[i]->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ break;
++ else
++ hSyncEvents[i] = chnlInfo.hSyncEvent;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
++ uTimeout, &uIndex);
++ if (DSP_SUCCEEDED(status)) {
++ /* Since we waited on the event, we have to
++ * reset it */
++ SYNC_SetEvent(hSyncEvents[uIndex]);
++ *pMask = 1 << uIndex;
++ }
++ }
++ }
++func_end:
++ if (hSyncEvents)
++ MEM_Free(hSyncEvents);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
++ (DSP_FAILED(status) && *pMask == 0));
++
++ return status;
++}
++
++/*
++ * ======== DeleteStrm ========
++ * Purpose:
++ * Frees the resources allocated for a stream.
++ */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ if (hStrm->hChnl) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
++ /* Free all SM address translator resources */
++ if (DSP_SUCCEEDED(status)) {
++ if (hStrm->hXlator) {
++ /* force free */
++ (void)CMM_XlatorDelete(hStrm->hXlator,
++ true);
++ }
++ }
++ }
++ MEM_FreeObject(hStrm);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== DeleteStrmMgr ========
++ * Purpose:
++ * Frees stream manager.
++ */
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
++{
++ if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
++
++ if (hStrmMgr->hSync)
++ SYNC_DeleteCS(hStrmMgr->hSync);
++
++ MEM_FreeObject(hStrmMgr);
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
+new file mode 100644
+index 0000000..67656bf
+--- /dev/null
++++ b/drivers/dsp/bridge/services/cfg.c
+@@ -0,0 +1,483 @@
++/*
++ * cfg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfgce.c ========
++ * Purpose:
++ * Implementation of platform specific config services.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Arp-2004 hp Support for handling more than one Device.
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
++ *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
++ *! 10-Aug-2000 rr: Cosmetic changes.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
++ *! replaces CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Comments and bugfixes: modified after code review
++ *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks strlen of the
++ *! read value from the registry against the passed in BufSize;
++ *! CFG_GetZLFile,CFG_GetWMDFileName and
++ *! CFG_GetExecFile also modified same way.
++ *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
++ *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
++ *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
++ *! CFG_GetDevNode reads the Devnodestring from the registry.
++ *! CFG_SetDevObject stores the registry path as
++ *! DevNodestring in the registry.
++ *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
++ *! 22-Nov-1999 kc: Added windows.h to remove warnings.
++ *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
++ *! from the registry which was set by the DRV Request
++ *! Resources.
++ *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
++ *! changes for drv.h resource structure and wsxreg.h new
++ *! entry(DevObject) Hard coded entries removed for those items
++ *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
++ *! registry. CFG_Get HostResources modified for opening up
++ *! two mem winodws.
++ *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
++ *! type of Resource Structure.
++ *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
++#endif
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ */
++void CFG_Exit(void)
++{
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
++}
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ */
++DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetAutoStart: \n\thDevNode:"
++ "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
++ dwBufSize = sizeof(*pdwAutoStart);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++ if (!pdwAutoStart)
++ status = CFG_E_INVALIDPOINTER;
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
++ (u8 *)pdwAutoStart, &dwBufSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetAutoStart SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetAutoStart Failed \n");
++ }
++#endif
++ DBC_Ensure((status == DSP_SOK &&
++ (*pdwAutoStart == 0 || *pdwAutoStart == 1))
++ || status != DSP_SOK);
++ return status;
++}
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ */
++DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
++ "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
++ *pdwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pdwValue)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBufSize = sizeof(pdwValue);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* check the device string and then call the REG_SetValue*/
++ if (!(strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Fetching DSP Device from "
++ "Registry \n");
++ status = REG_GetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP",
++ (u8 *)pdwValue, &dwBufSize);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Identify the Device to Fetch \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDevObject SUCCESS DevObject"
++ ": 0x%x\n ", *pdwValue);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ */
++DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable)
++{
++ DSP_STATUS status = DSP_SOK; /* return value */
++ u32 dwResSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetDSPResources, args: "
++ "\n\thDevNode: 0x%x\n\tpDSPResTable: 0x%x\n",
++ hDevNode, pDSPResTable);
++ if (!hDevNode) {
++ status = CFG_E_INVALIDHDEVNODE;
++ } else if (!pDSPResTable) {
++ status = CFG_E_INVALIDPOINTER;
++ } else {
++ status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
++ (u8 *)pDSPResTable,
++ &dwResSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDSPResources SUCCESS\n");
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDSPResources Failed \n");
++ }
++#ifdef DEBUG
++ /* assert that resource values are reasonable */
++ DBC_Assert(pDSPResTable->uChipType < 256);
++ DBC_Assert(pDSPResTable->uWordSize > 0);
++ DBC_Assert(pDSPResTable->uWordSize < 32);
++ DBC_Assert(pDSPResTable->cChips > 0);
++ DBC_Assert(pDSPResTable->cChips < 256);
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ */
++DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
++ OUT char *pstrExecFile)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 cExecSize = ulBufSize;
++ GT_3trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetExecFile:\n\tthDevNode: "
++ "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
++ ulBufSize, pstrExecFile);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pstrExecFile)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
++ (u8 *)pstrExecFile, &cExecSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ else if (cExecSize > ulBufSize)
++ status = DSP_ESIZE;
++
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetExecFile SUCCESS Exec File"
++ "name : %s\n ", pstrExecFile);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetExecFile Failed \n");
++ }
++#endif
++ DBC_Ensure(((status == DSP_SOK) &&
++ (strlen(pstrExecFile) <= ulBufSize)) || (status != DSP_SOK));
++ return status;
++}
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host allocated resources assigned to a given device.
++ */
++DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetHostResources, args:\n\t"
++ "pHostResTable: 0x%x\n\thDevNode: 0x%x\n",
++ pHostResTable, hDevNode);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pHostResTable)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ dwBufSize = sizeof(struct CFG_HOSTRES);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
++ CURRENTCONFIG,
++ (u8 *)pHostResTable, &dwBufSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetHostResources SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetHostResources Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Object handle from the Registry
++ */
++DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBufSize;
++ DBC_Require(pdwValue != NULL);
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetObject, args:pdwValue: "
++ "0x%x\n", *pdwValue);
++ dwBufSize = sizeof(pdwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, MGROBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ default:
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetObject SUCCESS DrvObject: "
++ "0x%x\n ", *pdwValue);
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ *pdwValue = 0;
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
++ (DSP_FAILED(status) && *pdwValue == 0));
++ return status;
++}
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ */
++bool CFG_Init(void)
++{
++ struct CFG_DSPRES dspResources;
++ GT_create(&CFG_debugMask, "CF"); /* CF for ConFig */
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
++
++ dspResources.uChipType = DSPTYPE_64;
++ dspResources.cChips = 1;
++ dspResources.uWordSize = DSPWORDSIZE;
++ dspResources.cMemTypes = 0;
++ dspResources.aMemDesc[0].uMemType = 0;
++ dspResources.aMemDesc[0].ulMin = 0;
++ dspResources.aMemDesc[0].ulMax = 0;
++ if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
++ (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Initialized DSP resources in "
++ "Registry \n");
++ } else
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Failed to Initialize DSP resources"
++ " in Registry \n");
++ return true;
++}
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle and devNode pointer for a given devnode.
++ */
++DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBuffSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetDevObject, args: \n\t"
++ "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBuffSize = sizeof(dwValue);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the WCD device object in the Registry */
++
++ if (!(strcmp((char *)hDevNode, "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Registering the DSP Device \n");
++ status = REG_SetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP", REG_DWORD,\
++ (u8 *)&dwValue, dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ dwBuffSize = sizeof(hDevNode);
++ status = REG_SetValue(NULL,
++ (char *)hDevNode, "DEVNODESTRING_DSP",
++ REG_DWORD, (u8 *)&hDevNode,
++ dwBuffSize);
++ }
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Register Device \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_SetDevObject SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_SetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_SetObject ========
++ * Purpose:
++ * Store the Driver Object handle
++ */
++DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBuffSize;
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetObject, args: dwValue: "
++ "0x%x\n", dwValue);
++ dwBuffSize = sizeof(dwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
++ (u8 *)&dwValue, dwBuffSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
++ (u8 *) &dwValue, dwBuffSize);
++ break;
++ default:
++ break;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status))
++ GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
++ else
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
++
++#endif
++ return status;
++}
+diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
+new file mode 100644
+index 0000000..b499b14
+--- /dev/null
++++ b/drivers/dsp/bridge/services/clk.c
+@@ -0,0 +1,375 @@
++/*
++ * clk.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.c ========
++ * Purpose:
++ * Clock and Timer services.
++ *
++ * Public Functions:
++ * CLK_Exit
++ * CLK_Init
++ * CLK_Enable
++ * CLK_Disable
++ * CLK_GetRate
++ * CLK_Set_32KHz
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: moved all clock functions from sync module.
++ * And added CLK_Set_32KHz, CLK_Set_SysClk.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++typedef volatile unsigned long REG_UWORD32;
++
++#define SSI_Base 0x48058000
++
++#define SSI_BASE IO_ADDRESS(SSI_Base)
++
++
++struct SERVICES_Clk_t {
++ struct clk *clk_handle;
++ const char *clk_name;
++ int id;
++};
++
++/* The row order of the below array needs to match with the clock enumerations
++ * 'SERVICES_ClkId' provided in the header file.. any changes in the
++ * enumerations needs to be fixed in the array as well */
++static struct SERVICES_Clk_t SERVICES_Clks[] = {
++ {NULL, "iva2_ck", -1},
++ {NULL, "mailboxes_ick", -1},
++ {NULL, "gpt5_fck", -1},
++ {NULL, "gpt5_ick", -1},
++ {NULL, "gpt6_fck", -1},
++ {NULL, "gpt6_ick", -1},
++ {NULL, "gpt7_fck", -1},
++ {NULL, "gpt7_ick", -1},
++ {NULL, "gpt8_fck", -1},
++ {NULL, "gpt8_ick", -1},
++ {NULL, "wdt_fck", 3},
++ {NULL, "wdt_ick", 3},
++ {NULL, "mcbsp_fck", 1},
++ {NULL, "mcbsp_ick", 1},
++ {NULL, "mcbsp_fck", 2},
++ {NULL, "mcbsp_ick", 2},
++ {NULL, "mcbsp_fck", 3},
++ {NULL, "mcbsp_ick", 3},
++ {NULL, "mcbsp_fck", 4},
++ {NULL, "mcbsp_ick", 4},
++ {NULL, "mcbsp_fck", 5},
++ {NULL, "mcbsp_ick", 5},
++ {NULL, "ssi_ssr_sst_fck", -1},
++ {NULL, "ssi_ick", -1},
++ {NULL, "omap_32k_fck", -1},
++ {NULL, "sys_ck", -1},
++ {NULL, ""}
++};
++
++/* Generic TIMER object: */
++struct TIMER_OBJECT {
++ struct timer_list timer;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Cleanup CLK module.
++ */
++void CLK_Exit(void)
++{
++ int i = 0;
++
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
++ /* Relinquish the clock handles */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ if (SERVICES_Clks[i].clk_handle)
++ clk_put(SERVICES_Clks[i].clk_handle);
++
++ SERVICES_Clks[i].clk_handle = NULL;
++ i++;
++ }
++
++}
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initialize CLK module.
++ */
++bool CLK_Init(void)
++{
++ static struct platform_device dspbridge_device;
++ struct clk *clk_handle;
++ int i = 0;
++ GT_create(&CLK_debugMask, "CK"); /* CK for CLK */
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
++
++ dspbridge_device.dev.bus = &platform_bus_type;
++
++ /* Get the clock handles from base port and store locally */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ /* get the handle from BP */
++ dspbridge_device.id = SERVICES_Clks[i].id;
++
++ clk_handle = clk_get(&dspbridge_device.dev,
++ SERVICES_Clks[i].clk_name);
++
++ if (!clk_handle) {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: failed to get Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ /* should we fail here?? */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: PASS and Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ }
++ SERVICES_Clks[i].clk_handle = clk_handle;
++ i++;
++ }
++
++ return true;
++}
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enable Clock .
++ *
++*/
++DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Enable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (clk_enable(pClk) == 0x0) {
++ /* Success ? */
++ } else {
++ pr_err("CLK_Enable: failed to Enable CLK %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ } else {
++ pr_err("CLK_Enable: failed to get CLK %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ /* The SSI module need to configured not to have the Forced idle for
++ * master interface. If it is set to forced idle, the SSI module is
++ * transitioning to standby thereby causing the client in the DSP hang
++ * waiting for the SSI module to be active after enabling the clocks
++ */
++ if (clk_id == SERVICESCLK_ssi_fck)
++ SSI_Clk_Prepare(true);
++
++ return status;
++}
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * To Set parent of a clock to 32KHz.
++ */
++
++DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ struct clk *pClkParent;
++ enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
++ pClkParent = SERVICES_Clks[sys_32k_id].clk_handle;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK %s, "
++ "CLK dev id = %d is setting to 32KHz \n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_Set_32KHz: "
++ "Failed to set to 32KHz %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disable the clock.
++ *
++*/
++DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 clkUseCnt;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Disable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ clkUseCnt = CLK_Get_UseCnt(clk_id);
++ if (clkUseCnt == -1) {
++ pr_err("CLK_Disable: failed to get CLK Use count for CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ } else if (clkUseCnt == 0) {
++ pr_err("CLK_Disable: CLK %s, CLK dev id= %d is already"
++ "disabled\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ return status;
++ }
++ if (clk_id == SERVICESCLK_ssi_ick)
++ SSI_Clk_Prepare(false);
++
++ if (pClk) {
++ clk_disable(pClk);
++ } else {
++ pr_err("CLK_Disable: failed to get CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * GetClock Speed.
++ *
++ */
++
++DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ u32 clkSpeedHz;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ *speedKhz = 0x0;
++
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_GetRate: CLK %s, "
++ "CLK dev Id = %d \n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ clkSpeedHz = clk_get_rate(pClk);
++ *speedKhz = clkSpeedHz / 1000;
++ GT_2trace(CLK_debugMask, GT_6CLASS,
++ "CLK_GetRate: clkSpeedHz = %d , "
++ "speedinKhz=%d\n", clkSpeedHz, *speedKhz);
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 useCount = -1;
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ if (pClk) {
++ useCount = pClk->usecount; /* FIXME: usecount shouldn't be used */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return useCount;
++}
++
++void SSI_Clk_Prepare(bool FLAG)
++{
++ u32 ssi_sysconfig;
++ ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
++
++ if (FLAG) {
++ /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
++ * no idle
++ */
++ ssi_sysconfig = 0x1011;
++ } else {
++ /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
++ * forced idle
++ */
++ ssi_sysconfig = 0x1;
++ }
++ __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
++}
+diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
+new file mode 100644
+index 0000000..dd33c2d
+--- /dev/null
++++ b/drivers/dsp/bridge/services/csl.c
+@@ -0,0 +1,173 @@
++/*
++ * csl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cslce.c ========
++ * Purpose:
++ * Provides platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_Atoi
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtokr
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap.
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
++ *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
++ * CSP_Init().
++ *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
++ *! Removed call to GT_set().
++ *! 19-Jan-1998 cr: Code review cleanup.
++ *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
++ *! combined csl32.c csl95.c and cslnt.c into csl.c. Also
++ *! changed CSL_lowercase to CSL_Uppercase.
++ *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
++ *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/csl.h>
++
++/* Is character c in the string pstrDelim? */
++#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
++ (strchr(pstrDelim, c) != NULL))
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ */
++void CSL_Exit(void)
++{
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
++}
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ */
++bool CSL_Init(void)
++{
++ GT_create(&CSL_DebugMask, "CS");
++
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ */
++void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
++{
++ char tens;
++
++ DBC_Require(dwNum < 100);
++
++ if (dwNum < 100) {
++ tens = (char) dwNum / 10;
++ dwNum = dwNum % 10;
++
++ if (tens) {
++ pstrNumber[0] = tens + '0';
++ pstrNumber[1] = (char) dwNum + '0';
++ pstrNumber[2] = '\0';
++ } else {
++ pstrNumber[0] = (char) dwNum + '0';
++ pstrNumber[1] = '\0';
++ }
++ } else {
++ pstrNumber[0] = '\0';
++ }
++}
++
++
++
++
++/*
++ * ======= CSL_Strtokr =======
++ * Purpose:
++ * Re-entrant version of strtok.
++ */
++char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
++ OUT char **ppstrLast)
++{
++ char *pstrTemp;
++ char *pstrToken;
++
++ DBC_Require(szSeparators != NULL);
++ DBC_Require(ppstrLast != NULL);
++ DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
++
++ /*
++ * Set string location to beginning (pstrSrc != NULL) or to the
++ * beginning of the next token.
++ */
++ pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
++ if (*pstrTemp == '\0') {
++ pstrToken = NULL;
++ } else {
++ pstrToken = pstrTemp;
++ while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
++ szSeparators)) {
++ pstrTemp++;
++ }
++ if (*pstrTemp != '\0') {
++ while (IsDelimiter(*pstrTemp, szSeparators)) {
++ /* TODO: Shouldn't we do this for
++ * only 1 char?? */
++ *pstrTemp = '\0';
++ pstrTemp++;
++ }
++ }
++
++ /* Location in string for next call */
++ *ppstrLast = pstrTemp;
++ }
++
++ return pstrToken;
++}
+diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
+new file mode 100644
+index 0000000..5e1773f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dbg.c
+@@ -0,0 +1,119 @@
++/*
++ * dbg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbgce.c ========
++ * Purpose:
++ * Provide debugging services for DSP/BIOS Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Trace
++ *
++ * Notes:
++ * Requires gt.h.
++ *
++ * This implementation does not create GT masks on a per WMD basis.
++ * There is currently no facility for a WMD to alter the GT mask.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 28-May-1997 cr: Added reference counting.
++ *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 20-May-1996 gp: Remove DEBUG conditional compilation.
++ *! 15-May-1996 gp: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++#if (defined(DEBUG) || defined (DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Ensures trace capability is set up for link drivers.
++ */
++bool DBG_Init(void)
++{
++ GT_create(&DBG_debugMask, "WD"); /* for WmD (link driver) debug */
++
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ */
++DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, pstrFormat);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ if (bLevel & *(DBG_debugMask).flags)
++ printk(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of the DBG module.
++ */
++void DBG_Exit(void)
++{
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
++}
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
+new file mode 100644
+index 0000000..bd608d1
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dpc.c
+@@ -0,0 +1,274 @@
++/*
++ * dpc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpcce.c ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ *
++ * Public Functions:
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
++ *! to THREAD_PRIORITY_IDLE for polling IPC.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
++ *! modified.DPC_Destroy frees the DPC_Object only on
++ *! Successful termination of the thread and the handle.
++ *! 06-Jan-1999 ag: Format cleanup for code review.
++ *! Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
++ *! (Needed to access client(s) CHNL buffers).
++ *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dpc.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f435044 /* "DPC_" (in reverse). */
++
++/* The DPC object, passed to our priority event callback routine: */
++struct DPC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ void *pRefData; /* Argument for client's DPC. */
++ DPC_PROC pfnDPC; /* Client's DPC. */
++ u32 numRequested; /* Number of requested DPC's. */
++ u32 numScheduled; /* Number of executed DPC's. */
++ struct tasklet_struct dpc_tasklet;
++
++#ifdef DEBUG
++ u32 cEntryCount; /* Number of times DPC reentered. */
++ u32 numRequestedMax; /* Keep track of max pending DPC's. */
++#endif
++
++ spinlock_t dpc_lock;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ */
++DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
++ void *pRefData)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = NULL;
++
++ if ((phDPC != NULL) && (pfnDPC != NULL)) {
++ /*
++ * Allocate a DPC object to store information allowing our DPC
++ * callback to dispatch to the client's DPC.
++ */
++ MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
++ if (pDPCObject != NULL) {
++ tasklet_init(&pDPCObject->dpc_tasklet,
++ DPC_DeferredProcedure,
++ (u32) pDPCObject);
++ /* Fill out our DPC Object: */
++ pDPCObject->pRefData = pRefData;
++ pDPCObject->pfnDPC = pfnDPC;
++ pDPCObject->numRequested = 0;
++ pDPCObject->numScheduled = 0;
++#ifdef DEBUG
++ pDPCObject->numRequestedMax = 0;
++ pDPCObject->cEntryCount = 0;
++#endif
++ spin_lock_init(&pDPCObject->dpc_lock);
++ *phDPC = pDPCObject;
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EMEMORY\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EPOINTER\n");
++ status = DSP_EPOINTER;
++ }
++ DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
++ || DSP_SUCCEEDED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create(). Frees the Object only if the thread
++ * and the event terminated successfuly.
++ */
++DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++
++ /* Free our DPC object: */
++ if (DSP_SUCCEEDED(status)) {
++ tasklet_kill(&pDPCObject->dpc_tasklet);
++ MEM_FreeObject(pDPCObject);
++ pDPCObject = NULL;
++ GT_0trace(DPC_DebugMask, GT_2CLASS,
++ "DPC_Destroy: SUCCESS\n");
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Destroy: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
++ || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ */
++void DPC_Exit(void)
++{
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
++}
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ */
++bool DPC_Init(void)
++{
++ GT_create(&DPC_DebugMask, "DP");
++
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ */
++DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++ unsigned long flags;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++ /* Increment count of DPC's pending. Needs to be protected
++ * from ISRs since this function is called from process
++ * context also. */
++ spin_lock_irqsave(&hDPC->dpc_lock, flags);
++ pDPCObject->numRequested++;
++ spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
++ tasklet_schedule(&(hDPC->dpc_tasklet));
++#ifdef DEBUG
++ if (pDPCObject->numRequested > pDPCObject->numScheduled +
++ pDPCObject->numRequestedMax) {
++ pDPCObject->numRequestedMax = pDPCObject->numRequested -
++ pDPCObject->numScheduled;
++ }
++#endif
++ /* If an interrupt occurs between incrementing numRequested and the
++ * assertion below, then DPC will get executed while returning from
++ * ISR, which will complete all requests and make numRequested equal
++ * to numScheduled, firing this assertion. This happens only when
++ * DPC is being scheduled in process context */
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Schedule: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== DeferredProcedure ========
++ * Purpose:
++ * Main DPC routine. This is called by host OS DPC callback
++ * mechanism with interrupts enabled.
++ */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
++{
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
++ /* read numRequested in local variable */
++ u32 requested;
++ u32 serviced;
++
++ DBC_Require(pDPCObject != NULL);
++ requested = pDPCObject->numRequested;
++ serviced = pDPCObject->numScheduled;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
++ "pDeferredContext=%x\n", pDeferredContext);
++ /* Rollover taken care of using != instead of < */
++ if (serviced != requested) {
++ if (pDPCObject->pfnDPC != NULL) {
++ /* Process pending DPC's: */
++ do {
++ /* Call client's DPC: */
++ (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
++ serviced++;
++ } while (serviced != requested);
++ }
++ pDPCObject->numScheduled = requested;
++ }
++ GT_2trace(DPC_DebugMask, GT_ENTER,
++ "< DPC_DeferredProcedure requested %d"
++ " serviced %d\n", requested, serviced);
++}
++
+diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
+new file mode 100644
+index 0000000..ba1d26f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/kfile.c
+@@ -0,0 +1,338 @@
++/*
++ * kfile.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfilece.c ========
++ * Purpose:
++ * This module provides file i/o services.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ *
++ *! Revision History
++ *! ================
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
++ *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
++ *! Removed GT_set().
++ *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
++ *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x4c49464b /* hex code of KFIL (reversed) */
++#define MAXFILENAMELENGTH 256
++#define GENERAL_FAILURE 0xffffffff /* SetFilePointer error */
++
++/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
++struct KFILE_FileObj {
++ u32 dwSignature;
++ __kernel_pid_t owner_pid; /* PID of process that opened this file */
++ char *fileName ;
++ bool isOpen ;
++ u32 size ;
++ u32 curPos ;
++ long hInternal; /* internal handle of file */
++ struct file *fileDesc;
++
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask KFILE_debugMask = { NULL, NULL }; /* Debug mask */
++#endif
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ */
++s32 KFILE_Close(struct KFILE_FileObj *hFile)
++{
++ s32 cRetVal = 0; /* 0 indicates success */
++ s32 fRetVal = 0;
++ __kernel_pid_t curr_pid;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
++ hFile);
++
++ /* Check for valid handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* Close file only if opened by the same process (id). Otherwise
++ * Linux closes all open file handles when process exits.*/
++ /* Return PID instead of process handle */
++ curr_pid = (__kernel_pid_t)current->pid;
++ fRetVal = filp_close(hFile->fileDesc, NULL) ;
++ if (fRetVal) {
++ cRetVal = E_KFILE_ERROR;
++ GT_1trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Close: sys_close "
++ "returned %d\n", fRetVal);
++ }
++ MEM_FreeObject(hFile);
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
++ "invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count
++ * is 0.
++ */
++void KFILE_Exit(void)
++{
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
++}
++
++/*
++ * ======== KFILE_Init ========
++ */
++bool KFILE_Init(void)
++{
++ GT_create(&KFILE_debugMask, "KF"); /* "KF" for KFile */
++
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Open a file for reading ONLY
++ */
++struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
++{
++ struct KFILE_FileObj *hFile; /* file handle */
++ DSP_STATUS status;
++ mm_segment_t fs;
++
++ struct file*fileDesc = NULL;
++ DBC_Require(pszMode != NULL);
++ DBC_Require(pszFileName != NULL);
++
++ GT_2trace(KFILE_debugMask, GT_ENTER,
++ "KFILE_Open: pszFileName %s, pszMode "
++ "%s\n", pszFileName, pszMode);
++
++ /* create a KFILE object */
++ MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
++
++ if (hFile) {
++ fs = get_fs();
++ set_fs(get_ds());
++ /* Third argument is mode (permissions). Ignored unless creating file */
++ fileDesc = filp_open(pszFileName, O_RDONLY, 0);
++ if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
++ (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
++ || (fileDesc->f_op->llseek == NULL)) {
++ status = DSP_EFILE;
++ } else {
++ hFile->fileDesc = fileDesc;
++ hFile->fileName = (char *)pszFileName;
++ hFile->isOpen = true;
++ hFile->curPos = 0;
++ hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
++ SEEK_END);
++ fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
++ /* Return PID instead of process handle */
++ hFile->owner_pid = current->pid;
++
++ status = DSP_SOK;
++ }
++ set_fs(fs);
++ if (DSP_FAILED(status)) {
++ /* free memory, and clear handle */
++ MEM_FreeObject(hFile);
++ hFile = NULL;
++ }
++ } else {
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Open: MEM_AllocObject failed\n");
++ status = DSP_EMEMORY;
++ }
++ return hFile;
++}
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * Reads a specified number of bytes into a buffer.
++ */
++s32
++KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount,
++ struct KFILE_FileObj *hFile)
++{
++ u32 dwBytesRead = 0;
++ s32 cRetVal = 0;
++ mm_segment_t fs;
++
++ DBC_Require(pBuffer != NULL);
++
++ GT_4trace(KFILE_debugMask, GT_4CLASS,
++ "KFILE_Read: buffer 0x%x, cSize 0x%x,"
++ "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ if ((cSize > 0) && (cCount > 0) && pBuffer) {
++ /* read from file */
++ fs = get_fs();
++ set_fs(get_ds());
++ dwBytesRead = hFile->fileDesc->f_op->read(hFile->
++ fileDesc, pBuffer, cSize *cCount,
++ &(hFile->fileDesc->f_pos));
++ set_fs(fs);
++ if (dwBytesRead) {
++ cRetVal = dwBytesRead / cSize;
++ hFile->curPos += dwBytesRead;
++ DBC_Assert((dwBytesRead / cSize) <= \
++ (u32)cCount);
++ } else {
++ cRetVal = E_KFILE_ERROR;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: sys_read() failed\n");
++ }
++ } else {
++ cRetVal = DSP_EINVALIDARG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: Invalid argument(s)\n");
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: invalid file handle\n");
++ }
++
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * Sets the file position indicator. NOTE: we don't support seeking
++ * beyond the boundaries of a file.
++ */
++s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
++{
++ s32 cRetVal = 0; /* 0 for success */
++ u32 dwCurPos = 0;
++
++ struct file *fileDesc = NULL;
++
++ GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
++ "lOffset 0x%x, cOrigin 0x%x\n",
++ hFile, lOffset, cOrigin);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* based on the origin flag, move the internal pointer */
++
++ fileDesc = hFile->fileDesc;
++ switch (cOrigin) {
++ case KFILE_SEEK_SET:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_SET);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++
++ case KFILE_SEEK_CUR:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_CUR);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ case KFILE_SEEK_END:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_END);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ default:
++ cRetVal = E_KFILE_BADORIGINFLAG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:bad origin flag\n");
++ break;
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * Reports the current value of the position indicator. We did not
++ * consider 64 bit long file size, which implies a 4GB file limit
++ * (2 to 32 power).
++ */
++s32 KFILE_Tell(struct KFILE_FileObj *hFile)
++{
++ u32 dwCurPos = 0;
++ s32 lRetVal = E_KFILE_ERROR;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
++
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++
++ /* Get current position. */
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
++ SEEK_CUR);
++ if (dwCurPos >= 0)
++ lRetVal = dwCurPos;
++
++ } else {
++ lRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return lRetVal;
++}
++
+diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
+new file mode 100644
+index 0000000..7fa3e76
+--- /dev/null
++++ b/drivers/dsp/bridge/services/list.c
+@@ -0,0 +1,285 @@
++/*
++ * list.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== listce.c ========
++ * Purpose
++ * Provides standard circular list handling functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_Init
++ * LST_InitElem
++ * LST_InsertBefore
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ *! Revision History
++ *! ================
++ *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
++ *! list manipulation code.
++ *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ */
++struct LST_LIST *LST_Create(void)
++{
++ struct LST_LIST *pList;
++
++ GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
++
++ pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
++ MEM_NONPAGED);
++ if (pList != NULL) {
++ pList->head.next = &pList->head;
++ pList->head.prev = &pList->head;
++ pList->head.self = NULL;
++ }
++
++ return pList;
++}
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ */
++void LST_Delete(struct LST_LIST *pList)
++{
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
++
++ MEM_Free(pList);
++}
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of the LST module.
++ */
++void LST_Exit(void)
++{
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
++}
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the
++ * list is empty.
++ */
++struct LST_ELEM *LST_First(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem = NULL;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
++
++ if (!LST_IsEmpty(pList))
++ pElem = pList->head.next;
++
++ return pElem;
++}
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * "Pops" the head off the list and returns a pointer to it.
++ */
++struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
++
++ if (LST_IsEmpty(pList))
++ return NULL;
++
++ /* pElem is always valid because the list cannot be empty
++ * at this point */
++ pElem = pList->head.next;
++ pList->head.next = pElem->next;
++ pElem->next->prev = &pList->head;
++
++ return pElem->self;
++}
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initialize LST module private state.
++ */
++bool LST_Init(void)
++{
++ GT_create(&LST_debugMask, "LS"); /* LS for LSt module */
++
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ */
++void LST_InitElem(struct LST_ELEM *pElem)
++{
++ DBC_Require(pElem != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
++
++ if (pElem) {
++ pElem->next = NULL;
++ pElem->prev = NULL;
++ pElem->self = pElem;
++ }
++}
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ */
++void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
++ struct LST_ELEM *pElemExisting)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++ DBC_Require(pElemExisting != NULL);
++
++ GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
++ "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
++ pElemExisting);
++
++ pElemExisting->prev->next = pElem;
++ pElem->prev = pElemExisting->prev;
++ pElem->next = pElemExisting;
++ pElemExisting->prev = pElem;
++}
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the
++ * next element is the head of the list or the list is empty.
++ */
++struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ struct LST_ELEM *pNextElem = NULL;
++
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_Next: pList 0x%x, pCurElem 0x%x\n",
++ pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ if (pCurElem->next != &pList->head)
++ pNextElem = pCurElem->next;
++ }
++
++ return pNextElem;
++}
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ */
++void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_PutTail: pList 0x%x, pElem 0x%x\n",
++ pList, pElem);
++
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++
++ DBC_Ensure(!LST_IsEmpty(pList));
++}
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ */
++void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_RemoveElem: pList 0x%x, pCurElem "
++ "0x%x\n", pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++
++ /* set elem fields to NULL to prevent illegal references */
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
+new file mode 100644
+index 0000000..0a10304
+--- /dev/null
++++ b/drivers/dsp/bridge/services/mem.c
+@@ -0,0 +1,599 @@
++/*
++ * mem.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.c ========
++ * Purpose:
++ * Implementation of platform specific memory services.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreePhysMem
++ * MEM_Init
++ * MEM_ExtPhysPoolInit
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Jan-2004 hp: Added support for External physical memory pool
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Code cleanup.
++ *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
++ *! Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
++ *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
++ *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 16-Aug-1999 kc: modified for WinCE.
++ *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
++ *! Mdl offset now ORed not added to userBuf.
++ *! 23-Dec-1997 cr: Code review changes.
++ *! 08-Dec-1997 cr: Prepared for code review.
++ *! 24-Jun-1997 cr: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mem.h>
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Defines */
++#define MEM_512MB 0x1fffffff
++#define memInfoSign 0x464E494D /* "MINF" (in reverse). */
++
++#ifdef DEBUG
++#define MEM_CHECK /* Use to detect source of memory leaks */
++#endif
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool extPhysMemPoolEnabled;
++
++struct extPhysMemPool {
++ u32 physMemBase;
++ u32 physMemSize;
++ u32 virtMemBase;
++ u32 nextPhysAllocPtr;
++};
++
++static struct extPhysMemPool extMemPool;
++
++/* Information about each element allocated on heap */
++struct memInfo {
++ struct LST_ELEM link; /* Must be first */
++ size_t size;
++ void *caller;
++ u32 dwSignature; /* Should be last */
++};
++
++#ifdef MEM_CHECK
++
++/*
++ * This structure holds a linked list to all memory elements allocated on
++ * heap by DSP/BIOS Bridge. This is used to report memory leaks and free
++ * such elements while removing the DSP/BIOS Bridge driver
++ */
++struct memMan {
++ struct LST_LIST lst;
++ spinlock_t lock;
++};
++
++static struct memMan mMan;
++
++/*
++ * These functions are similar to LST_PutTail and LST_RemoveElem and are
++ * duplicated here to make MEM independent of LST
++ */
++static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++ pElem->self = pElem;
++}
++
++static inline void MLST_RemoveElem(struct LST_LIST *pList,
++ struct LST_ELEM *pCurElem)
++{
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++}
++
++static void MEM_Check(void)
++{
++ struct memInfo *pMem;
++ struct LST_ELEM *last = &mMan.lst.head;
++ struct LST_ELEM *curr = mMan.lst.head.next;
++
++ if (!LST_IsEmpty(&mMan.lst)) {
++ GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "Addr Size Caller\n");
++ while (curr != last) {
++ pMem = (struct memInfo *)curr;
++ curr = curr->next;
++ if ((u32)pMem > PAGE_OFFSET &&
++ MEM_IsValidHandle(pMem, memInfoSign)) {
++ GT_3trace(MEM_debugMask, GT_7CLASS,
++ "%lx %d\t [<%p>]\n",
++ (u32) pMem + sizeof(struct memInfo),
++ pMem->size, pMem->caller);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32)pMem + sizeof(struct memInfo));
++ break;
++ }
++ }
++ }
++ DBC_Ensure(LST_IsEmpty(&mMan.lst));
++}
++
++#endif
++
++void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
++{
++ u32 poolVirtBase;
++
++ /* get the virtual address for the physical memory pool passed */
++ poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
++
++ if ((void **)poolVirtBase == NULL) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "[PHYS_POOL]Mapping External "
++ "physical memory to virt failed \n");
++ extPhysMemPoolEnabled = false;
++ } else {
++ extMemPool.physMemBase = poolPhysBase;
++ extMemPool.physMemSize = poolSize;
++ extMemPool.virtMemBase = poolVirtBase;
++ extMemPool.nextPhysAllocPtr = poolPhysBase;
++ extPhysMemPoolEnabled = true;
++ GT_3trace(MEM_debugMask, GT_1CLASS,
++ "ExtMemory Pool details " "Pool"
++ "Physical mem base = %0x " "Pool Physical mem size "
++ "= %0x" "Pool Virtual mem base = %0x \n",
++ poolPhysBase, poolSize, poolVirtBase);
++ }
++}
++
++static void MEM_ExtPhysPoolRelease(void)
++{
++ GT_0trace(MEM_debugMask, GT_1CLASS,
++ "Releasing External memory pool \n");
++ if (extPhysMemPoolEnabled) {
++ iounmap((void *)(extMemPool.virtMemBase));
++ extPhysMemPoolEnabled = false;
++ }
++}
++
++/*
++ * ======== MEM_ExtPhysMemAlloc ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory from external memory pool
++ */
++
++static void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
++{
++ u32 newAllocPtr;
++ u32 offset;
++ u32 virtAddr;
++
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation" "bytes=0x%x , "
++ "align=0x%x \n", bytes, align);
++ if (align == 0) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "No alignment request in allocation call !! \n");
++ align = 1;
++ }
++ if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
++ - extMemPool.nextPhysAllocPtr)) {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "unable to allocate memory for bytes = 0x%x \n",
++ bytes);
++ pPhysAddr = NULL;
++ return NULL;
++ } else {
++ offset = (extMemPool.nextPhysAllocPtr & (align - 1));
++ if (offset == 0)
++ newAllocPtr = extMemPool.nextPhysAllocPtr;
++ else
++ newAllocPtr = (extMemPool.nextPhysAllocPtr) +
++ (align - offset);
++ if ((newAllocPtr + bytes) <=
++ (extMemPool.physMemBase + extMemPool.physMemSize)) {
++ /* we can allocate */
++ *pPhysAddr = newAllocPtr;
++ extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
++ virtAddr = extMemPool.virtMemBase + (newAllocPtr -
++ extMemPool.physMemBase);
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation succedded "
++ "phys address=0x%x , virtaddress=0x%x \n",
++ newAllocPtr, virtAddr);
++ return (void *)virtAddr;
++ } else {
++ *pPhysAddr = 0;
++ return NULL;
++ }
++ }
++}
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ */
++void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *)pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++
++ default:
++ GT_0trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Alloc: unexpected "
++ "MEM_POOLATTRS value\n");
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ */
++void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
++{
++ void *pVaMem = NULL;
++ dma_addr_t paMem;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
++ "0x%x\n", cBytes, ulAlign);
++
++ if (cBytes > 0) {
++ if (extPhysMemPoolEnabled) {
++ pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
++ (u32 *)&paMem);
++ } else
++ pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pVaMem == NULL) {
++ *pPhysicalAddress = 0;
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_AllocPhysMem failed: "
++ "0x%x\n", pVaMem);
++ } else {
++ *pPhysicalAddress = paMem;
++ }
++ }
++ return pVaMem;
++}
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ */
++void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
++ cBytes, type);
++
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
++ pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Calloc: unexpected "
++ "MEM_POOLATTRS value 0x%x\n", type);
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of the MEM module.
++ */
++void MEM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++#ifdef MEM_CHECK
++ if (cRefs == 0)
++ MEM_Check();
++
++#endif
++ MEM_ExtPhysPoolRelease();
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Flush cache
++ */
++void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
++{
++ DBC_Require(cRefs > 0);
++
++ switch (FlushType) {
++ /* invalidate only */
++ case PROC_INVALIDATE_MEM:
++ dmac_inv_range(pMemBuf, pMemBuf + cBytes);
++ outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback only */
++ case PROC_WRITEBACK_MEM:
++ dmac_clean_range(pMemBuf, pMemBuf + cBytes);
++ outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback and invalidate */
++ case PROC_WRITEBACK_INVALIDATE_MEM:
++ dmac_flush_range(pMemBuf, pMemBuf + cBytes);
++ outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
++ "FlushMemType 0x%x\n", FlushType);
++ break;
++ }
++
++}
++
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ */
++void MEM_Free(IN void *pMemBuf)
++{
++#ifdef MEM_CHECK
++ struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
++#endif
++
++ DBC_Require(pMemBuf != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
++ pMemBuf);
++
++ if (pMemBuf) {
++#ifndef MEM_CHECK
++ kfree(pMemBuf);
++#else
++ if (pMem) {
++ if (pMem->dwSignature == memInfoSign) {
++ spin_lock(&mMan.lock);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem->dwSignature = 0;
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32) pMem + sizeof(struct memInfo));
++ }
++ }
++#endif
++ }
++}
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ */
++void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
++ u32 cBytes)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(pVirtualAddress != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
++ "0x%x\n", pVirtualAddress);
++
++ if (!extPhysMemPoolEnabled)
++ dma_free_coherent(NULL, cBytes, pVirtualAddress,
++ pPhysicalAddress);
++}
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initialize MEM module private state.
++ */
++bool MEM_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ GT_create(&MEM_debugMask, "MM"); /* MM for MeM module */
++
++#ifdef MEM_CHECK
++ mMan.lst.head.next = &mMan.lst.head;
++ mMan.lst.head.prev = &mMan.lst.head;
++ mMan.lst.head.self = NULL;
++ spin_lock_init(&mMan.lock);
++#endif
++
++ }
++
++ cRefs++;
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs > 0);
++
++ return true;
++}
+diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
+new file mode 100644
+index 0000000..2eff3eb
+--- /dev/null
++++ b/drivers/dsp/bridge/services/ntfy.c
+@@ -0,0 +1,329 @@
++/*
++ * ntfy.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfyce.c ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE related code.
++ *! 05-Nov-2001 kc Updated DSP_HNOTIFICATION structure.
++ *! 10-May-2001 jeh Removed SERVICES module init/exit from NTFY_Init/Exit.
++ *! NTFY_Register() returns DSP_ENOTIMPL for all but
++ *! DSP_SIGNALEVENT.
++ *! 12-Oct-2000 jeh Use MEM_IsValidHandle().
++ *! 07-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define NTFY_SIGNATURE 0x5946544e /* "YFTN" */
++
++/*
++ * ======== NTFY_OBJECT ========
++ */
++struct NTFY_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct LST_LIST *notifyList; /* List of NOTIFICATION objects */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++};
++
++/*
++ * ======== NOTIFICATION ========
++ * This object will be created when a client registers for events.
++ */
++struct NOTIFICATION {
++ struct LST_ELEM listElem;
++ u32 uEventMask; /* Events to be notified about */
++ u32 uNotifyType; /* Type of notification to be sent */
++
++ /*
++ * We keep a copy of the event name to check if the event has
++ * already been registered. (SYNC also keeps a copy of the name).
++ */
++ char *pstrName; /* Name of event */
++ HANDLE hEvent; /* Handle for notification */
++ struct SYNC_OBJECT *hSync;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask NTFY_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DeleteNotify(struct NOTIFICATION *pNotify);
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ */
++DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
++{
++ struct NTFY_OBJECT *pNtfy;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phNtfy != NULL);
++
++ *phNtfy = NULL;
++ MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
++
++ if (pNtfy) {
++
++ status = SYNC_InitializeDPCCS(&pNtfy->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pNtfy->notifyList = LST_Create();
++ if (pNtfy->notifyList == NULL) {
++ (void) SYNC_DeleteCS(pNtfy->hSync);
++ MEM_FreeObject(pNtfy);
++ status = DSP_EMEMORY;
++ } else {
++ *phNtfy = pNtfy;
++ }
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
++ (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
++ NTFY_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ */
++void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /* Remove any elements remaining in list */
++ if (hNtfy->notifyList) {
++ while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
++ notifyList))) {
++ DeleteNotify(pNotify);
++ }
++ DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
++ LST_Delete(hNtfy->notifyList);
++ }
++ if (hNtfy->hSync)
++ (void)SYNC_DeleteCS(hNtfy->hSync);
++
++ MEM_FreeObject(hNtfy);
++}
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ */
++void NTFY_Exit(void)
++{
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
++}
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ */
++bool NTFY_Init(void)
++{
++ GT_create(&NTFY_debugMask, "NY"); /* "NY" for NtfY */
++
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
++
++ return true;
++}
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ */
++void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /*
++ * Go through notifyList and notify all clients registered for
++ * uEventMask events.
++ */
++
++ (void) SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ if (pNotify->uEventMask & uEventMask) {
++ /* Notify */
++ if (pNotify->uNotifyType == DSP_SIGNALEVENT)
++ (void)SYNC_SetEvent(pNotify->hSync);
++
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++
++ (void) SYNC_LeaveCS(hNtfy->hSync);
++}
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ */
++DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
++ struct DSP_NOTIFICATION *hNotification,
++ u32 uEventMask, u32 uNotifyType)
++{
++ struct NOTIFICATION *pNotify;
++ struct SYNC_ATTRS syncAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ if (hNotification == NULL)
++ status = DSP_EHANDLE;
++
++ /* Return DSP_ENOTIMPL if uNotifyType is not supported */
++ if (DSP_SUCCEEDED(status)) {
++ if (!IsValidNotifyMask(uNotifyType))
++ status = DSP_ENOTIMPL;
++
++ }
++
++ if (DSP_FAILED(status))
++ return status;
++
++ (void)SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++
++ if (hNotification->handle == pNotify->hSync) {
++ /* found */
++ break;
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++ if (pNotify == NULL) {
++ /* Not registered */
++ if (uEventMask == 0) {
++ status = DSP_EVALUE;
++ } else {
++ /* Allocate NOTIFICATION object, add to list */
++ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
++ MEM_PAGED);
++ if (pNotify == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem((struct LST_ELEM *) pNotify);
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
++ hNotification->handle = pNotify->hSync;
++
++ if (DSP_SUCCEEDED(status)) {
++ pNotify->uEventMask = uEventMask;
++ pNotify->uNotifyType = uNotifyType;
++ LST_PutTail(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ } else {
++ DeleteNotify(pNotify);
++ }
++ }
++ } else {
++ /* Found in list */
++ if (uEventMask == 0) {
++ /* Remove from list and free */
++ LST_RemoveElem(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ DeleteNotify(pNotify);
++ } else {
++ /* Update notification mask (type shouldn't change) */
++ pNotify->uEventMask = uEventMask;
++ }
++ }
++ (void)SYNC_LeaveCS(hNtfy->hSync);
++ return status;
++}
++
++/*
++ * ======== DeleteNotify ========
++ * Purpose:
++ * Free the notification object.
++ */
++static void DeleteNotify(struct NOTIFICATION *pNotify)
++{
++ if (pNotify->hSync)
++ (void) SYNC_CloseEvent(pNotify->hSync);
++
++ if (pNotify->pstrName)
++ MEM_Free(pNotify->pstrName);
++
++ MEM_Free(pNotify);
++}
++
+diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
+new file mode 100644
+index 0000000..0d85f41
+--- /dev/null
++++ b/drivers/dsp/bridge/services/reg.c
+@@ -0,0 +1,196 @@
++/*
++ * reg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regce.c ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! ================
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/reg.h>
++#include <regsup.h>
++
++#if GT_TRACE
++struct GT_Mask REG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== REG_DeleteValue ========
++ * Deletes a registry entry value. NOTE: A registry entry value is not the
++ * same as * a registry key.
++ */
++DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS status;
++ DBC_Require(pstrSubkey && pstrValue);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
++
++ /* Note that we don't use phKey */
++ if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_EnumValue ========
++ * Enumerates a registry key and retrieve values stored under the key.
++ * We will assume the input pdwValueSize is smaller than
++ * REG_MAXREGPATHLENGTH for implementation purposes.
++ */
++DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
++ IN CONST char *pstrKey, IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
++ pdwDataSize);
++ DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrKey) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
++
++ status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
++ pstrData, pdwDataSize);
++
++ return status;
++}
++
++/*
++ * ======== REG_Exit ========
++ * Discontinue usage of the REG module.
++ */
++void REG_Exit(void)
++{
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
++
++ regsupExit();
++}
++
++/*
++ * ======== REG_GetValue ========
++ * Retrieve a value from the registry.
++ */
++DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, OUT u8 *pbData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrSubkey && pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_Init ========
++ * Initialize the REG module's private state.
++ */
++bool REG_Init(void)
++{
++ bool fInit;
++
++ GT_create(&REG_debugMask, "RG"); /* RG for ReG */
++
++ fInit = regsupInit();
++
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
++
++ return fInit;
++}
++
++/*
++ * ======== REG_SetValue ========
++ * Set a value in the registry.
++ */
++DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, IN CONST u32 dwType,
++ IN u8 *pbData, IN u32 dwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(dwDataSize > 0);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
+new file mode 100644
+index 0000000..5251b68
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.c
+@@ -0,0 +1,368 @@
++/*
++ * regsup.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.c ========
++ * Purpose:
++ * Provide registry support functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-May-2002 map: Integrated PSI's dspimage update mechanism
++ *! 11-May-2002 gp: Turned PERF "on".
++ *! 21-May-2002 map: Fixed bug in SetValue - if resizing datasize, set
++ *! new size too
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- This */
++#include <regsup.h>
++
++struct RegValueStruct {
++ char name[BRIDGE_MAX_NAME_SIZE]; /* Name of a given value entry */
++ u32 dataSize; /* Size of the data */
++ void *pData; /* Pointer to the actual data */
++};
++
++struct RegKeyStruct {
++ /*The current number of value entries this key has*/
++ u32 numValueEntries;
++ /* Array of value entries */
++ struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
++};
++
++
++/* Pointer to the registry support key */
++static struct RegKeyStruct *pRegKey;
++
++#if GT_TRACE
++extern struct GT_Mask REG_debugMask; /* GT trace var. */
++/*
++ * ======== printS ========
++ * Purpose:
++ * Displays printable characters in pBuf, if any.
++ */
++static inline void printS(void *pBuf)
++{
++ int pos = 0;
++ if (*(REG_debugMask).flags & (GT_2CLASS)) {
++ while (*(u8 *)((pBuf)+pos) >= ' ' &&
++ *(u8 *)((pBuf)+pos) <= '~') {
++ GT_1trace(REG_debugMask, GT_2CLASS, "%c",
++ *(u8 *)((pBuf) + pos++));
++ }
++
++ GT_0trace(REG_debugMask, GT_2CLASS, "\n");
++ }
++}
++#else
++#define printS(pBuf)
++#endif
++
++/*
++ * ======== regsupInit ========
++ * Purpose:
++ * Initialize the Registry Support module's private state.
++ */
++bool regsupInit(void)
++{
++ if (pRegKey != NULL)
++ return true;
++
++ /* Need to allocate and setup our registry. */
++ pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
++ if (pRegKey == NULL)
++ return false;
++
++ return true;
++}
++
++/*
++ * ======== regsupExit ========
++ * Purpose:
++ * Release all registry support allocations.
++ */
++void regsupExit(void)
++{
++ u32 i;
++
++ /* Make sure data has actually been allocated. */
++ if (pRegKey == NULL) {
++ /* Nothing initialized.return! */
++ return;
++ }
++
++ GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
++ pRegKey->numValueEntries);
++
++ /* Now go through each entry and free all resources. */
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ if (pRegKey->values[i].name[0] != '\0') {
++ /* We have a valid entry.free it up! */
++ if (pRegKey->values[i].pData != NULL) {
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E %d\t %s DATA %x ", i,
++ pRegKey->values[i].name,
++ *(u32 *)pRegKey->values[i].pData);
++ printS((u8 *)(pRegKey->values[i].pData));
++ MEM_Free(pRegKey->values[i].pData);
++ }
++ pRegKey->values[i].pData = NULL;
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].name[0] = '\0';
++ }
++ }
++
++ /* Now that all of the resources are freed up, free the main one! */
++ MEM_Free(pRegKey);
++
++ /* Don't forget to NULL out the global entry! */
++ pRegKey = NULL;
++}
++
++/*
++ * ======== regsupGetValue ========
++ * Purpose:
++ * Get the value of the entry having the given name.
++ */
++DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++
++ /* We have a match! Copy out the data. */
++ memcpy(pBuf, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++
++ /* Get the size for the caller. */
++ *dataSize = pRegKey->values[i].dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (DSP_SUCCEEDED(retVal)) {
++ GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++ } else {
++ GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupSetValue ========
++ * Purpose:
++ * Sets the value of the entry having the given name.
++ */
++DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* Make sure the new data size is the same. */
++ if (dataSize != pRegKey->values[i].dataSize) {
++ /* The caller needs a different data size! */
++ MEM_Free(pRegKey->values[i].pData);
++ pRegKey->values[i].pData = MEM_Alloc(dataSize,
++ MEM_NONPAGED);
++ if (pRegKey->values[i].pData == NULL)
++ break;
++
++ }
++
++ /* We have a match! Copy out the data. */
++ memcpy(pRegKey->values[i].pData, pBuf, dataSize);
++
++ /* Reset datasize - overwrite if new or same */
++ pRegKey->values[i].dataSize = dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ /* See if we found a match or if this is a new entry */
++ if (i == pRegKey->numValueEntries) {
++ /* No match, need to make a new entry */
++ /* First check to see if we can make any more entries. */
++ if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
++ strncpy(pRegKey->values[pRegKey->numValueEntries].name,
++ valName, BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[pRegKey->numValueEntries].pData =
++ MEM_Alloc(dataSize, MEM_NONPAGED);
++ if (pRegKey->values[pRegKey->numValueEntries].pData !=
++ NULL) {
++ memcpy(pRegKey->
++ values[pRegKey->numValueEntries].pData,
++ pBuf, dataSize);
++ pRegKey->
++ values[pRegKey->numValueEntries].dataSize =
++ dataSize;
++ pRegKey->numValueEntries++;
++ retVal = DSP_SOK;
++ }
++ } else {
++ GT_0trace(REG_debugMask, GT_7CLASS,
++ "MAX NUM REG ENTRIES REACHED\n");
++ }
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupEnumValue ========
++ * Purpose:
++ * Returns registry "values" and their "data" under a (sub)key.
++ */
++DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
++ u32 i;
++ u32 dwKeyLen;
++ u32 count = 0;
++
++ DBC_Require(pstrKey);
++ dwKeyLen = strlen(pstrKey);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if ((strncmp(pRegKey->values[i].name, pstrKey,
++ dwKeyLen) == 0) && count++ == dwIndex) {
++ /* We have a match! Copy out the data. */
++ memcpy(pstrData, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++ /* Get the size for the caller. */
++ *pdwDataSize = pRegKey->values[i].dataSize;
++ *pdwValueSize = strlen(&(pRegKey->
++ values[i].name[dwKeyLen]));
++ strncpy(pstrValue,
++ &(pRegKey->values[i].name[dwKeyLen]),
++ *pdwValueSize + 1);
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E Key %s, Value %s, Data %x ",
++ pstrKey, pstrValue, *(u32 *)pstrData);
++ printS((u8 *)pstrData);
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (count && DSP_FAILED(retVal))
++ retVal = REG_E_NOMOREITEMS;
++
++ return retVal;
++}
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ /* See if the name matches... */
++ if (strncmp(pRegKey->values[i].name, pstrValue,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* We have a match! Delete this key. To delete a
++ * key, we free all resources associated with this
++ * key and, if we're not already the last entry in
++ * the array, we copy that entry into this deleted
++ * key.
++ */
++ MEM_Free(pRegKey->values[i].pData);
++ if ((pRegKey->numValueEntries - 1) == i) {
++ /* we're deleting the last one */
++ pRegKey->values[i].name[0] = '\0';
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].pData = NULL;
++ } else {
++ /* move the last one here */
++ strncpy(pRegKey->values[i].name, pRegKey->
++ values[pRegKey->numValueEntries - 1].name,
++ BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[i].dataSize =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].dataSize;
++ pRegKey->values[i].pData =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].pData;
++ /* don't have to do this, but for
++ * the paranoid... */
++ pRegKey->
++ values[pRegKey->numValueEntries-1].name[0] =
++ '\0';
++ }
++
++ /* another one bites the dust. */
++ pRegKey->numValueEntries--;
++
++ /* Set our status to good and exit... */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++ return retVal;
++
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
+new file mode 100644
+index 0000000..011be52
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.h
+@@ -0,0 +1,58 @@
++/*
++ * regsup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef _REGSUP_H_
++#define _REGSUP_H_
++
++#define BRIDGE_MAX_NAME_SIZE MAXREGPATHLENGTH
++#define BRIDGE_MAX_NUM_REG_ENTRIES 52
++
++/* Init function. MUST be called BEFORE any calls are */
++/* made into this psuedo-registry!!! Returns TRUE/FALSE for SUCCESS/ERROR */
++extern bool regsupInit(void);
++
++/* Release all registry support allocations. */
++extern void regsupExit(void);
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++/* Get the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value retrieved. Returns DSP_EFAIL
++ * otherwise.*/
++extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
++
++/* Sets the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value set. Returns DSP_EFAIL otherwise. */
++extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
++
++/* Returns registry "values" and their "data" under a (sub)key. */
++extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
++
++#endif
++
+diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
+new file mode 100644
+index 0000000..346007e
+--- /dev/null
++++ b/drivers/dsp/bridge/services/services.c
+@@ -0,0 +1,193 @@
++/*
++ * services.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.c ========
++ * Purpose:
++ * Provide SERVICES loading.
++ *
++ * Public Functions:
++ * SERVICES_Exit
++ * SERVICES_Init
++ *
++ *
++ *! Revision History
++ *! ================
++ *! 20-Nov-2000 rr: NTFY_Init/Exit added.
++ *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/services.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SERVICES_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++static u32 cRefs; /* SERVICES module reference count */
++
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void SERVICES_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
++ cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ /* Uninitialize all SERVICES modules here */
++ NTFY_Exit();
++ UTIL_Exit();
++ SYNC_Exit();
++ CLK_Exit();
++ REG_Exit();
++ LST_Exit();
++ KFILE_Exit();
++ DPC_Exit();
++ DBG_Exit();
++ CSL_Exit();
++ CFG_Exit();
++ MEM_Exit();
++
++ GT_exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ */
++bool SERVICES_Init(void)
++{
++ bool fInit = true;
++ bool fCFG, fCSL, fDBG, fDPC, fKFILE, fLST, fMEM;
++ bool fREG, fSYNC, fCLK, fUTIL, fNTFY;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ GT_init();
++ GT_create(&SERVICES_debugMask, "OS"); /* OS for OSal */
++
++ GT_0trace(SERVICES_debugMask, GT_ENTER,
++ "SERVICES_Init: entered\n");
++
++ /* Perform required initialization of SERVICES modules. */
++ fMEM = MEM_Init();
++ fREG = REG_Init();
++ fCFG = CFG_Init();
++ fCSL = CSL_Init();
++ fDBG = DBG_Init();
++ fDPC = DPC_Init();
++ fKFILE = KFILE_Init();
++ fLST = LST_Init();
++ /* fREG = REG_Init(); */
++ fSYNC = SYNC_Init();
++ fCLK = CLK_Init();
++ fUTIL = UTIL_Init();
++ fNTFY = NTFY_Init();
++
++ fInit = fCFG && fCSL && fDBG && fDPC && fKFILE &&
++ fLST && fMEM && fREG && fSYNC && fCLK && fUTIL;
++
++ if (!fInit) {
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fUTIL)
++ UTIL_Exit();
++
++ if (fSYNC)
++ SYNC_Exit();
++
++ if (fCLK)
++ CLK_Exit();
++
++ if (fREG)
++ REG_Exit();
++
++ if (fLST)
++ LST_Exit();
++
++ if (fKFILE)
++ KFILE_Exit();
++
++ if (fDPC)
++ DPC_Exit();
++
++ if (fDBG)
++ DBG_Exit();
++
++ if (fCSL)
++ CSL_Exit();
++
++ if (fCFG)
++ CFG_Exit();
++
++ if (fMEM)
++ MEM_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
++
++ return fInit;
++}
++
+diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
+new file mode 100644
+index 0000000..7ab9347
+--- /dev/null
++++ b/drivers/dsp/bridge/services/sync.c
+@@ -0,0 +1,602 @@
++/*
++ * sync.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.c ========
++ * Purpose:
++ * Synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Nov-2001 kc: Minor cosmetic changes.
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 10-Aug-2000 rr: SYNC_PostMessage added.
++ *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 22-Sep-1999 kc: Modified from sync95.c.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x434e5953 /* "SYNC" (in reverse) */
++
++enum wait_state {
++ wo_waiting,
++ wo_signalled
++} ;
++
++enum sync_state {
++ so_reset,
++ so_signalled
++} ;
++
++struct WAIT_OBJECT {
++ enum wait_state state;
++ struct SYNC_OBJECT *signalling_event;
++ struct semaphore sem;
++};
++
++/* Generic SYNC object: */
++struct SYNC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ enum sync_state state;
++ spinlock_t sync_lock;
++ struct WAIT_OBJECT *pWaitObj;
++};
++
++struct SYNC_DPCCSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ spinlock_t sync_dpccs_lock;
++ s32 count;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SYNC_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static int test_and_set(volatile void *ptr, int val)
++{
++ int ret = val;
++ asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
++ return ret;
++}
++
++static void timeout_callback(unsigned long hWaitObj);
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close an existing SYNC event object.
++ */
++DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ if (pEvent->pWaitObj) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: Wait object not NULL\n");
++ }
++ MEM_FreeObject(pEvent);
++
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: invalid "
++ "hEvent handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Cleanup SYNC module.
++ */
++void SYNC_Exit(void)
++{
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
++}
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initialize SYNC module.
++ */
++bool SYNC_Init(void)
++{
++ GT_create(&SYNC_debugMask, "SY"); /* SY for SYnc */
++
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Open a new synchronization event object.
++ */
++DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS *pAttrs)
++{
++ struct SYNC_OBJECT *pEvent = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phEvent != NULL);
++
++ GT_2trace(SYNC_debugMask, GT_ENTER,
++ "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
++ "0x%x\n", phEvent, pAttrs);
++
++ /* Allocate memory for sync object */
++ MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
++ if (pEvent != NULL) {
++ pEvent->state = so_reset;
++ pEvent->pWaitObj = NULL;
++ spin_lock_init(&pEvent->sync_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_OpenEvent: MEM_AllocObject failed\n");
++ }
++
++ *phEvent = pEvent;
++
++ return status;
++}
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset an event to non-signalled.
++ */
++DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ pEvent->state = so_reset;
++ status = DSP_SOK;
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_ResetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Set an event to signaled and unblock one waiting thread.
++ *
++ * This function is called from ISR, DPC and user context. Hence interrupts
++ * are disabled to ensure atomicity.
++ */
++
++DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ unsigned long flags;
++
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ spin_lock_irqsave(&hEvent->sync_lock, flags);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: pEvent->pWaitObj "
++ "= 0x%x \n", pEvent->pWaitObj);
++ if (pEvent->pWaitObj)
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
++ "pEvent->pWaitObj->state = 0x%x \n",
++ pEvent->pWaitObj->state);
++ if (pEvent->pWaitObj != NULL &&
++ test_and_set(&pEvent->pWaitObj->state,
++ wo_signalled) == wo_waiting) {
++
++ pEvent->state = so_reset;
++ pEvent->pWaitObj->signalling_event = pEvent;
++ up(&pEvent->pWaitObj->sem);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: Unlock "
++ "Semaphore for hEvent 0x%x\n", hEvent);
++ } else {
++ pEvent->state = so_signalled;
++ }
++ spin_unlock_irqrestore(&hEvent->sync_lock, flags);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Note: dwTimeOut must be 0xffffffff to signal infinite wait.
++ */
++DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ u32 temp;
++
++ GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
++ "dwTimeOut 0x%x", hEvent, dwTimeout);
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
++ &temp);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnEvent: invalid hEvent"
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ */
++DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
++ u32 uCount, u32 dwTimeout,
++ OUT u32 *puIndex)
++{
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 curr;
++ struct WAIT_OBJECT *Wp;
++
++ DBC_Require(uCount > 0);
++ DBC_Require(hSyncEvents != NULL);
++ DBC_Require(puIndex != NULL);
++
++ for (i = 0; i < uCount; i++)
++ DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
++
++ GT_4trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnMultipleEvents: hSyncEvents:"
++ "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
++ hSyncEvents, uCount, dwTimeout, puIndex);
++
++ Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
++ if (Wp == NULL)
++ return DSP_EMEMORY;
++
++ Wp->state = wo_waiting;
++ Wp->signalling_event = NULL;
++ init_MUTEX_LOCKED(&(Wp->sem));
++
++ for (curr = 0; curr < uCount; curr++) {
++ hSyncEvents[curr]->pWaitObj = Wp;
++ if (hSyncEvents[curr]->state == so_signalled) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Detected signaled Event !!!\n");
++ if (test_and_set(&(Wp->state), wo_signalled) ==
++ wo_waiting) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Setting Signal Event!!!\n");
++ hSyncEvents[curr]->state = so_reset;
++ Wp->signalling_event = hSyncEvents[curr];
++ }
++ curr++; /* Will try optimizing later */
++ break;
++ }
++ }
++
++ curr--; /* Will try optimizing later */
++ if (Wp->state != wo_signalled && dwTimeout > 0) {
++ struct timer_list timeout;
++ if (dwTimeout != SYNC_INFINITE) {
++ init_timer(&timeout);
++ timeout.function = timeout_callback;
++ timeout.data = (unsigned long)Wp;
++ timeout.expires = jiffies + dwTimeout * HZ / 1000;
++ add_timer(&timeout);
++ }
++ if (down_interruptible(&(Wp->sem))) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
++ "WaitOnMultipleEvents Interrupted by signal\n");
++ status = DSP_EFAIL;
++ }
++ if (dwTimeout != SYNC_INFINITE) {
++ if (in_interrupt()) {
++ if (!del_timer(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ } else {
++ if (!del_timer_sync(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ }
++ }
++ }
++ for (i = 0; i <= curr; i++) {
++ if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
++ /* Memory corruption here if hSyncEvents[i] is
++ * freed before following statememt. */
++ hSyncEvents[i]->pWaitObj = NULL;
++ }
++ if (hSyncEvents[i] == Wp->signalling_event)
++ *puIndex = i;
++
++ }
++ if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC:Signaling Event NULL!!!(:-\n");
++ status = DSP_ETIMEOUT;
++ }
++ if (Wp)
++ MEM_Free(Wp);
++ return status;
++}
++
++static void timeout_callback(unsigned long hWaitObj)
++{
++ struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
++ if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
++ up(&pWaitObj->sem);
++
++}
++
++/*
++ * ======== SYNC_DeleteCS ========
++ */
++DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (down_trylock(&pCSObj->sem) != 0) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(hCSObj);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ if (pDPCCSObj->count != 1) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "DPC CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(pDPCCSObj);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_DeleteCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_EnterCS ========
++ */
++DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
++ hCSObj);
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (in_interrupt()) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS called from "
++ "ISR/DPC or with ISR/DPC disabled!");
++ DBC_Assert(0);
++ } else if (down_interruptible(&pCSObj->sem)) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS interrupted by signal! "
++ "pCSObj=0x%X", pCSObj);
++ status = DSP_EFAIL;
++ }
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ pDPCCSObj->count--;
++ if (pDPCCSObj->count != 0) {
++ /* FATAL ERROR : Failed to acquire DPC CS */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS DPCCS %x locked,"
++ "count %d", pDPCCSObj, pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_EnterCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_InitializeCS ========
++ */
++DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = NULL;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
++
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
++ if (pCSObj != NULL) {
++ init_MUTEX(&pCSObj->sem);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeCS: MEM_AllocObject"
++ "failed\n");
++ }
++ /* return CS object */
++ *phCSObj = pCSObj;
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++ return status;
++}
++
++DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_DPCCSOBJECT *pCSObj = NULL;
++
++ DBC_Require(phCSObj);
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
++
++ if (phCSObj) {
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
++ SIGNATUREDPCCS);
++ if (pCSObj != NULL) {
++ pCSObj->count = 1;
++ spin_lock_init(&pCSObj->sync_dpccs_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeDPCCS: "
++ "MEM_AllocObject failed\n");
++ }
++
++ /* return CS object */
++ *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
++ "pCSObj %p\n", pCSObj);
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++
++ return status;
++}
++
++/*
++ * ======== SYNC_LeaveCS ========
++ */
++DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
++ hCSObj);
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ up(&pCSObj->sem);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ pDPCCSObj->count++;
++ if (pDPCCSObj->count != 1) {
++ /* FATAL ERROR : Invalid DPC CS count */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_LeaveCS DPCCS %x, "
++ "Invalid count %d", pDPCCSObj,
++ pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ }
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_LeaveCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
+new file mode 100644
+index 0000000..801b000
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_cmm.h
+@@ -0,0 +1,59 @@
++/*
++ * _cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _cmm.h ========
++ * Description:
++ * Private header file defining CMM manager objects and defines needed
++ * by IO manager to register shared memory regions when DSP base image
++ * is loaded(WMD_IO_OnLoaded).
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Aug-2001 ag Created.
++ */
++
++#ifndef _CMM_
++#define _CMM_
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for shared memory manager CMM.
++ * They are defined in the *cfg.cmd file by cdb code.
++ */
++#define SHM0_SHARED_BASE_SYM "_SHM0_BEG"
++#define SHM0_SHARED_END_SYM "_SHM0_END"
++#define SHM0_SHARED_RESERVED_BASE_SYM "_SHM0_RSVDSTRT"
++
++/*
++ * Shared Memory Region #0(SHMSEG0) is used in the following way:
++ *
++ * |(_SHM0_BEG) | (_SHM0_RSVDSTRT) | (_SHM0_END)
++ * V V V
++ * ------------------------------------------------------------
++ * | DSP-side allocations | GPP-side allocations |
++ * ------------------------------------------------------------
++ *
++ *
++ */
++
++#endif /* _CMM_ */
+diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
+new file mode 100644
+index 0000000..df281ad
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_deh.h
+@@ -0,0 +1,46 @@
++/*
++ * _deh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _deh.h ========
++ * Description:
++ * Private header for DEH module.
++ *
++ *! Revision History:
++ *! ================
++ *! 21-Sep-2001 kc: created.
++ */
++
++#ifndef _DEH_
++#define _DEH_
++
++#include <dspbridge/dpc.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/wmd.h>
++
++#define SIGNATURE 0x5f484544 /* "DEH_" backwards */
++
++/* DEH Manager: only one created per board: */
++struct DEH_MGR {
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct NTFY_OBJECT *hNtfy; /* NTFY object */
++ struct DPC_OBJECT *hMmuFaultDpc; /* DPC object handle. */
++ struct DSP_ERRORINFO errInfo; /* DSP exception info. */
++} ;
++
++#endif /* _DEH_ */
+diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
+new file mode 100644
+index 0000000..fa5e9ee
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_msg_sm.h
+@@ -0,0 +1,158 @@
++/*
++ * _msg_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _msg_sm.h ========
++ * Description:
++ * Private header file defining MSG manager objects and defines needed
++ * by IO manager.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 09-May-2001 jeh Code Review cleanup.
++ *! 08-Nov-2000 jeh Created.
++ */
++
++#ifndef _MSG_SM_
++#define _MSG_SM_
++
++#include <dspbridge/list.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for messages. They are
++ * defined in the *cfg.cmd file by cdb code.
++ */
++#define MSG_SHARED_BUFFER_BASE_SYM "_MSG_BEG"
++#define MSG_SHARED_BUFFER_LIMIT_SYM "_MSG_END"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++/*
++ * ======== MSG ========
++ * There is a control structure for messages to the DSP, and a control
++ * structure for messages from the DSP. The shared memory region for
++ * transferring messages is partitioned as follows:
++ *
++ * ----------------------------------------------------------
++ * |Control | Messages from DSP | Control | Messages to DSP |
++ * ----------------------------------------------------------
++ *
++ * MSG control structure for messages to the DSP is used in the following
++ * way:
++ *
++ * bufEmpty - This flag is set to FALSE by the GPP after it has output
++ * messages for the DSP. The DSP host driver sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 by the GPP after it has written the messages,
++ * set the size, and set bufEmpty to FALSE.
++ * The DSP Host driver uses SWI_andn of the postSWI field
++ * when a host interrupt occurs. The host driver clears
++ * this after posting the SWI.
++ * size - Number of messages to be read by the DSP.
++ *
++ * For messages from the DSP:
++ * bufEmpty - This flag is set to FALSE by the DSP after it has output
++ * messages for the GPP. The DPC on the GPP sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 the DPC on the GPP after copying the messages.
++ * size - Number of messages to be read by the GPP.
++ */
++struct MSG {
++ u32 bufEmpty; /* to/from DSP buffer is empty */
++ u32 postSWI; /* Set to "1" to post MSG SWI */
++ u32 size; /* Number of messages to/from the DSP */
++ u32 resvd;
++} ;
++
++/*
++ * ======== MSG_MGR ========
++ * The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
++ * have MSG_QUEUE to hold all messages that come up from the corresponding
++ * node on the DSP. The MSG_MGR also has a shared queue of messages
++ * ready to go to the DSP.
++ */
++struct MSG_MGR {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++
++ struct IO_MGR *hIOMgr; /* IO manager */
++ struct LST_LIST *queueList; /* List of MSG_QUEUEs */
++ struct SYNC_CSOBJECT *hSyncCS; /* For critical sections */
++ /* Signalled when MsgFrame is available */
++ struct SYNC_OBJECT *hSyncEvent;
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ struct LST_LIST *msgUsedList; /* MsgFrames ready to go to DSP */
++ u32 uMsgsPending; /* # of queued messages to go to DSP */
++ u32 uMaxMsgs; /* Max # of msgs that fit in buffer */
++ MSG_ONEXIT onExit; /* called when RMS_EXIT is received */
++} ;
++
++/*
++ * ======== MSG_QUEUE ========
++ * Each NODE has a MSG_QUEUE for receiving messages from the
++ * corresponding node on the DSP. The MSG_QUEUE object maintains a list
++ * of messages that have been sent to the host, but not yet read (MSG_Get),
++ * and a list of free frames that can be filled when new messages arrive
++ * from the DSP.
++ * The MSG_QUEUE's hSynEvent gets posted when a message is ready.
++ */
++struct MSG_QUEUE {
++ struct LST_ELEM listElem;
++ u32 dwSignature;
++ struct MSG_MGR *hMsgMgr;
++ u32 uMaxMsgs; /* Node message depth */
++ u32 dwId; /* Node environment pointer */
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ /* Filled MsgFramess waiting to be read */
++ struct LST_LIST *msgUsedList;
++ HANDLE hArg; /* Handle passed to mgr onExit callback */
++ struct SYNC_OBJECT *hSyncEvent; /* Signalled when message is ready */
++ struct SYNC_OBJECT *hSyncDone; /* For synchronizing cleanup */
++ struct SYNC_OBJECT *hSyncDoneAck; /* For synchronizing cleanup */
++ struct NTFY_OBJECT *hNtfy; /* For notification of message ready */
++ bool fDone; /* TRUE <==> deleting the object */
++ u32 refCount; /* Number of pending MSG_get/put calls */
++};
++
++/*
++ * ======== MSG_DSPMSG ========
++ */
++struct MSG_DSPMSG {
++ struct DSP_MSG msg;
++ u32 dwId; /* Identifies the node the message goes to */
++} ;
++
++/*
++ * ======== MSG_FRAME ========
++ */
++struct MSG_FRAME {
++ struct LST_ELEM listElem;
++ struct MSG_DSPMSG msgData;
++} ;
++
++#endif /* _MSG_SM_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
+new file mode 100644
+index 0000000..815f695
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap.h
+@@ -0,0 +1,384 @@
++/*
++ * _tiomap.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap.h ========
++ * Description:
++ * Definitions and types private to this WMD.
++ *
++ */
++
++#ifndef _TIOMAP_
++#define _TIOMAP_
++
++#include <dspbridge/devdefs.h>
++#include <hw_defs.h>
++#include <hw_mbox.h>
++#include <dspbridge/wmdioctl.h> /* for WMDIOCTL_EXTPROC defn */
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++
++struct MAP_L4PERIPHERAL {
++ u32 physAddr;
++ u32 dspVirtAddr;
++} ;
++
++#define ARM_MAILBOX_START 0xfffcf000
++#define ARM_MAILBOX_LENGTH 0x800
++
++/* New Registers in OMAP3.1 */
++
++#define TESTBLOCK_ID_START 0xfffed400
++#define TESTBLOCK_ID_LENGTH 0xff
++
++/* ID Returned by OMAP1510 */
++#define TBC_ID_VALUE 0xB47002F
++
++#define SPACE_LENGTH 0x2000
++#define API_CLKM_DPLL_DMA 0xfffec000
++#define ARM_INTERRUPT_OFFSET 0xb00
++
++#define BIOS_24XX
++
++#define L4_PERIPHERAL_NULL 0x0
++#define DSPVA_PERIPHERAL_NULL 0x0
++
++#define MAX_LOCK_TLB_ENTRIES 15
++
++#define L4_PERIPHERAL_PRM 0x48306000 /*PRM L4 Peripheral */
++#define DSPVA_PERIPHERAL_PRM 0x1181e000
++#define L4_PERIPHERAL_SCM 0x48002000 /*SCM L4 Peripheral */
++#define DSPVA_PERIPHERAL_SCM 0x1181f000
++#define L4_PERIPHERAL_MMU 0x5D000000 /*MMU L4 Peripheral */
++#define DSPVA_PERIPHERAL_MMU 0x11820000
++#define L4_PERIPHERAL_CM 0x48004000 /* Core L4, Clock Management */
++#define DSPVA_PERIPHERAL_CM 0x1181c000
++#define L4_PERIPHERAL_PER 0x48005000 /* PER */
++#define DSPVA_PERIPHERAL_PER 0x1181d000
++
++#define L4_PERIPHERAL_GPIO1 0x48310000
++#define DSPVA_PERIPHERAL_GPIO1 0x11809000
++#define L4_PERIPHERAL_GPIO2 0x49050000
++#define DSPVA_PERIPHERAL_GPIO2 0x1180a000
++#define L4_PERIPHERAL_GPIO3 0x49052000
++#define DSPVA_PERIPHERAL_GPIO3 0x1180b000
++#define L4_PERIPHERAL_GPIO4 0x49054000
++#define DSPVA_PERIPHERAL_GPIO4 0x1180c000
++#define L4_PERIPHERAL_GPIO5 0x49056000
++#define DSPVA_PERIPHERAL_GPIO5 0x1180d000
++
++#define L4_PERIPHERAL_IVA2WDT 0x49030000
++#define DSPVA_PERIPHERAL_IVA2WDT 0x1180e000
++
++#define L4_PERIPHERAL_DISPLAY 0x48050000
++#define DSPVA_PERIPHERAL_DISPLAY 0x1180f000
++
++#define L4_PERIPHERAL_SSI 0x48058000
++#define DSPVA_PERIPHERAL_SSI 0x11804000
++#define L4_PERIPHERAL_GDD 0x48059000
++#define DSPVA_PERIPHERAL_GDD 0x11805000
++#define L4_PERIPHERAL_SS1 0x4805a000
++#define DSPVA_PERIPHERAL_SS1 0x11806000
++#define L4_PERIPHERAL_SS2 0x4805b000
++#define DSPVA_PERIPHERAL_SS2 0x11807000
++
++#define L4_PERIPHERAL_CAMERA 0x480BC000
++#define DSPVA_PERIPHERAL_CAMERA 0x11819000
++
++#define L4_PERIPHERAL_SDMA 0x48056000
++#define DSPVA_PERIPHERAL_SDMA 0x11810000 /*0x1181d000 conflicts with PER */
++
++#define L4_PERIPHERAL_UART1 0x4806a000
++#define DSPVA_PERIPHERAL_UART1 0x11811000
++#define L4_PERIPHERAL_UART2 0x4806c000
++#define DSPVA_PERIPHERAL_UART2 0x11812000
++#define L4_PERIPHERAL_UART3 0x49020000
++#define DSPVA_PERIPHERAL_UART3 0x11813000
++
++#define L4_PERIPHERAL_MCBSP1 0x48074000
++#define DSPVA_PERIPHERAL_MCBSP1 0x11814000
++#define L4_PERIPHERAL_MCBSP2 0x49022000
++#define DSPVA_PERIPHERAL_MCBSP2 0x11815000
++#define L4_PERIPHERAL_MCBSP3 0x49024000
++#define DSPVA_PERIPHERAL_MCBSP3 0x11816000
++#define L4_PERIPHERAL_MCBSP4 0x49026000
++#define DSPVA_PERIPHERAL_MCBSP4 0x11817000
++#define L4_PERIPHERAL_MCBSP5 0x48096000
++#define DSPVA_PERIPHERAL_MCBSP5 0x11818000
++
++#define L4_PERIPHERAL_GPTIMER5 0x49038000
++#define DSPVA_PERIPHERAL_GPTIMER5 0x11800000
++#define L4_PERIPHERAL_GPTIMER6 0x4903a000
++#define DSPVA_PERIPHERAL_GPTIMER6 0x11801000
++#define L4_PERIPHERAL_GPTIMER7 0x4903c000
++#define DSPVA_PERIPHERAL_GPTIMER7 0x11802000
++#define L4_PERIPHERAL_GPTIMER8 0x4903e000
++#define DSPVA_PERIPHERAL_GPTIMER8 0x11803000
++
++#define L4_PERIPHERAL_SPI1 0x48098000
++#define DSPVA_PERIPHERAL_SPI1 0x1181a000
++#define L4_PERIPHERAL_SPI2 0x4809a000
++#define DSPVA_PERIPHERAL_SPI2 0x1181b000
++
++#define L4_PERIPHERAL_MBOX 0x48094000
++#define DSPVA_PERIPHERAL_MBOX 0x11808000
++
++#define PM_GRPSEL_BASE 0x48307000
++#define DSPVA_GRPSEL_BASE 0x11821000
++
++#define L4_PERIPHERAL_SIDETONE_MCBSP2 0x49028000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP2 0x11824000
++#define L4_PERIPHERAL_SIDETONE_MCBSP3 0x4902a000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP3 0x11825000
++
++/* define a static array with L4 mappings */
++static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
++ {L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX},
++ {L4_PERIPHERAL_SCM, DSPVA_PERIPHERAL_SCM},
++ {L4_PERIPHERAL_MMU, DSPVA_PERIPHERAL_MMU},
++ {L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5},
++ {L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6},
++ {L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7},
++ {L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8},
++ {L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1},
++ {L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2},
++ {L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3},
++ {L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4},
++ {L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5},
++ {L4_PERIPHERAL_IVA2WDT, DSPVA_PERIPHERAL_IVA2WDT},
++ {L4_PERIPHERAL_DISPLAY, DSPVA_PERIPHERAL_DISPLAY},
++ {L4_PERIPHERAL_SSI, DSPVA_PERIPHERAL_SSI},
++ {L4_PERIPHERAL_GDD, DSPVA_PERIPHERAL_GDD},
++ {L4_PERIPHERAL_SS1, DSPVA_PERIPHERAL_SS1},
++ {L4_PERIPHERAL_SS2, DSPVA_PERIPHERAL_SS2},
++ {L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1},
++ {L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2},
++ {L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3},
++ {L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1},
++ {L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2},
++ {L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3},
++ {L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4},
++ {L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5},
++ {L4_PERIPHERAL_CAMERA, DSPVA_PERIPHERAL_CAMERA},
++ {L4_PERIPHERAL_SPI1, DSPVA_PERIPHERAL_SPI1},
++ {L4_PERIPHERAL_SPI2, DSPVA_PERIPHERAL_SPI2},
++ {L4_PERIPHERAL_PRM, DSPVA_PERIPHERAL_PRM},
++ {L4_PERIPHERAL_CM, DSPVA_PERIPHERAL_CM},
++ {L4_PERIPHERAL_PER, DSPVA_PERIPHERAL_PER},
++ {PM_GRPSEL_BASE, DSPVA_GRPSEL_BASE},
++ {L4_PERIPHERAL_SIDETONE_MCBSP2, DSPVA_PERIPHERAL_SIDETONE_MCBSP2},
++ {L4_PERIPHERAL_SIDETONE_MCBSP3, DSPVA_PERIPHERAL_SIDETONE_MCBSP3},
++ {L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
++};
++
++/*
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where c -> Externel Clock Command: Clk & Autoidle Disable/Enable
++ * i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
++ */
++
++/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
++#define MBX_PM_CLK_IDMASK 0x7F
++
++/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
++#define MBX_PM_CLK_CMDSHIFT 7
++
++/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
++#define MBX_PM_CLK_CMDMASK 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
++#define MBX_CORE1_RESOURCES 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
++#define MBX_CORE2_RESOURCES 1
++
++/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
++#define MBX_PM_MAX_RESOURCES 11
++
++/* Power Management Commands */
++enum BPWR_ExtClockCmd {
++ BPWR_DisableClock = 0,
++ BPWR_EnableClock,
++ BPWR_DisableAutoIdle,
++ BPWR_EnableAutoIdle
++} ;
++
++/* OMAP242x specific resources */
++enum BPWR_ExtClockId {
++ BPWR_GPTimer5 = 0x10,
++ BPWR_GPTimer6,
++ BPWR_GPTimer7,
++ BPWR_GPTimer8,
++ BPWR_WDTimer3,
++ BPWR_MCBSP1,
++ BPWR_MCBSP2,
++ BPWR_MCBSP3,
++ BPWR_MCBSP4,
++ BPWR_MCBSP5,
++ BPWR_SSI = 0x20
++} ;
++
++static const u32 BPWR_CLKID[] = {
++ (u32) BPWR_GPTimer5,
++ (u32) BPWR_GPTimer6,
++ (u32) BPWR_GPTimer7,
++ (u32) BPWR_GPTimer8,
++ (u32) BPWR_WDTimer3,
++ (u32) BPWR_MCBSP1,
++ (u32) BPWR_MCBSP2,
++ (u32) BPWR_MCBSP3,
++ (u32) BPWR_MCBSP4,
++ (u32) BPWR_MCBSP5,
++ (u32) BPWR_SSI
++};
++
++struct BPWR_Clk_t {
++ u32 clkId;
++ enum SERVICES_ClkId funClk;
++ enum SERVICES_ClkId intClk;
++} ;
++
++static const struct BPWR_Clk_t BPWR_Clks[] = {
++ {(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
++ {(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
++ {(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
++ {(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
++ {(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
++ {(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
++ {(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
++ {(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
++ {(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
++ {(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
++ {(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
++};
++
++/* Interrupt Register Offsets */
++#define INTH_IT_REG_OFFSET 0x00 /* Interrupt register offset */
++#define INTH_MASK_IT_REG_OFFSET 0x04 /* Mask Interrupt reg offset */
++
++#define DSP_MAILBOX1_INT 10
++
++/*
++ * INTH_InterruptKind_t
++ * Identify the kind of interrupt: either FIQ/IRQ
++ */
++enum INTH_InterruptKind_t {
++ INTH_IRQ = 0,
++ INTH_FIQ = 1
++} ;
++
++enum INTH_SensitiveEdge_t {
++ FALLING_EDGE_SENSITIVE = 0,
++ LOW_LEVEL_SENSITIVE = 1
++} ;
++
++/*
++ * Bit definition of Interrupt Level Registers
++ */
++
++/* Mail Box defines */
++#define MB_ARM2DSP1_REG_OFFSET 0x00
++
++#define MB_ARM2DSP1B_REG_OFFSET 0x04
++
++#define MB_DSP2ARM1B_REG_OFFSET 0x0C
++
++#define MB_ARM2DSP1_FLAG_REG_OFFSET 0x18
++
++#define MB_ARM2DSP_FLAG 0x0001
++
++#define MBOX_ARM2DSP HW_MBOX_ID_0
++#define MBOX_DSP2ARM HW_MBOX_ID_1
++#define MBOX_ARM HW_MBOX_U0_ARM
++#define MBOX_DSP HW_MBOX_U1_DSP1
++
++#define ENABLE true
++#define DISABLE false
++
++#define HIGH_LEVEL true
++#define LOW_LEVEL false
++
++/* Macro's */
++#define REG16(A) (*(REG_UWORD16 *)(A))
++
++#define ClearBit(reg, mask) (reg &= ~mask)
++#define SetBit(reg, mask) (reg |= mask)
++
++#define SetGroupBits16(reg, position, width, value) \
++ do {\
++ reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
++ reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
++ } while (0);
++
++#define ClearBitIndex(reg, index) (reg &= ~(1 << (index)))
++
++/* This mini driver's device context: */
++struct WMD_DEV_CONTEXT {
++ struct DEV_OBJECT *hDevObject; /* Handle to WCD device object. */
++ u32 dwDspBaseAddr; /* Arm's API to DSP virtual base addr */
++ /*
++ * DSP External memory prog address as seen virtually by the OS on
++ * the host side.
++ */
++ u32 dwDspExtBaseAddr; /* See the comment above */
++ u32 dwAPIRegBase; /* API memory mapped registers */
++ u32 dwDSPMmuBase; /* DSP MMU Mapped registers */
++ u32 dwMailBoxBase; /* Mail box mapped registers */
++ u32 dwAPIClkBase; /* CLK Registers */
++ u32 dwDSPClkM2Base; /* DSP Clock Module m2 */
++ u32 dwPublicRhea; /* Pub Rhea */
++ u32 dwIntAddr; /* MB INTR reg */
++ u32 dwTCEndianism; /* TC Endianism register */
++ u32 dwTestBase; /* DSP MMU Mapped registers */
++ u32 dwSelfLoop; /* Pointer to the selfloop */
++ u32 dwDSPStartAdd; /* API Boot vector */
++ u32 dwInternalSize; /* Internal memory size */
++
++ /*
++ * Processor specific info is set when prog loaded and read from DCD.
++ * [See WMD_BRD_Ctrl()] PROC info contains DSP-MMU TLB entries.
++ */
++ /* DMMU TLB entries */
++ struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
++ u32 dwBrdState; /* Last known board state. */
++ u32 ulIntMask; /* int mask */
++ u16 ioBase; /* Board I/O base */
++ u32 numTLBEntries; /* DSP MMU TLB entry counter */
++ u32 fixedTLBEntries; /* Fixed DSPMMU TLB entry count */
++
++ /* TC Settings */
++ bool tcWordSwapOn; /* Traffic Controller Word Swap */
++ struct PgTableAttrs *pPtAttrs;
++ u32 uDspPerClks;
++} ;
++
++ /*
++ * ======== WMD_TLB_DspVAToMpuPA ========
++ * Given a DSP virtual address, traverse the page table and return
++ * a corresponding MPU physical address and size.
++ */
++extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 ulVirtAddr,
++ OUT u32 *ulPhysAddr,
++ OUT u32 *sizeTlb);
++
++#endif /* _TIOMAP_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+new file mode 100644
+index 0000000..6b21047
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+@@ -0,0 +1,53 @@
++/*
++ * _tiomap_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_mmu.h ========
++ * Description:
++ * Definitions and types for the DSP MMU modules
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb: Renamed HW types. Removed dspMmuTlbEntry
++ *! 05-Jan-2004 vp: Moved the file to a platform specific folder from common.
++ *! 21-Mar-2003 sb: Added macro definition TIHEL_LARGEPAGESIZE
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_MMU_
++#define _TIOMAP_MMU_
++
++#include "_tiomap.h"
++
++/*
++ * ======== configureDspMmu ========
++ *
++ * Make DSP MMu page table entries.
++ * Note: Not utilizing Coarse / Fine page tables.
++ * SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
++ * DSP Byte address 0x40_0000 is word addr 0x20_0000.
++ */
++extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dataBasePhys,
++ u32 dspBaseVirt,
++ u32 sizeInBytes,
++ s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++#endif /* _TIOMAP_MMU_ */
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+new file mode 100644
+index 0000000..7ebd7b5
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+@@ -0,0 +1,102 @@
++/*
++ * _tiomap_pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_pwr.h ========
++ * Description:
++ * Definitions and types for the DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_PWR_
++#define _TIOMAP_PWR_
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++
++/*
++ * ======== SleepDSP =========
++ * Places the DSP in DeepSleep.
++ */
++extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 dwCmd, IN void *pArgs);
++/*
++ * ========InterruptDSP========
++ * Sends an interrupt to DSP unconditionally.
++ */
++extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
++/*
++ * ======== PostScale_DSP ========
++ * Handle Post Scale notification to DSP
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== PreScale_DSP ========
++ * Handle Pre Scale notification to DSP
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== handle_constraints_set ========
++ * Handle constraints request from DSP
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== DSP_PeripheralClocks_Disable ========
++ * This function disables all the peripheral clocks that
++ * were enabled by DSP. Call this function only when
++ * DSP is entering Hibernation or when DSP is in
++ * Error state
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSP_PeripheralClocks_Enable ========
++ * This function enables all the peripheral clocks that
++ * were requested by DSP.
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSPClkWakeupEventCtrl ========
++ * This function sets the group selction bits for while
++ * enabling/disabling.
++ */
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable);
++
++#endif /* _TIOMAP_PWR_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
+new file mode 100644
+index 0000000..47e1e5d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
+@@ -0,0 +1,46 @@
++/*
++ * _tiomap_util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_util.h ========
++ * Description:
++ * Definitions and types for the utility routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_UTIL_
++#define _TIOMAP_UTIL_
++
++/* Time out Values in uSeconds*/
++#define TIHELEN_ACKTIMEOUT 10000
++
++/* Time delay for HOM->SAM transition. */
++#define WAIT_SAM 1000000 /* in usec (1000 millisec) */
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ * The argument dwSyncAddr is set to 1 before releasing the DSP.
++ * If the DSP starts running, it will clear this location.
++ */
++extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
++
++#endif /* _TIOMAP_UTIL_ */
++
+diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
+new file mode 100644
+index 0000000..e8ffb2f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/chnl_sm.c
+@@ -0,0 +1,1100 @@
++/*
++ * chnl_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD channel module.
++ *
++ * Public Functions:
++ * WMD_CHNL_AddIOReq
++ * WMD_CHNL_CancelIO
++ * WMD_CHNL_Close
++ * WMD_CHNL_Create
++ * WMD_CHNL_Destroy
++ * WMD_CHNL_FlushIO
++ * WMD_CHNL_GetInfo
++ * WMD_CHNL_GetIOC
++ * WMD_CHNL_GetMgrInfo
++ * WMD_CHNL_Idle
++ * WMD_CHNL_Open
++ *
++ * Notes:
++ * The lower edge functions must be implemented by the WMD writer, and
++ * are declared in chnl_sm.h.
++ *
++ * Care is taken in this code to prevent simulataneous access to channel
++ * queues from
++ * 1. Threads.
++ * 2. IO_DPC(), scheduled from the IO_ISR() as an event.
++ *
++ * This is done primarily by:
++ * - Semaphores.
++ * - state flags in the channel object; and
++ * - ensuring the IO_Dispatch() routine, which is called from both
++ * CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
++ * This invariant condition is:
++ *
++ * LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
++ * and
++ * !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
++ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 29-Aug-2002 rr Changed the SYNC error code return to DSP error code return
++ * in WMD_CHNL_GetIOC.
++ *! 22-Jan-2002 ag Zero-copy support added.
++ *! CMM_CallocBuf() used for SM allocations.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
++ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
++ *! Remove #ifdef DEBUG from around channel cIOCs field.
++ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
++ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
++ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
++ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
++ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
++ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
++ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
++ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
++ *! SM addrs taken from COFF(IO) or host resource(SM).
++ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
++ *! address and length from symbols defined in the currently
++ *! loaded COFF file. See _chn_sm.h.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
++ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
++ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
++ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
++ *! of the SHM window length reported by Windows CM.
++ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
++ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
++ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
++ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
++ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
++ *! 13-Sep-1996 gp: Added performance statistics for channel.
++ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
++ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
++ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
++ *! 17-Jul-1996 gp: Started pseudo coding.
++ *! 11-Jul-1996 gp: Stubbed out.
++ */
++
++/* ----------------------------------- OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini-Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Define for This */
++#define USERMODE_ADDR PAGE_OFFSET
++
++#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
++
++/* ----------------------------------- Function Prototypes */
++static struct LST_LIST *CreateChirpList(u32 uChirps);
++
++static void FreeChirpList(struct LST_LIST *pList);
++
++static struct CHNL_IRP *MakeNewChirp(void);
++
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ */
++DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr, u32 dwArg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwState;
++ bool fIsEOS;
++ struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
++ u8 *pHostSysBuf = NULL;
++ bool fSchedDPC = false;
++ u16 wMbVal = 0;
++
++ DBG_Trace(DBG_ENTER,
++ "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
++ "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType, pChnl->uId);
++
++ fIsEOS = (cBytes == 0) ? true : false;
++
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
++ if (!(pHostBuf < (void *)USERMODE_ADDR)) {
++ pHostSysBuf = pHostBuf;
++ goto func_cont;
++ }
++ /* if addr in user mode, then copy to kernel space */
++ pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
++ if (pHostSysBuf == NULL) {
++ status = DSP_EMEMORY;
++ DBG_Trace(DBG_LEVEL7,
++ "No memory to allocate kernel buffer\n");
++ goto func_cont;
++ }
++ if (CHNL_IsOutput(pChnl->uMode)) {
++ status = copy_from_user(pHostSysBuf, pHostBuf,
++ cBufSize);
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying user buffer to "
++ "kernel, %d bytes remaining.\n",
++ status);
++ MEM_Free(pHostSysBuf);
++ pHostSysBuf = NULL;
++ status = DSP_EPOINTER;
++ }
++ }
++ }
++func_cont:
++ /* Validate args: */
++ if (pHostBuf == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
++ status = CHNL_E_NOEOS;
++ } else {
++ /* Check the channel state: only queue chirp if channel state
++ * allows */
++ dwState = pChnl->dwState;
++ if (dwState != CHNL_STATEREADY) {
++ if (dwState & CHNL_STATECANCEL) {
++ status = CHNL_E_CANCELLED;
++ } else if ((dwState & CHNL_STATEEOS)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = CHNL_E_EOS;
++ } else {
++ /* No other possible states left: */
++ DBC_Assert(0);
++ }
++ }
++ }
++ /* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
++ * channels. DPCCS is held to avoid race conditions with PCPY channels.
++ * If DPC is scheduled in process context (IO_Schedule) and any
++ * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
++ * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* This is a processor-copy channel. */
++ if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
++ /* Check buffer size on output channels for fit. */
++ if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
++ status = CHNL_E_BUFSIZE;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a free chirp: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
++ if (pChirp == NULL)
++ status = CHNL_E_NOIORPS;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Enqueue the chirp on the chnl's IORequest queue: */
++ pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
++ pChirp->pHostSysBuf = pHostSysBuf;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: for dma chans dwDspAddr contains dsp address
++ * of SM buffer.*/
++ DBC_Assert(pChnlMgr->uWordSize != 0);
++ /* DSP address */
++ pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
++ pChirp->cBytes = cBytes;
++ pChirp->cBufSize = cBufSize;
++ /* Only valid for output channel */
++ pChirp->dwArg = dwArg;
++ pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
++ CHNL_IOCSTATCOMPLETE);
++ LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
++ pChirp);
++ pChnl->cIOReqs++;
++ DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
++ /* If end of stream, update the channel state to prevent
++ * more IOR's: */
++ if (fIsEOS)
++ pChnl->dwState |= CHNL_STATEEOS;
++
++ {
++ /* Legacy DSM Processor-Copy */
++ DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
++ /* Request IO from the DSP */
++ IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
++ (CHNL_IsInput(pChnl->uMode) ?
++ IO_INPUT : IO_OUTPUT), &wMbVal);
++ fSchedDPC = true;
++ }
++ }
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ if (wMbVal != 0)
++ IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
++
++ if (fSchedDPC == true) {
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(pChnlMgr->hIOMgr);
++ }
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ */
++DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ u32 iChnl = -1;
++ CHNL_MODE uMode;
++ struct CHNL_IRP *pChirp;
++ struct CHNL_MGR *pChnlMgr = NULL;
++
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ iChnl = pChnl->uId;
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Mark this channel as cancelled, to prevent further IORequests or
++ * IORequests or dispatching. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnl->dwState |= CHNL_STATECANCEL;
++ if (LST_IsEmpty(pChnl->pIORequests))
++ goto func_cont;
++
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* Indicate we have no more buffers available for transfer: */
++ if (CHNL_IsInput(pChnl->uMode)) {
++ IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
++ } else {
++ /* Record that we no longer have output buffers
++ * available: */
++ pChnlMgr->dwOutputMask &= ~(1 << iChnl);
++ }
++ }
++ /* Move all IOR's to IOC queue: */
++ while (!LST_IsEmpty(pChnl->pIORequests)) {
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (pChirp) {
++ pChirp->cBytes = 0;
++ pChirp->status |= CHNL_IOCSTATCANCEL;
++ LST_PutTail(pChnl->pIOCompletions,
++ (struct LST_ELEM *)pChirp);
++ pChnl->cIOCs++;
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ }
++ }
++func_cont:
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ */
++DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++
++ /* Check args: */
++ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_cont;
++ }
++ {
++ /* Cancel IO: this ensures no further IO requests or
++ * notifications.*/
++ status = WMD_CHNL_CancelIO(hChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Assert I/O on this channel is now cancelled: Protects
++ * from IO_DPC. */
++ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
++ /* Invalidate channel object: Protects from
++ * CHNL_GetIOCompletion(). */
++ pChnl->dwSignature = 0x0000;
++ /* Free the slot in the channel manager: */
++ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
++ pChnl->pChnlMgr->cOpenChannels -= 1;
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ /* Reset channel event: (NOTE: hUserEvent freed in user
++ * context.). */
++ if (pChnl->hSyncEvent) {
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ SYNC_CloseEvent(pChnl->hSyncEvent);
++ pChnl->hSyncEvent = NULL;
++ }
++ /* Free I/O request and I/O completion queues: */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ pChnl->cIOReqs = 0;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ /* Release channel object. */
++ MEM_FreeObject(pChnl);
++ pChnl = NULL;
++ }
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ */
++DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = NULL;
++ s32 cChannels;
++#ifdef DEBUG
++ struct CHNL_MGR *hChnlMgr;
++#endif
++ /* Check DBC requirements: */
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->cChannels > 0);
++ DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++#ifdef DEBUG
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr == NULL);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate channel manager object: */
++ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
++ if (pChnlMgr) {
++ /* The cChannels attr must equal the # of supported
++ * chnls for each transport(# chnls for PCPY = DDMA =
++ * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
++ * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */
++ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
++ cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
++ CHNL_PCPY));
++ /* Create array of channels: */
++ pChnlMgr->apChannel = MEM_Calloc(
++ sizeof(struct CHNL_OBJECT *) *
++ cChannels, MEM_NONPAGED);
++ if (pChnlMgr->apChannel) {
++ /* Initialize CHNL_MGR object: */
++ /* Shared memory driver. */
++ pChnlMgr->dwType = CHNL_TYPESM;
++ pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
++ /* total # chnls supported */
++ pChnlMgr->cChannels = cChannels;
++ pChnlMgr->cOpenChannels = 0;
++ pChnlMgr->dwOutputMask = 0;
++ pChnlMgr->dwLastOutput = 0;
++ pChnlMgr->hDevObject = hDevObject;
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_InitializeDPCCS
++ (&pChnlMgr->hCSObj);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ WMD_CHNL_Destroy(pChnlMgr);
++ *phChnlMgr = NULL;
++ } else {
++ /* Return channel manager object to caller... */
++ *phChnlMgr = pChnlMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ u32 iChnl;
++
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Close all open channels: */
++ for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
++ if (DSP_SUCCEEDED
++ (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
++ DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
++ }
++ }
++ /* release critical section */
++ if (pChnlMgr->hCSObj)
++ SYNC_DeleteCS(pChnlMgr->hCSObj);
++
++ /* Free channel manager object: */
++ if (pChnlMgr->apChannel)
++ MEM_Free(pChnlMgr->apChannel);
++
++ /* Set hChnlMgr to NULL in device object. */
++ DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
++ /* Free this Chnl Mgr object: */
++ MEM_FreeObject(hChnlMgr);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * purpose:
++ * Flushes all the outstanding data requests on a channel.
++ */
++DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ CHNL_MODE uMode = -1;
++ struct CHNL_MGR *pChnlMgr;
++ struct CHNL_IOC chnlIOC;
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ if ((dwTimeOut == CHNL_IOCNOWAIT)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = DSP_EINVALIDARG;
++ } else {
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: Currently, if another thread continues to add IO
++ * requests to this channel, this function will continue to
++ * flush all such queued IO requests. */
++ if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
++ /* Wait for IO completions, up to the specified
++ * timeout: */
++ while (!LST_IsEmpty(pChnl->pIORequests) &&
++ DSP_SUCCEEDED(status)) {
++ status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
++ &chnlIOC);
++ if (DSP_FAILED(status))
++ continue;
++
++ if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
++ status = CHNL_E_WAITTIMEOUT;
++
++ }
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++ /* Now, leave the channel in the ready state: */
++ pChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++ }
++ DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ */
++DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ if (pInfo != NULL) {
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ /* Return the requested information: */
++ pInfo->hChnlMgr = pChnl->pChnlMgr;
++ pInfo->hEvent = pChnl->hUserEvent;
++ pInfo->dwID = pChnl->uId;
++ pInfo->dwMode = pChnl->uMode;
++ pInfo->cPosition = pChnl->cBytesMoved;
++ pInfo->hProcess = pChnl->hProcess;
++ pInfo->hSyncEvent = pChnl->hSyncEvent;
++ pInfo->cIOCs = pChnl->cIOCs;
++ pInfo->cIOReqs = pChnl->cIOReqs;
++ pInfo->dwState = pChnl->dwState;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Optionally wait for I/O completion on a channel. Dequeue an I/O
++ * completion record, which contains information about the completed
++ * I/O request.
++ * Note: Ensures Channel Invariant (see notes above).
++ */
++DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp;
++ DSP_STATUS statSync;
++ bool fDequeueIOC = true;
++ struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
++ u8 *pHostSysBuf = NULL;
++
++ DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
++ "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType);
++ /* Check args: */
++ if (pIOC == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (dwTimeOut == CHNL_IOCNOWAIT) {
++ if (LST_IsEmpty(pChnl->pIOCompletions))
++ status = CHNL_E_NOIOC;
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ ioc.status = CHNL_IOCSTATCOMPLETE;
++ if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
++ if (dwTimeOut == CHNL_IOCINFINITE)
++ dwTimeOut = SYNC_INFINITE;
++
++ statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
++ if (statSync == DSP_ETIMEOUT) {
++ /* No response from DSP */
++ ioc.status |= CHNL_IOCSTATTIMEOUT;
++ fDequeueIOC = false;
++ } else if (statSync == DSP_EFAIL) {
++ /* This can occur when the user mode thread is
++ * aborted (^C), or when _VWIN32_WaitSingleObject()
++ * fails due to unkown causes. */
++ /* Even though Wait failed, there may be something in
++ * the Q: */
++ if (LST_IsEmpty(pChnl->pIOCompletions)) {
++ ioc.status |= CHNL_IOCSTATCANCEL;
++ fDequeueIOC = false;
++ }
++ }
++ }
++ /* See comment in AddIOReq */
++ SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (fDequeueIOC) {
++ /* Dequeue IOC and set pIOC; */
++ DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
++ /* Update pIOC from channel state and chirp: */
++ if (pChirp) {
++ pChnl->cIOCs--;
++ /* If this is a zero-copy channel, then set IOC's pBuf
++ * to the DSP's address. This DSP address will get
++ * translated to user's virtual addr later. */
++ {
++ pHostSysBuf = pChirp->pHostSysBuf;
++ ioc.pBuf = pChirp->pHostUserBuf;
++ }
++ ioc.cBytes = pChirp->cBytes;
++ ioc.cBufSize = pChirp->cBufSize;
++ ioc.dwArg = pChirp->dwArg;
++ ioc.status |= pChirp->status;
++ /* Place the used chirp on the free list: */
++ LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
++ pChirp);
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ }
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ ioc.dwArg = 0;
++ ioc.cBufSize = 0;
++ }
++ /* Ensure invariant: If any IOC's are queued for this channel... */
++ if (!LST_IsEmpty(pChnl->pIOCompletions)) {
++ /* Since DSPStream_Reclaim() does not take a timeout
++ * parameter, we pass the stream's timeout value to
++ * WMD_CHNL_GetIOC. We cannot determine whether or not
++ * we have waited in User mode. Since the stream's timeout
++ * value may be non-zero, we still have to set the event.
++ * Therefore, this optimization is taken out.
++ *
++ * if (dwTimeOut == CHNL_IOCNOWAIT) {
++ * ... ensure event is set..
++ * SYNC_SetEvent(pChnl->hSyncEvent);
++ * } */
++ SYNC_SetEvent(pChnl->hSyncEvent);
++ } else {
++ /* else, if list is empty, ensure event is reset. */
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
++ if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
++ if (!(ioc.pBuf < (void *) USERMODE_ADDR))
++ goto func_cont;
++
++ /* If the addr is in user mode, then copy it */
++ if (!pHostSysBuf || !ioc.pBuf) {
++ status = DSP_EPOINTER;
++ DBG_Trace(DBG_LEVEL7,
++ "System buffer NULL in IO completion.\n");
++ goto func_cont;
++ }
++ if (!CHNL_IsInput(pChnl->uMode))
++ goto func_cont1;
++
++ /*pHostUserBuf */
++ status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
++#ifndef RES_CLEANUP_DISABLE
++ if (status) {
++ if (current->flags & PF_EXITING) {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags == PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ status = 0;
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags != PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ }
++ }
++#endif
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying kernel buffer to user, %d"
++ " bytes remaining. in_interupt %d\n",
++ status, in_interrupt());
++ status = DSP_EPOINTER;
++ }
++func_cont1:
++ MEM_Free(pHostSysBuf);
++ }
++func_cont:
++ /* Update User's IOC block: */
++ *pIOC = ioc;
++func_end:
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Retrieve information related to the channel manager.
++ */
++DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
++ OUT struct CHNL_MGRINFO *pMgrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
++
++ if (pMgrInfo != NULL) {
++ if (uChnlID <= CHNL_MAXCHANNELS) {
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Return the requested information: */
++ pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
++ pMgrInfo->cOpenChannels = pChnlMgr->
++ cOpenChannels;
++ pMgrInfo->dwType = pChnlMgr->dwType;
++ /* total # of chnls */
++ pMgrInfo->cChannels = pChnlMgr->cChannels;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = CHNL_E_BADCHANID;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Idles a particular channel.
++ */
++DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ bool fFlush)
++{
++ CHNL_MODE uMode;
++ struct CHNL_MGR *pChnlMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
++
++ uMode = hChnl->uMode;
++ pChnlMgr = hChnl->pChnlMgr;
++
++ if (CHNL_IsOutput(uMode) && !fFlush) {
++ /* Wait for IO completions, up to the specified timeout: */
++ status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++
++ /* Reset the byte count and put channel back in ready state. */
++ hChnl->cBytesMoved = 0;
++ hChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Open a new half-duplex channel to the DSP board.
++ */
++DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
++ u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ struct CHNL_OBJECT *pChnl = NULL;
++ struct SYNC_ATTRS *pSyncAttrs = NULL;
++ struct SYNC_OBJECT *hSyncEvent = NULL;
++ /* Ensure DBC requirements: */
++ DBC_Require(phChnl != NULL);
++ DBC_Require(pAttrs != NULL);
++ *phChnl = NULL;
++ /* Validate Args: */
++ if (pAttrs->uIOReqs == 0) {
++ status = DSP_EINVALIDARG;
++ } else {
++ if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uChnlId != CHNL_PICKFREE) {
++ if (uChnlId >= pChnlMgr->cChannels) {
++ status = CHNL_E_BADCHANID;
++ } else if (pChnlMgr->apChannel[uChnlId] !=
++ NULL) {
++ status = CHNL_E_CHANBUSY;
++ }
++ } else {
++ /* Check for free channel */
++ status = SearchFreeChannel(pChnlMgr, &uChnlId);
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ DBC_Assert(uChnlId < pChnlMgr->cChannels);
++ /* Create channel object: */
++ MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
++ if (!pChnl) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /* Protect queues from IO_DPC: */
++ pChnl->dwState = CHNL_STATECANCEL;
++ /* Allocate initial IOR and IOC queues: */
++ pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
++ pChnl->pIORequests = CreateChirpList(0);
++ pChnl->pIOCompletions = CreateChirpList(0);
++ pChnl->cChirps = pAttrs->uIOReqs;
++ pChnl->cIOCs = 0;
++ pChnl->cIOReqs = 0;
++ status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ status = NTFY_Create(&pChnl->hNtfy);
++ if (DSP_FAILED(status)) {
++ /* The only failure that could have occurred */
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pChnl->pIOCompletions && pChnl->pIORequests &&
++ pChnl->pFreeList) {
++ /* Initialize CHNL object fields: */
++ pChnl->pChnlMgr = pChnlMgr;
++ pChnl->uId = uChnlId;
++ pChnl->uMode = uMode;
++ pChnl->hUserEvent = hSyncEvent; /* for Linux */
++ pChnl->hSyncEvent = hSyncEvent;
++ /* get the process handle */
++ pChnl->hProcess = current->pid;
++ pChnl->pCBArg = 0;
++ pChnl->cBytesMoved = 0;
++ /* Default to proc-copy */
++ pChnl->uChnlType = CHNL_PCPY;
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EINVALIDARG;
++ }
++ if (DSP_FAILED(status)) {
++ /* Free memory */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ if (hSyncEvent) {
++ SYNC_CloseEvent(hSyncEvent);
++ hSyncEvent = NULL;
++ }
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ MEM_FreeObject(pChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert channel object in channel manager: */
++ pChnlMgr->apChannel[pChnl->uId] = pChnl;
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnlMgr->cOpenChannels++;
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ /* Return result... */
++ pChnl->dwSignature = CHNL_SIGNATURE;
++ pChnl->dwState = CHNL_STATEREADY;
++ *phChnl = pChnl;
++ }
++func_end:
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
++ (*phChnl == NULL));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Registers for events on a particular channel.
++ */
++DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
++
++ status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ return status;
++}
++
++/*
++ * ======== CreateChirpList ========
++ * Purpose:
++ * Initialize a queue of channel I/O Request/Completion packets.
++ * Parameters:
++ * uChirps: Number of Chirps to allocate.
++ * Returns:
++ * Pointer to queue of IRPs, or NULL.
++ * Requires:
++ * Ensures:
++ */
++static struct LST_LIST *CreateChirpList(u32 uChirps)
++{
++ struct LST_LIST *pChirpList;
++ struct CHNL_IRP *pChirp;
++ u32 i;
++
++ pChirpList = LST_Create();
++
++ if (pChirpList) {
++ /* Make N chirps and place on queue. */
++ for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
++ NULL); i++) {
++ LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
++ }
++
++ /* If we couldn't allocate all chirps, free those allocated: */
++ if (i != uChirps) {
++ FreeChirpList(pChirpList);
++ pChirpList = NULL;
++ }
++ }
++
++ return pChirpList;
++}
++
++/*
++ * ======== FreeChirpList ========
++ * Purpose:
++ * Free the queue of Chirps.
++ */
++static void FreeChirpList(struct LST_LIST *pChirpList)
++{
++ DBC_Require(pChirpList != NULL);
++
++ while (!LST_IsEmpty(pChirpList))
++ MEM_Free(LST_GetHead(pChirpList));
++
++ LST_Delete(pChirpList);
++}
++
++/*
++ * ======== MakeNewChirp ========
++ * Allocate the memory for a new channel IRP.
++ */
++static struct CHNL_IRP *MakeNewChirp(void)
++{
++ struct CHNL_IRP *pChirp;
++
++ pChirp = (struct CHNL_IRP *)MEM_Calloc(
++ sizeof(struct CHNL_IRP), MEM_NONPAGED);
++ if (pChirp != NULL) {
++ /* LST_InitElem only resets the list's member values. */
++ LST_InitElem(&pChirp->link);
++ }
++
++ return pChirp;
++}
++
++/*
++ * ======== SearchFreeChannel ========
++ * Search for a free channel slot in the array of channel pointers.
++ */
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl)
++{
++ DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++
++ for (i = 0; i < pChnlMgr->cChannels; i++) {
++ if (pChnlMgr->apChannel[i] == NULL) {
++ status = DSP_SOK;
++ *pdwChnl = i;
++ break;
++ }
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
+new file mode 100644
+index 0000000..325f1f1
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/io_sm.c
+@@ -0,0 +1,2011 @@
++/*
++ * io_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== io_sm.c ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ *
++ * Public Functions:
++ * WMD_IO_Create
++ * WMD_IO_Destroy
++ * WMD_IO_OnLoaded
++ * IO_AndSetValue
++ * IO_BufSize
++ * IO_CancelChnl
++ * IO_DPC
++ * IO_ISR
++ * IO_IVAISR
++ * IO_OrSetValue
++ * IO_ReadValue
++ * IO_ReadValueLong
++ * IO_RequestChnl
++ * IO_Schedule
++ * IO_WriteValue
++ * IO_WriteValueLong
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure of the WIN32_WaitSingleObject
++ * function (SYNC_WaitOnEvent).
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/workqueue.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdioctl.h>
++#include <_tiomap.h>
++#include <tiomap_io.h>
++#include <_tiomap_pwr.h>
++#include <tiomap_io.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/rms_sh.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/drv.h>
++#include "_cmm.h"
++
++/* ----------------------------------- This */
++#include <dspbridge/io_sm.h>
++#include "_msg_sm.h"
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define OUTPUTNOTREADY 0xffff
++#define NOTENABLED 0xffff /* channel(s) not enabled */
++
++#define EXTEND "_EXT_END"
++
++#define SwapWord(x) (x)
++#define ulPageAlignSize 0x10000 /* Page Align Size */
++
++#define MAX_PM_REQS 32
++
++/* IO Manager: only one created per board: */
++struct IO_MGR {
++ /* These four fields must be the first fields in a IO_MGR_ struct: */
++ u32 dwSignature; /* Used for object validation */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents */
++
++ /* These fields initialized in WMD_IO_Create(): */
++ struct CHNL_MGR *hChnlMgr;
++ struct SHM *pSharedMem; /* Shared Memory control */
++ u8 *pInput; /* Address of input channel */
++ u8 *pOutput; /* Address of output channel */
++ struct MSG_MGR *hMsgMgr; /* Message manager */
++ struct MSG *pMsgInputCtrl; /* Msg control for from DSP messages */
++ struct MSG *pMsgOutputCtrl; /* Msg control for to DSP messages */
++ u8 *pMsgInput; /* Address of input messages */
++ u8 *pMsgOutput; /* Address of output messages */
++ u32 uSMBufSize; /* Size of a shared memory I/O channel */
++ bool fSharedIRQ; /* Is this IRQ shared? */
++ struct DPC_OBJECT *hDPC; /* DPC object handle */
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u16 wIntrVal; /* interrupt value */
++ /* private extnd proc info; mmu setup */
++ struct MGR_PROCESSOREXTINFO extProcInfo;
++ struct CMM_OBJECT *hCmmMgr; /* Shared Mem Mngr */
++ struct work_struct io_workq; /*workqueue */
++ u32 dQuePowerMbxVal[MAX_PM_REQS];
++ u32 iQuePowerHead;
++ u32 iQuePowerTail;
++#ifndef DSP_TRACEBUF_DISABLED
++ u32 ulTraceBufferBegin; /* Trace message start address */
++ u32 ulTraceBufferEnd; /* Trace message end address */
++ u32 ulTraceBufferCurrent; /* Trace message current address */
++ u32 ulGPPReadPointer; /* GPP Read pointer to Trace buffer */
++ u8 *pMsg;
++ u32 ulGppVa;
++ u32 ulDspVa;
++#endif
++} ;
++
++/* ----------------------------------- Function Prototypes */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void IO_DispatchPM(struct work_struct *work);
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp);
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask);
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static struct workqueue_struct *bridge_workqueue;
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
++#endif
++
++/* Bus Addr (cached kernel)*/
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA);
++
++#ifdef CONFIG_BRIDGE_DVFS
++/* The maximum number of OPPs that are supported */
++extern s32 dsp_max_opps;
++/* The Vdd1 opp table information */
++extern u32 vdd1_dsp_freq[6][4] ;
++#endif
++
++#if GT_TRACE
++static struct GT_Mask dsp_trace_mask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== WMD_IO_Create ========
++ * Create an IO manager object.
++ */
++DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct IO_MGR *pIOMgr = NULL;
++ struct SHM *pSharedMem = NULL;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++ struct CFG_HOSTRES hostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct CHNL_MGR *hChnlMgr;
++ static int ref_count;
++ u32 devType;
++ /* Check DBC requirements: */
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr != NULL);
++ DBC_Require(hChnlMgr->hIOMgr == NULL);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ DEV_GetDevType(hDevObject, &devType);
++ /* DSP shared memory area will get set properly when
++ * a program is loaded. They are unknown until a COFF file is
++ * loaded. I chose the value -1 because it was less likely to be
++ * a valid address than 0. */
++ pSharedMem = (struct SHM *) -1;
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /*
++ * Create a Single Threaded Work Queue
++ */
++
++ if (ref_count == 0)
++ bridge_workqueue = create_workqueue("bridge_work-queue");
++
++ if (bridge_workqueue <= 0)
++ DBG_Trace(DBG_LEVEL1, "Workque Create"
++ " failed 0x%d \n", bridge_workqueue);
++
++
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
++ if (pIOMgr == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /*Intializing Work Element*/
++ if (ref_count == 0) {
++ INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++ ref_count = 1;
++ } else
++ PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++
++ /* Initialize CHNL_MGR object: */
++#ifndef DSP_TRACEBUF_DISABLED
++ pIOMgr->pMsg = NULL;
++#endif
++ pIOMgr->hChnlMgr = hChnlMgr;
++ pIOMgr->uWordSize = pMgrAttrs->uWordSize;
++ pIOMgr->pSharedMem = pSharedMem;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pIOMgr->hCSObj);
++
++ if (devType == DSP_UNIT) {
++ /* Create a DPC object: */
++ status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ pIOMgr->iQuePowerHead = 0;
++ pIOMgr->iQuePowerTail = 0;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension() , &hostRes);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr->hWmdContext = hWmdContext;
++ pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
++ IO_DisableInterrupt(hWmdContext);
++ if (devType == DSP_UNIT) {
++ /* Plug the channel ISR:. */
++ if ((request_irq(INT_MAIL_MPU_IRQ, IO_ISR, 0,
++ "DspBridge\tmailbox", (void *)pIOMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status))
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pIOMgr);
++ else
++ status = CHNL_E_ISR;
++ } else
++ status = CHNL_E_ISR;
++func_cont:
++ if (DSP_FAILED(status)) {
++ /* Cleanup: */
++ WMD_IO_Destroy(pIOMgr);
++ *phIOMgr = NULL;
++ } else {
++ /* Return IO manager object to caller... */
++ hChnlMgr->hIOMgr = pIOMgr;
++ *phIOMgr = pIOMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Disable interrupts, destroy the IO manager.
++ */
++DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
++ /* Unplug IRQ: */
++ /* Disable interrupts from the board: */
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject,
++ &hWmdContext)))
++ DBC_Assert(hWmdContext);
++ (void)CHNLSM_DisableInterrupt(hWmdContext);
++ destroy_workqueue(bridge_workqueue);
++ /* Linux function to uninstall ISR */
++ free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr);
++ (void)DPC_Destroy(hIOMgr->hDPC);
++#ifndef DSP_TRACEBUF_DISABLED
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++#endif
++ SYNC_DeleteCS(hIOMgr->hCSObj); /* Leak Fix. */
++ /* Free this IO manager object: */
++ MEM_FreeObject(hIOMgr);
++ } else
++ status = DSP_EHANDLE;
++
++ return status;
++}
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called when a new program is loaded to get shared memory buffer
++ * parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
++ * are in DSP address units.
++ */
++DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
++{
++ struct COD_MANAGER *hCodMan;
++ struct CHNL_MGR *hChnlMgr;
++ struct MSG_MGR *hMsgMgr;
++ u32 ulShmBase;
++ u32 ulShmBaseOffset;
++ u32 ulShmLimit;
++ u32 ulShmLength = -1;
++ u32 ulMemLength = -1;
++ u32 ulMsgBase;
++ u32 ulMsgLimit;
++ u32 ulMsgLength = -1;
++ u32 ulExtEnd;
++ u32 ulGppPa = 0;
++ u32 ulGppVa = 0;
++ u32 ulDspVa = 0;
++ u32 ulSegSize = 0;
++ u32 ulPadSize = 0;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 uNumProcs = 0;
++ s32 ndx = 0;
++ /* DSP MMU setup table */
++ struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
++ struct CFG_HOSTRES hostRes;
++ u32 mapAttrs;
++ u32 ulShm0End;
++ u32 ulDynExtBase;
++ u32 ulSeg1Size = 0;
++ u32 paCurr = 0;
++ u32 vaCurr = 0;
++ u32 gppVaCurr = 0;
++ u32 numBytes = 0;
++ u32 allBits = 0;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++
++ status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ hChnlMgr = hIOMgr->hChnlMgr;
++ /* The message manager is destroyed when the board is stopped. */
++ DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
++ hMsgMgr = hIOMgr->hMsgMgr;
++ DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
++ DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ if (hIOMgr->pSharedMem)
++ hIOMgr->pSharedMem = NULL;
++
++ /* Get start and length of channel part of shared memory */
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
++ &ulShmBase);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
++ &ulShmLimit);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ if (ulShmLimit <= ulShmBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* get total length in bytes */
++ ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
++ /* Calculate size of a PROCCOPY shared memory region */
++ DBG_Trace(DBG_LEVEL7,
++ "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
++ (ulShmLength - sizeof(struct SHM)));
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
++ &ulMsgBase);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
++ &ulMsgLimit);
++ if (DSP_SUCCEEDED(status)) {
++ if (ulMsgLimit <= ulMsgBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* Length (bytes) of messaging part of shared
++ * memory */
++ ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
++ hIOMgr->uWordSize;
++ /* Total length (bytes) of shared memory:
++ * chnl + msg */
++ ulMemLength = ulShmLength + ulMsgLength;
++ }
++ } else {
++ status = CHNL_E_NOMEMMAP;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++#ifndef DSP_TRACEBUF_DISABLED
++ status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
++ ulShm0End);
++#else
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
++#endif
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get memory reserved in host resources */
++ (void)MGR_EnumProcessorInfo(0,
++ (struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
++ sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
++ CFG_GetHostResources((
++ struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &hostRes);
++ /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
++ ndx = 0;
++ ulGppPa = hostRes.dwMemPhys[1];
++ ulGppVa = hostRes.dwMemBase[1];
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
++ /* Why can't we directly take the DSPVA from the symbols? */
++ ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
++ ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
++ ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
++ ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
++ ulPageAlignSize);
++ if (ulPadSize == ulPageAlignSize)
++ ulPadSize = 0x0;
++
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
++ "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
++ "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
++ ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
++ ulSeg1Size);
++
++ if ((ulSegSize + ulSeg1Size + ulPadSize) >
++ hostRes.dwMemLength[1]) {
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
++ "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
++ "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
++ ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
++ ulExtEnd, ulSegSize, ulSeg1Size);
++ DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
++ "Required 0x%x\n", hostRes.dwMemLength[1],
++ ulSegSize + ulSeg1Size + ulPadSize);
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ paCurr = ulGppPa;
++ vaCurr = ulDynExtBase * hIOMgr->uWordSize;
++ gppVaCurr = ulGppVa;
++ numBytes = ulSeg1Size;
++
++ /*
++ * Try to fit into TLB entries. If not possible, push them to page
++ * tables. It is quite possible that if sections are not on
++ * bigger page boundary, we may end up making several small pages.
++ * So, push them onto page tables, if that is the case.
++ */
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, paCurr, vaCurr,
++ pgSize[i], mapAttrs);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size*/
++ break;
++ }
++ }
++ }
++ paCurr += ulPadSize;
++ vaCurr += ulPadSize;
++ gppVaCurr += ulPadSize;
++
++ /* configure the TLB entries for the next cacheable segment */
++ numBytes = ulSegSize;
++ vaCurr = ulDspVa * hIOMgr->uWordSize;
++ allBits = 0x0;
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned*/
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
++ "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
++ numBytes);
++ for (i = 0; i < 4; i++) {
++ if (!(numBytes >= pgSize[i]) ||
++ !((allBits & (pgSize[i]-1)) == 0))
++ continue;
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ /* This is the physical address written to
++ * DSP MMU */
++ aEProc[ndx].ulGppPa = paCurr;
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
++ * ADDRESS!!! */
++ aEProc[ndx].ulGppVa = gppVaCurr;
++ aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
++ uWordSize;
++ aEProc[ndx].ulSize = pgSize[i];
++ aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
++ aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
++ aEProc[ndx].mixedMode = HW_MMU_CPUES;
++ DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap(
++ hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
++ mapAttrs);
++ DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ }
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have reached
++ an address aligned to a bigger page size*/
++ break;
++ }
++ }
++
++ /* Copy remaining entries from CDB. All entries are 1 MB and should not
++ * conflict with SHM entries on MPU or DSP side */
++ for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
++ DSP_SUCCEEDED(status); i++) {
++ if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
++ continue;
++
++ if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
++ && hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
++ ulGppPa + ulSegSize)
++ || (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
++ 0x100000 / hIOMgr->uWordSize && hIOMgr->
++ extProcInfo.tyTlb[i].ulDspVirt
++ <= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
++ DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
++ "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
++ "GppPa %x, DspVa %x, Bytes %x.\n", i,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ ulGppPa, ulDspVa, ulSegSize);
++ status = DSP_EFAIL;
++ } else {
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
++ tyTlb[i].ulDspVirt;
++ aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
++ tyTlb[i].ulGppPhys;
++ aEProc[ndx].ulGppVa = 0;
++ /* Can't convert, so set to zero*/
++ aEProc[ndx].ulSize = 0x100000; /* 1 MB*/
++ DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
++ "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulDspVa);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ 0x100000, mapAttrs);
++ }
++ }
++ }
++ if (i < 7 && DSP_SUCCEEDED(status)) {
++ /* All CDB entries could not be made*/
++ status = DSP_EFAIL;
++ }
++func_cont:
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ /* Map the L4 peripherals */
++ i = 0;
++ while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, L4PeripheralTable[i].physAddr,
++ L4PeripheralTable[i].dspVirtAddr, HW_PAGE_SIZE_4KB,
++ mapAttrs);
++ if (DSP_FAILED(status))
++ break;
++ i++;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
++ aEProc[i].ulDspVa = 0;
++ aEProc[i].ulGppPa = 0;
++ aEProc[i].ulGppVa = 0;
++ aEProc[i].ulSize = 0;
++ }
++ /* Set the SHM physical address entry (grayed out in CDB file)
++ * to the virtual uncached ioremapped address of SHM reserved
++ * on MPU */
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
++ ulPadSize);
++ DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
++ /* Need SHM Phys addr. IO supports only one DSP for now:
++ * uNumProcs=1 */
++ if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
++ (uNumProcs != 1)) {
++ status = CHNL_E_NOMEMMAP;
++ DBC_Assert(false);
++ } else {
++ DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
++ /* ulShmBase may not be at ulDspVa address */
++ ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
++ hIOMgr->uWordSize;
++ /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
++ * _BRD_Start() the MMU will be re-programed with MMU
++ * DSPVa-GPPPa pair info while DSP is in a known
++ * (reset) state. */
++ DBC_Assert(hIOMgr->pIntfFxns != NULL);
++ DBC_Assert(hIOMgr->hWmdContext != NULL);
++ status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
++ hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
++ ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
++ "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
++ ulGppPhys);
++ ulShmBase += ulShmBaseOffset;
++ ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
++ ulMemLength);
++ DBC_Assert(ulShmBase != 0);
++ if (DSP_SUCCEEDED(status)) {
++ status = registerSHMSegs(hIOMgr, hCodMan,
++ aEProc[0].ulGppPa);
++ /* Register SM */
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
++ hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
++ sizeof(struct SHM);
++ hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
++ sizeof(struct SHM))/2;
++ hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
++ DBG_Trace(DBG_LEVEL3,
++ "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
++ hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
++ DBG_Trace(DBG_LEVEL3,
++ "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
++ hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
++ sizeof(struct SHM));
++ /* Set up Shared memory addresses for messaging. */
++ hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
++ hIOMgr->pSharedMem +
++ ulShmLength);
++ hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
++ sizeof(struct MSG);
++ hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
++ pMsgInputCtrl + ulMsgLength / 2);
++ hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
++ sizeof(struct MSG);
++ hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
++ hIOMgr->pMsgInput) /
++ sizeof(struct MSG_DSPMSG);
++ DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
++ "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
++ "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
++ "0x%x \n", (u8 *)hIOMgr->pSharedMem,
++ (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
++ (u8 *)hIOMgr->pMsgInputCtrl,
++ (u8 *)hIOMgr->pMsgInput,
++ (u8 *)hIOMgr->pMsgOutputCtrl,
++ (u8 *)hIOMgr->pMsgOutput);
++ DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
++ "0x%x\n", hMsgMgr->uMaxMsgs);
++ memset((void *) hIOMgr->pSharedMem, 0, sizeof(struct SHM));
++ }
++#ifndef DSP_TRACEBUF_DISABLED
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the start address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
++ &hIOMgr->ulTraceBufferBegin);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
++ (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferBegin - ulDspVa);
++ /* Get the end address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
++ &hIOMgr->ulTraceBufferEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferEnd - ulDspVa);
++ /* Get the current address of DSP write pointer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan,
++ BRIDGE_SYS_PUTC_current,
++ &hIOMgr->ulTraceBufferCurrent);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
++ ulPadSize) + (hIOMgr->
++ ulTraceBufferCurrent - ulDspVa);
++ /* Calculate the size of trace buffer */
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++ hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulTraceBufferBegin) *
++ hIOMgr->uWordSize) + 2, MEM_NONPAGED);
++ if (!hIOMgr->pMsg)
++ status = DSP_EMEMORY;
++
++ DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
++ hIOMgr->ulDspVa = ulDspVa;
++ hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
++ }
++#endif
++ IO_EnableInterrupt(hIOMgr->hWmdContext);
++ return status;
++}
++
++/*
++ * ======== IO_BufSize ========
++ * Size of shared memory I/O channel.
++ */
++u32 IO_BufSize(struct IO_MGR *hIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++
++ return hIOMgr->uSMBufSize;
++}
++
++/*
++ * ======== IO_CancelChnl ========
++ * Cancel IO on a given PCPY channel.
++ */
++void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
++ struct SHM *sm;
++
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ sm = hIOMgr->pSharedMem;
++
++ /* Inform DSP that we have no more buffers on this channel: */
++ IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (~(1 << ulChnl)));
++
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++}
++
++/*
++ * ======== IO_DispatchChnl ========
++ * Proc-copy chanl dispatch.
++ */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
++
++ /* See if there is any data available for transfer: */
++ DBC_Assert(iMode == IO_SERVICE);
++
++ /* Any channel will do for this mode: */
++ InputChnl(pIOMgr, pChnl, iMode);
++ OutputChnl(pIOMgr, pChnl, iMode);
++}
++
++/*
++ * ======== IO_DispatchMsg ========
++ * Performs I/O dispatch on message queues.
++ */
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
++
++ /* We are performing both input and output processing. */
++ InputMsg(pIOMgr, hMsgMgr);
++ OutputMsg(pIOMgr, hMsgMgr);
++}
++
++/*
++ * ======== IO_DispatchPM ========
++ * Performs I/O dispatch on PM related messages from DSP
++ */
++static void IO_DispatchPM(struct work_struct *work)
++{
++ struct IO_MGR *pIOMgr =
++ container_of(work, struct IO_MGR, io_workq);
++ DSP_STATUS status;
++ u32 pArg[2];
++
++ /*DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));*/
++
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
++
++ /* Perform Power message processing here */
++ while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
++ pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
++ iQuePowerTail]);
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
++ pArg[0]);
++ /* Send the command to the WMD clk/pwr manager to handle */
++ if (pArg[0] == MBX_PM_HIBERNATE_EN) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
++ "command\n");
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
++ "Hibernation command failed\n");
++ }
++ } else if (pArg[0] == MBX_PM_OPP_REQ) {
++ pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
++ "value =0x%x \n", pArg[1]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
++ pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to set constraint = 0x%x \n",
++ pArg[1]);
++ }
++
++ } else {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
++ "value of msg = 0x%x: \n", pArg[0]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to control the DSP clk = 0x%x \n",
++ *pArg);
++ }
++ }
++ /* increment the tail count here */
++ pIOMgr->iQuePowerTail++;
++ if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
++ pIOMgr->iQuePowerTail = 0;
++
++ }
++
++}
++
++/*
++ * ======== IO_DPC ========
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O as a non-preemptible event.It can only be
++ * pre-empted by an ISR.
++ */
++void IO_DPC(IN OUT void *pRefData)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
++ struct CHNL_MGR *pChnlMgr;
++ struct MSG_MGR *pMsgMgr;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++ pChnlMgr = pIOMgr->hChnlMgr;
++ DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
++ DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
++ /* Check value of interrupt register to ensure it is a valid error */
++ if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
++ /* notify DSP/BIOS exception */
++ if (hDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
++
++ }
++ IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
++#ifdef CHNL_MESSAGES
++ if (pMsgMgr) {
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++ IO_DispatchMsg(pIOMgr, pMsgMgr);
++ }
++#endif
++#ifndef DSP_TRACEBUF_DISABLED
++ if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
++ /* notify DSP Trace message */
++ if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
++ PrintDSPDebugTrace(pIOMgr);
++ }
++#endif
++
++#ifndef DSP_TRACEBUF_DISABLED
++ PrintDSPDebugTrace(pIOMgr);
++#endif
++}
++
++
++/*
++ * ======== IO_ISR ========
++ * Main interrupt handler for the shared memory IO manager.
++ * Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O.
++ */
++irqreturn_t IO_ISR(int irq, IN void *pRefData)
++{
++ struct IO_MGR *hIOMgr = (struct IO_MGR *)pRefData;
++ bool fSchedDPC;
++ DBC_Require(irq == INT_MAIL_MPU_IRQ);
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
++
++ /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
++ if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
++ {
++ DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
++ if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
++ hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
++ hIOMgr->wIntrVal;
++ hIOMgr->iQuePowerHead++;
++ if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
++ hIOMgr->iQuePowerHead = 0;
++
++ queue_work(bridge_workqueue, &hIOMgr->io_workq);
++ }
++ if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
++ DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
++ hIOMgr->wIntrVal = 0;
++ } else if (fSchedDPC) {
++ /* PROC-COPY defer i/o */
++ DPC_Schedule(hIOMgr->hDPC);
++ }
++ }
++ } else
++ /* Ensure that, if WMD didn't claim it, the IRQ is shared. */
++ DBC_Ensure(hIOMgr->fSharedIRQ);
++ return IRQ_HANDLED;
++}
++
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request chanenel I/O from the DSP. Sets flags in shared memory, then
++ * interrupts the DSP.
++ */
++void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ DBC_Require(pChnl != NULL);
++ DBC_Require(pwMbVal != NULL);
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ if (iMode == IO_INPUT) {
++ /* Assertion fires if CHNL_AddIOReq() called on a stream
++ * which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
++ (pChnl->dwState == CHNL_STATEEOS));
++ /* Indicate to the DSP we have a buffer available for input: */
++ IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (1 << pChnl->uId));
++ *pwMbVal = MBX_PCPY_CLASS;
++ } else if (iMode == IO_OUTPUT) {
++ /* This assertion fails if CHNL_AddIOReq() was called on a
++ * stream which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
++ CHNL_STATEREADY);
++ /* Record the fact that we have a buffer available for
++ * output: */
++ pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
++ } else {
++ DBC_Assert(iMode); /* Shouldn't get here. */
++ }
++}
++
++/*
++ * ======== IO_Schedule ========
++ * Schedule DPC for IO.
++ */
++void IO_Schedule(struct IO_MGR *pIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DPC_Schedule(pIOMgr->hDPC);
++}
++
++/*
++ * ======== FindReadyOutput ========
++ * Search for a host output channel which is ready to send. If this is
++ * called as a result of servicing the DPC, then implement a round
++ * robin search; otherwise, this was called by a client thread (via
++ * IO_Dispatch()), so just start searching from the current channel id.
++ */
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask)
++{
++ u32 uRetval = OUTPUTNOTREADY;
++ u32 id, startId;
++ u32 shift;
++
++ id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ DBC_Assert(id < CHNL_MAXCHANNELS);
++ if (dwMask) {
++ shift = (1 << id);
++ startId = id;
++ do {
++ if (dwMask & shift) {
++ uRetval = id;
++ if (pChnl == NULL)
++ pChnlMgr->dwLastOutput = id;
++
++ break;
++ }
++ id = id + 1;
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ shift = (1 << id);
++ } while (id != startId);
++ }
++ DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
++ return uRetval;
++}
++
++/*
++ * ======== InputChnl ========
++ * Dispatch a buffer on an input channel.
++ */
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ u32 uBytes;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwArg;
++ bool fClearChnl = false;
++ bool fNotifyClient = false;
++
++ sm = pIOMgr->pSharedMem;
++ pChnlMgr = pIOMgr->hChnlMgr;
++
++ DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
++
++ /* Attempt to perform input.... */
++ if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
++ goto func_end;
++
++ uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
++ pChnlMgr->uWordSize;
++ chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
++ dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
++ if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
++ /* Shouldn't be here: would indicate corrupted SHM. */
++ DBC_Assert(chnlId);
++ goto func_end;
++ }
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
++ if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
++ if (!pChnl->pIORequests)
++ goto func_end;
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
++ pIORequests);
++ if (pChirp) {
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ /* Ensure we don't overflow the client's
++ * buffer: */
++ uBytes = min(uBytes, pChirp->cBytes);
++ /* Transfer buffer from DSP side: */
++ uBytes = ReadData(pIOMgr->hWmdContext,
++ pChirp->pHostSysBuf,
++ pIOMgr->pInput, uBytes);
++ pChnl->cBytesMoved += uBytes;
++ pChirp->cBytes = uBytes;
++ pChirp->dwArg = dwArg;
++ pChirp->status = CHNL_IOCSTATCOMPLETE;
++ DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
++ "\n", *((RMS_WORD *)(pChirp->
++ pHostSysBuf)));
++ if (uBytes == 0) {
++ /* This assertion fails if the DSP
++ * sends EOS more than once on this
++ * channel: */
++ DBC_Assert(!(pChnl->dwState &
++ CHNL_STATEEOS));
++ /* Zero bytes indicates EOS. Update
++ * IOC status for this chirp, and also
++ * the channel state: */
++ pChirp->status |= CHNL_IOCSTATEOS;
++ pChnl->dwState |= CHNL_STATEEOS;
++ /* Notify that end of stream has
++ * occurred */
++ NTFY_Notify(pChnl->hNtfy,
++ DSP_STREAMDONE);
++ DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
++ "chnl = 0x%x\n", pChnl);
++ }
++ /* Tell DSP if no more I/O buffers available: */
++ if (!pChnl->pIORequests)
++ goto func_end;
++ if (LST_IsEmpty(pChnl->pIORequests)) {
++ IO_AndValue(pIOMgr->hWmdContext,
++ struct SHM, sm, hostFreeMask,
++ ~(1 << pChnl->uId));
++ }
++ fClearChnl = true;
++ fNotifyClient = true;
++ } else {
++ /* Input full for this channel, but we have no
++ * buffers available. The channel must be
++ * "idling". Clear out the physical input
++ * channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* Input channel cancelled: clear input channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* DPC fired after host closed channel: clear input channel. */
++ fClearChnl = true;
++ }
++ if (fClearChnl) {
++ /* Indicate to the DSP we have read the input: */
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ if (fNotifyClient) {
++ /* Notify client with IO completion record: */
++ NotifyChnlComplete(pChnl, pChirp);
++ }
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
++}
++
++/*
++ * ======== InputMsg ========
++ * Copies messages from shared memory to the message queues.
++ */
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs;
++ u32 i;
++ u8 *pMsgInput;
++ struct MSG_QUEUE *hMsgQueue;
++ struct MSG_FRAME *pMsg;
++ struct MSG_DSPMSG msg;
++ struct MSG *pCtrl;
++ u32 fInputEmpty;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgInputCtrl;
++ /* Get the number of input messages to be read. */
++ fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
++ if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
++ return;
++
++ pMsgInput = pIOMgr->pMsgInput;
++ for (i = 0; i < uMsgs; i++) {
++ /* Read the next message */
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
++ msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
++ msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
++ msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
++ msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ pMsgInput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->queueList)
++ goto func_end;
++
++ /* Determine which queue to put the message in */
++ hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
++ DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
++ "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
++ msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
++ /* Interrupt may occur before shared memory and message
++ * input locations have been set up. If all nodes were
++ * cleaned up, hMsgMgr->uMaxMsgs should be 0. */
++ if (hMsgQueue && uMsgs > hMsgMgr->uMaxMsgs)
++ goto func_end;
++
++ while (hMsgQueue != NULL) {
++ if (msg.dwId == hMsgQueue->dwId) {
++ /* Found it */
++ if (msg.msg.dwCmd == RMS_EXITACK) {
++ /* The exit message does not get
++ * queued */
++ /* Call the node exit notification */
++ /* Node handle */ /* status */
++ (*hMsgMgr->onExit)((HANDLE)hMsgQueue->
++ hArg, msg.msg.dwArg1);
++ } else {
++ /* Not an exit acknowledgement, queue
++ * the message */
++ if (!hMsgQueue->msgFreeList)
++ goto func_end;
++ pMsg = (struct MSG_FRAME *)LST_GetHead
++ (hMsgQueue->msgFreeList);
++ if (hMsgQueue->msgUsedList && pMsg) {
++ pMsg->msgData = msg;
++ LST_PutTail(hMsgQueue->
++ msgUsedList,
++ (struct LST_ELEM *)pMsg);
++ NTFY_Notify(hMsgQueue->hNtfy,
++ DSP_NODEMESSAGEREADY);
++ SYNC_SetEvent(hMsgQueue->
++ hSyncEvent);
++ } else {
++ /* No free frame to copy the
++ * message into */
++ DBG_Trace(DBG_LEVEL7, "NO FREE "
++ "MSG FRAMES, DISCARDING"
++ " MESSAGE\n");
++ }
++ }
++ break;
++ }
++
++ if (!hMsgMgr->queueList || !hMsgQueue)
++ goto func_end;
++ hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
++ queueList, (struct LST_ELEM *)hMsgQueue);
++ }
++ }
++ /* Set the post SWI flag */
++ if (uMsgs > 0) {
++ /* Tell the DSP we've read the messages */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
++ true);
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
++ true);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== NotifyChnlComplete ========
++ * Purpose:
++ * Signal the channel event, notifying the client that I/O has completed.
++ */
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp)
++{
++ bool fSignalEvent;
++
++ DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ DBC_Require(pChnl->hSyncEvent != NULL);
++ /* Note: we signal the channel event only if the queue of IO
++ * completions is empty. If it is not empty, the event is sure to be
++ * signalled by the only IO completion list consumer:
++ * WMD_CHNL_GetIOC(). */
++ fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
++ /* Enqueue the IO completion info for the client: */
++ LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
++ pChnl->cIOCs++;
++ DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
++ /* Signal the channel event (if not already set) that IO is complete: */
++ if (fSignalEvent)
++ SYNC_SetEvent(pChnl->hSyncEvent);
++
++ /* Notify that IO is complete */
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
++}
++
++/*
++ * ======== OutputChnl ========
++ * Purpose:
++ * Dispatch a buffer on an output channel.
++ */
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ struct CHNL_IRP *pChirp;
++ u32 dwDspFMask;
++
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
++ /* Attempt to perform output: */
++ if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
++ goto func_end;
++
++ if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
++ goto func_end;
++
++ /* Look to see if both a PC and DSP output channel are ready: */
++ dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
++ dspFreeMask);
++ chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
++ dwDspFMask));
++ if (chnlId == OUTPUTNOTREADY)
++ goto func_end;
++
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if (!pChnl || !pChnl->pIORequests) {
++ /* Shouldn't get here: */
++ goto func_end;
++ }
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (!pChirp)
++ goto func_end;
++
++ pChnl->cIOReqs--;
++ if (pChnl->cIOReqs < 0 || !pChnl->pIORequests)
++ goto func_end;
++
++ /* Record fact that no more I/O buffers available: */
++ if (LST_IsEmpty(pChnl->pIORequests))
++ pChnlMgr->dwOutputMask &= ~(1 << chnlId);
++
++ /* Transfer buffer to DSP side: */
++ pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
++ pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
++ cBytes));
++ pChnl->cBytesMoved += pChirp->cBytes;
++ /* Write all 32 bits of arg */
++ IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
++ (u16)chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
++ (u16)pChnlMgr->uWordSize);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
++ uWordSize);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
++ /* Indicate to the DSP we have written the output: */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ /* Notify client with IO completion record (keep EOS) */
++ pChirp->status &= CHNL_IOCSTATEOS;
++ NotifyChnlComplete(pChnl, pChirp);
++ /* Notify if stream is done. */
++ if (pChirp->status & CHNL_IOCSTATEOS)
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
++
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
++}
++/*
++ * ======== OutputMsg ========
++ * Copies messages from the message queues to the shared memory.
++ */
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs = 0;
++ u32 i;
++ u8 *pMsgOutput;
++ struct MSG_FRAME *pMsg;
++ struct MSG *pCtrl;
++ u32 fOutputEmpty;
++ u32 val;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgOutputCtrl;
++
++ /* Check if output has been cleared */
++ fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ if (fOutputEmpty) {
++ uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
++ hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
++ pMsgOutput = pIOMgr->pMsgOutput;
++ /* Copy uMsgs messages into shared memory */
++ for (i = 0; i < uMsgs; i++) {
++ if (!hMsgMgr->msgUsedList) {
++ DBG_Trace(DBG_LEVEL3, "msgUsedList is NULL\n");
++ pMsg = NULL;
++ goto func_end;
++ } else
++ pMsg = (struct MSG_FRAME *)LST_GetHead(
++ hMsgMgr->msgUsedList);
++ if (pMsg != NULL) {
++ val = (pMsg->msgData).dwId;
++ addr = (u32)&(((struct MSG_DSPMSG *)
++ pMsgOutput)->dwId);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwCmd;
++ addr = (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwCmd);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg1;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg1);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg2;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg2);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ pMsgOutput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->msgFreeList)
++ goto func_end;
++ LST_PutTail(hMsgMgr->msgFreeList,
++ (struct LST_ELEM *) pMsg);
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++ } else {
++ DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
++ }
++ }
++
++ if (uMsgs > 0) {
++ hMsgMgr->uMsgsPending -= uMsgs;
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, (u16)uMsgs);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, uMsgs);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty, false);
++ /* Set the post SWI flag */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ postSWI, true);
++ /* Tell the DSP we have written the output. */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== registerSHMSegs ========
++ * purpose:
++ * Registers GPP SM segment with CMM.
++ */
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 ulShm0_Base = 0;
++ u32 ulShm0_End = 0;
++ u32 ulShm0_RsrvdStart = 0;
++ u32 ulRsrvdSize = 0;
++ u32 ulGppPhys;
++ u32 ulDspVirt;
++ u32 ulShmSegId0 = 0;
++ u32 dwOffset, dwGPPBaseVA, ulDSPSize;
++
++ /* Read address and size info for first SM region.*/
++ /* Get start of 1st SM Heap region */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
++ DBC_Assert(ulShm0_Base != 0);
++ /* Get end of 1st SM Heap region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0_End);
++ DBC_Assert(ulShm0_End != 0);
++ }
++ /* start of Gpp reserved region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
++ &ulShm0_RsrvdStart);
++ DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart 0x%x \n",
++ ulShm0_RsrvdStart);
++ DBC_Assert(ulShm0_RsrvdStart != 0);
++ }
++ /* Register with CMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
++ CMM_ALLSEGMENTS);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
++ "Un-Register SM segments \n");
++ }
++ } else {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
++ "Handle \n");
++ }
++ }
++ /* Register new SM region(s) */
++ if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
++ /* calc size (bytes) of SM the GPP can alloc from */
++ ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulRsrvdSize > 0);
++ /* calc size of SM DSP can alloc from */
++ ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulDSPSize > 0);
++ /* First TLB entry reserved for Bridge SM use.*/
++ ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ /* get size in bytes */
++ ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
++ uWordSize;
++ /* Calc byte offset used to convert GPP phys <-> DSP byte
++ * address.*/
++ if (dwGPPBasePA > ulDspVirt)
++ dwOffset = dwGPPBasePA - ulDspVirt;
++ else
++ dwOffset = ulDspVirt - dwGPPBasePA;
++
++ DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is actually uncached kernel virtual address*/
++ dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
++ - ulDspVirt;
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is the physical address*/
++ dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
++ uWordSize - ulDspVirt;
++ /* Register SM Segment 0.*/
++ status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
++ ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
++ CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
++ (u32)(ulShm0_Base * hIOMgr->uWordSize),
++ ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
++ "Seg 0 \n");
++ }
++ /* first SM region is segId = 1 */
++ DBC_Assert(ulShmSegId0 == 1);
++ }
++ return status;
++}
++
++/*
++ * ======== ReadData ========
++ * Copies buffers from the shared memory to the host buffer.
++ */
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/*
++ * ======== WriteData ========
++ * Copies buffers from the host side buffer to the shared memory.
++ */
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/* ZCPY IO routines. */
++void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
++{
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
++}
++
++/*
++ * ======== IO_SHMcontrol ========
++ * Sets the requested SHM setting.
++ */
++DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 i;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++
++ switch (desc) {
++ case SHM_CURROPP:
++ /* Update the shared memory with requested OPP information */
++ if (pArgs != NULL)
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt =
++ *(u32 *)pArgs;
++ else
++ return DSP_EFAIL;
++ break;
++ case SHM_OPPINFO:
++ /* Update the shared memory with the voltage, frequency,
++ min and max frequency values for an OPP */
++ for (i = 0; i <= dsp_max_opps; i++) {
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
++ vdd1_dsp_freq[i][0];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].voltage);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
++ frequency = vdd1_dsp_freq[i][1];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].frequency);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
++ vdd1_dsp_freq[i][2];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].minFreq);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
++ vdd1_dsp_freq[i][3];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].maxFreq);
++ }
++ hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
++ /* Update the current OPP number */
++ if (pdata->dsp_get_opp)
++ i = (*pdata->dsp_get_opp)();
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
++ DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
++ "%d\n", i);
++ break;
++ case SHM_GETOPP:
++ /* Get the OPP that DSP has requested */
++ *(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ break;
++ default:
++ break;
++
++ queue_work(bridge_workqueue,
++ &(hIOMgr->io_workq));
++ }
++#endif
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_IO_GetProcLoad ========
++ * Gets the Processor's Load information
++ */
++DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat)
++{
++ pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
++ pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
++ pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
++ pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
++
++ DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
++ "Pred Freq = %d\n", pProcStat->uCurrLoad,
++ pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
++ pProcStat->uPredictedFreq);
++ return DSP_SOK;
++}
++
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
++{
++ u32 ulNewMessageLength = 0, ulGPPCurPointer;
++
++ GT_0trace(dsp_trace_mask, GT_ENTER, "Entering PrintDSPDebugTrace\n");
++
++ while (true) {
++ /* Get the DSP current pointer */
++ ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
++ ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
++ hIOMgr->ulDspVa);
++
++ /* No new debug messages available yet */
++ if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
++ break;
++
++ /* Continuous data */
++ else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
++ ulNewMessageLength = ulGPPCurPointer - hIOMgr->
++ ulGPPReadPointer;
++
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ ulNewMessageLength);
++ hIOMgr->pMsg[ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer += ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ /* Handle trace buffer wraparound */
++ else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer);
++ ulNewMessageLength = ulGPPCurPointer -
++ hIOMgr->ulTraceBufferBegin;
++ memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer],
++ (char *)hIOMgr->ulTraceBufferBegin,
++ ulNewMessageLength);
++ hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer +
++ ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
++ ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ }
++}
++#endif
++
++/*
++ * ======== PackTraceBuffer ========
++ * Removes extra nulls from the trace buffer returned from the DSP.
++ * Works even on buffers that already are packed (null removed); but has
++ * one bug in that case -- loses the last character (replaces with '\0').
++ * Continues through conversion for full set of nBytes input characters.
++ * Parameters:
++ * lpBuf: Pointer to input/output buffer
++ * nBytes: Number of characters in the buffer
++ * ulNumWords: Number of DSP words in the buffer. Indicates potential
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * lpBuf must be a fully allocated writable block of at least nBytes.
++ * There are no more than ulNumWords extra characters needed (the number of
++ * linefeeds minus the number of NULLS in the input buffer).
++ */
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *lpTmpBuf;
++ char *lpBufStart;
++ char *lpTmpStart;
++ u32 nCnt;
++ char thisChar;
++
++ /* tmp workspace, 1 KB longer than input buf */
++ lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
++ if (lpTmpBuf == NULL) {
++ DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lpBufStart = lpBuf;
++ lpTmpStart = lpTmpBuf;
++ for (nCnt = nBytes; nCnt > 0; nCnt--) {
++ thisChar = *lpBuf++;
++ switch (thisChar) {
++ case '\0': /* Skip null bytes */
++ break;
++ case '\n': /* Convert \n to \r\n */
++ /* NOTE: do not reverse order; Some OS */
++ /* editors control doesn't understand "\n\r" */
++ *lpTmpBuf++ = '\r';
++ *lpTmpBuf++ = '\n';
++ break;
++ default: /* Copy in the actual ascii byte */
++ *lpTmpBuf++ = thisChar;
++ break;
++ }
++ }
++ *lpTmpBuf = '\0'; /* Make sure tmp buf is null terminated */
++ /* Cut output down to input buf size */
++ strncpy(lpBufStart, lpTmpStart, nBytes);
++ /*Make sure output is null terminated */
++ lpBufStart[nBytes - 1] = '\0';
++ MEM_Free(lpTmpStart);
++ }
++
++ return status;
++}
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++/*
++ * ======== PrintDspTraceBuffer ========
++ * Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * hDehMgr muse be valid. Checked in WMD_DEH_Notify.
++ */
++DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT *hWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++ struct COD_MANAGER *hCodMgr;
++ u32 ulTraceEnd;
++ u32 ulTraceBegin;
++ u32 ulNumBytes = 0;
++ u32 ulNumWords = 0;
++ u32 ulWordSize = 2;
++ CONST u32 uMaxSize = 512;
++ char *pszBuf;
++ u16 *lpszBuf;
++
++ struct WMD_DEV_CONTEXT *pWmdContext = (struct WMD_DEV_CONTEXT *)
++ hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)
++ pWmdContext->hDevObject;
++
++ status = DEV_GetCodMgr(pDevObject, &hCodMgr);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
++ status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
++ ulTraceBegin);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
++ ulTraceEnd);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
++ /* If the chip type is 55 then the addresses will be
++ * byte addresses; convert them to word addresses. */
++ if (ulNumBytes > uMaxSize)
++ ulNumBytes = uMaxSize;
++
++ /* make sure the data we request fits evenly */
++ ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumBytes 0x%x\n", ulNumBytes);
++ ulNumWords = ulNumBytes * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumWords 0x%x\n", ulNumWords);
++ status = DEV_GetIntfFxns(pDevObject, &pIntfFxns);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
++ lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
++ if (pszBuf != NULL) {
++ /* Read bytes from the DSP trace buffer... */
++ status = (*pIntfFxns->pfnBrdRead)(hWmdContext,
++ (u8 *)pszBuf, (u32)ulTraceBegin,
++ ulNumBytes, 0);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "Failed to Read Trace Buffer.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Pack and do newline conversion */
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "before pack and unpack.\n");
++ PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
++ GT_1trace(dsp_trace_mask, GT_1CLASS,
++ "DSP Trace Buffer:\n%s\n", pszBuf);
++ }
++ MEM_Free(pszBuf);
++ MEM_Free(lpszBuf);
++ } else {
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed to "
++ "allocate trace buffer.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++#endif
++ return status;
++}
++
++void IO_SM_init(void)
++{
++
++ GT_create(&dsp_trace_mask, "DT"); /* DSP Trace Mask */
++
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
+new file mode 100644
+index 0000000..5585cdb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.c
+@@ -0,0 +1,172 @@
++/*
++ * mmu_fault.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== mmu_fault.c ========
++ * Description:
++ * Implements DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: Support for IVA MMU exception.
++ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
++ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
++ *! 05-Jan-2004 vp: Updated support for 24xx silicon
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/host_os.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "_deh.h"
++#include <dspbridge/cfg.h>
++#include "_tiomap_mmu.h"
++#include "_tiomap.h"
++#include "mmu_fault.h"
++
++static u32 dmmuEventMask;
++u32 faultAddr;
++
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++void MMU_FaultDpc(IN void *pRefData)
++{
++ struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
++
++ if (pDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
++}
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
++ DBC_Require(irq == INT_DSP_MMU_IRQ);
++ DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources "
++ "in MMU ISR **\n");
++ if (MMU_CheckIfFault(pDevContext)) {
++ printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
++ "0x%x\n", dmmuEventMask);
++ printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
++ "0x%x\n", faultAddr);
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ /*
++ * Schedule a DPC directly. In the future, it may be
++ * necessary to check if DSP MMU fault is intended for
++ * Bridge.
++ */
++ DPC_Schedule(pDehMgr->hMmuFaultDpc);
++ /* Reset errInfo structure before use. */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
++ pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "***** MMU FAULT ***** faultcode 0x%x\n",
++ dmmuEventMask);
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * ======== MMU_CheckIfFault ========
++ * Check to see if MMU Fault is valid TLB miss from DSP
++ * Note: This function is called from an ISR
++ */
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
++{
++
++
++ bool retVal = false;
++ DSP_STATUS status = DSP_SOK;
++ HW_STATUS hwStatus;
++ struct CFG_HOSTRES resources;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
++ "MMU_CheckIfFault **\n");
++
++ hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
++ if (dmmuEventMask == HW_MMU_TRANSLATION_FAULT) {
++ HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
++ DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", faultAddr);
++ retVal = true;
++ }
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
+new file mode 100644
+index 0000000..be59333
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.h
+@@ -0,0 +1,45 @@
++/*
++ * mmu_fault.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mmu_fault.h ========
++ * Description:
++ * Defines DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: IVA MMU handlers.
++ *! 10-Sep-2001 kc: created.
++ */
++
++#ifndef MMU_FAULT_
++#define MMU_FAULT_
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++ void MMU_FaultDpc(IN void *pRefData);
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData);
++
++#endif /* MMU_FAULT_ */
++
+diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
+new file mode 100644
+index 0000000..b9b2bec
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/msg_sm.c
+@@ -0,0 +1,643 @@
++/*
++ * msg_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD message module.
++ *
++ * Public Functions:
++ * WMD_MSG_Create
++ * WMD_MSG_CreateQueue
++ * WMD_MSG_Delete
++ * WMD_MSG_DeleteQueue
++ * WMD_MSG_Get
++ * WMD_MSG_Put
++ * WMD_MSG_RegisterNotify
++ * WMD_MSG_SetQueueId
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Jul-2002 jeh Release critical section in WMD_MSG_Put() before
++ *! scheduling DPC.
++ *! 09-May-2001 jeh Free MSG queue NTFY object, remove unnecessary set/
++ *! reset of events.
++ *! 10-Jan-2001 jeh Set/Reset message manager and message queue events
++ *! correctly.
++ *! 04-Dec-2000 jeh Bug fixes.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- This */
++#include <_msg_sm.h>
++#include <dspbridge/wmdmsg.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MSGQ_SIGNATURE 0x5147534d /* "QGSM" */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
++static void FreeMsgList(struct LST_LIST *msgList);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct MSG_MGR *pMsgMgr;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++ DEV_GetIOMgr(hDevObject, &hIOMgr);
++ DBC_Assert(hIOMgr != NULL);
++ *phMsgMgr = NULL;
++ /* Allocate MSG manager object */
++ MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
++
++ if (pMsgMgr) {
++ pMsgMgr->onExit = msgCallback;
++ pMsgMgr->hIOMgr = hIOMgr;
++ /* List of MSG_QUEUEs */
++ pMsgMgr->queueList = LST_Create();
++ /* Queues of message frames for messages to the DSP. Message
++ * frames will only be added to the free queue when a
++ * MSG_QUEUE object is created. */
++ pMsgMgr->msgFreeList = LST_Create();
++ pMsgMgr->msgUsedList = LST_Create();
++ if (pMsgMgr->queueList == NULL ||
++ pMsgMgr->msgFreeList == NULL ||
++ pMsgMgr->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
++
++ /* Create an event to be used by WMD_MSG_Put() in waiting
++ * for an available free frame from the message manager. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ *phMsgMgr = pMsgMgr;
++ else
++ DeleteMsgMgr(pMsgMgr);
++
++ } else {
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Create a MSG_QUEUE for sending/receiving messages to/from a node
++ * on the DSP.
++ */
++DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE hArg)
++{
++ u32 i;
++ u32 uNumAllocated = 0;
++ struct MSG_QUEUE *pMsgQ;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ DBC_Require(phMsgQueue != NULL);
++
++ *phMsgQueue = NULL;
++ /* Allocate MSG_QUEUE object */
++ MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
++ if (!pMsgQ) {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ LST_InitElem((struct LST_ELEM *) pMsgQ);
++ pMsgQ->uMaxMsgs = uMaxMsgs;
++ pMsgQ->hMsgMgr = hMsgMgr;
++ pMsgQ->hArg = hArg; /* Node handle */
++ pMsgQ->dwId = dwId; /* Node env (not valid yet) */
++ /* Queues of Message frames for messages from the DSP */
++ pMsgQ->msgFreeList = LST_Create();
++ pMsgQ->msgUsedList = LST_Create();
++ if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++
++ /* Create event that will be signalled when a message from
++ * the DSP is available. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
++
++ /* Create a notification list for message ready notification. */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pMsgQ->hNtfy);
++
++ /* Create events that will be used to synchronize cleanup
++ * when the object is deleted. hSyncDone will be set to
++ * unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
++ * will be set by the unblocked thread to signal that it
++ * is unblocked and will no longer reference the object. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* Initialize message frames and put in appropriate queues */
++ for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
++ status = AddNewMsg(hMsgMgr->msgFreeList);
++ if (DSP_SUCCEEDED(status)) {
++ uNumAllocated++;
++ status = AddNewMsg(pMsgQ->msgFreeList);
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Stay inside CS to prevent others from taking any
++ * of the newly allocated message frames. */
++ DeleteMsgQueue(pMsgQ, uNumAllocated);
++ } else {
++ LST_PutTail(hMsgMgr->queueList,
++ (struct LST_ELEM *)pMsgQ);
++ *phMsgQueue = pMsgQ;
++ /* Signal that free frames are now available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ } else {
++ DeleteMsgQueue(pMsgQ, 0);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ */
++void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ DeleteMsgMgr(hMsgMgr);
++}
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ */
++void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
++{
++ struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
++ u32 refCount;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ hMsgQueue->fDone = true;
++ /* Unblock all threads blocked in MSG_Get() or MSG_Put(). */
++ refCount = hMsgQueue->refCount;
++ while (refCount) {
++ /* Unblock thread */
++ SYNC_SetEvent(hMsgQueue->hSyncDone);
++ /* Wait for acknowledgement */
++ SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
++ refCount = hMsgQueue->refCount;
++ }
++ /* Remove message queue from hMsgMgr->queueList */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
++ /* Free the message queue object */
++ DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
++ if (!hMsgMgr->msgFreeList)
++ goto func_cont;
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++}
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Get a message from a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fGotMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++ if (!hMsgQueue->msgUsedList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* If a message is already there, get it */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
++ msgUsedList);
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ if (LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_ResetEvent(hMsgQueue->hSyncEvent);
++
++ fGotMsg = true;
++ }
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ if (DSP_SUCCEEDED(status) && !fGotMsg) {
++ /* Wait til message is available, timeout, or done. We don't
++ * have to schedule the DPC, since the DSP will send messages
++ * when they are available. */
++ hSyncs[0] = hMsgQueue->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(!LST_IsEmpty(hMsgQueue->
++ msgUsedList));
++ /* Get msg from used list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgQueue->msgUsedList);
++ /* Copy message into pMsg and put frame on the
++ * free list */
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset the event if there are still queued messages */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_SetEvent(hMsgQueue->hSyncEvent);
++
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Put a message onto a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fPutMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++
++ (void) SYNC_EnterCS(hMsgMgr->hSyncCS);
++
++ /* If a message frame is available, use it */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId = hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ fPutMsg = true;
++ }
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++
++ /* Release critical section before scheduling DPC */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ if (DSP_SUCCEEDED(status) && !fPutMsg) {
++ /* Wait til a free message frame is available, timeout,
++ * or done */
++ hSyncs[0] = hMsgMgr->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ status = DSP_EPOINTER;
++ goto func_cont;
++ }
++ /* Get msg from free list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgMgr->msgFreeList);
++ /* Copy message into pMsg and put frame on the
++ * used list */
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId =
++ hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList,
++ (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ /* Schedule a DPC, to do the actual
++ * data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset event if there are still frames available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ */
++DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(hNotification != NULL);
++ DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
++ DBC_Require(uNotifyType == DSP_SIGNALEVENT);
++
++ status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ if (status == DSP_EVALUE) {
++ /* Not registered. Ok, since we couldn't have known. Node
++ * notifications are split between node state change handled
++ * by NODE, and message ready handled by MSG. */
++ status = DSP_SOK;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ */
++void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ /* DBC_Require(dwId != 0); */
++
++ /*
++ * A message queue must be created when a node is allocated,
++ * so that NODE_RegisterNotify() can be called before the node
++ * is created. Since we don't know the node environment until the
++ * node is created, we need this function to set hMsgQueue->dwId
++ * to the node environment, after the node is created.
++ */
++ hMsgQueue->dwId = dwId;
++}
++
++/*
++ * ======== AddNewMsg ========
++ * Must be called in message manager critical section.
++ */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++ DSP_STATUS status = DSP_SOK;
++
++ pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
++ MEM_PAGED);
++ if (pMsg != NULL) {
++ LST_InitElem((struct LST_ELEM *) pMsg);
++ LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteMsgMgr ========
++ */
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ if (hMsgMgr->queueList) {
++ if (LST_IsEmpty(hMsgMgr->queueList)) {
++ LST_Delete(hMsgMgr->queueList);
++ hMsgMgr->queueList = NULL;
++ }
++ }
++
++ if (hMsgMgr->msgFreeList) {
++ FreeMsgList(hMsgMgr->msgFreeList);
++ hMsgMgr->msgFreeList = NULL;
++ }
++
++ if (hMsgMgr->msgUsedList) {
++ FreeMsgList(hMsgMgr->msgUsedList);
++ hMsgMgr->msgUsedList = NULL;
++ }
++
++ if (hMsgMgr->hSyncEvent)
++ SYNC_CloseEvent(hMsgMgr->hSyncEvent);
++
++ if (hMsgMgr->hSyncCS)
++ SYNC_DeleteCS(hMsgMgr->hSyncCS);
++
++ MEM_FreeObject(hMsgMgr);
++}
++
++/*
++ * ======== DeleteMsgQueue ========
++ */
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
++{
++ struct MSG_MGR *hMsgMgr;
++ struct MSG_FRAME *pMsg;
++ u32 i;
++
++ if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE)
++ || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList)
++ goto func_end;
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++
++ /* Pull off uNumToDSP message frames from Msg manager and free */
++ for (i = 0; i < uNumToDSP; i++) {
++
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ MEM_Free(pMsg);
++ } else {
++ /* Cannot free all of the message frames */
++ break;
++ }
++ }
++
++ if (hMsgQueue->msgFreeList) {
++ FreeMsgList(hMsgQueue->msgFreeList);
++ hMsgQueue->msgFreeList = NULL;
++ }
++
++ if (hMsgQueue->msgUsedList) {
++ FreeMsgList(hMsgQueue->msgUsedList);
++ hMsgQueue->msgUsedList = NULL;
++ }
++
++
++ if (hMsgQueue->hNtfy)
++ NTFY_Delete(hMsgQueue->hNtfy);
++
++ if (hMsgQueue->hSyncEvent)
++ SYNC_CloseEvent(hMsgQueue->hSyncEvent);
++
++ if (hMsgQueue->hSyncDone)
++ SYNC_CloseEvent(hMsgQueue->hSyncDone);
++
++ if (hMsgQueue->hSyncDoneAck)
++ SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
++
++ MEM_FreeObject(hMsgQueue);
++func_end:
++ return;
++
++}
++
++/*
++ * ======== FreeMsgList ========
++ */
++static void FreeMsgList(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++
++ if (!msgList)
++ goto func_end;
++
++ while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
++ MEM_Free(pMsg);
++
++ DBC_Assert(LST_IsEmpty(msgList));
++
++ LST_Delete(msgList);
++func_end:
++ return;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
+new file mode 100644
+index 0000000..2ab585d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430.c
+@@ -0,0 +1,2149 @@
++/*
++ * tiomap.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== tiomap.c ========
++ * Processor Manager Driver for TI OMAP3430 EVM.
++ *
++ * Public Function:
++ * WMD_DRV_Entry
++ *
++ *! Revision History:
++ *! ================
++ * 26-March-2008 HK and AL: Added WMD_DEV_WalkTbl funciton.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <mach-omap2/prm.h>
++#include <mach-omap2/cm.h>
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++#include <mach/control.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++#include <hw_mbox.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdmsg.h>
++#include <dspbridge/pwr.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Local */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_util.h"
++#include "tiomap_io.h"
++
++
++/* Offset in shared mem to write to in order to synchronize start with DSP */
++#define SHMSYNCOFFSET 4 /* GPP byte offset */
++
++#define BUFFERSIZE 1024
++
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++#define PAGES_II_LVL_TABLE 512
++#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
++
++#define MMU_GFLUSH 0x60
++
++/* Forward Declarations: */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dwDSPAddr);
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT BRD_STATUS *pdwState);
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState);
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttr);
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes);
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig);
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs);
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
++static u32 user_va2pa(struct mm_struct *mm, u32 address);
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs);
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);
++static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,
++ u32 sysctrl_base);
++void GetHWRegs(u32 prcm_base, u32 cm_base);
++
++/* ----------------------------------- Globals */
++
++/* Attributes of L2 page tables for DSP MMU */
++struct PageInfo {
++ u32 numEntries; /* Number of valid PTEs in the L2 PT */
++} ;
++
++/* Attributes used to manage the DSP MMU page tables */
++struct PgTableAttrs {
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++
++ u32 L1BasePa; /* Physical address of the L1 PT */
++ u32 L1BaseVa; /* Virtual address of the L1 PT */
++ u32 L1size; /* Size of the L1 PT */
++ u32 L1TblAllocPa;
++ /* Physical address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocVa;
++ /* Virtual address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocSz;
++ /* Size of consistent memory allocated for L1 table.
++ * May not be aligned */
++
++ u32 L2BasePa; /* Physical address of the L2 PT */
++ u32 L2BaseVa; /* Virtual address of the L2 PT */
++ u32 L2size; /* Size of the L2 PT */
++ u32 L2TblAllocPa;
++ /* Physical address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocVa;
++ /* Virtual address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocSz;
++ /* Size of consistent memory allocated for L2 table.
++ * May not be aligned */
++
++ u32 L2NumPages; /* Number of allocated L2 PT */
++ struct PageInfo *pgInfo; /* Array [L2NumPages] of L2 PT info structs */
++} ;
++
++/*
++ * If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
++ * to boot
++ */
++extern s32 dsp_debug;
++
++
++/*
++ * This mini driver's function interface table.
++ */
++static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
++ WCD_MAJOR_VERSION, /* WCD ver. for which this mini driver is built. */
++ WCD_MINOR_VERSION,
++ WMD_DEV_Create,
++ WMD_DEV_Destroy,
++ WMD_DEV_Ctrl,
++ WMD_BRD_Monitor,
++ WMD_BRD_Start,
++ WMD_BRD_Stop,
++ WMD_BRD_Status,
++ WMD_BRD_Read,
++ WMD_BRD_Write,
++ WMD_BRD_SetState,
++ WMD_BRD_MemCopy,
++ WMD_BRD_MemWrite,
++ WMD_BRD_MemMap,
++ WMD_BRD_MemUnMap,
++ /* The following CHNL functions are provided by chnl_io.lib: */
++ WMD_CHNL_Create,
++ WMD_CHNL_Destroy,
++ WMD_CHNL_Open,
++ WMD_CHNL_Close,
++ WMD_CHNL_AddIOReq,
++ WMD_CHNL_GetIOC,
++ WMD_CHNL_CancelIO,
++ WMD_CHNL_FlushIO,
++ WMD_CHNL_GetInfo,
++ WMD_CHNL_GetMgrInfo,
++ WMD_CHNL_Idle,
++ WMD_CHNL_RegisterNotify,
++ /* The following DEH functions are provided by tihelen_ue_deh.c */
++ WMD_DEH_Create,
++ WMD_DEH_Destroy,
++ WMD_DEH_Notify,
++ WMD_DEH_RegisterNotify,
++ WMD_DEH_GetInfo,
++ /* The following IO functions are provided by chnl_io.lib: */
++ WMD_IO_Create,
++ WMD_IO_Destroy,
++ WMD_IO_OnLoaded,
++ WMD_IO_GetProcLoad,
++ /* The following MSG functions are provided by chnl_io.lib: */
++ WMD_MSG_Create,
++ WMD_MSG_CreateQueue,
++ WMD_MSG_Delete,
++ WMD_MSG_DeleteQueue,
++ WMD_MSG_Get,
++ WMD_MSG_Put,
++ WMD_MSG_RegisterNotify,
++ WMD_MSG_SetQueueId,
++};
++
++static inline void tlb_flush_all(const u32 base)
++{
++ __raw_writeb(__raw_readb(base + MMU_GFLUSH) | 1, base + MMU_GFLUSH);
++}
++
++static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++ u32 temp = 0;
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++
++ if ((temp & HW_PWR_STATE_ON) == HW_PWR_STATE_OFF ||
++ (temp & HW_PWR_STATE_ON) == HW_PWR_STATE_RET) {
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ WakeDSP(pDevContext, NULL);
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ } else
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++}
++
++static void bad_page_dump(u32 pa, struct page *pg)
++{
++ pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
++ pr_emerg("Bad page state in process '%s'\n"
++ "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
++ "Backtrace:\n",
++ current->comm, pg, (int)(2*sizeof(unsigned long)),
++ (unsigned long)pg->flags, pg->mapping,
++ page_mapcount(pg), page_count(pg));
++ BUG();
++}
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * purpose:
++ * Mini Driver entry point.
++ */
++void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName)
++{
++
++ DBC_Require(pstrWMDFileName != NULL);
++ DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
++
++ IO_SM_init(); /* Initialization of io_sm module */
++
++ if (strcmp(pstrWMDFileName, "UMA") == 0)
++ *ppDrvInterface = &drvInterfaceFxns;
++ else
++ DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
++
++}
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * purpose:
++ * This WMD_BRD_Monitor puts DSP into a Loadable state.
++ * i.e Application can load and start the device.
++ *
++ * Preconditions:
++ * Device in 'OFF' state.
++ */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ enum HW_PwrState_t pwrState;
++
++ DBG_Trace(DBG_ENTER, "Board in the monitor state \n");
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ goto error_return;
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Read and set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Disable Automatic transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ status = run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the device state to IDLE */
++ pDevContext->dwBrdState = BRD_IDLE;
++
++ }
++error_return:
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Read ========
++ * purpose:
++ * Reads buffers for DSP memory.
++ */
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
++ " 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Read: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ /* change here to account for the 3 bands of the DSP internal memory */
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
++ } else {
++ DBG_Trace(DBG_LEVEL1,
++ "**** Reading From external memory **** \n ");
++ status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ return status;
++ }
++ /* copy the data from DSP memory, */
++ memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_SetState ========
++ * purpose:
++ * This routine updates the Board status.
++ */
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
++ ulBrdState);
++ pDevContext->dwBrdState = ulBrdState;
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Start ========
++ * purpose:
++ * Initializes DSP MMU and Starts DSP.
++ *
++ * Preconditions:
++ * a) DSP domain is 'ACTIVE'.
++ * b) DSP_RST1 is asserted.
++ * b) DSP_RST2 is released.
++ */
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 dwSyncAddr = 0;
++ u32 ulShmBase; /* Gpp Phys SM base addr(byte) */
++ u32 ulShmBaseVirt; /* Dsp Virt SM base addr */
++ u32 ulTLBBaseVirt; /* Base of MMU TLB entry */
++ u32 ulShmOffsetVirt; /* offset of ulShmBaseVirt from ulTLBBaseVirt */
++ s32 iEntryNdx;
++ s32 itmpEntryNdx = 0; /* DSP-MMU TLB entry base address */
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ u32 ulDspClkRate;
++ u32 ulDspClkAddr;
++ u32 ulBiosGpTimer;
++ u32 uClkCmd;
++ struct IO_MGR *hIOMgr;
++ u32 ulLoadMonitorTimer;
++ u32 extClkId = 0;
++ u32 tmpIndex;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
++ "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
++
++ /* The device context contains all the mmu setup info from when the
++ * last dsp base image was loaded. The first entry is always
++ * SHMMEM base. */
++ /* Get SHM_BEG - convert to byte address */
++ (void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
++ &ulShmBaseVirt);
++ ulShmBaseVirt *= DSPWORDSIZE;
++ DBC_Assert(ulShmBaseVirt != 0);
++ /* DSP Virtual address */
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
++ /* Kernel logical address */
++ ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
++
++ DBC_Assert(ulShmBase != 0);
++ /* 2nd wd is used as sync field */
++ dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
++ /* Write a signature into the SHM base + offset; this will
++ * get cleared when the DSP program starts. */
++ if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
++ status = DSP_EFAIL;
++ } else
++ *((volatile u32 *)dwSyncAddr) = 0xffffffff;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ /* Assert RST1 i.e only the RST only for DSP megacell */
++ /* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
++ if (dsp_debug) {
++ /* Set the bootmode to self loop */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to self loop"
++ " for IVA2 Device\n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
++ } else {
++ /* Set the bootmode to '0' - direct boot */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to direct"
++ " boot for IVA2 Device \n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Reset and Unreset the RST2, so that BOOTADDR is copied to
++ * IVA2 SYSC register */
++ HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ /* Disbale the DSP MMU */
++ HW_MMU_Disable(resources.dwDmmuBase);
++ /* Disable TWL */
++ HW_MMU_TWLDisable(resources.dwDmmuBase);
++
++ /* Only make TLB entry if both addresses are non-zero */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
++ iEntryNdx++) {
++ if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
++ (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
++ DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
++ " 0x%x DspVa 0x%x Size 0x%x\n",
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize);
++ configureDspMmu(pDevContext,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
++ DSPWORDSIZE,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize,
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].endianism,
++ pDevContext->aTLBEntry[iEntryNdx].elemSize,
++ pDevContext->aTLBEntry[iEntryNdx].
++ mixedMode);
++ itmpEntryNdx++;
++ }
++ } /* end for */
++ }
++
++ /* Lock the above TLB entries and get the BIOS and load monitor timer
++ * information*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_TTBSet(resources.dwDmmuBase,
++ pDevContext->pPtAttrs->L1BasePa);
++ HW_MMU_TWLEnable(resources.dwDmmuBase);
++ /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
++
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwDmmuBase) + 0x10));
++ temp = (temp & 0xFFFFFFEF) | 0x11;
++ *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)) =
++ (u32) temp;
++
++ /* Let the DSP MMU run */
++ HW_MMU_Enable(resources.dwDmmuBase);
++
++ /* Enable the BIOS clock */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_BIOSGPTIMER,
++ &ulBiosGpTimer);
++ DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_LOADMON_GPTIMER,
++ &ulLoadMonitorTimer);
++ DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
++ ulLoadMonitorTimer);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulLoadMonitorTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Disable: 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, " Error while setting"
++ "LM Timer to 32KHz\n");
++ }
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Enable : 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for Load "
++ "Monitor Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulBiosGpTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
++ "Disable: 0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ " Error while setting BIOS Timer to 32KHz\n");
++ }
++
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
++ "0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for BIOS Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the DSP clock rate */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ "_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
++ /*Set Autoidle Mode for IVA2 PLL */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
++ "0x%x \n", ulDspClkAddr);
++ if ((unsigned int *)ulDspClkAddr != NULL) {
++ /* Get the clock rate */
++ status = CLK_GetRate(SERVICESCLK_iva2_ck,
++ &ulDspClkRate);
++ DBG_Trace(DBG_LEVEL5,
++ "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
++ ulDspClkRate);
++ (void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
++ ulDspClkAddr, sizeof(u32), 0);
++ }
++/*PM_IVA2GRPSEL_PER = 0xC0;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ temp = (temp & 0xFFFFFF30) | 0xC0;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8)) =
++ (u32) temp;
++
++/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ temp = (temp & 0xFFFFFF3F);
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4)) =
++ (u32) temp;
++/*CM_SLEEPDEP_PER |= 0x04;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerBase) + 0x44));
++ temp = (temp & 0xFFFFFFFB) | 0x04;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerBase) + 0x44)) =
++ (u32) temp;
++
++/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x48));
++ temp = (temp & 0xFFFFFFFC) | 0x03;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x48)) =
++ (u32) temp;
++
++
++ /* Enable Mailbox events and also drain any pending
++ * stale messages */
++ (void)CHNLSM_EnableInterrupt(pDevContext);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
++ temp);
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
++ temp);
++
++ /* Let DSP go */
++ DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
++ /* Enable DSP MMU Interrupts */
++ HW_MMU_EventEnable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ /* release the RST1, DSP starts executing now .. */
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
++
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
++ temp);
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
++ temp);
++ DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
++ dwSyncAddr);
++ DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address = 0x%x \n",
++ dwDSPAddr);
++ if (dsp_debug)
++ while (*((volatile u16 *)dwSyncAddr))
++ ;;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait for DSP to clear word in shared memory */
++ /* Read the Location */
++ if (!WaitForStart(pDevContext, dwSyncAddr)) {
++ status = WMD_E_TIMEOUT;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start Failed to Synchronize\n");
++ }
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_SUCCEEDED(status)) {
++ IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start: OPP information initialzed\n");
++ /* Write the synchronization bit to indicate the
++ * completion of OPP table update to DSP
++ */
++ *((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* update board state */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ /* (void)CHNLSM_EnableInterrupt(pDevContext);*/
++ DBG_Trace(DBG_LEVEL7, "Device Started \n ");
++ } else {
++ pDevContext->dwBrdState = BRD_UNKNOWN;
++ DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * purpose:
++ * Puts DSP in self loop.
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 dspPwrState;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void)CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
++ * before turning off the clocks.. This is to ensure that there are no
++ * pending L3 or other transactons from IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
++ return DSP_EFAIL;
++ }
++
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
++ if (dspPwrState != HW_PWR_STATE_OFF) {
++
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
++
++ mdelay(10);
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++
++ run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++
++ udelay(50);
++
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: CLK_Disable failed "
++ "for iva2_fck\n");
++ }
++ /* IVA2 is not in OFF state */
++ /* Set PM_PWSTCTRL_IVA2 to OFF */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_OFF);
++ /* Set the SW supervised state transition for Sleep */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_SLEEP);
++ } else {
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
++ " for iva2_fck\n");
++ }
++ }
++ udelay(10);
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *) pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Delete ========
++ * purpose:
++ * Puts DSP in Low power mode
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void) CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive
++ * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
++ * to ensure that there are no pending L3 or other transactons from
++ * IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
++ return DSP_EFAIL;
++ }
++ status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
++ " iva2_fck\n");
++ }
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *)pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Returns the board status.
++ */
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS *pdwState)
++{
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ *pdwState = pDevContext->dwBrdState;
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Copies the buffers to DSP internal or external memory.
++ */
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
++ "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
++ "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Write: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType, false);
++ }
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy : DspLogicAddr=0x%x \n",
++ pDevContext->dwDspBaseAddr);
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Creates a driver object. Puts DSP in self loop.
++ */
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = NULL;
++ s32 iEntryNdx;
++ s32 tcWordSwap;
++ u32 tcWordSwapSize = sizeof(tcWordSwap);
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 pg_tbl_pa;
++ u32 pg_tbl_va;
++ u32 align_size;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
++ "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
++ ppDevContext, hDevObject, pConfig, pDspConfig);
++ /* Allocate and initialize a data structure to contain the mini driver
++ * state, which becomes the context for later calls into this WMD. */
++ pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
++ if (!pDevContext) {
++ DBG_Trace(DBG_ENTER, "Failed to allocate mem \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_ENTER, "Failed to get host resources \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++
++ pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
++ pDevContext->dwSelfLoop = (u32)NULL;
++ pDevContext->uDspPerClks = 0;
++ pDevContext->dwInternalSize = OMAP_DSP_SIZE;
++ /* Clear dev context MMU table entries.
++ * These get set on WMD_BRD_IOCTL() call after program loaded. */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
++ }
++ pDevContext->numTLBEntries = 0;
++ pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
++ (pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
++ if (!pDevContext->dwDspBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create: failed to Map the API memory\n");
++ }
++ pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
++ if (pPtAttrs != NULL) {
++ /* Assuming that we use only DSP's memory map
++ * until 0x4000:0000 , we would need only 1024
++ * L1 enties i.e L1 size = 4K */
++ pPtAttrs->L1size = 0x1000;
++ align_size = pPtAttrs->L1size;
++ /* Align sizes are expected to be power of 2 */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
++ align_size, &pg_tbl_pa);
++ /* Check if the PA is aligned for us */
++ if ((pg_tbl_pa) & (align_size-1)) {
++ /* PA not aligned to page table size ,
++ * try with more allocation and align */
++ MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa, pPtAttrs->L1size);
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
++ align_size, &pg_tbl_pa);
++ /* We should be able to get aligned table now */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
++ /* Align the PA to the next 'align' boundary */
++ pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
++ (~(align_size-1));
++ pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
++ pg_tbl_pa);
++ } else {
++ /* We got aligned PA, cool */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
++ pPtAttrs->L1BasePa = pg_tbl_pa;
++ pPtAttrs->L1BaseVa = pg_tbl_va;
++ }
++ if (pPtAttrs->L1BaseVa)
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++
++ /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
++ * L4 pages */
++ pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
++ pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
++ pPtAttrs->L2NumPages;
++ align_size = 4; /* Make it u32 aligned */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
++ align_size, &pg_tbl_pa);
++ pPtAttrs->L2TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L2TblAllocVa = pg_tbl_va;
++ pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
++ pPtAttrs->L2BasePa = pg_tbl_pa;
++ pPtAttrs->L2BaseVa = pg_tbl_va;
++
++ if (pPtAttrs->L2BaseVa)
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++
++ pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
++ sizeof(struct PageInfo), MEM_NONPAGED);
++ DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
++ "%x, size %x\n", pPtAttrs->L1BasePa,
++ pPtAttrs->L1BaseVa, pPtAttrs->L1size,
++ pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
++ pPtAttrs->L2size);
++ DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
++ pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
++ }
++ if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
++ (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
++ pDevContext->pPtAttrs = pPtAttrs;
++ else
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Endianism Register */ /* Need to set this */
++ /* Retrieve the TC u16 SWAP Option */
++ status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
++ (u8 *)&tcWordSwap, &tcWordSwapSize);
++ /* Save the value */
++ pDevContext->tcWordSwapOn = tcWordSwap;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Clock Divisor for the DSP module */
++ DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
++ "enable the clock \n");
++ status = CLK_Enable(SERVICESCLK_mailbox_ick);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_create:Reset mail box and "
++ "enable the clock Fail\n");
++ }
++ udelay(5);
++ /* 24xx-Linux MMU address is obtained from the host
++ * resources struct */
++ pDevContext->dwDSPMmuBase = resources.dwDmmuBase;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDevContext->hDevObject = hDevObject;
++ pDevContext->ulIntMask = 0;
++ /* Store current board state. */
++ pDevContext->dwBrdState = BRD_STOPPED;
++ /* Return this ptr to our device state to the WCD for storage:*/
++ *ppDevContext = pDevContext;
++ DBG_Trace(DBG_ENTER, "Device Created \n");
++ } else {
++ if (pPtAttrs != NULL) {
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa,
++ pPtAttrs->L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa,
++ pPtAttrs->L1TblAllocSz);
++ }
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ if (pDevContext)
++ MEM_Free(pDevContext);
++
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create Error Device not created\n");
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Receives device specific commands.
++ */
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
++ s32 ndx;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext: 0x%x\n\t\t dwCmd: "
++ "0x%x\n\t\tpArgs: 0x%x\n", pDevContext, dwCmd, pArgs);
++ switch (dwCmd) {
++ case WMDIOCTL_CHNLREAD:
++ break;
++ case WMDIOCTL_CHNLWRITE:
++ break;
++ case WMDIOCTL_SETMMUCONFIG:
++ /* store away dsp-mmu setup values for later use */
++ for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
++ pDevContext->aTLBEntry[ndx] = *paExtProc;
++
++ break;
++ case WMDIOCTL_DEEPSLEEP:
++ case WMDIOCTL_EMERGENCYSLEEP:
++ /* Currently only DSP Idle is supported Need to update for
++ * later releases */
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
++ status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
++ break;
++ case WMDIOCTL_WAKEUP:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
++ status = WakeDSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CLK_CTRL:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
++ status = DSP_SOK;
++ /* Looking For Baseport Fix for Clocks */
++ status = DSPPeripheralClkCtrl(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_PWR_HIBERNATE:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
++ status = handle_hibernation_fromDSP(pDevContext);
++ break;
++ case WMDIOCTL_PRESCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
++ status = PreScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_POSTSCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
++ status = PostScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CONSTRAINT_REQUEST:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
++ status = handle_constraints_set(pDevContext, pArgs);
++ break;
++ default:
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
++ break;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Destroys the driver object.
++ */
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
++ hDevContext;
++ DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
++ hDevContext);
++ /* first put the device to stop state */
++ WMD_BRD_Delete(pDevContext);
++ if (pDevContext && pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa, pPtAttrs->
++ L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa, pPtAttrs->
++ L1TblAllocSz);
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ }
++ /* Free the driver's device context: */
++ MEM_Free((void *) hDevContext);
++ return status;
++}
++
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 srcAddr = ulDspSrcAddr;
++ u32 destAddr = ulDspDestAddr;
++ u32 copyBytes = 0;
++ u32 totalBytes = ulNumBytes;
++ u8 hostBuf[BUFFERSIZE];
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
++ copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
++ /* Read from External memory */
++ status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
++ copyBytes, ulMemType);
++ if (DSP_SUCCEEDED(status)) {
++ if (destAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ /* Write to Internal memory */
++ status = WriteDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType);
++ } else {
++ /* Write to External memory */
++ status = WriteExtDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType, false);
++ }
++ }
++ totalBytes -= copyBytes;
++ srcAddr += copyBytes;
++ destAddr += copyBytes;
++ }
++ return status;
++}
++
++/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 ulRemainBytes = 0;
++ u32 ulBytes = 0;
++ ulRemainBytes = ulNumBytes;
++ while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
++ ulBytes =
++ ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
++ if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(hDevContext, pbHostBuf,
++ dwDSPAddr, ulBytes, ulMemType, true);
++ }
++ ulRemainBytes -= ulBytes;
++ dwDSPAddr += ulBytes;
++ pbHostBuf = pbHostBuf + ulBytes;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * This function maps MPU buffer to the DSP address space. It performs
++ * linear to physical address translation if required. It translates each
++ * page since linear addresses can be physically non-contiguous
++ * All address & size arguments are assumed to be page aligned (in proc.c)
++ *
++ * TODO: Disable MMU while updating the page tables (but that'll stall DSP)
++ */
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, u32 ulMapAttr)
++{
++ u32 attrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct HW_MMUMapAttrs_t hwAttrs;
++ struct vm_area_struct *vma;
++ struct mm_struct *mm = current->mm;
++ u32 write = 0;
++ u32 numUsrPgs = 0;
++ struct page *mappedPage, *pg;
++ s32 pgNum;
++ u32 va = ulVirtAddr;
++ struct task_struct *curr_task = current;
++ u32 pgI = 0;
++ u32 mpuAddr, pa;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
++ "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, ulMapAttr);
++ if (ulNumBytes == 0)
++ return DSP_EINVALIDARG;
++
++ if (ulMapAttr != 0) {
++ attrs = ulMapAttr;
++ } else {
++ /* Assign default attributes */
++ attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
++ }
++ /* Take mapping properties */
++ if (attrs & DSP_MAPBIGENDIAN)
++ hwAttrs.endianism = HW_BIG_ENDIAN;
++ else
++ hwAttrs.endianism = HW_LITTLE_ENDIAN;
++
++ hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
++ ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
++ /* Ignore elementSize if mixedSize is enabled */
++ if (hwAttrs.mixedSize == 0) {
++ if (attrs & DSP_MAPELEMSIZE8) {
++ /* Size is 8 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
++ } else if (attrs & DSP_MAPELEMSIZE16) {
++ /* Size is 16 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
++ } else if (attrs & DSP_MAPELEMSIZE32) {
++ /* Size is 32 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
++ } else if (attrs & DSP_MAPELEMSIZE64) {
++ /* Size is 64 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
++ } else {
++ /*
++ * Mixedsize isn't enabled, so size can't be
++ * zero here
++ */
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: MMU element size is zero\n");
++ return DSP_EINVALIDARG;
++ }
++ }
++ if (attrs & DSP_MAPDONOTLOCK)
++ hwAttrs.donotlockmpupage = 1;
++ else
++ hwAttrs.donotlockmpupage = 0;
++
++ if (attrs & DSP_MAPVMALLOCADDR) {
++ return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ }
++ /*
++ * Do OS-specific user-va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ if ((attrs & DSP_MAPPHYSICALADDR)) {
++ status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ goto func_cont;
++ }
++
++ /*
++ * Important Note: ulMpuAddr is mapped from user application process
++ * to current process - it must lie completely within the current
++ * virtual memory address space in order to be of use to us here!
++ */
++ down_read(&mm->mmap_sem);
++ vma = find_vma(mm, ulMpuAddr);
++ if (vma)
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++
++ /*
++ * It is observed that under some circumstances, the user buffer is
++ * spread across several VMAs. So loop through and check if the entire
++ * user buffer is covered
++ */
++ while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
++ /* jump to the next VMA region */
++ vma = find_vma(mm, vma->vm_end + 1);
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++ }
++ if (!vma) {
++ DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
++ "MPU Buffer !!! \n");
++ status = DSP_EINVALIDARG;
++ up_read(&mm->mmap_sem);
++ goto func_cont;
++ }
++
++ if (vma->vm_flags & VM_IO) {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ mpuAddr = ulMpuAddr;
++ DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"
++ "ulNumBytes= %d\n", numUsrPgs, ulNumBytes);
++ /* Get the physical addresses for user buffer */
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pa = user_va2pa(mm, mpuAddr);
++ if (!pa) {
++ status = DSP_EFAIL;
++ pr_err("DSPBRIDGE: VM_IO mapping physical"
++ "address is invalid\n");
++ break;
++ }
++ if (pfn_valid(__phys_to_pfn(pa))) {
++ pg = phys_to_page(pa);
++ get_page(pg);
++ if (page_count(pg) < 1) {
++ pr_err("Bad page in VM_IO buffer\n");
++ bad_page_dump(pa, pg);
++ }
++ }
++ status = PteSet(pDevContext->pPtAttrs, pa,
++ va, HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN VM_IO"
++ "PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ mpuAddr += HW_PAGE_SIZE_4KB;
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ } else {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
++ write = 1;
++
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,
++ write, 1, &mappedPage, NULL);
++ if (pgNum > 0) {
++ if (page_count(mappedPage) < 1) {
++ pr_err("Bad page count after doing"
++ "get_user_pages on"
++ "user buffer\n");
++ bad_page_dump(page_to_phys(mappedPage),
++ mappedPage);
++ }
++ status = PteSet(pDevContext->pPtAttrs,
++ page_to_phys(mappedPage), va,
++ HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ ulMpuAddr += HW_PAGE_SIZE_4KB;
++ } else {
++ pr_err("DSPBRIDGE: get_user_pages FAILED,"
++ "MPU addr = 0x%x,"
++ "vma->vm_flags = 0x%lx,"
++ "get_user_pages Err"
++ "Value = %d, Buffer"
++ "size=0x%x\n", ulMpuAddr,
++ vma->vm_flags, pgNum,
++ ulNumBytes);
++ status = DSP_EFAIL;
++ break;
++ }
++ }
++ }
++ up_read(&mm->mmap_sem);
++func_cont:
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ /*
++ * Roll out the mapped pages incase it failed in middle of
++ * mapping
++ */
++ if (pgI) {
++ WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,
++ (pgI * PG_SIZE_4K));
++ }
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Invalidate the PTEs for the DSP VA block to be unmapped.
++ *
++ * PTEs of a mapped memory block are contiguous in any page table
++ * So, instead of looking up the PTE address for every 4K block,
++ * we clear consecutive PTEs until we unmap all the bytes
++ */
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes)
++{
++ u32 L1BaseVa;
++ u32 L2BaseVa;
++ u32 L2BasePa;
++ u32 L2PageNum;
++ u32 pteVal;
++ u32 pteSize;
++ u32 pteCount;
++ u32 pteAddrL1;
++ u32 pteAddrL2 = 0;
++ u32 remBytes;
++ u32 remBytesL2;
++ u32 vaCurr;
++ struct page *pg = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct PgTableAttrs *pt = pDevContext->pPtAttrs;
++ u32 pacount = 0;
++ u32 *pPhysAddrPageTbl = NULL;
++ u32 temp;
++ u32 patemp = 0;
++ u32 pAddr;
++ u32 numof4KPages = 0;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
++ "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
++ pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
++ vaCurr = ulVirtAddr;
++ remBytes = ulNumBytes;
++ remBytesL2 = 0;
++ L1BaseVa = pt->L1BaseVa;
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
++ "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
++ vaCurr, remBytes);
++ while (remBytes && (DSP_SUCCEEDED(status))) {
++ u32 vaCurrOrig = vaCurr;
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /*
++ * Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA
++ */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ /*
++ * Find the L2 PTE address from which we will start
++ * clearing, the number of PTEs to be cleared on this
++ * page, and the size of VA space that needs to be
++ * cleared on this L2 page
++ */
++ pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
++ pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
++ pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
++ sizeof(u32);
++ if (remBytes < (pteCount * PG_SIZE_4K))
++ pteCount = remBytes / PG_SIZE_4K;
++
++ remBytesL2 = pteCount * PG_SIZE_4K;
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
++ "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
++ L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
++ /*
++ * Unmap the VA space on this L2 PT. A quicker way
++ * would be to clear pteCount entries starting from
++ * pteAddrL2. However, below code checks that we don't
++ * clear invalid entries or less than 64KB for a 64KB
++ * entry. Similar checking is done for L1 PTEs too
++ * below
++ */
++ while (remBytesL2 && (DSP_SUCCEEDED(status))) {
++ pteVal = *(u32 *)pteAddrL2;
++ pteSize = HW_MMU_PteSizeL2(pteVal);
++ /* vaCurr aligned to pteSize? */
++ if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ if (pteSize == HW_PAGE_SIZE_64KB)
++ numof4KPages = 16;
++ else
++ numof4KPages = 1;
++ temp = 0;
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] =
++ pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(pteAddrL2,
++ vaCurr, pteSize) == RET_OK) {
++ status = DSP_SOK;
++ remBytesL2 -= pteSize;
++ vaCurr += pteSize;
++ pteAddrL2 += (pteSize >> 12) *
++ sizeof(u32);
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (remBytesL2 == 0) {
++ pt->pgInfo[L2PageNum].numEntries -= pteCount;
++ if (pt->pgInfo[L2PageNum].numEntries == 0) {
++ /*
++ * Clear the L1 PTE pointing to the
++ * L2 PT
++ */
++ if (RET_OK == HW_MMU_PteClear(L1BaseVa,
++ vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))
++ status = DSP_SOK;
++ else {
++ status = DSP_EFAIL;
++ SYNC_LeaveCS(pt->hCSObj);
++ goto EXIT_LOOP;
++ }
++ }
++ remBytes -= pteCount * PG_SIZE_4K;
++ } else {
++ status = DSP_EFAIL;
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
++ "numEntries %x, pteCount %x, status: 0x%x\n",
++ L2PageNum, pt->pgInfo[L2PageNum].numEntries,
++ pteCount, status);
++ SYNC_LeaveCS(pt->hCSObj);
++ } else
++ /* vaCurr aligned to pteSize? */
++ /* pteSize = 1 MB or 16 MB */
++ if ((pteSize != 0) && (remBytes >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ if (pteSize == HW_PAGE_SIZE_1MB)
++ numof4KPages = 256;
++ else
++ numof4KPages = 4096;
++ temp = 0;
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] = pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)
++ == RET_OK) {
++ status = DSP_SOK;
++ remBytes -= pteSize;
++ vaCurr += pteSize;
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ /*
++ * It is better to flush the TLB here, so that any stale old entries
++ * get flushed
++ */
++EXIT_LOOP:
++ flush_all(pDevContext);
++ for (temp = 0; temp < pacount; temp++) {
++ patemp = pPhysAddrPageTbl[temp];
++ if (pfn_valid(__phys_to_pfn(patemp))) {
++ pg = phys_to_page(patemp);
++ if (page_count(pg) < 1) {
++ pr_info("DSPBRIDGE:UNMAP function: COUNT 0"
++ "FOR PA 0x%x, size = 0x%x\n",
++ patemp, ulNumBytes);
++ bad_page_dump(patemp, pg);
++ }
++ SetPageDirty(pg);
++ page_cache_release(pg);
++ }
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
++ "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
++ "remBytesL2 %x\n", status, remBytes, remBytesL2);
++ return status;
++}
++
++/*
++ * ======== user_va2pa ========
++ * Purpose:
++ * This function walks through the Linux page tables to convert a userland
++ * virtual address to physical address
++ */
++static u32 user_va2pa(struct mm_struct *mm, u32 address)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++
++ pgd = pgd_offset(mm, address);
++ if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
++ pmd = pmd_offset(pgd, address);
++ if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
++ ptep = pte_offset_map(pmd, address);
++ if (ptep) {
++ pte = *ptep;
++ if (pte_present(pte))
++ return pte & PAGE_MASK;
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++/*
++ * ======== PteUpdate ========
++ * This function calculates the optimum page-aligned addresses and sizes
++ * Caller must pass page-aligned values
++ */
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ u32 i;
++ u32 allBits;
++ u32 paCurr = pa;
++ u32 vaCurr = va;
++ u32 numBytes = size;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++ DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
++ "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
++ status = PteSet(pDevContext->pPtAttrs, paCurr,
++ vaCurr, pgSize[i], mapAttrs);
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size */
++ break;
++ }
++ }
++ }
++ DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
++ numBytes);
++ return status;
++}
++
++/*
++ * ======== PteSet ========
++ * This function calculates PTE address (MPU virtual) to be updated
++ * It also manages the L2 page tables
++ */
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs)
++{
++ u32 i;
++ u32 pteVal;
++ u32 pteAddrL1;
++ u32 pteSize;
++ u32 pgTblVa; /* Base address of the PT that will be updated */
++ u32 L1BaseVa;
++ /* Compiler warns that the next three variables might be used
++ * uninitialized in this function. Doesn't seem so. Working around,
++ * anyways. */
++ u32 L2BaseVa = 0;
++ u32 L2BasePa = 0;
++ u32 L2PageNum = 0;
++ DSP_STATUS status = DSP_SOK;
++ DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
++ "size %x, attrs %x\n", pt, pa, va, size, attrs);
++ L1BaseVa = pt->L1BaseVa;
++ pgTblVa = L1BaseVa;
++ if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
++ if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ } else {
++ return DSP_EFAIL;
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /* Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ } else if (pteSize == 0) {
++ /* L1 PTE is invalid. Allocate a L2 PT and
++ * point the L1 PTE to it */
++ /* Find a free L2 PT. */
++ for (i = 0; (i < pt->L2NumPages) &&
++ (pt->pgInfo[i].numEntries != 0); i++)
++ ;;
++ if (i < pt->L2NumPages) {
++ L2PageNum = i;
++ L2BasePa = pt->L2BasePa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ L2BaseVa = pt->L2BaseVa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ /* Endianness attributes are ignored for
++ * HW_MMU_COARSE_PAGE_SIZE */
++ status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
++ HW_MMU_COARSE_PAGE_SIZE, attrs);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Found valid L1 PTE of another size.
++ * Should not overwrite it. */
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pgTblVa = L2BaseVa;
++ if (size == HW_PAGE_SIZE_64KB)
++ pt->pgInfo[L2PageNum].numEntries += 16;
++ else
++ pt->pgInfo[L2PageNum].numEntries++;
++ DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
++ "PageNum %x numEntries %x\n", L2BaseVa,
++ L2BasePa, L2PageNum,
++ pt->pgInfo[L2PageNum].numEntries);
++ }
++ SYNC_LeaveCS(pt->hCSObj);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
++ pgTblVa, pa, va, size);
++ DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
++ "mixedSize %x\n", attrs->endianism,
++ attrs->elementSize, attrs->mixedSize);
++ status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
++ }
++ DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
++ return status;
++}
++
++/* Memory map kernel VA -- memory allocated with vmalloc */
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ struct HW_MMUMapAttrs_t *hwAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct page *pPage[1];
++ u32 i;
++ u32 paCurr;
++ u32 paNext;
++ u32 vaCurr;
++ u32 sizeCurr;
++ u32 numPages;
++ u32 pa;
++ u32 numOf4KPages;
++ u32 temp = 0;
++
++ DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
++ "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);
++
++ /*
++ * Do Kernel va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
++ i = 0;
++ vaCurr = ulMpuAddr;
++ pPage[0] = vmalloc_to_page((void *)vaCurr);
++ paNext = page_to_phys(pPage[0]);
++ while (DSP_SUCCEEDED(status) && (i < numPages)) {
++ /*
++ * Reuse paNext from the previous iteraion to avoid
++ * an extra va2pa call
++ */
++ paCurr = paNext;
++ sizeCurr = PAGE_SIZE;
++ /*
++ * If the next page is physically contiguous,
++ * map it with the current one by increasing
++ * the size of the region to be mapped
++ */
++ while (++i < numPages) {
++ pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
++ paNext = page_to_phys(pPage[0]);
++ DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
++ "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
++ if (paNext == (paCurr + sizeCurr))
++ sizeCurr += PAGE_SIZE;
++ else
++ break;
++
++ }
++ if (paNext == 0) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ pa = paCurr;
++ numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;
++ while (temp++ < numOf4KPages) {
++ get_page(phys_to_page(pa));
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
++ (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);
++ vaCurr += sizeCurr;
++ }
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
++ status);
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);
++ return status;
++}
++
++static DSP_STATUS run_IdleBoot(u32 prm_base, u32 cm_base,
++ u32 sysctrl_base)
++{
++ u32 temp;
++ DSP_STATUS status = DSP_SOK;
++ enum HW_PwrState_t pwrState;
++
++ /* Read PM_PWSTST_IVA2 */
++ HW_PWRST_IVA2RegGet(prm_base, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(prm_base, HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(cm_base, HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
++ }
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ udelay(10);
++ /* Assert IVA2-RST1 and IVA2-RST2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x07;
++ udelay(30);
++ /* set the SYSC for Idle Boot */
++ *((REG_UWORD32 *)((u32)(sysctrl_base) + 0x404)) = (u32)0x01;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x4)) =
++ (u32) temp;
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ udelay(20);
++ GetHWRegs(prm_base, cm_base);
++ /* Release Reset1 and Reset2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x05;
++ udelay(20);
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x04;
++ udelay(30);
++ return status;
++}
++
++
++void GetHWRegs(u32 prm_base, u32 cm_base)
++{
++ u32 temp;
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x00));
++ DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x20));
++ DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x48));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x4c));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x50));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x58));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE0));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE4));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0xA10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
++}
++
++/*
++ * ======== configureDspMmu ========
++ * Make DSP MMU page table entries.
++ */
++void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
++ u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ struct CFG_HOSTRES resources;
++ struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(sizeInBytes > 0);
++ DBG_Trace(DBG_LEVEL1,
++ "configureDspMmu entry %x pa %x, va %x, bytes %x ",
++ nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
++
++ DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
++ endianism, elemSize, mixedSize);
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ status = HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, dataBasePhys,
++ dspBaseVirt, sizeInBytes, nEntryStart,
++ &mapAttrs, HW_SET, HW_SET);
++}
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ */
++bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
++{
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++
++ /* Wait for response from board */
++ while (*((volatile u16 *)dwSyncAddr) && --usCount)
++ udelay(10);
++
++ /* If timed out: return FALSE */
++ if (!usCount) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
++ return FALSE;
++ }
++ return TRUE;
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+new file mode 100644
+index 0000000..cbf6925
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+@@ -0,0 +1,731 @@
++/*
++ * tiomap_pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap_pwr.c ========
++ * Description:
++ * Implementation of DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
++ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
++ *! code.
++ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
++ *! 06-Dec-2002 cring: Added Palm support.
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/io_sm.h>
++#include <dspbridge/chnl_sm.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/brddefs.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/iodefs.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++
++#include <dspbridge/pwr_sh.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_util.h"
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++
++#ifdef CONFIG_PM
++#include <mach/board-3430sdp.h>
++#endif
++extern struct MAILBOX_CONTEXT mboxsetting;
++static unsigned short enable_off_mode = 0;
++/*
++ * ======== handle_constraints_set ========
++ * Sets new DSP constraint
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 *pConstraintVal;
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES resources;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ pConstraintVal = (u32 *)(pArgs);
++ /* Read the target value requested by DSP */
++ DBG_Trace(DBG_LEVEL7, "handle_constraints_set:"
++ "opp requested = 0x%x\n", (u32)*(pConstraintVal+1));
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++
++ /* Set the new opp value */
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)((u32)*(pConstraintVal+1));
++ return DSP_SOK;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 opplevel;
++ struct IO_MGR *hIOMgr;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Off state, how much time should
++ * we wait? */
++ while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
++ status = WMD_E_TIMEOUT;
++ return status;
++ } else {
++
++ /* Save mailbox settings */
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
++ mboxsetting.sysconfig);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
++ mboxsetting.irqEnable0);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
++ mboxsetting.irqEnable1);
++ /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Bridger Driver state */
++ pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
++#ifdef CONFIG_BRIDGE_DVFS
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_FAILED(status))
++ return status;
++ IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
++ /* Set the OPP to low level before moving to OFF mode */
++ if (opplevel != VDD1_OPP1) {
++ DBG_Trace(DBG_LEVEL5,
++ "Tiomap_pwr.c - DSP requested"
++ " OPP = %d, MPU requesting low"
++ " OPP %d instead\n", opplevel,
++ VDD1_OPP1);
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(VDD1_OPP1);
++ status = DSP_SOK;
++ }
++#endif /* CONFIG_BRIDGE_DVFS */
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "handle_hibernation_fromDSP- FAILED\n");
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== SleepDSP ========
++ * Put DSP in low power consuming state.
++ */
++DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
++ IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ enum HW_PwrState_t pwrState;
++ enum HW_PwrState_t targetPwrState;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
++
++ /* next, check if sleep code is valid... */
++ if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
++ return DSP_EINVALIDARG;
++ }
++ switch (pDevContext->dwBrdState) {
++ case BRD_RUNNING:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP - Sent hibernate "
++ "command to DSP\n");
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPRETENTION);
++ targetPwrState = HW_PWR_STATE_RET;
++ }
++ break;
++ case BRD_RETENTION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else
++ return DSP_SOK;
++ break;
++ case BRD_HIBERNATION:
++ case BRD_DSP_HIBERNATION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ /* Already in Hibernation, so just return */
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
++ "hibernation\n");
++ return DSP_SOK;
++ case BRD_STOPPED:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Board in STOP state \n");
++ return DSP_SALREADYASLEEP;
++ default:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Bridge in Illegal state\n");
++ return DSP_EFAIL;
++ }
++ /* Get the PRCM DSP power domain status */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Standby state, how much time
++ * should we wait?*/
++ while ((pwrState != targetPwrState) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
++ " STANDBY %x \n", pwrState);
++ return WMD_E_TIMEOUT;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
++ pwrState);
++ /* Update the Bridger Driver state */
++ if (enable_off_mode)
++ pDevContext->dwBrdState = BRD_HIBERNATION;
++ else
++ pDevContext->dwBrdState = BRD_RETENTION;
++ /* Turn off DSP Peripheral clocks */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
++ }
++#endif
++ return status;
++}
++
++
++/*
++ * ======== WakeDSP ========
++ * Wake up DSP from sleep.
++ */
++DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++ u32 temp;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ /* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
++ if (pDevContext->dwBrdState == BRD_RUNNING ||
++ pDevContext->dwBrdState == BRD_STOPPED ||
++ pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ /* The Device is in 'RET' or 'OFF' state and WMD state is not
++ * 'SLEEP', this means state inconsistency, so return */
++ status = DSP_SOK;
++ return status;
++ }
++ /* Enable the DSP peripheral clocks and load monitor timer
++ * before waking the DSP */
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
++ pDevContext->uDspPerClks);
++ status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
++
++ /* Enabling Dppll in lock mode */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++
++ udelay(10);
++ if (DSP_SUCCEEDED(status)) {
++ /* Send a message to DSP to wake up */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ DBG_Trace(DBG_LEVEL7,
++ "\nWakeDSP: Power State After sending Interrupt "
++ "to DSP %x\n", pwrState);
++ /* set the device state to RUNNIG */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ } else {
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== DSPPeripheralClkCtrl ========
++ * Enable/Disable the DSP peripheral clocks as needed..
++ */
++DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 extClk = 0;
++ u32 extClkId = 0;
++ u32 extClkCmd = 0;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++ u32 tmpIndex;
++ u32 dspPerClksBefore;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++
++ DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
++ dspPerClksBefore = pDevContext->uDspPerClks;
++ DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
++ dspPerClksBefore);
++
++ extClk = (u32)*((u32 *)pArgs);
++
++ DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
++ extClk);
++
++ extClkId = extClk & MBX_PM_CLK_IDMASK;
++
++ /* process the power message -- TODO, keep it in a separate function */
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++ /* TODO -- Assert may be a too hard restriction here.. May be we should
++ * just return with failure when the CLK ID does not match */
++ /* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
++ if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl : Could n't get clock Id for"
++ "clkid 0x%x \n", clkIdIndex);
++ /* return with a more meaningfull error code */
++ return DSP_EFAIL;
++ }
++ extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
++ switch (extClkCmd) {
++ case BPWR_DisableClock:
++ /* Call BP to disable the needed clock */
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Disable CLK for \n");
++ status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, false);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) &=
++ (~((u32) (1 << clkIdIndex)));
++ } else {
++ DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
++ "to disable clk\n");
++ }
++ break;
++ case BPWR_EnableClock:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Enable CLK for \n");
++ status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, true);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) |= (1 << clkIdIndex);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl:Failed to Enable clk\n");
++ }
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Unsupported CMD \n");
++ /* unsupported cmd */
++ /* TODO -- provide support for AUTOIDLE Enable/Disable
++ * commands */
++ }
++ return status;
++}
++
++/*
++ * ========PreScale_DSP========
++ * Sends prescale notification to DSP
++ *
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
++ "0x%x\n", voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
++ "No notification to DSP\n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Send a prenotificatio to DSP */
++ DBG_Trace(DBG_LEVEL7,
++ "PreScale_DSP: Sent notification to DSP\n");
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
++ " state in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========PostScale_DSP========
++ * Sends postscale notification to DSP
++ *
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
++ voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: IVA in sleep. Wrote to shared "
++ "memory \n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ /* Send a post notification to DSP */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: Wrote to shared memory Sent post"
++ " notification to DSP\n");
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
++ "in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Disable========
++ * Disables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++
++ u32 clkIdx;
++ DSP_STATUS status = DSP_SOK;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Disables the interface clock of the peripheral */
++ status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ /* Disables the functional clock of the periphearl */
++ status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Enable========
++ * Enables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 clkIdx;
++ DSP_STATUS int_clk_status = DSP_EFAIL, fun_clk_status = DSP_EFAIL;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Enable the interface clock of the peripheral */
++ int_clk_status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
++ /* Enable the functional clock of the periphearl */
++ fun_clk_status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
++ }
++ }
++ if ((int_clk_status | fun_clk_status) != DSP_SOK)
++ return DSP_EFAIL;
++ return DSP_SOK;
++}
++
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable)
++{
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ u32 iva2_grpsel;
++ u32 mpu_grpsel;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return;
++
++ switch (ClkId) {
++ case BPWR_GPTimer5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer6:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT6;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT6;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer7:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT7;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT7;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer8:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT8;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT8;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP1:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP2:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP3:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP4:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ }
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
+new file mode 100644
+index 0000000..6121e8f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.c
+@@ -0,0 +1,427 @@
++/*
++ * tiomap_io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.c ========
++ * Description:
++ * Implementation for the io read/write routines.
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp: Fixed warning in WriteDspData function.
++ *! 16-Apr-2003 vp: Added support for TC word swap
++ *! 26-Feb-2003 vp: Fixed issue with EXT_BEG and EXT_END address.
++ *! 24-Feb-2003 vp: Ported to Linux platform
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/cfg.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "tiomap_io.h"
++
++static u32 ulExtBase;
++static u32 ulExtEnd;
++
++static u32 ulShm0End;
++static u32 ulDynExtBase;
++static u32 ulTraceSecBeg;
++static u32 ulTraceSecEnd;
++static u32 ulShmBaseVirt;
++
++bool bSymbolsReloaded = true;
++
++/*
++ * ======== ReadExtDspData ========
++ * Copies DSP external memory buffers to the host side buffers.
++ */
++DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ u32 dwExtProgVirtMem;
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ bool bTraceRead = false;
++
++ DBG_Trace(DBG_ENTER, "ReadExtDspData,"
++ "hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
++ "\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++
++ if (!ulShmBaseVirt) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ }
++ DBC_Assert(ulShmBaseVirt != 0);
++
++ /* Check if it is a read of Trace section */
++ if (!ulTraceSecBeg) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ }
++ DBC_Assert(ulTraceSecBeg != 0);
++
++ if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ DBC_Assert(ulTraceSecEnd != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
++ "section 0x%x \n", dwDSPAddr);
++ bTraceRead = true;
++ }
++ }
++
++ /* If reading from TRACE, force remap/unmap */
++ if ((bTraceRead) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ pDevContext->dwDspExtBaseAddr = 0;
++ }
++
++ if (!dwBaseAddr) {
++ /* Initialize ulExtBase and ulExtEnd */
++ ulExtBase = 0;
++ ulExtEnd = 0;
++
++ /* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
++ if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DYNEXTBASE, &ulDynExtBase);
++ }
++ DBC_Assert(ulDynExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTBASE, &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTEND, &ulExtEnd);
++ }
++ DBC_Assert(ulExtEnd != 0);
++
++ /* Trace buffer is right after the SHM SEG0,
++ * so set the base address to SHMBASE */
++ if (bTraceRead) {
++ ulExtBase = ulShmBaseVirt;
++ ulExtEnd = ulTraceSecEnd;
++ }
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++
++ if (ulExtEnd < ulExtBase)
++ status = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(status)) {
++ ulTLBBaseVirt =
++ pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
++
++ if (bTraceRead) {
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to SHMMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ } else {
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
++ ulDynExtBase + 1,
++ HW_PAGE_SIZE_64KB);
++ dwExtProgVirtMem -= ulShmOffsetVirt;
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ pDevContext->dwDspExtBaseAddr =
++ dwExtProgVirtMem;
++
++ /* This dwDspExtBaseAddr will get cleared only when the board is
++ * stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "failed to Map the program memory\n");
++ }
++ }
++
++ dwBaseAddr = dwExtProgVirtMem;
++ }
++ }
++
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7,
++ "Symbols missing for Ext Prog reading \n");
++ status = DSP_EFAIL;
++ }
++
++ offset = dwDSPAddr - ulExtBase;
++
++ if (DSP_SUCCEEDED(status))
++ memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
++
++ return status;
++}
++/*
++ * ======== WriteDspData ========
++ * purpose:
++ * Copies buffers to the DSP internal/external memory.
++ */
++DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
++{
++ u32 offset;
++ u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status;
++ u32 base1, base2, base3;
++ base1 = OMAP_DSP_MEM1_SIZE;
++ base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
++ base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
++ DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
++ if (offset < base1) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
++ resources.dwMemLength[2]);
++ } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
++ resources.dwMemLength[3]);
++ offset = offset - base2;
++ } else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
++ offset < base3 + OMAP_DSP_MEM3_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
++ resources.dwMemLength[4]);
++ offset = offset - base3;
++ } else{
++ status = DSP_EFAIL;
++ return status;
++ }
++ if (ulNumBytes)
++ memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+offset;
++
++ return status;
++}
++
++/*
++ * ======== WriteExtDspData ========
++ * purpose:
++ * Copies buffers to the external memory.
++ *
++ */
++DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType, bool bDynamicLoad)
++{
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ u32 dwOffset = 0;
++ u8 bTempByte1, bTempByte2;
++ u8 remainByte[4];
++ s32 i;
++ DSP_STATUS retVal = DSP_SOK;
++ u32 dwExtProgVirtMem;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ struct CFG_HOSTRES hostRes;
++ bool bTraceLoad = false;
++ bTempByte1 = 0x0;
++ bTempByte2 = 0x0;
++
++ DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
++ "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
++ if (bSymbolsReloaded) {
++ /* Check if it is a load to Trace section */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
++ "section 0x%x \n", dwDSPAddr);
++ bTraceLoad = true;
++ }
++ }
++
++ /* If dynamic, force remap/unmap */
++ if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ if (!dwBaseAddr) {
++ if (bSymbolsReloaded)
++ /* Get SHM_BEG EXT_BEG and EXT_END. */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ DBC_Assert(ulShmBaseVirt != 0);
++ if (bDynamicLoad) {
++ if (DSP_SUCCEEDED(retVal)) {
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal)) {
++ /* DR OMAPS00013235 : DLModules array may be
++ * in EXTMEM. It is expected that DYNEXTMEM and
++ * EXTMEM are contiguous, so checking for the
++ * upper bound at EXTEND should be Ok. */
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ } else {
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTBASE,
++ &ulExtBase);
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ }
++ /* Trace buffer it right after the SHM SEG0, so set the
++ * base address to SHMBASE */
++ if (bTraceLoad)
++ ulExtBase = ulShmBaseVirt;
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++ if (ulExtEnd < ulExtBase)
++ retVal = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(retVal)) {
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
++ DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DSP_TRACESEC_END,
++ &ulShm0End);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulDynExtBase);
++ }
++ }
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ if (bTraceLoad) {
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].
++ ulGppVa;
++ } else {
++ CFG_GetHostResources(
++ (struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++ dwExtProgVirtMem = hostRes.dwMemBase[1];
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ }
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
++ "pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++
++ pDevContext->dwDspExtBaseAddr =
++ (u32)MEM_LinearAddress((void *)
++ TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
++ - ulExtBase);
++ dwBaseAddr += pDevContext->dwDspExtBaseAddr;
++ /* This dwDspExtBaseAddr will get cleared only when
++ * the board is stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ retVal = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
++ "to Map the program memory\n");
++ }
++ }
++ }
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
++ retVal = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ for (i = 0; i < 4; i++)
++ remainByte[i] = 0x0;
++
++ dwOffset = dwDSPAddr - ulExtBase;
++ /* Also make sure the dwDSPAddr is < ulExtEnd */
++ if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
++ DBG_Trace(DBG_LEVEL7, "We can not load at this address "
++ "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
++ "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
++ ulExtEnd);
++ retVal = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if (ulNumBytes)
++ memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
++ ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
++ }
++ /* Unmap here to force remap for other Ext loads */
++ if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
++ MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ bSymbolsReloaded = false;
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
+new file mode 100644
+index 0000000..84a7553
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.h
+@@ -0,0 +1,112 @@
++/*
++ * tiomap_io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.h ========
++ * Description:
++ * Definitions, types and function prototypes for the io
++ * (r/w external mem).
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_IO_
++#define _TIOMAP_IO_
++
++/*
++ * Symbol that defines beginning of shared memory.
++ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
++ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
++ * (see dspMmuTlbEntry()).
++ */
++#define SHMBASENAME "SHM_BEG"
++#define EXTBASE "EXT_BEG"
++#define EXTEND "_EXT_END"
++#define DYNEXTBASE "_DYNEXT_BEG"
++#define DYNEXTEND "_DYNEXT_END"
++#define IVAEXTMEMBASE "_IVAEXTMEM_BEG"
++#define IVAEXTMEMEND "_IVAEXTMEM_END"
++
++
++#define DSP_TRACESEC_BEG "_BRIDGE_TRACE_BEG"
++#define DSP_TRACESEC_END "_BRIDGE_TRACE_END"
++
++#define SYS_PUTCBEG "_SYS_PUTCBEG"
++#define SYS_PUTCEND "_SYS_PUTCEND"
++#define BRIDGE_SYS_PUTC_current "_BRIDGE_SYS_PUTC_current"
++
++
++#define WORDSWAP_ENABLE 0x3 /* Enable word swap */
++
++/*
++ * ======== ReadExtDspData ========
++ * Reads it from DSP External memory. The external memory for the DSP
++ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
++ */
++extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteDspData ========
++ */
++extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteExtDspData ========
++ * Writes to the DSP External memory for external program.
++ * The ext mem for progra is configured by the combination of DSP MMU and
++ * SHM Memory manager in the CDB
++ */
++extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType,
++ bool bDynamicLoad);
++
++/*
++ * ======== WriteExt32BitDspData ========
++ * Writes 32 bit data to the external memory
++ */
++extern inline void WriteExt32BitDspData(IN const
++ struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
++ IN u32 val)
++{
++ *(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
++ 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
++}
++
++/*
++ * ======== ReadExt32BitDspData ========
++ * Reads 32 bit data from the external memory
++ */
++extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
++ *pDevContext, IN u32 dwDSPAddr)
++{
++ u32 retVal;
++ retVal = *(u32 *)dwDSPAddr;
++
++ retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
++ & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
++ return retVal;
++}
++
++#endif /* _TIOMAP_IO_ */
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
+new file mode 100644
+index 0000000..a6d5d62
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
+@@ -0,0 +1,195 @@
++/*
++ * tiomap_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#include <dspbridge/dbg.h>
++
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++
++#define MAILBOX_FIFOSTATUS(m) (0x80 + 4 * (m))
++
++static inline unsigned int fifo_full(void __iomem *mbox_base, int mbox_id)
++{
++ return __raw_readl(mbox_base + MAILBOX_FIFOSTATUS(mbox_id)) & 0x1;
++}
++
++DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 numMbxMsg;
++ u32 mbxValue;
++ struct CFG_HOSTRES resources;
++ u32 devType;
++ struct IO_MGR *hIOMgr;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
++
++ /* Read the messages in the mailbox until the message queue is empty */
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ DEV_GetDevType(pDevContext->hDevObject, &devType);
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (devType == DSP_UNIT) {
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_DSP2ARM, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ &mbxValue);
++ numMbxMsg--;
++ }
++ /* clear the DSP mailbox as well...*/
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_ARM2DSP, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_ARM2DSP, &mbxValue);
++ numMbxMsg--;
++ udelay(10);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_INT_NEW_MSG);
++ }
++ /* Enable the new message events on this IRQ line */
++ HW_MBOX_EventEnable(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ MBOX_ARM,
++ HW_MBOX_INT_NEW_MSG);
++ }
++
++ return status;
++}
++
++DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
++ MBOX_ARM, HW_MBOX_INT_NEW_MSG);
++ return DSP_SOK;
++}
++
++DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext,
++ u16 wMbVal)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ u32 opplevel = 0;
++#endif
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ unsigned long timeout;
++ u32 temp;
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ return DSP_EFAIL;
++#ifdef CONFIG_BRIDGE_DVFS
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ if (pdata->dsp_get_opp)
++ opplevel = (*pdata->dsp_get_opp)();
++ if (opplevel == 1) {
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(opplevel+1);
++ }
++ }
++#endif
++
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ /* Restore mailbox settings */
++ /* Restart the peripheral clocks that were disabled only
++ * in DSP initiated Hibernation case.*/
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ DSP_PeripheralClocks_Enable(pDevContext, NULL);
++ /* Enabling Dpll in lock mode*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++ }
++ HW_MBOX_restoreSettings(resources.dwMboxBase);
++
++ /* Access MMU SYS CONFIG register to generate a short wakeup */
++ temp = (u32) *((REG_UWORD32 *) ((u32)
++ (resources.dwDmmuBase) + 0x10));
++
++ pDevContext->dwBrdState = BRD_RUNNING;
++ }
++ timeout = jiffies + msecs_to_jiffies(1);
++ while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) {
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n");
++ return WMD_E_TIMEOUT;
++ }
++ }
++ DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
++ wMbVal);
++
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ wMbVal);
++ return DSP_SOK;
++}
++
++bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC,
++ u16 *pwIntrVal)
++{
++ struct CFG_HOSTRES resources;
++ u32 numMbxMsg;
++ u32 mbxValue;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
++
++ if (numMbxMsg > 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
++ HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
++
++ DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
++ *pwIntrVal = (u16) mbxValue;
++ }
++ /* Set *pfSchedDPC to true; */
++ *pfSchedDPC = true;
++ return true;
++}
+diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
+new file mode 100644
+index 0000000..d5551cb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/ue_deh.c
+@@ -0,0 +1,329 @@
++/*
++ * ue_deh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ue_deh.c ========
++ * Description:
++ * Implements upper edge DSP exception handling (DEH) functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn: Support for IVA DEH.
++ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "mmu_fault.h"
++#include "_tiomap.h"
++#include "_deh.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_pwr.h"
++#include <dspbridge/io_sm.h>
++
++static struct HW_MMUMapAttrs_t mapAttrs = { HW_LITTLE_ENDIAN,
++ HW_ELEM_SIZE_16BIT,
++ HW_MMU_CPUES} ;
++#define VirtToPhys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
++/*
++ * ======== WMD_DEH_Create ========
++ * Creates DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = NULL;
++ struct CFG_HOSTRES cfgHostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ /* Get WMD context info. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
++ if (pDehMgr == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Create an NTFY object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pDehMgr->hNtfy);
++
++ /* Create a DPC object. */
++ status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
++ (void *)pDehMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &cfgHostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in context structure */
++ pDehMgr->hWmdContext = hWmdContext;
++ pDehMgr->errInfo.dwErrMask = 0L;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Install ISR function for DSP MMU fault */
++ if ((request_irq(INT_DSP_MMU_IRQ, MMU_FaultIsr, 0,
++ "DspBridge\tiommu fault", (void *)pDehMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* If create failed, cleanup */
++ WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
++ *phDehMgr = NULL;
++ } else {
++ *phDehMgr = (struct DEH_MGR *)pDehMgr;
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Destroys DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* If notification object exists, delete it */
++ if (pDehMgr->hNtfy)
++ (void)NTFY_Delete(pDehMgr->hNtfy);
++ /* Disable DSP MMU fault */
++ free_irq(INT_DSP_MMU_IRQ, pDehMgr);
++ (void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
++ /* Deallocate the DEH manager object */
++ MEM_FreeObject(pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Registers for DEH notifications.
++ */
++DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
++ pDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ status = NTFY_Register(pDehMgr->hNtfy, hNotification,
++ uEventMask, uNotifyType);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_DEH_Notify ========
++ * DEH error notification function. Informs user about the error.
++ */
++void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
++ u32 dwErrInfo)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 memPhysical = 0;
++ u32 HW_MMU_MAX_TLB_COUNT = 31;
++ u32 extern faultAddr;
++ struct CFG_HOSTRES resources;
++ u32 dummyVaAddr;
++ HW_STATUS hwStatus;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources in MMU ISR **\n");
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
++ ulEventMask);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
++ "**********\n");
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++
++ switch (ulEventMask) {
++ case DSP_SYSERROR:
++ /* reset errInfo structure before use */
++ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ pDehMgr->errInfo.dwVal1 = dwErrInfo;
++ printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
++ "= 0x%x\n", dwErrInfo);
++ break;
++ case DSP_MMUFAULT:
++ /* MMU fault routine should have set err info
++ * structure */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
++ "errInfo = 0x%x\n", dwErrInfo);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal1);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal2);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", (unsigned int)faultAddr);
++ dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ memPhysical = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ dummyVaAddr = PG_ALIGN_LOW((u32)dummyVaAddr,
++ PG_SIZE_4K);
++ memPhysical = VirtToPhys(dummyVaAddr);
++ DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
++ "mem Physical= 0x%x\n", memPhysical);
++ pDevContext = (struct WMD_DEV_CONTEXT *)
++ pDehMgr->hWmdContext;
++ /* Reset the dynamic mmu index to fixed count if it
++ * exceeds 31. So that the dynmmuindex is always
++ * between the range of standard/fixed entries
++ * and 31. */
++ if (pDevContext->numTLBEntries >
++ HW_MMU_MAX_TLB_COUNT) {
++ pDevContext->numTLBEntries = pDevContext->
++ fixedTLBEntries;
++ }
++ DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
++ "PA: 0x%x\n", pDevContext->
++ numTLBEntries, faultAddr, memPhysical);
++ if (DSP_SUCCEEDED(status)) {
++ hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
++ memPhysical, faultAddr,
++ HW_PAGE_SIZE_4KB, 1, &mapAttrs,
++ HW_SET, HW_SET);
++ }
++ /* send an interrupt to DSP */
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ MBX_DEH_CLASS | MBX_DEH_EMMU);
++ /* Clear MMU interrupt */
++ HW_MMU_EventAck(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL6,
++ "WMD_DEH_Notify: Unknown Error, errInfo = "
++ "0x%x\n", dwErrInfo);
++ break;
++ }
++ /* Set the Board state as ERROR */
++ pDevContext->dwBrdState = BRD_ERROR;
++ /* Disable all the clocks that were enabled by DSP */
++ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ /* Call DSP Trace Buffer */
++ PrintDspTraceBuffer(hDehMgr->hWmdContext);
++
++ /* Signal DSP error/exception event. */
++ NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
++
++}
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Retrieves error information.
++ */
++DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBC_Require(pDehMgr);
++ DBC_Require(pErrInfo);
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* Copy DEH error info structure to PROC error info
++ * structure. */
++ pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
++ pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
++ pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
++ pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
++ }
++
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
++
++ return status;
++}
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch
new file mode 100644
index 0000000000..d75f15d00a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch
@@ -0,0 +1,20 @@
+--- a/drivers/video/fbsysfs.c 2009-07-17 12:23:16.000000000 -0700
++++ b/drivers/video/fbsysfs.c 2009-07-17 12:24:32.000000000 -0700
+@@ -489,7 +489,7 @@
+ * fbdev to use configfs instead of sysfs */
+ static struct device_attribute device_attrs[] = {
+ __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+- __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
++ __ATTR(blank, S_IRUGO|S_IWUGO, show_blank, store_blank),
+ __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+ __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+ __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+@@ -498,7 +498,7 @@
+ __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+ __ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(stride, S_IRUGO, show_stride, NULL),
+- __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
++ __ATTR(rotate, S_IRUGO|S_IWUGO, show_rotate, store_rotate),
+ __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+ #ifdef CONFIG_FB_BACKLIGHT
+ __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch
new file mode 100644
index 0000000000..eaa78e28c7
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch
@@ -0,0 +1,44 @@
+From c78da49092fd206943f77aa9ebc3fa2c1301ac5a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Thu, 23 Apr 2009 18:19:32 -0700
+Subject: [PATCH] DSS2: Export display status to sysfs
+
+It is useful to know from userspace if the display has been turned off,
+e.g. to toggle display power from userspace.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 2c88718..28438fb 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -326,6 +326,15 @@ static ssize_t show_virt(struct device *dev,
+ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
+ }
+
++static ssize_t show_display_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omap_display *display = fb2display(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", display->state);
++}
++
+ static struct device_attribute omapfb_attrs[] = {
+ __ATTR(rotate_type, S_IRUGO, show_rotate_type, NULL),
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+@@ -333,6 +342,7 @@ static struct device_attribute omapfb_attrs[] = {
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
++ __ATTR(display_state, S_IRUGO, show_display_state, NULL),
+ };
+
+ int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch
new file mode 100644
index 0000000000..98a82c8a35
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch
@@ -0,0 +1,177 @@
+From a9cc890ffea21fa492678b1755a263120cbddf0e Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Mon, 20 Apr 2009 20:29:11 -0700
+Subject: [PATCH] DSS2: OMAPFB: Translate X/Y coordinates for the video planes when rotating.
+
+When rotating the video planes, translate the X/Y coordinates such that
+a [0,0] from userspace always maps to the correct upper left corner of
+the display. This patch assumes that you rotate plane 0 before rotating
+plane 1. Patch also corrects the scaling parameters so that the video is
+displayed in the correct orientation (vertically, instead of horizontally)
+when rotating by 90 / 270 degrees.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/dss/dispc.c | 16 ++++++++++++----
+ drivers/video/omap2/dss/overlay.c | 6 ++++++
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 28 ++++++++++++++++++++++++++++
+ 3 files changed, 46 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 7e551c2..bece91d 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1580,10 +1580,18 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ _dispc_set_pic_size(plane, width, height);
+
+ if (plane != OMAP_DSS_GFX) {
+- _dispc_set_scaling(plane, width, height,
+- out_width, out_height,
+- ilace, five_taps, fieldmode);
+- _dispc_set_vid_size(plane, out_width, out_height);
++ if (rotation == 1 || rotation == 3) {
++ _dispc_set_scaling(plane, width, height,
++ out_height, out_width,
++ ilace, five_taps, fieldmode);
++ _dispc_set_vid_size(plane, out_height, out_width);
++ } else {
++ _dispc_set_scaling(plane, width, height,
++ out_width, out_height,
++ ilace, five_taps, fieldmode);
++ _dispc_set_vid_size(plane, out_width, out_height);
++ }
++
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index c047206..a1a02b5 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -344,6 +344,20 @@
+ outh = info->out_height;
+ }
+
++ if ((ovl->supported_modes & info->color_mode) == 0) {
++ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
++ return -EINVAL;
++ }
++
++ if (ovl->id != OMAP_DSS_GFX && (info->rotation == 1 ||
++ info->rotation == 3)) {
++ if(outw > dh || outh > dw)
++ return -EINVAL;
++
++ /* If coordinates are invalid, they will be clipped later... */
++ return 0;
++ }
++
+ if (dw < info->pos_x + outw) {
+ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
+ dw, info->pos_x, outw);
+@@ -356,11 +370,6 @@
+ return -EINVAL;
+ }
+
+- if ((ovl->supported_modes & info->color_mode) == 0) {
+- DSSERR("overlay doesn't support mode %d\n", info->color_mode);
+- return -EINVAL;
+- }
+-
+ return 0;
+ }
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -400,7 +400,7 @@
+ struct omap_overlay *ovl;
+ bool ilace = 0;
+ int outw, outh;
+- int r;
++ int r, pos_x = 0, pos_y = 0;
+ int num_planes_enabled = 0;
+
+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+@@ -451,11 +451,51 @@
+ else
+ outh = ovl->info.out_height;
+
++ if (ovl->id != OMAP_DSS_GFX && ovl->info.rotation != 0) {
++ /* We need to rotate pos_x and pos_y with respect
++ to OMAP_DSS_GFX */
++
++ u16 dw, dh;
++ display->get_resolution(display, &dw, &dh);
++
++ DSSDBG("plane pos was: (%d, %d), %dx%d, scr: %dx%d \n", ovl->info.pos_x,
++ ovl->info.pos_y, outw, outh, dw, dh);
++
++ switch (ovl->info.rotation) {
++ case 1:
++ pos_y = ovl->info.pos_x;
++ pos_x = dw - ovl->info.pos_y - outh;
++ break;
++ case 2:
++ pos_x = dw - ovl->info.pos_x - outw;
++ pos_y = dh - ovl->info.pos_y - outh;
++ break;
++ case 3:
++ pos_x = ovl->info.pos_y;
++ pos_y = dh - ovl->info.pos_x - outw;
++ break;
++ }
++
++ /* Check sanity */
++ if (ovl->info.rotation != 2) {
++ if (dw < pos_x + outh)
++ pos_x = pos_y = 0;
++ else if (dh < pos_y + outw)
++ pos_x = pos_y = 0;
++ } else if ( (dw < ovl->info.pos_x + outw) || (dh < ovl->info.pos_y + outh) )
++ pos_x = pos_y = 0;
++
++ DSSDBG("pos_x is %d, pos_y is %d\n", pos_x, pos_y);
++ } else {
++ pos_x = ovl->info.pos_x;
++ pos_y = ovl->info.pos_y;
++ }
++
+ r = dispc_setup_plane(ovl->id, ovl->manager->id,
+ ovl->info.paddr,
+ ovl->info.screen_width,
+- ovl->info.pos_x,
+- ovl->info.pos_y,
++ pos_x,
++ pos_y,
+ ovl->info.width,
+ ovl->info.height,
+ outw,
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -484,22 +484,7 @@
+
+ if (var->rotate != fbi->var.rotate) {
+ DBG("rotation changing\n");
+-
+ ofbi->rotation = var->rotate;
+-
+- if (abs(var->rotate - fbi->var.rotate) != 2) {
+- int tmp;
+- DBG("rotate changing 90/270 degrees. "
+- "swapping x/y res\n");
+-
+- tmp = var->yres;
+- var->yres = var->xres;
+- var->xres = tmp;
+-
+- tmp = var->yres_virtual;
+- var->yres_virtual = var->xres_virtual;
+- var->xres_virtual = tmp;
+- }
+ }
+
+ xres_min = OMAPFB_PLANE_XRES_MIN;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch
new file mode 100644
index 0000000000..7cb8a7d9bf
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch
@@ -0,0 +1,52 @@
+From 19a31ba4e8408ce80a4dbb96af489304c5e8128f Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Fri, 22 May 2009 18:58:33 -0700
+Subject: [PATCH] Fix scaling checks when rotation is 90 or 270 degrees.
+
+---
+ drivers/video/omap2/dss/dispc.c | 25 +++++++++++++++++++------
+ 1 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 088d353..77ca81b 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1508,16 +1508,29 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ }
+ } else {
+ /* video plane */
+-
++ u8 error = 0;
+ unsigned long fclk = 0;
+
+- if (out_width < width / maxdownscale ||
+- out_width > width * 8)
+- return -EINVAL;
++ if(rotation == 1 || rotation == 3)
++ {
++ if (out_width < height / maxdownscale || out_width > height * 8)
++ error = 1;
++
++ if (out_height < width / maxdownscale || out_height > width * 8)
++ error = 1;
++ } else {
++ if (out_width < width / maxdownscale || out_width > width * 8)
++ error = 1;
+
+- if (out_height < height / maxdownscale ||
+- out_height > height * 8)
++ if (out_height < height / maxdownscale || out_height > height * 8)
++ error = 1;
++ }
++
++ if(error != 0)
++ {
++ printk("DSS: Unable to down/up scale video plane\n");
+ return -EINVAL;
++ }
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+--
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch
new file mode 100644
index 0000000000..5a8c84471b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch
@@ -0,0 +1,131 @@
+Index: git/arch/arm/mach-omap2/board-omap3beagle.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
++++ git/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -154,6 +154,7 @@ static int beagle_twl_gpio_setup(struct
+ * power switch and overcurrent detect
+ */
+
++#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+ gpio_request(gpio + 1, "EHCI_nOC");
+ gpio_direction_input(gpio + 1);
+
+@@ -163,7 +164,7 @@ static int beagle_twl_gpio_setup(struct
+
+ /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+-
++#endif
+ return 0;
+ }
+
+Index: git/arch/arm/mach-omap2/usb-ehci.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/usb-ehci.c
++++ git/arch/arm/mach-omap2/usb-ehci.c
+@@ -147,9 +147,11 @@ static void setup_ehci_io_mux(void)
+
+ void __init usb_ehci_init(void)
+ {
++#if 0 /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+ /* Setup Pin IO MUX for EHCI */
+ if (cpu_is_omap34xx())
+ setup_ehci_io_mux();
++#endif
+
+ if (platform_device_register(&ehci_device) < 0) {
+ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+Index: git/drivers/usb/host/ehci-omap.c
+===================================================================
+--- git.orig/drivers/usb/host/ehci-omap.c
++++ git/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,25 @@
+ * to get the PHY state machine in working state
+ */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OMAP3_BEAGLE
++#define EXT_PHY_RESET_GPIO_PORT2 (147)
++#else
+ #define EXT_PHY_RESET_GPIO_PORT1 (57)
+ #define EXT_PHY_RESET_GPIO_PORT2 (61)
++#endif
+ #define EXT_PHY_RESET_DELAY (10)
+
++#define PHY_STP_PULLUP_ENABLE (0x10)
++#define PHY_STP_PULLUP_DISABLE (0x90)
++
+ /* ISSUE2:
+ * USBHOST supports External charge pump PHYs only
+ * Use the VBUS from Port1 to power VBUS of Port2 externally
+ * So use Port2 as the working ULPI port
+ */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+
+@@ -225,14 +234,43 @@ static int omap_start_ehc(struct platfor
+
+ #ifdef EXTERNAL_PHY_RESET
+ /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+ gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(EXT_PHY_RESET_DELAY);
+ #endif
+
++ /*
++ * The PHY register 0x7 - Interface Control register is
++ * configured to disable the integrated STP pull-up resistor
++ * used for interface protection.
++ *
++ * May not need to be here.
++ */
++ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (PHY_STP_PULLUP_DISABLE),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++ /* Force PHY to HS */
++ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (0x40),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+ /* Configure TLL for 60Mhz clk for ULPI */
+ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +345,9 @@ static int omap_start_ehc(struct platfor
+ * Hold the PHY in RESET for enough time till PHY is settled and ready
+ */
+ udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+
+@@ -393,7 +433,9 @@ static void omap_stop_ehc(struct platfor
+
+
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm
new file mode 100644
index 0000000000..76b746bf91
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm
@@ -0,0 +1,773 @@
+P3
+171 35
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 170 170 170 204 204 204 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 0 0 0
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 34 34 34 221 221 221 255 255 255 68 68 68 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 136 136 136 255 255 255 119 119 119 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 136 136 136 238 238 238 255 255 255 255 255 255
+187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 187 187 187
+255 255 255 255 255 255 255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0
+0 0 0 17 17 17 153 153 153 255 255 255 255 255 255 255 255 255 238 238 238 255 255 255
+85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 187 187 187 255 255 255 255 255 255
+238 238 238 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255
+255 255 255 255 255 255 68 68 68 0 0 0 119 119 119 187 187 187 255 255 255 255 255 255
+255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 85 85 85 238 238 238 255 255 255 51 51 51 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 17 17 17 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0
+0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+119 119 119 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255
+255 255 255 255 255 255 68 68 68 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0 0 0 0 204 204 204
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 153 153 153 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 153 153 153 255 255 255 170 170 170 17 17 17 0 0 0 0 0 0
+102 102 102 221 221 221 238 238 238 17 17 17 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0
+34 34 34 255 255 255 238 238 238 17 17 17 0 0 0 0 0 0 136 136 136 255 255 255
+85 85 85 0 0 0 34 34 34 255 255 255 221 221 221 102 102 102 0 0 0 0 0 0
+17 17 17 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+119 119 119 255 255 255 119 119 119 68 68 68 255 255 255 221 221 221 0 0 0 187 187 187
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 119 119 119 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 51 51 51 170 170 170
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0
+0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 187 187 187 136 136 136 51 51 51
+0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+68 68 68 255 255 255 187 187 187 153 153 153 255 255 255 255 255 255 85 85 85 238 238 238
+255 255 255 34 34 34 0 0 0 0 0 0 51 51 51 170 170 170 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 68 68 68 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0
+0 0 0 0 0 0 51 51 51 136 136 136 136 136 136 136 136 136 255 255 255 255 255 255
+102 102 102 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 238 238 238 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 238 238 238 221 221 221 238 238 238 255 255 255 255 255 255 204 204 204 255 255 255
+221 221 221 0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 170 170 170 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136
+0 0 0 0 0 0 51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0
+102 102 102 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 102 102 102 255 255 255
+204 204 204 0 0 0 51 51 51 255 255 255 204 204 204 85 85 85 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 204 204 204 255 255 255 255 255 255 170 170 170 221 221 221 255 255 255 255 255 255
+153 153 153 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0
+51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 51 51 51 0 0 0 0 0 0
+119 119 119 238 238 238 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+85 85 85 0 0 0 17 17 17 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 136 136 136 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+136 136 136 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 153 153 153 255 255 255 255 255 255 85 85 85 119 119 119 255 255 255 255 255 255
+102 102 102 0 0 0 0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255
+255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
+85 85 85 0 0 0 0 0 0 17 17 17 136 136 136 255 255 255 255 255 255 255 255 255
+255 255 255 187 187 187 136 136 136 17 17 17 0 0 0 0 0 0 119 119 119 255 255 255
+255 255 255 255 255 255 136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0
+102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 119 119 119
+0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 187 187 187 255 255 255 255 255 255
+255 255 255 255 255 255 136 136 136 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 102 102 102 255 255 255 221 221 221 0 0 0 17 17 17 238 238 238 255 255 255
+34 34 34 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255
+136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0
+0 0 0 0 0 0 0 0 0 17 17 17 170 170 170 255 255 255 255 255 255 255 255 255
+153 153 153 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch
new file mode 100644
index 0000000000..9000642104
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch
@@ -0,0 +1,9 @@
+--- git/arch/arm/plat-omap/include/mach/vmalloc.h 2009-06-09 15:14:54.000000000 -0700
++++ git/arch/arm/plat-omap/include/mach/vmalloc.h 2009-06-09 15:06:35.000000000 -0700
+@@ -17,5 +17,5 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+-#define VMALLOC_END (PAGE_OFFSET + 0x18000000)
++#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch
new file mode 100644
index 0000000000..14e0934468
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch
@@ -0,0 +1,11 @@
+--- a/drivers/video/backlight/backlight.c 2009-07-17 12:20:05.000000000 -0700
++++ b/drivers/video/backlight/backlight.c 2009-07-17 12:20:46.000000000 -0700
+@@ -205,7 +205,7 @@
+
+ static struct device_attribute bl_device_attributes[] = {
+ __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
+- __ATTR(brightness, 0644, backlight_show_brightness,
++ __ATTR(brightness, 0666, backlight_show_brightness,
+ backlight_store_brightness),
+ __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
+ NULL),
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch
new file mode 100644
index 0000000000..65b551f1de
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch
@@ -0,0 +1,10 @@
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -128,6 +128,7 @@ config MACH_OMAP3EVM
+ config MACH_OMAP3_BEAGLE
+ bool "OMAP3 BEAGLE board"
+ depends on ARCH_OMAP3 && ARCH_OMAP34XX
++ select BACKLIGHT_CLASS_DEVICE
+
+ config MACH_OVERO
+ bool "Gumstix Overo board"
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch
new file mode 100644
index 0000000000..ef8b3626bc
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch
@@ -0,0 +1,93 @@
+From db8f1eba9154789c45c6a92413bbbd94f5d9c7f5 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Wed, 29 Apr 2009 17:30:25 -0700
+Subject: [PATCH] Touch Book: turn on/off the class D amplifier depending on whether the
+ headphones are plugged into the jack or not.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ sound/soc/omap/omap3beagle.c | 33 +++++++++++++++++++++++++++++++++
+ 1 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
+index fd24a4a..1236638 100644
+--- a/sound/soc/omap/omap3beagle.c
++++ b/sound/soc/omap/omap3beagle.c
+@@ -20,7 +20,10 @@
+ */
+
+ #include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/soc.h>
+@@ -35,6 +38,9 @@
+ #include "omap-pcm.h"
+ #include "../codecs/twl4030.h"
+
++#define TB_HEADPHONE_GPIO 56
++#define TB_HEADPHONE_IRQ OMAP_GPIO_IRQ(TB_HEADPHONE_GPIO)
++
+ static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -103,6 +109,33 @@ static struct snd_soc_device omap3beagle_snd_devdata = {
+
+ static struct platform_device *omap3beagle_snd_device;
+
++static void jack_work_func(struct work_struct *wq)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++ struct snd_soc_codec *codec = socdev->codec;
++
++ snd_soc_dapm_sync(codec);
++}
++DECLARE_WORK(jack_work, jack_work_func);
++
++static irqreturn_t touchbook_headphone_event(int irq, void *snd)
++{
++ int status = gpio_get_value(TB_HEADPHONE_GPIO);
++ struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++ struct snd_soc_codec *codec = socdev->codec;
++
++ if(status) {
++ snd_soc_dapm_disable_pin(codec, "HFL");
++ snd_soc_dapm_disable_pin(codec, "HFR");
++ } else {
++ snd_soc_dapm_enable_pin(codec, "HFL");
++ snd_soc_dapm_enable_pin(codec, "HFR");
++ }
++
++ schedule_work(&jack_work);
++ return IRQ_HANDLED;
++}
++
+ static int __init omap3beagle_soc_init(void)
+ {
+ int ret;
+@@ -123,10 +156,22 @@ static int __init omap3beagle_soc_init(void)
+ omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
+ *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
++ /* Touch Book -- headphone jack sensor */
++ omap_set_gpio_debounce(TB_HEADPHONE_GPIO, 1);
++ omap_set_gpio_debounce_time(TB_HEADPHONE_GPIO, 0xff);
++
++ ret = request_irq(TB_HEADPHONE_IRQ, touchbook_headphone_event, IRQF_TRIGGER_RISING |
++ IRQF_TRIGGER_FALLING, "touchbook_headphone", omap3beagle_snd_device);
++ if (ret < 0)
++ goto err1;
++
+ ret = platform_device_add(omap3beagle_snd_device);
+ if (ret)
+ goto err1;
+
++ /* Detect headphone status */
++ touchbook_headphone_event(0, omap3beagle_snd_device);
++
+ return 0;
+
+ err1:
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff
new file mode 100644
index 0000000000..c7856731e5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff
@@ -0,0 +1,66 @@
+--- /tmp/board-omap3beagle.c 2009-07-01 01:06:44.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-01 01:06:50.000000000 +0200
+@@ -125,6 +125,13 @@
+ .wires = 8,
+ .gpio_wp = 29,
+ },
++ {
++ .mmc = 2,
++ .wires = 4,
++ .gpio_wp = 141,
++ .gpio_cd = 162,
++ .transceiver = true,
++ },
+ {} /* Terminator */
+ };
+
+@@ -132,6 +139,11 @@
+ .supply = "vmmc",
+ };
+
++static struct regulator_consumer_supply beagle_vmmc2_supply = {
++ .supply = "vmmc",
++};
++
++
+ static struct regulator_consumer_supply beagle_vsim_supply = {
+ .supply = "vmmc_aux",
+ };
+@@ -148,6 +160,7 @@
+
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
++ beagle_vmmc2_supply.dev = mmc[1].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+
+ /* REVISIT: need ehci-omap hooks for external VBUS
+@@ -209,6 +222,21 @@
+ .consumer_supplies = &beagle_vmmc1_supply,
+ };
+
++/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .min_uV = 2700000,
++ .max_uV = 3150000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
++ | REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
+ /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+ static struct regulator_init_data beagle_vsim = {
+ .constraints = {
+@@ -284,6 +312,7 @@
+ .gpio = &beagle_gpio_data,
+ .power = &beagle_power_data,
+ .vmmc1 = &beagle_vmmc1,
++ .vmmc2 = &beagle_vmmc2,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch
new file mode 100644
index 0000000000..f8353afee5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch
@@ -0,0 +1,87 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 7c3897f..0c62ace 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -491,9 +491,82 @@ static ssize_t ads7846_disable_store(struct device *dev,
+
+ static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+
++static ssize_t show_debounce_max(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_max);
++}
++
++static ssize_t show_debounce_tol(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_tol);
++}
++
++static ssize_t show_debounce_rep(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->debounce_rep);
++}
++
++static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->x_plate_ohms);
++}
++
++static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_max = i;
++ return count;
++}
++
++static ssize_t write_debounce_tol(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_tol = i;
++ return count;
++}
++
++static ssize_t write_debounce_rep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->debounce_rep = i;
++ return count;
++}
++
++static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i;
++
++ if (strict_strtoul(buf, 10, &i))
++ return -EINVAL;
++
++ ts->x_plate_ohms = i;
++ return count;
++}
++
++static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
++static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
++static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
++static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++
+ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_pen_down.attr,
+ &dev_attr_disable.attr,
++ &dev_attr_debounce_max.attr,
++ &dev_attr_debounce_tol.attr,
++ &dev_attr_debounce_rep.attr,
++ &dev_attr_x_plate_ohms.attr,
+ NULL,
+ };
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch
new file mode 100644
index 0000000000..6196716f23
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch
@@ -0,0 +1,108 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 0c62ace..8f6e83c 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -127,6 +127,7 @@ struct ads7846 {
+ void (*filter_cleanup)(void *data);
+ int (*get_pendown_state)(void);
+ int gpio_pendown;
++ int rotate;
+ };
+
+ /* leave chip selected when we're done, for quicker re-select? */
+@@ -511,6 +512,11 @@ static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *at
+ return sprintf(buf, "%u\n", ts->x_plate_ohms);
+ }
+
++static ssize_t show_rotate(struct device *dev, struct device_attribute *attr, char *buf) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ return sprintf(buf, "%u\n", ts->rotate);
++}
++
+ static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ unsigned long i;
+@@ -555,10 +561,22 @@ static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *a
+ return count;
+ }
+
++static ssize_t write_rotate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++ struct ads7846 *ts = dev_get_drvdata(dev);
++ unsigned long i = 0;
++
++ if (strict_strtoul(buf, 10, &i) || i > 3)
++ return -EINVAL;
++
++ ts->rotate = i;
++ return count;
++}
++
+ static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
+ static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
+ static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
+ static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++static DEVICE_ATTR(rotate, S_IRUGO | S_IWUGO, show_rotate, write_rotate);
+
+ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_pen_down.attr,
+@@ -567,6 +585,7 @@ static struct attribute *ads784x_attributes[] = {
+ &dev_attr_debounce_tol.attr,
+ &dev_attr_debounce_rep.attr,
+ &dev_attr_x_plate_ohms.attr,
++ &dev_attr_rotate.attr,
+ NULL,
+ };
+
+@@ -596,6 +615,8 @@ static void ads7846_rx(void *ads)
+ {
+ struct ads7846 *ts = ads;
+ struct ads7846_packet *packet = ts->packet;
++ struct ads7846_platform_data *pdata = ts->spi->dev.platform_data;
++
+ unsigned Rt;
+ u16 x, y, z1, z2;
+
+@@ -657,6 +678,7 @@ static void ads7846_rx(void *ads)
+ * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
+ */
+ if (Rt) {
++ int t;
+ struct input_dev *input = ts->input;
+
+ if (!ts->pendown) {
+@@ -666,6 +688,27 @@ static void ads7846_rx(void *ads)
+ dev_dbg(&ts->spi->dev, "DOWN\n");
+ #endif
+ }
++
++ switch(ts->rotate)
++ {
++ case 0:
++ x = pdata->x_max - x + pdata->x_min;
++ y = pdata->y_max - y + pdata->y_min;
++ break;
++ case 1:
++ t = x;
++ x = pdata->x_max - (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++ y = pdata->y_min + (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++ break;
++ case 2:
++ break;
++ case 3:
++ t = x;
++ x = pdata->x_min + (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++ y = pdata->y_max - (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++ break;
++ }
++
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+ input_report_abs(input, ABS_PRESSURE, Rt);
+@@ -980,6 +1023,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+
+ dev_set_drvdata(&spi->dev, ts);
+
++ ts->rotate = 0;
+ ts->packet = packet;
+ ts->spi = spi;
+ ts->input = input_dev;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch
new file mode 100644
index 0000000000..e2df6cf83d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch
@@ -0,0 +1,30 @@
+--- a/drivers/usb/core/hub.c 2009-07-28 08:47:00.000000000 -0700
++++ b/drivers/usb/core/hub.c 2009-07-28 08:32:20.000000000 -0700
+@@ -22,6 +22,7 @@
+ #include <linux/kthread.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/gpio.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+@@ -3129,9 +3130,18 @@
+ USB_PORT_FEAT_C_RESET);
+ }
+
+- if (connect_change)
++ if (connect_change) {
++ if(portstatus & USB_PORT_STAT_CONNECTION) {
++ gpio_set_value(176,0);
++ mdelay(25);
++ }
+ hub_port_connect_change(hub, i,
+ portstatus, portchange);
++ if(portstatus & USB_PORT_STAT_CONNECTION) {
++ mdelay(75);
++ gpio_set_value(176,1);
++ }
++ }
+ } /* end for i */
+
+ /* deal with hub status changes */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch
new file mode 100644
index 0000000000..2bcfbdcc2f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch
@@ -0,0 +1,36 @@
+--- git/drivers/usb/gadget/file_storage.c 2009-06-07 12:18:05.000000000 -0700
++++ git/drivers/usb/gadget/file_storage.c 2009-06-07 12:08:36.000000000 -0700
+@@ -283,8 +283,8 @@
+ *
+ * DO NOT REUSE THESE IDs with any other driver!! Ever!!
+ * Instead: allocate your own, using normal USB-IF procedures. */
+-#define DRIVER_VENDOR_ID 0x0525 // NetChip
+-#define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget
++#define DRIVER_VENDOR_ID 0xa110 // Always Innovating, Inc.
++#define DRIVER_PRODUCT_ID 0x0001 // Tablet product
+
+
+ /*
+@@ -2025,9 +2025,9 @@
+ {
+ u8 *buf = (u8 *) bh->buf;
+
+- static char vendor_id[] = "Linux ";
++ static char vendor_id[] = "AI, Inc.";
+ static char product_disk_id[] = "File-Stor Gadget";
+- static char product_cdrom_id[] = "File-CD Gadget ";
++ static char product_cdrom_id[] = "Touch Book ";
+
+ if (!fsg->curlun) { // Unsupported LUNs are okay
+ fsg->bad_lun_okay = 1;
+@@ -3671,8 +3671,8 @@
+ }
+ if (num_sectors < min_sectors) {
+ LINFO(curlun, "file too small: %s\n", filename);
+- rc = -ETOOSMALL;
+- goto out;
++// rc = -ETOOSMALL;
++// goto out;
+ }
+
+ get_file(filp);
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3evm/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/defconfig
new file mode 100644
index 0000000000..7a90a53edb
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/defconfig
@@ -0,0 +1,2217 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-omap1
+# Fri Feb 27 17:50:51 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+# CONFIG_OMAP_PM_SRF is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+CONFIG_MACH_OMAP3EVM=y
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+CONFIG_ARM_ERRATUM_451034=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=y
+CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTSDIO=y
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_93CX6=m
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+CONFIG_REALTEK_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_SMC911X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_PWRBUTTON=y
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_LP5521 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_SI21XX is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DVB_LGS8GL5 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=14
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_LTV350QV=y
+CONFIG_LCD_ILI9320=y
+# CONFIG_LCD_TDO24M is not set
+CONFIG_LCD_VGG2432A4=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3EVM=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+# CONFIG_LEDS_OMAP is not set
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+CONFIG_PREEMPT_TRACER=y
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-dss2.diff b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-dss2.diff
new file mode 100644
index 0000000000..60832e72ca
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-dss2.diff
@@ -0,0 +1,443 @@
+From: hvaibhav@ti.com
+To: linux-fbdev-devel@lists.sourceforge.net, linux-omap@vger.kernel.org
+Cc: Vaibhav Hiremath <hvaibhav@ti.com>
+Subject: [REVIEW PATCH] Added OMAP3EVM support on Tomis FBDEV/DSS Patches
+Date: Fri, 14 Nov 2008 12:02:32 +0530
+
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+
+Tested LCD, TV, DVI (480P) out on OMAP3EVM board.
+
+Please make sure that you change the option
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=7 and apply the
+Mans Rullgard clock patches to support set_rate and round_rate API.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/mach-omap2/board-omap3evm.c | 224 ++++++++++++++++++++++++++++++++--
+ drivers/video/omap2/Kconfig | 5 +
+ drivers/video/omap2/Makefile | 1 +
+ drivers/video/omap2/panel-omap3evm.c | 110 +++++++++++++++++
+ 5 files changed, 341 insertions(+), 53 deletions(-)
+ create mode 100644 drivers/video/omap2/panel-omap3evm.c
+
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index 42ab826..e244fa7 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -37,6 +37,8 @@
+ #include <mach/usb-ehci.h>
+ #include <mach/common.h>
+ #include <mach/mcspi.h>
++#include <mach/omapfb.h>
++#include <mach/display.h>
+
+ #include "sdram-micron-mt46h32m32lf-6.h"
+ #include "twl4030-generic-scripts.h"
+@@ -161,14 +163,215 @@ static int __init omap3_evm_i2c_init(void)
+ omap_register_i2c_bus(3, 400, NULL, 0);
+ return 0;
+ }
++static struct omap_fbmem_config evm_fbmem0_config = {
++ .size = 480*720*4,
++ .start = OMAPFB_MEMTYPE_SDRAM,
++};
+
+-static struct platform_device omap3_evm_lcd_device = {
+- .name = "omap3evm_lcd",
+- .id = -1,
++static struct omap_fbmem_config evm_fbmem1_config = {
++ .size = 480*720*4,
++ .start = OMAPFB_MEMTYPE_SDRAM,
+ };
+
+-static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
+- .ctrl_name = "internal",
++static struct omap_fbmem_config evm_fbmem2_config = {
++ .size = 480*720*4,
++ .start = OMAPFB_MEMTYPE_SDRAM,
++};
++#define LCD_PANEL_LR 2
++#define LCD_PANEL_UD 3
++#define LCD_PANEL_INI 152
++#define LCD_PANEL_ENABLE_GPIO 153
++#define LCD_PANEL_QVGA 154
++#define LCD_PANEL_RESB 155
++
++#define ENABLE_VDAC_DEDICATED 0x03
++#define ENABLE_VDAC_DEV_GRP 0x20
++#define ENABLE_VPLL2_DEDICATED 0x05
++#define ENABLE_VPLL2_DEV_GRP 0xE0
++
++#define TWL4030_GPIODATA_IN3 0x03
++#define TWL4030_GPIODATA_DIR3 0x06
++#define TWL4030_VPLL2_DEV_GRP 0x33
++#define TWL4030_VPLL2_DEDICATED 0x36
++
++static int lcd_enabled;
++static int dvi_enabled;
++
++static void __init evm_display_init(void)
++{
++ int r;
++ r = gpio_request(LCD_PANEL_LR, "lcd_panel_lr");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_LR\n");
++ return;
++ }
++ r = gpio_request(LCD_PANEL_UD, "lcd_panel_ud");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_UD\n");
++ goto err_1;
++ }
++
++ r = gpio_request(LCD_PANEL_INI, "lcd_panel_ini");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_INI\n");
++ goto err_2;
++ }
++ r = gpio_request(LCD_PANEL_RESB, "lcd_panel_resb");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_RESB\n");
++ goto err_3;
++ }
++ r = gpio_request(LCD_PANEL_QVGA, "lcd_panel_qvga");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_QVGA\n");
++ goto err_4;
++ }
++
++ gpio_direction_output(LCD_PANEL_LR, 0);
++ gpio_direction_output(LCD_PANEL_UD, 0);
++ gpio_direction_output(LCD_PANEL_INI, 0);
++ gpio_direction_output(LCD_PANEL_RESB, 0);
++ gpio_direction_output(LCD_PANEL_QVGA, 0);
++
++#define TWL_LED_LEDEN 0x00
++#define TWL_PWMA_PWMAON 0x00
++#define TWL_PWMA_PWMAOFF 0x01
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
++
++ gpio_direction_output(LCD_PANEL_RESB, 1);
++ gpio_direction_output(LCD_PANEL_INI, 1);
++ gpio_direction_output(LCD_PANEL_QVGA, 0);
++ gpio_direction_output(LCD_PANEL_LR, 1);
++ gpio_direction_output(LCD_PANEL_UD, 1);
++
++ return;
++
++err_4:
++ gpio_free(LCD_PANEL_RESB);
++err_3:
++ gpio_free(LCD_PANEL_INI);
++err_2:
++ gpio_free(LCD_PANEL_UD);
++err_1:
++ gpio_free(LCD_PANEL_LR);
++
++}
++
++static int panel_enable_lcd(struct omap_display *display)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
++ }
++ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
++ lcd_enabled = 1;
++ return 0;
++}
++
++static void panel_disable_lcd(struct omap_display *display)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEV_GRP);
++ }
++ gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
++ lcd_enabled = 0;
++}
++
++static struct omap_display_data evm_display_data = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .panel_name = "panel-sdp3430",
++ .u.dpi.data_lines = 16,
++ .panel_enable = panel_enable_lcd,
++ .panel_disable = panel_disable_lcd,
++};
++
++static int panel_enable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEDICATED, TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
++ return 0;
++}
++
++static void panel_disable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEV_GRP);
++}
++
++static struct omap_display_data evm_display_data_tv = {
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .name = "tv",
++ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .panel_enable = panel_enable_tv,
++ .panel_disable = panel_disable_tv,
++};
++
++
++static int panel_enable_dvi(struct omap_display *display)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
++ TWL4030_GPIODATA_IN3);
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
++ TWL4030_GPIODATA_DIR3);
++ dvi_enabled = 1;
++
++ return 0;
++}
++
++static void panel_disable_dvi(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
++ TWL4030_GPIODATA_IN3);
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
++ TWL4030_GPIODATA_DIR3);
++ dvi_enabled = 0;
++}
++
++
++static struct omap_display_data evm_display_data_dvi = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .panel_name = "panel-dvi",
++ .u.dpi.data_lines = 24,
++ .panel_enable = panel_enable_dvi,
++ .panel_disable = panel_disable_dvi,
++};
++
++static struct omap_dss_platform_data evm_dss_data = {
++ .num_displays = 3,
++ .displays = {
++ &evm_display_data,
++ &evm_display_data_dvi,
++ &evm_display_data_tv,
++ }
++};
++static struct platform_device evm_dss_device = {
++ .name = "omap-dss",
++ .id = -1,
++ .dev = {
++ .platform_data = &evm_dss_data,
++ },
+ };
+
+ static void ads7846_dev_init(void)
+@@ -227,11 +430,13 @@ static void __init omap3_evm_init_irq(void)
+
+ static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_evm_uart_config },
+- { OMAP_TAG_LCD, &omap3_evm_lcd_config },
++ { OMAP_TAG_FBMEM, &evm_fbmem0_config },
++ { OMAP_TAG_FBMEM, &evm_fbmem1_config },
++ { OMAP_TAG_FBMEM, &evm_fbmem2_config },
+ };
+
+ static struct platform_device *omap3_evm_devices[] __initdata = {
+- &omap3_evm_lcd_device,
++ &evm_dss_device,
+ &omap3evm_smc911x_device,
+ };
+
+@@ -250,8 +455,6 @@ static void __init omap3_evm_init(void)
+ omap3_evm_i2c_init();
+
+ platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
+- omap_board_config = omap3_evm_config;
+- omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
+
+ spi_register_board_info(omap3evm_spi_board_info,
+ ARRAY_SIZE(omap3evm_spi_board_info));
+@@ -262,10 +465,13 @@ static void __init omap3_evm_init(void)
+ usb_ehci_init();
+ omap3evm_flash_init();
+ ads7846_dev_init();
++ evm_display_init();
+ }
+
+ static void __init omap3_evm_map_io(void)
+ {
++ omap_board_config = omap3_evm_config;
++ omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
+ omap2_set_globals_343x();
+ omap2_map_common_io();
+ }
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+index 95691ad..8211ffd 100644
+--- a/drivers/video/omap2/Kconfig
++++ b/drivers/video/omap2/Kconfig
+@@ -51,4 +51,9 @@ config PANEL_SDP3430
+ help
+ SDP3430 LCD
+
++config PANEL_OMAP3EVM
++ tristate "OMAP3EVM Panel"
++ depends on OMAP2_DSS
++ help
++ OMAP3EVM LCD Panel
+ endmenu
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+index 73ab1c0..668e8c6 100644
+--- a/drivers/video/omap2/Makefile
++++ b/drivers/video/omap2/Makefile
+@@ -3,3 +3,4 @@ omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+
+ obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
+ obj-$(CONFIG_PANEL_SDP3430) += panel-sdp3430.o
++obj-$(CONFIG_PANEL_OMAP3EVM) += panel-omap3evm.o
+diff --git a/drivers/video/omap2/panel-omap3evm.c b/drivers/video/omap2/panel-omap3evm.c
+new file mode 100644
+index 0000000..4a00b02
+--- /dev/null
++++ b/drivers/video/omap2/panel-omap3evm.c
+@@ -0,0 +1,110 @@
++/*
++ * LCD panel support for the TI OMAP3EVM board
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Author: Vaibhav Hiremath <hvaibhav@ti.com>
++ *
++ * Derived from drivers/video/omap2/panel-sdp3430.c
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static int omap3evm_panel_init(struct omap_display *display)
++{
++ return 0;
++}
++
++static void omap3evm_panel_cleanup(struct omap_display *display)
++{
++}
++
++static int omap3evm_panel_enable(struct omap_display *display)
++{
++ int r = 0;
++
++ if (display->hw_config.panel_enable)
++ r = display->hw_config.panel_enable(display);
++
++ return r;
++}
++
++static void omap3evm_panel_disable(struct omap_display *display)
++{
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++}
++
++static int omap3evm_panel_suspend(struct omap_display *display)
++{
++ omap3evm_panel_disable(display);
++ return 0;
++}
++
++static int omap3evm_panel_resume(struct omap_display *display)
++{
++ return omap3evm_panel_enable(display);
++}
++
++static struct omap_panel omap3evm_panel = {
++ .owner = THIS_MODULE,
++ .name = "panel-evm",
++ .init = omap3evm_panel_init,
++ .cleanup = omap3evm_panel_cleanup,
++ .enable = omap3evm_panel_enable,
++ .disable = omap3evm_panel_disable,
++ .suspend = omap3evm_panel_suspend,
++ .resume = omap3evm_panel_resume,
++ /*.set_mode = omap3evm_set_mode, */
++
++ .timings = {
++ .pixel_clock = 26000,
++
++ .hsw = 4,
++ .hfp = 4,
++ .hbp = 40,
++
++ .vsw = 2,
++ .vfp = 2,
++ .vbp = 7,
++ },
++
++ .acb = 0x28,
++
++ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
++ OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
++
++ .x_res = 480,
++ .y_res = 640,
++ .bpp = 18,
++};
++
++
++static int __init omap3evm_panel_drv_init(void)
++{
++ omap_dss_register_panel(&omap3evm_panel);
++ return 0;
++}
++
++static void __exit omap3evm_panel_drv_exit(void)
++{
++ omap_dss_unregister_panel(&omap3evm_panel);
++}
++
++module_init(omap3evm_panel_drv_init);
++module_exit(omap3evm_panel_drv_exit);
++MODULE_LICENSE("GPL");
+--
+1.5.6
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-lcd-redtint.diff b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-lcd-redtint.diff
new file mode 100644
index 0000000000..54ea3c9f68
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap3evm/omap3evm-lcd-redtint.diff
@@ -0,0 +1,66 @@
+Message-ID: <c656a4d20809270046u341aec27k6d896d4b42e799d4@mail.gmail.com>
+Date: Sat, 27 Sep 2008 03:46:18 -0400
+From: "arun c" <arun.edarath@gmail.com>
+To: "Daniel Schaeffer" <daniel.schaeffer@timesys.com>
+Subject: Re: OMAP3EVM LCD red tint
+
+Hi Daniel Schaeffer
+
+On Fri, Sep 26, 2008 at 4:20 PM, Daniel Schaeffer
+<daniel.schaeffer@timesys.com> wrote:
+> Has anyone looked into why the LCD display on the OMAP3EVM is always tinted
+> red? I created a couple of color test images that I cat'ed to /dev/fb and it
+> looks like the blue color channel is completely ignored. I was testing on
+> v2.6.26-omap2 but is doesn't look like there have been any changes to the fb
+> driver since then so I'm assuming the issue is also present in the head of
+> the git tree.
+>
+> Regards,
+>
+> Daniel Schaeffer
+>
+
+Try the patch below(Remember that you may have to manually edit because
+this patch is against current HEAD)
+
+
+diff --git a/drivers/video/omap/lcd_omap3evm.c
+b/drivers/video/omap/lcd_omap3evm.c
+index a564ca5..821bafe 100644
+--- a/drivers/video/omap/lcd_omap3evm.c
++++ b/drivers/video/omap/lcd_omap3evm.c
+@@ -44,6 +44,8 @@
+ #define ENABLE_VDAC_DEV_GRP 0x20
+ #define ENABLE_VPLL2_DEDICATED 0x05
+ #define ENABLE_VPLL2_DEV_GRP 0xE0
++#define TWL4030_VPLL2_DEV_GRP 0x33
++#define TWL4030_VPLL2_DEDICATED 0x36
+
+ #define TWL_LED_LEDEN 0x00
+ #define TWL_PWMA_PWMAON 0x00
+@@ -86,12 +88,24 @@ static void omap3evm_panel_cleanup(struct lcd_panel *panel)
+
+ static int omap3evm_panel_enable(struct lcd_panel *panel)
+ {
++ if (omap_rev > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
++ }
+ omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 0);
+ return 0;
+ }
+
+ static void omap3evm_panel_disable(struct lcd_panel *panel)
+ {
++ if (omap_rev > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEV_GRP);
++ }
+ omap_set_gpio_dataout(LCD_PANEL_ENABLE_GPIO, 1);
+ }
+
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap5912osk/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap5912osk/defconfig
new file mode 100644
index 0000000000..3c334868ea
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/omap5912osk/defconfig
@@ -0,0 +1,1098 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc2-omap1
+# Tue Aug 21 23:22:37 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_OMAP_BOOT_TAG is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_STI is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MMU_FWK is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+# CONFIG_OMAP_DSP is not set
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+CONFIG_MACH_OMAP_OSK=y
+# CONFIG_OMAP_OSK_MISTRAL is not set
+# CONFIG_MACH_NOKIA770 is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_MACH_OMAP_APOLLON_PLUS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_OMAP_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x10400000,8M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_OMAP=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_TLV320AIC23 is not set
+# CONFIG_GPIOEXPANDER_OMAP is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/overo-cpufreq.diff b/recipes/linux/linux-omap-pm-2.6.29/overo-cpufreq.diff
new file mode 100644
index 0000000000..a51d8560e1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/overo-cpufreq.diff
@@ -0,0 +1,25 @@
+--- /tmp/board-overo.c 2009-04-23 12:46:21.000000000 +0200
++++ git/arch/arm/mach-omap2/board-overo.c 2009-04-23 12:46:31.000000000 +0200
+@@ -48,6 +48,12 @@
+ #include <mach/nand.h>
+ #include <mach/usb.h>
+
++#include <mach/omap-pm.h>
++#include <mach/clock.h>
++
++#include "pm.h"
++#include "omap3-opp.h"
++
+ #include "sdram-micron-mt46h32m32lf-6.h"
+ #include "twl4030-generic-scripts.h"
+ #include "mmc-twl4030.h"
+@@ -359,7 +365,8 @@
+
+ static void __init overo_init_irq(void)
+ {
+- omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL, NULL, NULL);
++ omap2_init_common_hw(mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
++ omap3_dsp_rate_table, omap3_l3_rate_table);
+ omap_init_irq();
+ omap_gpio_init();
+ }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/overo/defconfig b/recipes/linux/linux-omap-pm-2.6.29/overo/defconfig
new file mode 100644
index 0000000000..3d025659e3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/overo/defconfig
@@ -0,0 +1,2250 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Tue Apr 28 18:41:30 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=1
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+# CONFIG_OMAP_PM_NOOP is not set
+CONFIG_OMAP_PM_SRF=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+CONFIG_MACH_OVERO=y
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_LL is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_EEPROM_93CX6=m
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=m
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+# CONFIG_DVB_TDA8261 is not set
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+# CONFIG_DVB_TUNER_CX24113 is not set
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_SI21XX is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+# CONFIG_DVB_LGDT3304 is not set
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DVB_LGS8GL5 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=10
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=y
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_HRTIMER=m
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OVERO=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_MUSB_DEBUG=y
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+CONFIG_USB_SERIAL_OPTION=m
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_OMAP=y
+CONFIG_USB_OMAP=y
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+# CONFIG_LEDS_OMAP is not set
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/overo/ehci.patch b/recipes/linux/linux-omap-pm-2.6.29/overo/ehci.patch
new file mode 100644
index 0000000000..72c6b9bec3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/overo/ehci.patch
@@ -0,0 +1,113 @@
+diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
+index 489439d..2c6305b 100644
+--- a/arch/arm/mach-omap2/usb-ehci.c
++++ b/arch/arm/mach-omap2/usb-ehci.c
+@@ -152,9 +152,7 @@ static void setup_ehci_io_mux(void)
+
+ void __init usb_ehci_init(void)
+ {
+- /* Setup Pin IO MUX for EHCI */
+- if (cpu_is_omap34xx())
+- setup_ehci_io_mux();
++ /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+
+ if (platform_device_register(&ehci_device) < 0) {
+ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index 1b3266c..8472996 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,26 @@
+ * to get the PHY state machine in working state
+ */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OVERO
++#define EXT_PHY_RESET_GPIO_PORT2 (183)
++#else
+ #define EXT_PHY_RESET_GPIO_PORT1 (57)
+ #define EXT_PHY_RESET_GPIO_PORT2 (61)
++#endif
+ #define EXT_PHY_RESET_DELAY (10)
+
++#define PHY_STP_PULLUP_ENABLE (0x10)
++#define PHY_STP_PULLUP_DISABLE (0x90)
++
++
+ /* ISSUE2:
+ * USBHOST supports External charge pump PHYs only
+ * Use the VBUS from Port1 to power VBUS of Port2 externally
+ * So use Port2 as the working ULPI port
+ */
++#ifndef CONFIG_MACH_OVERO
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+
+@@ -225,14 +235,43 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+
+ #ifdef EXTERNAL_PHY_RESET
+ /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OVERO
+ gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+ gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+ gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(EXT_PHY_RESET_DELAY);
+ #endif
+
++ /*
++ * The PHY register 0x7 - Interface Control register is
++ * configured to disable the integrated STP pull-up resistor
++ * used for interface protection.
++ *
++ * May not need to be here.
++ */
++ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (PHY_STP_PULLUP_DISABLE),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++ /* Force PHY to HS */
++ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
++ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++ (0x40),
++ EHCI_INSNREG05_ULPI);
++
++ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+ /* Configure TLL for 60Mhz clk for ULPI */
+ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +346,9 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+ * Hold the PHY in RESET for enough time till PHY is settled and ready
+ */
+ udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OVERO
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+
+@@ -393,7 +434,9 @@ static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+
+
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OVERO
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
+
+--
+1.6.0.4.790.gaa14a
diff --git a/recipes/linux/linux-omap-pm-2.6.29/read_die_ids.patch b/recipes/linux/linux-omap-pm-2.6.29/read_die_ids.patch
new file mode 100644
index 0000000000..3f6c930cc1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/read_die_ids.patch
@@ -0,0 +1,23 @@
+OMAP2/3 TAP: enable debug messages
+
+From: Paul Walmsley <paul@pwsan.com>
+
+This patch causes the OMAP2/3 chip ID code to display the full DIE_ID registers at boot.
+
+---
+
+ arch/arm/mach-omap2/id.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
+index c7f9ab7..a154b5e 100644
+--- a/arch/arm/mach-omap2/id.c
++++ b/arch/arm/mach-omap2/id.c
+@@ -10,6 +10,7 @@
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
++#define DEBUG
+
+ #include <linux/module.h>
+ #include <linux/kernel.h>
diff --git a/recipes/linux/linux-omap-pm-2.6.29/register-all-OPPs.diff b/recipes/linux/linux-omap-pm-2.6.29/register-all-OPPs.diff
new file mode 100644
index 0000000000..95e6b9bfab
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/register-all-OPPs.diff
@@ -0,0 +1,12 @@
+--- /tmp/clock34xx.c 2009-02-18 13:51:18.000000000 +0100
++++ git/arch/arm/mach-omap2/clock34xx.c 2009-02-18 13:51:51.000000000 +0100
+@@ -698,8 +698,7 @@
+ if (!mpu_opps)
+ return;
+
+- /* Avoid registering the 120% Overdrive with CPUFreq */
+- prcm = mpu_opps + MAX_VDD1_OPP - 1;
++ prcm = mpu_opps + MAX_VDD1_OPP;
+ for (; prcm->rate; prcm--) {
+ freq_table[i].index = i;
+ freq_table[i].frequency = prcm->rate / 1000;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/timer-suppression.patch b/recipes/linux/linux-omap-pm-2.6.29/timer-suppression.patch
new file mode 100644
index 0000000000..04362c96e3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/timer-suppression.patch
@@ -0,0 +1,43 @@
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index b854a89..26f5569 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -253,6 +253,16 @@ void tick_nohz_stop_sched_tick(void)
+
+ /* Schedule the tick, if we are at least one jiffie off */
+ if ((long)delta_jiffies >= 1) {
++ /*
++ * calculate the expiry time for the next timer wheel
++ * timer
++ */
++ expires = ktime_add_ns(last_update, tick_period.tv64 *
++ delta_jiffies);
++
++ /* Skip reprogram of event if its not changed */
++ if(ts->tick_stopped && ktime_equal(expires, dev->next_event))
++ goto out2;
+
+ if (delta_jiffies > 1)
+ cpu_set(cpu, nohz_cpu_mask);
+@@ -304,12 +314,7 @@ void tick_nohz_stop_sched_tick(void)
+ goto out;
+ }
+
+- /*
+- * calculate the expiry time for the next timer wheel
+- * timer
+- */
+- expires = ktime_add_ns(last_update, tick_period.tv64 *
+- delta_jiffies);
++ /* Mark expiries */
+ ts->idle_expires = expires;
+
+ if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
+@@ -328,6 +333,7 @@ void tick_nohz_stop_sched_tick(void)
+ tick_do_update_jiffies64(ktime_get());
+ cpu_clear(cpu, nohz_cpu_mask);
+ }
++out2:
+ raise_softirq_irqoff(TIMER_SOFTIRQ);
+ out:
+ ts->next_jiffies = next_jiffies;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/touchscreen.patch b/recipes/linux/linux-omap-pm-2.6.29/touchscreen.patch
new file mode 100644
index 0000000000..2325c401e4
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/touchscreen.patch
@@ -0,0 +1,22 @@
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index d8109ae..f8ce669 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -128,8 +128,16 @@ static int ads7846_get_pendown_state(void)
+ }
+
+ struct ads7846_platform_data ads7846_config = {
++ .x_max = 0x0fff,
++ .y_max = 0x0fff,
++ .x_plate_ohms = 180,
++ .pressure_max = 255,
++ .debounce_max = 10,
++ .debounce_tol = 3,
++ .debounce_rep = 1,
+ .get_pendown_state = ads7846_get_pendown_state,
+ .keep_vref_on = 1,
++ .settle_delay_usecs = 150,
+ };
+
+ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/usbttyfix.patch b/recipes/linux/linux-omap-pm-2.6.29/usbttyfix.patch
new file mode 100644
index 0000000000..997705a31b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/usbttyfix.patch
@@ -0,0 +1,29 @@
+To get USB HOST mode working on USB OTG Port with USB TTY enabled U-boot
+
+Signed-off-by: Syed Mohammed Khasim <khasim@ti.com>
+---
+--- linux-2.6.git/drivers/usb/musb/omap2430.c 2009-01-19 22:42:18.000000000 +0530
++++ linux-2.6.git/drivers/usb/musb/omap2430.c 2009-02-19 12:45:22.000000000 +0530
+@@ -33,6 +33,7 @@
+ #include <linux/list.h>
+ #include <linux/clk.h>
+ #include <linux/io.h>
++#include <linux/i2c/twl4030.h>
+
+ #include <asm/mach-types.h>
+ #include <mach/hardware.h>
+@@ -233,6 +234,14 @@ int __init musb_platform_init(struct mus
+ omap_cfg_reg(AE5_2430_USB0HS_STP);
+ #endif
+
++ /* Reset MUSB Controller */
++ omap_writel(SOFTRST,OTG_SYSCONFIG);
++
++#if defined(CONFIG_TWL4030_USB)
++ /* Reset the TWL USB PHY */
++ twl4030_i2c_write_u8(TWL4030_MODULE_USB, 0x60, 0x4);
++#endif
++
+ musb->xceiv = *x;
+ musb_platform_resume(musb);
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/01-vfp-pm.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/01-vfp-pm.patch
new file mode 100644
index 0000000000..70d4d1efc5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/01-vfp-pm.patch
@@ -0,0 +1,128 @@
+From: Ben Dooks <ben-linux@fluff.org>
+Date: Thu, 18 Dec 2008 10:26:54 +0000 (+0100)
+Subject: 5349/1: VFP: Add PM code to save and restore current VFP state
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=d504d72ad38e54b5feda67e956834348d6a500e1
+
+5349/1: VFP: Add PM code to save and restore current VFP state
+
+[ARM] 5349/1: VFP: Add PM code to save and restore current VFP state
+
+When CONFIG_PM is selected, the VFP code does not have any handler
+installed to deal with either saving the VFP state of the current
+task, nor does it do anything to try and restore the VFP after a
+resume.
+
+On resume, the VFP will have been reset and the co-processor access
+control registers are in an indeterminate state (very probably the
+CP10 and CP11 the VFP uses will have been disabled by the ARM core
+reset). When this happens, resume will break as soon as it tries to
+unfreeze the tasks and restart scheduling.
+
+Add a sys device to allow us to hook the suspend call to save the
+current thread state if the thread is using VFP and a resume hook
+which restores the CP10/CP11 access and ensures the VFP is disabled
+so that the lazy swapping will take place on next access.
+
+Signed-off-by: Ben Dooks <ben-linux@fluff.org>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
+index c85860b..8de86e4 100644
+--- a/arch/arm/vfp/vfp.h
++++ b/arch/arm/vfp/vfp.h
+@@ -377,6 +377,6 @@ struct op {
+ u32 flags;
+ };
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ extern void vfp_save_state(void *location, u32 fpexc);
+ #endif
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index a62dcf7..b21f43f 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -166,7 +166,7 @@ process_exception:
+ @ retry the faulted instruction
+ ENDPROC(vfp_support_entry)
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ ENTRY(vfp_save_state)
+ @ Save the current VFP state
+ @ r0 - save location
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 67ca340..9f476a1 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -322,6 +322,61 @@ static void vfp_enable(void *unused)
+ set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
+ }
+
++#ifdef CONFIG_PM
++#include <linux/sysdev.h>
++
++static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
++{
++ struct thread_info *ti = current_thread_info();
++ u32 fpexc = fmrx(FPEXC);
++
++ /* if vfp is on, then save state for resumption */
++ if (fpexc & FPEXC_EN) {
++ printk(KERN_DEBUG "%s: saving vfp state\n", __func__);
++ vfp_save_state(&ti->vfpstate, fpexc);
++
++ /* disable, just in case */
++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
++ }
++
++ /* clear any information we had about last context state */
++ memset(last_VFP_context, 0, sizeof(last_VFP_context));
++
++ return 0;
++}
++
++static int vfp_pm_resume(struct sys_device *dev)
++{
++ /* ensure we have access to the vfp */
++ vfp_enable(NULL);
++
++ /* and disable it to ensure the next usage restores the state */
++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
++
++ return 0;
++}
++
++static struct sysdev_class vfp_pm_sysclass = {
++ .name = "vfp",
++ .suspend = vfp_pm_suspend,
++ .resume = vfp_pm_resume,
++};
++
++static struct sys_device vfp_pm_sysdev = {
++ .cls = &vfp_pm_sysclass,
++};
++
++static void vfp_pm_init(void)
++{
++ sysdev_class_register(&vfp_pm_sysclass);
++ sysdev_register(&vfp_pm_sysdev);
++}
++
++
++#else
++static inline void vfp_pm_init(void) { }
++#endif /* CONFIG_PM */
++
+ #include <linux/smp.h>
+
+ /*
+@@ -365,6 +420,7 @@ static int __init vfp_init(void)
+ vfp_vector = vfp_support_entry;
+
+ thread_register_notifier(&vfp_notifier_block);
++ vfp_pm_init();
+
+ /*
+ * We detected VFP, and the support code is
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/02-vfp-ptrace.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/02-vfp-ptrace.patch
new file mode 100644
index 0000000000..feba206f95
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/02-vfp-ptrace.patch
@@ -0,0 +1,231 @@
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Wed, 11 Feb 2009 11:12:56 +0000 (+0100)
+Subject: 5387/1: Add ptrace VFP support on ARM
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4dd5beb2244f15c895aba46474bd89545327d1a6
+
+5387/1: Add ptrace VFP support on ARM
+
+[ARM] 5387/1: Add ptrace VFP support on ARM
+
+This patch adds ptrace support for setting and getting the VFP registers
+using PTRACE_SETVFPREGS and PTRACE_GETVFPREGS. The user_vfp structure
+defined in asm/user.h contains 32 double registers (to cover VFPv3 and
+Neon hardware) and the FPSCR register.
+
+Cc: Paul Brook <paul@codesourcery.com>
+Cc: Daniel Jacobowitz <dan@codesourcery.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
+index 7319261..236a06b 100644
+--- a/arch/arm/include/asm/ptrace.h
++++ b/arch/arm/include/asm/ptrace.h
+@@ -27,6 +27,8 @@
+ /* PTRACE_SYSCALL is 24 */
+ #define PTRACE_GETCRUNCHREGS 25
+ #define PTRACE_SETCRUNCHREGS 26
++#define PTRACE_GETVFPREGS 27
++#define PTRACE_SETVFPREGS 28
+
+ /*
+ * PSR bits
+diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
+index 68b9ec8..b9dc8a8 100644
+--- a/arch/arm/include/asm/thread_info.h
++++ b/arch/arm/include/asm/thread_info.h
+@@ -113,6 +113,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
+ extern void iwmmxt_task_release(struct thread_info *);
+ extern void iwmmxt_task_switch(struct thread_info *);
+
++extern void vfp_sync_state(struct thread_info *thread);
++
+ #endif
+
+ /*
+diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h
+index 825c1e7..df95e05 100644
+--- a/arch/arm/include/asm/user.h
++++ b/arch/arm/include/asm/user.h
+@@ -81,4 +81,13 @@ struct user{
+ #define HOST_TEXT_START_ADDR (u.start_code)
+ #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+
++/*
++ * User specific VFP registers. If only VFPv2 is present, registers 16 to 31
++ * are ignored by the ptrace system call.
++ */
++struct user_vfp {
++ unsigned long long fpregs[32];
++ unsigned long fpscr;
++};
++
+ #endif /* _ARM_USER_H */
+diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
+index df653ea..89882a1 100644
+--- a/arch/arm/kernel/ptrace.c
++++ b/arch/arm/kernel/ptrace.c
+@@ -653,6 +653,54 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp)
+ }
+ #endif
+
++#ifdef CONFIG_VFP
++/*
++ * Get the child VFP state.
++ */
++static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
++{
++ struct thread_info *thread = task_thread_info(tsk);
++ union vfp_state *vfp = &thread->vfpstate;
++ struct user_vfp __user *ufp = data;
++
++ vfp_sync_state(thread);
++
++ /* copy the floating point registers */
++ if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
++ sizeof(vfp->hard.fpregs)))
++ return -EFAULT;
++
++ /* copy the status and control register */
++ if (put_user(vfp->hard.fpscr, &ufp->fpscr))
++ return -EFAULT;
++
++ return 0;
++}
++
++/*
++ * Set the child VFP state.
++ */
++static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
++{
++ struct thread_info *thread = task_thread_info(tsk);
++ union vfp_state *vfp = &thread->vfpstate;
++ struct user_vfp __user *ufp = data;
++
++ vfp_sync_state(thread);
++
++ /* copy the floating point registers */
++ if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
++ sizeof(vfp->hard.fpregs)))
++ return -EFAULT;
++
++ /* copy the status and control register */
++ if (get_user(vfp->hard.fpscr, &ufp->fpscr))
++ return -EFAULT;
++
++ return 0;
++}
++#endif
++
+ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+ int ret;
+@@ -775,6 +823,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ break;
+ #endif
+
++#ifdef CONFIG_VFP
++ case PTRACE_GETVFPREGS:
++ ret = ptrace_getvfpregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_SETVFPREGS:
++ ret = ptrace_setvfpregs(child, (void __user *)data);
++ break;
++#endif
++
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
+index 8de86e4..c8c98dd 100644
+--- a/arch/arm/vfp/vfp.h
++++ b/arch/arm/vfp/vfp.h
+@@ -377,6 +377,4 @@ struct op {
+ u32 flags;
+ };
+
+-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ extern void vfp_save_state(void *location, u32 fpexc);
+-#endif
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index b21f43f..902d396 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -166,7 +166,6 @@ process_exception:
+ @ retry the faulted instruction
+ ENDPROC(vfp_support_entry)
+
+-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+ ENTRY(vfp_save_state)
+ @ Save the current VFP state
+ @ r0 - save location
+@@ -181,7 +180,6 @@ ENTRY(vfp_save_state)
+ stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
+ mov pc, lr
+ ENDPROC(vfp_save_state)
+-#endif
+
+ last_VFP_context_address:
+ .word last_VFP_context
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 9f476a1..7e12390 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -377,6 +377,55 @@ static void vfp_pm_init(void)
+ static inline void vfp_pm_init(void) { }
+ #endif /* CONFIG_PM */
+
++/*
++ * Synchronise the hardware VFP state of a thread other than current with the
++ * saved one. This function is used by the ptrace mechanism.
++ */
++#ifdef CONFIG_SMP
++void vfp_sync_state(struct thread_info *thread)
++{
++ /*
++ * On SMP systems, the VFP state is automatically saved at every
++ * context switch. We mark the thread VFP state as belonging to a
++ * non-existent CPU so that the saved one will be reloaded when
++ * needed.
++ */
++ thread->vfpstate.hard.cpu = NR_CPUS;
++}
++#else
++void vfp_sync_state(struct thread_info *thread)
++{
++ unsigned int cpu = get_cpu();
++ u32 fpexc = fmrx(FPEXC);
++
++ /*
++ * If VFP is enabled, the previous state was already saved and
++ * last_VFP_context updated.
++ */
++ if (fpexc & FPEXC_EN)
++ goto out;
++
++ if (!last_VFP_context[cpu])
++ goto out;
++
++ /*
++ * Save the last VFP state on this CPU.
++ */
++ fmxr(FPEXC, fpexc | FPEXC_EN);
++ vfp_save_state(last_VFP_context[cpu], fpexc);
++ fmxr(FPEXC, fpexc);
++
++ /*
++ * Set the context to NULL to force a reload the next time the thread
++ * uses the VFP.
++ */
++ last_VFP_context[cpu] = NULL;
++
++out:
++ put_cpu();
++}
++#endif
++
+ #include <linux/smp.h>
+
+ /*
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/03-vfp-corruption.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/03-vfp-corruption.patch
new file mode 100644
index 0000000000..216d4f5eaa
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/03-vfp-corruption.patch
@@ -0,0 +1,136 @@
+From: George G. Davis <gdavis@mvista.com>
+Date: Wed, 1 Apr 2009 18:27:18 +0000 (+0100)
+Subject: 5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4f7720780dc4a298a6d59c0ec39f7687022cc36f
+
+5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+
+[ARM] 5440/1: Fix VFP state corruption due to preemption during VFP exceptions
+
+We've observed that ARM VFP state can be corrupted during VFP exception
+handling when PREEMPT is enabled. The exact conditions are difficult
+to reproduce but appear to occur during VFP exception handling when a
+task causes a VFP exception which is handled via VFP_bounce and is then
+preempted by yet another task which in turn causes yet another VFP
+exception. Since the VFP_bounce code is not preempt safe, VFP state then
+becomes corrupt. In order to prevent preemption from occuring while
+handling a VFP exception, this patch disables preemption while handling
+VFP exceptions.
+
+Signed-off-by: George G. Davis <gdavis@mvista.com>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+
+diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
+index ba592a9..a2bed62 100644
+--- a/arch/arm/vfp/entry.S
++++ b/arch/arm/vfp/entry.S
+@@ -15,13 +15,16 @@
+ * r10 = thread_info structure
+ * lr = failure return
+ */
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/assembler.h>
++#include <asm/thread_info.h>
+ #include <asm/vfpmacros.h>
++#include "../kernel/entry-header.S"
+
+ ENTRY(do_vfp)
++#ifdef CONFIG_PREEMPT
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ add r11, r4, #1 @ increment it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ enable_irq
+ ldr r4, .LCvfp
+ ldr r11, [r10, #TI_CPU] @ CPU number
+@@ -30,6 +33,12 @@ ENTRY(do_vfp)
+ ENDPROC(do_vfp)
+
+ ENTRY(vfp_null_entry)
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, lr
+ ENDPROC(vfp_null_entry)
+
+@@ -41,6 +50,12 @@ ENDPROC(vfp_null_entry)
+
+ __INIT
+ ENTRY(vfp_testing_entry)
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ ldr r0, VFP_arch_address
+ str r5, [r0] @ known non-zero value
+ mov pc, r9 @ we have handled the fault
+diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
+index 902d396..ea0a156 100644
+--- a/arch/arm/vfp/vfphw.S
++++ b/arch/arm/vfp/vfphw.S
+@@ -131,6 +131,12 @@ check_for_exception:
+ VFPFMXR FPEXC, r1 @ restore FPEXC last
+ sub r2, r2, #4
+ str r2, [sp, #S_PC] @ retry the instruction
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, r9 @ we think we have handled things
+
+
+@@ -149,6 +155,12 @@ look_for_VFP_exceptions:
+ @ not recognised by VFP
+
+ DBGSTR "not VFP"
++#ifdef CONFIG_PREEMPT
++ get_thread_info r10
++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count
++ sub r11, r4, #1 @ decrement it
++ str r11, [r10, #TI_PREEMPT]
++#endif
+ mov pc, lr
+
+ process_exception:
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 75457b3..01599c4 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -266,7 +266,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ * on VFP subarch 1.
+ */
+ vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
+- return;
++ goto exit;
+ }
+
+ /*
+@@ -297,7 +297,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
+ */
+ if (fpexc ^ (FPEXC_EX | FPEXC_FP2V))
+- return;
++ goto exit;
+
+ /*
+ * The barrier() here prevents fpinst2 being read
+@@ -310,6 +310,8 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
+ if (exceptions)
+ vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
++ exit:
++ preempt_enable();
+ }
+
+ static void vfp_enable(void *unused)
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch
new file mode 100644
index 0000000000..221b2774a1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/04-vfp-threads.patch
@@ -0,0 +1,98 @@
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Jul 2009 21:20:59 +0000 (+0300)
+Subject: So far vfp_sync_state worked only for threads other than the current one. This worked...
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=23671113997664ae55c8132fc4a56e676d5b46c7
+
+So far vfp_sync_state worked only for threads other than the current one. This worked for tracing other threads, but not for PTRACE_TRACEME. Syncing for the current thread will also be needed by an upcoming patch adding support for VFP context save / restore around signal handlers.
+
+For SMP we need get_cpu now, since we have to protect the FPEXC
+register, other than this things remained the same for threads other
+than the current.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+
+diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
+index 01599c4..969b77a 100644
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -380,12 +380,19 @@ static inline void vfp_pm_init(void) { }
+ #endif /* CONFIG_PM */
+
+ /*
+- * Synchronise the hardware VFP state of a thread other than current with the
+- * saved one. This function is used by the ptrace mechanism.
++ * Synchronise the hardware VFP state of a thread with the saved one.
++ * This function is used by the ptrace mechanism and the signal handler path.
+ */
+-#ifdef CONFIG_SMP
+ void vfp_sync_state(struct thread_info *thread)
+ {
++ unsigned int cpu = get_cpu();
++ u32 fpexc = fmrx(FPEXC);
++ int vfp_enabled;
++ int self;
++
++ vfp_enabled = fpexc & FPEXC_EN;
++ self = thread == current_thread_info();
++#ifdef CONFIG_SMP
+ /*
+ * On SMP systems, the VFP state is automatically saved at every
+ * context switch. We mark the thread VFP state as belonging to a
+@@ -393,18 +400,22 @@ void vfp_sync_state(struct thread_info *thread)
+ * needed.
+ */
+ thread->vfpstate.hard.cpu = NR_CPUS;
+-}
+-#else
+-void vfp_sync_state(struct thread_info *thread)
+-{
+- unsigned int cpu = get_cpu();
+- u32 fpexc = fmrx(FPEXC);
+-
+ /*
+- * If VFP is enabled, the previous state was already saved and
+- * last_VFP_context updated.
++ * Only the current thread's saved VFP context can be out-of-date.
++ * For others there is nothing else to do, since we already ensured
++ * force loading above.
+ */
+- if (fpexc & FPEXC_EN)
++ if (!self)
++ goto out;
++#endif
++ /*
++ * If the VFP is enabled only the current thread's saved VFP
++ * context can get out-of-date. For other threads the context
++ * was updated when the current thread started to use the VFP.
++ * This also means that the context will be reloaded next time
++ * the thread uses the VFP, so no need to enforce it.
++ */
++ if (vfp_enabled && !self)
+ goto out;
+
+ if (!last_VFP_context[cpu])
+@@ -413,8 +424,14 @@ void vfp_sync_state(struct thread_info *thread)
+ /*
+ * Save the last VFP state on this CPU.
+ */
+- fmxr(FPEXC, fpexc | FPEXC_EN);
++ if (!vfp_enabled)
++ fmxr(FPEXC, fpexc | FPEXC_EN);
+ vfp_save_state(last_VFP_context[cpu], fpexc);
++ /*
++ * Disable VFP in case it was enabled so that the force reload
++ * can happen.
++ */
++ fpexc &= ~FPEXC_EN;
+ fmxr(FPEXC, fpexc);
+
+ /*
+@@ -426,7 +443,6 @@ void vfp_sync_state(struct thread_info *thread)
+ out:
+ put_cpu();
+ }
+-#endif
+
+ #include <linux/smp.h>
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/vfp/05-vfp-signal-handlers.patch b/recipes/linux/linux-omap-pm-2.6.29/vfp/05-vfp-signal-handlers.patch
new file mode 100644
index 0000000000..f648188584
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.29/vfp/05-vfp-signal-handlers.patch
@@ -0,0 +1,148 @@
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Jul 2009 21:21:06 +0000 (+0300)
+Subject: Signal handlers can use floating point, so prevent them to corrupt the main thread...
+X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4daa6b5d833c401a9de6f136ea23daa971fc4fdc
+
+Signal handlers can use floating point, so prevent them to corrupt the main thread's VFP context. So far there were two signal stack frame formats defined based on the VFP implementation, but recently a new user struct was added for ptrace that covers all possibilities, so use it for the signal stack too.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+
+diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
+index bf65e9f..5534653 100644
+--- a/arch/arm/include/asm/ucontext.h
++++ b/arch/arm/include/asm/ucontext.h
+@@ -59,23 +59,19 @@ struct iwmmxt_sigframe {
+ #endif /* CONFIG_IWMMXT */
+
+ #ifdef CONFIG_VFP
+-#if __LINUX_ARM_ARCH__ < 6
+-/* For ARM pre-v6, we use fstmiax and fldmiax. This adds one extra
+- * word after the registers, and a word of padding at the end for
+- * alignment. */
+ #define VFP_MAGIC 0x56465001
+-#define VFP_STORAGE_SIZE 152
+-#else
+-#define VFP_MAGIC 0x56465002
+-#define VFP_STORAGE_SIZE 144
+-#endif
+
+ struct vfp_sigframe
+ {
+ unsigned long magic;
+ unsigned long size;
+- union vfp_state storage;
+-};
++ struct user_vfp ufp;
++ unsigned long reserved;
++} __attribute__((__aligned__(8)));
++
++/* 8 byte for magic and size, 260 byte for ufp and 4 byte padding */
++#define VFP_STORAGE_SIZE sizeof(struct vfp_sigframe)
++
+ #endif /* CONFIG_VFP */
+
+ /*
+@@ -91,7 +87,7 @@ struct aux_sigframe {
+ #ifdef CONFIG_IWMMXT
+ struct iwmmxt_sigframe iwmmxt;
+ #endif
+-#if 0 && defined CONFIG_VFP /* Not yet saved. */
++#ifdef CONFIG_VFP
+ struct vfp_sigframe vfp;
+ #endif
+ /* Something that isn't a valid magic number for any coprocessor. */
+diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
+index 80b8b5c..a5ef7f5 100644
+--- a/arch/arm/kernel/signal.c
++++ b/arch/arm/kernel/signal.c
+@@ -196,6 +196,67 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
+
+ #endif
+
++#ifdef CONFIG_VFP
++
++static int preserve_vfp_context(struct vfp_sigframe __user *frame)
++{
++ struct thread_info *thread = current_thread_info();
++ struct vfp_hard_struct *h = &thread->vfpstate.hard;
++ const unsigned long magic = VFP_MAGIC;
++ const unsigned long size = VFP_STORAGE_SIZE;
++ int err = 0;
++
++ vfp_sync_state(thread);
++ __put_user_error(magic, &frame->magic, err);
++ __put_user_error(size, &frame->size, err);
++
++ /*
++ * Copy the floating point registers. There can be unused
++ * registers see asm/hwcap.h for details.
++ */
++ err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
++ sizeof(h->fpregs));
++ /*
++ * Copy the status and control register.
++ */
++ __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
++
++ return err ? -EFAULT : 0;
++}
++
++static int restore_vfp_context(struct vfp_sigframe __user *frame)
++{
++ struct thread_info *thread = current_thread_info();
++ struct vfp_hard_struct *h = &thread->vfpstate.hard;
++ unsigned long magic;
++ unsigned long size;
++ int err = 0;
++
++ vfp_sync_state(thread);
++ __get_user_error(magic, &frame->magic, err);
++ __get_user_error(size, &frame->size, err);
++
++ if (err)
++ return -EFAULT;
++ if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
++ return -EINVAL;
++
++ /*
++ * Copy the floating point registers. There can be unused
++ * registers see asm/hwcap.h for details.
++ */
++ err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
++ sizeof(h->fpregs));
++ /*
++ * Copy the status and control register.
++ */
++ __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
++
++ return err ? -EFAULT : 0;
++}
++
++#endif
++
+ /*
+ * Do a signal return; undo the signal stack. These are aligned to 64-bit.
+ */
+@@ -254,8 +315,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
+ err |= restore_iwmmxt_context(&aux->iwmmxt);
+ #endif
+ #ifdef CONFIG_VFP
+-// if (err == 0)
+-// err |= vfp_restore_state(&sf->aux.vfp);
++ if (err == 0)
++ err |= restore_vfp_context(&aux->vfp);
+ #endif
+
+ return err;
+@@ -369,8 +430,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
+ err |= preserve_iwmmxt_context(&aux->iwmmxt);
+ #endif
+ #ifdef CONFIG_VFP
+-// if (err == 0)
+-// err |= vfp_save_state(&sf->aux.vfp);
++ if (err == 0)
++ err |= preserve_vfp_context(&aux->vfp);
+ #endif
+ __put_user_error(0, &aux->end_magic, err);
+
diff --git a/recipes/linux/linux-omap-pm-2.6.31/beagleboard/defconfig b/recipes/linux/linux-omap-pm-2.6.31/beagleboard/defconfig
new file mode 100644
index 0000000000..f43c8f5fbb
--- /dev/null
+++ b/recipes/linux/linux-omap-pm-2.6.31/beagleboard/defconfig
@@ -0,0 +1,2765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc1-omap1
+# Thu Jul 30 12:51:41 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+# CONFIG_PHONET is not set
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID6_PQ=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+CONFIG_RTL8187_LEDS=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_P54_SPI is not set
+CONFIG_P54_LEDS=y
+CONFIG_ATH_COMMON=m
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2800USB=m
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_RFKILL=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_WL12XX=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+CONFIG_USB_NET_INT51X1=m
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OMAP24XX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_BROADSHEET=m
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_HID_GREENASIA is not set
+CONFIG_HID_SMARTJOYPLUS=m
+# CONFIG_SMARTJOYPLUS_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_THRUSTMASTER is not set
+CONFIG_HID_WACOM=m
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_OUTPUT=y
+CONFIG_ANDROID_TIMED_GPIO=m
+# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set
+# CONFIG_DST is not set
+CONFIG_POHMELFS=m
+# CONFIG_POHMELFS_DEBUG is not set
+CONFIG_POHMELFS_CRYPTO=y
+# CONFIG_STLC45XX is not set
+CONFIG_USB_SERIAL_ATEN2011=m
+# CONFIG_B3DFG is not set
+# CONFIG_PLAN9AUTH is not set
+# CONFIG_HECI is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_USB_SERIAL_QUATECH2=m
+CONFIG_USB_CPC=m
+# CONFIG_FB_UDL is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+# CONFIG_GFS2_FS_LOCKING_DLM is not set
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+# CONFIG_EXOFS_FS is not set
+CONFIG_NILFS2_FS=m
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-pm/beagle-writable-uboot.diff b/recipes/linux/linux-omap-pm/beagle-writable-uboot.diff
new file mode 100644
index 0000000000..7c5a36df9e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/beagle-writable-uboot.diff
@@ -0,0 +1,10 @@
+--- a/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-08 16:30:01.000000000 -0700
++++ b/arch/arm/mach-omap2/board-omap3beagle.c 2009-07-13 13:56:37.000000000 -0700
+@@ -68,7 +68,6 @@ static struct mtd_partition omap3beagle_
+ .name = "U-Boot",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 15 * NAND_BLOCK_SIZE,
+- .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot Env",
diff --git a/recipes/linux/linux-omap-pm/beagleboard/defconfig b/recipes/linux/linux-omap-pm/beagleboard/defconfig
index 83327b444e..5e0a85a708 100644
--- a/recipes/linux/linux-omap-pm/beagleboard/defconfig
+++ b/recipes/linux/linux-omap-pm/beagleboard/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-omap1
-# Thu Mar 5 20:20:28 2009
+# Linux kernel version: 2.6.29-omap1
+# Fri Jun 19 15:20:15 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -34,32 +34,44 @@ CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
@@ -70,10 +82,8 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
-# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
@@ -81,10 +91,12 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -95,7 +107,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
@@ -103,13 +114,11 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_DEV_INTEGRITY=y
#
# IO Schedulers
@@ -123,7 +132,6 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
CONFIG_FREEZER=y
#
@@ -134,7 +142,6 @@ CONFIG_FREEZER=y
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
@@ -161,11 +168,13 @@ CONFIG_FREEZER=y
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_DAVINCI is not set
CONFIG_ARCH_OMAP=y
# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# TI OMAP Implementations
@@ -189,7 +198,6 @@ CONFIG_OMAP_BOOT_REASON=y
# CONFIG_OMAP_GPIO_SWITCH is not set
# CONFIG_OMAP_MUX is not set
CONFIG_OMAP_MCBSP=y
-# CONFIG_OMAP_MMU_FWK is not set
# CONFIG_OMAP_MBOX_FWK is not set
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
@@ -203,37 +211,21 @@ CONFIG_OMAP_LL_DEBUG_UART3=y
# CONFIG_OMAP_PM_NONE is not set
# CONFIG_OMAP_PM_NOOP is not set
CONFIG_OMAP_PM_SRF=y
-CONFIG_OMAP2_DSS=y
-CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
-# CONFIG_OMAP2_DSS_RFBI is not set
-CONFIG_OMAP2_DSS_VENC=y
-# CONFIG_OMAP2_DSS_SDI is not set
-CONFIG_OMAP2_DSS_DSI=y
-CONFIG_OMAP2_DSS_USE_DSI_PLL=y
-# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
-CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
CONFIG_ARCH_OMAP34XX=y
CONFIG_ARCH_OMAP3430=y
#
# OMAP Board Type
#
+# CONFIG_MACH_NOKIA_RX51 is not set
# CONFIG_MACH_OMAP_LDP is not set
# CONFIG_MACH_OMAP_3430SDP is not set
-CONFIG_MACH_OMAP3EVM=y
+# CONFIG_MACH_OMAP3EVM is not set
CONFIG_MACH_OMAP3_BEAGLE=y
# CONFIG_MACH_OVERO is not set
# CONFIG_MACH_OMAP3_PANDORA is not set
#
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
# Processor Type
#
CONFIG_CPU_32=y
@@ -294,7 +286,6 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
@@ -350,7 +341,6 @@ CONFIG_NEON=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=y
@@ -373,6 +363,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -381,55 +372,74 @@ CONFIG_XFRM=y
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=y
# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
+# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -445,7 +455,7 @@ CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
-# CONFIG_NF_CONNTRACK_EVENTS is not set
+CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=m
CONFIG_NF_CT_PROTO_GRE=m
CONFIG_NF_CT_PROTO_SCTP=m
@@ -461,18 +471,18 @@ CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
# CONFIG_NETFILTER_TPROXY is not set
-CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
@@ -491,7 +501,7 @@ CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
@@ -505,7 +515,38 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
-# CONFIG_IP_VS is not set
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
#
# IP: Netfilter Configuration
@@ -570,46 +611,54 @@ CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
-CONFIG_BRIDGE_NF_EBTABLES=y
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_IP6=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
-CONFIG_BRIDGE_EBT_NFLOG=m
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-CONFIG_STP=y
-CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
# CONFIG_NET_DSA is not set
CONFIG_VLAN_8021Q=m
-# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_VLAN_8021Q_GVRP=y
# CONFIG_DECNET is not set
-CONFIG_LLC=y
+CONFIG_LLC=m
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
+CONFIG_WAN_ROUTER=m
CONFIG_NET_SCHED=y
#
@@ -618,6 +667,7 @@ CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_MULTIQ=m
CONFIG_NET_SCH_RED=m
@@ -627,7 +677,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_DRR=m
#
# Classification
@@ -644,33 +694,77 @@ CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_STACK=32
-CONFIG_NET_EMATCH_CMP=m
-CONFIG_NET_EMATCH_NBYTE=m
-CONFIG_NET_EMATCH_U32=m
-CONFIG_NET_EMATCH_META=m
-CONFIG_NET_EMATCH_TEXT=m
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=m
-CONFIG_NET_ACT_GACT=m
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=m
-# CONFIG_NET_ACT_IPT is not set
-CONFIG_NET_ACT_NAT=m
-CONFIG_NET_ACT_PEDIT=m
-CONFIG_NET_ACT_SIMP=m
-CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
CONFIG_BT=y
CONFIG_BT_L2CAP=y
CONFIG_BT_SCO=y
@@ -684,25 +778,35 @@ CONFIG_BT_HIDP=y
#
# Bluetooth device drivers
#
-CONFIG_BT_HCIUSB=y
-CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTUSB=y
CONFIG_BT_HCIBTSDIO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIBCM203X=y
CONFIG_BT_HCIBPA10X=y
-# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIBFUSB=y
# CONFIG_BT_HCIBRF6150 is not set
# CONFIG_BT_HCIH4P is not set
# CONFIG_BT_HCIVHCI is not set
-# CONFIG_AF_RXRPC is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
CONFIG_NL80211=y
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
CONFIG_MAC80211=y
#
@@ -717,13 +821,11 @@ CONFIG_MAC80211_RC_DEFAULT="pid"
CONFIG_MAC80211_LEDS=y
# CONFIG_MAC80211_DEBUGFS is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_CRYPT_TKIP=y
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
#
# Device Drivers
@@ -746,6 +848,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -819,6 +922,11 @@ CONFIG_MTD_NAND_PLATFORM=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=y
@@ -846,11 +954,18 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_93CX6=y
# CONFIG_ICS932S401 is not set
# CONFIG_OMAP_STI is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -894,6 +1009,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -917,13 +1033,12 @@ CONFIG_DM_MULTIPATH=m
CONFIG_DM_DELAY=m
# CONFIG_DM_UEVENT is not set
CONFIG_NETDEVICES=y
-# CONFIG_IFB is not set
CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
CONFIG_TUN=m
-# CONFIG_VETH is not set
+CONFIG_VETH=m
# CONFIG_NET_ETHERNET is not set
CONFIG_MII=y
# CONFIG_NETDEV_1000 is not set
@@ -949,7 +1064,9 @@ CONFIG_P54_USB=y
CONFIG_HOSTAP=y
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
-# CONFIG_B43 is not set
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
# CONFIG_B43LEGACY is not set
CONFIG_ZD1211RW=y
# CONFIG_ZD1211RW_DEBUG is not set
@@ -964,31 +1081,40 @@ CONFIG_RT2X00_LIB_LEDS=y
# CONFIG_RT2X00_DEBUG is not set
#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
# USB Network Adapters
#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=y
CONFIG_USB_NET_CDCETHER=y
-CONFIG_USB_NET_DM9601=m
-# CONFIG_USB_NET_SMSC95XX is not set
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_NET1080=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
CONFIG_USB_NET_RNDIS_HOST=y
-CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_NET_CDC_SUBSET=y
CONFIG_USB_ALI_M5632=y
CONFIG_USB_AN2720=y
CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_ZAURUS=y
# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
CONFIG_PPP=m
CONFIG_PPP_MULTILINK=y
CONFIG_PPP_FILTER=y
@@ -998,19 +1124,22 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
CONFIG_PPPOL2TP=m
# CONFIG_SLIP is not set
CONFIG_SLHC=m
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
# CONFIG_ISDN is not set
#
# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=y
# CONFIG_INPUT_POLLDEV is not set
#
@@ -1042,7 +1171,6 @@ CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
@@ -1054,7 +1182,15 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
#
# Hardware I/O ports
@@ -1095,10 +1231,10 @@ CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
@@ -1117,7 +1253,6 @@ CONFIG_I2C_HELPER_AUTO=y
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
CONFIG_I2C_OMAP=y
-# CONFIG_I2C2_OMAP_BEAGLE is not set
# CONFIG_I2C_SIMTEC is not set
#
@@ -1137,20 +1272,15 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
CONFIG_TWL4030_MADC=m
-CONFIG_TWL4030_PWRBUTTON=y
CONFIG_TWL4030_POWEROFF=y
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_SENSORS_TSL2563 is not set
-# CONFIG_LP5521 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -1163,12 +1293,12 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
# CONFIG_SPI_OMAP24XX is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
# CONFIG_SPI_TSC210X is not set
# CONFIG_SPI_TSC2301 is not set
# CONFIG_SPI_SPIDEV is not set
@@ -1220,6 +1350,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -1240,6 +1371,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
@@ -1263,8 +1395,8 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_TSC210X is not set
CONFIG_SENSORS_OMAP34XX=y
# CONFIG_HWMON_DEBUG_CHIP is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
@@ -1283,7 +1415,9 @@ CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-# CONFIG_SSB is not set
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
#
# Multifunction device drivers
@@ -1293,6 +1427,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
CONFIG_TWL4030_CORE=y
# CONFIG_TWL4030_POWER is not set
# CONFIG_MFD_TMIO is not set
@@ -1302,6 +1437,7 @@ CONFIG_TWL4030_CORE=y
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
@@ -1339,19 +1475,25 @@ CONFIG_MEDIA_TUNER_XC5000=m
CONFIG_MEDIA_TUNER_MXL5005S=m
CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
CONFIG_VIDEO_TVEEPROM=m
CONFIG_VIDEO_TUNER=m
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
CONFIG_VIDEO_MSP3400=m
CONFIG_VIDEO_CS53L32A=m
CONFIG_VIDEO_WM8775=m
CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
CONFIG_VIDEO_CX25840=m
CONFIG_VIDEO_CX2341X=m
-# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_VIVI=m
# CONFIG_VIDEO_CPIA is not set
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_VIDEO_SAA5246A is not set
@@ -1363,11 +1505,13 @@ CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SONIXB=m
@@ -1388,30 +1532,34 @@ CONFIG_VIDEO_PVRUSB2=m
CONFIG_VIDEO_PVRUSB2_SYSFS=y
CONFIG_VIDEO_PVRUSB2_DVB=y
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
-# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
CONFIG_VIDEO_USBVISION=m
CONFIG_VIDEO_USBVIDEO=m
CONFIG_USB_VICAM=m
CONFIG_USB_IBMCAM=m
CONFIG_USB_KONICAWC=m
CONFIG_USB_QUICKCAM_MESSENGER=m
-# CONFIG_USB_ET61X251 is not set
+CONFIG_USB_ET61X251=m
CONFIG_VIDEO_OVCAMCHIP=m
CONFIG_USB_W9968CF=m
CONFIG_USB_OV511=m
CONFIG_USB_SE401=m
CONFIG_USB_SN9C102=m
CONFIG_USB_STV680=m
-# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_ZC0301=m
CONFIG_USB_PWC=m
# CONFIG_USB_PWC_DEBUG is not set
CONFIG_USB_ZR364XX=m
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
CONFIG_RADIO_ADAPTERS=y
# CONFIG_USB_DSBR is not set
# CONFIG_USB_SI470X is not set
# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_TTPCI_EEPROM is not set
@@ -1445,15 +1593,15 @@ CONFIG_DVB_USB_CINERGY_T2=m
CONFIG_DVB_USB_ANYSEE=m
CONFIG_DVB_USB_DTV5100=m
CONFIG_DVB_USB_AF9015=m
-CONFIG_DVB_TTUSB_BUDGET=m
-CONFIG_DVB_TTUSB_DEC=m
CONFIG_DVB_SIANO_SMS1XXX=m
CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
#
# Supported FlexCopII (B2C2) Adapters
#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
#
# Supported DVB Frontends
@@ -1465,6 +1613,12 @@ CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
# DVB-S (satellite) frontends
#
CONFIG_DVB_CX24110=m
@@ -1476,8 +1630,10 @@ CONFIG_DVB_STB6000=m
CONFIG_DVB_STV0299=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
CONFIG_DVB_VES1X93=m
CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
CONFIG_DVB_TDA826X=m
CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
@@ -1490,7 +1646,7 @@ CONFIG_DVB_SP8870=m
CONFIG_DVB_SP887X=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_CX22702=m
-# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_DRX397XD=m
CONFIG_DVB_L64781=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
@@ -1514,15 +1670,21 @@ CONFIG_DVB_STV0297=m
# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
#
CONFIG_DVB_NXT200X=m
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
CONFIG_DVB_S5H1409=m
CONFIG_DVB_AU8522=m
CONFIG_DVB_S5H1411=m
#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
# Digital terrestrial only tuners/PLL
#
CONFIG_DVB_PLL=m
@@ -1534,7 +1696,7 @@ CONFIG_DVB_TUNER_DIB0070=m
CONFIG_DVB_LNBP21=m
# CONFIG_DVB_ISL6405 is not set
CONFIG_DVB_ISL6421=m
-# CONFIG_DVB_LGS8GL5 is not set
+CONFIG_DVB_LGS8GL5=m
#
# Tools to develop new frontends
@@ -1574,19 +1736,30 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
-CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=14
-CONFIG_FB_OMAP2=y
-CONFIG_FB_OMAP2_DEBUG=y
-# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
-CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
#
# OMAP2/3 Display Device Drivers
#
CONFIG_PANEL_GENERIC=y
-CONFIG_PANEL_SHARP_LS037V7DW01=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
# CONFIG_PANEL_N800 is not set
# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1627,6 +1800,8 @@ CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1638,7 +1813,7 @@ CONFIG_SND_DRIVERS=y
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-CONFIG_SND_ARM=y
+# CONFIG_SND_ARM is not set
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=y
@@ -1646,11 +1821,8 @@ CONFIG_SND_USB_CAIAQ=m
CONFIG_SND_USB_CAIAQ_INPUT=y
CONFIG_SND_SOC=y
CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_MCBSP=y
-CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
-# CONFIG_SND_OMAP_SOC_OMAP3EVM is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
-CONFIG_SND_SOC_TWL4030=y
# CONFIG_SOUND_PRIME is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
@@ -1671,11 +1843,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1683,12 +1853,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
# CONFIG_THRUSTMASTER_FF is not set
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
@@ -1720,10 +1893,12 @@ CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_OMAP_EHCI_PHY_MODE=y
# CONFIG_OMAP_EHCI_TLL_MODE is not set
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_HWA_HCD is not set
@@ -1749,7 +1924,7 @@ CONFIG_USB_INVENTRA_DMA=y
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
CONFIG_USB_WDM=m
-# CONFIG_USB_TMC is not set
+CONFIG_USB_TMC=m
#
# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
@@ -1763,7 +1938,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1832,12 +2006,14 @@ CONFIG_USB_SERIAL_SPCP8X5=m
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
CONFIG_USB_SERIAL_DEBUG=m
#
@@ -1850,21 +2026,30 @@ CONFIG_USB_EMI26=m
# CONFIG_USB_RIO500 is not set
CONFIG_USB_LEGOTOWER=m
CONFIG_USB_LCD=m
-# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_BERRY_CHARGE=m
CONFIG_USB_LED=m
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
+CONFIG_USB_TEST=m
# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
@@ -1879,22 +2064,26 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
CONFIG_USB_GADGET_DUALSPEED=y
-# CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
#
# OTG and related infrastructure
@@ -1930,20 +2119,21 @@ CONFIG_LEDS_CLASS=y
# LED drivers
#
# CONFIG_LEDS_OMAP_DEBUG is not set
-# CONFIG_LEDS_OMAP is not set
+CONFIG_LEDS_OMAP=y
# CONFIG_LEDS_OMAP_PWM is not set
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
-# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -2013,7 +2203,38 @@ CONFIG_REGULATOR=y
# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
# CONFIG_REGULATOR_BQ24022 is not set
CONFIG_REGULATOR_TWL4030=y
-# CONFIG_UIO is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
#
# CBUS support
@@ -2038,8 +2259,17 @@ CONFIG_JBD=y
CONFIG_JBD2=m
# CONFIG_JBD2_DEBUG is not set
CONFIG_FS_MBCACHE=m
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
@@ -2047,19 +2277,29 @@ CONFIG_XFS_FS=m
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
# CONFIG_XFS_DEBUG is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
# CONFIG_QUOTA_NETLINK_INTERFACE is not set
CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
#
@@ -2079,7 +2319,9 @@ CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
#
# Pseudo filesystems
@@ -2091,18 +2333,18 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -2121,40 +2363,70 @@ CONFIG_JFFS2_RUBIN=y
# CONFIG_JFFS2_CMODE_SIZE is not set
CONFIG_JFFS2_CMODE_FAVOURLZO=y
CONFIG_UBIFS_FS=y
-# CONFIG_UBIFS_FS_XATTR is not set
-# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
#
# Partition Types
@@ -2164,65 +2436,67 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_OSF_PARTITION is not set
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
+CONFIG_EFI_PARTITION=y
# CONFIG_SYSV68_PARTITION is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-# CONFIG_DLM is not set
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
#
# Kernel hacking
#
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
@@ -2249,6 +2523,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
@@ -2257,6 +2532,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
@@ -2265,7 +2541,10 @@ CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
@@ -2275,7 +2554,9 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
@@ -2288,7 +2569,8 @@ CONFIG_HAVE_ARCH_KGDB=y
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
@@ -2301,40 +2583,42 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
-# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m
-# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m
#
# Authenticated Encryption with Associated Data
#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
#
# Block modes
#
CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
+CONFIG_CRYPTO_XTS=m
#
# Hash modes
@@ -2345,14 +2629,14 @@ CONFIG_CRYPTO_XCBC=m
#
# Digest
#
-CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
@@ -2372,8 +2656,8 @@ CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
@@ -2388,13 +2672,14 @@ CONFIG_CRYPTO_LZO=y
#
# Random Number Generation
#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
#
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
diff --git a/recipes/linux/linux-omap-pm/beagleboard/ehci.patch b/recipes/linux/linux-omap-pm/beagleboard/ehci.patch
index 5a8c84471b..c55ff601c4 100644
--- a/recipes/linux/linux-omap-pm/beagleboard/ehci.patch
+++ b/recipes/linux/linux-omap-pm/beagleboard/ehci.patch
@@ -1,131 +1,46 @@
-Index: git/arch/arm/mach-omap2/board-omap3beagle.c
-===================================================================
---- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
-+++ git/arch/arm/mach-omap2/board-omap3beagle.c
-@@ -154,6 +154,7 @@ static int beagle_twl_gpio_setup(struct
+From f8f10f496bce396416d7156da876222c6ce8c341 Mon Sep 17 00:00:00 2001
+From: Steven Kipisz <skipisz@beagleboard.org>
+Date: Wed, 9 Jan 2009 12:01:11 -0600
+Subject: [PATCH-USB] Omap3 beagleboard: add support for EHCI in revision C1 boards
+
+Signed-off-by: Jason Kridner <jkridner@beagleboard.org>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 10 +---------
+ arch/arm/mach-omap2/usb-ehci.c | 4 +---
+ drivers/usb/host/ehci-omap.c | 26 ++++++++++++++++++++++++++
+ 3 files changed, 28 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index fe97bab..de81153 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -140,15 +140,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
* power switch and overcurrent detect
*/
-+#if 0 /* TODO: This needs to be modified to not rely on u-boot */
- gpio_request(gpio + 1, "EHCI_nOC");
- gpio_direction_input(gpio + 1);
-
-@@ -163,7 +164,7 @@ static int beagle_twl_gpio_setup(struct
-
- /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
- gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+- gpio_request(gpio + 1, "EHCI_nOC");
+- gpio_direction_input(gpio + 1);
-
-+#endif
+- /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+- gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+-
+- /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+- gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
++ /* TODO: This needs to be modified to not rely on u-boot */
+
return 0;
}
+--- /tmp/usb-ehci.c 2009-07-30 13:14:34.000000000 +0200
++++ git/arch/arm/mach-omap2/usb-ehci.c 2009-07-30 13:16:03.000000000 +0200
+@@ -170,9 +170,7 @@
-Index: git/arch/arm/mach-omap2/usb-ehci.c
-===================================================================
---- git.orig/arch/arm/mach-omap2/usb-ehci.c
-+++ git/arch/arm/mach-omap2/usb-ehci.c
-@@ -147,9 +147,11 @@ static void setup_ehci_io_mux(void)
+ platform_device_add_data(&ehci_device, &pdata, sizeof(pdata));
- void __init usb_ehci_init(void)
- {
-+#if 0 /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
- /* Setup Pin IO MUX for EHCI */
- if (cpu_is_omap34xx())
- setup_ehci_io_mux();
-+#endif
+- /* Setup Pin IO MUX for EHCI */
+- if (cpu_is_omap34xx())
+- setup_ehci_io_mux();
++ /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
if (platform_device_register(&ehci_device) < 0) {
printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
-Index: git/drivers/usb/host/ehci-omap.c
-===================================================================
---- git.orig/drivers/usb/host/ehci-omap.c
-+++ git/drivers/usb/host/ehci-omap.c
-@@ -48,16 +48,25 @@
- * to get the PHY state machine in working state
- */
- #define EXTERNAL_PHY_RESET
-+#ifdef CONFIG_MACH_OMAP3_BEAGLE
-+#define EXT_PHY_RESET_GPIO_PORT2 (147)
-+#else
- #define EXT_PHY_RESET_GPIO_PORT1 (57)
- #define EXT_PHY_RESET_GPIO_PORT2 (61)
-+#endif
- #define EXT_PHY_RESET_DELAY (10)
-
-+#define PHY_STP_PULLUP_ENABLE (0x10)
-+#define PHY_STP_PULLUP_DISABLE (0x90)
-+
- /* ISSUE2:
- * USBHOST supports External charge pump PHYs only
- * Use the VBUS from Port1 to power VBUS of Port2 externally
- * So use Port2 as the working ULPI port
- */
-+#ifndef CONFIG_MACH_OMAP3_BEAGLE
- #define VBUS_INTERNAL_CHARGEPUMP_HACK
-+#endif
-
- #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
-
-@@ -225,14 +234,43 @@ static int omap_start_ehc(struct platfor
-
- #ifdef EXTERNAL_PHY_RESET
- /* Refer: ISSUE1 */
-+#ifndef CONFIG_MACH_OMAP3_BEAGLE
- gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
- gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
-+#endif
- gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
- gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
-+ gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
- /* Hold the PHY in RESET for enough time till DIR is high */
- udelay(EXT_PHY_RESET_DELAY);
- #endif
-
-+ /*
-+ * The PHY register 0x7 - Interface Control register is
-+ * configured to disable the integrated STP pull-up resistor
-+ * used for interface protection.
-+ *
-+ * May not need to be here.
-+ */
-+ omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
-+ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
-+ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
-+ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
-+ (PHY_STP_PULLUP_DISABLE),
-+ EHCI_INSNREG05_ULPI);
-+
-+ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
-+
-+ /* Force PHY to HS */
-+ omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
-+ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */
-+ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
-+ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
-+ (0x40),
-+ EHCI_INSNREG05_ULPI);
-+
-+ while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
-+
- /* Configure TLL for 60Mhz clk for ULPI */
- ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
- if (IS_ERR(ehci_clocks->usbtll_fck_clk))
-@@ -307,7 +345,9 @@ static int omap_start_ehc(struct platfor
- * Hold the PHY in RESET for enough time till PHY is settled and ready
- */
- udelay(EXT_PHY_RESET_DELAY);
-+#ifndef CONFIG_MACH_OMAP3_BEAGLE
- gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
-+#endif
- gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
- #endif
-
-@@ -393,7 +433,9 @@ static void omap_stop_ehc(struct platfor
-
-
- #ifdef EXTERNAL_PHY_RESET
-+#ifndef CONFIG_MACH_OMAP3_BEAGLE
- gpio_free(EXT_PHY_RESET_GPIO_PORT1);
-+#endif
- gpio_free(EXT_PHY_RESET_GPIO_PORT2);
- #endif
-
diff --git a/recipes/linux/linux-omap-pm/dss2/0001-OMAPFB-move-omapfb.h-to-include-linux.patch b/recipes/linux/linux-omap-pm/dss2/0001-OMAPFB-move-omapfb.h-to-include-linux.patch
new file mode 100644
index 0000000000..90151db610
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0001-OMAPFB-move-omapfb.h-to-include-linux.patch
@@ -0,0 +1,1297 @@
+From 6ded8e833fa9559202dbd4c70a1bd95ffffacc5d Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 11 Feb 2009 16:33:02 +0200
+Subject: [PATCH 001/146] OMAPFB: move omapfb.h to include/linux/
+
+This is needed so that omapfb.h is automatically exported to user space.
+
+omapfb.h should be cleaned up later. Some stuff can probably be moved
+to omapfb's private include file.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/mach-omap1/board-nokia770.c | 2 +-
+ arch/arm/mach-omap2/board-n800.c | 2 +-
+ arch/arm/mach-omap2/io.c | 2 +-
+ arch/arm/plat-omap/fb.c | 2 +-
+ arch/arm/plat-omap/include/mach/omapfb.h | 398 ------------------------------
+ drivers/video/omap/blizzard.c | 2 +-
+ drivers/video/omap/dispc.c | 2 +-
+ drivers/video/omap/hwa742.c | 2 +-
+ drivers/video/omap/lcd_2430sdp.c | 2 +-
+ drivers/video/omap/lcd_ams_delta.c | 2 +-
+ drivers/video/omap/lcd_apollon.c | 2 +-
+ drivers/video/omap/lcd_h3.c | 2 +-
+ drivers/video/omap/lcd_h4.c | 3 +-
+ drivers/video/omap/lcd_inn1510.c | 2 +-
+ drivers/video/omap/lcd_inn1610.c | 2 +-
+ drivers/video/omap/lcd_ldp.c | 2 +-
+ drivers/video/omap/lcd_mipid.c | 2 +-
+ drivers/video/omap/lcd_omap2evm.c | 2 +-
+ drivers/video/omap/lcd_omap3beagle.c | 2 +-
+ drivers/video/omap/lcd_omap3evm.c | 2 +-
+ drivers/video/omap/lcd_osk.c | 2 +-
+ drivers/video/omap/lcd_overo.c | 2 +-
+ drivers/video/omap/lcd_palmte.c | 2 +-
+ drivers/video/omap/lcd_palmtt.c | 2 +-
+ drivers/video/omap/lcd_palmz71.c | 3 +-
+ drivers/video/omap/lcdc.c | 2 +-
+ drivers/video/omap/omapfb_main.c | 2 +-
+ drivers/video/omap/rfbi.c | 3 +-
+ drivers/video/omap/sossi.c | 2 +-
+ include/linux/omapfb.h | 398 ++++++++++++++++++++++++++++++
+ 30 files changed, 426 insertions(+), 429 deletions(-)
+ delete mode 100644 arch/arm/plat-omap/include/mach/omapfb.h
+ create mode 100644 include/linux/omapfb.h
+
+diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
+index ed2a48a..63be1bc 100644
+--- a/arch/arm/mach-omap1/board-nokia770.c
++++ b/arch/arm/mach-omap1/board-nokia770.c
+@@ -18,6 +18,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
+ #include <linux/workqueue.h>
++#include <linux/omapfb.h>
+ #include <linux/delay.h>
+
+ #include <mach/hardware.h>
+@@ -32,7 +33,6 @@
+ #include <mach/keypad.h>
+ #include <mach/common.h>
+ #include <mach/dsp_common.h>
+-#include <mach/omapfb.h>
+ #include <mach/hwa742.h>
+ #include <mach/lcd_mipid.h>
+ #include <mach/mmc.h>
+diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
+index 23296e9..e2907ac 100644
+--- a/arch/arm/mach-omap2/board-n800.c
++++ b/arch/arm/mach-omap2/board-n800.c
+@@ -22,6 +22,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/i2c.h>
++#include <linux/omapfb.h>
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -34,7 +35,6 @@
+ #include <mach/lcd_mipid.h>
+ #include <mach/clock.h>
+ #include <mach/menelaus.h>
+-#include <mach/omapfb.h>
+ #include <mach/blizzard.h>
+ #include <mach/onenand.h>
+ #include <mach/board-nokia.h>
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index 3a86b0f..5c91f36 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -20,6 +20,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
++#include <linux/omapfb.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
+
+@@ -28,7 +29,6 @@
+ #include <asm/mach/map.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <mach/sram.h>
+ #include <mach/sdrc.h>
+ #include <mach/gpmc.h>
+diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
+index 3746222..40615a6 100644
+--- a/arch/arm/plat-omap/fb.c
++++ b/arch/arm/plat-omap/fb.c
+@@ -28,13 +28,13 @@
+ #include <linux/platform_device.h>
+ #include <linux/bootmem.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach/map.h>
+
+ #include <mach/board.h>
+ #include <mach/sram.h>
+-#include <mach/omapfb.h>
+
+ #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h
+deleted file mode 100644
+index b226bdf..0000000
+--- a/arch/arm/plat-omap/include/mach/omapfb.h
++++ /dev/null
+@@ -1,398 +0,0 @@
+-/*
+- * File: arch/arm/plat-omap/include/mach/omapfb.h
+- *
+- * Framebuffer driver for TI OMAP boards
+- *
+- * Copyright (C) 2004 Nokia Corporation
+- * Author: Imre Deak <imre.deak@nokia.com>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-#ifndef __OMAPFB_H
+-#define __OMAPFB_H
+-
+-#include <asm/ioctl.h>
+-#include <asm/types.h>
+-
+-/* IOCTL commands. */
+-
+-#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
+-#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
+-#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
+-#define OMAP_IO(num) _IO('O', num)
+-
+-#define OMAPFB_MIRROR OMAP_IOW(31, int)
+-#define OMAPFB_SYNC_GFX OMAP_IO(37)
+-#define OMAPFB_VSYNC OMAP_IO(38)
+-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
+-#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
+-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
+-#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
+-#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
+-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
+-#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
+-#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
+-#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
+-#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
+-#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
+-#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
+-#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
+-
+-#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+-#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+-#define OMAPFB_CAPS_PANEL_MASK 0xff000000
+-
+-#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
+-#define OMAPFB_CAPS_TEARSYNC 0x00002000
+-#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
+-#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
+-#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
+-#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
+-#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
+-#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
+-#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
+-
+-/* Values from DSP must map to lower 16-bits */
+-#define OMAPFB_FORMAT_MASK 0x00ff
+-#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
+-#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
+-#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
+-#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
+-#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
+-
+-#define OMAPFB_EVENT_READY 1
+-#define OMAPFB_EVENT_DISABLED 2
+-
+-#define OMAPFB_MEMTYPE_SDRAM 0
+-#define OMAPFB_MEMTYPE_SRAM 1
+-#define OMAPFB_MEMTYPE_MAX 1
+-
+-enum omapfb_color_format {
+- OMAPFB_COLOR_RGB565 = 0,
+- OMAPFB_COLOR_YUV422,
+- OMAPFB_COLOR_YUV420,
+- OMAPFB_COLOR_CLUT_8BPP,
+- OMAPFB_COLOR_CLUT_4BPP,
+- OMAPFB_COLOR_CLUT_2BPP,
+- OMAPFB_COLOR_CLUT_1BPP,
+- OMAPFB_COLOR_RGB444,
+- OMAPFB_COLOR_YUY422,
+-};
+-
+-struct omapfb_update_window {
+- __u32 x, y;
+- __u32 width, height;
+- __u32 format;
+- __u32 out_x, out_y;
+- __u32 out_width, out_height;
+- __u32 reserved[8];
+-};
+-
+-struct omapfb_update_window_old {
+- __u32 x, y;
+- __u32 width, height;
+- __u32 format;
+-};
+-
+-enum omapfb_plane {
+- OMAPFB_PLANE_GFX = 0,
+- OMAPFB_PLANE_VID1,
+- OMAPFB_PLANE_VID2,
+-};
+-
+-enum omapfb_channel_out {
+- OMAPFB_CHANNEL_OUT_LCD = 0,
+- OMAPFB_CHANNEL_OUT_DIGIT,
+-};
+-
+-struct omapfb_plane_info {
+- __u32 pos_x;
+- __u32 pos_y;
+- __u8 enabled;
+- __u8 channel_out;
+- __u8 mirror;
+- __u8 reserved1;
+- __u32 out_width;
+- __u32 out_height;
+- __u32 reserved2[12];
+-};
+-
+-struct omapfb_mem_info {
+- __u32 size;
+- __u8 type;
+- __u8 reserved[3];
+-};
+-
+-struct omapfb_caps {
+- __u32 ctrl;
+- __u32 plane_color;
+- __u32 wnd_color;
+-};
+-
+-enum omapfb_color_key_type {
+- OMAPFB_COLOR_KEY_DISABLED = 0,
+- OMAPFB_COLOR_KEY_GFX_DST,
+- OMAPFB_COLOR_KEY_VID_SRC,
+-};
+-
+-struct omapfb_color_key {
+- __u8 channel_out;
+- __u32 background;
+- __u32 trans_key;
+- __u8 key_type;
+-};
+-
+-enum omapfb_update_mode {
+- OMAPFB_UPDATE_DISABLED = 0,
+- OMAPFB_AUTO_UPDATE,
+- OMAPFB_MANUAL_UPDATE
+-};
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/completion.h>
+-#include <linux/interrupt.h>
+-#include <linux/fb.h>
+-#include <linux/mutex.h>
+-
+-#include <mach/board.h>
+-
+-#define OMAP_LCDC_INV_VSYNC 0x0001
+-#define OMAP_LCDC_INV_HSYNC 0x0002
+-#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
+-#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
+-#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
+-#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
+-
+-#define OMAP_LCDC_SIGNAL_MASK 0x003f
+-
+-#define OMAP_LCDC_PANEL_TFT 0x0100
+-
+-#define OMAPFB_PLANE_XRES_MIN 8
+-#define OMAPFB_PLANE_YRES_MIN 8
+-
+-#ifdef CONFIG_ARCH_OMAP1
+-#define OMAPFB_PLANE_NUM 1
+-#else
+-#define OMAPFB_PLANE_NUM 3
+-#endif
+-
+-struct omapfb_device;
+-
+-struct lcd_panel {
+- const char *name;
+- int config; /* TFT/STN, signal inversion */
+- int bpp; /* Pixel format in fb mem */
+- int data_lines; /* Lines on LCD HW interface */
+-
+- int x_res, y_res;
+- int pixel_clock; /* In kHz */
+- int hsw; /* Horizontal synchronization
+- pulse width */
+- int hfp; /* Horizontal front porch */
+- int hbp; /* Horizontal back porch */
+- int vsw; /* Vertical synchronization
+- pulse width */
+- int vfp; /* Vertical front porch */
+- int vbp; /* Vertical back porch */
+- int acb; /* ac-bias pin frequency */
+- int pcd; /* pixel clock divider.
+- Obsolete use pixel_clock instead */
+-
+- int (*init) (struct lcd_panel *panel,
+- struct omapfb_device *fbdev);
+- void (*cleanup) (struct lcd_panel *panel);
+- int (*enable) (struct lcd_panel *panel);
+- void (*disable) (struct lcd_panel *panel);
+- unsigned long (*get_caps) (struct lcd_panel *panel);
+- int (*set_bklight_level)(struct lcd_panel *panel,
+- unsigned int level);
+- unsigned int (*get_bklight_level)(struct lcd_panel *panel);
+- unsigned int (*get_bklight_max) (struct lcd_panel *panel);
+- int (*run_test) (struct lcd_panel *panel, int test_num);
+-};
+-
+-struct extif_timings {
+- int cs_on_time;
+- int cs_off_time;
+- int we_on_time;
+- int we_off_time;
+- int re_on_time;
+- int re_off_time;
+- int we_cycle_time;
+- int re_cycle_time;
+- int cs_pulse_width;
+- int access_time;
+-
+- int clk_div;
+-
+- u32 tim[5]; /* set by extif->convert_timings */
+-
+- int converted;
+-};
+-
+-struct lcd_ctrl_extif {
+- int (*init) (struct omapfb_device *fbdev);
+- void (*cleanup) (void);
+- void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
+- unsigned long (*get_max_tx_rate)(void);
+- int (*convert_timings) (struct extif_timings *timings);
+- void (*set_timings) (const struct extif_timings *timings);
+- void (*set_bits_per_cycle)(int bpc);
+- void (*write_command) (const void *buf, unsigned int len);
+- void (*read_data) (void *buf, unsigned int len);
+- void (*write_data) (const void *buf, unsigned int len);
+- void (*transfer_area) (int width, int height,
+- void (callback)(void * data), void *data);
+- int (*setup_tearsync) (unsigned pin_cnt,
+- unsigned hs_pulse_time, unsigned vs_pulse_time,
+- int hs_pol_inv, int vs_pol_inv, int div);
+- int (*enable_tearsync) (int enable, unsigned line);
+-
+- unsigned long max_transmit_size;
+-};
+-
+-struct omapfb_notifier_block {
+- struct notifier_block nb;
+- void *data;
+- int plane_idx;
+-};
+-
+-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+- unsigned long event,
+- void *fbi);
+-
+-struct omapfb_mem_region {
+- u32 paddr;
+- void __iomem *vaddr;
+- unsigned long size;
+- u8 type; /* OMAPFB_PLANE_MEM_* */
+- unsigned alloc:1; /* allocated by the driver */
+- unsigned map:1; /* kernel mapped by the driver */
+-};
+-
+-struct omapfb_mem_desc {
+- int region_cnt;
+- struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
+-};
+-
+-struct lcd_ctrl {
+- const char *name;
+- void *data;
+-
+- int (*init) (struct omapfb_device *fbdev,
+- int ext_mode,
+- struct omapfb_mem_desc *req_md);
+- void (*cleanup) (void);
+- void (*bind_client) (struct omapfb_notifier_block *nb);
+- void (*get_caps) (int plane, struct omapfb_caps *caps);
+- int (*set_update_mode)(enum omapfb_update_mode mode);
+- enum omapfb_update_mode (*get_update_mode)(void);
+- int (*setup_plane) (int plane, int channel_out,
+- unsigned long offset,
+- int screen_width,
+- int pos_x, int pos_y, int width,
+- int height, int color_mode);
+- int (*set_rotate) (int angle);
+- int (*setup_mem) (int plane, size_t size,
+- int mem_type, unsigned long *paddr);
+- int (*mmap) (struct fb_info *info,
+- struct vm_area_struct *vma);
+- int (*set_scale) (int plane,
+- int orig_width, int orig_height,
+- int out_width, int out_height);
+- int (*enable_plane) (int plane, int enable);
+- int (*update_window) (struct fb_info *fbi,
+- struct omapfb_update_window *win,
+- void (*callback)(void *),
+- void *callback_data);
+- void (*sync) (void);
+- void (*suspend) (void);
+- void (*resume) (void);
+- int (*run_test) (int test_num);
+- int (*setcolreg) (u_int regno, u16 red, u16 green,
+- u16 blue, u16 transp,
+- int update_hw_mem);
+- int (*set_color_key) (struct omapfb_color_key *ck);
+- int (*get_color_key) (struct omapfb_color_key *ck);
+-};
+-
+-enum omapfb_state {
+- OMAPFB_DISABLED = 0,
+- OMAPFB_SUSPENDED= 99,
+- OMAPFB_ACTIVE = 100
+-};
+-
+-struct omapfb_plane_struct {
+- int idx;
+- struct omapfb_plane_info info;
+- enum omapfb_color_format color_mode;
+- struct omapfb_device *fbdev;
+-};
+-
+-struct omapfb_device {
+- int state;
+- int ext_lcdc; /* Using external
+- LCD controller */
+- struct mutex rqueue_mutex;
+-
+- int palette_size;
+- u32 pseudo_palette[17];
+-
+- struct lcd_panel *panel; /* LCD panel */
+- const struct lcd_ctrl *ctrl; /* LCD controller */
+- const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
+- struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
+- interface */
+- struct device *dev;
+- struct fb_var_screeninfo new_var; /* for mode changes */
+-
+- struct omapfb_mem_desc mem_desc;
+- struct fb_info *fb_info[OMAPFB_PLANE_NUM];
+-};
+-
+-struct omapfb_platform_data {
+- struct omap_lcd_config lcd;
+- struct omapfb_mem_desc mem_desc;
+- void *ctrl_platform_data;
+-};
+-
+-#ifdef CONFIG_ARCH_OMAP1
+-extern struct lcd_ctrl omap1_lcd_ctrl;
+-#else
+-extern struct lcd_ctrl omap2_disp_ctrl;
+-#endif
+-
+-extern void omapfb_reserve_sdram(void);
+-extern void omapfb_register_panel(struct lcd_panel *panel);
+-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+-extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+- unsigned long event);
+-extern int omapfb_register_client(struct omapfb_notifier_block *nb,
+- omapfb_notifier_callback_t callback,
+- void *callback_data);
+-extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
+-extern int omapfb_update_window_async(struct fb_info *fbi,
+- struct omapfb_update_window *win,
+- void (*callback)(void *),
+- void *callback_data);
+-
+-/* in arch/arm/plat-omap/fb.c */
+-extern void omapfb_set_ctrl_platform_data(void *pdata);
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __OMAPFB_H */
+diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
+index d5e5955..56097ae 100644
+--- a/drivers/video/omap/blizzard.c
++++ b/drivers/video/omap/blizzard.c
+@@ -25,9 +25,9 @@
+ #include <linux/fb.h>
+ #include <linux/delay.h>
+ #include <linux/clk.h>
++#include <linux/omapfb.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+ #include <mach/blizzard.h>
+
+ #include "dispc.h"
+diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
+index 350b444..9f04e34 100644
+--- a/drivers/video/omap/dispc.c
++++ b/drivers/video/omap/dispc.c
+@@ -24,9 +24,9 @@
+ #include <linux/vmalloc.h>
+ #include <linux/clk.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/sram.h>
+-#include <mach/omapfb.h>
+ #include <mach/board.h>
+
+ #include "dispc.h"
+diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
+index ca51583..e93a51b 100644
+--- a/drivers/video/omap/hwa742.c
++++ b/drivers/video/omap/hwa742.c
+@@ -25,9 +25,9 @@
+ #include <linux/fb.h>
+ #include <linux/delay.h>
+ #include <linux/clk.h>
++#include <linux/omapfb.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+ #include <mach/hwa742.h>
+
+ #define HWA742_REV_CODE_REG 0x0
+diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
+index 13c822e..e199bba 100644
+--- a/drivers/video/omap/lcd_2430sdp.c
++++ b/drivers/video/omap/lcd_2430sdp.c
+@@ -26,9 +26,9 @@
+ #include <linux/delay.h>
+ #include <linux/gpio.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
+diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
+index 1f74399..e480b6b 100644
+--- a/drivers/video/omap/lcd_ams_delta.c
++++ b/drivers/video/omap/lcd_ams_delta.c
+@@ -24,10 +24,10 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/delay.h>
++#include <linux/omapfb.h>
+
+ #include <mach/board-ams-delta.h>
+ #include <mach/hardware.h>
+-#include <mach/omapfb.h>
+
+ #define AMS_DELTA_DEFAULT_CONTRAST 112
+
+diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
+index 626ae3a..15a0ced 100644
+--- a/drivers/video/omap/lcd_apollon.c
++++ b/drivers/video/omap/lcd_apollon.c
+@@ -23,10 +23,10 @@
+
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+
+ /* #define USE_35INCH_LCD 1 */
+
+diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
+index 2486237..f7264ea 100644
+--- a/drivers/video/omap/lcd_h3.c
++++ b/drivers/video/omap/lcd_h3.c
+@@ -22,9 +22,9 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/i2c/tps65010.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
+
+ #define MODULE_NAME "omapfb-lcd_h3"
+
+diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
+index 6ff5643..d72df0c 100644
+--- a/drivers/video/omap/lcd_h4.c
++++ b/drivers/video/omap/lcd_h4.c
+@@ -21,8 +21,7 @@
+
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+-
+-#include <mach/omapfb.h>
++#include <linux/omapfb.h>
+
+ static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+ {
+diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
+index 6953ed4..f6e05d7 100644
+--- a/drivers/video/omap/lcd_inn1510.c
++++ b/drivers/video/omap/lcd_inn1510.c
+@@ -22,9 +22,9 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/fpga.h>
+-#include <mach/omapfb.h>
+
+ static int innovator1510_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
+index 4c4f7ee..c599e41 100644
+--- a/drivers/video/omap/lcd_inn1610.c
++++ b/drivers/video/omap/lcd_inn1610.c
+@@ -21,9 +21,9 @@
+
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
+
+ #define MODULE_NAME "omapfb-lcd_h3"
+
+diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
+index 8925230..1c25186 100644
+--- a/drivers/video/omap/lcd_ldp.c
++++ b/drivers/video/omap/lcd_ldp.c
+@@ -25,10 +25,10 @@
+ #include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
+diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
+index 3165d3d..025ee97 100644
+--- a/drivers/video/omap/lcd_mipid.c
++++ b/drivers/video/omap/lcd_mipid.c
+@@ -22,8 +22,8 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/spi/spi.h>
++#include <linux/omapfb.h>
+
+-#include <mach/omapfb.h>
+ #include <mach/lcd_mipid.h>
+
+ #define MIPID_MODULE_NAME "lcd_mipid"
+diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
+index 2fc46c2..1908a2b 100644
+--- a/drivers/video/omap/lcd_omap2evm.c
++++ b/drivers/video/omap/lcd_omap2evm.c
+@@ -25,9 +25,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define LCD_PANEL_ENABLE_GPIO 154
+diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
+index 40454dc..dbb832c 100644
+--- a/drivers/video/omap/lcd_omap3beagle.c
++++ b/drivers/video/omap/lcd_omap3beagle.c
+@@ -24,9 +24,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define LCD_PANEL_ENABLE_GPIO 170
+diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
+index 1c3d814..10ba48c 100644
+--- a/drivers/video/omap/lcd_omap3evm.c
++++ b/drivers/video/omap/lcd_omap3evm.c
+@@ -24,9 +24,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define LCD_PANEL_ENABLE_GPIO 153
+diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
+index 379c96d..d6b193e 100644
+--- a/drivers/video/omap/lcd_osk.c
++++ b/drivers/video/omap/lcd_osk.c
+@@ -22,10 +22,10 @@
+
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+
+ static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+ {
+diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
+index 2bc5c92..40c2026 100644
+--- a/drivers/video/omap/lcd_overo.c
++++ b/drivers/video/omap/lcd_overo.c
+@@ -22,10 +22,10 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+ #include <mach/mux.h>
+-#include <mach/omapfb.h>
+ #include <asm/mach-types.h>
+
+ #define LCD_ENABLE 144
+diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
+index 2183173..dcb456c 100644
+--- a/drivers/video/omap/lcd_palmte.c
++++ b/drivers/video/omap/lcd_palmte.c
+@@ -22,9 +22,9 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/fpga.h>
+-#include <mach/omapfb.h>
+
+ static int palmte_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
+index 57b0f6c..e8adab8 100644
+--- a/drivers/video/omap/lcd_palmtt.c
++++ b/drivers/video/omap/lcd_palmtt.c
+@@ -28,9 +28,9 @@ GPIO13 - screen blanking
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/gpio.h>
+-#include <mach/omapfb.h>
+
+ static int palmtt_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
+index d33d78b..d5b3f82 100644
+--- a/drivers/video/omap/lcd_palmz71.c
++++ b/drivers/video/omap/lcd_palmz71.c
+@@ -23,8 +23,7 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+-
+-#include <mach/omapfb.h>
++#include <linux/omapfb.h>
+
+ static int palmz71_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
+index ab39492..633e33c 100644
+--- a/drivers/video/omap/lcdc.c
++++ b/drivers/video/omap/lcdc.c
+@@ -28,9 +28,9 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/vmalloc.h>
+ #include <linux/clk.h>
++#include <linux/omapfb.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
+ #include <asm/mach-types.h>
+
+diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
+index 0df4523..a06f964 100644
+--- a/drivers/video/omap/omapfb_main.c
++++ b/drivers/video/omap/omapfb_main.c
+@@ -27,9 +27,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/mm.h>
+ #include <linux/uaccess.h>
++#include <linux/omapfb.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
+ #include "lcdc.h"
+ #include "dispc.h"
+diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
+index ee01e84..9040678 100644
+--- a/drivers/video/omap/rfbi.c
++++ b/drivers/video/omap/rfbi.c
+@@ -26,8 +26,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/clk.h>
+ #include <linux/io.h>
+-
+-#include <mach/omapfb.h>
++#include <linux/omapfb.h>
+
+ #include "dispc.h"
+
+diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
+index a769462..cab398f 100644
+--- a/drivers/video/omap/sossi.c
++++ b/drivers/video/omap/sossi.c
+@@ -23,9 +23,9 @@
+ #include <linux/clk.h>
+ #include <linux/irq.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <mach/dma.h>
+-#include <mach/omapfb.h>
+
+ #include "lcdc.h"
+
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+new file mode 100644
+index 0000000..b226bdf
+--- /dev/null
++++ b/include/linux/omapfb.h
+@@ -0,0 +1,398 @@
++/*
++ * File: arch/arm/plat-omap/include/mach/omapfb.h
++ *
++ * Framebuffer driver for TI OMAP boards
++ *
++ * Copyright (C) 2004 Nokia Corporation
++ * Author: Imre Deak <imre.deak@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __OMAPFB_H
++#define __OMAPFB_H
++
++#include <asm/ioctl.h>
++#include <asm/types.h>
++
++/* IOCTL commands. */
++
++#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
++#define OMAP_IOR(num, dtype) _IOR('O', num, dtype)
++#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
++#define OMAP_IO(num) _IO('O', num)
++
++#define OMAPFB_MIRROR OMAP_IOW(31, int)
++#define OMAPFB_SYNC_GFX OMAP_IO(37)
++#define OMAPFB_VSYNC OMAP_IO(38)
++#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
++#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps)
++#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
++#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
++#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
++#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old)
++#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key)
++#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key)
++#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info)
++#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info)
++#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
++#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
++#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
++
++#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
++#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
++#define OMAPFB_CAPS_PANEL_MASK 0xff000000
++
++#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000
++#define OMAPFB_CAPS_TEARSYNC 0x00002000
++#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000
++#define OMAPFB_CAPS_PLANE_SCALE 0x00008000
++#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000
++#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000
++#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000
++#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000
++#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000
++
++/* Values from DSP must map to lower 16-bits */
++#define OMAPFB_FORMAT_MASK 0x00ff
++#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100
++#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200
++#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400
++#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800
++#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000
++
++#define OMAPFB_EVENT_READY 1
++#define OMAPFB_EVENT_DISABLED 2
++
++#define OMAPFB_MEMTYPE_SDRAM 0
++#define OMAPFB_MEMTYPE_SRAM 1
++#define OMAPFB_MEMTYPE_MAX 1
++
++enum omapfb_color_format {
++ OMAPFB_COLOR_RGB565 = 0,
++ OMAPFB_COLOR_YUV422,
++ OMAPFB_COLOR_YUV420,
++ OMAPFB_COLOR_CLUT_8BPP,
++ OMAPFB_COLOR_CLUT_4BPP,
++ OMAPFB_COLOR_CLUT_2BPP,
++ OMAPFB_COLOR_CLUT_1BPP,
++ OMAPFB_COLOR_RGB444,
++ OMAPFB_COLOR_YUY422,
++};
++
++struct omapfb_update_window {
++ __u32 x, y;
++ __u32 width, height;
++ __u32 format;
++ __u32 out_x, out_y;
++ __u32 out_width, out_height;
++ __u32 reserved[8];
++};
++
++struct omapfb_update_window_old {
++ __u32 x, y;
++ __u32 width, height;
++ __u32 format;
++};
++
++enum omapfb_plane {
++ OMAPFB_PLANE_GFX = 0,
++ OMAPFB_PLANE_VID1,
++ OMAPFB_PLANE_VID2,
++};
++
++enum omapfb_channel_out {
++ OMAPFB_CHANNEL_OUT_LCD = 0,
++ OMAPFB_CHANNEL_OUT_DIGIT,
++};
++
++struct omapfb_plane_info {
++ __u32 pos_x;
++ __u32 pos_y;
++ __u8 enabled;
++ __u8 channel_out;
++ __u8 mirror;
++ __u8 reserved1;
++ __u32 out_width;
++ __u32 out_height;
++ __u32 reserved2[12];
++};
++
++struct omapfb_mem_info {
++ __u32 size;
++ __u8 type;
++ __u8 reserved[3];
++};
++
++struct omapfb_caps {
++ __u32 ctrl;
++ __u32 plane_color;
++ __u32 wnd_color;
++};
++
++enum omapfb_color_key_type {
++ OMAPFB_COLOR_KEY_DISABLED = 0,
++ OMAPFB_COLOR_KEY_GFX_DST,
++ OMAPFB_COLOR_KEY_VID_SRC,
++};
++
++struct omapfb_color_key {
++ __u8 channel_out;
++ __u32 background;
++ __u32 trans_key;
++ __u8 key_type;
++};
++
++enum omapfb_update_mode {
++ OMAPFB_UPDATE_DISABLED = 0,
++ OMAPFB_AUTO_UPDATE,
++ OMAPFB_MANUAL_UPDATE
++};
++
++#ifdef __KERNEL__
++
++#include <linux/completion.h>
++#include <linux/interrupt.h>
++#include <linux/fb.h>
++#include <linux/mutex.h>
++
++#include <mach/board.h>
++
++#define OMAP_LCDC_INV_VSYNC 0x0001
++#define OMAP_LCDC_INV_HSYNC 0x0002
++#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
++#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
++#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
++#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
++
++#define OMAP_LCDC_SIGNAL_MASK 0x003f
++
++#define OMAP_LCDC_PANEL_TFT 0x0100
++
++#define OMAPFB_PLANE_XRES_MIN 8
++#define OMAPFB_PLANE_YRES_MIN 8
++
++#ifdef CONFIG_ARCH_OMAP1
++#define OMAPFB_PLANE_NUM 1
++#else
++#define OMAPFB_PLANE_NUM 3
++#endif
++
++struct omapfb_device;
++
++struct lcd_panel {
++ const char *name;
++ int config; /* TFT/STN, signal inversion */
++ int bpp; /* Pixel format in fb mem */
++ int data_lines; /* Lines on LCD HW interface */
++
++ int x_res, y_res;
++ int pixel_clock; /* In kHz */
++ int hsw; /* Horizontal synchronization
++ pulse width */
++ int hfp; /* Horizontal front porch */
++ int hbp; /* Horizontal back porch */
++ int vsw; /* Vertical synchronization
++ pulse width */
++ int vfp; /* Vertical front porch */
++ int vbp; /* Vertical back porch */
++ int acb; /* ac-bias pin frequency */
++ int pcd; /* pixel clock divider.
++ Obsolete use pixel_clock instead */
++
++ int (*init) (struct lcd_panel *panel,
++ struct omapfb_device *fbdev);
++ void (*cleanup) (struct lcd_panel *panel);
++ int (*enable) (struct lcd_panel *panel);
++ void (*disable) (struct lcd_panel *panel);
++ unsigned long (*get_caps) (struct lcd_panel *panel);
++ int (*set_bklight_level)(struct lcd_panel *panel,
++ unsigned int level);
++ unsigned int (*get_bklight_level)(struct lcd_panel *panel);
++ unsigned int (*get_bklight_max) (struct lcd_panel *panel);
++ int (*run_test) (struct lcd_panel *panel, int test_num);
++};
++
++struct extif_timings {
++ int cs_on_time;
++ int cs_off_time;
++ int we_on_time;
++ int we_off_time;
++ int re_on_time;
++ int re_off_time;
++ int we_cycle_time;
++ int re_cycle_time;
++ int cs_pulse_width;
++ int access_time;
++
++ int clk_div;
++
++ u32 tim[5]; /* set by extif->convert_timings */
++
++ int converted;
++};
++
++struct lcd_ctrl_extif {
++ int (*init) (struct omapfb_device *fbdev);
++ void (*cleanup) (void);
++ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
++ unsigned long (*get_max_tx_rate)(void);
++ int (*convert_timings) (struct extif_timings *timings);
++ void (*set_timings) (const struct extif_timings *timings);
++ void (*set_bits_per_cycle)(int bpc);
++ void (*write_command) (const void *buf, unsigned int len);
++ void (*read_data) (void *buf, unsigned int len);
++ void (*write_data) (const void *buf, unsigned int len);
++ void (*transfer_area) (int width, int height,
++ void (callback)(void * data), void *data);
++ int (*setup_tearsync) (unsigned pin_cnt,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int div);
++ int (*enable_tearsync) (int enable, unsigned line);
++
++ unsigned long max_transmit_size;
++};
++
++struct omapfb_notifier_block {
++ struct notifier_block nb;
++ void *data;
++ int plane_idx;
++};
++
++typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
++ unsigned long event,
++ void *fbi);
++
++struct omapfb_mem_region {
++ u32 paddr;
++ void __iomem *vaddr;
++ unsigned long size;
++ u8 type; /* OMAPFB_PLANE_MEM_* */
++ unsigned alloc:1; /* allocated by the driver */
++ unsigned map:1; /* kernel mapped by the driver */
++};
++
++struct omapfb_mem_desc {
++ int region_cnt;
++ struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
++};
++
++struct lcd_ctrl {
++ const char *name;
++ void *data;
++
++ int (*init) (struct omapfb_device *fbdev,
++ int ext_mode,
++ struct omapfb_mem_desc *req_md);
++ void (*cleanup) (void);
++ void (*bind_client) (struct omapfb_notifier_block *nb);
++ void (*get_caps) (int plane, struct omapfb_caps *caps);
++ int (*set_update_mode)(enum omapfb_update_mode mode);
++ enum omapfb_update_mode (*get_update_mode)(void);
++ int (*setup_plane) (int plane, int channel_out,
++ unsigned long offset,
++ int screen_width,
++ int pos_x, int pos_y, int width,
++ int height, int color_mode);
++ int (*set_rotate) (int angle);
++ int (*setup_mem) (int plane, size_t size,
++ int mem_type, unsigned long *paddr);
++ int (*mmap) (struct fb_info *info,
++ struct vm_area_struct *vma);
++ int (*set_scale) (int plane,
++ int orig_width, int orig_height,
++ int out_width, int out_height);
++ int (*enable_plane) (int plane, int enable);
++ int (*update_window) (struct fb_info *fbi,
++ struct omapfb_update_window *win,
++ void (*callback)(void *),
++ void *callback_data);
++ void (*sync) (void);
++ void (*suspend) (void);
++ void (*resume) (void);
++ int (*run_test) (int test_num);
++ int (*setcolreg) (u_int regno, u16 red, u16 green,
++ u16 blue, u16 transp,
++ int update_hw_mem);
++ int (*set_color_key) (struct omapfb_color_key *ck);
++ int (*get_color_key) (struct omapfb_color_key *ck);
++};
++
++enum omapfb_state {
++ OMAPFB_DISABLED = 0,
++ OMAPFB_SUSPENDED= 99,
++ OMAPFB_ACTIVE = 100
++};
++
++struct omapfb_plane_struct {
++ int idx;
++ struct omapfb_plane_info info;
++ enum omapfb_color_format color_mode;
++ struct omapfb_device *fbdev;
++};
++
++struct omapfb_device {
++ int state;
++ int ext_lcdc; /* Using external
++ LCD controller */
++ struct mutex rqueue_mutex;
++
++ int palette_size;
++ u32 pseudo_palette[17];
++
++ struct lcd_panel *panel; /* LCD panel */
++ const struct lcd_ctrl *ctrl; /* LCD controller */
++ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
++ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
++ interface */
++ struct device *dev;
++ struct fb_var_screeninfo new_var; /* for mode changes */
++
++ struct omapfb_mem_desc mem_desc;
++ struct fb_info *fb_info[OMAPFB_PLANE_NUM];
++};
++
++struct omapfb_platform_data {
++ struct omap_lcd_config lcd;
++ struct omapfb_mem_desc mem_desc;
++ void *ctrl_platform_data;
++};
++
++#ifdef CONFIG_ARCH_OMAP1
++extern struct lcd_ctrl omap1_lcd_ctrl;
++#else
++extern struct lcd_ctrl omap2_disp_ctrl;
++#endif
++
++extern void omapfb_reserve_sdram(void);
++extern void omapfb_register_panel(struct lcd_panel *panel);
++extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
++extern void omapfb_notify_clients(struct omapfb_device *fbdev,
++ unsigned long event);
++extern int omapfb_register_client(struct omapfb_notifier_block *nb,
++ omapfb_notifier_callback_t callback,
++ void *callback_data);
++extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
++extern int omapfb_update_window_async(struct fb_info *fbi,
++ struct omapfb_update_window *win,
++ void (*callback)(void *),
++ void *callback_data);
++
++/* in arch/arm/plat-omap/fb.c */
++extern void omapfb_set_ctrl_platform_data(void *pdata);
++
++#endif /* __KERNEL__ */
++
++#endif /* __OMAPFB_H */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0002-DSS2-OMAP2-3-Display-Subsystem-driver.patch b/recipes/linux/linux-omap-pm/dss2/0002-DSS2-OMAP2-3-Display-Subsystem-driver.patch
new file mode 100644
index 0000000000..0b8e2e2c6b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0002-DSS2-OMAP2-3-Display-Subsystem-driver.patch
@@ -0,0 +1,14450 @@
+From 8dd3bdbcdeba2b9ebba84ac6dde99c3673c08437 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 10:23:42 +0300
+Subject: [PATCH 002/146] DSS2: OMAP2/3 Display Subsystem driver
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ Documentation/arm/OMAP/DSS | 311 +++
+ arch/arm/plat-omap/Makefile | 2 +-
+ arch/arm/plat-omap/include/mach/display.h | 520 ++++
+ arch/arm/plat-omap/include/mach/vram.h | 33 +
+ arch/arm/plat-omap/include/mach/vrfb.h | 47 +
+ arch/arm/plat-omap/vram.c | 615 +++++
+ arch/arm/plat-omap/vrfb.c | 159 ++
+ drivers/video/Kconfig | 1 +
+ drivers/video/Makefile | 1 +
+ drivers/video/omap2/Kconfig | 3 +
+ drivers/video/omap2/Makefile | 4 +
+ drivers/video/omap2/dss/Kconfig | 89 +
+ drivers/video/omap2/dss/Makefile | 6 +
+ drivers/video/omap2/dss/core.c | 641 +++++
+ drivers/video/omap2/dss/dispc.c | 2968 +++++++++++++++++++++++
+ drivers/video/omap2/dss/display.c | 693 ++++++
+ drivers/video/omap2/dss/dpi.c | 393 +++
+ drivers/video/omap2/dss/dsi.c | 3752 +++++++++++++++++++++++++++++
+ drivers/video/omap2/dss/dss.c | 345 +++
+ drivers/video/omap2/dss/dss.h | 331 +++
+ drivers/video/omap2/dss/manager.c | 576 +++++
+ drivers/video/omap2/dss/overlay.c | 587 +++++
+ drivers/video/omap2/dss/rfbi.c | 1304 ++++++++++
+ drivers/video/omap2/dss/sdi.c | 245 ++
+ drivers/video/omap2/dss/venc.c | 600 +++++
+ 25 files changed, 14225 insertions(+), 1 deletions(-)
+ create mode 100644 Documentation/arm/OMAP/DSS
+ create mode 100644 arch/arm/plat-omap/include/mach/display.h
+ create mode 100644 arch/arm/plat-omap/include/mach/vram.h
+ create mode 100644 arch/arm/plat-omap/include/mach/vrfb.h
+ create mode 100644 arch/arm/plat-omap/vram.c
+ create mode 100644 arch/arm/plat-omap/vrfb.c
+ create mode 100644 drivers/video/omap2/Kconfig
+ create mode 100644 drivers/video/omap2/Makefile
+ create mode 100644 drivers/video/omap2/dss/Kconfig
+ create mode 100644 drivers/video/omap2/dss/Makefile
+ create mode 100644 drivers/video/omap2/dss/core.c
+ create mode 100644 drivers/video/omap2/dss/dispc.c
+ create mode 100644 drivers/video/omap2/dss/display.c
+ create mode 100644 drivers/video/omap2/dss/dpi.c
+ create mode 100644 drivers/video/omap2/dss/dsi.c
+ create mode 100644 drivers/video/omap2/dss/dss.c
+ create mode 100644 drivers/video/omap2/dss/dss.h
+ create mode 100644 drivers/video/omap2/dss/manager.c
+ create mode 100644 drivers/video/omap2/dss/overlay.c
+ create mode 100644 drivers/video/omap2/dss/rfbi.c
+ create mode 100644 drivers/video/omap2/dss/sdi.c
+ create mode 100644 drivers/video/omap2/dss/venc.c
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+new file mode 100644
+index 0000000..9e902a2
+--- /dev/null
++++ b/Documentation/arm/OMAP/DSS
+@@ -0,0 +1,311 @@
++OMAP2/3 Display Subsystem
++-------------------------
++
++This is an almost total rewrite of the OMAP FB driver in drivers/video/omap
++(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI,
++TV-out and multiple display support, but there are lots of small improvements
++also.
++
++The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB,
++panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live
++currently side by side, you can choose which one to use.
++
++Features
++--------
++
++Working and tested features include:
++
++- MIPI DPI (parallel) output
++- MIPI DSI output in command mode
++- MIPI DBI (RFBI) output
++- SDI output
++- TV output
++- All pieces can be compiled as a module or inside kernel
++- Use DISPC to update any of the outputs
++- Use CPU to update RFBI or DSI output
++- OMAP DISPC planes
++- RGB16, RGB24 packed, RGB24 unpacked
++- YUV2, UYVY
++- Scaling
++- Adjusting DSS FCK to find a good pixel clock
++- Use DSI DPLL to create DSS FCK
++
++Tested boards include:
++- OMAP3 SDP board
++- Beagle board
++- N810
++
++omapdss driver
++--------------
++
++The DSS driver does not itself have any support for Linux framebuffer, V4L or
++such like the current ones, but it has an internal kernel API that upper level
++drivers can use.
++
++The DSS driver models OMAP's overlays, overlay managers and displays in a
++flexible way to enable non-common multi-display configuration. In addition to
++modelling the hardware overlays, omapdss supports virtual overlays and overlay
++managers. These can be used when updating a display with CPU or system DMA.
++
++Panel and controller drivers
++----------------------------
++
++The drivers implement panel or controller specific functionality and are not
++usually visible to users except through omapfb driver. They register
++themselves to the DSS driver.
++
++omapfb driver
++-------------
++
++The omapfb driver implements arbitrary number of standard linux framebuffers.
++These framebuffers can be routed flexibly to any overlays, thus allowing very
++dynamic display architecture.
++
++The driver exports some omapfb specific ioctls, which are compatible with the
++ioctls in the old driver.
++
++The rest of the non standard features are exported via sysfs. Whether the final
++implementation will use sysfs, or ioctls, is still open.
++
++V4L2 drivers
++------------
++
++V4L2 is being implemented in TI.
++
++From omapdss point of view the V4L2 drivers should be similar to framebuffer
++driver.
++
++Architecture
++--------------------
++
++Some clarification what the different components do:
++
++ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the
++ pixel data for the image. Framebuffer has width and height and color
++ depth.
++ - Overlay defines where the pixels are read from and where they go on the
++ screen. The overlay may be smaller than framebuffer, thus displaying only
++ part of the framebuffer. The position of the overlay may be changed if
++ the overlay is smaller than the display.
++ - Overlay manager combines the overlays in to one image and feeds them to
++ display.
++ - Display is the actual physical display device.
++
++A framebuffer can be connected to multiple overlays to show the same pixel data
++on all of the overlays. Note that in this case the overlay input sizes must be
++the same, but, in case of video overlays, the output size can be different. Any
++framebuffer can be connected to any overlay.
++
++An overlay can be connected to one overlay manager. Also DISPC overlays can be
++connected only to DISPC overlay managers, and virtual overlays can be only
++connected to virtual overlays.
++
++An overlay manager can be connected to one display. There are certain
++restrictions which kinds of displays an overlay manager can be connected:
++
++ - DISPC TV overlay manager can be only connected to TV display.
++ - Virtual overlay managers can only be connected to DBI or DSI displays.
++ - DISPC LCD overlay manager can be connected to all displays, except TV
++ display.
++
++Sysfs
++-----
++The sysfs interface is mainly used for testing. I don't think sysfs
++interface is the best for this in the final version, but I don't quite know
++what would be the best interfaces for these things.
++
++The sysfs interface is divided to two parts: DSS and FB.
++
++/sys/class/graphics/fb? directory:
++mirror 0=off, 1=on
++rotate Rotation 0-3 for 0, 90, 180, 270 degrees
++rotate_type 0 = DMA rotation, 1 = VRFB rotation
++overlays List of overlay numbers to which framebuffer pixels go
++phys_addr Physical address of the framebuffer
++virt_addr Virtual address of the framebuffer
++size Size of the framebuffer
++
++/sys/devices/platform/omapdss/overlay? directory:
++enabled 0=off, 1=on
++input_size width,height (ie. the framebuffer size)
++manager Destination overlay manager name
++name
++output_size width,height
++position x,y
++screen_width width
++
++/sys/devices/platform/omapdss/manager? directory:
++display Destination display
++name
++
++/sys/devices/platform/omapdss/display? directory:
++ctrl_name Controller name
++mirror 0=off, 1=on
++update_mode 0=off, 1=auto, 2=manual
++enabled 0=off, 1=on
++name
++rotate Rotation 0-3 for 0, 90, 180, 270 degrees
++timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
++ When writing, two special timings are accepted for tv-out:
++ "pal" and "ntsc"
++panel_name
++tear_elim Tearing elimination 0=off, 1=on
++
++There are also some debugfs files at <debugfs>/omapdss/ which show information
++about clocks and registers.
++
++Examples
++--------
++
++The following definitions have been made for the examples below:
++
++ovl0=/sys/devices/platform/omapdss/overlay0
++ovl1=/sys/devices/platform/omapdss/overlay1
++ovl2=/sys/devices/platform/omapdss/overlay2
++
++mgr0=/sys/devices/platform/omapdss/manager0
++mgr1=/sys/devices/platform/omapdss/manager1
++
++lcd=/sys/devices/platform/omapdss/display0
++dvi=/sys/devices/platform/omapdss/display1
++tv=/sys/devices/platform/omapdss/display2
++
++fb0=/sys/class/graphics/fb0
++fb1=/sys/class/graphics/fb1
++fb2=/sys/class/graphics/fb2
++
++Default setup on OMAP3 SDP
++--------------------------
++
++Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI
++and TV-out are not in use. The columns from left to right are:
++framebuffers, overlays, overlay managers, displays. Framebuffers are
++handled by omapfb, and the rest by the DSS.
++
++FB0 --- GFX -\ DVI
++FB1 --- VID1 --+- LCD ---- LCD
++FB2 --- VID2 -/ TV ----- TV
++
++Example: Switch from LCD to DVI
++----------------------
++
++w=`cat $dvi/horizontal | cut -d "," -f 1`
++h=`cat $dvi/vertical | cut -d "," -f 1`
++
++echo "0" > $lcd/enabled
++echo "" > $mgr0/display
++fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
++# at this point you have to switch the dvi/lcd dip-switch from the omap board
++echo "dvi" > $mgr0/display
++echo "1" > $dvi/enabled
++
++After this the configuration looks like:
++
++FB0 --- GFX -\ -- DVI
++FB1 --- VID1 --+- LCD -/ LCD
++FB2 --- VID2 -/ TV ----- TV
++
++Example: Clone GFX overlay to LCD and TV
++-------------------------------
++
++w=`cat $tv/horizontal | cut -d "," -f 1`
++h=`cat $tv/vertical | cut -d "," -f 1`
++
++echo "0" > $ovl0/enabled
++echo "0" > $ovl1/enabled
++
++echo "" > $fb1/overlays
++echo "0,1" > $fb0/overlays
++
++echo "$w,$h" > $ovl1/output_size
++echo "tv" > $ovl1/manager
++
++echo "1" > $ovl0/enabled
++echo "1" > $ovl1/enabled
++
++echo "1" > $tv/enabled
++
++After this the configuration looks like (only relevant parts shown):
++
++FB0 +-- GFX ---- LCD ---- LCD
++ \- VID1 ---- TV ---- TV
++
++Misc notes
++----------
++
++OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
++
++Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
++of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
++
++Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB
++does not support mirroring.
++
++VRFB rotation requires much more memory than non-rotated framebuffer, so you
++probably need to increase your vram setting before using VRFB rotation. Also,
++many applications may not work with VRFB if they do not pay attention to all
++framebuffer parameters.
++
++Kernel boot arguments
++---------------------
++
++vram=<size>
++ - Amount of total VRAM to preallocate. For example, "10M". omapfb
++ allocates memory for framebuffers from VRAM.
++
++omapfb.mode=<display>:<mode>[,...]
++ - Default video mode for specified displays. For example,
++ "dvi:800x400MR-24@60". See drivers/video/modedb.c.
++ There are also two special modes: "pal" and "ntsc" that
++ can be used to tv out.
++
++omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
++ - VRAM allocated for a framebuffer. Normally omapfb allocates vram
++ depending on the display size. With this you can manually allocate
++ more or define the physical address of each framebuffer. For example,
++ "1:4M" to allocate 4M for fb1.
++
++omapfb.debug=<y|n>
++ - Enable debug printing. You have to have OMAPFB debug support enabled
++ in kernel config.
++
++omapfb.test=<y|n>
++ - Draw test pattern to framebuffer whenever framebuffer settings change.
++ You need to have OMAPFB debug support enabled in kernel config.
++
++omapfb.vrfb=<y|n>
++ - Use VRFB rotation for all framebuffers.
++
++omapfb.rotate=<angle>
++ - Default rotation applied to all framebuffers.
++ 0 - 0 degree rotation
++ 1 - 90 degree rotation
++ 2 - 180 degree rotation
++ 3 - 270 degree rotation
++
++omapfb.mirror=<y|n>
++ - Default mirror for all framebuffers. Only works with DMA rotation.
++
++omapdss.def_disp=<display>
++ - Name of default display, to which all overlays will be connected.
++ Common examples are "lcd" or "tv".
++
++omapdss.debug=<y|n>
++ - Enable debug printing. You have to have DSS debug support enabled in
++ kernel config.
++
++TODO
++----
++
++DSS locking
++
++Error checking
++- Lots of checks are missing or implemented just as BUG()
++
++System DMA update for DSI
++- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how
++ to skip the empty byte?)
++
++OMAP1 support
++- Not sure if needed
++
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index a832795..cfc0967 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -4,7 +4,7 @@
+
+ # Common support
+ obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
+- usb.o fb.o io.o
++ usb.o fb.o vram.o vrfb.o io.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+new file mode 100644
+index 0000000..6288353
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -0,0 +1,520 @@
++/*
++ * linux/include/asm-arm/arch-omap/display.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ASM_ARCH_OMAP_DISPLAY_H
++#define __ASM_ARCH_OMAP_DISPLAY_H
++
++#include <linux/list.h>
++#include <linux/kobject.h>
++#include <asm/atomic.h>
++
++#define DISPC_IRQ_FRAMEDONE (1 << 0)
++#define DISPC_IRQ_VSYNC (1 << 1)
++#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
++#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
++#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
++#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
++#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
++#define DISPC_IRQ_GFX_END_WIN (1 << 7)
++#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
++#define DISPC_IRQ_OCP_ERR (1 << 9)
++#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
++#define DISPC_IRQ_VID1_END_WIN (1 << 11)
++#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
++#define DISPC_IRQ_VID2_END_WIN (1 << 13)
++#define DISPC_IRQ_SYNC_LOST (1 << 14)
++#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
++#define DISPC_IRQ_WAKEUP (1 << 16)
++
++enum omap_display_type {
++ OMAP_DISPLAY_TYPE_NONE = 0,
++ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
++ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
++ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
++ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
++ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
++};
++
++enum omap_plane {
++ OMAP_DSS_GFX = 0,
++ OMAP_DSS_VIDEO1 = 1,
++ OMAP_DSS_VIDEO2 = 2
++};
++
++enum omap_channel {
++ OMAP_DSS_CHANNEL_LCD = 0,
++ OMAP_DSS_CHANNEL_DIGIT = 1,
++};
++
++enum omap_color_mode {
++ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
++ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
++ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
++ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
++ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
++ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
++ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
++ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
++ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
++ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
++ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
++ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
++ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
++ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
++
++ OMAP_DSS_COLOR_GFX_OMAP3 =
++ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
++ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
++
++ OMAP_DSS_COLOR_VID_OMAP3 =
++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
++ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
++};
++
++enum omap_lcd_display_type {
++ OMAP_DSS_LCD_DISPLAY_STN,
++ OMAP_DSS_LCD_DISPLAY_TFT,
++};
++
++enum omap_dss_load_mode {
++ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
++ OMAP_DSS_LOAD_CLUT_ONLY = 1,
++ OMAP_DSS_LOAD_FRAME_ONLY = 2,
++ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
++};
++
++enum omap_dss_color_key_type {
++ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
++ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
++};
++
++enum omap_rfbi_te_mode {
++ OMAP_DSS_RFBI_TE_MODE_1 = 1,
++ OMAP_DSS_RFBI_TE_MODE_2 = 2,
++};
++
++enum omap_panel_config {
++ OMAP_DSS_LCD_IVS = 1<<0,
++ OMAP_DSS_LCD_IHS = 1<<1,
++ OMAP_DSS_LCD_IPC = 1<<2,
++ OMAP_DSS_LCD_IEO = 1<<3,
++ OMAP_DSS_LCD_RF = 1<<4,
++ OMAP_DSS_LCD_ONOFF = 1<<5,
++
++ OMAP_DSS_LCD_TFT = 1<<20,
++};
++
++enum omap_dss_venc_type {
++ OMAP_DSS_VENC_TYPE_COMPOSITE,
++ OMAP_DSS_VENC_TYPE_SVIDEO,
++};
++
++struct omap_display;
++struct omap_panel;
++struct omap_ctrl;
++
++/* RFBI */
++
++struct rfbi_timings {
++ int cs_on_time;
++ int cs_off_time;
++ int we_on_time;
++ int we_off_time;
++ int re_on_time;
++ int re_off_time;
++ int we_cycle_time;
++ int re_cycle_time;
++ int cs_pulse_width;
++ int access_time;
++
++ int clk_div;
++
++ u32 tim[5]; /* set by rfbi_convert_timings() */
++
++ int converted;
++};
++
++void omap_rfbi_write_command(const void *buf, u32 len);
++void omap_rfbi_read_data(void *buf, u32 len);
++void omap_rfbi_write_data(const void *buf, u32 len);
++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
++ u16 x, u16 y,
++ u16 w, u16 h);
++int omap_rfbi_enable_te(bool enable, unsigned line);
++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int extif_div);
++
++/* DSI */
++int dsi_vc_dcs_write(int channel, u8 *data, int len);
++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
++int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
++int dsi_vc_send_null(int channel);
++
++/* Board specific data */
++struct omap_dss_display_config {
++ enum omap_display_type type;
++
++ union {
++ struct {
++ u8 data_lines;
++ } dpi;
++
++ struct {
++ u8 channel;
++ u8 data_lines;
++ } rfbi;
++
++ struct {
++ u8 datapairs;
++ } sdi;
++
++ struct {
++ u8 clk_lane;
++ u8 clk_pol;
++ u8 data1_lane;
++ u8 data1_pol;
++ u8 data2_lane;
++ u8 data2_pol;
++ unsigned long ddr_clk_hz;
++ } dsi;
++
++ struct {
++ enum omap_dss_venc_type type;
++ } venc;
++ } u;
++
++ int panel_reset_gpio;
++ int ctrl_reset_gpio;
++
++ const char *name; /* for debug */
++ const char *ctrl_name;
++ const char *panel_name;
++
++ void *panel_data;
++ void *ctrl_data;
++
++ /* platform specific enable/disable */
++ int (*panel_enable)(struct omap_display *display);
++ void (*panel_disable)(struct omap_display *display);
++ int (*ctrl_enable)(struct omap_display *display);
++ void (*ctrl_disable)(struct omap_display *display);
++ int (*set_backlight)(struct omap_display *display,
++ int level);
++};
++
++struct device;
++
++/* Board specific data */
++struct omap_dss_board_info {
++ unsigned (*get_last_off_on_transaction_id)(struct device *dev);
++ int (*dsi_power_up)(void);
++ void (*dsi_power_down)(void);
++ int num_displays;
++ struct omap_dss_display_config *displays[];
++};
++
++struct omap_ctrl {
++ struct module *owner;
++
++ const char *name;
++
++ int (*init)(struct omap_display *display);
++ void (*cleanup)(struct omap_display *display);
++ int (*enable)(struct omap_display *display);
++ void (*disable)(struct omap_display *display);
++ int (*suspend)(struct omap_display *display);
++ int (*resume)(struct omap_display *display);
++ void (*setup_update)(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h);
++
++ int (*enable_te)(struct omap_display *display, bool enable);
++
++ u8 (*get_rotate)(struct omap_display *display);
++ int (*set_rotate)(struct omap_display *display, u8 rotate);
++
++ bool (*get_mirror)(struct omap_display *display);
++ int (*set_mirror)(struct omap_display *display, bool enable);
++
++ int (*run_test)(struct omap_display *display, int test);
++ int (*memory_read)(struct omap_display *display,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h);
++
++ u8 pixel_size;
++
++ struct rfbi_timings timings;
++
++ void *priv;
++};
++
++struct omap_video_timings {
++ /* Unit: pixels */
++ u16 x_res;
++ /* Unit: pixels */
++ u16 y_res;
++ /* Unit: KHz */
++ u32 pixel_clock;
++ /* Unit: pixel clocks */
++ u16 hsw; /* Horizontal synchronization pulse width */
++ /* Unit: pixel clocks */
++ u16 hfp; /* Horizontal front porch */
++ /* Unit: pixel clocks */
++ u16 hbp; /* Horizontal back porch */
++ /* Unit: line clocks */
++ u16 vsw; /* Vertical synchronization pulse width */
++ /* Unit: line clocks */
++ u16 vfp; /* Vertical front porch */
++ /* Unit: line clocks */
++ u16 vbp; /* Vertical back porch */
++
++};
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++/* Hardcoded timings for tv modes. Venc only uses these to
++ * identify the mode, and does not actually use the configs
++ * itself. However, the configs should be something that
++ * a normal monitor can also show */
++const extern struct omap_video_timings omap_dss_pal_timings;
++const extern struct omap_video_timings omap_dss_ntsc_timings;
++#endif
++
++struct omap_panel {
++ struct module *owner;
++
++ const char *name;
++
++ int (*init)(struct omap_display *display);
++ void (*cleanup)(struct omap_display *display);
++ int (*remove)(struct omap_display *display);
++ int (*enable)(struct omap_display *display);
++ void (*disable)(struct omap_display *display);
++ int (*suspend)(struct omap_display *display);
++ int (*resume)(struct omap_display *display);
++ int (*run_test)(struct omap_display *display, int test);
++
++ struct omap_video_timings timings;
++
++ int acbi; /* ac-bias pin transitions per interrupt */
++ /* Unit: line clocks */
++ int acb; /* ac-bias pin frequency */
++
++ enum omap_panel_config config;
++
++ u8 recommended_bpp;
++
++ void *priv;
++};
++
++/* XXX perhaps this should be removed */
++enum omap_dss_overlay_managers {
++ OMAP_DSS_OVL_MGR_LCD,
++ OMAP_DSS_OVL_MGR_TV,
++};
++
++struct omap_overlay_manager;
++
++struct omap_overlay_info {
++ bool enabled;
++
++ u32 paddr;
++ void __iomem *vaddr;
++ u16 screen_width;
++ u16 width;
++ u16 height;
++ enum omap_color_mode color_mode;
++ u8 rotation;
++ bool mirror;
++
++ u16 pos_x;
++ u16 pos_y;
++ u16 out_width; /* if 0, out_width == width */
++ u16 out_height; /* if 0, out_height == height */
++};
++
++enum omap_overlay_caps {
++ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
++ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
++};
++
++struct omap_overlay {
++ struct kobject kobj;
++ struct list_head list;
++
++ const char *name;
++ int id;
++ struct omap_overlay_manager *manager;
++ enum omap_color_mode supported_modes;
++ struct omap_overlay_info info;
++ enum omap_overlay_caps caps;
++
++ int (*set_manager)(struct omap_overlay *ovl,
++ struct omap_overlay_manager *mgr);
++ int (*unset_manager)(struct omap_overlay *ovl);
++
++ int (*set_overlay_info)(struct omap_overlay *ovl,
++ struct omap_overlay_info *info);
++ void (*get_overlay_info)(struct omap_overlay *ovl,
++ struct omap_overlay_info *info);
++};
++
++enum omap_overlay_manager_caps {
++ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
++};
++
++struct omap_overlay_manager {
++ struct kobject kobj;
++ struct list_head list;
++
++ const char *name;
++ int id;
++ enum omap_overlay_manager_caps caps;
++ struct omap_display *display;
++ int num_overlays;
++ struct omap_overlay **overlays;
++ enum omap_display_type supported_displays;
++
++ int (*set_display)(struct omap_overlay_manager *mgr,
++ struct omap_display *display);
++ int (*unset_display)(struct omap_overlay_manager *mgr);
++
++ int (*apply)(struct omap_overlay_manager *mgr);
++
++ void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
++ void (*set_trans_key)(struct omap_overlay_manager *mgr,
++ enum omap_dss_color_key_type type,
++ u32 trans_key);
++ void (*enable_trans_key)(struct omap_overlay_manager *mgr,
++ bool enable);
++};
++
++enum omap_display_caps {
++ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
++};
++
++enum omap_dss_update_mode {
++ OMAP_DSS_UPDATE_DISABLED = 0,
++ OMAP_DSS_UPDATE_AUTO,
++ OMAP_DSS_UPDATE_MANUAL,
++};
++
++enum omap_dss_display_state {
++ OMAP_DSS_DISPLAY_DISABLED = 0,
++ OMAP_DSS_DISPLAY_ACTIVE,
++ OMAP_DSS_DISPLAY_SUSPENDED,
++};
++
++struct omap_display {
++ struct kobject kobj;
++ struct list_head list;
++
++ /*atomic_t ref_count;*/
++ int ref_count;
++ /* helper variable for driver suspend/resume */
++ int activate_after_resume;
++
++ enum omap_display_type type;
++ const char *name;
++
++ enum omap_display_caps caps;
++
++ struct omap_overlay_manager *manager;
++
++ enum omap_dss_display_state state;
++
++ struct omap_dss_display_config hw_config; /* board specific data */
++ struct omap_ctrl *ctrl; /* static common data */
++ struct omap_panel *panel; /* static common data */
++
++ int (*enable)(struct omap_display *display);
++ void (*disable)(struct omap_display *display);
++
++ int (*suspend)(struct omap_display *display);
++ int (*resume)(struct omap_display *display);
++
++ void (*get_resolution)(struct omap_display *display,
++ u16 *xres, u16 *yres);
++ int (*get_recommended_bpp)(struct omap_display *display);
++
++ int (*check_timings)(struct omap_display *display,
++ struct omap_video_timings *timings);
++ void (*set_timings)(struct omap_display *display,
++ struct omap_video_timings *timings);
++ void (*get_timings)(struct omap_display *display,
++ struct omap_video_timings *timings);
++ int (*update)(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h);
++ int (*sync)(struct omap_display *display);
++ int (*wait_vsync)(struct omap_display *display);
++
++ int (*set_update_mode)(struct omap_display *display,
++ enum omap_dss_update_mode);
++ enum omap_dss_update_mode (*get_update_mode)
++ (struct omap_display *display);
++
++ int (*enable_te)(struct omap_display *display, bool enable);
++ int (*get_te)(struct omap_display *display);
++
++ u8 (*get_rotate)(struct omap_display *display);
++ int (*set_rotate)(struct omap_display *display, u8 rotate);
++
++ bool (*get_mirror)(struct omap_display *display);
++ int (*set_mirror)(struct omap_display *display, bool enable);
++
++ int (*run_test)(struct omap_display *display, int test);
++ int (*memory_read)(struct omap_display *display,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h);
++
++ void (*configure_overlay)(struct omap_overlay *overlay);
++};
++
++int omap_dss_get_num_displays(void);
++struct omap_display *omap_dss_get_display(int no);
++void omap_dss_put_display(struct omap_display *display);
++
++void omap_dss_register_ctrl(struct omap_ctrl *ctrl);
++void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl);
++
++void omap_dss_register_panel(struct omap_panel *panel);
++void omap_dss_unregister_panel(struct omap_panel *panel);
++
++int omap_dss_get_num_overlay_managers(void);
++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
++
++int omap_dss_get_num_overlays(void);
++struct omap_overlay *omap_dss_get_overlay(int num);
++
++typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
++
++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
++ unsigned long timeout);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+new file mode 100644
+index 0000000..f176562
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -0,0 +1,33 @@
++/*
++ * File: arch/arm/plat-omap/include/mach/vram.h
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __OMAPVRAM_H
++#define __OMAPVRAM_H
++
++#include <asm/types.h>
++
++extern int omap_vram_free(unsigned long paddr, size_t size);
++extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
++extern int omap_vram_reserve(unsigned long paddr, size_t size);
++extern void omap2_set_sdram_vram(u32 size, u32 start);
++extern void omap2_set_sram_vram(u32 size, u32 start);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+new file mode 100644
+index 0000000..2047862
+--- /dev/null
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -0,0 +1,47 @@
++/*
++ * File: arch/arm/plat-omap/include/mach/vrfb.h
++ *
++ * VRFB
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __VRFB_H
++#define __VRFB_H
++
++#define OMAP_VRFB_LINE_LEN 2048
++
++struct vrfb
++{
++ u8 context;
++ void __iomem *vaddr[4];
++ unsigned long paddr[4];
++ u16 xoffset;
++ u16 yoffset;
++ u8 bytespp;
++};
++
++extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
++ u8 bytespp);
++extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
++ u16 width, u16 height,
++ u8 bytespp);
++
++#endif /* __VRFB_H */
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+new file mode 100644
+index 0000000..f24a110
+--- /dev/null
++++ b/arch/arm/plat-omap/vram.c
+@@ -0,0 +1,615 @@
++/*
++ * linux/arch/arm/plat-omap/vram.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*#define DEBUG*/
++
++#include <linux/vmalloc.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/list.h>
++#include <linux/dma-mapping.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/bootmem.h>
++#include <linux/omapfb.h>
++
++#include <asm/setup.h>
++
++#include <mach/sram.h>
++#include <mach/vram.h>
++
++#ifdef DEBUG
++#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define OMAP2_SRAM_START 0x40200000
++/* Maximum size, in reality this is smaller if SRAM is partially locked. */
++#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
++
++#define REG_MAP_SIZE(_page_cnt) \
++ ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
++#define REG_MAP_PTR(_rg, _page_nr) \
++ (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
++#define REG_MAP_MASK(_page_nr) \
++ (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
++
++#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
++
++/* postponed regions are used to temporarily store region information at boot
++ * time when we cannot yet allocate the region list */
++#define MAX_POSTPONED_REGIONS 10
++
++static int postponed_cnt __initdata;
++static struct {
++ unsigned long paddr;
++ size_t size;
++} postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
++
++struct vram_alloc {
++ struct list_head list;
++ unsigned long paddr;
++ unsigned pages;
++};
++
++struct vram_region {
++ struct list_head list;
++ struct list_head alloc_list;
++ unsigned long paddr;
++ unsigned pages;
++};
++
++static DEFINE_MUTEX(region_mutex);
++static LIST_HEAD(region_list);
++
++static inline int region_mem_type(unsigned long paddr)
++{
++ if (paddr >= OMAP2_SRAM_START &&
++ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
++ return OMAPFB_MEMTYPE_SRAM;
++ else
++ return OMAPFB_MEMTYPE_SDRAM;
++}
++
++static struct vram_region *omap_vram_create_region(unsigned long paddr,
++ unsigned pages)
++{
++ struct vram_region *rm;
++
++ rm = kzalloc(sizeof(*rm), GFP_KERNEL);
++
++ if (rm) {
++ INIT_LIST_HEAD(&rm->alloc_list);
++ rm->paddr = paddr;
++ rm->pages = pages;
++ }
++
++ return rm;
++}
++
++#if 0
++static void omap_vram_free_region(struct vram_region *vr)
++{
++ list_del(&vr->list);
++ kfree(vr);
++}
++#endif
++
++static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
++ unsigned long paddr, unsigned pages)
++{
++ struct vram_alloc *va;
++ struct vram_alloc *new;
++
++ new = kzalloc(sizeof(*va), GFP_KERNEL);
++
++ if (!new)
++ return NULL;
++
++ new->paddr = paddr;
++ new->pages = pages;
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ if (va->paddr > new->paddr)
++ break;
++ }
++
++ list_add_tail(&new->list, &va->list);
++
++ return new;
++}
++
++static void omap_vram_free_allocation(struct vram_alloc *va)
++{
++ list_del(&va->list);
++ kfree(va);
++}
++
++static __init int omap_vram_add_region_postponed(unsigned long paddr,
++ size_t size)
++{
++ if (postponed_cnt == MAX_POSTPONED_REGIONS)
++ return -ENOMEM;
++
++ postponed_regions[postponed_cnt].paddr = paddr;
++ postponed_regions[postponed_cnt].size = size;
++
++ ++postponed_cnt;
++
++ return 0;
++}
++
++/* add/remove_region can be exported if there's need to add/remove regions
++ * runtime */
++static int omap_vram_add_region(unsigned long paddr, size_t size)
++{
++ struct vram_region *rm;
++ unsigned pages;
++
++ DBG("adding region paddr %08lx size %d\n",
++ paddr, size);
++
++ size &= PAGE_MASK;
++ pages = size >> PAGE_SHIFT;
++
++ rm = omap_vram_create_region(paddr, pages);
++ if (rm == NULL)
++ return -ENOMEM;
++
++ list_add(&rm->list, &region_list);
++
++ return 0;
++}
++
++int omap_vram_free(unsigned long paddr, size_t size)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++ unsigned start, end;
++
++ DBG("free mem paddr %08lx size %d\n", paddr, size);
++
++ size = PAGE_ALIGN(size);
++
++ mutex_lock(&region_mutex);
++
++ list_for_each_entry(rm, &region_list, list) {
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ start = alloc->paddr;
++ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
++
++ if (start >= paddr && end < paddr + size)
++ goto found;
++ }
++ }
++
++ mutex_unlock(&region_mutex);
++ return -EINVAL;
++
++found:
++ omap_vram_free_allocation(alloc);
++
++ mutex_unlock(&region_mutex);
++ return 0;
++}
++EXPORT_SYMBOL(omap_vram_free);
++
++static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++ size_t size;
++
++ size = pages << PAGE_SHIFT;
++
++ list_for_each_entry(rm, &region_list, list) {
++ unsigned long start, end;
++
++ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
++
++ if (region_mem_type(rm->paddr) != region_mem_type(paddr))
++ continue;
++
++ start = rm->paddr;
++ end = start + (rm->pages << PAGE_SHIFT) - 1;
++ if (start > paddr || end < paddr + size - 1)
++ continue;
++
++ DBG("block ok, checking allocs\n");
++
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ end = alloc->paddr - 1;
++
++ if (start <= paddr && end >= paddr + size - 1)
++ goto found;
++
++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
++ }
++
++ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
++
++ if (!(start <= paddr && end >= paddr + size - 1))
++ continue;
++found:
++ DBG("FOUND area start %lx, end %lx\n", start, end);
++
++ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
++ return -ENOMEM;
++
++ return 0;
++ }
++
++ return -ENOMEM;
++}
++
++int omap_vram_reserve(unsigned long paddr, size_t size)
++{
++ unsigned pages;
++ int r;
++
++ DBG("reserve mem paddr %08lx size %d\n", paddr, size);
++
++ size = PAGE_ALIGN(size);
++ pages = size >> PAGE_SHIFT;
++
++ mutex_lock(&region_mutex);
++
++ r = _omap_vram_reserve(paddr, pages);
++
++ mutex_unlock(&region_mutex);
++
++ return r;
++}
++EXPORT_SYMBOL(omap_vram_reserve);
++
++static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
++{
++ struct vram_region *rm;
++ struct vram_alloc *alloc;
++
++ list_for_each_entry(rm, &region_list, list) {
++ unsigned long start, end;
++
++ DBG("checking region %lx %d\n", rm->paddr, rm->pages);
++
++ if (region_mem_type(rm->paddr) != mtype)
++ continue;
++
++ start = rm->paddr;
++
++ list_for_each_entry(alloc, &rm->alloc_list, list) {
++ end = alloc->paddr;
++
++ if (end - start >= pages << PAGE_SHIFT)
++ goto found;
++
++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
++ }
++
++ end = rm->paddr + (rm->pages << PAGE_SHIFT);
++found:
++ if (end - start < pages << PAGE_SHIFT)
++ continue;
++
++ DBG("FOUND %lx, end %lx\n", start, end);
++
++ alloc = omap_vram_create_allocation(rm, start, pages);
++ if (alloc == NULL)
++ return -ENOMEM;
++
++ *paddr = start;
++
++ return 0;
++ }
++
++ return -ENOMEM;
++}
++
++int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
++{
++ unsigned pages;
++ int r;
++
++ BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
++
++ DBG("alloc mem type %d size %d\n", mtype, size);
++
++ size = PAGE_ALIGN(size);
++ pages = size >> PAGE_SHIFT;
++
++ mutex_lock(&region_mutex);
++
++ r = _omap_vram_alloc(mtype, pages, paddr);
++
++ mutex_unlock(&region_mutex);
++
++ return r;
++}
++EXPORT_SYMBOL(omap_vram_alloc);
++
++#ifdef CONFIG_PROC_FS
++static void *r_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ struct list_head *l = v;
++
++ (*pos)++;
++
++ if (list_is_last(l, &region_list))
++ return NULL;
++
++ return l->next;
++}
++
++static void *r_start(struct seq_file *m, loff_t *pos)
++{
++ loff_t p = *pos;
++ struct list_head *l = &region_list;
++
++ mutex_lock(&region_mutex);
++
++ do {
++ l = l->next;
++ if (l == &region_list)
++ return NULL;
++ } while (p--);
++
++ return l;
++}
++
++static void r_stop(struct seq_file *m, void *v)
++{
++ mutex_unlock(&region_mutex);
++}
++
++static int r_show(struct seq_file *m, void *v)
++{
++ struct vram_region *vr;
++ struct vram_alloc *va;
++ unsigned size;
++
++ vr = list_entry(v, struct vram_region, list);
++
++ size = vr->pages << PAGE_SHIFT;
++
++ seq_printf(m, "%08lx-%08lx (%d bytes)\n",
++ vr->paddr, vr->paddr + size - 1,
++ size);
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ size = va->pages << PAGE_SHIFT;
++ seq_printf(m, " %08lx-%08lx (%d bytes)\n",
++ va->paddr, va->paddr + size - 1,
++ size);
++ }
++
++
++
++ return 0;
++}
++
++static const struct seq_operations resource_op = {
++ .start = r_start,
++ .next = r_next,
++ .stop = r_stop,
++ .show = r_show,
++};
++
++static int vram_open(struct inode *inode, struct file *file)
++{
++ return seq_open(file, &resource_op);
++}
++
++static const struct file_operations proc_vram_operations = {
++ .open = vram_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
++static int __init omap_vram_create_proc(void)
++{
++ proc_create("omap-vram", 0, NULL, &proc_vram_operations);
++
++ return 0;
++}
++#endif
++
++static __init int omap_vram_init(void)
++{
++ int i, r;
++
++ for (i = 0; i < postponed_cnt; i++)
++ omap_vram_add_region(postponed_regions[i].paddr,
++ postponed_regions[i].size);
++
++#ifdef CONFIG_PROC_FS
++ r = omap_vram_create_proc();
++ if (r)
++ return -ENOMEM;
++#endif
++
++ return 0;
++}
++
++arch_initcall(omap_vram_init);
++
++/* boottime vram alloc stuff */
++
++/* set from board file */
++static u32 omapfb_sram_vram_start __initdata;
++static u32 omapfb_sram_vram_size __initdata;
++
++/* set from board file */
++static u32 omapfb_sdram_vram_start __initdata;
++static u32 omapfb_sdram_vram_size __initdata;
++
++/* set from kernel cmdline */
++static u32 omapfb_def_sdram_vram_size __initdata;
++static u32 omapfb_def_sdram_vram_start __initdata;
++
++static void __init omapfb_early_vram(char **p)
++{
++ omapfb_def_sdram_vram_size = memparse(*p, p);
++ if (**p == ',')
++ omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
++
++ printk("omapfb_early_vram, %d, 0x%x\n",
++ omapfb_def_sdram_vram_size,
++ omapfb_def_sdram_vram_start);
++}
++__early_param("vram=", omapfb_early_vram);
++
++/*
++ * Called from map_io. We need to call to this early enough so that we
++ * can reserve the fixed SDRAM regions before VM could get hold of them.
++ */
++void __init omapfb_reserve_sdram(void)
++{
++ struct bootmem_data *bdata;
++ unsigned long sdram_start, sdram_size;
++ u32 paddr;
++ u32 size = 0;
++
++ /* cmdline arg overrides the board file definition */
++ if (omapfb_def_sdram_vram_size) {
++ size = omapfb_def_sdram_vram_size;
++ paddr = omapfb_def_sdram_vram_start;
++ }
++
++ if (!size) {
++ size = omapfb_sdram_vram_size;
++ paddr = omapfb_sdram_vram_start;
++ }
++
++#ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
++ if (!size) {
++ size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024;
++ paddr = 0;
++ }
++#endif
++
++ if (!size)
++ return;
++
++ size = PAGE_ALIGN(size);
++
++ bdata = NODE_DATA(0)->bdata;
++ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
++ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
++
++ if (paddr) {
++ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
++ paddr + size > sdram_start + sdram_size) {
++ printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
++ return;
++ }
++
++ reserve_bootmem(paddr, size, BOOTMEM_DEFAULT);
++ } else {
++ if (size > sdram_size) {
++ printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
++ return;
++ }
++
++ paddr = virt_to_phys(alloc_bootmem_pages(size));
++ BUG_ON(paddr & ~PAGE_MASK);
++ }
++
++ omap_vram_add_region_postponed(paddr, size);
++
++ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
++}
++
++/*
++ * Called at sram init time, before anything is pushed to the SRAM stack.
++ * Because of the stack scheme, we will allocate everything from the
++ * start of the lowest address region to the end of SRAM. This will also
++ * include padding for page alignment and possible holes between regions.
++ *
++ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
++ * this point, since the driver built as a module would have problem with
++ * freeing / reallocating the regions.
++ */
++unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail)
++{
++ unsigned long pend_avail;
++ unsigned long reserved;
++ u32 paddr;
++ u32 size;
++
++ paddr = omapfb_sram_vram_start;
++ size = omapfb_sram_vram_size;
++
++ if (!size)
++ return 0;
++
++ reserved = 0;
++ pend_avail = pstart_avail + size_avail;
++
++ if (!paddr) {
++ /* Dynamic allocation */
++ if ((size_avail & PAGE_MASK) < size) {
++ printk(KERN_ERR "Not enough SRAM for VRAM\n");
++ return 0;
++ }
++ size_avail = (size_avail - size) & PAGE_MASK;
++ paddr = pstart_avail + size_avail;
++ }
++
++ if (paddr < sram_pstart ||
++ paddr + size > sram_pstart + sram_size) {
++ printk(KERN_ERR "Illegal SRAM region for VRAM\n");
++ return 0;
++ }
++
++ /* Reserve everything above the start of the region. */
++ if (pend_avail - paddr > reserved)
++ reserved = pend_avail - paddr;
++ size_avail = pend_avail - reserved - pstart_avail;
++
++ omap_vram_add_region_postponed(paddr, size);
++
++ if (reserved)
++ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
++
++ return reserved;
++}
++
++void __init omap2_set_sdram_vram(u32 size, u32 start)
++{
++ omapfb_sdram_vram_start = start;
++ omapfb_sdram_vram_size = size;
++}
++
++void __init omap2_set_sram_vram(u32 size, u32 start)
++{
++ omapfb_sram_vram_start = start;
++ omapfb_sram_vram_size = size;
++}
++
++#endif
++
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+new file mode 100644
+index 0000000..7e0f8fc
+--- /dev/null
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -0,0 +1,159 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <mach/io.h>
++#include <mach/vrfb.h>
++
++/*#define DEBUG*/
++
++#ifdef DEBUG
++#define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define SMS_ROT_VIRT_BASE(context, rot) \
++ (((context >= 4) ? 0xD0000000 : 0x70000000) \
++ | 0x4000000 * (context) \
++ | 0x1000000 * (rot))
++
++#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
++
++#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
++#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
++#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
++#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
++#define SMS_IMAGEHEIGHT_OFFSET 16
++#define SMS_IMAGEWIDTH_OFFSET 0
++#define SMS_PH_OFFSET 8
++#define SMS_PW_OFFSET 4
++#define SMS_PS_OFFSET 0
++
++#define OMAP_SMS_BASE 0x6C000000
++#define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context)
++#define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context)
++#define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context)
++
++#define VRFB_NUM_CTXS 12
++/* bitmap of reserved contexts */
++static unsigned ctx_map;
++
++void omap_vrfb_adjust_size(u16 *width, u16 *height,
++ u8 bytespp)
++{
++ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
++ *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
++}
++EXPORT_SYMBOL(omap_vrfb_adjust_size);
++
++void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
++ u16 width, u16 height,
++ u8 bytespp)
++{
++ unsigned pixel_size_exp;
++ u16 vrfb_width;
++ u16 vrfb_height;
++ u8 ctx = vrfb->context;
++
++ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
++ width, height, bytespp);
++
++ if (bytespp == 4)
++ pixel_size_exp = 2;
++ else if (bytespp == 2)
++ pixel_size_exp = 1;
++ else
++ BUG();
++
++ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
++ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
++
++ DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
++
++ omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
++ omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
++ (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
++ SMS_ROT_SIZE(ctx));
++
++ omap_writel(pixel_size_exp << SMS_PS_OFFSET |
++ VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
++ VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
++ SMS_ROT_CONTROL(ctx));
++
++ DBG("vrfb offset pixels %d, %d\n",
++ vrfb_width - width, vrfb_height - height);
++
++ vrfb->xoffset = vrfb_width - width;
++ vrfb->yoffset = vrfb_height - height;
++ vrfb->bytespp = bytespp;
++}
++EXPORT_SYMBOL(omap_vrfb_setup);
++
++void omap_vrfb_release_ctx(struct vrfb *vrfb)
++{
++ int rot;
++
++ if (vrfb->context == 0xff)
++ return;
++
++ DBG("release ctx %d\n", vrfb->context);
++
++ ctx_map &= ~(1 << vrfb->context);
++
++ for (rot = 0; rot < 4; ++rot) {
++ if(vrfb->paddr[rot]) {
++ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
++ vrfb->paddr[rot] = 0;
++ }
++ }
++
++ vrfb->context = 0xff;
++}
++EXPORT_SYMBOL(omap_vrfb_release_ctx);
++
++int omap_vrfb_request_ctx(struct vrfb *vrfb)
++{
++ int rot;
++ u32 paddr;
++ u8 ctx;
++
++ DBG("request ctx\n");
++
++ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
++ if ((ctx_map & (1 << ctx)) == 0)
++ break;
++
++ if (ctx == VRFB_NUM_CTXS) {
++ printk(KERN_ERR "vrfb: no free contexts\n");
++ return -EBUSY;
++ }
++
++ DBG("found free ctx %d\n", ctx);
++
++ ctx_map |= 1 << ctx;
++
++ memset(vrfb, 0, sizeof(*vrfb));
++
++ vrfb->context = ctx;
++
++ for (rot = 0; rot < 4; ++rot) {
++ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
++ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
++ printk(KERN_ERR "vrfb: failed to reserve VRFB "
++ "area for ctx %d, rotation %d\n",
++ ctx, rot * 90);
++ omap_vrfb_release_ctx(vrfb);
++ return -ENOMEM;
++ }
++
++ vrfb->paddr[rot] = paddr;
++
++ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(omap_vrfb_request_ctx);
++
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index d6d65ef..95e03fd 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2146,6 +2146,7 @@ config FB_BROADSHEET
+ a bridge adapter.
+
+ source "drivers/video/omap/Kconfig"
++source "drivers/video/omap2/Kconfig"
+
+ source "drivers/video/backlight/Kconfig"
+ source "drivers/video/display/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 01a819f..01bf7a5 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -123,6 +123,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
+ obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+ obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
+ obj-$(CONFIG_FB_OMAP) += omap/
++obj-$(CONFIG_OMAP2_DSS) += omap2/
+ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+ obj-$(CONFIG_FB_CARMINE) += carminefb.o
+ obj-$(CONFIG_FB_MB862XX) += mb862xx/
+diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
+new file mode 100644
+index 0000000..89bf210
+--- /dev/null
++++ b/drivers/video/omap2/Kconfig
+@@ -0,0 +1,3 @@
++source "drivers/video/omap2/dss/Kconfig"
++source "drivers/video/omap2/displays/Kconfig"
++source "drivers/video/omap2/omapfb/Kconfig"
+diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
+new file mode 100644
+index 0000000..72134db
+--- /dev/null
++++ b/drivers/video/omap2/Makefile
+@@ -0,0 +1,4 @@
++# OMAP2/3 Display Subsystem
++obj-y += dss/
++obj-y += displays/
++obj-y += omapfb/
+diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
+new file mode 100644
+index 0000000..f2ce068
+--- /dev/null
++++ b/drivers/video/omap2/dss/Kconfig
+@@ -0,0 +1,89 @@
++menuconfig OMAP2_DSS
++ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
++ depends on ARCH_OMAP2 || ARCH_OMAP3
++ help
++ OMAP2/3 Display Subsystem support.
++
++if OMAP2_DSS
++
++config OMAP2_DSS_VRAM_SIZE
++ int "VRAM size (MB)"
++ range 0 32
++ default 4
++ help
++ The amount of SDRAM to reserve at boot time for video RAM use.
++ This VRAM will be used by omapfb and other drivers that need
++ large continuous RAM area for video use.
++
++ You can also set this with "vram=<bytes>" kernel argument, or
++ in the board file.
++
++config OMAP2_DSS_DEBUG_SUPPORT
++ bool "Debug support"
++ default y
++ help
++ This enables debug messages. You need to enable printing
++ with 'debug' module parameter.
++
++config OMAP2_DSS_RFBI
++ bool "RFBI support"
++ default n
++ help
++ MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
++
++config OMAP2_DSS_VENC
++ bool "VENC support"
++ default y
++ help
++ OMAP Video Encoder support.
++
++config OMAP2_DSS_SDI
++ bool "SDI support"
++ depends on ARCH_OMAP3
++ default n
++ help
++ SDI (Serial Display Interface) support.
++
++config OMAP2_DSS_DSI
++ bool "DSI support"
++ depends on ARCH_OMAP3
++ default n
++ help
++ MIPI DSI support.
++
++config OMAP2_DSS_USE_DSI_PLL
++ bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
++ default n
++ depends on OMAP2_DSS_DSI
++ help
++ Use DSI PLL to generate pixel clock. Currently only for DPI output.
++ DSI PLL can be used to generate higher and more precise pixel clocks.
++
++config OMAP2_DSS_FAKE_VSYNC
++ bool "Fake VSYNC irq from manual update displays"
++ default n
++ help
++ If this is selected, DSI will generate a fake DISPC VSYNC interrupt
++ when DSI has sent a frame. This is only needed with DSI or RFBI
++ displays using manual mode, and you want VSYNC to, for example,
++ time animation.
++
++config OMAP2_DSS_MIN_FCK_PER_PCK
++ int "Minimum FCK/PCK ratio (for scaling)"
++ range 0 32
++ default 0
++ help
++ This can be used to adjust the minimum FCK/PCK ratio.
++
++ With this you can make sure that DISPC FCK is at least
++ n x PCK. Video plane scaling requires higher FCK than
++ normally.
++
++ If this is set to 0, there's no extra constraint on the
++ DISPC FCK. However, the FCK will at minimum be
++ 2xPCK (if active matrix) or 3xPCK (if passive matrix).
++
++ Max FCK is 173MHz, so this doesn't work if your PCK
++ is very high.
++
++endif
+diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
+new file mode 100644
+index 0000000..980c72c
+--- /dev/null
++++ b/drivers/video/omap2/dss/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_OMAP2_DSS) += omapdss.o
++omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
++omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
++omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
++omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
++omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+new file mode 100644
+index 0000000..ae7cd06
+--- /dev/null
++++ b/drivers/video/omap2/dss/core.c
+@@ -0,0 +1,641 @@
++/*
++ * linux/drivers/video/omap2/dss/core.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "CORE"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/platform_device.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
++#include <linux/io.h>
++
++#include <mach/display.h>
++#include <mach/clock.h>
++
++#include "dss.h"
++
++static struct {
++ struct platform_device *pdev;
++ unsigned ctx_id;
++
++ struct clk *dss_ick;
++ struct clk *dss1_fck;
++ struct clk *dss2_fck;
++ struct clk *dss_54m_fck;
++ struct clk *dss_96m_fck;
++ unsigned num_clks_enabled;
++} core;
++
++static void dss_clk_enable_all_no_ctx(void);
++static void dss_clk_disable_all_no_ctx(void);
++static void dss_clk_enable_no_ctx(enum dss_clock clks);
++static void dss_clk_disable_no_ctx(enum dss_clock clks);
++
++static char *def_disp_name;
++module_param_named(def_disp, def_disp_name, charp, 0);
++MODULE_PARM_DESC(def_disp_name, "default display name");
++
++#ifdef DEBUG
++unsigned int dss_debug;
++module_param_named(debug, dss_debug, bool, 0644);
++#endif
++
++/* CONTEXT */
++static unsigned dss_get_ctx_id(void)
++{
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++
++ if (!pdata->get_last_off_on_transaction_id)
++ return 0;
++
++ return pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++}
++
++int dss_need_ctx_restore(void)
++{
++ int id = dss_get_ctx_id();
++
++ if (id != core.ctx_id) {
++ DSSDBG("ctx id %u -> id %u\n",
++ core.ctx_id, id);
++ core.ctx_id = id;
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++static void save_all_ctx(void)
++{
++ DSSDBG("save context\n");
++
++ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dss_save_context();
++ dispc_save_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_save_context();
++#endif
++
++ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++static void restore_all_ctx(void)
++{
++ DSSDBG("restore context\n");
++
++ dss_clk_enable_all_no_ctx();
++
++ dss_restore_context();
++ dispc_restore_context();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_restore_context();
++#endif
++
++ dss_clk_disable_all_no_ctx();
++}
++
++/* CLOCKS */
++void dss_dump_clocks(struct seq_file *s)
++{
++ int i;
++ struct clk *clocks[5] = {
++ core.dss_ick,
++ core.dss1_fck,
++ core.dss2_fck,
++ core.dss_54m_fck,
++ core.dss_96m_fck
++ };
++
++ seq_printf(s, "- dss -\n");
++
++ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled);
++
++ for (i = 0; i < 5; i++) {
++ if (!clocks[i])
++ continue;
++ seq_printf(s, "%-15s\t%lu\t%d\n",
++ clocks[i]->name,
++ clk_get_rate(clocks[i]),
++ clocks[i]->usecount);
++ }
++}
++
++static int dss_get_clocks(void)
++{
++ const struct {
++ struct clk **clock;
++ char *omap2_name;
++ char *omap3_name;
++ } clocks[5] = {
++ { &core.dss_ick, "dss_ick", "dss_ick" }, /* L3 & L4 ick */
++ { &core.dss1_fck, "dss1_fck", "dss1_alwon_fck" },
++ { &core.dss2_fck, "dss2_fck", "dss2_alwon_fck" },
++ { &core.dss_54m_fck, "dss_54m_fck", "dss_tv_fck" },
++ { &core.dss_96m_fck, NULL, "dss_96m_fck" },
++ };
++
++ int r = 0;
++ int i;
++ const int num_clocks = 5;
++
++ for (i = 0; i < num_clocks; i++)
++ *clocks[i].clock = NULL;
++
++ for (i = 0; i < num_clocks; i++) {
++ struct clk *clk;
++ const char *clk_name;
++
++ clk_name = cpu_is_omap34xx() ? clocks[i].omap3_name
++ : clocks[i].omap2_name;
++
++ if (!clk_name)
++ continue;
++
++ clk = clk_get(NULL, clk_name);
++
++ if (IS_ERR(clk)) {
++ DSSERR("can't get clock %s", clk_name);
++ r = PTR_ERR(clk);
++ goto err;
++ }
++
++ DSSDBG("clk %s, rate %ld\n",
++ clk_name, clk_get_rate(clk));
++
++ *clocks[i].clock = clk;
++ }
++
++ return 0;
++
++err:
++ for (i = 0; i < num_clocks; i++) {
++ if (!IS_ERR(*clocks[i].clock))
++ clk_put(*clocks[i].clock);
++ }
++
++ return r;
++}
++
++static void dss_put_clocks(void)
++{
++ if (core.dss_96m_fck)
++ clk_put(core.dss_96m_fck);
++ clk_put(core.dss_54m_fck);
++ clk_put(core.dss1_fck);
++ clk_put(core.dss2_fck);
++ clk_put(core.dss_ick);
++}
++
++unsigned long dss_clk_get_rate(enum dss_clock clk)
++{
++ switch (clk) {
++ case DSS_CLK_ICK:
++ return clk_get_rate(core.dss_ick);
++ case DSS_CLK_FCK1:
++ return clk_get_rate(core.dss1_fck);
++ case DSS_CLK_FCK2:
++ return clk_get_rate(core.dss2_fck);
++ case DSS_CLK_54M:
++ return clk_get_rate(core.dss_54m_fck);
++ case DSS_CLK_96M:
++ return clk_get_rate(core.dss_96m_fck);
++ }
++
++ BUG();
++ return 0;
++}
++
++static unsigned count_clk_bits(enum dss_clock clks)
++{
++ unsigned num_clks = 0;
++
++ if (clks & DSS_CLK_ICK)
++ ++num_clks;
++ if (clks & DSS_CLK_FCK1)
++ ++num_clks;
++ if (clks & DSS_CLK_FCK2)
++ ++num_clks;
++ if (clks & DSS_CLK_54M)
++ ++num_clks;
++ if (clks & DSS_CLK_96M)
++ ++num_clks;
++
++ return num_clks;
++}
++
++static void dss_clk_enable_no_ctx(enum dss_clock clks)
++{
++ unsigned num_clks = count_clk_bits(clks);
++
++ if (clks & DSS_CLK_ICK)
++ clk_enable(core.dss_ick);
++ if (clks & DSS_CLK_FCK1)
++ clk_enable(core.dss1_fck);
++ if (clks & DSS_CLK_FCK2)
++ clk_enable(core.dss2_fck);
++ if (clks & DSS_CLK_54M)
++ clk_enable(core.dss_54m_fck);
++ if (clks & DSS_CLK_96M)
++ clk_enable(core.dss_96m_fck);
++
++ core.num_clks_enabled += num_clks;
++}
++
++void dss_clk_enable(enum dss_clock clks)
++{
++ dss_clk_enable_no_ctx(clks);
++
++ if (cpu_is_omap34xx() && dss_need_ctx_restore())
++ restore_all_ctx();
++}
++
++static void dss_clk_disable_no_ctx(enum dss_clock clks)
++{
++ unsigned num_clks = count_clk_bits(clks);
++
++ if (clks & DSS_CLK_ICK)
++ clk_disable(core.dss_ick);
++ if (clks & DSS_CLK_FCK1)
++ clk_disable(core.dss1_fck);
++ if (clks & DSS_CLK_FCK2)
++ clk_disable(core.dss2_fck);
++ if (clks & DSS_CLK_54M)
++ clk_disable(core.dss_54m_fck);
++ if (clks & DSS_CLK_96M)
++ clk_disable(core.dss_96m_fck);
++
++ core.num_clks_enabled -= num_clks;
++}
++
++void dss_clk_disable(enum dss_clock clks)
++{
++ if (cpu_is_omap34xx()) {
++ unsigned num_clks = count_clk_bits(clks);
++
++ BUG_ON(core.num_clks_enabled < num_clks);
++
++ if (core.num_clks_enabled == num_clks)
++ save_all_ctx();
++ }
++
++ dss_clk_disable_no_ctx(clks);
++}
++
++static void dss_clk_enable_all_no_ctx(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_enable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all_no_ctx(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_disable_no_ctx(clks);
++}
++
++static void dss_clk_disable_all(void)
++{
++ enum dss_clock clks;
++
++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
++ if (cpu_is_omap34xx())
++ clks |= DSS_CLK_96M;
++ dss_clk_disable(clks);
++}
++
++/* DEBUGFS */
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++static void dss_debug_dump_clocks(struct seq_file *s)
++{
++ dss_dump_clocks(s);
++ dispc_dump_clocks(s);
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_dump_clocks(s);
++#endif
++}
++
++static int dss_debug_show(struct seq_file *s, void *unused)
++{
++ void (*func)(struct seq_file *) = s->private;
++ func(s);
++ return 0;
++}
++
++static int dss_debug_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, dss_debug_show, inode->i_private);
++}
++
++static const struct file_operations dss_debug_fops = {
++ .open = dss_debug_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static struct dentry *dss_debugfs_dir;
++
++static int dss_initialize_debugfs(void)
++{
++ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
++ if (IS_ERR(dss_debugfs_dir)) {
++ int err = PTR_ERR(dss_debugfs_dir);
++ dss_debugfs_dir = NULL;
++ return err;
++ }
++
++ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
++ &dss_debug_dump_clocks, &dss_debug_fops);
++
++ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
++ &dss_dump_regs, &dss_debug_fops);
++ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
++ &dispc_dump_regs, &dss_debug_fops);
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
++ &rfbi_dump_regs, &dss_debug_fops);
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
++ &dsi_dump_regs, &dss_debug_fops);
++#endif
++ return 0;
++}
++
++static void dss_uninitialize_debugfs(void)
++{
++ if (dss_debugfs_dir)
++ debugfs_remove_recursive(dss_debugfs_dir);
++}
++#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
++
++
++/* DSI powers */
++int dss_dsi_power_up(void)
++{
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++
++ if (!pdata->dsi_power_up)
++ return 0; /* presume power is always on then */
++
++ return pdata->dsi_power_up();
++}
++
++void dss_dsi_power_down(void)
++{
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++
++ if (!pdata->dsi_power_down)
++ return;
++
++ pdata->dsi_power_down();
++}
++
++
++
++/* PLATFORM DEVICE */
++static int omap_dss_probe(struct platform_device *pdev)
++{
++ int skip_init = 0;
++ int r;
++
++ core.pdev = pdev;
++
++ r = dss_get_clocks();
++ if (r)
++ goto fail0;
++
++ dss_clk_enable_all_no_ctx();
++
++ core.ctx_id = dss_get_ctx_id();
++ DSSDBG("initial ctx id %u\n", core.ctx_id);
++
++#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
++ /* DISPC_CONTROL */
++ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
++ skip_init = 1;
++#endif
++
++ r = dss_init(skip_init);
++ if (r) {
++ DSSERR("Failed to initialize DSS\n");
++ goto fail0;
++ }
++
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ r = rfbi_init();
++ if (r) {
++ DSSERR("Failed to initialize rfbi\n");
++ goto fail0;
++ }
++#endif
++
++ r = dpi_init();
++ if (r) {
++ DSSERR("Failed to initialize dpi\n");
++ goto fail0;
++ }
++
++ r = dispc_init();
++ if (r) {
++ DSSERR("Failed to initialize dispc\n");
++ goto fail0;
++ }
++#ifdef CONFIG_OMAP2_DSS_VENC
++ r = venc_init();
++ if (r) {
++ DSSERR("Failed to initialize venc\n");
++ goto fail0;
++ }
++#endif
++ if (cpu_is_omap34xx()) {
++#ifdef CONFIG_OMAP2_DSS_SDI
++ r = sdi_init(skip_init);
++ if (r) {
++ DSSERR("Failed to initialize SDI\n");
++ goto fail0;
++ }
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ r = dsi_init();
++ if (r) {
++ DSSERR("Failed to initialize DSI\n");
++ goto fail0;
++ }
++#endif
++ }
++
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++ r = dss_initialize_debugfs();
++ if (r)
++ goto fail0;
++#endif
++
++ dss_init_displays(pdev);
++ dss_init_overlay_managers(pdev);
++ dss_init_overlays(pdev, def_disp_name);
++
++ dss_clk_disable_all();
++
++ return 0;
++
++ /* XXX fail correctly */
++fail0:
++ return r;
++}
++
++static int omap_dss_remove(struct platform_device *pdev)
++{
++ int c;
++
++ dss_uninit_overlays(pdev);
++ dss_uninit_overlay_managers(pdev);
++ dss_uninit_displays(pdev);
++
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
++ dss_uninitialize_debugfs();
++#endif
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ venc_exit();
++#endif
++ dispc_exit();
++ dpi_exit();
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ rfbi_exit();
++#endif
++ if (cpu_is_omap34xx()) {
++#ifdef CONFIG_OMAP2_DSS_DSI
++ dsi_exit();
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ sdi_exit();
++#endif
++ }
++
++ dss_exit();
++
++ /* these should be removed at some point */
++ c = core.dss_ick->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_ick usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss_ick);
++ }
++
++ c = core.dss1_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss1_fck);
++ }
++
++ c = core.dss2_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss2_fck);
++ }
++
++ c = core.dss_54m_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
++ while (c-- > 0)
++ clk_disable(core.dss_54m_fck);
++ }
++
++ if (core.dss_96m_fck) {
++ c = core.dss_96m_fck->usecount;
++ if (c > 0) {
++ DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
++ c);
++ while (c-- > 0)
++ clk_disable(core.dss_96m_fck);
++ }
++ }
++
++ dss_put_clocks();
++
++ return 0;
++}
++
++static void omap_dss_shutdown(struct platform_device *pdev)
++{
++ DSSDBG("shutdown\n");
++}
++
++static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ DSSDBG("suspend %d\n", state.event);
++
++ return dss_suspend_all_displays();
++}
++
++static int omap_dss_resume(struct platform_device *pdev)
++{
++ DSSDBG("resume\n");
++
++ return dss_resume_all_displays();
++}
++
++static struct platform_driver omap_dss_driver = {
++ .probe = omap_dss_probe,
++ .remove = omap_dss_remove,
++ .shutdown = omap_dss_shutdown,
++ .suspend = omap_dss_suspend,
++ .resume = omap_dss_resume,
++ .driver = {
++ .name = "omapdss",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init omap_dss_init(void)
++{
++ return platform_driver_register(&omap_dss_driver);
++}
++
++static void __exit omap_dss_exit(void)
++{
++ platform_driver_unregister(&omap_dss_driver);
++}
++
++subsys_initcall(omap_dss_init);
++module_exit(omap_dss_exit);
++
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+new file mode 100644
+index 0000000..ffb5648
+--- /dev/null
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -0,0 +1,2968 @@
++/*
++ * linux/drivers/video/omap2/dss/dispc.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DISPC"
++
++#include <linux/kernel.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
++#include <linux/seq_file.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++
++#include <mach/sram.h>
++#include <mach/board.h>
++#include <mach/clock.h>
++
++#include <mach/display.h>
++
++#include "dss.h"
++
++/* DISPC */
++#define DISPC_BASE 0x48050400
++
++#define DISPC_SZ_REGS SZ_1K
++
++struct dispc_reg { u16 idx; };
++
++#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
++
++/* DISPC common */
++#define DISPC_REVISION DISPC_REG(0x0000)
++#define DISPC_SYSCONFIG DISPC_REG(0x0010)
++#define DISPC_SYSSTATUS DISPC_REG(0x0014)
++#define DISPC_IRQSTATUS DISPC_REG(0x0018)
++#define DISPC_IRQENABLE DISPC_REG(0x001C)
++#define DISPC_CONTROL DISPC_REG(0x0040)
++#define DISPC_CONFIG DISPC_REG(0x0044)
++#define DISPC_CAPABLE DISPC_REG(0x0048)
++#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
++#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
++#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
++#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
++#define DISPC_LINE_STATUS DISPC_REG(0x005C)
++#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
++#define DISPC_TIMING_H DISPC_REG(0x0064)
++#define DISPC_TIMING_V DISPC_REG(0x0068)
++#define DISPC_POL_FREQ DISPC_REG(0x006C)
++#define DISPC_DIVISOR DISPC_REG(0x0070)
++#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
++#define DISPC_SIZE_DIG DISPC_REG(0x0078)
++#define DISPC_SIZE_LCD DISPC_REG(0x007C)
++
++/* DISPC GFX plane */
++#define DISPC_GFX_BA0 DISPC_REG(0x0080)
++#define DISPC_GFX_BA1 DISPC_REG(0x0084)
++#define DISPC_GFX_POSITION DISPC_REG(0x0088)
++#define DISPC_GFX_SIZE DISPC_REG(0x008C)
++#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
++#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
++#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
++#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
++#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
++#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
++#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
++
++#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
++#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
++#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
++
++#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
++#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
++#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
++
++#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
++
++/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
++#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
++
++#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
++#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
++#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
++#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
++#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
++#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
++#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
++#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
++#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
++#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
++#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
++#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
++#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
++
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
++/* coef index i = {0, 1, 2, 3, 4} */
++#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
++#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
++
++#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
++
++
++#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
++ DISPC_IRQ_OCP_ERR | \
++ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
++ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
++ DISPC_IRQ_SYNC_LOST | \
++ DISPC_IRQ_SYNC_LOST_DIGIT)
++
++#define DISPC_MAX_NR_ISRS 8
++
++struct omap_dispc_isr_data {
++ omap_dispc_isr_t isr;
++ void *arg;
++ u32 mask;
++};
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dispc_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
++
++static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
++ DISPC_VID_ATTRIBUTES(0),
++ DISPC_VID_ATTRIBUTES(1) };
++
++static struct {
++ void __iomem *base;
++
++ struct clk *dpll4_m4_ck;
++
++ spinlock_t irq_lock;
++
++ unsigned long cache_req_pck;
++ unsigned long cache_prate;
++ struct dispc_clock_info cache_cinfo;
++
++ u32 irq_error_mask;
++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
++
++ spinlock_t error_lock;
++ u32 error_irqs;
++ struct work_struct error_work;
++
++ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
++} dispc;
++
++static void omap_dispc_set_irqs(void);
++
++static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
++{
++ __raw_writel(val, dispc.base + idx.idx);
++}
++
++static inline u32 dispc_read_reg(const struct dispc_reg idx)
++{
++ return __raw_readl(dispc.base + idx.idx);
++}
++
++#define SR(reg) \
++ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
++#define RR(reg) \
++ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
++
++void dispc_save_context(void)
++{
++ if (cpu_is_omap24xx())
++ return;
++
++ SR(SYSCONFIG);
++ SR(IRQENABLE);
++ SR(CONTROL);
++ SR(CONFIG);
++ SR(DEFAULT_COLOR0);
++ SR(DEFAULT_COLOR1);
++ SR(TRANS_COLOR0);
++ SR(TRANS_COLOR1);
++ SR(LINE_NUMBER);
++ SR(TIMING_H);
++ SR(TIMING_V);
++ SR(POL_FREQ);
++ SR(DIVISOR);
++ SR(GLOBAL_ALPHA);
++ SR(SIZE_DIG);
++ SR(SIZE_LCD);
++
++ SR(GFX_BA0);
++ SR(GFX_BA1);
++ SR(GFX_POSITION);
++ SR(GFX_SIZE);
++ SR(GFX_ATTRIBUTES);
++ SR(GFX_FIFO_THRESHOLD);
++ SR(GFX_ROW_INC);
++ SR(GFX_PIXEL_INC);
++ SR(GFX_WINDOW_SKIP);
++ SR(GFX_TABLE_BA);
++
++ SR(DATA_CYCLE1);
++ SR(DATA_CYCLE2);
++ SR(DATA_CYCLE3);
++
++ SR(CPR_COEF_R);
++ SR(CPR_COEF_G);
++ SR(CPR_COEF_B);
++
++ SR(GFX_PRELOAD);
++
++ /* VID1 */
++ SR(VID_BA0(0));
++ SR(VID_BA1(0));
++ SR(VID_POSITION(0));
++ SR(VID_SIZE(0));
++ SR(VID_ATTRIBUTES(0));
++ SR(VID_FIFO_THRESHOLD(0));
++ SR(VID_ROW_INC(0));
++ SR(VID_PIXEL_INC(0));
++ SR(VID_FIR(0));
++ SR(VID_PICTURE_SIZE(0));
++ SR(VID_ACCU0(0));
++ SR(VID_ACCU1(0));
++
++ SR(VID_FIR_COEF_H(0, 0));
++ SR(VID_FIR_COEF_H(0, 1));
++ SR(VID_FIR_COEF_H(0, 2));
++ SR(VID_FIR_COEF_H(0, 3));
++ SR(VID_FIR_COEF_H(0, 4));
++ SR(VID_FIR_COEF_H(0, 5));
++ SR(VID_FIR_COEF_H(0, 6));
++ SR(VID_FIR_COEF_H(0, 7));
++
++ SR(VID_FIR_COEF_HV(0, 0));
++ SR(VID_FIR_COEF_HV(0, 1));
++ SR(VID_FIR_COEF_HV(0, 2));
++ SR(VID_FIR_COEF_HV(0, 3));
++ SR(VID_FIR_COEF_HV(0, 4));
++ SR(VID_FIR_COEF_HV(0, 5));
++ SR(VID_FIR_COEF_HV(0, 6));
++ SR(VID_FIR_COEF_HV(0, 7));
++
++ SR(VID_CONV_COEF(0, 0));
++ SR(VID_CONV_COEF(0, 1));
++ SR(VID_CONV_COEF(0, 2));
++ SR(VID_CONV_COEF(0, 3));
++ SR(VID_CONV_COEF(0, 4));
++
++ SR(VID_FIR_COEF_V(0, 0));
++ SR(VID_FIR_COEF_V(0, 1));
++ SR(VID_FIR_COEF_V(0, 2));
++ SR(VID_FIR_COEF_V(0, 3));
++ SR(VID_FIR_COEF_V(0, 4));
++ SR(VID_FIR_COEF_V(0, 5));
++ SR(VID_FIR_COEF_V(0, 6));
++ SR(VID_FIR_COEF_V(0, 7));
++
++ SR(VID_PRELOAD(0));
++
++ /* VID2 */
++ SR(VID_BA0(1));
++ SR(VID_BA1(1));
++ SR(VID_POSITION(1));
++ SR(VID_SIZE(1));
++ SR(VID_ATTRIBUTES(1));
++ SR(VID_FIFO_THRESHOLD(1));
++ SR(VID_ROW_INC(1));
++ SR(VID_PIXEL_INC(1));
++ SR(VID_FIR(1));
++ SR(VID_PICTURE_SIZE(1));
++ SR(VID_ACCU0(1));
++ SR(VID_ACCU1(1));
++
++ SR(VID_FIR_COEF_H(1, 0));
++ SR(VID_FIR_COEF_H(1, 1));
++ SR(VID_FIR_COEF_H(1, 2));
++ SR(VID_FIR_COEF_H(1, 3));
++ SR(VID_FIR_COEF_H(1, 4));
++ SR(VID_FIR_COEF_H(1, 5));
++ SR(VID_FIR_COEF_H(1, 6));
++ SR(VID_FIR_COEF_H(1, 7));
++
++ SR(VID_FIR_COEF_HV(1, 0));
++ SR(VID_FIR_COEF_HV(1, 1));
++ SR(VID_FIR_COEF_HV(1, 2));
++ SR(VID_FIR_COEF_HV(1, 3));
++ SR(VID_FIR_COEF_HV(1, 4));
++ SR(VID_FIR_COEF_HV(1, 5));
++ SR(VID_FIR_COEF_HV(1, 6));
++ SR(VID_FIR_COEF_HV(1, 7));
++
++ SR(VID_CONV_COEF(1, 0));
++ SR(VID_CONV_COEF(1, 1));
++ SR(VID_CONV_COEF(1, 2));
++ SR(VID_CONV_COEF(1, 3));
++ SR(VID_CONV_COEF(1, 4));
++
++ SR(VID_FIR_COEF_V(1, 0));
++ SR(VID_FIR_COEF_V(1, 1));
++ SR(VID_FIR_COEF_V(1, 2));
++ SR(VID_FIR_COEF_V(1, 3));
++ SR(VID_FIR_COEF_V(1, 4));
++ SR(VID_FIR_COEF_V(1, 5));
++ SR(VID_FIR_COEF_V(1, 6));
++ SR(VID_FIR_COEF_V(1, 7));
++
++ SR(VID_PRELOAD(1));
++}
++
++void dispc_restore_context(void)
++{
++ RR(SYSCONFIG);
++ RR(IRQENABLE);
++ /*RR(CONTROL);*/
++ RR(CONFIG);
++ RR(DEFAULT_COLOR0);
++ RR(DEFAULT_COLOR1);
++ RR(TRANS_COLOR0);
++ RR(TRANS_COLOR1);
++ RR(LINE_NUMBER);
++ RR(TIMING_H);
++ RR(TIMING_V);
++ RR(POL_FREQ);
++ RR(DIVISOR);
++ RR(GLOBAL_ALPHA);
++ RR(SIZE_DIG);
++ RR(SIZE_LCD);
++
++ RR(GFX_BA0);
++ RR(GFX_BA1);
++ RR(GFX_POSITION);
++ RR(GFX_SIZE);
++ RR(GFX_ATTRIBUTES);
++ RR(GFX_FIFO_THRESHOLD);
++ RR(GFX_ROW_INC);
++ RR(GFX_PIXEL_INC);
++ RR(GFX_WINDOW_SKIP);
++ RR(GFX_TABLE_BA);
++
++ RR(DATA_CYCLE1);
++ RR(DATA_CYCLE2);
++ RR(DATA_CYCLE3);
++
++ RR(CPR_COEF_R);
++ RR(CPR_COEF_G);
++ RR(CPR_COEF_B);
++
++ RR(GFX_PRELOAD);
++
++ /* VID1 */
++ RR(VID_BA0(0));
++ RR(VID_BA1(0));
++ RR(VID_POSITION(0));
++ RR(VID_SIZE(0));
++ RR(VID_ATTRIBUTES(0));
++ RR(VID_FIFO_THRESHOLD(0));
++ RR(VID_ROW_INC(0));
++ RR(VID_PIXEL_INC(0));
++ RR(VID_FIR(0));
++ RR(VID_PICTURE_SIZE(0));
++ RR(VID_ACCU0(0));
++ RR(VID_ACCU1(0));
++
++ RR(VID_FIR_COEF_H(0, 0));
++ RR(VID_FIR_COEF_H(0, 1));
++ RR(VID_FIR_COEF_H(0, 2));
++ RR(VID_FIR_COEF_H(0, 3));
++ RR(VID_FIR_COEF_H(0, 4));
++ RR(VID_FIR_COEF_H(0, 5));
++ RR(VID_FIR_COEF_H(0, 6));
++ RR(VID_FIR_COEF_H(0, 7));
++
++ RR(VID_FIR_COEF_HV(0, 0));
++ RR(VID_FIR_COEF_HV(0, 1));
++ RR(VID_FIR_COEF_HV(0, 2));
++ RR(VID_FIR_COEF_HV(0, 3));
++ RR(VID_FIR_COEF_HV(0, 4));
++ RR(VID_FIR_COEF_HV(0, 5));
++ RR(VID_FIR_COEF_HV(0, 6));
++ RR(VID_FIR_COEF_HV(0, 7));
++
++ RR(VID_CONV_COEF(0, 0));
++ RR(VID_CONV_COEF(0, 1));
++ RR(VID_CONV_COEF(0, 2));
++ RR(VID_CONV_COEF(0, 3));
++ RR(VID_CONV_COEF(0, 4));
++
++ RR(VID_FIR_COEF_V(0, 0));
++ RR(VID_FIR_COEF_V(0, 1));
++ RR(VID_FIR_COEF_V(0, 2));
++ RR(VID_FIR_COEF_V(0, 3));
++ RR(VID_FIR_COEF_V(0, 4));
++ RR(VID_FIR_COEF_V(0, 5));
++ RR(VID_FIR_COEF_V(0, 6));
++ RR(VID_FIR_COEF_V(0, 7));
++
++ RR(VID_PRELOAD(0));
++
++ /* VID2 */
++ RR(VID_BA0(1));
++ RR(VID_BA1(1));
++ RR(VID_POSITION(1));
++ RR(VID_SIZE(1));
++ RR(VID_ATTRIBUTES(1));
++ RR(VID_FIFO_THRESHOLD(1));
++ RR(VID_ROW_INC(1));
++ RR(VID_PIXEL_INC(1));
++ RR(VID_FIR(1));
++ RR(VID_PICTURE_SIZE(1));
++ RR(VID_ACCU0(1));
++ RR(VID_ACCU1(1));
++
++ RR(VID_FIR_COEF_H(1, 0));
++ RR(VID_FIR_COEF_H(1, 1));
++ RR(VID_FIR_COEF_H(1, 2));
++ RR(VID_FIR_COEF_H(1, 3));
++ RR(VID_FIR_COEF_H(1, 4));
++ RR(VID_FIR_COEF_H(1, 5));
++ RR(VID_FIR_COEF_H(1, 6));
++ RR(VID_FIR_COEF_H(1, 7));
++
++ RR(VID_FIR_COEF_HV(1, 0));
++ RR(VID_FIR_COEF_HV(1, 1));
++ RR(VID_FIR_COEF_HV(1, 2));
++ RR(VID_FIR_COEF_HV(1, 3));
++ RR(VID_FIR_COEF_HV(1, 4));
++ RR(VID_FIR_COEF_HV(1, 5));
++ RR(VID_FIR_COEF_HV(1, 6));
++ RR(VID_FIR_COEF_HV(1, 7));
++
++ RR(VID_CONV_COEF(1, 0));
++ RR(VID_CONV_COEF(1, 1));
++ RR(VID_CONV_COEF(1, 2));
++ RR(VID_CONV_COEF(1, 3));
++ RR(VID_CONV_COEF(1, 4));
++
++ RR(VID_FIR_COEF_V(1, 0));
++ RR(VID_FIR_COEF_V(1, 1));
++ RR(VID_FIR_COEF_V(1, 2));
++ RR(VID_FIR_COEF_V(1, 3));
++ RR(VID_FIR_COEF_V(1, 4));
++ RR(VID_FIR_COEF_V(1, 5));
++ RR(VID_FIR_COEF_V(1, 6));
++ RR(VID_FIR_COEF_V(1, 7));
++
++ RR(VID_PRELOAD(1));
++
++ /* enable last, because LCD & DIGIT enable are here */
++ RR(CONTROL);
++}
++
++#undef SR
++#undef RR
++
++static inline void enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++void dispc_go(enum omap_channel channel)
++{
++ int bit;
++ unsigned long tmo;
++
++ enable_clocks(1);
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 0; /* LCDENABLE */
++ else
++ bit = 1; /* DIGITALENABLE */
++
++ /* if the channel is not enabled, we don't need GO */
++ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
++ goto end;
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 5; /* GOLCD */
++ else
++ bit = 6; /* GODIGIT */
++
++ tmo = jiffies + msecs_to_jiffies(200);
++ while (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
++ if (time_after(jiffies, tmo)) {
++ DSSERR("timeout waiting GO flag\n");
++ goto end;
++ }
++ cpu_relax();
++ }
++
++ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
++
++ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
++end:
++ enable_clocks(0);
++}
++
++static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
++}
++
++static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
++}
++
++static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
++{
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
++}
++
++static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
++ int vscaleup, int five_taps)
++{
++ /* Coefficients for horizontal up-sampling */
++ static const u32 coef_hup[8] = {
++ 0x00800000,
++ 0x0D7CF800,
++ 0x1E70F5FF,
++ 0x335FF5FE,
++ 0xF74949F7,
++ 0xF55F33FB,
++ 0xF5701EFE,
++ 0xF87C0DFF,
++ };
++
++ /* Coefficients for horizontal down-sampling */
++ static const u32 coef_hdown[8] = {
++ 0x24382400,
++ 0x28371FFE,
++ 0x2C361BFB,
++ 0x303516F9,
++ 0x11343311,
++ 0x1635300C,
++ 0x1B362C08,
++ 0x1F372804,
++ };
++
++ /* Coefficients for horizontal and vertical up-sampling */
++ static const u32 coef_hvup[2][8] = {
++ {
++ 0x00800000,
++ 0x037B02FF,
++ 0x0C6F05FE,
++ 0x205907FB,
++ 0x00404000,
++ 0x075920FE,
++ 0x056F0CFF,
++ 0x027B0300,
++ },
++ {
++ 0x00800000,
++ 0x0D7CF8FF,
++ 0x1E70F5FE,
++ 0x335FF5FB,
++ 0xF7404000,
++ 0xF55F33FE,
++ 0xF5701EFF,
++ 0xF87C0D00,
++ },
++ };
++
++ /* Coefficients for horizontal and vertical down-sampling */
++ static const u32 coef_hvdown[2][8] = {
++ {
++ 0x24382400,
++ 0x28391F04,
++ 0x2D381B08,
++ 0x3237170C,
++ 0x123737F7,
++ 0x173732F9,
++ 0x1B382DFB,
++ 0x1F3928FE,
++ },
++ {
++ 0x24382400,
++ 0x28371F04,
++ 0x2C361B08,
++ 0x3035160C,
++ 0x113433F7,
++ 0x163530F9,
++ 0x1B362CFB,
++ 0x1F3728FE,
++ },
++ };
++
++ /* Coefficients for vertical up-sampling */
++ static const u32 coef_vup[8] = {
++ 0x00000000,
++ 0x0000FF00,
++ 0x0000FEFF,
++ 0x0000FBFE,
++ 0x000000F7,
++ 0x0000FEFB,
++ 0x0000FFFE,
++ 0x000000FF,
++ };
++
++
++ /* Coefficients for vertical down-sampling */
++ static const u32 coef_vdown[8] = {
++ 0x00000000,
++ 0x000004FE,
++ 0x000008FB,
++ 0x00000CF9,
++ 0x0000F711,
++ 0x0000F90C,
++ 0x0000FB08,
++ 0x0000FE04,
++ };
++
++ const u32 *h_coef;
++ const u32 *hv_coef;
++ const u32 *hv_coef_mod;
++ const u32 *v_coef;
++ int i;
++
++ if (hscaleup)
++ h_coef = coef_hup;
++ else
++ h_coef = coef_hdown;
++
++ if (vscaleup) {
++ hv_coef = coef_hvup[five_taps];
++ v_coef = coef_vup;
++
++ if (hscaleup)
++ hv_coef_mod = NULL;
++ else
++ hv_coef_mod = coef_hvdown[five_taps];
++ } else {
++ hv_coef = coef_hvdown[five_taps];
++ v_coef = coef_vdown;
++
++ if (hscaleup)
++ hv_coef_mod = coef_hvup[five_taps];
++ else
++ hv_coef_mod = NULL;
++ }
++
++ for (i = 0; i < 8; i++) {
++ u32 h, hv;
++
++ h = h_coef[i];
++
++ hv = hv_coef[i];
++
++ if (hv_coef_mod) {
++ hv &= 0xffffff00;
++ hv |= (hv_coef_mod[i] & 0xff);
++ }
++
++ _dispc_write_firh_reg(plane, i, h);
++ _dispc_write_firhv_reg(plane, i, hv);
++ }
++
++ if (!five_taps)
++ return;
++
++ for (i = 0; i < 8; i++) {
++ u32 v;
++ v = v_coef[i];
++ _dispc_write_firv_reg(plane, i, v);
++ }
++}
++
++static void _dispc_setup_color_conv_coef(void)
++{
++ const struct color_conv_coef {
++ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
++ int full_range;
++ } ctbl_bt601_5 = {
++ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
++ };
++
++ const struct color_conv_coef *ct;
++
++#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
++
++ ct = &ctbl_bt601_5;
++
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
++
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
++
++#undef CVAL
++
++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
++}
++
++
++static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
++{
++ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
++ DISPC_VID_BA0(0),
++ DISPC_VID_BA0(1) };
++
++ dispc_write_reg(ba0_reg[plane], paddr);
++}
++
++static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
++{
++ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
++ DISPC_VID_BA1(0),
++ DISPC_VID_BA1(1) };
++
++ dispc_write_reg(ba1_reg[plane], paddr);
++}
++
++static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
++{
++ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
++ DISPC_VID_POSITION(0),
++ DISPC_VID_POSITION(1) };
++
++ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
++ dispc_write_reg(pos_reg[plane], val);
++}
++
++static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
++{
++ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
++ DISPC_VID_PICTURE_SIZE(0),
++ DISPC_VID_PICTURE_SIZE(1) };
++ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ dispc_write_reg(siz_reg[plane], val);
++}
++
++static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
++{
++ u32 val;
++ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
++ DISPC_VID_SIZE(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ dispc_write_reg(vsi_reg[plane-1], val);
++}
++
++static void _dispc_set_pix_inc(enum omap_plane plane, u16 inc)
++{
++ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
++ DISPC_VID_PIXEL_INC(0),
++ DISPC_VID_PIXEL_INC(1) };
++
++ dispc_write_reg(ri_reg[plane], inc);
++}
++
++static void _dispc_set_row_inc(enum omap_plane plane, u16 inc)
++{
++ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
++ DISPC_VID_ROW_INC(0),
++ DISPC_VID_ROW_INC(1) };
++
++ dispc_write_reg(ri_reg[plane], inc);
++}
++
++static void _dispc_set_color_mode(enum omap_plane plane,
++ enum omap_color_mode color_mode)
++{
++ u32 m = 0;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_CLUT1:
++ m = 0x0; break;
++ case OMAP_DSS_COLOR_CLUT2:
++ m = 0x1; break;
++ case OMAP_DSS_COLOR_CLUT4:
++ m = 0x2; break;
++ case OMAP_DSS_COLOR_CLUT8:
++ m = 0x3; break;
++ case OMAP_DSS_COLOR_RGB12U:
++ m = 0x4; break;
++ case OMAP_DSS_COLOR_ARGB16:
++ m = 0x5; break;
++ case OMAP_DSS_COLOR_RGB16:
++ m = 0x6; break;
++ case OMAP_DSS_COLOR_RGB24U:
++ m = 0x8; break;
++ case OMAP_DSS_COLOR_RGB24P:
++ m = 0x9; break;
++ case OMAP_DSS_COLOR_YUV2:
++ m = 0xa; break;
++ case OMAP_DSS_COLOR_UYVY:
++ m = 0xb; break;
++ case OMAP_DSS_COLOR_ARGB32:
++ m = 0xc; break;
++ case OMAP_DSS_COLOR_RGBA32:
++ m = 0xd; break;
++ case OMAP_DSS_COLOR_RGBX32:
++ m = 0xe; break;
++ default:
++ BUG(); break;
++ }
++
++ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
++}
++
++static void _dispc_set_channel_out(enum omap_plane plane,
++ enum omap_channel channel)
++{
++ int shift;
++ u32 val;
++
++ switch (plane) {
++ case OMAP_DSS_GFX:
++ shift = 8;
++ break;
++ case OMAP_DSS_VIDEO1:
++ case OMAP_DSS_VIDEO2:
++ shift = 16;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, channel, shift, shift);
++ dispc_write_reg(dispc_reg_att[plane], val);
++}
++
++void dispc_set_burst_size(enum omap_plane plane,
++ enum omap_burst_size burst_size)
++{
++ int shift;
++ u32 val;
++
++ enable_clocks(1);
++
++ switch (plane) {
++ case OMAP_DSS_GFX:
++ shift = 6;
++ break;
++ case OMAP_DSS_VIDEO1:
++ case OMAP_DSS_VIDEO2:
++ shift = 14;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, burst_size, shift+1, shift);
++ dispc_write_reg(dispc_reg_att[plane], val);
++
++ enable_clocks(0);
++}
++
++static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
++{
++ u32 val;
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = dispc_read_reg(dispc_reg_att[plane]);
++ val = FLD_MOD(val, enable, 9, 9);
++ dispc_write_reg(dispc_reg_att[plane], val);
++}
++
++void dispc_set_lcd_size(u16 width, u16 height)
++{
++ u32 val;
++ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ enable_clocks(1);
++ dispc_write_reg(DISPC_SIZE_LCD, val);
++ enable_clocks(0);
++}
++
++void dispc_set_digit_size(u16 width, u16 height)
++{
++ u32 val;
++ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
++ enable_clocks(1);
++ dispc_write_reg(DISPC_SIZE_DIG, val);
++ enable_clocks(0);
++}
++
++u32 dispc_get_plane_fifo_size(enum omap_plane plane)
++{
++ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
++ DISPC_VID_FIFO_SIZE_STATUS(0),
++ DISPC_VID_FIFO_SIZE_STATUS(1) };
++ u32 size;
++
++ enable_clocks(1);
++
++ if (cpu_is_omap24xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
++ else if (cpu_is_omap34xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
++ else
++ BUG();
++
++ if (cpu_is_omap34xx()) {
++ /* FIFOMERGE */
++ if (REG_GET(DISPC_CONFIG, 14, 14))
++ size *= 3;
++ }
++
++ enable_clocks(0);
++
++ return size;
++}
++
++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
++{
++ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
++ DISPC_VID_FIFO_THRESHOLD(0),
++ DISPC_VID_FIFO_THRESHOLD(1) };
++ u32 size;
++
++ enable_clocks(1);
++
++ size = dispc_get_plane_fifo_size(plane);
++
++ BUG_ON(low > size || high > size);
++
++ DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n",
++ plane, size,
++ REG_GET(ftrs_reg[plane], 11, 0),
++ REG_GET(ftrs_reg[plane], 27, 16),
++ low, high);
++
++ if (cpu_is_omap24xx())
++ dispc_write_reg(ftrs_reg[plane],
++ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
++ else
++ dispc_write_reg(ftrs_reg[plane],
++ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
++
++ enable_clocks(0);
++}
++
++void dispc_enable_fifomerge(bool enable)
++{
++ enable_clocks(1);
++
++ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
++
++ enable_clocks(0);
++}
++
++static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
++{
++ u32 val;
++ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
++ DISPC_VID_FIR(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
++ dispc_write_reg(fir_reg[plane-1], val);
++}
++
++static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
++{
++ u32 val;
++ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
++ DISPC_VID_ACCU0(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
++ dispc_write_reg(ac0_reg[plane-1], val);
++}
++
++static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
++{
++ u32 val;
++ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
++ DISPC_VID_ACCU1(1) };
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
++ dispc_write_reg(ac1_reg[plane-1], val);
++}
++
++
++static void _dispc_set_scaling(enum omap_plane plane,
++ u16 orig_width, u16 orig_height,
++ u16 out_width, u16 out_height,
++ bool ilace)
++{
++ int fir_hinc;
++ int fir_vinc;
++ int hscaleup, vscaleup, five_taps;
++ int fieldmode = 0;
++ int accu0 = 0;
++ int accu1 = 0;
++ u32 l;
++
++ BUG_ON(plane == OMAP_DSS_GFX);
++
++ hscaleup = orig_width <= out_width;
++ vscaleup = orig_height <= out_height;
++ five_taps = orig_height > out_height * 2;
++
++ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
++
++ if (!orig_width || orig_width == out_width)
++ fir_hinc = 0;
++ else
++ fir_hinc = 1024 * orig_width / out_width;
++
++ if (!orig_height || orig_height == out_height)
++ fir_vinc = 0;
++ else
++ fir_vinc = 1024 * orig_height / out_height;
++
++ _dispc_set_fir(plane, fir_hinc, fir_vinc);
++
++ l = dispc_read_reg(dispc_reg_att[plane]);
++ l &= ~((0x0f << 5) | (0x3 << 21));
++
++ l |= fir_hinc ? (1 << 5) : 0;
++ l |= fir_vinc ? (1 << 6) : 0;
++
++ l |= hscaleup ? 0 : (1 << 7);
++ l |= vscaleup ? 0 : (1 << 8);
++
++ l |= five_taps ? (1 << 21) : 0;
++ l |= five_taps ? (1 << 22) : 0;
++
++ dispc_write_reg(dispc_reg_att[plane], l);
++
++ if (ilace) {
++ if (fieldmode) {
++ accu0 = fir_vinc / 2;
++ accu1 = 0;
++ } else {
++ accu0 = 0;
++ accu1 = fir_vinc / 2;
++ if (accu1 >= 1024/2) {
++ accu0 = 1024/2;
++ accu1 -= accu0;
++ }
++ }
++ }
++
++ _dispc_set_vid_accu0(plane, 0, accu0);
++ _dispc_set_vid_accu1(plane, 0, accu1);
++}
++
++static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
++ bool mirroring, enum omap_color_mode color_mode)
++{
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY) {
++ int vidrot = 0;
++
++ if (mirroring) {
++ switch (rotation) {
++ case 0: vidrot = 2; break;
++ case 1: vidrot = 3; break;
++ case 2: vidrot = 0; break;
++ case 3: vidrot = 1; break;
++ }
++ } else {
++ switch (rotation) {
++ case 0: vidrot = 0; break;
++ case 1: vidrot = 1; break;
++ case 2: vidrot = 2; break;
++ case 3: vidrot = 1; break;
++ }
++ }
++
++ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
++
++ if (rotation == 1 || rotation == 3)
++ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
++ else
++ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
++ } else {
++ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
++ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
++ }
++}
++
++static int pixinc(int pixels, u8 ps)
++{
++ if (pixels == 1)
++ return 1;
++ else if (pixels > 1)
++ return 1 + (pixels - 1) * ps;
++ else if (pixels < 0)
++ return 1 - (-pixels + 1) * ps;
++ else
++ BUG();
++}
++
++static void calc_rotation_offset(u8 rotation, bool mirror,
++ u16 screen_width,
++ u16 width, u16 height,
++ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned *offset0, unsigned *offset1,
++ u16 *row_inc, u16 *pix_inc)
++{
++ u8 ps;
++ u16 fbw, fbh;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ ps = 2;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ ps = 3;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ ps = 4;
++ break;
++
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ ps = 2;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
++ width, height);
++
++ /* width & height are overlay sizes, convert to fb sizes */
++
++ if (rotation == 0 || rotation == 2) {
++ fbw = width;
++ fbh = height;
++ } else {
++ fbw = height;
++ fbh = width;
++ }
++
++ switch (rotation + mirror * 4) {
++ case 0:
++ *offset0 = 0;
++ if (fieldmode)
++ *offset1 = screen_width * ps;
++ else
++ *offset1 = 0;
++ *row_inc = pixinc(1 + (screen_width - fbw) +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++ case 1:
++ *offset0 = screen_width * (fbh - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 + ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
++ (fieldmode ? 1 : 0), ps);
++ *pix_inc = pixinc(-screen_width, ps);
++ break;
++ case 2:
++ *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 - screen_width * ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(-1 -
++ (screen_width - fbw) -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(-1, ps);
++ break;
++ case 3:
++ *offset0 = (fbw - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 - ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
++ (fieldmode ? 1 : 0), ps);
++ *pix_inc = pixinc(screen_width, ps);
++ break;
++
++ /* mirroring */
++ case 0 + 4:
++ *offset0 = (fbw - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 + screen_width * ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(screen_width * 2 - 1 +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(-1, ps);
++ break;
++
++ case 1 + 4:
++ *offset0 = 0;
++ if (fieldmode)
++ *offset1 = *offset0 + screen_width * ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
++ (fieldmode ? 1 : 0),
++ ps);
++ *pix_inc = pixinc(screen_width, ps);
++ break;
++
++ case 2 + 4:
++ *offset0 = screen_width * (fbh - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 + screen_width * ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(1 - screen_width * 2 -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ case 3 + 4:
++ *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ if (fieldmode)
++ *offset1 = *offset0 + screen_width * ps;
++ else
++ *offset1 = *offset0;
++ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
++ (fieldmode ? 1 : 0),
++ ps);
++ *pix_inc = pixinc(-screen_width, ps);
++ break;
++
++ default:
++ BUG();
++ }
++}
++
++static int _dispc_setup_plane(enum omap_plane plane,
++ enum omap_channel channel_out,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ u8 rotation, int mirror)
++{
++ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
++ bool five_taps = height > out_height * 2;
++ bool fieldmode = 0;
++ int cconv = 0;
++ unsigned offset0, offset1;
++ u16 row_inc;
++ u16 pix_inc;
++
++ if (plane == OMAP_DSS_GFX) {
++ if (width != out_width || height != out_height)
++ return -EINVAL;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_RGB24P:
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ } else {
++ /* video plane */
++ if (width > (2048 >> five_taps))
++ return -EINVAL;
++
++ if (out_width < width / maxdownscale ||
++ out_width > width * 8)
++ return -EINVAL;
++
++ if (out_height < height / maxdownscale ||
++ out_height > height * 8)
++ return -EINVAL;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_RGB24P:
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_RGBX32:
++ break;
++
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ if (plane == OMAP_DSS_VIDEO1)
++ return -EINVAL;
++ break;
++
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ cconv = 1;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ }
++
++ if (ilace && height >= out_height)
++ fieldmode = 1;
++
++ calc_rotation_offset(rotation, mirror,
++ screen_width, width, height, color_mode,
++ fieldmode,
++ &offset0, &offset1, &row_inc, &pix_inc);
++
++ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
++ offset0, offset1, row_inc, pix_inc);
++
++ if (ilace) {
++ if (fieldmode)
++ height /= 2;
++ pos_y /= 2;
++ out_height /= 2;
++
++ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
++ "out_height %d\n",
++ height, pos_y, out_height);
++ }
++
++ _dispc_set_channel_out(plane, channel_out);
++ _dispc_set_color_mode(plane, color_mode);
++
++ _dispc_set_plane_ba0(plane, paddr + offset0);
++ _dispc_set_plane_ba1(plane, paddr + offset1);
++
++ _dispc_set_row_inc(plane, row_inc);
++ _dispc_set_pix_inc(plane, pix_inc);
++
++ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
++ out_width, out_height);
++
++ _dispc_set_plane_pos(plane, pos_x, pos_y);
++
++ _dispc_set_pic_size(plane, width, height);
++
++ if (plane != OMAP_DSS_GFX) {
++ _dispc_set_scaling(plane, width, height,
++ out_width, out_height,
++ ilace);
++ _dispc_set_vid_size(plane, out_width, out_height);
++ _dispc_set_vid_color_conv(plane, cconv);
++ }
++
++ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
++
++ return 0;
++}
++
++static void _dispc_enable_plane(enum omap_plane plane, bool enable)
++{
++ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
++}
++
++static void dispc_disable_isr(void *data, u32 mask)
++{
++ struct completion *compl = data;
++ complete(compl);
++}
++
++static void _enable_lcd_out(bool enable)
++{
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
++}
++
++void dispc_enable_lcd_out(bool enable)
++{
++ struct completion frame_done_completion;
++ bool is_on;
++ int r;
++
++ enable_clocks(1);
++
++ /* When we disable LCD output, we need to wait until frame is done.
++ * Otherwise the DSS is still working, and turning off the clocks
++ * prevents DSS from going to OFF mode */
++ is_on = REG_GET(DISPC_CONTROL, 0, 0);
++
++ if (!enable && is_on) {
++ init_completion(&frame_done_completion);
++
++ r = omap_dispc_register_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_FRAMEDONE);
++
++ if (r)
++ DSSERR("failed to register FRAMEDONE isr\n");
++ }
++
++ _enable_lcd_out(enable);
++
++ if (!enable && is_on) {
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for FRAME DONE\n");
++
++ r = omap_dispc_unregister_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_FRAMEDONE);
++
++ if (r)
++ DSSERR("failed to unregister FRAMEDONE isr\n");
++ }
++
++ enable_clocks(0);
++}
++
++static void _enable_digit_out(bool enable)
++{
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
++}
++
++void dispc_enable_digit_out(bool enable)
++{
++ struct completion frame_done_completion;
++ int r;
++
++ enable_clocks(1);
++
++ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
++ enable_clocks(0);
++ return;
++ }
++
++ if (enable) {
++ /* When we enable digit output, we'll get an extra digit
++ * sync lost interrupt, that we need to ignore */
++ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
++ omap_dispc_set_irqs();
++ }
++
++ /* When we disable digit output, we need to wait until fields are done.
++ * Otherwise the DSS is still working, and turning off the clocks
++ * prevents DSS from going to OFF mode. And when enabling, we need to
++ * wait for the extra sync losts */
++ init_completion(&frame_done_completion);
++
++ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
++ if (r)
++ DSSERR("failed to register EVSYNC isr\n");
++
++ _enable_digit_out(enable);
++
++ /* XXX I understand from TRM that we should only wait for the
++ * current field to complete. But it seems we have to wait
++ * for both fields */
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for EVSYNC\n");
++
++ if (!wait_for_completion_timeout(&frame_done_completion,
++ msecs_to_jiffies(100)))
++ DSSERR("timeout waiting for EVSYNC\n");
++
++ r = omap_dispc_unregister_isr(dispc_disable_isr,
++ &frame_done_completion,
++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
++ if (r)
++ DSSERR("failed to unregister EVSYNC isr\n");
++
++ if (enable) {
++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
++ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
++ omap_dispc_set_irqs();
++ }
++
++ enable_clocks(0);
++}
++
++void dispc_lcd_enable_signal_polarity(bool act_high)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
++ enable_clocks(0);
++}
++
++void dispc_lcd_enable_signal(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
++ enable_clocks(0);
++}
++
++void dispc_pck_free_enable(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
++ enable_clocks(0);
++}
++
++void dispc_enable_fifohandcheck(bool enable)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
++ enable_clocks(0);
++}
++
++
++void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
++{
++ int mode;
++
++ switch (type) {
++ case OMAP_DSS_LCD_DISPLAY_STN:
++ mode = 0;
++ break;
++
++ case OMAP_DSS_LCD_DISPLAY_TFT:
++ mode = 1;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
++ enable_clocks(0);
++}
++
++void dispc_set_loadmode(enum omap_dss_load_mode mode)
++{
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
++ enable_clocks(0);
++}
++
++
++void dispc_set_default_color(enum omap_channel channel, u32 color)
++{
++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
++ DISPC_DEFAULT_COLOR1 };
++
++ enable_clocks(1);
++ dispc_write_reg(def_reg[channel], color);
++ enable_clocks(0);
++}
++
++u32 dispc_get_default_color(enum omap_channel channel)
++{
++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
++ DISPC_DEFAULT_COLOR1 };
++ u32 l;
++
++ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
++ channel != OMAP_DSS_CHANNEL_LCD);
++
++ enable_clocks(1);
++ l = dispc_read_reg(def_reg[channel]);
++ enable_clocks(0);
++
++ return l;
++}
++
++void dispc_set_trans_key(enum omap_channel ch,
++ enum omap_dss_color_key_type type,
++ u32 trans_key)
++{
++ const struct dispc_reg tr_reg[] = {
++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
++
++ dispc_write_reg(tr_reg[ch], trans_key);
++ enable_clocks(0);
++}
++
++void dispc_get_trans_key(enum omap_channel ch,
++ enum omap_dss_color_key_type *type,
++ u32 *trans_key)
++{
++ const struct dispc_reg tr_reg[] = {
++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
++
++ enable_clocks(1);
++ if (type) {
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ *type = REG_GET(DISPC_CONFIG, 11, 11) >> 11;
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ *type = REG_GET(DISPC_CONFIG, 13, 13) >> 13;
++ else
++ BUG();
++ }
++
++ if (trans_key)
++ *trans_key = dispc_read_reg(tr_reg[ch]);
++ enable_clocks(0);
++}
++
++void dispc_enable_trans_key(enum omap_channel ch, bool enable)
++{
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
++ enable_clocks(0);
++}
++
++bool dispc_trans_key_enabled(enum omap_channel ch)
++{
++ bool enabled;
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ enabled = REG_GET(DISPC_CONFIG, 10, 10);
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ enabled = REG_GET(DISPC_CONFIG, 12, 12);
++ else BUG();
++ enable_clocks(0);
++
++ return enabled;
++}
++
++
++void dispc_set_tft_data_lines(u8 data_lines)
++{
++ int code;
++
++ switch (data_lines) {
++ case 12:
++ code = 0;
++ break;
++ case 16:
++ code = 1;
++ break;
++ case 18:
++ code = 2;
++ break;
++ case 24:
++ code = 3;
++ break;
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
++ enable_clocks(0);
++}
++
++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
++{
++ u32 l;
++ int stallmode;
++ int gpout0 = 1;
++ int gpout1;
++
++ switch (mode) {
++ case OMAP_DSS_PARALLELMODE_BYPASS:
++ stallmode = 0;
++ gpout1 = 1;
++ break;
++
++ case OMAP_DSS_PARALLELMODE_RFBI:
++ stallmode = 1;
++ gpout1 = 0;
++ break;
++
++ case OMAP_DSS_PARALLELMODE_DSI:
++ stallmode = 1;
++ gpout1 = 1;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ enable_clocks(1);
++
++ l = dispc_read_reg(DISPC_CONTROL);
++
++ l = FLD_MOD(l, stallmode, 11, 11);
++ l = FLD_MOD(l, gpout0, 15, 15);
++ l = FLD_MOD(l, gpout1, 16, 16);
++
++ dispc_write_reg(DISPC_CONTROL, l);
++
++ enable_clocks(0);
++}
++
++static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
++ int vsw, int vfp, int vbp)
++{
++ u32 timing_h, timing_v;
++
++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
++ BUG_ON(hsw < 1 || hsw > 64);
++ BUG_ON(hfp < 1 || hfp > 256);
++ BUG_ON(hbp < 1 || hbp > 256);
++
++ BUG_ON(vsw < 1 || vsw > 64);
++ BUG_ON(vfp < 0 || vfp > 255);
++ BUG_ON(vbp < 0 || vbp > 255);
++
++ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
++ FLD_VAL(hbp-1, 27, 20);
++
++ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
++ FLD_VAL(vbp, 27, 20);
++ } else {
++ BUG_ON(hsw < 1 || hsw > 256);
++ BUG_ON(hfp < 1 || hfp > 4096);
++ BUG_ON(hbp < 1 || hbp > 4096);
++
++ BUG_ON(vsw < 1 || vsw > 256);
++ BUG_ON(vfp < 0 || vfp > 4095);
++ BUG_ON(vbp < 0 || vbp > 4095);
++
++ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
++ FLD_VAL(hbp-1, 31, 20);
++
++ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
++ FLD_VAL(vbp, 31, 20);
++ }
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_TIMING_H, timing_h);
++ dispc_write_reg(DISPC_TIMING_V, timing_v);
++ enable_clocks(0);
++}
++
++/* change name to mode? */
++void dispc_set_lcd_timings(struct omap_video_timings *timings)
++{
++ unsigned xtot, ytot;
++ unsigned long ht, vt;
++
++ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
++ timings->vsw, timings->vfp, timings->vbp);
++
++ dispc_set_lcd_size(timings->x_res, timings->y_res);
++
++ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
++ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
++
++ ht = (timings->pixel_clock * 1000) / xtot;
++ vt = (timings->pixel_clock * 1000) / xtot / ytot;
++
++ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
++ DSSDBG("pck %u\n", timings->pixel_clock);
++ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
++ timings->hsw, timings->hfp, timings->hbp,
++ timings->vsw, timings->vfp, timings->vbp);
++
++ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
++}
++
++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
++{
++ BUG_ON(lck_div < 1);
++ BUG_ON(pck_div < 2);
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_DIVISOR,
++ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
++ enable_clocks(0);
++}
++
++static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
++{
++ u32 l;
++ l = dispc_read_reg(DISPC_DIVISOR);
++ *lck_div = FLD_GET(l, 23, 16);
++ *pck_div = FLD_GET(l, 7, 0);
++}
++
++unsigned long dispc_fclk_rate(void)
++{
++ unsigned long r = 0;
++
++ if (dss_get_dispc_clk_source() == 0)
++ r = dss_clk_get_rate(DSS_CLK_FCK1);
++ else
++#ifdef CONFIG_OMAP2_DSS_DSI
++ r = dsi_get_dsi1_pll_rate();
++#else
++ BUG();
++#endif
++ return r;
++}
++
++unsigned long dispc_pclk_rate(void)
++{
++ int lcd, pcd;
++ unsigned long r;
++ u32 l;
++
++ l = dispc_read_reg(DISPC_DIVISOR);
++
++ lcd = FLD_GET(l, 23, 16);
++ pcd = FLD_GET(l, 7, 0);
++
++ r = dispc_fclk_rate();
++
++ return r / lcd / pcd;
++}
++
++void dispc_dump_clocks(struct seq_file *s)
++{
++ int lcd, pcd;
++
++ enable_clocks(1);
++
++ dispc_get_lcd_divisor(&lcd, &pcd);
++
++ seq_printf(s, "- dispc -\n");
++
++ seq_printf(s, "dispc fclk source = %s\n",
++ dss_get_dispc_clk_source() == 0 ?
++ "dss1_alwon_fclk" : "dsi1_pll_fclk");
++
++ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n",
++ dispc_fclk_rate(),
++ lcd, pcd,
++ dispc_pclk_rate());
++
++ enable_clocks(0);
++}
++
++void dispc_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DISPC_REVISION);
++ DUMPREG(DISPC_SYSCONFIG);
++ DUMPREG(DISPC_SYSSTATUS);
++ DUMPREG(DISPC_IRQSTATUS);
++ DUMPREG(DISPC_IRQENABLE);
++ DUMPREG(DISPC_CONTROL);
++ DUMPREG(DISPC_CONFIG);
++ DUMPREG(DISPC_CAPABLE);
++ DUMPREG(DISPC_DEFAULT_COLOR0);
++ DUMPREG(DISPC_DEFAULT_COLOR1);
++ DUMPREG(DISPC_TRANS_COLOR0);
++ DUMPREG(DISPC_TRANS_COLOR1);
++ DUMPREG(DISPC_LINE_STATUS);
++ DUMPREG(DISPC_LINE_NUMBER);
++ DUMPREG(DISPC_TIMING_H);
++ DUMPREG(DISPC_TIMING_V);
++ DUMPREG(DISPC_POL_FREQ);
++ DUMPREG(DISPC_DIVISOR);
++ DUMPREG(DISPC_GLOBAL_ALPHA);
++ DUMPREG(DISPC_SIZE_DIG);
++ DUMPREG(DISPC_SIZE_LCD);
++
++ DUMPREG(DISPC_GFX_BA0);
++ DUMPREG(DISPC_GFX_BA1);
++ DUMPREG(DISPC_GFX_POSITION);
++ DUMPREG(DISPC_GFX_SIZE);
++ DUMPREG(DISPC_GFX_ATTRIBUTES);
++ DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
++ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
++ DUMPREG(DISPC_GFX_ROW_INC);
++ DUMPREG(DISPC_GFX_PIXEL_INC);
++ DUMPREG(DISPC_GFX_WINDOW_SKIP);
++ DUMPREG(DISPC_GFX_TABLE_BA);
++
++ DUMPREG(DISPC_DATA_CYCLE1);
++ DUMPREG(DISPC_DATA_CYCLE2);
++ DUMPREG(DISPC_DATA_CYCLE3);
++
++ DUMPREG(DISPC_CPR_COEF_R);
++ DUMPREG(DISPC_CPR_COEF_G);
++ DUMPREG(DISPC_CPR_COEF_B);
++
++ DUMPREG(DISPC_GFX_PRELOAD);
++
++ DUMPREG(DISPC_VID_BA0(0));
++ DUMPREG(DISPC_VID_BA1(0));
++ DUMPREG(DISPC_VID_POSITION(0));
++ DUMPREG(DISPC_VID_SIZE(0));
++ DUMPREG(DISPC_VID_ATTRIBUTES(0));
++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
++ DUMPREG(DISPC_VID_ROW_INC(0));
++ DUMPREG(DISPC_VID_PIXEL_INC(0));
++ DUMPREG(DISPC_VID_FIR(0));
++ DUMPREG(DISPC_VID_PICTURE_SIZE(0));
++ DUMPREG(DISPC_VID_ACCU0(0));
++ DUMPREG(DISPC_VID_ACCU1(0));
++
++ DUMPREG(DISPC_VID_BA0(1));
++ DUMPREG(DISPC_VID_BA1(1));
++ DUMPREG(DISPC_VID_POSITION(1));
++ DUMPREG(DISPC_VID_SIZE(1));
++ DUMPREG(DISPC_VID_ATTRIBUTES(1));
++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
++ DUMPREG(DISPC_VID_ROW_INC(1));
++ DUMPREG(DISPC_VID_PIXEL_INC(1));
++ DUMPREG(DISPC_VID_FIR(1));
++ DUMPREG(DISPC_VID_PICTURE_SIZE(1));
++ DUMPREG(DISPC_VID_ACCU0(1));
++ DUMPREG(DISPC_VID_ACCU1(1));
++
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 0));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 1));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 2));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 3));
++ DUMPREG(DISPC_VID_CONV_COEF(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
++
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 0));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 1));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 2));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 3));
++ DUMPREG(DISPC_VID_CONV_COEF(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
++
++ DUMPREG(DISPC_VID_PRELOAD(0));
++ DUMPREG(DISPC_VID_PRELOAD(1));
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
++ bool ihs, bool ivs, u8 acbi, u8 acb)
++{
++ u32 l = 0;
++
++ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
++ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
++
++ l |= FLD_VAL(onoff, 17, 17);
++ l |= FLD_VAL(rf, 16, 16);
++ l |= FLD_VAL(ieo, 15, 15);
++ l |= FLD_VAL(ipc, 14, 14);
++ l |= FLD_VAL(ihs, 13, 13);
++ l |= FLD_VAL(ivs, 12, 12);
++ l |= FLD_VAL(acbi, 11, 8);
++ l |= FLD_VAL(acb, 7, 0);
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_POL_FREQ, l);
++ enable_clocks(0);
++}
++
++void dispc_set_pol_freq(struct omap_panel *panel)
++{
++ _dispc_set_pol_freq((panel->config & OMAP_DSS_LCD_ONOFF) != 0,
++ (panel->config & OMAP_DSS_LCD_RF) != 0,
++ (panel->config & OMAP_DSS_LCD_IEO) != 0,
++ (panel->config & OMAP_DSS_LCD_IPC) != 0,
++ (panel->config & OMAP_DSS_LCD_IHS) != 0,
++ (panel->config & OMAP_DSS_LCD_IVS) != 0,
++ panel->acbi, panel->acb);
++}
++
++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
++ u16 *lck_div, u16 *pck_div)
++{
++ u16 pcd_min = is_tft ? 2 : 3;
++ unsigned long best_pck;
++ u16 best_ld, cur_ld;
++ u16 best_pd, cur_pd;
++
++ best_pck = 0;
++ best_ld = 0;
++ best_pd = 0;
++
++ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
++ unsigned long lck = fck / cur_ld;
++
++ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
++ unsigned long pck = lck / cur_pd;
++ long old_delta = abs(best_pck - req_pck);
++ long new_delta = abs(pck - req_pck);
++
++ if (best_pck == 0 || new_delta < old_delta) {
++ best_pck = pck;
++ best_ld = cur_ld;
++ best_pd = cur_pd;
++
++ if (pck == req_pck)
++ goto found;
++ }
++
++ if (pck < req_pck)
++ break;
++ }
++
++ if (lck / pcd_min < req_pck)
++ break;
++ }
++
++found:
++ *lck_div = best_ld;
++ *pck_div = best_pd;
++}
++
++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
++ struct dispc_clock_info *cinfo)
++{
++ unsigned long prate;
++ struct dispc_clock_info cur, best;
++ int match = 0;
++ int min_fck_per_pck;
++ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1);
++
++ if (cpu_is_omap34xx())
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ else
++ prate = 0;
++
++ if (req_pck == dispc.cache_req_pck &&
++ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
++ dispc.cache_cinfo.fck == fck_rate)) {
++ DSSDBG("dispc clock info found from cache.\n");
++ *cinfo = dispc.cache_cinfo;
++ return 0;
++ }
++
++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
++
++ if (min_fck_per_pck &&
++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
++ DSSERR("Requested pixel clock not possible with the current "
++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
++ "the constraint off.\n");
++ min_fck_per_pck = 0;
++ }
++
++retry:
++ memset(&cur, 0, sizeof(cur));
++ memset(&best, 0, sizeof(best));
++
++ if (cpu_is_omap24xx()) {
++ /* XXX can we change the clock on omap2? */
++ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1);
++ cur.fck_div = 1;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck, cur.fck,
++ &cur.lck_div, &cur.pck_div);
++
++ cur.lck = cur.fck / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ best = cur;
++
++ goto found;
++ } else if (cpu_is_omap34xx()) {
++ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) {
++ cur.fck = prate / cur.fck_div * 2;
++
++ if (cur.fck > DISPC_MAX_FCK)
++ continue;
++
++ if (min_fck_per_pck &&
++ cur.fck < req_pck * min_fck_per_pck)
++ continue;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck, cur.fck,
++ &cur.lck_div, &cur.pck_div);
++
++ cur.lck = cur.fck / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
++ best = cur;
++
++ if (cur.pck == req_pck)
++ goto found;
++ }
++ }
++ } else {
++ BUG();
++ }
++
++found:
++ if (!match) {
++ if (min_fck_per_pck) {
++ DSSERR("Could not find suitable clock settings.\n"
++ "Turning FCK/PCK constraint off and"
++ "trying again.\n");
++ min_fck_per_pck = 0;
++ goto retry;
++ }
++
++ DSSERR("Could not find suitable clock settings.\n");
++
++ return -EINVAL;
++ }
++
++ if (cinfo)
++ *cinfo = best;
++
++ dispc.cache_req_pck = req_pck;
++ dispc.cache_prate = prate;
++ dispc.cache_cinfo = best;
++
++ return 0;
++}
++
++int dispc_set_clock_div(struct dispc_clock_info *cinfo)
++{
++ unsigned long prate;
++ int r;
++
++ if (cpu_is_omap34xx()) {
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ DSSDBG("dpll4_m4 = %ld\n", prate);
++ }
++
++ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
++ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div);
++ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div);
++
++ if (cpu_is_omap34xx()) {
++ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div);
++ if (r)
++ return r;
++ }
++
++ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
++
++ return 0;
++}
++
++int dispc_get_clock_div(struct dispc_clock_info *cinfo)
++{
++ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
++
++ if (cpu_is_omap34xx()) {
++ unsigned long prate;
++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck));
++ cinfo->fck_div = prate / (cinfo->fck / 2);
++ } else {
++ cinfo->fck_div = 0;
++ }
++
++ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
++ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
++
++ cinfo->lck = cinfo->fck / cinfo->lck_div;
++ cinfo->pck = cinfo->lck / cinfo->pck_div;
++
++ return 0;
++}
++
++static void omap_dispc_set_irqs(void)
++{
++ unsigned long flags;
++ u32 mask = dispc.irq_error_mask;
++ int i;
++ struct omap_dispc_isr_data *isr_data;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++
++ if (isr_data->isr == NULL)
++ continue;
++
++ mask |= isr_data->mask;
++ }
++
++ enable_clocks(1);
++ dispc_write_reg(DISPC_IRQENABLE, mask);
++ enable_clocks(0);
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++}
++
++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
++{
++ int i;
++ int ret;
++ unsigned long flags;
++ struct omap_dispc_isr_data *isr_data;
++
++ if (isr == NULL)
++ return -EINVAL;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ /* check for duplicate entry */
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++ if (isr_data->isr == isr && isr_data->arg == arg &&
++ isr_data->mask == mask) {
++ ret = -EINVAL;
++ goto err;
++ }
++ }
++
++ isr_data = NULL;
++ ret = -EBUSY;
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++
++ if (isr_data->isr != NULL)
++ continue;
++
++ isr_data->isr = isr;
++ isr_data->arg = arg;
++ isr_data->mask = mask;
++ ret = 0;
++
++ break;
++ }
++err:
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ if (ret == 0)
++ omap_dispc_set_irqs();
++
++ return ret;
++}
++EXPORT_SYMBOL(omap_dispc_register_isr);
++
++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
++{
++ int i;
++ unsigned long flags;
++ int ret = -EINVAL;
++ struct omap_dispc_isr_data *isr_data;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++ if (isr_data->isr != isr || isr_data->arg != arg ||
++ isr_data->mask != mask)
++ continue;
++
++ /* found the correct isr */
++
++ isr_data->isr = NULL;
++ isr_data->arg = NULL;
++ isr_data->mask = 0;
++
++ ret = 0;
++ break;
++ }
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
++
++ if (ret == 0)
++ omap_dispc_set_irqs();
++
++ return ret;
++}
++EXPORT_SYMBOL(omap_dispc_unregister_isr);
++
++#ifdef DEBUG
++static void print_irq_status(u32 status)
++{
++ if ((status & dispc.irq_error_mask) == 0)
++ return;
++
++ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DISPC_IRQ_##x) \
++ printk(#x " ");
++ PIS(GFX_FIFO_UNDERFLOW);
++ PIS(OCP_ERR);
++ PIS(VID1_FIFO_UNDERFLOW);
++ PIS(VID2_FIFO_UNDERFLOW);
++ PIS(SYNC_LOST);
++ PIS(SYNC_LOST_DIGIT);
++#undef PIS
++
++ printk("\n");
++}
++#endif
++
++/* Called from dss.c. Note that we don't touch clocks here,
++ * but we presume they are on because we got an IRQ. However,
++ * an irq handler may turn the clocks off, so we may not have
++ * clock later in the function. */
++void dispc_irq_handler(void)
++{
++ int i;
++ u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++ u32 handledirqs = 0;
++ u32 unhandled_errors;
++ struct omap_dispc_isr_data *isr_data;
++
++#ifdef DEBUG
++ if (dss_debug)
++ print_irq_status(irqstatus);
++#endif
++ /* Ack the interrupt. Do it here before clocks are possibly turned
++ * off */
++ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ isr_data = &dispc.registered_isr[i];
++
++ if (!isr_data->isr)
++ continue;
++
++ if (isr_data->mask & irqstatus) {
++ isr_data->isr(isr_data->arg, irqstatus);
++ handledirqs |= isr_data->mask;
++ }
++ }
++
++ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
++
++ if (unhandled_errors) {
++ spin_lock(&dispc.error_lock);
++ dispc.error_irqs |= unhandled_errors;
++ spin_unlock(&dispc.error_lock);
++
++ dispc.irq_error_mask &= ~unhandled_errors;
++ omap_dispc_set_irqs();
++
++ schedule_work(&dispc.error_work);
++ }
++}
++
++static void dispc_error_worker(struct work_struct *work)
++{
++ int i;
++ u32 errors;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc.error_lock, flags);
++ errors = dispc.error_irqs;
++ dispc.error_irqs = 0;
++ spin_unlock_irqrestore(&dispc.error_lock, flags);
++
++ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
++ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 0) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
++ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 1) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
++ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id == 2) {
++ dispc_enable_plane(ovl->id, 0);
++ dispc_go(ovl->manager->id);
++ mdelay(50);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_SYNC_LOST) {
++ DSSERR("SYNC_LOST, disabling LCD\n");
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
++ mgr->display->disable(mgr->display);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
++ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
++ mgr->display->disable(mgr->display);
++ break;
++ }
++ }
++ }
++
++ if (errors & DISPC_IRQ_OCP_ERR) {
++ DSSERR("OCP_ERR\n");
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
++ mgr->display->disable(mgr->display);
++ }
++ }
++
++ dispc.irq_error_mask |= errors;
++ omap_dispc_set_irqs();
++}
++
++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
++{
++ void dispc_irq_wait_handler(void *data, u32 mask)
++ {
++ complete((struct completion *)data);
++ }
++
++ int r;
++ DECLARE_COMPLETION_ONSTACK(completion);
++
++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
++ irqmask);
++
++ if (r)
++ return r;
++
++ timeout = wait_for_completion_timeout(&completion, timeout);
++
++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
++
++ if (timeout == 0)
++ return -ETIMEDOUT;
++
++ if (timeout == -ERESTARTSYS)
++ return -ERESTARTSYS;
++
++ return 0;
++}
++
++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
++ unsigned long timeout)
++{
++ void dispc_irq_wait_handler(void *data, u32 mask)
++ {
++ complete((struct completion *)data);
++ }
++
++ int r;
++ DECLARE_COMPLETION_ONSTACK(completion);
++
++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
++ irqmask);
++
++ if (r)
++ return r;
++
++ timeout = wait_for_completion_interruptible_timeout(&completion,
++ timeout);
++
++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
++
++ if (timeout == 0)
++ return -ETIMEDOUT;
++
++ if (timeout == -ERESTARTSYS)
++ return -ERESTARTSYS;
++
++ return 0;
++}
++
++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
++void dispc_fake_vsync_irq(void)
++{
++ u32 irqstatus = DISPC_IRQ_VSYNC;
++ int i;
++
++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
++ struct omap_dispc_isr_data *isr_data;
++ isr_data = &dispc.registered_isr[i];
++
++ if (!isr_data->isr)
++ continue;
++
++ if (isr_data->mask & irqstatus)
++ isr_data->isr(isr_data->arg, irqstatus);
++ }
++}
++#endif
++
++static void _omap_dispc_initialize_irq(void)
++{
++ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
++
++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
++
++ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
++ * so clear it */
++ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
++
++ omap_dispc_set_irqs();
++}
++
++static void _omap_dispc_initial_config(void)
++{
++ u32 l;
++
++ l = dispc_read_reg(DISPC_SYSCONFIG);
++ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
++ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
++ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
++ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
++ dispc_write_reg(DISPC_SYSCONFIG, l);
++
++ /* FUNCGATED */
++ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
++
++ /* L3 firewall setting: enable access to OCM RAM */
++ if (cpu_is_omap24xx())
++ __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
++
++ _dispc_setup_color_conv_coef();
++
++ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
++}
++
++int dispc_init(void)
++{
++ u32 rev;
++
++ spin_lock_init(&dispc.irq_lock);
++ spin_lock_init(&dispc.error_lock);
++
++ INIT_WORK(&dispc.error_work, dispc_error_worker);
++
++ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
++ if (!dispc.base) {
++ DSSERR("can't ioremap DISPC\n");
++ return -ENOMEM;
++ }
++
++ if (cpu_is_omap34xx()) {
++ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
++ if (IS_ERR(dispc.dpll4_m4_ck)) {
++ DSSERR("Failed to get dpll4_m4_ck\n");
++ return -ENODEV;
++ }
++ }
++
++ enable_clocks(1);
++
++ _omap_dispc_initial_config();
++
++ _omap_dispc_initialize_irq();
++
++ dispc_save_context();
++
++ rev = dispc_read_reg(DISPC_REVISION);
++ printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ enable_clocks(0);
++
++ return 0;
++}
++
++void dispc_exit(void)
++{
++ if (cpu_is_omap34xx())
++ clk_put(dispc.dpll4_m4_ck);
++ iounmap(dispc.base);
++}
++
++int dispc_enable_plane(enum omap_plane plane, bool enable)
++{
++ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
++
++ enable_clocks(1);
++ _dispc_enable_plane(plane, enable);
++ enable_clocks(0);
++
++ return 0;
++}
++
++int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ u8 rotation, bool mirror)
++{
++ int r = 0;
++
++ DSSDBG("dispc_setup_plane %d, ch %d, pa %x, sw %d, %d,%d, %dx%d -> "
++ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
++ plane, channel_out, paddr, screen_width, pos_x, pos_y,
++ width, height,
++ out_width, out_height,
++ ilace, color_mode,
++ rotation, mirror);
++
++ enable_clocks(1);
++
++ r = _dispc_setup_plane(plane, channel_out,
++ paddr, screen_width,
++ pos_x, pos_y,
++ width, height,
++ out_width, out_height,
++ color_mode, ilace,
++ rotation, mirror);
++
++ enable_clocks(0);
++
++ return r;
++}
++
++static int dispc_is_intersecting(int x1, int y1, int w1, int h1,
++ int x2, int y2, int w2, int h2)
++{
++ if (x1 >= (x2+w2))
++ return 0;
++
++ if ((x1+w1) <= x2)
++ return 0;
++
++ if (y1 >= (y2+h2))
++ return 0;
++
++ if ((y1+h1) <= y2)
++ return 0;
++
++ return 1;
++}
++
++static int dispc_is_overlay_scaled(struct omap_overlay_info *pi)
++{
++ if (pi->width != pi->out_width)
++ return 1;
++
++ if (pi->height != pi->out_height)
++ return 1;
++
++ return 0;
++}
++
++/* returns the area that needs updating */
++void dispc_setup_partial_planes(struct omap_display *display,
++ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
++{
++ struct omap_overlay_manager *mgr;
++ int i;
++
++ int x, y, w, h;
++
++ x = *xi;
++ y = *yi;
++ w = *wi;
++ h = *hi;
++
++ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
++ *xi, *yi, *wi, *hi);
++
++
++ mgr = display->manager;
++
++ if (!mgr) {
++ DSSDBG("no manager\n");
++ return;
++ }
++
++ for (i = 0; i < mgr->num_overlays; i++) {
++ struct omap_overlay *ovl;
++ struct omap_overlay_info *pi;
++ ovl = mgr->overlays[i];
++
++ if (ovl->manager != mgr)
++ continue;
++
++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
++ continue;
++
++ pi = &ovl->info;
++
++ if (!pi->enabled)
++ continue;
++ /*
++ * If the plane is intersecting and scaled, we
++ * enlarge the update region to accomodate the
++ * whole area
++ */
++
++ if (dispc_is_intersecting(x, y, w, h,
++ pi->pos_x, pi->pos_y,
++ pi->out_width, pi->out_height)) {
++ if (dispc_is_overlay_scaled(pi)) {
++
++ int x1, y1, x2, y2;
++
++ if (x > pi->pos_x)
++ x1 = pi->pos_x;
++ else
++ x1 = x;
++
++ if (y > pi->pos_y)
++ y1 = pi->pos_y;
++ else
++ y1 = y;
++
++ if ((x + w) < (pi->pos_x + pi->out_width))
++ x2 = pi->pos_x + pi->out_width;
++ else
++ x2 = x + w;
++
++ if ((y + h) < (pi->pos_y + pi->out_height))
++ y2 = pi->pos_y + pi->out_height;
++ else
++ y2 = y + h;
++
++ x = x1;
++ y = y1;
++ w = x2 - x1;
++ h = y2 - y1;
++
++ DSSDBG("Update area after enlarge due to "
++ "scaling %d, %d %dx%d\n",
++ x, y, w, h);
++ }
++ }
++ }
++
++ for (i = 0; i < mgr->num_overlays; i++) {
++ struct omap_overlay *ovl = mgr->overlays[i];
++ struct omap_overlay_info *pi = &ovl->info;
++
++ int px = pi->pos_x;
++ int py = pi->pos_y;
++ int pw = pi->width;
++ int ph = pi->height;
++ int pow = pi->out_width;
++ int poh = pi->out_height;
++ u32 pa = pi->paddr;
++ int psw = pi->screen_width;
++ int bpp;
++
++ if (ovl->manager != mgr)
++ continue;
++
++ /*
++ * If plane is not enabled or the update region
++ * does not intersect with the plane in question,
++ * we really disable the plane from hardware
++ */
++
++ if (!pi->enabled ||
++ !dispc_is_intersecting(x, y, w, h,
++ px, py, pow, poh)) {
++ dispc_enable_plane(ovl->id, 0);
++ continue;
++ }
++
++ switch (pi->color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ bpp = 16;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ bpp = 24;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ bpp = 32;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ if (x > pi->pos_x) {
++ px = 0;
++ pw -= (x - pi->pos_x);
++ pa += (x - pi->pos_x) * bpp / 8;
++ } else {
++ px = pi->pos_x - x;
++ }
++
++ if (y > pi->pos_y) {
++ py = 0;
++ ph -= (y - pi->pos_y);
++ pa += (y - pi->pos_y) * psw * bpp / 8;
++ } else {
++ py = pi->pos_y - y;
++ }
++
++ if (w < (px+pw))
++ pw -= (px+pw) - (w);
++
++ if (h < (py+ph))
++ ph -= (py+ph) - (h);
++
++ /* Can't scale the GFX plane */
++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 ||
++ dispc_is_overlay_scaled(pi) == 0) {
++ pow = pw;
++ poh = ph;
++ }
++
++ DSSDBG("calc plane %d, %x, sw %d, %d,%d, %dx%d -> %dx%d\n",
++ ovl->id, pa, psw, px, py, pw, ph, pow, poh);
++
++ dispc_setup_plane(ovl->id, mgr->id,
++ pa, psw,
++ px, py,
++ pw, ph,
++ pow, poh,
++ pi->color_mode, 0,
++ pi->rotation, // XXX rotation probably wrong
++ pi->mirror);
++
++ dispc_enable_plane(ovl->id, 1);
++ }
++
++ *xi = x;
++ *yi = y;
++ *wi = w;
++ *hi = h;
++
++}
++
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+new file mode 100644
+index 0000000..9aaf392
+--- /dev/null
++++ b/drivers/video/omap2/dss/display.c
+@@ -0,0 +1,693 @@
++/*
++ * linux/drivers/video/omap2/dss/display.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DISPLAY"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/jiffies.h>
++#include <linux/list.h>
++#include <linux/platform_device.h>
++
++#include <mach/display.h>
++#include "dss.h"
++
++static int num_displays;
++static LIST_HEAD(display_list);
++
++static ssize_t display_name_show(struct omap_display *display, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n", display->name);
++}
++
++static ssize_t display_enabled_show(struct omap_display *display, char *buf)
++{
++ bool enabled = display->state != OMAP_DSS_DISPLAY_DISABLED;
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
++}
++
++static ssize_t display_enabled_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ bool enabled, r;
++
++ enabled = simple_strtoul(buf, NULL, 10);
++
++ if (enabled != (display->state != OMAP_DSS_DISPLAY_DISABLED)) {
++ if (enabled) {
++ r = display->enable(display);
++ if (r)
++ return r;
++ } else {
++ display->disable(display);
++ }
++ }
++
++ return size;
++}
++
++static ssize_t display_upd_mode_show(struct omap_display *display, char *buf)
++{
++ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
++ if (display->get_update_mode)
++ mode = display->get_update_mode(display);
++ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
++}
++
++static ssize_t display_upd_mode_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ int val, r;
++ enum omap_dss_update_mode mode;
++
++ val = simple_strtoul(buf, NULL, 10);
++
++ switch (val) {
++ case OMAP_DSS_UPDATE_DISABLED:
++ case OMAP_DSS_UPDATE_AUTO:
++ case OMAP_DSS_UPDATE_MANUAL:
++ mode = (enum omap_dss_update_mode)val;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if ((r = display->set_update_mode(display, mode)))
++ return r;
++
++ return size;
++}
++
++static ssize_t display_tear_show(struct omap_display *display, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ display->get_te ? display->get_te(display) : 0);
++}
++
++static ssize_t display_tear_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ unsigned long te;
++ int r;
++
++ if (!display->enable_te || !display->get_te)
++ return -ENOENT;
++
++ te = simple_strtoul(buf, NULL, 0);
++
++ if ((r = display->enable_te(display, te)))
++ return r;
++
++ return size;
++}
++
++static ssize_t display_timings_show(struct omap_display *display, char *buf)
++{
++ struct omap_video_timings t;
++
++ if (!display->get_timings)
++ return -ENOENT;
++
++ display->get_timings(display, &t);
++
++ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
++ t.pixel_clock,
++ t.x_res, t.hfp, t.hbp, t.hsw,
++ t.y_res, t.vfp, t.vbp, t.vsw);
++}
++
++static ssize_t display_timings_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ struct omap_video_timings t;
++ int r, found;
++
++ if (!display->set_timings || !display->check_timings)
++ return -ENOENT;
++
++ found = 0;
++#ifdef CONFIG_OMAP2_DSS_VENC
++ if (strncmp("pal", buf, 3) == 0) {
++ t = omap_dss_pal_timings;
++ found = 1;
++ } else if (strncmp("ntsc", buf, 4) == 0) {
++ t = omap_dss_ntsc_timings;
++ found = 1;
++ }
++#endif
++ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
++ &t.pixel_clock,
++ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
++ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
++ return -EINVAL;
++
++ if ((r = display->check_timings(display, &t)))
++ return r;
++
++ display->set_timings(display, &t);
++
++ return size;
++}
++
++static ssize_t display_rotate_show(struct omap_display *display, char *buf)
++{
++ int rotate;
++ if (!display->get_rotate)
++ return -ENOENT;
++ rotate = display->get_rotate(display);
++ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
++}
++
++static ssize_t display_rotate_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ unsigned long rot;
++ int r;
++
++ if (!display->set_rotate || !display->get_rotate)
++ return -ENOENT;
++
++ rot = simple_strtoul(buf, NULL, 0);
++
++ if ((r = display->set_rotate(display, rot)))
++ return r;
++
++ return size;
++}
++
++static ssize_t display_mirror_show(struct omap_display *display, char *buf)
++{
++ int mirror;
++ if (!display->get_mirror)
++ return -ENOENT;
++ mirror = display->get_mirror(display);
++ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
++}
++
++static ssize_t display_mirror_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ unsigned long mirror;
++ int r;
++
++ if (!display->set_mirror || !display->get_mirror)
++ return -ENOENT;
++
++ mirror = simple_strtoul(buf, NULL, 0);
++
++ if ((r = display->set_mirror(display, mirror)))
++ return r;
++
++ return size;
++}
++
++static ssize_t display_panel_name_show(struct omap_display *display, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ display->panel ? display->panel->name : "");
++}
++
++static ssize_t display_ctrl_name_show(struct omap_display *display, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ display->ctrl ? display->ctrl->name : "");
++}
++
++struct display_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct omap_display *, char *);
++ ssize_t (*store)(struct omap_display *, const char *, size_t);
++};
++
++#define DISPLAY_ATTR(_name, _mode, _show, _store) \
++ struct display_attribute display_attr_##_name = \
++ __ATTR(_name, _mode, _show, _store)
++
++static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL);
++static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
++ display_enabled_show, display_enabled_store);
++static DISPLAY_ATTR(update_mode, S_IRUGO|S_IWUSR,
++ display_upd_mode_show, display_upd_mode_store);
++static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR,
++ display_tear_show, display_tear_store);
++static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR,
++ display_timings_show, display_timings_store);
++static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR,
++ display_rotate_show, display_rotate_store);
++static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
++ display_mirror_show, display_mirror_store);
++static DISPLAY_ATTR(panel_name, S_IRUGO, display_panel_name_show, NULL);
++static DISPLAY_ATTR(ctrl_name, S_IRUGO, display_ctrl_name_show, NULL);
++
++static struct attribute *display_sysfs_attrs[] = {
++ &display_attr_name.attr,
++ &display_attr_enabled.attr,
++ &display_attr_update_mode.attr,
++ &display_attr_tear_elim.attr,
++ &display_attr_timings.attr,
++ &display_attr_rotate.attr,
++ &display_attr_mirror.attr,
++ &display_attr_panel_name.attr,
++ &display_attr_ctrl_name.attr,
++ NULL
++};
++
++static ssize_t display_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
++{
++ struct omap_display *display;
++ struct display_attribute *display_attr;
++
++ display = container_of(kobj, struct omap_display, kobj);
++ display_attr = container_of(attr, struct display_attribute, attr);
++
++ if (!display_attr->show)
++ return -ENOENT;
++
++ return display_attr->show(display, buf);
++}
++
++static ssize_t display_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_display *display;
++ struct display_attribute *display_attr;
++
++ display = container_of(kobj, struct omap_display, kobj);
++ display_attr = container_of(attr, struct display_attribute, attr);
++
++ if (!display_attr->store)
++ return -ENOENT;
++
++ return display_attr->store(display, buf, size);
++}
++
++static struct sysfs_ops display_sysfs_ops = {
++ .show = display_attr_show,
++ .store = display_attr_store,
++};
++
++static struct kobj_type display_ktype = {
++ .sysfs_ops = &display_sysfs_ops,
++ .default_attrs = display_sysfs_attrs,
++};
++
++static void default_get_resolution(struct omap_display *display,
++ u16 *xres, u16 *yres)
++{
++ *xres = display->panel->timings.x_res;
++ *yres = display->panel->timings.y_res;
++}
++
++static void default_configure_overlay(struct omap_overlay *ovl)
++{
++ unsigned low, high, size;
++ enum omap_burst_size burst;
++ enum omap_plane plane = ovl->id;
++
++ burst = OMAP_DSS_BURST_16x32;
++ size = 16 * 32 / 8;
++
++ dispc_set_burst_size(plane, burst);
++
++ high = dispc_get_plane_fifo_size(plane) - 1;
++ low = dispc_get_plane_fifo_size(plane) - size;
++
++ dispc_setup_plane_fifo(plane, low, high);
++}
++
++static int default_wait_vsync(struct omap_display *display)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ u32 irq;
++
++ if (display->type == OMAP_DISPLAY_TYPE_VENC)
++ irq = DISPC_IRQ_EVSYNC_ODD;
++ else
++ irq = DISPC_IRQ_VSYNC;
++
++ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++}
++
++static int default_get_recommended_bpp(struct omap_display *display)
++{
++ if (display->panel->recommended_bpp)
++ return display->panel->recommended_bpp;
++
++ switch (display->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ if (display->hw_config.u.dpi.data_lines == 24)
++ return 24;
++ else
++ return 16;
++
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DSI:
++ if (display->ctrl->pixel_size == 24)
++ return 24;
++ else
++ return 16;
++ case OMAP_DISPLAY_TYPE_VENC:
++ case OMAP_DISPLAY_TYPE_SDI:
++ return 24;
++ return 24;
++ default:
++ BUG();
++ }
++}
++
++void dss_init_displays(struct platform_device *pdev)
++{
++ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
++ int i, r;
++
++ INIT_LIST_HEAD(&display_list);
++
++ num_displays = 0;
++
++ for (i = 0; i < pdata->num_displays; ++i) {
++ struct omap_display *display;
++
++ switch (pdata->displays[i]->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ case OMAP_DISPLAY_TYPE_DBI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ case OMAP_DISPLAY_TYPE_SDI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++#endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ case OMAP_DISPLAY_TYPE_VENC:
++#endif
++ break;
++ default:
++ DSSERR("Support for display '%s' not compiled in.\n",
++ pdata->displays[i]->name);
++ continue;
++ }
++
++ display = kzalloc(sizeof(*display), GFP_KERNEL);
++
++ /*atomic_set(&display->ref_count, 0);*/
++ display->ref_count = 0;
++
++ display->hw_config = *pdata->displays[i];
++ display->type = pdata->displays[i]->type;
++ display->name = pdata->displays[i]->name;
++
++ display->get_resolution = default_get_resolution;
++ display->get_recommended_bpp = default_get_recommended_bpp;
++ display->configure_overlay = default_configure_overlay;
++ display->wait_vsync = default_wait_vsync;
++
++ switch (display->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ dpi_init_display(display);
++ break;
++#ifdef CONFIG_OMAP2_DSS_RFBI
++ case OMAP_DISPLAY_TYPE_DBI:
++ rfbi_init_display(display);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ case OMAP_DISPLAY_TYPE_VENC:
++ venc_init_display(display);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_SDI
++ case OMAP_DISPLAY_TYPE_SDI:
++ sdi_init_display(display);
++ break;
++#endif
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++ dsi_init_display(display);
++ break;
++#endif
++ default:
++ BUG();
++ }
++
++ r = kobject_init_and_add(&display->kobj, &display_ktype,
++ &pdev->dev.kobj, "display%d", num_displays);
++
++ if (r) {
++ DSSERR("failed to create sysfs file\n");
++ continue;
++ }
++
++ num_displays++;
++
++ list_add_tail(&display->list, &display_list);
++ }
++}
++
++void dss_uninit_displays(struct platform_device *pdev)
++{
++ struct omap_display *display;
++
++ while (!list_empty(&display_list)) {
++ display = list_first_entry(&display_list,
++ struct omap_display, list);
++ list_del(&display->list);
++ kobject_del(&display->kobj);
++ kobject_put(&display->kobj);
++ kfree(display);
++ }
++
++ num_displays = 0;
++}
++
++int dss_suspend_all_displays(void)
++{
++ int r;
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ display->activate_after_resume = 0;
++ continue;
++ }
++
++ if (!display->suspend) {
++ DSSERR("display '%s' doesn't implement suspend\n",
++ display->name);
++ r = -ENOSYS;
++ goto err;
++ }
++
++ r = display->suspend(display);
++
++ if (r)
++ goto err;
++
++ display->activate_after_resume = 1;
++ }
++
++ return 0;
++err:
++ /* resume all displays that were suspended */
++ dss_resume_all_displays();
++ return r;
++}
++
++int dss_resume_all_displays(void)
++{
++ int r;
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->activate_after_resume && display->resume) {
++ r = display->resume(display);
++ if (r)
++ return r;
++ }
++
++ display->activate_after_resume = 0;
++ }
++
++ return 0;
++}
++
++int omap_dss_get_num_displays(void)
++{
++ return num_displays;
++}
++EXPORT_SYMBOL(omap_dss_get_num_displays);
++
++struct omap_display *dss_get_display(int no)
++{
++ int i = 0;
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (i++ == no)
++ return display;
++ }
++
++ return NULL;
++}
++
++struct omap_display *omap_dss_get_display(int no)
++{
++ struct omap_display *display;
++
++ display = dss_get_display(no);
++
++ if (!display)
++ return NULL;
++
++ switch (display->type) {
++ case OMAP_DISPLAY_TYPE_VENC:
++ break;
++
++ case OMAP_DISPLAY_TYPE_DPI:
++ case OMAP_DISPLAY_TYPE_SDI:
++ if (display->panel == NULL)
++ return NULL;
++ break;
++
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DSI:
++ if (display->panel == NULL || display->ctrl == NULL)
++ return NULL;
++ break;
++
++ default:
++ return NULL;
++ }
++
++ if (display->ctrl) {
++ if (!try_module_get(display->ctrl->owner))
++ goto err0;
++
++ if (display->ctrl->init)
++ if (display->ctrl->init(display) != 0)
++ goto err1;
++ }
++
++ if (display->panel) {
++ if (!try_module_get(display->panel->owner))
++ goto err2;
++
++ if (display->panel->init)
++ if (display->panel->init(display) != 0)
++ goto err3;
++ }
++
++ display->ref_count++;
++ /*
++ if (atomic_cmpxchg(&display->ref_count, 0, 1) != 0)
++ return 0;
++*/
++
++ return display;
++err3:
++ if (display->panel)
++ module_put(display->panel->owner);
++err2:
++ if (display->ctrl && display->ctrl->cleanup)
++ display->ctrl->cleanup(display);
++err1:
++ if (display->ctrl)
++ module_put(display->ctrl->owner);
++err0:
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_get_display);
++
++void omap_dss_put_display(struct omap_display *display)
++{
++ if (--display->ref_count > 0)
++ return;
++/*
++ if (atomic_cmpxchg(&display->ref_count, 1, 0) != 1)
++ return;
++*/
++ if (display->ctrl) {
++ if (display->ctrl->cleanup)
++ display->ctrl->cleanup(display);
++ module_put(display->ctrl->owner);
++ }
++
++ if (display->panel) {
++ if (display->panel->cleanup)
++ display->panel->cleanup(display);
++ module_put(display->panel->owner);
++ }
++}
++EXPORT_SYMBOL(omap_dss_put_display);
++
++void omap_dss_register_ctrl(struct omap_ctrl *ctrl)
++{
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->hw_config.ctrl_name &&
++ strcmp(display->hw_config.ctrl_name, ctrl->name) == 0) {
++ display->ctrl = ctrl;
++ DSSDBG("ctrl '%s' registered\n", ctrl->name);
++ }
++ }
++}
++EXPORT_SYMBOL(omap_dss_register_ctrl);
++
++void omap_dss_register_panel(struct omap_panel *panel)
++{
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->hw_config.panel_name &&
++ strcmp(display->hw_config.panel_name, panel->name) == 0) {
++ display->panel = panel;
++ DSSDBG("panel '%s' registered\n", panel->name);
++ }
++ }
++}
++EXPORT_SYMBOL(omap_dss_register_panel);
++
++void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl)
++{
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->hw_config.ctrl_name &&
++ strcmp(display->hw_config.ctrl_name, ctrl->name) == 0)
++ display->ctrl = NULL;
++ }
++}
++EXPORT_SYMBOL(omap_dss_unregister_ctrl);
++
++void omap_dss_unregister_panel(struct omap_panel *panel)
++{
++ struct omap_display *display;
++
++ list_for_each_entry(display, &display_list, list) {
++ if (display->hw_config.panel_name &&
++ strcmp(display->hw_config.panel_name, panel->name) == 0)
++ display->panel = NULL;
++ }
++}
++EXPORT_SYMBOL(omap_dss_unregister_panel);
+diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
+new file mode 100644
+index 0000000..71fffca
+--- /dev/null
++++ b/drivers/video/omap2/dss/dpi.c
+@@ -0,0 +1,393 @@
++/*
++ * linux/drivers/video/omap2/dss/dpi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include <mach/cpu.h>
++
++#include "dss.h"
++
++static struct {
++ int update_enabled;
++} dpi;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
++ unsigned long *fck, int *lck_div, int *pck_div)
++{
++ struct dsi_clock_info cinfo;
++ int r;
++
++ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
++ if (r)
++ return r;
++
++ r = dsi_pll_program(&cinfo);
++ if (r)
++ return r;
++
++ dss_select_clk_source(0, 1);
++
++ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
++
++ *fck = cinfo.dsi1_pll_fclk;
++ *lck_div = cinfo.lck_div;
++ *pck_div = cinfo.pck_div;
++
++ return 0;
++}
++#else
++static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
++ unsigned long *fck, int *lck_div, int *pck_div)
++{
++ struct dispc_clock_info cinfo;
++ int r;
++
++ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
++ if (r)
++ return r;
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r)
++ return r;
++
++ *fck = cinfo.fck;
++ *lck_div = cinfo.lck_div;
++ *pck_div = cinfo.pck_div;
++
++ return 0;
++}
++#endif
++
++static int dpi_set_mode(struct omap_display *display)
++{
++ struct omap_panel *panel = display->panel;
++ int lck_div, pck_div;
++ unsigned long fck;
++ unsigned long pck;
++ bool is_tft;
++ int r = 0;
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dispc_set_pol_freq(panel);
++
++ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ r = dpi_set_dsi_clk(is_tft, panel->timings.pixel_clock * 1000,
++ &fck, &lck_div, &pck_div);
++#else
++ r = dpi_set_dispc_clk(is_tft, panel->timings.pixel_clock * 1000,
++ &fck, &lck_div, &pck_div);
++#endif
++ if (r)
++ goto err0;
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ if (pck != panel->timings.pixel_clock) {
++ DSSWARN("Could not find exact pixel clock. "
++ "Requested %d kHz, got %lu kHz\n",
++ panel->timings.pixel_clock, pck);
++
++ panel->timings.pixel_clock = pck;
++ }
++
++ dispc_set_lcd_timings(&panel->timings);
++
++err0:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return r;
++}
++
++static int dpi_basic_init(struct omap_display *display)
++{
++ bool is_tft;
++
++ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
++ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
++ OMAP_DSS_LCD_DISPLAY_STN);
++ dispc_set_tft_data_lines(display->hw_config.u.dpi.data_lines);
++
++ return 0;
++}
++
++static int dpi_display_enable(struct omap_display *display)
++{
++ struct omap_panel *panel = display->panel;
++ int r;
++
++ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("display already enabled\n");
++ return -EINVAL;
++ }
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ r = dpi_basic_init(display);
++ if (r)
++ goto err0;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dss_clk_enable(DSS_CLK_FCK2);
++ r = dsi_pll_init(0, 1);
++ if (r)
++ goto err1;
++#endif
++ r = dpi_set_mode(display);
++ if (r)
++ goto err2;
++
++ mdelay(2);
++
++ dispc_enable_lcd_out(1);
++
++ r = panel->enable(display);
++ if (r)
++ goto err3;
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++
++err3:
++ dispc_enable_lcd_out(0);
++err2:
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dsi_pll_uninit();
++err1:
++ dss_clk_disable(DSS_CLK_FCK2);
++#endif
++err0:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return r;
++}
++
++static int dpi_display_resume(struct omap_display *display);
++
++static void dpi_display_disable(struct omap_display *display)
++{
++ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ return;
++
++ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ dpi_display_resume(display);
++
++ display->panel->disable(display);
++
++ dispc_enable_lcd_out(0);
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ dss_select_clk_source(0, 0);
++ dsi_pll_uninit();
++ dss_clk_disable(DSS_CLK_FCK2);
++#endif
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++}
++
++static int dpi_display_suspend(struct omap_display *display)
++{
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EINVAL;
++
++ DSSDBG("dpi_display_suspend\n");
++
++ if (display->panel->suspend)
++ display->panel->suspend(display);
++
++ dispc_enable_lcd_out(0);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ return 0;
++}
++
++static int dpi_display_resume(struct omap_display *display)
++{
++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ return -EINVAL;
++
++ DSSDBG("dpi_display_resume\n");
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dispc_enable_lcd_out(1);
++
++ if (display->panel->resume)
++ display->panel->resume(display);
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++}
++
++static void dpi_set_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("dpi_set_timings\n");
++ display->panel->timings = *timings;
++ if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ dpi_set_mode(display);
++ dispc_go(OMAP_DSS_CHANNEL_LCD);
++ }
++}
++
++static int dpi_check_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ bool is_tft;
++ int r;
++ int lck_div, pck_div;
++ unsigned long fck;
++ unsigned long pck;
++
++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
++ if (timings->hsw < 1 || timings->hsw > 64 ||
++ timings->hfp < 1 || timings->hfp > 256 ||
++ timings->hbp < 1 || timings->hbp > 256) {
++ return -EINVAL;
++ }
++
++ if (timings->vsw < 1 || timings->vsw > 64 ||
++ timings->vfp > 255 || timings->vbp > 255) {
++ return -EINVAL;
++ }
++ } else {
++ if (timings->hsw < 1 || timings->hsw > 256 ||
++ timings->hfp < 1 || timings->hfp > 4096 ||
++ timings->hbp < 1 || timings->hbp > 4096) {
++ return -EINVAL;
++ }
++
++ if (timings->vsw < 1 || timings->vsw > 64 ||
++ timings->vfp > 4095 || timings->vbp > 4095) {
++ return -EINVAL;
++ }
++ }
++
++ if (timings->pixel_clock == 0)
++ return -EINVAL;
++
++ is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++
++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
++ {
++ struct dsi_clock_info cinfo;
++ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
++ &cinfo);
++
++ if (r)
++ return r;
++
++ fck = cinfo.dsi1_pll_fclk;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++ }
++#else
++ {
++ struct dispc_clock_info cinfo;
++ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
++ &cinfo);
++
++ if (r)
++ return r;
++
++ fck = cinfo.fck;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++ }
++#endif
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ timings->pixel_clock = pck;
++
++ return 0;
++}
++
++static void dpi_get_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ *timings = display->panel->timings;
++}
++
++static int dpi_display_set_update_mode(struct omap_display *display,
++ enum omap_dss_update_mode mode)
++{
++ if (mode == OMAP_DSS_UPDATE_MANUAL)
++ return -EINVAL;
++
++ if (mode == OMAP_DSS_UPDATE_DISABLED) {
++ dispc_enable_lcd_out(0);
++ dpi.update_enabled = 0;
++ } else {
++ dispc_enable_lcd_out(1);
++ dpi.update_enabled = 1;
++ }
++
++ return 0;
++}
++
++static enum omap_dss_update_mode dpi_display_get_update_mode(
++ struct omap_display *display)
++{
++ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
++ OMAP_DSS_UPDATE_DISABLED;
++}
++
++void dpi_init_display(struct omap_display *display)
++{
++ DSSDBG("DPI init_display\n");
++
++ display->enable = dpi_display_enable;
++ display->disable = dpi_display_disable;
++ display->suspend = dpi_display_suspend;
++ display->resume = dpi_display_resume;
++ display->set_timings = dpi_set_timings;
++ display->check_timings = dpi_check_timings;
++ display->get_timings = dpi_get_timings;
++ display->set_update_mode = dpi_display_set_update_mode;
++ display->get_update_mode = dpi_display_get_update_mode;
++}
++
++int dpi_init(void)
++{
++ return 0;
++}
++
++void dpi_exit(void)
++{
++}
++
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+new file mode 100644
+index 0000000..4442931
+--- /dev/null
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -0,0 +1,3752 @@
++/*
++ * linux/drivers/video/omap2/dss/dsi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DSI"
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
++#include <linux/seq_file.h>
++#include <linux/kfifo.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include <mach/clock.h>
++
++#include "dss.h"
++
++/*#define VERBOSE_IRQ*/
++
++#define DSI_BASE 0x4804FC00
++
++struct dsi_reg { u16 idx; };
++
++#define DSI_REG(idx) ((const struct dsi_reg) { idx })
++
++#define DSI_SZ_REGS SZ_1K
++/* DSI Protocol Engine */
++
++#define DSI_REVISION DSI_REG(0x0000)
++#define DSI_SYSCONFIG DSI_REG(0x0010)
++#define DSI_SYSSTATUS DSI_REG(0x0014)
++#define DSI_IRQSTATUS DSI_REG(0x0018)
++#define DSI_IRQENABLE DSI_REG(0x001C)
++#define DSI_CTRL DSI_REG(0x0040)
++#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
++#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
++#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
++#define DSI_CLK_CTRL DSI_REG(0x0054)
++#define DSI_TIMING1 DSI_REG(0x0058)
++#define DSI_TIMING2 DSI_REG(0x005C)
++#define DSI_VM_TIMING1 DSI_REG(0x0060)
++#define DSI_VM_TIMING2 DSI_REG(0x0064)
++#define DSI_VM_TIMING3 DSI_REG(0x0068)
++#define DSI_CLK_TIMING DSI_REG(0x006C)
++#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
++#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
++#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
++#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
++#define DSI_VM_TIMING4 DSI_REG(0x0080)
++#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
++#define DSI_VM_TIMING5 DSI_REG(0x0088)
++#define DSI_VM_TIMING6 DSI_REG(0x008C)
++#define DSI_VM_TIMING7 DSI_REG(0x0090)
++#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
++#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
++#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
++#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
++#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
++#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
++#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
++#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
++
++/* DSIPHY_SCP */
++
++#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
++#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
++#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
++#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
++
++/* DSI_PLL_CTRL_SCP */
++
++#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
++#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
++#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
++#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
++#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dsi_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
++
++/* Global interrupts */
++#define DSI_IRQ_VC0 (1 << 0)
++#define DSI_IRQ_VC1 (1 << 1)
++#define DSI_IRQ_VC2 (1 << 2)
++#define DSI_IRQ_VC3 (1 << 3)
++#define DSI_IRQ_WAKEUP (1 << 4)
++#define DSI_IRQ_RESYNC (1 << 5)
++#define DSI_IRQ_PLL_LOCK (1 << 7)
++#define DSI_IRQ_PLL_UNLOCK (1 << 8)
++#define DSI_IRQ_PLL_RECALL (1 << 9)
++#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
++#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
++#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
++#define DSI_IRQ_TE_TRIGGER (1 << 16)
++#define DSI_IRQ_ACK_TRIGGER (1 << 17)
++#define DSI_IRQ_SYNC_LOST (1 << 18)
++#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
++#define DSI_IRQ_TA_TIMEOUT (1 << 20)
++#define DSI_IRQ_ERROR_MASK \
++ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
++ DSI_IRQ_TA_TIMEOUT)
++#define DSI_IRQ_CHANNEL_MASK 0xf
++
++/* Virtual channel interrupts */
++#define DSI_VC_IRQ_CS (1 << 0)
++#define DSI_VC_IRQ_ECC_CORR (1 << 1)
++#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
++#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
++#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
++#define DSI_VC_IRQ_BTA (1 << 5)
++#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
++#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
++#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
++#define DSI_VC_IRQ_ERROR_MASK \
++ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
++ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
++ DSI_VC_IRQ_FIFO_TX_UDF)
++
++/* ComplexIO interrupts */
++#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
++#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
++#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
++#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
++#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
++#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
++#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
++#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
++#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
++#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
++#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
++#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
++
++#define DSI_DT_DCS_SHORT_WRITE_0 0x05
++#define DSI_DT_DCS_SHORT_WRITE_1 0x15
++#define DSI_DT_DCS_READ 0x06
++#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
++#define DSI_DT_NULL_PACKET 0x09
++#define DSI_DT_DCS_LONG_WRITE 0x39
++
++#define DSI_DT_RX_ACK_WITH_ERR 0x02
++#define DSI_DT_RX_DCS_LONG_READ 0x1c
++#define DSI_DT_RX_SHORT_READ_1 0x21
++#define DSI_DT_RX_SHORT_READ_2 0x22
++
++#define FINT_MAX 2100000
++#define FINT_MIN 750000
++#define REGN_MAX (1 << 7)
++#define REGM_MAX ((1 << 11) - 1)
++#define REGM3_MAX (1 << 4)
++#define REGM4_MAX (1 << 4)
++
++enum fifo_size {
++ DSI_FIFO_SIZE_0 = 0,
++ DSI_FIFO_SIZE_32 = 1,
++ DSI_FIFO_SIZE_64 = 2,
++ DSI_FIFO_SIZE_96 = 3,
++ DSI_FIFO_SIZE_128 = 4,
++};
++
++#define DSI_CMD_FIFO_LEN 16
++
++struct dsi_cmd_update {
++ int bytespp;
++ u16 x;
++ u16 y;
++ u16 w;
++ u16 h;
++};
++
++struct dsi_cmd_mem_read {
++ void *buf;
++ size_t size;
++ u16 x;
++ u16 y;
++ u16 w;
++ u16 h;
++ size_t *ret_size;
++ struct completion *completion;
++};
++
++struct dsi_cmd_test {
++ int test_num;
++ int *result;
++ struct completion *completion;
++};
++
++enum dsi_cmd {
++ DSI_CMD_UPDATE,
++ DSI_CMD_AUTOUPDATE,
++ DSI_CMD_SYNC,
++ DSI_CMD_MEM_READ,
++ DSI_CMD_TEST,
++ DSI_CMD_SET_TE,
++ DSI_CMD_SET_UPDATE_MODE,
++ DSI_CMD_SET_ROTATE,
++ DSI_CMD_SET_MIRROR,
++};
++
++struct dsi_cmd_item {
++ struct omap_display *display;
++
++ enum dsi_cmd cmd;
++
++ union {
++ struct dsi_cmd_update r;
++ struct completion *sync;
++ struct dsi_cmd_mem_read mem_read;
++ struct dsi_cmd_test test;
++ int te;
++ enum omap_dss_update_mode update_mode;
++ int rotate;
++ int mirror;
++ } u;
++};
++
++static struct
++{
++ void __iomem *base;
++
++ unsigned long dsi1_pll_fclk; /* Hz */
++ unsigned long dsi2_pll_fclk; /* Hz */
++ unsigned long dsiphy; /* Hz */
++ unsigned long ddr_clk; /* Hz */
++
++ struct {
++ struct omap_display *display;
++ enum fifo_size fifo_size;
++ int dest_per; /* destination peripheral 0-3 */
++ } vc[4];
++
++ struct mutex lock;
++
++ unsigned pll_locked;
++
++ struct completion bta_completion;
++
++ struct work_struct framedone_work;
++ struct work_struct process_work;
++ struct workqueue_struct *workqueue;
++
++ enum omap_dss_update_mode user_update_mode;
++ enum omap_dss_update_mode target_update_mode;
++ enum omap_dss_update_mode update_mode;
++ int use_te;
++ int framedone_scheduled; /* helps to catch strange framedone bugs */
++
++ unsigned long cache_req_pck;
++ unsigned long cache_clk_freq;
++ struct dsi_clock_info cache_cinfo;
++
++ struct kfifo *cmd_fifo;
++ spinlock_t cmd_lock;
++ struct completion cmd_done;
++ atomic_t cmd_fifo_full;
++ atomic_t cmd_pending;
++
++ bool autoupdate_setup;
++
++#ifdef DEBUG
++ ktime_t perf_setup_time;
++ ktime_t perf_start_time;
++ int perf_measure_frames;
++
++ struct {
++ int x, y, w, h;
++ int bytespp;
++ } update_region;
++
++#endif
++ int debug_process;
++ int debug_read;
++ int debug_write;
++} dsi;
++
++#ifdef DEBUG
++static unsigned int dsi_perf;
++module_param_named(dsi_perf, dsi_perf, bool, 0644);
++#endif
++
++static void dsi_process_cmd_fifo(struct work_struct *work);
++static void dsi_push_update(struct omap_display *display,
++ int x, int y, int w, int h);
++static void dsi_push_autoupdate(struct omap_display *display);
++
++static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
++{
++ __raw_writel(val, dsi.base + idx.idx);
++}
++
++static inline u32 dsi_read_reg(const struct dsi_reg idx)
++{
++ return __raw_readl(dsi.base + idx.idx);
++}
++
++
++void dsi_save_context(void)
++{
++}
++
++void dsi_restore_context(void)
++{
++}
++
++static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
++ int value)
++{
++ int t = 100000;
++
++ while (REG_GET(idx, bitnum, bitnum) != value) {
++ if (--t == 0)
++ return !value;
++ }
++
++ return value;
++}
++
++#ifdef DEBUG
++static void perf_mark_setup(void)
++{
++ dsi.perf_setup_time = ktime_get();
++}
++
++static void perf_mark_start(void)
++{
++ dsi.perf_start_time = ktime_get();
++}
++
++static void perf_show(const char *name)
++{
++ ktime_t t, setup_time, trans_time;
++ u32 total_bytes;
++ u32 setup_us, trans_us, total_us;
++ const int numframes = 100;
++ static u32 s_trans_us, s_min_us = 0xffffffff, s_max_us;
++
++ if (!dsi_perf)
++ return;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
++ return;
++
++ t = ktime_get();
++
++ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
++ setup_us = (u32)ktime_to_us(setup_time);
++ if (setup_us == 0)
++ setup_us = 1;
++
++ trans_time = ktime_sub(t, dsi.perf_start_time);
++ trans_us = (u32)ktime_to_us(trans_time);
++ if (trans_us == 0)
++ trans_us = 1;
++
++ total_us = setup_us + trans_us;
++
++ total_bytes = dsi.update_region.w *
++ dsi.update_region.h *
++ dsi.update_region.bytespp;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
++ dsi.perf_measure_frames++;
++
++ if (trans_us < s_min_us)
++ s_min_us = trans_us;
++
++ if (trans_us > s_max_us)
++ s_max_us = trans_us;
++
++ s_trans_us += trans_us;
++
++ if (dsi.perf_measure_frames < numframes)
++ return;
++
++ DSSINFO("%s update: %d frames in %u us "
++ "(min/max/avg %u/%u/%u), %u fps\n",
++ name, numframes,
++ s_trans_us,
++ s_min_us,
++ s_max_us,
++ s_trans_us / numframes,
++ 1000*1000 / (s_trans_us / numframes));
++
++ dsi.perf_measure_frames = 0;
++ s_trans_us = 0;
++ s_min_us = 0xffffffff;
++ s_max_us = 0;
++ } else {
++ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
++ "%u kbytes/sec\n",
++ name,
++ setup_us,
++ trans_us,
++ total_us,
++ 1000*1000 / total_us,
++ total_bytes,
++ total_bytes * 1000 / total_us);
++ }
++}
++#else
++#define perf_mark_setup()
++#define perf_mark_start()
++#define perf_show(x)
++#endif
++
++static void print_irq_status(u32 status)
++{
++#ifndef VERBOSE_IRQ
++ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
++ return;
++#endif
++ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DSI_IRQ_##x) \
++ printk(#x " ");
++#ifdef VERBOSE_IRQ
++ PIS(VC0);
++ PIS(VC1);
++ PIS(VC2);
++ PIS(VC3);
++#endif
++ PIS(WAKEUP);
++ PIS(RESYNC);
++ PIS(PLL_LOCK);
++ PIS(PLL_UNLOCK);
++ PIS(PLL_RECALL);
++ PIS(COMPLEXIO_ERR);
++ PIS(HS_TX_TIMEOUT);
++ PIS(LP_RX_TIMEOUT);
++ PIS(TE_TRIGGER);
++ PIS(ACK_TRIGGER);
++ PIS(SYNC_LOST);
++ PIS(LDO_POWER_GOOD);
++ PIS(TA_TIMEOUT);
++#undef PIS
++
++ printk("\n");
++}
++
++static void print_irq_status_vc(int channel, u32 status)
++{
++#ifndef VERBOSE_IRQ
++ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
++ return;
++#endif
++ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
++
++#define PIS(x) \
++ if (status & DSI_VC_IRQ_##x) \
++ printk(#x " ");
++ PIS(CS);
++ PIS(ECC_CORR);
++#ifdef VERBOSE_IRQ
++ PIS(PACKET_SENT);
++#endif
++ PIS(FIFO_TX_OVF);
++ PIS(FIFO_RX_OVF);
++ PIS(BTA);
++ PIS(ECC_NO_CORR);
++ PIS(FIFO_TX_UDF);
++ PIS(PP_BUSY_CHANGE);
++#undef PIS
++ printk("\n");
++}
++
++static void print_irq_status_cio(u32 status)
++{
++ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
++
++#define PIS(x) \
++ if (status & DSI_CIO_IRQ_##x) \
++ printk(#x " ");
++ PIS(ERRSYNCESC1);
++ PIS(ERRSYNCESC2);
++ PIS(ERRSYNCESC3);
++ PIS(ERRESC1);
++ PIS(ERRESC2);
++ PIS(ERRESC3);
++ PIS(ERRCONTROL1);
++ PIS(ERRCONTROL2);
++ PIS(ERRCONTROL3);
++ PIS(STATEULPS1);
++ PIS(STATEULPS2);
++ PIS(STATEULPS3);
++ PIS(ERRCONTENTIONLP0_1);
++ PIS(ERRCONTENTIONLP1_1);
++ PIS(ERRCONTENTIONLP0_2);
++ PIS(ERRCONTENTIONLP1_2);
++ PIS(ERRCONTENTIONLP0_3);
++ PIS(ERRCONTENTIONLP1_3);
++ PIS(ULPSACTIVENOT_ALL0);
++ PIS(ULPSACTIVENOT_ALL1);
++#undef PIS
++
++ printk("\n");
++}
++
++static int debug_irq;
++
++/* called from dss */
++void dsi_irq_handler(void)
++{
++ u32 irqstatus, vcstatus, ciostatus;
++ int i;
++
++ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
++
++ if (irqstatus & DSI_IRQ_ERROR_MASK) {
++ DSSERR("DSI error, irqstatus %x\n", irqstatus);
++ print_irq_status(irqstatus);
++ } else if (debug_irq) {
++ print_irq_status(irqstatus);
++ }
++
++ for (i = 0; i < 4; ++i) {
++ if ((irqstatus & (1<<i)) == 0)
++ continue;
++
++ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
++
++ if (vcstatus & DSI_VC_IRQ_BTA)
++ complete(&dsi.bta_completion);
++
++ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
++ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
++ i, vcstatus);
++ print_irq_status_vc(i, vcstatus);
++ } else if (debug_irq) {
++ print_irq_status_vc(i, vcstatus);
++ }
++
++ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
++ }
++
++ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
++ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
++
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
++
++ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
++ print_irq_status_cio(ciostatus);
++ }
++
++ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
++}
++
++
++static void _dsi_initialize_irq(void)
++{
++ u32 l;
++ int i;
++
++ /* disable all interrupts */
++ dsi_write_reg(DSI_IRQENABLE, 0);
++ for (i = 0; i < 4; ++i)
++ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
++
++ /* clear interrupt status */
++ l = dsi_read_reg(DSI_IRQSTATUS);
++ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
++
++ for (i = 0; i < 4; ++i) {
++ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
++ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
++ }
++
++ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
++
++ /* enable error irqs */
++ l = DSI_IRQ_ERROR_MASK;
++ dsi_write_reg(DSI_IRQENABLE, l);
++
++ l = DSI_VC_IRQ_ERROR_MASK;
++ for (i = 0; i < 4; ++i)
++ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
++
++ /* XXX zonda responds incorrectly, causing control error:
++ Exit from LP-ESC mode to LP11 uses wrong transition states on the
++ data lines LP0 and LN0. */
++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
++ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
++}
++
++static void dsi_vc_enable_bta_irq(int channel)
++{
++ u32 l;
++
++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
++ l |= DSI_VC_IRQ_BTA;
++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
++}
++
++static void dsi_vc_disable_bta_irq(int channel)
++{
++ u32 l;
++
++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
++ l &= ~DSI_VC_IRQ_BTA;
++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
++}
++
++/* DSI func clock. this could also be DSI2_PLL_FCLK */
++static inline void enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++/* source clock for DSI PLL. this could also be PCLKFREE */
++static inline void dsi_enable_pll_clock(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_FCK2);
++ else
++ dss_clk_disable(DSS_CLK_FCK2);
++
++ if (enable && dsi.pll_locked) {
++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
++ DSSERR("cannot lock PLL when enabling clocks\n");
++ }
++}
++
++#ifdef DEBUG
++static void _dsi_print_reset_status(void)
++{
++ u32 l;
++
++ if (!dss_debug)
++ return;
++
++ /* A dummy read using the SCP interface to any DSIPHY register is
++ * required after DSIPHY reset to complete the reset of the DSI complex
++ * I/O. */
++ l = dsi_read_reg(DSI_DSIPHY_CFG5);
++
++ printk(KERN_DEBUG "DSI resets: ");
++
++ l = dsi_read_reg(DSI_PLL_STATUS);
++ printk("PLL (%d) ", FLD_GET(l, 0, 0));
++
++ l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
++ printk("CIO (%d) ", FLD_GET(l, 29, 29));
++
++ l = dsi_read_reg(DSI_DSIPHY_CFG5);
++ printk("PHY (%x, %d, %d, %d)\n",
++ FLD_GET(l, 28, 26),
++ FLD_GET(l, 29, 29),
++ FLD_GET(l, 30, 30),
++ FLD_GET(l, 31, 31));
++}
++#else
++#define _dsi_print_reset_status()
++#endif
++
++static inline int dsi_if_enable(bool enable)
++{
++ DSSDBG("dsi_if_enable(%d)\n", enable);
++
++ enable = enable ? 1 : 0;
++ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
++
++ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
++ DSSERR("Failed to set dsi_if_enable to %d\n", enable);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static unsigned long dsi_fclk_rate(void)
++{
++ unsigned long r;
++
++ if (dss_get_dsi_clk_source() == 0) {
++ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
++ r = dss_clk_get_rate(DSS_CLK_FCK1);
++ } else {
++ /* DSI FCLK source is DSI2_PLL_FCLK */
++ r = dsi.dsi2_pll_fclk;
++ }
++
++ return r;
++}
++
++static int dsi_set_lp_clk_divisor(void)
++{
++ int n;
++ unsigned long dsi_fclk;
++ unsigned long mhz;
++
++ /* LP_CLK_DIVISOR, DSI fclk/n, should be 20MHz - 32kHz */
++
++ dsi_fclk = dsi_fclk_rate();
++
++ for (n = 1; n < (1 << 13) - 1; ++n) {
++ mhz = dsi_fclk / n;
++ if (mhz <= 20*1000*1000)
++ break;
++ }
++
++ if (n == (1 << 13) - 1) {
++ DSSERR("Failed to find LP_CLK_DIVISOR\n");
++ return -EINVAL;
++ }
++
++ DSSDBG("LP_CLK_DIV %d, LP_CLK %ld\n", n, mhz);
++
++ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
++ if (dsi_fclk > 30*1000*1000)
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
++
++ return 0;
++}
++
++
++enum dsi_pll_power_state {
++ DSI_PLL_POWER_OFF = 0x0,
++ DSI_PLL_POWER_ON_HSCLK = 0x1,
++ DSI_PLL_POWER_ON_ALL = 0x2,
++ DSI_PLL_POWER_ON_DIV = 0x3,
++};
++
++static int dsi_pll_power(enum dsi_pll_power_state state)
++{
++ int t = 0;
++
++ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
++
++ /* PLL_PWR_STATUS */
++ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
++ udelay(1);
++ if (t++ > 1000) {
++ DSSERR("Failed to set DSI PLL power mode to %d\n",
++ state);
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
++ struct dsi_clock_info *cinfo)
++{
++ struct dsi_clock_info cur, best;
++ int min_fck_per_pck;
++ int match = 0;
++
++ if (req_pck == dsi.cache_req_pck &&
++ dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
++ DSSDBG("DSI clock info found from cache\n");
++ *cinfo = dsi.cache_cinfo;
++ return 0;
++ }
++
++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
++
++ if (min_fck_per_pck &&
++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
++ DSSERR("Requested pixel clock not possible with the current "
++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
++ "the constraint off.\n");
++ min_fck_per_pck = 0;
++ }
++
++ DSSDBG("dsi_pll_calc\n");
++
++retry:
++ memset(&best, 0, sizeof(best));
++
++ memset(&cur, 0, sizeof(cur));
++ cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
++ cur.use_dss2_fck = 1;
++ cur.highfreq = 0;
++
++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
++ if (cur.highfreq == 0)
++ cur.fint = cur.clkin / cur.regn;
++ else
++ cur.fint = cur.clkin / (2 * cur.regn);
++
++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
++ continue;
++
++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
++ unsigned long a, b;
++
++ a = 2 * cur.regm * (cur.clkin/1000);
++ b = cur.regn * (cur.highfreq + 1);
++ cur.dsiphy = a / b * 1000;
++
++ if (cur.dsiphy > 1800 * 1000 * 1000)
++ break;
++
++ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
++ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
++ ++cur.regm3) {
++ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
++
++ /* this will narrow down the search a bit,
++ * but still give pixclocks below what was
++ * requested */
++ if (cur.dsi1_pll_fclk < req_pck)
++ break;
++
++ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
++ continue;
++
++ if (min_fck_per_pck &&
++ cur.dsi1_pll_fclk <
++ req_pck * min_fck_per_pck)
++ continue;
++
++ match = 1;
++
++ find_lck_pck_divs(is_tft, req_pck,
++ cur.dsi1_pll_fclk,
++ &cur.lck_div,
++ &cur.pck_div);
++
++ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
++ cur.pck = cur.lck / cur.pck_div;
++
++ if (abs(cur.pck - req_pck) <
++ abs(best.pck - req_pck)) {
++ best = cur;
++
++ if (cur.pck == req_pck)
++ goto found;
++ }
++ }
++ }
++ }
++found:
++ if (!match) {
++ if (min_fck_per_pck) {
++ DSSERR("Could not find suitable clock settings.\n"
++ "Turning FCK/PCK constraint off and"
++ "trying again.\n");
++ min_fck_per_pck = 0;
++ goto retry;
++ }
++
++ DSSERR("Could not find suitable clock settings.\n");
++
++ return -EINVAL;
++ }
++
++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
++ best.regm4 = best.dsiphy / 48000000;
++ if (best.regm4 > REGM4_MAX)
++ best.regm4 = REGM4_MAX;
++ else if (best.regm4 == 0)
++ best.regm4 = 1;
++ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
++
++ if (cinfo)
++ *cinfo = best;
++
++ dsi.cache_req_pck = req_pck;
++ dsi.cache_clk_freq = 0;
++ dsi.cache_cinfo = best;
++
++ return 0;
++}
++
++static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
++ struct dsi_clock_info *cinfo)
++{
++ struct dsi_clock_info cur, best;
++ const bool use_dss2_fck = 1;
++ unsigned long datafreq;
++
++ DSSDBG("dsi_pll_calc_ddrfreq\n");
++
++ if (clk_freq == dsi.cache_clk_freq &&
++ dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
++ DSSDBG("DSI clock info found from cache\n");
++ *cinfo = dsi.cache_cinfo;
++ return 0;
++ }
++
++ datafreq = clk_freq * 4;
++
++ memset(&best, 0, sizeof(best));
++
++ memset(&cur, 0, sizeof(cur));
++ cur.use_dss2_fck = use_dss2_fck;
++ if (use_dss2_fck) {
++ cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
++ cur.highfreq = 0;
++ } else {
++ cur.clkin = dispc_pclk_rate();
++ if (cur.clkin < 32000000)
++ cur.highfreq = 0;
++ else
++ cur.highfreq = 1;
++ }
++
++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
++ if (cur.highfreq == 0)
++ cur.fint = cur.clkin / cur.regn;
++ else
++ cur.fint = cur.clkin / (2 * cur.regn);
++
++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
++ continue;
++
++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
++ unsigned long a, b;
++
++ a = 2 * cur.regm * (cur.clkin/1000);
++ b = cur.regn * (cur.highfreq + 1);
++ cur.dsiphy = a / b * 1000;
++
++ if (cur.dsiphy > 1800 * 1000 * 1000)
++ break;
++
++ if (abs(cur.dsiphy - datafreq) <
++ abs(best.dsiphy - datafreq)) {
++ best = cur;
++ /* DSSDBG("best %ld\n", best.dsiphy); */
++ }
++
++ if (cur.dsiphy == datafreq)
++ goto found;
++ }
++ }
++found:
++ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
++ best.regm3 = best.dsiphy / 48000000;
++ if (best.regm3 > REGM3_MAX)
++ best.regm3 = REGM3_MAX;
++ else if (best.regm3 == 0)
++ best.regm3 = 1;
++ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
++
++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
++ best.regm4 = best.dsiphy / 48000000;
++ if (best.regm4 > REGM4_MAX)
++ best.regm4 = REGM4_MAX;
++ else if (best.regm4 == 0)
++ best.regm4 = 1;
++ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
++
++ if (cinfo)
++ *cinfo = best;
++
++ dsi.cache_clk_freq = clk_freq;
++ dsi.cache_req_pck = 0;
++ dsi.cache_cinfo = best;
++
++ return 0;
++}
++
++int dsi_pll_program(struct dsi_clock_info *cinfo)
++{
++ int r = 0;
++ u32 l;
++
++ DSSDBG("dsi_pll_program\n");
++
++ dsi.dsiphy = cinfo->dsiphy;
++ dsi.ddr_clk = dsi.dsiphy / 4;
++ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
++ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
++
++ DSSDBG("DSI Fint %ld\n", cinfo->fint);
++
++ DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
++ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
++ cinfo->clkin,
++ cinfo->highfreq);
++
++ /* DSIPHY == CLKIN4DDR */
++ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n",
++ cinfo->regm,
++ cinfo->regn,
++ cinfo->clkin,
++ cinfo->highfreq + 1,
++ cinfo->dsiphy);
++
++ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
++ dsi.dsiphy / 1000 / 1000 / 2);
++
++ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk);
++
++ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
++ cinfo->regm3, cinfo->dsi1_pll_fclk);
++ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
++ cinfo->regm4, cinfo->dsi2_pll_fclk);
++
++ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
++ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
++ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
++ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
++ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
++ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
++ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
++ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
++ /* DSI_PLL_CLKSEL */
++ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
++ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
++ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
++ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
++
++ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
++
++ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
++ DSSERR("dsi pll go bit not going down.\n");
++ r = -EIO;
++ goto err;
++ }
++
++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
++ DSSERR("cannot lock PLL\n");
++ r = -EIO;
++ goto err;
++ }
++
++ dsi.pll_locked = 1;
++
++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
++ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
++ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
++ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
++ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
++ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
++ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
++ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
++ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
++ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
++ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
++ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
++ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
++ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
++
++ DSSDBG("PLL config done\n");
++err:
++ return r;
++}
++
++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
++{
++ int r = 0;
++ enum dsi_pll_power_state pwstate;
++ struct dispc_clock_info cinfo;
++
++ DSSDBG("PLL init\n");
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ /* configure dispc fck and pixel clock to something sane */
++ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
++ if (r)
++ goto err0;
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r) {
++ DSSERR("Failed to set basic clocks\n");
++ goto err0;
++ }
++
++ r = dss_dsi_power_up();
++ if (r)
++ goto err0;
++
++ /* PLL does not come out of reset without this... */
++ dispc_pck_free_enable(1);
++
++ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
++ DSSERR("PLL not coming out of reset.\n");
++ r = -ENODEV;
++ goto err1;
++ }
++
++ /* ... but if left on, we get problems when planes do not
++ * fill the whole display. No idea about this XXX */
++ dispc_pck_free_enable(0);
++
++ if (enable_hsclk && enable_hsdiv)
++ pwstate = DSI_PLL_POWER_ON_ALL;
++ else if (enable_hsclk)
++ pwstate = DSI_PLL_POWER_ON_HSCLK;
++ else if (enable_hsdiv)
++ pwstate = DSI_PLL_POWER_ON_DIV;
++ else
++ pwstate = DSI_PLL_POWER_OFF;
++
++ r = dsi_pll_power(pwstate);
++
++ if (r)
++ goto err1;
++
++ DSSDBG("PLL init done\n");
++
++ return 0;
++err1:
++ dss_dsi_power_down();
++err0:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++ return r;
++}
++
++void dsi_pll_uninit(void)
++{
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++
++ dsi.pll_locked = 0;
++ dsi_pll_power(DSI_PLL_POWER_OFF);
++ dss_dsi_power_down();
++ DSSDBG("PLL uninit done\n");
++}
++
++unsigned long dsi_get_dsi1_pll_rate(void)
++{
++ return dsi.dsi1_pll_fclk;
++}
++
++unsigned long dsi_get_dsi2_pll_rate(void)
++{
++ return dsi.dsi2_pll_fclk;
++}
++
++void dsi_dump_clocks(struct seq_file *s)
++{
++ int clksel;
++
++ enable_clocks(1);
++
++ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
++
++ seq_printf(s, "- dsi -\n");
++
++ seq_printf(s, "dsi fclk source = %s\n",
++ dss_get_dsi_clk_source() == 0 ?
++ "dss1_alwon_fclk" : "dsi2_pll_fclk");
++
++ seq_printf(s, "dsi pll source = %s\n",
++ clksel == 0 ?
++ "dss2_alwon_fclk" : "pclkfree");
++
++ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n",
++ dsi.dsiphy, dsi.ddr_clk);
++
++ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n"
++ "dsi2_pll_fck\t%lu (%s)\n",
++ dsi.dsi1_pll_fclk,
++ dss_get_dispc_clk_source() == 0 ? "off" : "on",
++ dsi.dsi2_pll_fclk,
++ dss_get_dsi_clk_source() == 0 ? "off" : "on");
++
++ enable_clocks(0);
++}
++
++void dsi_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DSI_REVISION);
++ DUMPREG(DSI_SYSCONFIG);
++ DUMPREG(DSI_SYSSTATUS);
++ DUMPREG(DSI_IRQSTATUS);
++ DUMPREG(DSI_IRQENABLE);
++ DUMPREG(DSI_CTRL);
++ DUMPREG(DSI_COMPLEXIO_CFG1);
++ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
++ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
++ DUMPREG(DSI_CLK_CTRL);
++ DUMPREG(DSI_TIMING1);
++ DUMPREG(DSI_TIMING2);
++ DUMPREG(DSI_VM_TIMING1);
++ DUMPREG(DSI_VM_TIMING2);
++ DUMPREG(DSI_VM_TIMING3);
++ DUMPREG(DSI_CLK_TIMING);
++ DUMPREG(DSI_TX_FIFO_VC_SIZE);
++ DUMPREG(DSI_RX_FIFO_VC_SIZE);
++ DUMPREG(DSI_COMPLEXIO_CFG2);
++ DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
++ DUMPREG(DSI_VM_TIMING4);
++ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
++ DUMPREG(DSI_VM_TIMING5);
++ DUMPREG(DSI_VM_TIMING6);
++ DUMPREG(DSI_VM_TIMING7);
++ DUMPREG(DSI_STOPCLK_TIMING);
++
++ DUMPREG(DSI_VC_CTRL(0));
++ DUMPREG(DSI_VC_TE(0));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
++ DUMPREG(DSI_VC_IRQSTATUS(0));
++ DUMPREG(DSI_VC_IRQENABLE(0));
++
++ DUMPREG(DSI_VC_CTRL(1));
++ DUMPREG(DSI_VC_TE(1));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
++ DUMPREG(DSI_VC_IRQSTATUS(1));
++ DUMPREG(DSI_VC_IRQENABLE(1));
++
++ DUMPREG(DSI_VC_CTRL(2));
++ DUMPREG(DSI_VC_TE(2));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
++ DUMPREG(DSI_VC_IRQSTATUS(2));
++ DUMPREG(DSI_VC_IRQENABLE(2));
++
++ DUMPREG(DSI_VC_CTRL(3));
++ DUMPREG(DSI_VC_TE(3));
++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
++ DUMPREG(DSI_VC_IRQSTATUS(3));
++ DUMPREG(DSI_VC_IRQENABLE(3));
++
++ DUMPREG(DSI_DSIPHY_CFG0);
++ DUMPREG(DSI_DSIPHY_CFG1);
++ DUMPREG(DSI_DSIPHY_CFG2);
++ DUMPREG(DSI_DSIPHY_CFG5);
++
++ DUMPREG(DSI_PLL_CONTROL);
++ DUMPREG(DSI_PLL_STATUS);
++ DUMPREG(DSI_PLL_GO);
++ DUMPREG(DSI_PLL_CONFIGURATION1);
++ DUMPREG(DSI_PLL_CONFIGURATION2);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++enum dsi_complexio_power_state {
++ DSI_COMPLEXIO_POWER_OFF = 0x0,
++ DSI_COMPLEXIO_POWER_ON = 0x1,
++ DSI_COMPLEXIO_POWER_ULPS = 0x2,
++};
++
++static int dsi_complexio_power(enum dsi_complexio_power_state state)
++{
++ int t = 0;
++
++ /* PWR_CMD */
++ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
++
++ /* PWR_STATUS */
++ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
++ udelay(1);
++ if (t++ > 1000) {
++ DSSERR("failed to set complexio power state to "
++ "%d\n", state);
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++static void dsi_complexio_config(struct omap_display *display)
++{
++ u32 r;
++
++ int clk_lane = display->hw_config.u.dsi.clk_lane;
++ int data1_lane = display->hw_config.u.dsi.data1_lane;
++ int data2_lane = display->hw_config.u.dsi.data2_lane;
++ int clk_pol = display->hw_config.u.dsi.clk_pol;
++ int data1_pol = display->hw_config.u.dsi.data1_pol;
++ int data2_pol = display->hw_config.u.dsi.data2_pol;
++
++ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
++ r = FLD_MOD(r, clk_lane, 2, 0);
++ r = FLD_MOD(r, clk_pol, 3, 3);
++ r = FLD_MOD(r, data1_lane, 6, 4);
++ r = FLD_MOD(r, data1_pol, 7, 7);
++ r = FLD_MOD(r, data2_lane, 10, 8);
++ r = FLD_MOD(r, data2_pol, 11, 11);
++ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
++
++ /* The configuration of the DSI complex I/O (number of data lanes,
++ position, differential order) should not be changed while
++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
++ the hardware to take into account a new configuration of the complex
++ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
++ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
++ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
++ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
++ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
++ DSI complex I/O configuration is unknown. */
++
++ /*
++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
++ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
++ */
++}
++
++static inline unsigned ns2ddr(unsigned ns)
++{
++ /* convert time in ns to ddr ticks, rounding up */
++ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
++}
++
++static inline unsigned ddr2ns(unsigned ddr)
++{
++ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
++}
++
++static void dsi_complexio_timings(void)
++{
++ u32 r;
++ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
++ u32 tlpx_half, tclk_trail, tclk_zero;
++ u32 tclk_prepare;
++
++ /* calculate timings */
++
++ /* 1 * DDR_CLK = 2 * UI */
++
++ /* min 40ns + 4*UI max 85ns + 6*UI */
++ ths_prepare = ns2ddr(59) + 2;
++
++ /* min 145ns + 10*UI */
++ ths_prepare_ths_zero = ns2ddr(145) + 5;
++
++ /* min max(8*UI, 60ns+4*UI) */
++ ths_trail = max((unsigned)4, ns2ddr(60) + 2);
++
++ /* min 100ns */
++ ths_exit = ns2ddr(100);
++
++ /* tlpx min 50n */
++ tlpx_half = ns2ddr(25);
++
++ /* min 60ns */
++ tclk_trail = ns2ddr(60);
++
++ /* min 38ns, max 95ns */
++ tclk_prepare = ns2ddr(38);
++
++ /* min tclk-prepare + tclk-zero = 300ns */
++ tclk_zero = ns2ddr(300 - 38);
++
++ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
++ ths_prepare, ddr2ns(ths_prepare),
++ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
++ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
++ ths_trail, ddr2ns(ths_trail),
++ ths_exit, ddr2ns(ths_exit));
++
++ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
++ "tclk_zero %u (%uns)\n",
++ tlpx_half, ddr2ns(tlpx_half),
++ tclk_trail, ddr2ns(tclk_trail),
++ tclk_zero, ddr2ns(tclk_zero));
++ DSSDBG("tclk_prepare %u (%uns)\n",
++ tclk_prepare, ddr2ns(tclk_prepare));
++
++ /* program timings */
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG0);
++ r = FLD_MOD(r, ths_prepare, 31, 24);
++ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
++ r = FLD_MOD(r, ths_trail, 15, 8);
++ r = FLD_MOD(r, ths_exit, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG0, r);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG1);
++ r = FLD_MOD(r, tlpx_half, 22, 16);
++ r = FLD_MOD(r, tclk_trail, 15, 8);
++ r = FLD_MOD(r, tclk_zero, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG1, r);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG2);
++ r = FLD_MOD(r, tclk_prepare, 7, 0);
++ dsi_write_reg(DSI_DSIPHY_CFG2, r);
++}
++
++
++static int dsi_complexio_init(struct omap_display *display)
++{
++ int r = 0;
++
++ DSSDBG("dsi_complexio_init\n");
++
++ /* CIO_CLK_ICG, enable L3 clk to CIO */
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
++
++ /* A dummy read using the SCP interface to any DSIPHY register is
++ * required after DSIPHY reset to complete the reset of the DSI complex
++ * I/O. */
++ dsi_read_reg(DSI_DSIPHY_CFG5);
++
++ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
++ DSSERR("ComplexIO PHY not coming out of reset.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ dsi_complexio_config(display);
++
++ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
++
++ if (r)
++ goto err;
++
++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
++ DSSERR("ComplexIO not coming out of reset.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
++ DSSERR("ComplexIO LDO power down.\n");
++ r = -ENODEV;
++ goto err;
++ }
++
++ dsi_complexio_timings();
++
++ /*
++ The configuration of the DSI complex I/O (number of data lanes,
++ position, differential order) should not be changed while
++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
++ hardware to recognize a new configuration of the complex I/O (done
++ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
++ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
++ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
++ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
++ bit to 1. If the sequence is not followed, the DSi complex I/O
++ configuration is undetermined.
++ */
++ dsi_if_enable(1);
++ dsi_if_enable(0);
++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
++ dsi_if_enable(1);
++ dsi_if_enable(0);
++
++ DSSDBG("CIO init done\n");
++err:
++ return r;
++}
++
++static void dsi_complexio_uninit(void)
++{
++ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
++}
++
++static int _dsi_wait_reset(void)
++{
++ int i = 0;
++
++ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
++ if (i++ > 5) {
++ DSSERR("soft reset failed\n");
++ return -ENODEV;
++ }
++ udelay(1);
++ }
++
++ return 0;
++}
++
++static int _dsi_reset(void)
++{
++ /* Soft reset */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
++ return _dsi_wait_reset();
++}
++
++
++static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
++ enum fifo_size size3, enum fifo_size size4)
++{
++ u32 r = 0;
++ int add = 0;
++ int i;
++
++ dsi.vc[0].fifo_size = size1;
++ dsi.vc[1].fifo_size = size2;
++ dsi.vc[2].fifo_size = size3;
++ dsi.vc[3].fifo_size = size4;
++
++ for (i = 0; i < 4; i++) {
++ u8 v;
++ int size = dsi.vc[i].fifo_size;
++
++ if (add + size > 4) {
++ DSSERR("Illegal FIFO configuration\n");
++ BUG();
++ }
++
++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
++ r |= v << (8 * i);
++ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
++ add += size;
++ }
++
++ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
++}
++
++static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
++ enum fifo_size size3, enum fifo_size size4)
++{
++ u32 r = 0;
++ int add = 0;
++ int i;
++
++ dsi.vc[0].fifo_size = size1;
++ dsi.vc[1].fifo_size = size2;
++ dsi.vc[2].fifo_size = size3;
++ dsi.vc[3].fifo_size = size4;
++
++ for (i = 0; i < 4; i++) {
++ u8 v;
++ int size = dsi.vc[i].fifo_size;
++
++ if (add + size > 4) {
++ DSSERR("Illegal FIFO configuration\n");
++ BUG();
++ }
++
++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
++ r |= v << (8 * i);
++ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
++ add += size;
++ }
++
++ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
++}
++
++static int dsi_force_tx_stop_mode_io(void)
++{
++ u32 r;
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
++ DSSERR("TX_STOP bit not going down\n");
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void dsi_vc_print_status(int channel)
++{
++ u32 r;
++
++ r = dsi_read_reg(DSI_VC_CTRL(channel));
++ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
++ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
++ channel,
++ FLD_GET(r, 5, 5),
++ FLD_GET(r, 6, 6),
++ FLD_GET(r, 15, 15),
++ FLD_GET(r, 16, 16),
++ FLD_GET(r, 20, 20));
++
++ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
++ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
++}
++
++static void dsi_vc_config(int channel)
++{
++ u32 r;
++
++ DSSDBG("dsi_vc_config %d\n", channel);
++
++ r = dsi_read_reg(DSI_VC_CTRL(channel));
++
++ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
++ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
++ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
++ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
++ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
++ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
++ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
++
++ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
++ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
++
++ dsi_write_reg(DSI_VC_CTRL(channel), r);
++}
++
++static void dsi_vc_config_vp(int channel)
++{
++ u32 r;
++
++ DSSDBG("dsi_vc_config_vp\n");
++
++ r = dsi_read_reg(DSI_VC_CTRL(channel));
++
++ r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */
++ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
++ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
++ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
++ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
++ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
++ r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */
++
++ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
++ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
++
++ dsi_write_reg(DSI_VC_CTRL(channel), r);
++}
++
++
++static int dsi_vc_enable(int channel, bool enable)
++{
++ DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable);
++
++ enable = enable ? 1 : 0;
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
++
++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void dsi_vc_enable_hs(int channel, bool enable)
++{
++ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
++
++ dsi_vc_enable(channel, 0);
++ dsi_if_enable(0);
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
++
++ dsi_vc_enable(channel, 1);
++ dsi_if_enable(1);
++
++ dsi_force_tx_stop_mode_io();
++}
++
++static void dsi_vc_flush_long_data(int channel)
++{
++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
++ u32 val;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
++ (val >> 0) & 0xff,
++ (val >> 8) & 0xff,
++ (val >> 16) & 0xff,
++ (val >> 24) & 0xff);
++ }
++}
++
++static void dsi_show_rx_ack_with_err(u16 err)
++{
++ DSSERR("\tACK with ERROR (%#x):\n", err);
++ if (err & (1 << 0))
++ DSSERR("\t\tSoT Error\n");
++ if (err & (1 << 1))
++ DSSERR("\t\tSoT Sync Error\n");
++ if (err & (1 << 2))
++ DSSERR("\t\tEoT Sync Error\n");
++ if (err & (1 << 3))
++ DSSERR("\t\tEscape Mode Entry Command Error\n");
++ if (err & (1 << 4))
++ DSSERR("\t\tLP Transmit Sync Error\n");
++ if (err & (1 << 5))
++ DSSERR("\t\tHS Receive Timeout Error\n");
++ if (err & (1 << 6))
++ DSSERR("\t\tFalse Control Error\n");
++ if (err & (1 << 7))
++ DSSERR("\t\t(reserved7)\n");
++ if (err & (1 << 8))
++ DSSERR("\t\tECC Error, single-bit (corrected)\n");
++ if (err & (1 << 9))
++ DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
++ if (err & (1 << 10))
++ DSSERR("\t\tChecksum Error\n");
++ if (err & (1 << 11))
++ DSSERR("\t\tData type not recognized\n");
++ if (err & (1 << 12))
++ DSSERR("\t\tInvalid VC ID\n");
++ if (err & (1 << 13))
++ DSSERR("\t\tInvalid Transmission Length\n");
++ if (err & (1 << 14))
++ DSSERR("\t\t(reserved14)\n");
++ if (err & (1 << 15))
++ DSSERR("\t\tDSI Protocol Violation\n");
++}
++
++static u16 dsi_vc_flush_receive_data(int channel)
++{
++ /* RX_FIFO_NOT_EMPTY */
++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
++ u32 val;
++ u8 dt;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ DSSDBG("\trawval %#08x\n", val);
++ dt = FLD_GET(val, 5, 0);
++ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
++ u16 err = FLD_GET(val, 23, 8);
++ dsi_show_rx_ack_with_err(err);
++ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
++ DSSDBG("\tDCS short response, 1 byte: %#x\n",
++ FLD_GET(val, 23, 8));
++ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
++ DSSDBG("\tDCS short response, 2 byte: %#x\n",
++ FLD_GET(val, 23, 8));
++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
++ DSSDBG("\tDCS long response, len %d\n",
++ FLD_GET(val, 23, 8));
++ dsi_vc_flush_long_data(channel);
++ } else {
++ DSSERR("\tunknown datatype 0x%02x\n", dt);
++ }
++ }
++ return 0;
++}
++
++static int dsi_vc_send_bta(int channel)
++{
++ unsigned long tmo;
++
++ /*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */
++
++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
++ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
++ dsi_vc_flush_receive_data(channel);
++ }
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
++
++ tmo = jiffies + msecs_to_jiffies(10);
++ while (REG_GET(DSI_VC_CTRL(channel), 6, 6) == 1) {
++ if (time_after(jiffies, tmo)) {
++ DSSERR("Failed to send BTA\n");
++ return -EIO;
++ }
++ }
++
++ return 0;
++}
++
++static int dsi_vc_send_bta_sync(int channel)
++{
++ int r = 0;
++
++ init_completion(&dsi.bta_completion);
++
++ dsi_vc_enable_bta_irq(channel);
++
++ r = dsi_vc_send_bta(channel);
++ if (r)
++ goto err;
++
++ if (wait_for_completion_timeout(&dsi.bta_completion,
++ msecs_to_jiffies(500)) == 0) {
++ DSSERR("Failed to receive BTA\n");
++ r = -EIO;
++ goto err;
++ }
++err:
++ dsi_vc_disable_bta_irq(channel);
++
++ return r;
++}
++
++static inline void dsi_vc_write_long_header(int channel, u8 data_type,
++ u16 len, u8 ecc)
++{
++ u32 val;
++ u8 data_id;
++
++ /*data_id = data_type | channel << 6; */
++ data_id = data_type | dsi.vc[channel].dest_per << 6;
++
++ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
++ FLD_VAL(ecc, 31, 24);
++
++ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
++}
++
++static inline void dsi_vc_write_long_payload(int channel,
++ u8 b1, u8 b2, u8 b3, u8 b4)
++{
++ u32 val;
++
++ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
++
++/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
++ b1, b2, b3, b4, val); */
++
++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
++}
++
++static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
++ u8 ecc)
++{
++ /*u32 val; */
++ int i;
++ u8 *p;
++ int r = 0;
++ u8 b1, b2, b3, b4;
++
++ if (dsi.debug_write)
++ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
++
++ /* len + header */
++ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
++ DSSERR("unable to send long packet: packet too long.\n");
++ return -EINVAL;
++ }
++
++ dsi_vc_write_long_header(channel, data_type, len, ecc);
++
++ /*dsi_vc_print_status(0); */
++
++ p = data;
++ for (i = 0; i < len >> 2; i++) {
++ if (dsi.debug_write)
++ DSSDBG("\tsending full packet %d\n", i);
++ /*dsi_vc_print_status(0); */
++
++ b1 = *p++;
++ b2 = *p++;
++ b3 = *p++;
++ b4 = *p++;
++
++ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
++ }
++
++ i = len % 4;
++ if (i) {
++ b1 = 0; b2 = 0; b3 = 0;
++
++ if (dsi.debug_write)
++ DSSDBG("\tsending remainder bytes %d\n", i);
++
++ switch (i) {
++ case 3:
++ b1 = *p++;
++ b2 = *p++;
++ b3 = *p++;
++ break;
++ case 2:
++ b1 = *p++;
++ b2 = *p++;
++ break;
++ case 1:
++ b1 = *p++;
++ break;
++ }
++
++ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
++ }
++
++ return r;
++}
++
++static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
++{
++ u32 r;
++ u8 data_id;
++
++ if (dsi.debug_write)
++ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
++ channel,
++ data_type, data & 0xff, (data >> 8) & 0xff);
++
++ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
++ DSSERR("ERROR FIFO FULL, aborting transfer\n");
++ return -EINVAL;
++ }
++
++ data_id = data_type | channel << 6;
++
++ r = (data_id << 0) | (data << 8) | (ecc << 24);
++
++ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
++
++ return 0;
++}
++
++int dsi_vc_send_null(int channel)
++{
++ u8 nullpkg[] = {0, 0, 0, 0};
++ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
++}
++EXPORT_SYMBOL(dsi_vc_send_null);
++
++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
++{
++ int r;
++
++ BUG_ON(len == 0);
++
++ if (len == 1) {
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
++ data[0], 0);
++ } else if (len == 2) {
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
++ data[0] | (data[1] << 8), 0);
++ } else {
++ /* 0x39 = DCS Long Write */
++ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
++ data, len, 0);
++ }
++
++ return r;
++}
++EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
++
++int dsi_vc_dcs_write(int channel, u8 *data, int len)
++{
++ int r;
++
++ r = dsi_vc_dcs_write_nosync(channel, data, len);
++ if (r)
++ return r;
++
++ /* Some devices need time to process the msg in low power mode.
++ This also makes the write synchronous, and checks that
++ the peripheral is still alive */
++ r = dsi_vc_send_bta_sync(channel);
++
++ return r;
++}
++EXPORT_SYMBOL(dsi_vc_dcs_write);
++
++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
++{
++ u32 val;
++ u8 dt;
++ int r;
++
++ if (dsi.debug_read)
++ DSSDBG("dsi_vc_dcs_read\n");
++
++ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
++ if (r)
++ return r;
++
++ r = dsi_vc_send_bta_sync(channel);
++ if (r)
++ return r;
++
++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { /* RX_FIFO_NOT_EMPTY */
++ DSSERR("RX fifo empty when trying to read.\n");
++ return -EIO;
++ }
++
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ if (dsi.debug_read)
++ DSSDBG("\theader: %08x\n", val);
++ dt = FLD_GET(val, 5, 0);
++ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
++ u16 err = FLD_GET(val, 23, 8);
++ dsi_show_rx_ack_with_err(err);
++ return -1;
++
++ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
++ u8 data = FLD_GET(val, 15, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
++
++ if (buflen < 1)
++ return -1;
++
++ buf[0] = data;
++
++ return 1;
++ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
++ u16 data = FLD_GET(val, 23, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
++
++ if (buflen < 2)
++ return -1;
++
++ buf[0] = data & 0xff;
++ buf[1] = (data >> 8) & 0xff;
++
++ return 2;
++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
++ int w;
++ int len = FLD_GET(val, 23, 8);
++ if (dsi.debug_read)
++ DSSDBG("\tDCS long response, len %d\n", len);
++
++ if (len > buflen)
++ return -1;
++
++ /* two byte checksum ends the packet, not included in len */
++ for (w = 0; w < len + 2;) {
++ int b;
++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
++ if (dsi.debug_read)
++ DSSDBG("\t\t%02x %02x %02x %02x\n",
++ (val >> 0) & 0xff,
++ (val >> 8) & 0xff,
++ (val >> 16) & 0xff,
++ (val >> 24) & 0xff);
++
++ for (b = 0; b < 4; ++b) {
++ if (w < len)
++ buf[w] = (val >> (b * 8)) & 0xff;
++ /* we discard the 2 byte checksum */
++ ++w;
++ }
++ }
++
++ return len;
++
++ } else {
++ DSSERR("\tunknown datatype 0x%02x\n", dt);
++ return -1;
++ }
++}
++EXPORT_SYMBOL(dsi_vc_dcs_read);
++
++
++int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
++{
++ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
++ len, 0);
++}
++EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
++
++
++static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("LP_TX_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING2);
++ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
++ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
++ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
++ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
++ dsi_write_reg(DSI_TIMING2, r);
++
++ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_ta_timeout(int ns, int x8, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("TA_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
++ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
++ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
++ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ DSSDBG("TA_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_stop_state_counter(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in DSI_FCK */
++
++ fck = dsi_fclk_rate();
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("STOP_STATE_COUNTER_IO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING1);
++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
++ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
++ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
++ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
++ dsi_write_reg(DSI_TIMING1, r);
++
++ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++
++static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
++{
++ u32 r;
++ unsigned long fck;
++ int ticks;
++
++ /* ticks in TxByteClkHS */
++
++ fck = dsi.ddr_clk / 4;
++ ticks = (fck / 1000 / 1000) * ns / 1000;
++
++ if (ticks > 0x1fff) {
++ DSSERR("HS_TX_TO too high\n");
++ return -EINVAL;
++ }
++
++ r = dsi_read_reg(DSI_TIMING2);
++ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
++ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
++ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
++ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
++ dsi_write_reg(DSI_TIMING2, r);
++
++ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n",
++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
++ (fck / 1000 / 1000),
++ ticks);
++
++ return 0;
++}
++static int dsi_proto_config(struct omap_display *display)
++{
++ u32 r;
++ int buswidth = 0;
++
++ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0);
++
++ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0,
++ DSI_FIFO_SIZE_0);
++
++ /* XXX what values for the timeouts? */
++ dsi_set_stop_state_counter(1000, 0, 0);
++
++ dsi_set_ta_timeout(50000, 1, 1);
++
++ /* 3000ns * 16 */
++ dsi_set_lp_rx_timeout(3000, 0, 1);
++
++ /* 10000ns * 4 */
++ dsi_set_hs_tx_timeout(10000, 1, 0);
++
++ switch (display->ctrl->pixel_size) {
++ case 16:
++ buswidth = 0;
++ break;
++ case 18:
++ buswidth = 1;
++ break;
++ case 24:
++ buswidth = 2;
++ break;
++ default:
++ BUG();
++ }
++
++ r = dsi_read_reg(DSI_CTRL);
++ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
++ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
++ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
++ /* XXX what should the ratio be */
++ r = FLD_MOD(r, 0, 4, 4); /* VP_CLK_RATIO, VP_PCLK = VP_CLK/2 */
++ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
++ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
++ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
++ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
++ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
++ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
++ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
++
++ dsi_write_reg(DSI_CTRL, r);
++
++ /* we configure vc0 for L4 communication, and
++ * vc1 for dispc */
++ dsi_vc_config(0);
++ dsi_vc_config_vp(1);
++
++ /* set all vc targets to peripheral 0 */
++ dsi.vc[0].dest_per = 0;
++ dsi.vc[1].dest_per = 0;
++ dsi.vc[2].dest_per = 0;
++ dsi.vc[3].dest_per = 0;
++
++ return 0;
++}
++
++static void dsi_proto_timings(void)
++{
++ int tlpx_half, tclk_zero, tclk_prepare, tclk_trail;
++ int tclk_pre, tclk_post;
++ int ddr_clk_pre, ddr_clk_post;
++ u32 r;
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG1);
++ tlpx_half = FLD_GET(r, 22, 16);
++ tclk_trail = FLD_GET(r, 15, 8);
++ tclk_zero = FLD_GET(r, 7, 0);
++
++ r = dsi_read_reg(DSI_DSIPHY_CFG2);
++ tclk_prepare = FLD_GET(r, 7, 0);
++
++ /* min 8*UI */
++ tclk_pre = 20;
++ /* min 60ns + 52*UI */
++ tclk_post = ns2ddr(60) + 26;
++
++ ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) / 4;
++ ddr_clk_post = (tclk_post + tclk_trail) / 4;
++
++ r = dsi_read_reg(DSI_CLK_TIMING);
++ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
++ r = FLD_MOD(r, ddr_clk_post, 7, 0);
++ dsi_write_reg(DSI_CLK_TIMING, r);
++
++ DSSDBG("ddr_clk_pre %d, ddr_clk_post %d\n",
++ ddr_clk_pre,
++ ddr_clk_post);
++}
++
++
++#define DSI_DECL_VARS \
++ int __dsi_cb = 0; u32 __dsi_cv = 0;
++
++#define DSI_FLUSH(ch) \
++ if (__dsi_cb > 0) { \
++ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
++ __dsi_cb = __dsi_cv = 0; \
++ }
++
++#define DSI_PUSH(ch, data) \
++ do { \
++ __dsi_cv |= (data) << (__dsi_cb * 8); \
++ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
++ if (++__dsi_cb > 3) \
++ DSI_FLUSH(ch); \
++ } while (0)
++
++static int dsi_update_screen_l4(struct omap_display *display,
++ int x, int y, int w, int h)
++{
++ /* Note: supports only 24bit colors in 32bit container */
++ int first = 1;
++ int fifo_stalls = 0;
++ int max_dsi_packet_size;
++ int max_data_per_packet;
++ int max_pixels_per_packet;
++ int pixels_left;
++ int bytespp = 3;
++ int scr_width;
++ u32 __iomem *data;
++ int start_offset;
++ int horiz_inc;
++ int current_x;
++ struct omap_overlay *ovl;
++
++ debug_irq = 0;
++
++ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
++ x, y, w, h);
++
++ ovl = display->manager->overlays[0];
++
++ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
++ return -EINVAL;
++
++ if (display->ctrl->pixel_size != 24)
++ return -EINVAL;
++
++ scr_width = ovl->info.screen_width;
++ data = ovl->info.vaddr;
++
++ start_offset = scr_width * y + x;
++ horiz_inc = scr_width - w;
++ current_x = x;
++
++ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
++ * in fifo */
++
++ /* When using CPU, max long packet size is TX buffer size */
++ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
++
++ /* we seem to get better perf if we divide the tx fifo to half,
++ and while the other half is being sent, we fill the other half
++ max_dsi_packet_size /= 2; */
++
++ max_data_per_packet = max_dsi_packet_size - 4 - 1;
++
++ max_pixels_per_packet = max_data_per_packet / bytespp;
++
++ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
++
++ display->ctrl->setup_update(display, x, y, w, h);
++
++ pixels_left = w * h;
++
++ DSSDBG("total pixels %d\n", pixels_left);
++
++ data += start_offset;
++
++#ifdef DEBUG
++ dsi.update_region.x = x;
++ dsi.update_region.y = y;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ dsi.update_region.bytespp = bytespp;
++#endif
++
++ perf_mark_start();
++
++ while (pixels_left > 0) {
++ /* 0x2c = write_memory_start */
++ /* 0x3c = write_memory_continue */
++ u8 dcs_cmd = first ? 0x2c : 0x3c;
++ int pixels;
++ DSI_DECL_VARS;
++ first = 0;
++
++#if 1
++ /* using fifo not empty */
++ /* TX_FIFO_NOT_EMPTY */
++ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
++ udelay(1);
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#elif 1
++ /* using fifo emptiness */
++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
++ max_dsi_packet_size) {
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#else
++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow, pixels left %d\n",
++ pixels_left);
++ dsi_if_enable(0);
++ return -EIO;
++ }
++ }
++#endif
++ pixels = min(max_pixels_per_packet, pixels_left);
++
++ pixels_left -= pixels;
++
++ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
++ 1 + pixels * bytespp, 0);
++
++ DSI_PUSH(0, dcs_cmd);
++
++ while (pixels-- > 0) {
++ u32 pix = __raw_readl(data++);
++
++ DSI_PUSH(0, (pix >> 16) & 0xff);
++ DSI_PUSH(0, (pix >> 8) & 0xff);
++ DSI_PUSH(0, (pix >> 0) & 0xff);
++
++ current_x++;
++ if (current_x == x+w) {
++ current_x = x;
++ data += horiz_inc;
++ }
++ }
++
++ DSI_FLUSH(0);
++ }
++
++ perf_show("L4");
++
++ return 0;
++}
++
++#if 0
++static void dsi_clear_screen_l4(struct omap_display *display,
++ int x, int y, int w, int h)
++{
++ int first = 1;
++ int fifo_stalls = 0;
++ int max_dsi_packet_size;
++ int max_data_per_packet;
++ int max_pixels_per_packet;
++ int pixels_left;
++ int bytespp = 3;
++ int pixnum;
++
++ debug_irq = 0;
++
++ DSSDBG("dsi_clear_screen_l4 (%d,%d %dx%d)\n",
++ x, y, w, h);
++
++ if (display->ctrl->bpp != 24)
++ return -EINVAL;
++
++ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp)
++ * bytes in fifo */
++
++ /* When using CPU, max long packet size is TX buffer size */
++ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
++
++ max_data_per_packet = max_dsi_packet_size - 4 - 1;
++
++ max_pixels_per_packet = max_data_per_packet / bytespp;
++
++ enable_clocks(1);
++
++ display->ctrl->setup_update(display, x, y, w, h);
++
++ pixels_left = w * h;
++
++ dsi.update_region.x = x;
++ dsi.update_region.y = y;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ dsi.update_region.bytespp = bytespp;
++
++ start_measuring();
++
++ pixnum = 0;
++
++ while (pixels_left > 0) {
++ /* 0x2c = write_memory_start */
++ /* 0x3c = write_memory_continue */
++ u8 dcs_cmd = first ? 0x2c : 0x3c;
++ int pixels;
++ DSI_DECL_VARS;
++ first = 0;
++
++ /* TX_FIFO_NOT_EMPTY */
++ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
++ fifo_stalls++;
++ if (fifo_stalls > 0xfffff) {
++ DSSERR("fifo stalls overflow\n");
++ dsi_if_enable(0);
++ enable_clocks(0);
++ return;
++ }
++ }
++
++ pixels = min(max_pixels_per_packet, pixels_left);
++
++ pixels_left -= pixels;
++
++ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
++ 1 + pixels * bytespp, 0);
++
++ DSI_PUSH(0, dcs_cmd);
++
++ while (pixels-- > 0) {
++ u32 pix;
++
++ pix = 0x000000;
++
++ DSI_PUSH(0, (pix >> 16) & 0xff);
++ DSI_PUSH(0, (pix >> 8) & 0xff);
++ DSI_PUSH(0, (pix >> 0) & 0xff);
++ }
++
++ DSI_FLUSH(0);
++ }
++
++ enable_clocks(0);
++
++ end_measuring("L4 CLEAR");
++}
++#endif
++
++static void dsi_setup_update_dispc(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ DSSDBG("dsi_setup_update_dispc(%d,%d %dx%d)\n",
++ x, y, w, h);
++
++#ifdef DEBUG
++ dsi.update_region.x = x;
++ dsi.update_region.y = y;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ dsi.update_region.bytespp = 3; // XXX
++#endif
++
++ dispc_setup_partial_planes(display, &x, &y, &w, &h);
++
++ dispc_set_lcd_size(w, h);
++}
++
++static void dsi_setup_autoupdate_dispc(struct omap_display *display)
++{
++ u16 w, h;
++
++ display->get_resolution(display, &w, &h);
++
++#ifdef DEBUG
++ dsi.update_region.x = 0;
++ dsi.update_region.y = 0;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ dsi.update_region.bytespp = 3; // XXX
++#endif
++
++ /* the overlay settings may not have been applied, if we were in manual
++ * mode earlier, so do it here */
++ display->manager->apply(display->manager);
++
++ dispc_set_lcd_size(w, h);
++
++ dsi.autoupdate_setup = 0;
++}
++
++static void dsi_update_screen_dispc(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int bytespp = 3;
++ int total_len;
++ int line_packet_len;
++ u32 l;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
++ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
++ x, y, w, h);
++
++ /* TODO: one packet could be longer, I think? Max is the line buffer */
++ line_packet_len = w * bytespp + 1; /* 1 byte for DCS cmd */
++ total_len = line_packet_len * h;
++
++ display->ctrl->setup_update(display, x, y, w, h);
++
++ if (0)
++ dsi_vc_print_status(1);
++
++ perf_mark_start();
++
++ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
++ dsi_write_reg(DSI_VC_TE(1), l);
++
++ dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, line_packet_len, 0);
++
++ if (dsi.use_te)
++ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
++ else
++ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
++ dsi_write_reg(DSI_VC_TE(1), l);
++
++ dispc_enable_lcd_out(1);
++
++ if (dsi.use_te)
++ dsi_vc_send_bta(1);
++}
++
++static void framedone_callback(void *data, u32 mask)
++{
++ if (dsi.framedone_scheduled) {
++ DSSERR("Framedone already scheduled. Bogus FRAMEDONE IRQ?\n");
++ return;
++ }
++
++ dsi.framedone_scheduled = 1;
++
++ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
++ * itself off. However, DSI still has the pixels in its buffers, and
++ * is sending the data. Thus we have to wait until we can do a new
++ * transfer or turn the clocks off. We do that in a separate work
++ * func. */
++ queue_work(dsi.workqueue, &dsi.framedone_work);
++}
++
++static void framedone_worker(struct work_struct *work)
++{
++ u32 l;
++ unsigned long tmo;
++ int i = 0;
++
++ l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
++
++ /* There shouldn't be much stuff in DSI buffers, if any, so we'll
++ * just busyloop */
++ if (l > 0) {
++ tmo = jiffies + msecs_to_jiffies(50);
++ while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */
++ i++;
++ if (time_after(jiffies, tmo)) {
++ DSSERR("timeout waiting TE_SIZE to zero\n");
++ break;
++ }
++ cpu_relax();
++ }
++ }
++
++ if (REG_GET(DSI_VC_TE(1), 30, 30))
++ DSSERR("TE_EN not zero\n");
++
++ if (REG_GET(DSI_VC_TE(1), 31, 31))
++ DSSERR("TE_START not zero\n");
++
++ perf_show("DISPC");
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
++ DSSDBG("FRAMEDONE\n");
++
++#if 0
++ if (l)
++ DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
++#else
++ if (l > 1024*3)
++ DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
++#endif
++
++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
++ dispc_fake_vsync_irq();
++#endif
++ dsi.framedone_scheduled = 0;
++
++ /* XXX check that fifo is not full. otherwise we would sleep and never
++ * get to process_cmd_fifo below */
++ /* We check for target_update_mode, not update_mode. No reason to push
++ * new updates if we're turning auto update off */
++ if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_push_autoupdate(dsi.vc[1].display);
++
++ atomic_set(&dsi.cmd_pending, 0);
++ dsi_process_cmd_fifo(NULL);
++}
++
++static void dsi_start_auto_update(struct omap_display *display)
++{
++ DSSDBG("starting auto update\n");
++
++ dsi.autoupdate_setup = 1;
++
++ dsi_push_autoupdate(display);
++}
++
++
++
++
++
++
++
++
++
++
++
++
++
++/* FIFO functions */
++
++static void dsi_signal_fifo_waiters(void)
++{
++ if (atomic_read(&dsi.cmd_fifo_full) > 0) {
++ DSSDBG("SIGNALING: Fifo not full for waiter!\n");
++ complete(&dsi.cmd_done);
++ atomic_dec(&dsi.cmd_fifo_full);
++ }
++}
++
++/* returns 1 for async op, and 0 for sync op */
++static int dsi_do_update(struct omap_display *display,
++ struct dsi_cmd_update *upd)
++{
++ int r;
++ u16 x = upd->x, y = upd->y, w = upd->w, h = upd->h;
++ u16 dw, dh;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
++ return 0;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return 0;
++
++ display->get_resolution(display, &dw, &dh);
++ if (x > dw || y > dh)
++ return 0;
++
++ if (x + w > dw)
++ w = dw - x;
++
++ if (y + h > dh)
++ h = dh - y;
++
++ DSSDBGF("%d,%d %dx%d", x, y, w, h);
++
++ perf_mark_setup();
++
++ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ dsi_setup_update_dispc(display, x, y, w, h);
++ dsi_update_screen_dispc(display, x, y, w, h);
++ return 1;
++ } else {
++ r = dsi_update_screen_l4(display, x, y, w, h);
++ if (r)
++ DSSERR("L4 update failed\n");
++ return 0;
++ }
++}
++
++/* returns 1 for async op, and 0 for sync op */
++static int dsi_do_autoupdate(struct omap_display *display)
++{
++ int r;
++ u16 w, h;
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
++ return 0;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return 0;
++
++ display->get_resolution(display, &w, &h);
++
++ perf_mark_setup();
++
++ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ if (dsi.autoupdate_setup)
++ dsi_setup_autoupdate_dispc(display);
++ dsi_update_screen_dispc(display, 0, 0, w, h);
++ return 1;
++ } else {
++ r = dsi_update_screen_l4(display, 0, 0, w, h);
++ if (r)
++ DSSERR("L4 update failed\n");
++ return 0;
++ }
++}
++
++static void dsi_do_cmd_mem_read(struct omap_display *display,
++ struct dsi_cmd_mem_read *mem_read)
++{
++ int r;
++ r = display->ctrl->memory_read(display,
++ mem_read->buf,
++ mem_read->size,
++ mem_read->x,
++ mem_read->y,
++ mem_read->w,
++ mem_read->h);
++
++ *mem_read->ret_size = (size_t)r;
++ complete(mem_read->completion);
++}
++
++static void dsi_do_cmd_test(struct omap_display *display,
++ struct dsi_cmd_test *test)
++{
++ int r = 0;
++
++ DSSDBGF("");
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return;
++
++ /* run test first in low speed mode */
++ dsi_vc_enable_hs(0, 0);
++
++ if (display->ctrl->run_test) {
++ r = display->ctrl->run_test(display, test->test_num);
++ if (r)
++ goto end;
++ }
++
++ if (display->panel->run_test) {
++ r = display->panel->run_test(display, test->test_num);
++ if (r)
++ goto end;
++ }
++
++ /* then in high speed */
++ dsi_vc_enable_hs(0, 1);
++
++ if (display->ctrl->run_test) {
++ r = display->ctrl->run_test(display, test->test_num);
++ if (r)
++ goto end;
++ }
++
++ if (display->panel->run_test)
++ r = display->panel->run_test(display, test->test_num);
++
++end:
++ dsi_vc_enable_hs(0, 1);
++
++ *test->result = r;
++ complete(test->completion);
++
++ DSSDBG("test end\n");
++}
++
++static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
++{
++ dsi.use_te = enable;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return;
++
++ display->ctrl->enable_te(display, enable);
++
++ if (enable) {
++ /* disable LP_RX_TO, so that we can receive TE.
++ * Time to wait for TE is longer than the timer allows */
++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
++ } else {
++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++ }
++}
++
++static void dsi_do_cmd_set_update_mode(struct omap_display *display,
++ enum omap_dss_update_mode mode)
++{
++ dsi.update_mode = mode;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return;
++
++ if (mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(display);
++}
++
++static void dsi_process_cmd_fifo(struct work_struct *work)
++{
++ int len;
++ struct dsi_cmd_item p;
++ unsigned long flags;
++ struct omap_display *display;
++ int exit = 0;
++
++ if (dsi.debug_process)
++ DSSDBGF("");
++
++ if (atomic_cmpxchg(&dsi.cmd_pending, 0, 1) == 1) {
++ if (dsi.debug_process)
++ DSSDBG("cmd pending, skip process\n");
++ return;
++ }
++
++ while (!exit) {
++ spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
++
++ len = __kfifo_get(dsi.cmd_fifo, (unsigned char *)&p,
++ sizeof(p));
++ if (len == 0) {
++ if (dsi.debug_process)
++ DSSDBG("nothing more in fifo, atomic clear\n");
++ atomic_set(&dsi.cmd_pending, 0);
++ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
++ break;
++ }
++
++ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
++
++ BUG_ON(len != sizeof(p));
++
++ display = p.display;
++
++ if (dsi.debug_process)
++ DSSDBG("processing cmd %d\n", p.cmd);
++
++ switch (p.cmd) {
++ case DSI_CMD_UPDATE:
++ if (dsi_do_update(display, &p.u.r)) {
++ if (dsi.debug_process)
++ DSSDBG("async update\n");
++ exit = 1;
++ } else {
++ if (dsi.debug_process)
++ DSSDBG("sync update\n");
++ }
++ break;
++
++ case DSI_CMD_AUTOUPDATE:
++ if (dsi_do_autoupdate(display)) {
++ if (dsi.debug_process)
++ DSSDBG("async autoupdate\n");
++ exit = 1;
++ } else {
++ if (dsi.debug_process)
++ DSSDBG("sync autoupdate\n");
++ }
++ break;
++
++ case DSI_CMD_SYNC:
++ if (dsi.debug_process)
++ DSSDBG("Signaling SYNC done!\n");
++ complete(p.u.sync);
++ break;
++
++ case DSI_CMD_MEM_READ:
++ dsi_do_cmd_mem_read(display, &p.u.mem_read);
++ break;
++
++ case DSI_CMD_TEST:
++ dsi_do_cmd_test(display, &p.u.test);
++ break;
++
++ case DSI_CMD_SET_TE:
++ dsi_do_cmd_set_te(display, p.u.te);
++ break;
++
++ case DSI_CMD_SET_UPDATE_MODE:
++ dsi_do_cmd_set_update_mode(display, p.u.update_mode);
++ break;
++
++ case DSI_CMD_SET_ROTATE:
++ display->ctrl->set_rotate(display, p.u.rotate);
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi.autoupdate_setup = 1;
++ break;
++
++ case DSI_CMD_SET_MIRROR:
++ display->ctrl->set_mirror(display, p.u.mirror);
++ break;
++
++ default:
++ BUG();
++ }
++ }
++
++ if (dsi.debug_process)
++ DSSDBG("exit dsi_process_cmd_fifo\n");
++
++ dsi_signal_fifo_waiters();
++}
++
++static void dsi_push_cmd(struct dsi_cmd_item *p)
++{
++ int ret;
++
++ if (dsi.debug_process)
++ DSSDBGF("");
++
++ while (1) {
++ unsigned long flags;
++ unsigned avail, used;
++
++ spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
++ used = __kfifo_len(dsi.cmd_fifo) / sizeof(struct dsi_cmd_item);
++ avail = DSI_CMD_FIFO_LEN - used;
++
++ if (dsi.debug_process)
++ DSSDBG("%u/%u items left in fifo\n", avail, used);
++
++ if (avail == 0) {
++ if (dsi.debug_process)
++ DSSDBG("cmd fifo full, waiting...\n");
++ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
++ atomic_inc(&dsi.cmd_fifo_full);
++ wait_for_completion(&dsi.cmd_done);
++ if (dsi.debug_process)
++ DSSDBG("cmd fifo not full, woke up\n");
++ continue;
++ }
++
++ ret = __kfifo_put(dsi.cmd_fifo, (unsigned char *)p,
++ sizeof(*p));
++
++ spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
++
++ BUG_ON(ret != sizeof(*p));
++
++ break;
++ }
++
++ queue_work(dsi.workqueue, &dsi.process_work);
++}
++
++static void dsi_push_update(struct omap_display *display,
++ int x, int y, int w, int h)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_UPDATE;
++
++ p.u.r.x = x;
++ p.u.r.y = y;
++ p.u.r.w = w;
++ p.u.r.h = h;
++
++ DSSDBG("pushing UPDATE %d,%d %dx%d\n", x, y, w, h);
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_autoupdate(struct omap_display *display)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_AUTOUPDATE;
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_sync(struct omap_display *display,
++ struct completion *sync_comp)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_SYNC;
++ p.u.sync = sync_comp;
++
++ DSSDBG("pushing SYNC\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_mem_read(struct omap_display *display,
++ struct dsi_cmd_mem_read *mem_read)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_MEM_READ;
++ p.u.mem_read = *mem_read;
++
++ DSSDBG("pushing MEM_READ\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_test(struct omap_display *display, int test_num,
++ int *result, struct completion *completion)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_TEST;
++ p.u.test.test_num = test_num;
++ p.u.test.result = result;
++ p.u.test.completion = completion;
++
++ DSSDBG("pushing TEST\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_set_te(struct omap_display *display, bool enable)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_SET_TE;
++ p.u.te = enable;
++
++ DSSDBG("pushing SET_TE\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_set_update_mode(struct omap_display *display,
++ enum omap_dss_update_mode mode)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_SET_UPDATE_MODE;
++ p.u.update_mode = mode;
++
++ DSSDBG("pushing SET_UPDATE_MODE\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_set_rotate(struct omap_display *display, int rotate)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_SET_ROTATE;
++ p.u.rotate = rotate;
++
++ DSSDBG("pushing SET_ROTATE\n");
++
++ dsi_push_cmd(&p);
++}
++
++static void dsi_push_set_mirror(struct omap_display *display, int mirror)
++{
++ struct dsi_cmd_item p;
++
++ p.display = display;
++ p.cmd = DSI_CMD_SET_MIRROR;
++ p.u.mirror = mirror;
++
++ DSSDBG("pushing SET_MIRROR\n");
++
++ dsi_push_cmd(&p);
++}
++
++static int dsi_wait_sync(struct omap_display *display)
++{
++ long wait = msecs_to_jiffies(60000);
++ struct completion compl;
++
++ DSSDBGF("");
++
++ init_completion(&compl);
++ dsi_push_sync(display, &compl);
++
++ DSSDBG("Waiting for SYNC to happen...\n");
++ wait = wait_for_completion_timeout(&compl, wait);
++ DSSDBG("Released from SYNC\n");
++
++ if (wait == 0) {
++ DSSERR("timeout waiting sync\n");
++ return -ETIME;
++ }
++
++ return 0;
++}
++
++
++
++
++
++
++
++
++
++
++
++
++/* Display funcs */
++
++static int dsi_display_init_dispc(struct omap_display *display)
++{
++ int r;
++
++ r = omap_dispc_register_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++ if (r) {
++ DSSERR("can't get FRAMEDONE irq\n");
++ return r;
++ }
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
++ dispc_enable_fifohandcheck(1);
++
++ dispc_set_tft_data_lines(display->ctrl->pixel_size);
++
++ {
++ struct omap_video_timings timings = {
++ .hsw = 1,
++ .hfp = 1,
++ .hbp = 1,
++ .vsw = 1,
++ .vfp = 0,
++ .vbp = 0,
++ };
++
++ dispc_set_lcd_timings(&timings);
++ }
++
++ return 0;
++}
++
++static void dsi_display_uninit_dispc(struct omap_display *display)
++{
++ omap_dispc_unregister_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++}
++
++static int dsi_display_init_dsi(struct omap_display *display)
++{
++ struct dsi_clock_info cinfo;
++ int r;
++
++ _dsi_print_reset_status();
++
++ r = dsi_pll_init(1, 0);
++ if (r)
++ goto err0;
++
++ r = dsi_pll_calc_ddrfreq(display->hw_config.u.dsi.ddr_clk_hz, &cinfo);
++ if (r)
++ goto err1;
++
++ r = dsi_pll_program(&cinfo);
++ if (r)
++ goto err1;
++
++ DSSDBG("PLL OK\n");
++
++ r = dsi_complexio_init(display);
++ if (r)
++ goto err1;
++
++ _dsi_print_reset_status();
++
++ dsi_proto_timings();
++ dsi_set_lp_clk_divisor();
++
++ if (1)
++ _dsi_print_reset_status();
++
++ r = dsi_proto_config(display);
++ if (r)
++ goto err2;
++
++ /* enable interface */
++ dsi_vc_enable(0, 1);
++ dsi_vc_enable(1, 1);
++ dsi_if_enable(1);
++ dsi_force_tx_stop_mode_io();
++
++ if (display->ctrl && display->ctrl->enable) {
++ r = display->ctrl->enable(display);
++ if (r)
++ goto err3;
++ }
++
++ if (display->panel && display->panel->enable) {
++ r = display->panel->enable(display);
++ if (r)
++ goto err4;
++ }
++
++ /* enable high-speed after initial config */
++ dsi_vc_enable_hs(0, 1);
++
++ return 0;
++err4:
++ if (display->ctrl && display->ctrl->disable)
++ display->ctrl->disable(display);
++err3:
++ dsi_if_enable(0);
++err2:
++ dsi_complexio_uninit();
++err1:
++ dsi_pll_uninit();
++err0:
++ return r;
++}
++
++static void dsi_display_uninit_dsi(struct omap_display *display)
++{
++ if (display->panel && display->panel->disable)
++ display->panel->disable(display);
++ if (display->ctrl && display->ctrl->disable)
++ display->ctrl->disable(display);
++
++ dsi_complexio_uninit();
++ dsi_pll_uninit();
++}
++
++static int dsi_core_init(void)
++{
++ /* Autoidle */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
++
++ /* ENWAKEUP */
++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
++
++ /* SIDLEMODE smart-idle */
++ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
++
++ _dsi_initialize_irq();
++
++ return 0;
++}
++
++static int dsi_display_enable(struct omap_display *display)
++{
++ int r = 0;
++
++ DSSDBG("dsi_display_enable\n");
++
++ mutex_lock(&dsi.lock);
++
++ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("display already enabled\n");
++ r = -EINVAL;
++ goto err0;
++ }
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ r = _dsi_reset();
++ if (r)
++ return r;
++
++ dsi_core_init();
++
++ r = dsi_display_init_dispc(display);
++ if (r)
++ goto err1;
++
++ r = dsi_display_init_dsi(display);
++ if (r)
++ goto err2;
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ if (dsi.use_te)
++ dsi_push_set_te(display, 1);
++
++ dsi_push_set_update_mode(display, dsi.user_update_mode);
++ dsi.target_update_mode = dsi.user_update_mode;
++
++ mutex_unlock(&dsi.lock);
++
++ return dsi_wait_sync(display);
++
++err2:
++ dsi_display_uninit_dispc(display);
++err1:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++err0:
++ mutex_unlock(&dsi.lock);
++ DSSDBG("dsi_display_enable FAILED\n");
++ return r;
++}
++
++static void dsi_display_disable(struct omap_display *display)
++{
++ DSSDBG("dsi_display_disable\n");
++
++ mutex_lock(&dsi.lock);
++
++ if (display->state == OMAP_DSS_DISPLAY_DISABLED ||
++ display->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ goto end;
++
++ if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
++ dsi_push_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
++ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
++ }
++
++ dsi_wait_sync(display);
++
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ dsi_display_uninit_dispc(display);
++
++ dsi_display_uninit_dsi(display);
++
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++end:
++ mutex_unlock(&dsi.lock);
++}
++
++static int dsi_display_suspend(struct omap_display *display)
++{
++ DSSDBG("dsi_display_suspend\n");
++
++ dsi_display_disable(display);
++
++ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ return 0;
++}
++
++static int dsi_display_resume(struct omap_display *display)
++{
++ DSSDBG("dsi_display_resume\n");
++
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++ return dsi_display_enable(display);
++}
++
++static int dsi_display_update(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
++
++ if (w == 0 || h == 0)
++ return 0;
++
++ mutex_lock(&dsi.lock);
++
++ if (dsi.target_update_mode == OMAP_DSS_UPDATE_MANUAL)
++ dsi_push_update(display, x, y, w, h);
++ /* XXX else return error? */
++
++ mutex_unlock(&dsi.lock);
++
++ return 0;
++}
++
++static int dsi_display_sync(struct omap_display *display)
++{
++ DSSDBGF("");
++ return dsi_wait_sync(display);
++}
++
++static int dsi_display_set_update_mode(struct omap_display *display,
++ enum omap_dss_update_mode mode)
++{
++ DSSDBGF("%d", mode);
++
++ mutex_lock(&dsi.lock);
++
++ if (dsi.target_update_mode != mode) {
++ dsi_push_set_update_mode(display, mode);
++
++ dsi.target_update_mode = mode;
++ dsi.user_update_mode = mode;
++ }
++
++ mutex_unlock(&dsi.lock);
++
++ return dsi_wait_sync(display);
++}
++
++static enum omap_dss_update_mode dsi_display_get_update_mode(
++ struct omap_display *display)
++{
++ return dsi.update_mode;
++}
++
++static int dsi_display_enable_te(struct omap_display *display, bool enable)
++{
++ DSSDBGF("%d", enable);
++
++ if (!display->ctrl->enable_te)
++ return -ENOENT;
++
++ dsi_push_set_te(display, enable);
++
++ return dsi_wait_sync(display);
++}
++
++static int dsi_display_get_te(struct omap_display *display)
++{
++ return dsi.use_te;
++}
++
++
++
++static int dsi_display_set_rotate(struct omap_display *display, u8 rotate)
++{
++ DSSDBGF("%d", rotate);
++
++ if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
++ return -EINVAL;
++
++ dsi_push_set_rotate(display, rotate);
++
++ return dsi_wait_sync(display);
++}
++
++static u8 dsi_display_get_rotate(struct omap_display *display)
++{
++ if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
++ return 0;
++
++ return display->ctrl->get_rotate(display);
++}
++
++static int dsi_display_set_mirror(struct omap_display *display, bool mirror)
++{
++ DSSDBGF("%d", mirror);
++
++ if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
++ return -EINVAL;
++
++ dsi_push_set_mirror(display, mirror);
++
++ return dsi_wait_sync(display);
++}
++
++static bool dsi_display_get_mirror(struct omap_display *display)
++{
++ if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
++ return 0;
++
++ return display->ctrl->get_mirror(display);
++}
++
++static int dsi_display_run_test(struct omap_display *display, int test_num)
++{
++ long wait = msecs_to_jiffies(60000);
++ struct completion compl;
++ int result;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EIO;
++
++ DSSDBGF("%d", test_num);
++
++ init_completion(&compl);
++
++ dsi_push_test(display, test_num, &result, &compl);
++
++ DSSDBG("Waiting for SYNC to happen...\n");
++ wait = wait_for_completion_timeout(&compl, wait);
++ DSSDBG("Released from SYNC\n");
++
++ if (wait == 0) {
++ DSSERR("timeout waiting test sync\n");
++ return -ETIME;
++ }
++
++ return result;
++}
++
++static int dsi_display_memory_read(struct omap_display *display,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ long wait = msecs_to_jiffies(60000);
++ struct completion compl;
++ struct dsi_cmd_mem_read mem_read;
++ size_t ret_size;
++
++ DSSDBGF("");
++
++ if (!display->ctrl->memory_read)
++ return -EINVAL;
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EIO;
++
++ init_completion(&compl);
++
++ mem_read.x = x;
++ mem_read.y = y;
++ mem_read.w = w;
++ mem_read.h = h;
++ mem_read.buf = buf;
++ mem_read.size = size;
++ mem_read.ret_size = &ret_size;
++ mem_read.completion = &compl;
++
++ dsi_push_mem_read(display, &mem_read);
++
++ DSSDBG("Waiting for SYNC to happen...\n");
++ wait = wait_for_completion_timeout(&compl, wait);
++ DSSDBG("Released from SYNC\n");
++
++ if (wait == 0) {
++ DSSERR("timeout waiting mem read sync\n");
++ return -ETIME;
++ }
++
++ return ret_size;
++}
++
++static void dsi_configure_overlay(struct omap_overlay *ovl)
++{
++ unsigned low, high, size;
++ enum omap_burst_size burst;
++ enum omap_plane plane = ovl->id;
++
++ burst = OMAP_DSS_BURST_16x32;
++ size = 16 * 32 / 8;
++
++ dispc_set_burst_size(plane, burst);
++
++ high = dispc_get_plane_fifo_size(plane) - size;
++ low = 0;
++ dispc_setup_plane_fifo(plane, low, high);
++}
++
++void dsi_init_display(struct omap_display *display)
++{
++ DSSDBG("DSI init\n");
++
++ display->enable = dsi_display_enable;
++ display->disable = dsi_display_disable;
++ display->suspend = dsi_display_suspend;
++ display->resume = dsi_display_resume;
++ display->update = dsi_display_update;
++ display->sync = dsi_display_sync;
++ display->set_update_mode = dsi_display_set_update_mode;
++ display->get_update_mode = dsi_display_get_update_mode;
++ display->enable_te = dsi_display_enable_te;
++ display->get_te = dsi_display_get_te;
++
++ display->get_rotate = dsi_display_get_rotate;
++ display->set_rotate = dsi_display_set_rotate;
++
++ display->get_mirror = dsi_display_get_mirror;
++ display->set_mirror = dsi_display_set_mirror;
++
++ display->run_test = dsi_display_run_test;
++ display->memory_read = dsi_display_memory_read;
++
++ display->configure_overlay = dsi_configure_overlay;
++
++ display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ dsi.vc[0].display = display;
++ dsi.vc[1].display = display;
++}
++
++int dsi_init(void)
++{
++ u32 rev;
++
++ spin_lock_init(&dsi.cmd_lock);
++ dsi.cmd_fifo = kfifo_alloc(
++ DSI_CMD_FIFO_LEN * sizeof(struct dsi_cmd_item),
++ GFP_KERNEL,
++ &dsi.cmd_lock);
++
++ init_completion(&dsi.cmd_done);
++ atomic_set(&dsi.cmd_fifo_full, 0);
++ atomic_set(&dsi.cmd_pending, 0);
++
++ init_completion(&dsi.bta_completion);
++
++ dsi.workqueue = create_singlethread_workqueue("dsi");
++ INIT_WORK(&dsi.framedone_work, framedone_worker);
++ INIT_WORK(&dsi.process_work, dsi_process_cmd_fifo);
++
++ mutex_init(&dsi.lock);
++
++ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
++ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
++
++ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
++ if (!dsi.base) {
++ DSSERR("can't ioremap DSI\n");
++ return -ENOMEM;
++ }
++
++ enable_clocks(1);
++
++ rev = dsi_read_reg(DSI_REVISION);
++ printk(KERN_INFO "OMAP DSI rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ enable_clocks(0);
++
++ return 0;
++}
++
++void dsi_exit(void)
++{
++ flush_workqueue(dsi.workqueue);
++ destroy_workqueue(dsi.workqueue);
++
++ iounmap(dsi.base);
++
++ kfifo_free(dsi.cmd_fifo);
++
++ DSSDBG("omap_dsi_exit\n");
++}
++
+diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
+new file mode 100644
+index 0000000..adc1f34
+--- /dev/null
++++ b/drivers/video/omap2/dss/dss.c
+@@ -0,0 +1,345 @@
++/*
++ * linux/drivers/video/omap2/dss/dss.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "DSS"
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/seq_file.h>
++
++#include <mach/display.h>
++#include "dss.h"
++
++#define DSS_BASE 0x48050000
++
++#define DSS_SZ_REGS SZ_512
++
++struct dss_reg {
++ u16 idx;
++};
++
++#define DSS_REG(idx) ((const struct dss_reg) { idx })
++
++#define DSS_REVISION DSS_REG(0x0000)
++#define DSS_SYSCONFIG DSS_REG(0x0010)
++#define DSS_SYSSTATUS DSS_REG(0x0014)
++#define DSS_IRQSTATUS DSS_REG(0x0018)
++#define DSS_CONTROL DSS_REG(0x0040)
++#define DSS_SDI_CONTROL DSS_REG(0x0044)
++#define DSS_PLL_CONTROL DSS_REG(0x0048)
++#define DSS_SDI_STATUS DSS_REG(0x005C)
++
++#define REG_GET(idx, start, end) \
++ FLD_GET(dss_read_reg(idx), start, end)
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
++
++static struct {
++ void __iomem *base;
++
++ u32 ctx[DSS_SZ_REGS / sizeof(u32)];
++} dss;
++
++static int _omap_dss_wait_reset(void);
++
++static inline void dss_write_reg(const struct dss_reg idx, u32 val)
++{
++ __raw_writel(val, dss.base + idx.idx);
++}
++
++static inline u32 dss_read_reg(const struct dss_reg idx)
++{
++ return __raw_readl(dss.base + idx.idx);
++}
++
++#define SR(reg) \
++ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
++#define RR(reg) \
++ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
++
++void dss_save_context(void)
++{
++ if (cpu_is_omap24xx())
++ return;
++
++ SR(SYSCONFIG);
++ SR(CONTROL);
++
++#ifdef CONFIG_OMAP2_DSS_SDI
++ SR(SDI_CONTROL);
++ SR(PLL_CONTROL);
++#endif
++}
++
++void dss_restore_context(void)
++{
++ if (_omap_dss_wait_reset())
++ DSSERR("DSS not coming out of reset after sleep\n");
++
++ RR(SYSCONFIG);
++ RR(CONTROL);
++
++#ifdef CONFIG_OMAP2_DSS_SDI
++ RR(SDI_CONTROL);
++ RR(PLL_CONTROL);
++#endif
++}
++
++#undef SR
++#undef RR
++
++void dss_sdi_init(u8 datapairs)
++{
++ u32 l;
++
++ BUG_ON(datapairs > 3 || datapairs < 1);
++
++ l = dss_read_reg(DSS_SDI_CONTROL);
++ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
++ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
++ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
++ dss_write_reg(DSS_SDI_CONTROL, l);
++
++ l = dss_read_reg(DSS_PLL_CONTROL);
++ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
++ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
++ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
++ dss_write_reg(DSS_PLL_CONTROL, l);
++}
++
++void dss_sdi_enable(void)
++{
++ dispc_pck_free_enable(1);
++
++ /* Reset SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
++ udelay(1); /* wait 2x PCLK */
++
++ /* Lock SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
++
++ /* Waiting for PLL lock request to complete */
++ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6))
++ ;
++
++ /* Clearing PLL_GO bit */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
++
++ /* Waiting for PLL to lock */
++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5)))
++ ;
++
++ dispc_lcd_enable_signal(1);
++
++ /* Waiting for SDI reset to complete */
++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2)))
++ ;
++}
++
++void dss_sdi_disable(void)
++{
++ dispc_lcd_enable_signal(0);
++
++ dispc_pck_free_enable(0);
++
++ /* Reset SDI PLL */
++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
++}
++
++void dss_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(DSS_REVISION);
++ DUMPREG(DSS_SYSCONFIG);
++ DUMPREG(DSS_SYSSTATUS);
++ DUMPREG(DSS_IRQSTATUS);
++ DUMPREG(DSS_CONTROL);
++ DUMPREG(DSS_SDI_CONTROL);
++ DUMPREG(DSS_PLL_CONTROL);
++ DUMPREG(DSS_SDI_STATUS);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++void dss_select_clk_source(bool dsi, bool dispc)
++{
++ u32 r;
++ r = dss_read_reg(DSS_CONTROL);
++ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
++ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
++ dss_write_reg(DSS_CONTROL, r);
++}
++
++int dss_get_dsi_clk_source(void)
++{
++ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
++}
++
++int dss_get_dispc_clk_source(void)
++{
++ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
++}
++
++static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
++{
++ dispc_irq_handler();
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
++{
++ u32 irqstatus;
++
++ irqstatus = dss_read_reg(DSS_IRQSTATUS);
++
++ if (irqstatus & (1<<0)) /* DISPC_IRQ */
++ dispc_irq_handler();
++#ifdef CONFIG_OMAP2_DSS_DSI
++ if (irqstatus & (1<<1)) /* DSI_IRQ */
++ dsi_irq_handler();
++#endif
++
++ return IRQ_HANDLED;
++}
++
++static int _omap_dss_wait_reset(void)
++{
++ unsigned timeout = 1000;
++
++ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
++ udelay(1);
++ if (!--timeout) {
++ DSSERR("soft reset failed\n");
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
++static int _omap_dss_reset(void)
++{
++ /* Soft reset */
++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
++ return _omap_dss_wait_reset();
++}
++
++void dss_set_venc_output(enum omap_dss_venc_type type)
++{
++ int l = 0;
++
++ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
++ l = 0;
++ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
++ l = 1;
++ else
++ BUG();
++
++ /* venc out selection. 0 = comp, 1 = svideo */
++ REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
++}
++
++void dss_set_dac_pwrdn_bgz(bool enable)
++{
++ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
++}
++
++int dss_init(bool skip_init)
++{
++ int r;
++ u32 rev;
++
++ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
++ if (!dss.base) {
++ DSSERR("can't ioremap DSS\n");
++ r = -ENOMEM;
++ goto fail0;
++ }
++
++ if (!skip_init) {
++ /* We need to wait here a bit, otherwise we sometimes start to
++ * get synclost errors, and after that only power cycle will
++ * restore DSS functionality. I have no idea why this happens.
++ * And we have to wait _before_ resetting the DSS, but after
++ * enabling clocks.
++ */
++ msleep(50);
++
++ _omap_dss_reset();
++
++ }
++ else
++ printk("DSS SKIP RESET\n");
++
++ /* autoidle */
++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
++
++ /* Select DPLL */
++ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
++ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
++ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
++#endif
++
++ r = request_irq(INT_24XX_DSS_IRQ,
++ cpu_is_omap24xx()
++ ? dss_irq_handler_omap2
++ : dss_irq_handler_omap3,
++ 0, "OMAP DSS", NULL);
++
++ if (r < 0) {
++ DSSERR("omap2 dss: request_irq failed\n");
++ goto fail1;
++ }
++
++ dss_save_context();
++
++ rev = dss_read_reg(DSS_REVISION);
++ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ return 0;
++
++fail1:
++ iounmap(dss.base);
++fail0:
++ return r;
++}
++
++void dss_exit(void)
++{
++ free_irq(INT_24XX_DSS_IRQ, NULL);
++
++ iounmap(dss.base);
++}
++
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+new file mode 100644
+index 0000000..bac5ece
+--- /dev/null
++++ b/drivers/video/omap2/dss/dss.h
+@@ -0,0 +1,331 @@
++/*
++ * linux/drivers/video/omap2/dss/dss.h
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __OMAP2_DSS_H
++#define __OMAP2_DSS_H
++
++#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
++#define DEBUG
++#endif
++
++#ifdef DEBUG
++extern unsigned int dss_debug;
++#ifdef DSS_SUBSYS_NAME
++#define DSSDBG(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSDBG(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSDBGF(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
++ ": %s(" format ")\n", \
++ __func__, \
++ ## __VA_ARGS__)
++#else
++#define DSSDBGF(format, ...) \
++ if (dss_debug) \
++ printk(KERN_DEBUG "omapdss: " \
++ ": %s(" format ")\n", \
++ __func__, \
++ ## __VA_ARGS__)
++#endif
++
++#else /* DEBUG */
++#define DSSDBG(format, ...)
++#define DSSDBGF(format, ...)
++#endif
++
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSERR(format, ...) \
++ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSERR(format, ...) \
++ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSINFO(format, ...) \
++ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSINFO(format, ...) \
++ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++#ifdef DSS_SUBSYS_NAME
++#define DSSWARN(format, ...) \
++ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
++ ## __VA_ARGS__)
++#else
++#define DSSWARN(format, ...) \
++ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
++#endif
++
++/* OMAP TRM gives bitfields as start:end, where start is the higher bit
++ number. For example 7:0 */
++#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
++#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
++#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
++#define FLD_MOD(orig, val, start, end) \
++ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
++
++#define DISPC_MAX_FCK 173000000
++
++enum omap_burst_size {
++ OMAP_DSS_BURST_4x32 = 0,
++ OMAP_DSS_BURST_8x32 = 1,
++ OMAP_DSS_BURST_16x32 = 2,
++};
++
++enum omap_parallel_interface_mode {
++ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
++ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
++ OMAP_DSS_PARALLELMODE_DSI,
++};
++
++enum dss_clock {
++ DSS_CLK_ICK = 1 << 0,
++ DSS_CLK_FCK1 = 1 << 1,
++ DSS_CLK_FCK2 = 1 << 2,
++ DSS_CLK_54M = 1 << 3,
++ DSS_CLK_96M = 1 << 4,
++};
++
++struct dispc_clock_info {
++ /* rates that we get with dividers below */
++ unsigned long fck;
++ unsigned long lck;
++ unsigned long pck;
++
++ /* dividers */
++ u16 fck_div;
++ u16 lck_div;
++ u16 pck_div;
++};
++
++struct dsi_clock_info {
++ /* rates that we get with dividers below */
++ unsigned long fint;
++ unsigned long dsiphy;
++ unsigned long clkin;
++ unsigned long dsi1_pll_fclk;
++ unsigned long dsi2_pll_fclk;
++ unsigned long lck;
++ unsigned long pck;
++
++ /* dividers */
++ u16 regn;
++ u16 regm;
++ u16 regm3;
++ u16 regm4;
++
++ u16 lck_div;
++ u16 pck_div;
++
++ u8 highfreq;
++ bool use_dss2_fck;
++};
++
++struct seq_file;
++struct platform_device;
++
++/* core */
++void dss_clk_enable(enum dss_clock clks);
++void dss_clk_disable(enum dss_clock clks);
++unsigned long dss_clk_get_rate(enum dss_clock clk);
++int dss_need_ctx_restore(void);
++void dss_dump_clocks(struct seq_file *s);
++
++int dss_dsi_power_up(void);
++void dss_dsi_power_down(void);
++
++/* display */
++void dss_init_displays(struct platform_device *pdev);
++void dss_uninit_displays(struct platform_device *pdev);
++int dss_suspend_all_displays(void);
++int dss_resume_all_displays(void);
++struct omap_display *dss_get_display(int no);
++
++/* manager */
++int dss_init_overlay_managers(struct platform_device *pdev);
++void dss_uninit_overlay_managers(struct platform_device *pdev);
++
++/* overlay */
++void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name);
++void dss_uninit_overlays(struct platform_device *pdev);
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display);
++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
++
++/* DSS */
++int dss_init(bool skip_init);
++void dss_exit(void);
++
++void dss_save_context(void);
++void dss_restore_context(void);
++
++void dss_dump_regs(struct seq_file *s);
++
++void dss_sdi_init(u8 datapairs);
++void dss_sdi_enable(void);
++void dss_sdi_disable(void);
++
++void dss_select_clk_source(bool dsi, bool dispc);
++int dss_get_dsi_clk_source(void);
++int dss_get_dispc_clk_source(void);
++void dss_set_venc_output(enum omap_dss_venc_type type);
++void dss_set_dac_pwrdn_bgz(bool enable);
++
++/* SDI */
++int sdi_init(bool skip_init);
++void sdi_exit(void);
++void sdi_init_display(struct omap_display *display);
++
++/* DSI */
++int dsi_init(void);
++void dsi_exit(void);
++
++void dsi_dump_clocks(struct seq_file *s);
++void dsi_dump_regs(struct seq_file *s);
++
++void dsi_save_context(void);
++void dsi_restore_context(void);
++
++void dsi_init_display(struct omap_display *display);
++void dsi_irq_handler(void);
++unsigned long dsi_get_dsi1_pll_rate(void);
++unsigned long dsi_get_dsi2_pll_rate(void);
++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
++ struct dsi_clock_info *cinfo);
++int dsi_pll_program(struct dsi_clock_info *cinfo);
++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
++void dsi_pll_uninit(void);
++
++/* DPI */
++int dpi_init(void);
++void dpi_exit(void);
++void dpi_init_display(struct omap_display *display);
++
++/* DISPC */
++int dispc_init(void);
++void dispc_exit(void);
++void dispc_dump_clocks(struct seq_file *s);
++void dispc_dump_regs(struct seq_file *s);
++void dispc_irq_handler(void);
++void dispc_fake_vsync_irq(void);
++
++void dispc_save_context(void);
++void dispc_restore_context(void);
++
++void dispc_lcd_enable_signal_polarity(bool act_high);
++void dispc_lcd_enable_signal(bool enable);
++void dispc_pck_free_enable(bool enable);
++void dispc_enable_fifohandcheck(bool enable);
++
++void dispc_set_lcd_size(u16 width, u16 height);
++void dispc_set_digit_size(u16 width, u16 height);
++u32 dispc_get_plane_fifo_size(enum omap_plane plane);
++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
++void dispc_enable_fifomerge(bool enable);
++void dispc_set_burst_size(enum omap_plane plane,
++ enum omap_burst_size burst_size);
++
++void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
++void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
++void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
++void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
++
++int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
++ u32 paddr, u16 screen_width,
++ u16 pos_x, u16 pos_y,
++ u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode,
++ bool ilace,
++ u8 rotation, bool mirror);
++
++void dispc_go(enum omap_channel channel);
++void dispc_enable_lcd_out(bool enable);
++void dispc_enable_digit_out(bool enable);
++int dispc_enable_plane(enum omap_plane plane, bool enable);
++
++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
++void dispc_set_tft_data_lines(u8 data_lines);
++void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
++void dispc_set_loadmode(enum omap_dss_load_mode mode);
++
++void dispc_set_default_color(enum omap_channel channel, u32 color);
++u32 dispc_get_default_color(enum omap_channel channel);
++void dispc_set_trans_key(enum omap_channel ch,
++ enum omap_dss_color_key_type type,
++ u32 trans_key);
++void dispc_get_trans_key(enum omap_channel ch,
++ enum omap_dss_color_key_type *type,
++ u32 *trans_key);
++void dispc_enable_trans_key(enum omap_channel ch, bool enable);
++bool dispc_trans_key_enabled(enum omap_channel ch);
++
++void dispc_set_lcd_timings(struct omap_video_timings *timings);
++unsigned long dispc_fclk_rate(void);
++unsigned long dispc_pclk_rate(void);
++void dispc_set_pol_freq(struct omap_panel *panel);
++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
++ u16 *lck_div, u16 *pck_div);
++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
++ struct dispc_clock_info *cinfo);
++int dispc_set_clock_div(struct dispc_clock_info *cinfo);
++int dispc_get_clock_div(struct dispc_clock_info *cinfo);
++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
++
++void dispc_setup_partial_planes(struct omap_display *display,
++ u16 *x, u16 *y, u16 *w, u16 *h);
++void dispc_draw_partial_planes(struct omap_display *display);
++
++
++/* VENC */
++int venc_init(void);
++void venc_exit(void);
++void venc_dump_regs(struct seq_file *s);
++void venc_init_display(struct omap_display *display);
++
++/* RFBI */
++int rfbi_init(void);
++void rfbi_exit(void);
++void rfbi_dump_regs(struct seq_file *s);
++
++int rfbi_configure(int rfbi_module, int bpp, int lines);
++void rfbi_enable_rfbi(bool enable);
++void rfbi_transfer_area(u16 width, u16 height,
++ void (callback)(void *data), void *data);
++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
++unsigned long rfbi_get_max_tx_rate(void);
++void rfbi_init_display(struct omap_display *display);
++
++#endif
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+new file mode 100644
+index 0000000..b0fee80
+--- /dev/null
++++ b/drivers/video/omap2/dss/manager.c
+@@ -0,0 +1,576 @@
++/*
++ * linux/drivers/video/omap2/dss/manager.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "MANAGER"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <mach/display.h>
++
++#include "dss.h"
++
++static int num_managers;
++static struct list_head manager_list;
++
++static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
++}
++
++static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ mgr->display ? mgr->display->name : "<none>");
++}
++
++static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const char *buf, size_t size)
++{
++ int r, i;
++ int len = size;
++ struct omap_display *display = NULL;
++
++ if (buf[size-1] == '\n')
++ --len;
++
++ if (len > 0) {
++ for (i = 0; i < omap_dss_get_num_displays(); ++i) {
++ display = dss_get_display(i);
++
++ if (strncmp(buf, display->name, len) == 0)
++ break;
++
++ display = NULL;
++ }
++ }
++
++ if (len > 0 && display == NULL)
++ return -EINVAL;
++
++ if (display)
++ DSSDBG("display %s found\n", display->name);
++
++ if (mgr->display) {
++ r = mgr->unset_display(mgr);
++ if (r) {
++ DSSERR("failed to unset display\n");
++ return r;
++ }
++ }
++
++ if (display) {
++ r = mgr->set_display(mgr, display);
++ if (r) {
++ DSSERR("failed to set manager\n");
++ return r;
++ }
++
++ r = mgr->apply(mgr);
++ if (r) {
++ DSSERR("failed to apply dispc config\n");
++ return r;
++ }
++ }
++
++ return size;
++}
++
++static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ u32 default_color;
++
++ default_color = dispc_get_default_color(mgr->id);
++ return snprintf(buf, PAGE_SIZE, "%d", default_color);
++}
++
++static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ u32 default_color;
++
++ if (sscanf(buf, "%d", &default_color) != 1)
++ return -EINVAL;
++ dispc_set_default_color(mgr->id, default_color);
++
++ return size;
++}
++
++static const char *color_key_type_str[] = {
++ "gfx-destination",
++ "video-source",
++};
++
++static ssize_t manager_color_key_type_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ enum omap_dss_color_key_type key_type;
++
++ dispc_get_trans_key(mgr->id, &key_type, NULL);
++ BUG_ON(key_type >= ARRAY_SIZE(color_key_type_str));
++
++ return snprintf(buf, PAGE_SIZE, "%s\n", color_key_type_str[key_type]);
++}
++
++static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ enum omap_dss_color_key_type key_type;
++ u32 key_value;
++
++ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
++ key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
++ if (sysfs_streq(buf, color_key_type_str[key_type]))
++ break;
++ }
++ if (key_type == ARRAY_SIZE(color_key_type_str))
++ return -EINVAL;
++ dispc_get_trans_key(mgr->id, NULL, &key_value);
++ dispc_set_trans_key(mgr->id, key_type, key_value);
++
++ return size;
++}
++
++static ssize_t manager_color_key_value_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ u32 key_value;
++
++ dispc_get_trans_key(mgr->id, NULL, &key_value);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", key_value);
++}
++
++static ssize_t manager_color_key_value_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ enum omap_dss_color_key_type key_type;
++ u32 key_value;
++
++ if (sscanf(buf, "%d", &key_value) != 1)
++ return -EINVAL;
++ dispc_get_trans_key(mgr->id, &key_type, NULL);
++ dispc_set_trans_key(mgr->id, key_type, key_value);
++
++ return size;
++}
++
++static ssize_t manager_color_key_enabled_show(struct omap_overlay_manager *mgr,
++ char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ dispc_trans_key_enabled(mgr->id));
++}
++
++static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ int enable;
++
++ if (sscanf(buf, "%d", &enable) != 1)
++ return -EINVAL;
++
++ dispc_enable_trans_key(mgr->id, enable);
++
++ return size;
++}
++
++
++struct manager_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct omap_overlay_manager *, char *);
++ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
++};
++
++#define MANAGER_ATTR(_name, _mode, _show, _store) \
++ struct manager_attribute manager_attr_##_name = \
++ __ATTR(_name, _mode, _show, _store)
++
++static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
++static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
++ manager_display_show, manager_display_store);
++static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
++ manager_default_color_show, manager_default_color_store);
++static MANAGER_ATTR(color_key_type, S_IRUGO|S_IWUSR,
++ manager_color_key_type_show, manager_color_key_type_store);
++static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
++ manager_color_key_value_show, manager_color_key_value_store);
++static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
++ manager_color_key_enabled_show, manager_color_key_enabled_store);
++
++static struct attribute *manager_sysfs_attrs[] = {
++ &manager_attr_name.attr,
++ &manager_attr_display.attr,
++ &manager_attr_default_color.attr,
++ &manager_attr_color_key_type.attr,
++ &manager_attr_color_key_value.attr,
++ &manager_attr_color_key_enabled.attr,
++ NULL
++};
++
++static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
++{
++ struct omap_overlay_manager *manager;
++ struct manager_attribute *manager_attr;
++
++ manager = container_of(kobj, struct omap_overlay_manager, kobj);
++ manager_attr = container_of(attr, struct manager_attribute, attr);
++
++ if (!manager_attr->show)
++ return -ENOENT;
++
++ return manager_attr->show(manager, buf);
++}
++
++static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay_manager *manager;
++ struct manager_attribute *manager_attr;
++
++ manager = container_of(kobj, struct omap_overlay_manager, kobj);
++ manager_attr = container_of(attr, struct manager_attribute, attr);
++
++ if (!manager_attr->store)
++ return -ENOENT;
++
++ return manager_attr->store(manager, buf, size);
++}
++
++static struct sysfs_ops manager_sysfs_ops = {
++ .show = manager_attr_show,
++ .store = manager_attr_store,
++};
++
++static struct kobj_type manager_ktype = {
++ .sysfs_ops = &manager_sysfs_ops,
++ .default_attrs = manager_sysfs_attrs,
++};
++
++static int omap_dss_set_display(struct omap_overlay_manager *mgr,
++ struct omap_display *display)
++{
++ int i;
++ int r;
++
++ if (display->manager) {
++ DSSERR("display '%s' already has a manager '%s'\n",
++ display->name, display->manager->name);
++ return -EINVAL;
++ }
++
++ if ((mgr->supported_displays & display->type) == 0) {
++ DSSERR("display '%s' does not support manager '%s'\n",
++ display->name, mgr->name);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < mgr->num_overlays; i++) {
++ struct omap_overlay *ovl = mgr->overlays[i];
++
++ if (ovl->manager != mgr || !ovl->info.enabled)
++ continue;
++
++ r = dss_check_overlay(ovl, display);
++ if (r)
++ return r;
++ }
++
++ display->manager = mgr;
++ mgr->display = display;
++
++ return 0;
++}
++
++static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
++{
++ if (!mgr->display) {
++ DSSERR("failed to unset display, display not set.\n");
++ return -EINVAL;
++ }
++
++ mgr->display->manager = NULL;
++ mgr->display = NULL;
++
++ return 0;
++}
++
++
++static int overlay_enabled(struct omap_overlay *ovl)
++{
++ return ovl->info.enabled && ovl->manager && ovl->manager->display;
++}
++
++/* We apply settings to both managers here so that we can use optimizations
++ * like fifomerge. Shadow registers can be changed first and the non-shadowed
++ * should be changed last, at the same time with GO */
++static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
++{
++ int i;
++ int ret = 0;
++ enum omap_dss_update_mode mode;
++ struct omap_display *display;
++ struct omap_overlay *ovl;
++ bool ilace = 0;
++ int outw, outh;
++ int r;
++ int num_planes_enabled = 0;
++
++ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ /* Configure normal overlay parameters and disable unused overlays */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (!overlay_enabled(ovl)) {
++ dispc_enable_plane(ovl->id, 0);
++ continue;
++ }
++
++ display = ovl->manager->display;
++
++ if (dss_check_overlay(ovl, display)) {
++ dispc_enable_plane(ovl->id, 0);
++ continue;
++ }
++
++ ++num_planes_enabled;
++
++ /* On a manual update display, in manual update mode, update()
++ * handles configuring planes */
++ mode = OMAP_DSS_UPDATE_AUTO;
++ if (display->get_update_mode)
++ mode = display->get_update_mode(mgr->display);
++
++ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ mode != OMAP_DSS_UPDATE_AUTO)
++ continue;
++
++ if (display->type == OMAP_DISPLAY_TYPE_VENC)
++ ilace = 1;
++
++ if (ovl->info.out_width == 0)
++ outw = ovl->info.width;
++ else
++ outw = ovl->info.out_width;
++
++ if (ovl->info.out_height == 0)
++ outh = ovl->info.height;
++ else
++ outh = ovl->info.out_height;
++
++ r = dispc_setup_plane(ovl->id, ovl->manager->id,
++ ovl->info.paddr,
++ ovl->info.screen_width,
++ ovl->info.pos_x,
++ ovl->info.pos_y,
++ ovl->info.width,
++ ovl->info.height,
++ outw,
++ outh,
++ ovl->info.color_mode,
++ ilace,
++ ovl->info.rotation,
++ ovl->info.mirror);
++
++ if (r) {
++ DSSERR("dispc_setup_plane failed for ovl %d\n",
++ ovl->id);
++ dispc_enable_plane(ovl->id, 0);
++ continue;
++ }
++
++ dispc_enable_plane(ovl->id, 1);
++ }
++
++ /* Enable fifo merge if possible */
++ dispc_enable_fifomerge(num_planes_enabled == 1);
++
++ /* Go through overlays again. This time we configure fifos. We have to
++ * do this after enabling/disabling fifomerge so that we have correct
++ * knowledge of fifo sizes */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (!overlay_enabled(ovl)) {
++ continue;
++ }
++
++ ovl->manager->display->configure_overlay(ovl);
++ }
++
++ /* Issue GO for managers */
++ list_for_each_entry(mgr, &manager_list, list) {
++ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
++ continue;
++
++ display = mgr->display;
++
++ if (!display)
++ continue;
++
++ /* We don't need GO with manual update display. LCD iface will
++ * always be turned off after frame, and new settings will
++ * be taken in to use at next update */
++ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
++ continue;
++
++ dispc_go(mgr->id);
++ }
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ return ret;
++}
++
++static void omap_dss_mgr_set_def_color(struct omap_overlay_manager *mgr,
++ u32 color)
++{
++ dispc_set_default_color(mgr->id, color);
++}
++
++static void omap_dss_mgr_set_trans_key(struct omap_overlay_manager *mgr,
++ enum omap_dss_color_key_type type,
++ u32 trans_key)
++{
++ dispc_set_trans_key(mgr->id, type, trans_key);
++}
++
++static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
++ bool enable)
++{
++ dispc_enable_trans_key(mgr->id, enable);
++}
++
++static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
++{
++ ++num_managers;
++ list_add_tail(&manager->list, &manager_list);
++}
++
++int dss_init_overlay_managers(struct platform_device *pdev)
++{
++ int i, r;
++
++ INIT_LIST_HEAD(&manager_list);
++
++ num_managers = 0;
++
++ for (i = 0; i < 2; ++i) {
++ struct omap_overlay_manager *mgr;
++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++ BUG_ON(mgr == NULL);
++
++ switch (i) {
++ case 0:
++ mgr->name = "lcd";
++ mgr->id = OMAP_DSS_CHANNEL_LCD;
++ mgr->supported_displays =
++ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
++ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
++ break;
++ case 1:
++ mgr->name = "tv";
++ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
++ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
++ break;
++ }
++
++ mgr->set_display = &omap_dss_set_display,
++ mgr->unset_display = &omap_dss_unset_display,
++ mgr->apply = &omap_dss_mgr_apply,
++ mgr->set_default_color = &omap_dss_mgr_set_def_color,
++ mgr->set_trans_key = &omap_dss_mgr_set_trans_key,
++ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
++ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
++
++ dss_overlay_setup_dispc_manager(mgr);
++
++ omap_dss_add_overlay_manager(mgr);
++
++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
++ &pdev->dev.kobj, "manager%d", i);
++
++ if (r) {
++ DSSERR("failed to create sysfs file\n");
++ continue;
++ }
++ }
++
++ return 0;
++}
++
++void dss_uninit_overlay_managers(struct platform_device *pdev)
++{
++ struct omap_overlay_manager *mgr;
++
++ while (!list_empty(&manager_list)) {
++ mgr = list_first_entry(&manager_list,
++ struct omap_overlay_manager, list);
++ list_del(&mgr->list);
++ kobject_del(&mgr->kobj);
++ kobject_put(&mgr->kobj);
++ kfree(mgr);
++ }
++
++ num_managers = 0;
++}
++
++int omap_dss_get_num_overlay_managers(void)
++{
++ return num_managers;
++}
++EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
++
++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
++{
++ int i = 0;
++ struct omap_overlay_manager *mgr;
++
++ list_for_each_entry(mgr, &manager_list, list) {
++ if (i++ == num)
++ return mgr;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_get_overlay_manager);
++
++#ifdef L4_EXAMPLE
++static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
++{
++ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
++
++ return 0;
++}
++#endif
++
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+new file mode 100644
+index 0000000..968edbe
+--- /dev/null
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -0,0 +1,587 @@
++/*
++ * linux/drivers/video/omap2/dss/overlay.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "OVERLAY"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/sysfs.h>
++#include <linux/kobject.h>
++#include <linux/platform_device.h>
++
++#include <mach/display.h>
++
++#include "dss.h"
++
++static int num_overlays;
++static struct list_head overlay_list;
++
++static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
++}
++
++static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ ovl->manager ? ovl->manager->name : "<none>");
++}
++
++static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, size_t size)
++{
++ int i, r;
++ struct omap_overlay_manager *mgr = NULL;
++ int len = size;
++
++ if (buf[size-1] == '\n')
++ --len;
++
++ if (len > 0) {
++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
++ mgr = omap_dss_get_overlay_manager(i);
++
++ if (strncmp(buf, mgr->name, len) == 0)
++ break;
++
++ mgr = NULL;
++ }
++ }
++
++ if (len > 0 && mgr == NULL)
++ return -EINVAL;
++
++ if (mgr)
++ DSSDBG("manager %s found\n", mgr->name);
++
++ if (mgr != ovl->manager) {
++ /* detach old manager */
++ if (ovl->manager) {
++ r = ovl->unset_manager(ovl);
++ if (r) {
++ DSSERR("detach failed\n");
++ return r;
++ }
++ }
++
++ if (mgr) {
++ r = ovl->set_manager(ovl, mgr);
++ if (r) {
++ DSSERR("Failed to attach overlay\n");
++ return r;
++ }
++ }
++ }
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
++static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.width, ovl->info.height);
++}
++
++static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
++}
++
++static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.pos_x, ovl->info.pos_y);
++}
++
++static ssize_t overlay_position_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ char *last;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.pos_x = simple_strtoul(buf, &last, 10);
++ ++last;
++ if (last - buf >= size)
++ return -EINVAL;
++
++ info.pos_y = simple_strtoul(last, &last, 10);
++
++ if ((r = ovl->set_overlay_info(ovl, &info)))
++ return r;
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
++static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d,%d\n",
++ ovl->info.out_width, ovl->info.out_height);
++}
++
++static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ char *last;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.out_width = simple_strtoul(buf, &last, 10);
++ ++last;
++ if (last - buf >= size)
++ return -EINVAL;
++
++ info.out_height = simple_strtoul(last, &last, 10);
++
++ if ((r = ovl->set_overlay_info(ovl, &info)))
++ return r;
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
++static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
++}
++
++static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, size_t size)
++{
++ int r;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.enabled = simple_strtoul(buf, NULL, 10);
++
++ if ((r = ovl->set_overlay_info(ovl, &info)))
++ return r;
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
++struct overlay_attribute {
++ struct attribute attr;
++ ssize_t (*show)(struct omap_overlay *, char *);
++ ssize_t (*store)(struct omap_overlay *, const char *, size_t);
++};
++
++#define OVERLAY_ATTR(_name, _mode, _show, _store) \
++ struct overlay_attribute overlay_attr_##_name = \
++ __ATTR(_name, _mode, _show, _store)
++
++static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
++static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
++ overlay_manager_show, overlay_manager_store);
++static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
++static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
++static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
++ overlay_position_show, overlay_position_store);
++static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
++ overlay_output_size_show, overlay_output_size_store);
++static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
++ overlay_enabled_show, overlay_enabled_store);
++
++static struct attribute *overlay_sysfs_attrs[] = {
++ &overlay_attr_name.attr,
++ &overlay_attr_manager.attr,
++ &overlay_attr_input_size.attr,
++ &overlay_attr_screen_width.attr,
++ &overlay_attr_position.attr,
++ &overlay_attr_output_size.attr,
++ &overlay_attr_enabled.attr,
++ NULL
++};
++
++static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
++{
++ struct omap_overlay *overlay;
++ struct overlay_attribute *overlay_attr;
++
++ overlay = container_of(kobj, struct omap_overlay, kobj);
++ overlay_attr = container_of(attr, struct overlay_attribute, attr);
++
++ if (!overlay_attr->show)
++ return -ENOENT;
++
++ return overlay_attr->show(overlay, buf);
++}
++
++static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t size)
++{
++ struct omap_overlay *overlay;
++ struct overlay_attribute *overlay_attr;
++
++ overlay = container_of(kobj, struct omap_overlay, kobj);
++ overlay_attr = container_of(attr, struct overlay_attribute, attr);
++
++ if (!overlay_attr->store)
++ return -ENOENT;
++
++ return overlay_attr->store(overlay, buf, size);
++}
++
++static struct sysfs_ops overlay_sysfs_ops = {
++ .show = overlay_attr_show,
++ .store = overlay_attr_store,
++};
++
++static struct kobj_type overlay_ktype = {
++ .sysfs_ops = &overlay_sysfs_ops,
++ .default_attrs = overlay_sysfs_attrs,
++};
++
++/* Check if overlay parameters are compatible with display */
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display)
++{
++ struct omap_overlay_info *info;
++ u16 outw, outh;
++ u16 dw, dh;
++
++ if (!display)
++ return 0;
++
++ if (!ovl->info.enabled)
++ return 0;
++
++ info = &ovl->info;
++
++ display->get_resolution(display, &dw, &dh);
++
++ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
++ ovl->id,
++ info->pos_x, info->pos_y,
++ info->width, info->height,
++ info->out_width, info->out_height,
++ dw, dh);
++
++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
++ outw = info->width;
++ outh = info->height;
++ } else {
++ if (info->out_width == 0)
++ outw = info->width;
++ else
++ outw = info->out_width;
++
++ if (info->out_height == 0)
++ outh = info->height;
++ else
++ outh = info->out_height;
++ }
++
++ if (dw < info->pos_x + outw) {
++ DSSDBG("check_overlay failed 1: %d < %d + %d\n",
++ dw, info->pos_x, outw);
++ return -EINVAL;
++ }
++
++ if (dh < info->pos_y + outh) {
++ DSSDBG("check_overlay failed 2: %d < %d + %d\n",
++ dh, info->pos_y, outh);
++ return -EINVAL;
++ }
++
++ if ((ovl->supported_modes & info->color_mode) == 0) {
++ DSSERR("overlay doesn't support mode %d\n", info->color_mode);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
++ struct omap_overlay_info *info)
++{
++ int r;
++ struct omap_overlay_info old_info;
++
++ old_info = ovl->info;
++ ovl->info = *info;
++
++ if (ovl->manager) {
++ r = dss_check_overlay(ovl, ovl->manager->display);
++ if (r) {
++ ovl->info = old_info;
++ return r;
++ }
++ }
++
++ return 0;
++}
++
++static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
++ struct omap_overlay_info *info)
++{
++ *info = ovl->info;
++}
++
++static int omap_dss_set_manager(struct omap_overlay *ovl,
++ struct omap_overlay_manager *mgr)
++{
++ int r;
++
++ if (ovl->manager) {
++ DSSERR("overlay '%s' already has a manager '%s'\n",
++ ovl->name, ovl->manager->name);
++ }
++
++ r = dss_check_overlay(ovl, mgr->display);
++ if (r)
++ return r;
++
++ ovl->manager = mgr;
++
++ return 0;
++}
++
++static int omap_dss_unset_manager(struct omap_overlay *ovl)
++{
++ if (!ovl->manager) {
++ DSSERR("failed to detach overlay: manager not set\n");
++ return -EINVAL;
++ }
++
++ ovl->manager = NULL;
++
++ return 0;
++}
++
++int omap_dss_get_num_overlays(void)
++{
++ return num_overlays;
++}
++EXPORT_SYMBOL(omap_dss_get_num_overlays);
++
++struct omap_overlay *omap_dss_get_overlay(int num)
++{
++ int i = 0;
++ struct omap_overlay *ovl;
++
++ list_for_each_entry(ovl, &overlay_list, list) {
++ if (i++ == num)
++ return ovl;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(omap_dss_get_overlay);
++
++static void omap_dss_add_overlay(struct omap_overlay *overlay)
++{
++ ++num_overlays;
++ list_add_tail(&overlay->list, &overlay_list);
++}
++
++static struct omap_overlay *dispc_overlays[3];
++
++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
++{
++ mgr->num_overlays = 3;
++ mgr->overlays = dispc_overlays;
++}
++
++void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
++{
++ int i, r;
++ struct omap_overlay_manager *lcd_mgr;
++ struct omap_overlay_manager *tv_mgr;
++ struct omap_overlay_manager *def_mgr = NULL;
++
++ INIT_LIST_HEAD(&overlay_list);
++
++ num_overlays = 0;
++
++ for (i = 0; i < 3; ++i) {
++ struct omap_overlay *ovl;
++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
++
++ BUG_ON(ovl == NULL);
++
++ switch (i) {
++ case 0:
++ ovl->name = "gfx";
++ ovl->id = OMAP_DSS_GFX;
++ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
++ break;
++ case 1:
++ ovl->name = "vid1";
++ ovl->id = OMAP_DSS_VIDEO1;
++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
++ OMAP_DSS_OVL_CAP_DISPC;
++ break;
++ case 2:
++ ovl->name = "vid2";
++ ovl->id = OMAP_DSS_VIDEO2;
++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
++ OMAP_DSS_OVL_CAP_DISPC;
++ break;
++ }
++
++ ovl->set_manager = &omap_dss_set_manager;
++ ovl->unset_manager = &omap_dss_unset_manager;
++ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
++ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
++
++ omap_dss_add_overlay(ovl);
++
++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
++ &pdev->dev.kobj, "overlay%d", i);
++
++ if (r) {
++ DSSERR("failed to create sysfs file\n");
++ continue;
++ }
++
++ dispc_overlays[i] = ovl;
++ }
++
++ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
++ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
++
++ if (def_disp_name) {
++ for (i = 0; i < omap_dss_get_num_displays() ; i++) {
++ struct omap_display *display = dss_get_display(i);
++
++ if (strcmp(display->name, def_disp_name) == 0) {
++ if (display->type != OMAP_DISPLAY_TYPE_VENC) {
++ lcd_mgr->set_display(lcd_mgr, display);
++ def_mgr = lcd_mgr;
++ } else {
++ lcd_mgr->set_display(tv_mgr, display);
++ def_mgr = tv_mgr;
++ }
++
++ break;
++ }
++ }
++
++ if (!def_mgr)
++ DSSWARN("default display %s not found\n",
++ def_disp_name);
++ }
++
++ if (def_mgr != lcd_mgr) {
++ /* connect lcd manager to first non-VENC display found */
++ for (i = 0; i < omap_dss_get_num_displays(); i++) {
++ struct omap_display *display = dss_get_display(i);
++ if (display->type != OMAP_DISPLAY_TYPE_VENC) {
++ lcd_mgr->set_display(lcd_mgr, display);
++
++ if (!def_mgr)
++ def_mgr = lcd_mgr;
++
++ break;
++ }
++ }
++ }
++
++ if (def_mgr != tv_mgr) {
++ /* connect tv manager to first VENC display found */
++ for (i = 0; i < omap_dss_get_num_displays(); i++) {
++ struct omap_display *display = dss_get_display(i);
++ if (display->type == OMAP_DISPLAY_TYPE_VENC) {
++ tv_mgr->set_display(tv_mgr, display);
++
++ if (!def_mgr)
++ def_mgr = tv_mgr;
++
++ break;
++ }
++ }
++ }
++
++ /* connect all dispc overlays to def_mgr */
++ if (def_mgr) {
++ for (i = 0; i < 3; i++) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++ omap_dss_set_manager(ovl, def_mgr);
++ }
++ }
++
++#ifdef L4_EXAMPLE
++ /* setup L4 overlay as an example */
++ {
++ static struct omap_overlay ovl = {
++ .name = "l4-ovl",
++ .supported_modes = OMAP_DSS_COLOR_RGB24U,
++ .set_manager = &omap_dss_set_manager,
++ .unset_manager = &omap_dss_unset_manager,
++ .setup_input = &omap_dss_setup_overlay_input,
++ .setup_output = &omap_dss_setup_overlay_output,
++ .enable = &omap_dss_enable_overlay,
++ };
++
++ static struct omap_overlay_manager mgr = {
++ .name = "l4",
++ .num_overlays = 1,
++ .overlays = &ovl,
++ .set_display = &omap_dss_set_display,
++ .unset_display = &omap_dss_unset_display,
++ .apply = &ovl_mgr_apply_l4,
++ .supported_displays =
++ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
++ };
++
++ omap_dss_add_overlay(&ovl);
++ omap_dss_add_overlay_manager(&mgr);
++ omap_dss_set_manager(&ovl, &mgr);
++ }
++#endif
++}
++
++void dss_uninit_overlays(struct platform_device *pdev)
++{
++ struct omap_overlay *ovl;
++
++ while (!list_empty(&overlay_list)) {
++ ovl = list_first_entry(&overlay_list,
++ struct omap_overlay, list);
++ list_del(&ovl->list);
++ kobject_del(&ovl->kobj);
++ kobject_put(&ovl->kobj);
++ kfree(ovl);
++ }
++
++ num_overlays = 0;
++}
++
+diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
+new file mode 100644
+index 0000000..3e9ae1e
+--- /dev/null
++++ b/drivers/video/omap2/dss/rfbi.c
+@@ -0,0 +1,1304 @@
++/*
++ * linux/drivers/video/omap2/dss/rfbi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "RFBI"
++
++#include <linux/kernel.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/kfifo.h>
++#include <linux/ktime.h>
++#include <linux/hrtimer.h>
++#include <linux/seq_file.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include "dss.h"
++
++/*#define MEASURE_PERF*/
++
++#define RFBI_BASE 0x48050800
++
++struct rfbi_reg { u16 idx; };
++
++#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
++
++#define RFBI_REVISION RFBI_REG(0x0000)
++#define RFBI_SYSCONFIG RFBI_REG(0x0010)
++#define RFBI_SYSSTATUS RFBI_REG(0x0014)
++#define RFBI_CONTROL RFBI_REG(0x0040)
++#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
++#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
++#define RFBI_CMD RFBI_REG(0x004c)
++#define RFBI_PARAM RFBI_REG(0x0050)
++#define RFBI_DATA RFBI_REG(0x0054)
++#define RFBI_READ RFBI_REG(0x0058)
++#define RFBI_STATUS RFBI_REG(0x005c)
++
++#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
++#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
++#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
++#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
++#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
++#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
++
++#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
++#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
++
++#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
++
++#define REG_FLD_MOD(idx, val, start, end) \
++ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
++
++/* To work around an RFBI transfer rate limitation */
++#define OMAP_RFBI_RATE_LIMIT 1
++
++enum omap_rfbi_cycleformat {
++ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
++ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
++ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
++ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
++};
++
++enum omap_rfbi_datatype {
++ OMAP_DSS_RFBI_DATATYPE_12 = 0,
++ OMAP_DSS_RFBI_DATATYPE_16 = 1,
++ OMAP_DSS_RFBI_DATATYPE_18 = 2,
++ OMAP_DSS_RFBI_DATATYPE_24 = 3,
++};
++
++enum omap_rfbi_parallelmode {
++ OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
++ OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
++ OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
++ OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
++};
++
++enum update_cmd {
++ RFBI_CMD_UPDATE = 0,
++ RFBI_CMD_SYNC = 1,
++};
++
++static int rfbi_convert_timings(struct rfbi_timings *t);
++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
++static void process_cmd_fifo(void);
++
++static struct {
++ void __iomem *base;
++
++ unsigned long l4_khz;
++
++ enum omap_rfbi_datatype datatype;
++ enum omap_rfbi_parallelmode parallelmode;
++
++ enum omap_rfbi_te_mode te_mode;
++ int te_enabled;
++
++ void (*framedone_callback)(void *data);
++ void *framedone_callback_data;
++
++ struct omap_display *display[2];
++
++ struct kfifo *cmd_fifo;
++ spinlock_t cmd_lock;
++ struct completion cmd_done;
++ atomic_t cmd_fifo_full;
++ atomic_t cmd_pending;
++#ifdef MEASURE_PERF
++ unsigned perf_bytes;
++ ktime_t perf_setup_time;
++ ktime_t perf_start_time;
++#endif
++} rfbi;
++
++struct update_region {
++ u16 x;
++ u16 y;
++ u16 w;
++ u16 h;
++};
++
++struct update_param {
++ u8 rfbi_module;
++ u8 cmd;
++
++ union {
++ struct update_region r;
++ struct completion *sync;
++ } par;
++};
++
++static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
++{
++ __raw_writel(val, rfbi.base + idx.idx);
++}
++
++static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
++{
++ return __raw_readl(rfbi.base + idx.idx);
++}
++
++static void rfbi_enable_clocks(bool enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++}
++
++void omap_rfbi_write_command(const void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ const u8 *b = buf;
++ for (; len; len--)
++ rfbi_write_reg(RFBI_CMD, *b++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ const u16 *w = buf;
++ BUG_ON(len & 1);
++ for (; len; len -= 2)
++ rfbi_write_reg(RFBI_CMD, *w++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_command);
++
++void omap_rfbi_read_data(void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ u8 *b = buf;
++ for (; len; len--) {
++ rfbi_write_reg(RFBI_READ, 0);
++ *b++ = rfbi_read_reg(RFBI_READ);
++ }
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ u16 *w = buf;
++ BUG_ON(len & ~1);
++ for (; len; len -= 2) {
++ rfbi_write_reg(RFBI_READ, 0);
++ *w++ = rfbi_read_reg(RFBI_READ);
++ }
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_read_data);
++
++void omap_rfbi_write_data(const void *buf, u32 len)
++{
++ rfbi_enable_clocks(1);
++ switch (rfbi.parallelmode) {
++ case OMAP_DSS_RFBI_PARALLELMODE_8:
++ {
++ const u8 *b = buf;
++ for (; len; len--)
++ rfbi_write_reg(RFBI_PARAM, *b++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_16:
++ {
++ const u16 *w = buf;
++ BUG_ON(len & 1);
++ for (; len; len -= 2)
++ rfbi_write_reg(RFBI_PARAM, *w++);
++ break;
++ }
++
++ case OMAP_DSS_RFBI_PARALLELMODE_9:
++ case OMAP_DSS_RFBI_PARALLELMODE_12:
++ default:
++ BUG();
++
++ }
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_data);
++
++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
++ u16 x, u16 y,
++ u16 w, u16 h)
++{
++ int start_offset = scr_width * y + x;
++ int horiz_offset = scr_width - w;
++ int i;
++
++ rfbi_enable_clocks(1);
++
++ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
++ const u16 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ const u8 __iomem *b = (const u8 __iomem *)pd;
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
++ const u32 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ const u8 __iomem *b = (const u8 __iomem *)pd;
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
++ const u16 __iomem *pd = buf;
++ pd += start_offset;
++
++ for (; h; --h) {
++ for (i = 0; i < w; ++i) {
++ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
++ ++pd;
++ }
++ pd += horiz_offset;
++ }
++ } else {
++ BUG();
++ }
++
++ rfbi_enable_clocks(0);
++}
++EXPORT_SYMBOL(omap_rfbi_write_pixels);
++
++#ifdef MEASURE_PERF
++static void perf_mark_setup(void)
++{
++ rfbi.perf_setup_time = ktime_get();
++}
++
++static void perf_mark_start(void)
++{
++ rfbi.perf_start_time = ktime_get();
++}
++
++static void perf_show(const char *name)
++{
++ ktime_t t, setup_time, trans_time;
++ u32 total_bytes;
++ u32 setup_us, trans_us, total_us;
++
++ t = ktime_get();
++
++ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
++ setup_us = (u32)ktime_to_us(setup_time);
++ if (setup_us == 0)
++ setup_us = 1;
++
++ trans_time = ktime_sub(t, rfbi.perf_start_time);
++ trans_us = (u32)ktime_to_us(trans_time);
++ if (trans_us == 0)
++ trans_us = 1;
++
++ total_us = setup_us + trans_us;
++
++ total_bytes = rfbi.perf_bytes;
++
++ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
++ "%u kbytes/sec\n",
++ name,
++ setup_us,
++ trans_us,
++ total_us,
++ 1000*1000 / total_us,
++ total_bytes,
++ total_bytes * 1000 / total_us);
++}
++#else
++#define perf_mark_setup()
++#define perf_mark_start()
++#define perf_show(x)
++#endif
++
++void rfbi_transfer_area(u16 width, u16 height,
++ void (callback)(void *data), void *data)
++{
++ u32 l;
++
++ /*BUG_ON(callback == 0);*/
++ BUG_ON(rfbi.framedone_callback != NULL);
++
++ DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
++
++ dispc_set_lcd_size(width, height);
++
++ dispc_enable_lcd_out(1);
++
++ rfbi.framedone_callback = callback;
++ rfbi.framedone_callback_data = data;
++
++ rfbi_enable_clocks(1);
++
++ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++ l = FLD_MOD(l, 1, 0, 0); /* enable */
++ if (!rfbi.te_enabled)
++ l = FLD_MOD(l, 1, 4, 4); /* ITE */
++
++ perf_mark_start();
++
++ rfbi_write_reg(RFBI_CONTROL, l);
++}
++
++static void framedone_callback(void *data, u32 mask)
++{
++ void (*callback)(void *data);
++
++ DSSDBG("FRAMEDONE\n");
++
++ perf_show("DISPC");
++
++ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
++
++ rfbi_enable_clocks(0);
++
++ callback = rfbi.framedone_callback;
++ rfbi.framedone_callback = NULL;
++
++ /*callback(rfbi.framedone_callback_data);*/
++
++ atomic_set(&rfbi.cmd_pending, 0);
++
++ process_cmd_fifo();
++}
++
++#if 1 /* VERBOSE */
++static void rfbi_print_timings(void)
++{
++ u32 l;
++ u32 time;
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ time = 1000000000 / rfbi.l4_khz;
++ if (l & (1 << 4))
++ time *= 2;
++
++ DSSDBG("Tick time %u ps\n", time);
++ l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
++ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
++ "REONTIME %d, REOFFTIME %d\n",
++ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
++ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
++
++ l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
++ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
++ "ACCESSTIME %d\n",
++ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
++ (l >> 22) & 0x3f);
++}
++#else
++static void rfbi_print_timings(void) {}
++#endif
++
++
++
++
++static u32 extif_clk_period;
++
++static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
++{
++ int bus_tick = extif_clk_period * div;
++ return (ps + bus_tick - 1) / bus_tick * bus_tick;
++}
++
++static int calc_reg_timing(struct rfbi_timings *t, int div)
++{
++ t->clk_div = div;
++
++ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
++
++ t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
++ t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
++ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
++
++ t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
++ t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
++ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
++
++ t->access_time = round_to_extif_ticks(t->access_time, div);
++ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
++ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
++
++ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
++ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
++ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
++ t->we_on_time, t->we_off_time, t->re_cycle_time,
++ t->we_cycle_time);
++ DSSDBG("[reg]rdaccess %d cspulse %d\n",
++ t->access_time, t->cs_pulse_width);
++
++ return rfbi_convert_timings(t);
++}
++
++static int calc_extif_timings(struct rfbi_timings *t)
++{
++ u32 max_clk_div;
++ int div;
++
++ rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
++ for (div = 1; div <= max_clk_div; div++) {
++ if (calc_reg_timing(t, div) == 0)
++ break;
++ }
++
++ if (div <= max_clk_div)
++ return 0;
++
++ DSSERR("can't setup timings\n");
++ return -1;
++}
++
++
++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
++{
++ int r;
++
++ if (!t->converted) {
++ r = calc_extif_timings(t);
++ if (r < 0)
++ DSSERR("Failed to calc timings\n");
++ }
++
++ BUG_ON(!t->converted);
++
++ rfbi_enable_clocks(1);
++ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
++ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
++
++ /* TIMEGRANULARITY */
++ REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
++ (t->tim[2] ? 1 : 0), 4, 4);
++
++ rfbi_print_timings();
++ rfbi_enable_clocks(0);
++}
++
++static int ps_to_rfbi_ticks(int time, int div)
++{
++ unsigned long tick_ps;
++ int ret;
++
++ /* Calculate in picosecs to yield more exact results */
++ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
++
++ ret = (time + tick_ps - 1) / tick_ps;
++
++ return ret;
++}
++
++#ifdef OMAP_RFBI_RATE_LIMIT
++unsigned long rfbi_get_max_tx_rate(void)
++{
++ unsigned long l4_rate, dss1_rate;
++ int min_l4_ticks = 0;
++ int i;
++
++ /* According to TI this can't be calculated so make the
++ * adjustments for a couple of known frequencies and warn for
++ * others.
++ */
++ static const struct {
++ unsigned long l4_clk; /* HZ */
++ unsigned long dss1_clk; /* HZ */
++ unsigned long min_l4_ticks;
++ } ftab[] = {
++ { 55, 132, 7, }, /* 7.86 MPix/s */
++ { 110, 110, 12, }, /* 9.16 MPix/s */
++ { 110, 132, 10, }, /* 11 Mpix/s */
++ { 120, 120, 10, }, /* 12 Mpix/s */
++ { 133, 133, 10, }, /* 13.3 Mpix/s */
++ };
++
++ l4_rate = rfbi.l4_khz / 1000;
++ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
++
++ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
++ /* Use a window instead of an exact match, to account
++ * for different DPLL multiplier / divider pairs.
++ */
++ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
++ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
++ min_l4_ticks = ftab[i].min_l4_ticks;
++ break;
++ }
++ }
++ if (i == ARRAY_SIZE(ftab)) {
++ /* Can't be sure, return anyway the maximum not
++ * rate-limited. This might cause a problem only for the
++ * tearing synchronisation.
++ */
++ DSSERR("can't determine maximum RFBI transfer rate\n");
++ return rfbi.l4_khz * 1000;
++ }
++ return rfbi.l4_khz * 1000 / min_l4_ticks;
++}
++#else
++int rfbi_get_max_tx_rate(void)
++{
++ return rfbi.l4_khz * 1000;
++}
++#endif
++
++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
++{
++ *clk_period = 1000000000 / rfbi.l4_khz;
++ *max_clk_div = 2;
++}
++
++static int rfbi_convert_timings(struct rfbi_timings *t)
++{
++ u32 l;
++ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
++ int actim, recyc, wecyc;
++ int div = t->clk_div;
++
++ if (div <= 0 || div > 2)
++ return -1;
++
++ /* Make sure that after conversion it still holds that:
++ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
++ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
++ */
++ weon = ps_to_rfbi_ticks(t->we_on_time, div);
++ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
++ if (weoff <= weon)
++ weoff = weon + 1;
++ if (weon > 0x0f)
++ return -1;
++ if (weoff > 0x3f)
++ return -1;
++
++ reon = ps_to_rfbi_ticks(t->re_on_time, div);
++ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
++ if (reoff <= reon)
++ reoff = reon + 1;
++ if (reon > 0x0f)
++ return -1;
++ if (reoff > 0x3f)
++ return -1;
++
++ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
++ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
++ if (csoff <= cson)
++ csoff = cson + 1;
++ if (csoff < max(weoff, reoff))
++ csoff = max(weoff, reoff);
++ if (cson > 0x0f)
++ return -1;
++ if (csoff > 0x3f)
++ return -1;
++
++ l = cson;
++ l |= csoff << 4;
++ l |= weon << 10;
++ l |= weoff << 14;
++ l |= reon << 20;
++ l |= reoff << 24;
++
++ t->tim[0] = l;
++
++ actim = ps_to_rfbi_ticks(t->access_time, div);
++ if (actim <= reon)
++ actim = reon + 1;
++ if (actim > 0x3f)
++ return -1;
++
++ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
++ if (wecyc < weoff)
++ wecyc = weoff;
++ if (wecyc > 0x3f)
++ return -1;
++
++ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
++ if (recyc < reoff)
++ recyc = reoff;
++ if (recyc > 0x3f)
++ return -1;
++
++ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
++ if (cs_pulse > 0x3f)
++ return -1;
++
++ l = wecyc;
++ l |= recyc << 6;
++ l |= cs_pulse << 12;
++ l |= actim << 22;
++
++ t->tim[1] = l;
++
++ t->tim[2] = div - 1;
++
++ t->converted = 1;
++
++ return 0;
++}
++
++/* xxx FIX module selection missing */
++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
++ unsigned hs_pulse_time, unsigned vs_pulse_time,
++ int hs_pol_inv, int vs_pol_inv, int extif_div)
++{
++ int hs, vs;
++ int min;
++ u32 l;
++
++ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
++ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
++ if (hs < 2)
++ return -EDOM;
++ if (mode == OMAP_DSS_RFBI_TE_MODE_2)
++ min = 2;
++ else /* OMAP_DSS_RFBI_TE_MODE_1 */
++ min = 4;
++ if (vs < min)
++ return -EDOM;
++ if (vs == hs)
++ return -EINVAL;
++ rfbi.te_mode = mode;
++ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
++ mode, hs, vs, hs_pol_inv, vs_pol_inv);
++
++ rfbi_enable_clocks(1);
++ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
++ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ if (hs_pol_inv)
++ l &= ~(1 << 21);
++ else
++ l |= 1 << 21;
++ if (vs_pol_inv)
++ l &= ~(1 << 20);
++ else
++ l |= 1 << 20;
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(omap_rfbi_setup_te);
++
++/* xxx FIX module selection missing */
++int omap_rfbi_enable_te(bool enable, unsigned line)
++{
++ u32 l;
++
++ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
++ if (line > (1 << 11) - 1)
++ return -EINVAL;
++
++ rfbi_enable_clocks(1);
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ l &= ~(0x3 << 2);
++ if (enable) {
++ rfbi.te_enabled = 1;
++ l |= rfbi.te_mode << 2;
++ } else
++ rfbi.te_enabled = 0;
++ rfbi_write_reg(RFBI_CONFIG(0), l);
++ rfbi_write_reg(RFBI_LINE_NUMBER, line);
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(omap_rfbi_enable_te);
++
++#if 0
++static void rfbi_enable_config(int enable1, int enable2)
++{
++ u32 l;
++ int cs = 0;
++
++ if (enable1)
++ cs |= 1<<0;
++ if (enable2)
++ cs |= 1<<1;
++
++ rfbi_enable_clocks(1);
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++
++ l = FLD_MOD(l, cs, 3, 2);
++ l = FLD_MOD(l, 0, 1, 1);
++
++ rfbi_write_reg(RFBI_CONTROL, l);
++
++
++ l = rfbi_read_reg(RFBI_CONFIG(0));
++ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
++ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
++ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
++
++ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
++ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
++ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
++
++ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
++ rfbi_write_reg(RFBI_CONFIG(0), l);
++
++ rfbi_enable_clocks(0);
++}
++#endif
++
++int rfbi_configure(int rfbi_module, int bpp, int lines)
++{
++ u32 l;
++ int cycle1 = 0, cycle2 = 0, cycle3 = 0;
++ enum omap_rfbi_cycleformat cycleformat;
++ enum omap_rfbi_datatype datatype;
++ enum omap_rfbi_parallelmode parallelmode;
++
++ switch (bpp) {
++ case 12:
++ datatype = OMAP_DSS_RFBI_DATATYPE_12;
++ break;
++ case 16:
++ datatype = OMAP_DSS_RFBI_DATATYPE_16;
++ break;
++ case 18:
++ datatype = OMAP_DSS_RFBI_DATATYPE_18;
++ break;
++ case 24:
++ datatype = OMAP_DSS_RFBI_DATATYPE_24;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ rfbi.datatype = datatype;
++
++ switch (lines) {
++ case 8:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
++ break;
++ case 9:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
++ break;
++ case 12:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
++ break;
++ case 16:
++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ rfbi.parallelmode = parallelmode;
++
++ if ((bpp % lines) == 0) {
++ switch (bpp / lines) {
++ case 1:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
++ break;
++ case 2:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
++ break;
++ case 3:
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
++ break;
++ default:
++ BUG();
++ return 1;
++ }
++ } else if ((2 * bpp % lines) == 0) {
++ if ((2 * bpp / lines) == 3)
++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
++ else {
++ BUG();
++ return 1;
++ }
++ } else {
++ BUG();
++ return 1;
++ }
++
++ switch (cycleformat) {
++ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
++ cycle1 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
++ cycle1 = lines;
++ cycle2 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
++ cycle1 = lines;
++ cycle2 = lines;
++ cycle3 = lines;
++ break;
++
++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
++ cycle1 = lines;
++ cycle2 = (lines / 2) | ((lines / 2) << 16);
++ cycle3 = (lines << 16);
++ break;
++ }
++
++ rfbi_enable_clocks(1);
++
++ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
++
++ l = 0;
++ l |= FLD_VAL(parallelmode, 1, 0);
++ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
++ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
++ l |= FLD_VAL(datatype, 6, 5);
++ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
++ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
++ l |= FLD_VAL(cycleformat, 10, 9);
++ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
++ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
++ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
++ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
++ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
++ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
++ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
++ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
++
++ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
++ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
++ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
++
++
++ l = rfbi_read_reg(RFBI_CONTROL);
++ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
++ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
++ rfbi_write_reg(RFBI_CONTROL, l);
++
++
++ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
++ bpp, lines, cycle1, cycle2, cycle3);
++
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++EXPORT_SYMBOL(rfbi_configure);
++
++static int rfbi_find_display(struct omap_display *disp)
++{
++ if (disp == rfbi.display[0])
++ return 0;
++
++ if (disp == rfbi.display[1])
++ return 1;
++
++ BUG();
++ return -1;
++}
++
++
++static void signal_fifo_waiters(void)
++{
++ if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
++ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
++ complete(&rfbi.cmd_done);
++ atomic_dec(&rfbi.cmd_fifo_full);
++ }
++}
++
++/* returns 1 for async op, and 0 for sync op */
++static int do_update(struct omap_display *display, struct update_region *upd)
++{
++ u16 x = upd->x;
++ u16 y = upd->y;
++ u16 w = upd->w;
++ u16 h = upd->h;
++
++ perf_mark_setup();
++
++ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ /*display->ctrl->enable_te(display, 1); */
++ dispc_setup_partial_planes(display, &x, &y, &w, &h);
++ }
++
++#ifdef MEASURE_PERF
++ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
++#endif
++
++ display->ctrl->setup_update(display, x, y, w, h);
++
++ if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ rfbi_transfer_area(w, h, NULL, NULL);
++ return 1;
++ } else {
++ struct omap_overlay *ovl;
++ void __iomem *addr;
++ int scr_width;
++
++ ovl = display->manager->overlays[0];
++ scr_width = ovl->info.screen_width;
++ addr = ovl->info.vaddr;
++
++ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
++
++ perf_show("L4");
++
++ return 0;
++ }
++}
++
++static void process_cmd_fifo(void)
++{
++ int len;
++ struct update_param p;
++ struct omap_display *display;
++ unsigned long flags;
++
++ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
++ return;
++
++ while (true) {
++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
++
++ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p,
++ sizeof(struct update_param));
++ if (len == 0) {
++ DSSDBG("nothing more in fifo\n");
++ atomic_set(&rfbi.cmd_pending, 0);
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++ break;
++ }
++
++ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
++
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++
++ BUG_ON(len != sizeof(struct update_param));
++ BUG_ON(p.rfbi_module > 1);
++
++ display = rfbi.display[p.rfbi_module];
++
++ if (p.cmd == RFBI_CMD_UPDATE) {
++ if (do_update(display, &p.par.r))
++ break; /* async op */
++ } else if (p.cmd == RFBI_CMD_SYNC) {
++ DSSDBG("Signaling SYNC done!\n");
++ complete(p.par.sync);
++ } else
++ BUG();
++ }
++
++ signal_fifo_waiters();
++}
++
++static void rfbi_push_cmd(struct update_param *p)
++{
++ int ret;
++
++ while (1) {
++ unsigned long flags;
++ int available;
++
++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
++ available = RFBI_CMD_FIFO_LEN_BYTES -
++ __kfifo_len(rfbi.cmd_fifo);
++
++/* DSSDBG("%d bytes left in fifo\n", available); */
++ if (available < sizeof(struct update_param)) {
++ DSSDBG("Going to wait because FIFO FULL..\n");
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++ atomic_inc(&rfbi.cmd_fifo_full);
++ wait_for_completion(&rfbi.cmd_done);
++ /*DSSDBG("Woke up because fifo not full anymore\n");*/
++ continue;
++ }
++
++ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
++ sizeof(struct update_param));
++/* DSSDBG("pushed %d bytes\n", ret);*/
++
++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
++
++ BUG_ON(ret != sizeof(struct update_param));
++
++ break;
++ }
++}
++
++static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
++{
++ struct update_param p;
++
++ p.rfbi_module = rfbi_module;
++ p.cmd = RFBI_CMD_UPDATE;
++
++ p.par.r.x = x;
++ p.par.r.y = y;
++ p.par.r.w = w;
++ p.par.r.h = h;
++
++ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
++
++ rfbi_push_cmd(&p);
++
++ process_cmd_fifo();
++}
++
++static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
++{
++ struct update_param p;
++
++ p.rfbi_module = rfbi_module;
++ p.cmd = RFBI_CMD_SYNC;
++ p.par.sync = sync_comp;
++
++ rfbi_push_cmd(&p);
++
++ DSSDBG("RFBI sync pushed to cmd fifo\n");
++
++ process_cmd_fifo();
++}
++
++void rfbi_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ DUMPREG(RFBI_REVISION);
++ DUMPREG(RFBI_SYSCONFIG);
++ DUMPREG(RFBI_SYSSTATUS);
++ DUMPREG(RFBI_CONTROL);
++ DUMPREG(RFBI_PIXEL_CNT);
++ DUMPREG(RFBI_LINE_NUMBER);
++ DUMPREG(RFBI_CMD);
++ DUMPREG(RFBI_PARAM);
++ DUMPREG(RFBI_DATA);
++ DUMPREG(RFBI_READ);
++ DUMPREG(RFBI_STATUS);
++
++ DUMPREG(RFBI_CONFIG(0));
++ DUMPREG(RFBI_ONOFF_TIME(0));
++ DUMPREG(RFBI_CYCLE_TIME(0));
++ DUMPREG(RFBI_DATA_CYCLE1(0));
++ DUMPREG(RFBI_DATA_CYCLE2(0));
++ DUMPREG(RFBI_DATA_CYCLE3(0));
++
++ DUMPREG(RFBI_CONFIG(1));
++ DUMPREG(RFBI_ONOFF_TIME(1));
++ DUMPREG(RFBI_CYCLE_TIME(1));
++ DUMPREG(RFBI_DATA_CYCLE1(1));
++ DUMPREG(RFBI_DATA_CYCLE2(1));
++ DUMPREG(RFBI_DATA_CYCLE3(1));
++
++ DUMPREG(RFBI_VSYNC_WIDTH);
++ DUMPREG(RFBI_HSYNC_WIDTH);
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++#undef DUMPREG
++}
++
++int rfbi_init(void)
++{
++ u32 rev;
++ u32 l;
++
++ spin_lock_init(&rfbi.cmd_lock);
++ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
++ &rfbi.cmd_lock);
++ if (IS_ERR(rfbi.cmd_fifo))
++ return -ENOMEM;
++
++ init_completion(&rfbi.cmd_done);
++ atomic_set(&rfbi.cmd_fifo_full, 0);
++ atomic_set(&rfbi.cmd_pending, 0);
++
++ rfbi.base = ioremap(RFBI_BASE, SZ_256);
++ if (!rfbi.base) {
++ DSSERR("can't ioremap RFBI\n");
++ return -ENOMEM;
++ }
++
++ rfbi_enable_clocks(1);
++
++ msleep(10);
++
++ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
++
++ /* Enable autoidle and smart-idle */
++ l = rfbi_read_reg(RFBI_SYSCONFIG);
++ l |= (1 << 0) | (2 << 3);
++ rfbi_write_reg(RFBI_SYSCONFIG, l);
++
++ rev = rfbi_read_reg(RFBI_REVISION);
++ printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
++
++ rfbi_enable_clocks(0);
++
++ return 0;
++}
++
++void rfbi_exit(void)
++{
++ DSSDBG("rfbi_exit\n");
++
++ kfifo_free(rfbi.cmd_fifo);
++
++ iounmap(rfbi.base);
++}
++
++/* struct omap_display support */
++static int rfbi_display_update(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ int rfbi_module;
++
++ if (w == 0 || h == 0)
++ return 0;
++
++ rfbi_module = rfbi_find_display(display);
++
++ rfbi_push_update(rfbi_module, x, y, w, h);
++
++ return 0;
++}
++
++static int rfbi_display_sync(struct omap_display *display)
++{
++ struct completion sync_comp;
++ int rfbi_module;
++
++ rfbi_module = rfbi_find_display(display);
++
++ init_completion(&sync_comp);
++ rfbi_push_sync(rfbi_module, &sync_comp);
++ DSSDBG("Waiting for SYNC to happen...\n");
++ wait_for_completion(&sync_comp);
++ DSSDBG("Released from SYNC\n");
++ return 0;
++}
++
++static int rfbi_display_enable_te(struct omap_display *display, bool enable)
++{
++ display->ctrl->enable_te(display, enable);
++ return 0;
++}
++
++static int rfbi_display_enable(struct omap_display *display)
++{
++ int r;
++
++ BUG_ON(display->panel == NULL || display->ctrl == NULL);
++
++ r = omap_dispc_register_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++ if (r) {
++ DSSERR("can't get FRAMEDONE irq\n");
++ return r;
++ }
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
++
++ dispc_set_tft_data_lines(display->ctrl->pixel_size);
++
++ rfbi_configure(display->hw_config.u.rfbi.channel,
++ display->ctrl->pixel_size,
++ display->hw_config.u.rfbi.data_lines);
++
++ rfbi_set_timings(display->hw_config.u.rfbi.channel,
++ &display->ctrl->timings);
++
++
++ if (display->ctrl && display->ctrl->enable) {
++ r = display->ctrl->enable(display);
++ if (r)
++ goto err;
++ }
++
++ if (display->panel && display->panel->enable) {
++ r = display->panel->enable(display);
++ if (r)
++ goto err;
++ }
++
++ return 0;
++err:
++ return -ENODEV;
++}
++
++static void rfbi_display_disable(struct omap_display *display)
++{
++ display->ctrl->disable(display);
++ omap_dispc_unregister_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++}
++
++void rfbi_init_display(struct omap_display *display)
++{
++ display->enable = rfbi_display_enable;
++ display->disable = rfbi_display_disable;
++ display->update = rfbi_display_update;
++ display->sync = rfbi_display_sync;
++ display->enable_te = rfbi_display_enable_te;
++
++ rfbi.display[display->hw_config.u.rfbi.channel] = display;
++
++ display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++}
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+new file mode 100644
+index 0000000..fbff2b2
+--- /dev/null
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -0,0 +1,245 @@
++/*
++ * linux/drivers/video/omap2/dss/sdi.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "SDI"
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++
++#include <mach/board.h>
++#include <mach/display.h>
++#include "dss.h"
++
++
++static struct {
++ bool skip_init;
++ bool update_enabled;
++} sdi;
++
++static void sdi_basic_init(void)
++{
++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
++
++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
++ dispc_set_tft_data_lines(24);
++ dispc_lcd_enable_signal_polarity(1);
++}
++
++static int sdi_display_enable(struct omap_display *display)
++{
++ struct dispc_clock_info cinfo;
++ u16 lck_div, pck_div;
++ unsigned long fck;
++ struct omap_panel *panel = display->panel;
++ unsigned long pck;
++ int r;
++
++ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("display already enabled\n");
++ return -EINVAL;
++ }
++
++ /* In case of skip_init sdi_init has already enabled the clocks */
++ if (!sdi.skip_init)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ sdi_basic_init();
++
++ /* 15.5.9.1.2 */
++ panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
++
++ dispc_set_pol_freq(panel);
++
++ if (!sdi.skip_init)
++ r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
++ &cinfo);
++ else
++ r = dispc_get_clock_div(&cinfo);
++
++ if (r)
++ goto err0;
++
++ fck = cinfo.fck;
++ lck_div = cinfo.lck_div;
++ pck_div = cinfo.pck_div;
++
++ pck = fck / lck_div / pck_div / 1000;
++
++ if (pck != panel->timings.pixel_clock) {
++ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
++ "got %lu kHz\n",
++ panel->timings.pixel_clock, pck);
++
++ panel->timings.pixel_clock = pck;
++ }
++
++
++ dispc_set_lcd_timings(&panel->timings);
++
++ r = dispc_set_clock_div(&cinfo);
++ if (r)
++ goto err1;
++
++ if (!sdi.skip_init) {
++ dss_sdi_init(display->hw_config.u.sdi.datapairs);
++ dss_sdi_enable();
++ mdelay(2);
++ }
++
++ dispc_enable_lcd_out(1);
++
++ r = panel->enable(display);
++ if (r)
++ goto err2;
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ sdi.skip_init = 0;
++
++ return 0;
++err2:
++ dispc_enable_lcd_out(0);
++err1:
++err0:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return r;
++}
++
++static int sdi_display_resume(struct omap_display *display);
++
++static void sdi_display_disable(struct omap_display *display)
++{
++ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ return;
++
++ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ sdi_display_resume(display);
++
++ display->panel->disable(display);
++
++ dispc_enable_lcd_out(0);
++
++ dss_sdi_disable();
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++}
++
++static int sdi_display_suspend(struct omap_display *display)
++{
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ return -EINVAL;
++
++ if (display->panel->suspend)
++ display->panel->suspend(display);
++
++ dispc_enable_lcd_out(0);
++
++ dss_sdi_disable();
++
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ return 0;
++}
++
++static int sdi_display_resume(struct omap_display *display)
++{
++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ return -EINVAL;
++
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
++ dss_sdi_enable();
++ mdelay(2);
++
++ dispc_enable_lcd_out(1);
++
++ if (display->panel->resume)
++ display->panel->resume(display);
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ return 0;
++}
++
++static int sdi_display_set_update_mode(struct omap_display *display,
++ enum omap_dss_update_mode mode)
++{
++ if (mode == OMAP_DSS_UPDATE_MANUAL)
++ return -EINVAL;
++
++ if (mode == OMAP_DSS_UPDATE_DISABLED) {
++ dispc_enable_lcd_out(0);
++ sdi.update_enabled = 0;
++ } else {
++ dispc_enable_lcd_out(1);
++ sdi.update_enabled = 1;
++ }
++
++ return 0;
++}
++
++static enum omap_dss_update_mode sdi_display_get_update_mode(
++ struct omap_display *display)
++{
++ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
++ OMAP_DSS_UPDATE_DISABLED;
++}
++
++static void sdi_get_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ *timings = display->panel->timings;
++}
++
++void sdi_init_display(struct omap_display *display)
++{
++ DSSDBG("SDI init\n");
++
++ display->enable = sdi_display_enable;
++ display->disable = sdi_display_disable;
++ display->suspend = sdi_display_suspend;
++ display->resume = sdi_display_resume;
++ display->set_update_mode = sdi_display_set_update_mode;
++ display->get_update_mode = sdi_display_get_update_mode;
++ display->get_timings = sdi_get_timings;
++}
++
++int sdi_init(bool skip_init)
++{
++ /* we store this for first display enable, then clear it */
++ sdi.skip_init = skip_init;
++
++ /*
++ * Enable clocks already here, otherwise there would be a toggle
++ * of them until sdi_display_enable is called.
++ */
++ if (skip_init)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ return 0;
++}
++
++void sdi_exit(void)
++{
++}
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+new file mode 100644
+index 0000000..aceed9f
+--- /dev/null
++++ b/drivers/video/omap2/dss/venc.c
+@@ -0,0 +1,600 @@
++/*
++ * linux/drivers/video/omap2/dss/venc.c
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * VENC settings from TI's DSS driver
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#define DSS_SUBSYS_NAME "VENC"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++
++#include <mach/display.h>
++#include <mach/cpu.h>
++
++#include "dss.h"
++
++#define VENC_BASE 0x48050C00
++
++/* Venc registers */
++#define VENC_REV_ID 0x00
++#define VENC_STATUS 0x04
++#define VENC_F_CONTROL 0x08
++#define VENC_VIDOUT_CTRL 0x10
++#define VENC_SYNC_CTRL 0x14
++#define VENC_LLEN 0x1C
++#define VENC_FLENS 0x20
++#define VENC_HFLTR_CTRL 0x24
++#define VENC_CC_CARR_WSS_CARR 0x28
++#define VENC_C_PHASE 0x2C
++#define VENC_GAIN_U 0x30
++#define VENC_GAIN_V 0x34
++#define VENC_GAIN_Y 0x38
++#define VENC_BLACK_LEVEL 0x3C
++#define VENC_BLANK_LEVEL 0x40
++#define VENC_X_COLOR 0x44
++#define VENC_M_CONTROL 0x48
++#define VENC_BSTAMP_WSS_DATA 0x4C
++#define VENC_S_CARR 0x50
++#define VENC_LINE21 0x54
++#define VENC_LN_SEL 0x58
++#define VENC_L21__WC_CTL 0x5C
++#define VENC_HTRIGGER_VTRIGGER 0x60
++#define VENC_SAVID__EAVID 0x64
++#define VENC_FLEN__FAL 0x68
++#define VENC_LAL__PHASE_RESET 0x6C
++#define VENC_HS_INT_START_STOP_X 0x70
++#define VENC_HS_EXT_START_STOP_X 0x74
++#define VENC_VS_INT_START_X 0x78
++#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
++#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
++#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
++#define VENC_VS_EXT_STOP_Y 0x88
++#define VENC_AVID_START_STOP_X 0x90
++#define VENC_AVID_START_STOP_Y 0x94
++#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
++#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
++#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
++#define VENC_TVDETGP_INT_START_STOP_X 0xB0
++#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
++#define VENC_GEN_CTRL 0xB8
++#define VENC_OUTPUT_CONTROL 0xC4
++#define VENC_DAC_B__DAC_C 0xC8
++
++struct venc_config {
++ u32 f_control;
++ u32 vidout_ctrl;
++ u32 sync_ctrl;
++ u32 llen;
++ u32 flens;
++ u32 hfltr_ctrl;
++ u32 cc_carr_wss_carr;
++ u32 c_phase;
++ u32 gain_u;
++ u32 gain_v;
++ u32 gain_y;
++ u32 black_level;
++ u32 blank_level;
++ u32 x_color;
++ u32 m_control;
++ u32 bstamp_wss_data;
++ u32 s_carr;
++ u32 line21;
++ u32 ln_sel;
++ u32 l21__wc_ctl;
++ u32 htrigger_vtrigger;
++ u32 savid__eavid;
++ u32 flen__fal;
++ u32 lal__phase_reset;
++ u32 hs_int_start_stop_x;
++ u32 hs_ext_start_stop_x;
++ u32 vs_int_start_x;
++ u32 vs_int_stop_x__vs_int_start_y;
++ u32 vs_int_stop_y__vs_ext_start_x;
++ u32 vs_ext_stop_x__vs_ext_start_y;
++ u32 vs_ext_stop_y;
++ u32 avid_start_stop_x;
++ u32 avid_start_stop_y;
++ u32 fid_int_start_x__fid_int_start_y;
++ u32 fid_int_offset_y__fid_ext_start_x;
++ u32 fid_ext_start_y__fid_ext_offset_y;
++ u32 tvdetgp_int_start_stop_x;
++ u32 tvdetgp_int_start_stop_y;
++ u32 gen_ctrl;
++};
++
++/* from TRM */
++static const struct venc_config venc_config_pal_trm = {
++ .f_control = 0,
++ .vidout_ctrl = 1,
++ .sync_ctrl = 0x40,
++ .llen = 0x35F, /* 863 */
++ .flens = 0x270, /* 624 */
++ .hfltr_ctrl = 0,
++ .cc_carr_wss_carr = 0x2F7225ED,
++ .c_phase = 0,
++ .gain_u = 0x111,
++ .gain_v = 0x181,
++ .gain_y = 0x140,
++ .black_level = 0x3B,
++ .blank_level = 0x3B,
++ .x_color = 0x7,
++ .m_control = 0x2,
++ .bstamp_wss_data = 0x3F,
++ .s_carr = 0x2A098ACB,
++ .line21 = 0,
++ .ln_sel = 0x01290015,
++ .l21__wc_ctl = 0x0000F603,
++ .htrigger_vtrigger = 0,
++
++ .savid__eavid = 0x06A70108,
++ .flen__fal = 0x00180270,
++ .lal__phase_reset = 0x00040135,
++ .hs_int_start_stop_x = 0x00880358,
++ .hs_ext_start_stop_x = 0x000F035F,
++ .vs_int_start_x = 0x01A70000,
++ .vs_int_stop_x__vs_int_start_y = 0x000001A7,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
++ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
++ .vs_ext_stop_y = 0x00000025,
++ .avid_start_stop_x = 0x03530083,
++ .avid_start_stop_y = 0x026C002E,
++ .fid_int_start_x__fid_int_start_y = 0x0001008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
++
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00FF0000,
++};
++
++/* from TRM */
++static const struct venc_config venc_config_ntsc_trm = {
++ .f_control = 0,
++ .vidout_ctrl = 1,
++ .sync_ctrl = 0x8040,
++ .llen = 0x359,
++ .flens = 0x20C,
++ .hfltr_ctrl = 0,
++ .cc_carr_wss_carr = 0x043F2631,
++ .c_phase = 0,
++ .gain_u = 0x102,
++ .gain_v = 0x16C,
++ .gain_y = 0x12F,
++ .black_level = 0x43,
++ .blank_level = 0x38,
++ .x_color = 0x7,
++ .m_control = 0x1,
++ .bstamp_wss_data = 0x38,
++ .s_carr = 0x21F07C1F,
++ .line21 = 0,
++ .ln_sel = 0x01310011,
++ .l21__wc_ctl = 0x0000F003,
++ .htrigger_vtrigger = 0,
++
++ .savid__eavid = 0x069300F4,
++ .flen__fal = 0x0016020C,
++ .lal__phase_reset = 0x00060107,
++ .hs_int_start_stop_x = 0x008E0350,
++ .hs_ext_start_stop_x = 0x000F0359,
++ .vs_int_start_x = 0x01A00000,
++ .vs_int_stop_x__vs_int_start_y = 0x020701A0,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
++ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
++ .vs_ext_stop_y = 0x00000006,
++ .avid_start_stop_x = 0x03480078,
++ .avid_start_stop_y = 0x02060024,
++ .fid_int_start_x__fid_int_start_y = 0x0001008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
++
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00F90000,
++};
++
++static const struct venc_config venc_config_pal_bdghi = {
++ .f_control = 0,
++ .vidout_ctrl = 0,
++ .sync_ctrl = 0,
++ .hfltr_ctrl = 0,
++ .x_color = 0,
++ .line21 = 0,
++ .ln_sel = 21,
++ .htrigger_vtrigger = 0,
++ .tvdetgp_int_start_stop_x = 0x00140001,
++ .tvdetgp_int_start_stop_y = 0x00010001,
++ .gen_ctrl = 0x00FB0000,
++
++ .llen = 864-1,
++ .flens = 625-1,
++ .cc_carr_wss_carr = 0x2F7625ED,
++ .c_phase = 0xDF,
++ .gain_u = 0x111,
++ .gain_v = 0x181,
++ .gain_y = 0x140,
++ .black_level = 0x3e,
++ .blank_level = 0x3e,
++ .m_control = 0<<2 | 1<<1,
++ .bstamp_wss_data = 0x42,
++ .s_carr = 0x2a098acb,
++ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
++ .savid__eavid = 0x06A70108,
++ .flen__fal = 23<<16 | 624<<0,
++ .lal__phase_reset = 2<<17 | 310<<0,
++ .hs_int_start_stop_x = 0x00920358,
++ .hs_ext_start_stop_x = 0x000F035F,
++ .vs_int_start_x = 0x1a7<<16,
++ .vs_int_stop_x__vs_int_start_y = 0x000601A7,
++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
++ .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
++ .vs_ext_stop_y = 0x05,
++ .avid_start_stop_x = 0x03530082,
++ .avid_start_stop_y = 0x0270002E,
++ .fid_int_start_x__fid_int_start_y = 0x0005008A,
++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
++ .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
++};
++
++const struct omap_video_timings omap_dss_pal_timings = {
++ .x_res = 720,
++ .y_res = 574,
++ .pixel_clock = 26181,
++ .hsw = 32,
++ .hfp = 80,
++ .hbp = 48,
++ .vsw = 7,
++ .vfp = 3,
++ .vbp = 6,
++};
++EXPORT_SYMBOL(omap_dss_pal_timings);
++
++const struct omap_video_timings omap_dss_ntsc_timings = {
++ .x_res = 720,
++ .y_res = 482,
++ .pixel_clock = 22153,
++ .hsw = 32,
++ .hfp = 80,
++ .hbp = 48,
++ .vsw = 10,
++ .vfp = 3,
++ .vbp = 6,
++};
++EXPORT_SYMBOL(omap_dss_ntsc_timings);
++
++static struct {
++ void __iomem *base;
++ struct mutex venc_lock;
++} venc;
++
++static struct omap_panel venc_panel = {
++ .name = "tv-out",
++};
++
++static inline void venc_write_reg(int idx, u32 val)
++{
++ __raw_writel(val, venc.base + idx);
++}
++
++static inline u32 venc_read_reg(int idx)
++{
++ u32 l = __raw_readl(venc.base + idx);
++ return l;
++}
++
++static void venc_write_config(const struct venc_config *config)
++{
++ DSSDBG("write venc conf\n");
++
++ venc_write_reg(VENC_LLEN, config->llen);
++ venc_write_reg(VENC_FLENS, config->flens);
++ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
++ venc_write_reg(VENC_C_PHASE, config->c_phase);
++ venc_write_reg(VENC_GAIN_U, config->gain_u);
++ venc_write_reg(VENC_GAIN_V, config->gain_v);
++ venc_write_reg(VENC_GAIN_Y, config->gain_y);
++ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
++ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
++ venc_write_reg(VENC_M_CONTROL, config->m_control);
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data);
++ venc_write_reg(VENC_S_CARR, config->s_carr);
++ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
++ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
++ venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
++ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
++ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
++ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
++ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
++ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
++ config->vs_int_stop_x__vs_int_start_y);
++ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
++ config->vs_int_stop_y__vs_ext_start_x);
++ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
++ config->vs_ext_stop_x__vs_ext_start_y);
++ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
++ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
++ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
++ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
++ config->fid_int_start_x__fid_int_start_y);
++ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
++ config->fid_int_offset_y__fid_ext_start_x);
++ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
++ config->fid_ext_start_y__fid_ext_offset_y);
++
++ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
++ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
++ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
++ venc_write_reg(VENC_X_COLOR, config->x_color);
++ venc_write_reg(VENC_LINE21, config->line21);
++ venc_write_reg(VENC_LN_SEL, config->ln_sel);
++ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
++ config->tvdetgp_int_start_stop_x);
++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
++ config->tvdetgp_int_start_stop_y);
++ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
++ venc_write_reg(VENC_F_CONTROL, config->f_control);
++ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
++}
++
++static void venc_reset(void)
++{
++ int t = 1000;
++
++ venc_write_reg(VENC_F_CONTROL, 1<<8);
++ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
++ if (--t == 0) {
++ DSSERR("Failed to reset venc\n");
++ return;
++ }
++ }
++
++ /* the magical sleep that makes things work */
++ msleep(20);
++}
++
++static void venc_enable_clocks(int enable)
++{
++ if (enable)
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++ DSS_CLK_96M);
++ else
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
++ DSS_CLK_96M);
++}
++
++static const struct venc_config *venc_timings_to_config(
++ struct omap_video_timings *timings)
++{
++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
++ return &venc_config_pal_trm;
++
++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
++ return &venc_config_ntsc_trm;
++
++ BUG();
++}
++
++int venc_init(void)
++{
++ u8 rev_id;
++
++ mutex_init(&venc.venc_lock);
++
++ venc_panel.timings = omap_dss_pal_timings;
++
++ venc.base = ioremap(VENC_BASE, SZ_1K);
++ if (!venc.base) {
++ DSSERR("can't ioremap VENC\n");
++ return -ENOMEM;
++ }
++
++ venc_enable_clocks(1);
++
++ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
++ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
++
++ venc_enable_clocks(0);
++
++ return 0;
++}
++
++void venc_exit(void)
++{
++ iounmap(venc.base);
++}
++
++static void venc_power_on(struct omap_display *display)
++{
++ venc_enable_clocks(1);
++
++ venc_reset();
++ venc_write_config(venc_timings_to_config(&display->panel->timings));
++
++ dss_set_venc_output(display->hw_config.u.venc.type);
++ dss_set_dac_pwrdn_bgz(1);
++
++ if (display->hw_config.u.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
++ if (cpu_is_omap24xx())
++ venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
++ else
++ venc_write_reg(VENC_OUTPUT_CONTROL, 0xa);
++ } else { /* S-Video */
++ venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
++ }
++
++ dispc_set_digit_size(display->panel->timings.x_res,
++ display->panel->timings.y_res/2);
++
++ if (display->hw_config.panel_enable)
++ display->hw_config.panel_enable(display);
++
++ dispc_enable_digit_out(1);
++}
++
++static void venc_power_off(struct omap_display *display)
++{
++ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
++ dss_set_dac_pwrdn_bgz(0);
++
++ dispc_enable_digit_out(0);
++
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++
++ venc_enable_clocks(0);
++}
++
++static int venc_enable_display(struct omap_display *display)
++{
++ int r = 0;
++
++ DSSDBG("venc_enable_display\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_on(display);
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static void venc_disable_display(struct omap_display *display)
++{
++ DSSDBG("venc_disable_display\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ goto end;
++
++ if (display->state == OMAP_DSS_DISPLAY_SUSPENDED) {
++ /* suspended is the same as disabled with venc */
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++ goto end;
++ }
++
++ venc_power_off(display);
++
++ display->state = OMAP_DSS_DISPLAY_DISABLED;
++end:
++ mutex_unlock(&venc.venc_lock);
++}
++
++static int venc_display_suspend(struct omap_display *display)
++{
++ int r = 0;
++
++ DSSDBG("venc_display_suspend\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_off(display);
++
++ display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static int venc_display_resume(struct omap_display *display)
++{
++ int r = 0;
++
++ DSSDBG("venc_display_resume\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ venc_power_on(display);
++
++ display->state = OMAP_DSS_DISPLAY_ACTIVE;
++err:
++ mutex_unlock(&venc.venc_lock);
++
++ return r;
++}
++
++static void venc_get_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ *timings = venc_panel.timings;
++}
++
++static void venc_set_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("venc_set_timings\n");
++ display->panel->timings = *timings;
++ if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ /* turn the venc off and on to get new timings to use */
++ venc_disable_display(display);
++ venc_enable_display(display);
++ }
++}
++
++static int venc_check_timings(struct omap_display *display,
++ struct omap_video_timings *timings)
++{
++ DSSDBG("venc_check_timings\n");
++
++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
++ return 0;
++
++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
++ return 0;
++
++ return -EINVAL;
++}
++
++void venc_init_display(struct omap_display *display)
++{
++ display->panel = &venc_panel;
++ display->enable = venc_enable_display;
++ display->disable = venc_disable_display;
++ display->suspend = venc_display_suspend;
++ display->resume = venc_display_resume;
++ display->get_timings = venc_get_timings;
++ display->set_timings = venc_set_timings;
++ display->check_timings = venc_check_timings;
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP-framebuffer-driver.patch b/recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP-framebuffer-driver.patch
new file mode 100644
index 0000000000..994bd23b82
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0003-DSS2-OMAP-framebuffer-driver.patch
@@ -0,0 +1,3403 @@
+From 0612cfdea0354b6c8b2deacbcd805427fb3b4c1f Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 10:25:48 +0300
+Subject: [PATCH 003/146] DSS2: OMAP framebuffer driver
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/fb.c | 28 +
+ drivers/video/omap/Kconfig | 5 +-
+ drivers/video/omap2/omapfb/Kconfig | 35 +
+ drivers/video/omap2/omapfb/Makefile | 2 +
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 656 ++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c | 2010 +++++++++++++++++++++++++++++
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 371 ++++++
+ drivers/video/omap2/omapfb/omapfb.h | 153 +++
+ include/linux/omapfb.h | 20 +
+ 9 files changed, 3278 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/video/omap2/omapfb/Kconfig
+ create mode 100644 drivers/video/omap2/omapfb/Makefile
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-ioctl.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-main.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb-sysfs.c
+ create mode 100644 drivers/video/omap2/omapfb/omapfb.h
+
+diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
+index 40615a6..1dc3415 100644
+--- a/arch/arm/plat-omap/fb.c
++++ b/arch/arm/plat-omap/fb.c
+@@ -327,6 +327,34 @@ static inline int omap_init_fb(void)
+
+ arch_initcall(omap_init_fb);
+
++#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
++
++static u64 omap_fb_dma_mask = ~(u32)0;
++static struct omapfb_platform_data omapfb_config;
++
++static struct platform_device omap_fb_device = {
++ .name = "omapfb",
++ .id = -1,
++ .dev = {
++ .dma_mask = &omap_fb_dma_mask,
++ .coherent_dma_mask = ~(u32)0,
++ .platform_data = &omapfb_config,
++ },
++ .num_resources = 0,
++};
++
++void omapfb_set_platform_data(struct omapfb_platform_data *data)
++{
++ omapfb_config = *data;
++}
++
++static inline int omap_init_fb(void)
++{
++ return platform_device_register(&omap_fb_device);
++}
++
++arch_initcall(omap_init_fb);
++
+ #else
+
+ void omapfb_reserve_sdram(void) {}
+diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
+index 551e3e9..455c605 100644
+--- a/drivers/video/omap/Kconfig
++++ b/drivers/video/omap/Kconfig
+@@ -1,6 +1,7 @@
+ config FB_OMAP
+ tristate "OMAP frame buffer support (EXPERIMENTAL)"
+- depends on FB && ARCH_OMAP
++ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
++
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+@@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID
+
+ config FB_OMAP_BOOTLOADER_INIT
+ bool "Check bootloader initialization"
+- depends on FB_OMAP
++ depends on FB_OMAP || FB_OMAP2
+ help
+ Say Y here if you want to enable checking if the bootloader has
+ already initialized the display controller. In this case the
+diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
+new file mode 100644
+index 0000000..4f66033
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/Kconfig
+@@ -0,0 +1,35 @@
++menuconfig FB_OMAP2
++ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
++ depends on FB && OMAP2_DSS
++
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ help
++ Frame buffer driver for OMAP2/3 based boards.
++
++config FB_OMAP2_DEBUG_SUPPORT
++ bool "Debug support for OMAP2/3 FB"
++ default y
++ depends on FB_OMAP2
++ help
++ Support for debug output. You have to enable the actual printing
++ with debug module parameter.
++
++config FB_OMAP2_FORCE_AUTO_UPDATE
++ bool "Force main display to automatic update mode"
++ depends on FB_OMAP2
++ help
++ Forces main display to automatic update mode (if possible),
++ and also enables tearsync (if possible). By default
++ displays that support manual update are started in manual
++ update mode.
++
++config FB_OMAP2_NUM_FBS
++ int "Number of framebuffers"
++ range 1 10
++ default 3
++ depends on FB_OMAP2
++ help
++ Select the number of framebuffers created. OMAP2/3 has 3 overlays
++ so normally this would be 3.
+diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
+new file mode 100644
+index 0000000..51c2e00
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_FB_OMAP2) += omapfb.o
++omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+new file mode 100644
+index 0000000..7f18d2a
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -0,0 +1,656 @@
++/*
++ * linux/drivers/video/omap2/omapfb-ioctl.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/fb.h>
++#include <linux/device.h>
++#include <linux/uaccess.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/omapfb.h>
++#include <linux/vmalloc.h>
++
++#include <mach/display.h>
++#include <mach/vrfb.h>
++
++#include "omapfb.h"
++
++static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ struct omap_overlay *ovl;
++ struct omap_overlay_info info;
++ int r = 0;
++
++ DBG("omapfb_setup_plane\n");
++
++ omapfb_lock(fbdev);
++
++ if (ofbi->num_overlays != 1) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ /* XXX uses only the first overlay */
++ ovl = ofbi->overlays[0];
++
++ if (pi->enabled && !ofbi->region.size) {
++ /*
++ * This plane's memory was freed, can't enable it
++ * until it's reallocated.
++ */
++ r = -EINVAL;
++ goto out;
++ }
++
++ ovl->get_overlay_info(ovl, &info);
++
++ info.pos_x = pi->pos_x;
++ info.pos_y = pi->pos_y;
++ info.out_width = pi->out_width;
++ info.out_height = pi->out_height;
++ info.enabled = pi->enabled;
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
++ goto out;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ goto out;
++ }
++
++ if (display) {
++ u16 w, h;
++
++ if (display->sync)
++ display->sync(display);
++
++ display->get_resolution(display, &w, &h);
++
++ if (display->update)
++ display->update(display, 0, 0, w, h);
++ }
++
++out:
++ omapfb_unlock(fbdev);
++ if (r)
++ dev_err(fbdev->dev, "setup_plane failed\n");
++ return r;
++}
++
++static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++
++ omapfb_lock(fbdev);
++
++ if (ofbi->num_overlays != 1) {
++ memset(pi, 0, sizeof(*pi));
++ } else {
++ struct omap_overlay_info *ovli;
++ struct omap_overlay *ovl;
++
++ ovl = ofbi->overlays[0];
++ ovli = &ovl->info;
++
++ pi->pos_x = ovli->pos_x;
++ pi->pos_y = ovli->pos_y;
++ pi->enabled = ovli->enabled;
++ pi->channel_out = 0; /* xxx */
++ pi->mirror = 0;
++ pi->out_width = ovli->out_width;
++ pi->out_height = ovli->out_height;
++ }
++
++ omapfb_unlock(fbdev);
++
++ return 0;
++}
++
++static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++ int r, i;
++ size_t size;
++
++ if (mi->type > OMAPFB_MEMTYPE_MAX)
++ return -EINVAL;
++
++ size = PAGE_ALIGN(mi->size);
++
++ rg = &ofbi->region;
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->info.enabled) {
++ r = -EBUSY;
++ goto out;
++ }
++ }
++
++ if (rg->size != size || rg->type != mi->type) {
++ r = omapfb_realloc_fbmem(fbi, size, mi->type);
++ if (r) {
++ dev_err(fbdev->dev, "realloc fbmem failed\n");
++ goto out;
++ }
++ }
++
++ r = 0;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++
++ rg = &ofbi->region;
++ memset(mi, 0, sizeof(*mi));
++
++ omapfb_lock(fbdev);
++ mi->size = rg->size;
++ mi->type = rg->type;
++ omapfb_unlock(fbdev);
++
++ return 0;
++}
++
++static int omapfb_update_window(struct fb_info *fbi,
++ u32 x, u32 y, u32 w, u32 h)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ u16 dw, dh;
++
++ if (!display)
++ return 0;
++
++ if (w == 0 || h == 0)
++ return 0;
++
++ display->get_resolution(display, &dw, &dh);
++
++ if (x + w > dw || y + h > dh)
++ return -EINVAL;
++
++ omapfb_lock(fbdev);
++ display->update(display, x, y, w, h);
++ omapfb_unlock(fbdev);
++
++ return 0;
++}
++
++static int omapfb_set_update_mode(struct fb_info *fbi,
++ enum omapfb_update_mode mode)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ enum omap_dss_update_mode um;
++ int r;
++
++ if (!display || !display->set_update_mode)
++ return -EINVAL;
++
++ switch (mode) {
++ case OMAPFB_UPDATE_DISABLED:
++ um = OMAP_DSS_UPDATE_DISABLED;
++ break;
++
++ case OMAPFB_AUTO_UPDATE:
++ um = OMAP_DSS_UPDATE_AUTO;
++ break;
++
++ case OMAPFB_MANUAL_UPDATE:
++ um = OMAP_DSS_UPDATE_MANUAL;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ omapfb_lock(fbdev);
++ r = display->set_update_mode(display, um);
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_get_update_mode(struct fb_info *fbi,
++ enum omapfb_update_mode *mode)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ enum omap_dss_update_mode m;
++
++ if (!display || !display->get_update_mode)
++ return -EINVAL;
++
++ omapfb_lock(fbdev);
++ m = display->get_update_mode(display);
++ omapfb_unlock(fbdev);
++
++ switch (m) {
++ case OMAP_DSS_UPDATE_DISABLED:
++ *mode = OMAPFB_UPDATE_DISABLED;
++ break;
++ case OMAP_DSS_UPDATE_AUTO:
++ *mode = OMAPFB_AUTO_UPDATE;
++ break;
++ case OMAP_DSS_UPDATE_MANUAL:
++ *mode = OMAPFB_MANUAL_UPDATE;
++ break;
++ default:
++ BUG();
++ }
++
++ return 0;
++}
++
++/* XXX this color key handling is a hack... */
++static struct omapfb_color_key omapfb_color_keys[2];
++
++static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
++ struct omapfb_color_key *ck)
++{
++ enum omap_dss_color_key_type kt;
++
++ if(!mgr->set_default_color || !mgr->set_trans_key ||
++ !mgr->enable_trans_key)
++ return 0;
++
++ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
++ mgr->enable_trans_key(mgr, 0);
++ omapfb_color_keys[mgr->id] = *ck;
++ return 0;
++ }
++
++ switch(ck->key_type) {
++ case OMAPFB_COLOR_KEY_GFX_DST:
++ kt = OMAP_DSS_COLOR_KEY_GFX_DST;
++ break;
++ case OMAPFB_COLOR_KEY_VID_SRC:
++ kt = OMAP_DSS_COLOR_KEY_VID_SRC;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ mgr->set_default_color(mgr, ck->background);
++ mgr->set_trans_key(mgr, kt, ck->trans_key);
++ mgr->enable_trans_key(mgr, 1);
++
++ omapfb_color_keys[mgr->id] = *ck;
++
++ return 0;
++}
++
++static int omapfb_set_color_key(struct fb_info *fbi,
++ struct omapfb_color_key *ck)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ int r;
++ int i;
++ struct omap_overlay_manager *mgr = NULL;
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager) {
++ mgr = ofbi->overlays[i]->manager;
++ break;
++ }
++ }
++
++ if (!mgr) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ if(!mgr->set_default_color || !mgr->set_trans_key ||
++ !mgr->enable_trans_key) {
++ r = -ENODEV;
++ goto err;
++ }
++
++ r = _omapfb_set_color_key(mgr, ck);
++err:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_get_color_key(struct fb_info *fbi,
++ struct omapfb_color_key *ck)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_overlay_manager *mgr = NULL;
++ int r = 0;
++ int i;
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager) {
++ mgr = ofbi->overlays[i]->manager;
++ break;
++ }
++ }
++
++ if (!mgr) {
++ r = -EINVAL;
++ goto err;
++ }
++
++ if(!mgr->set_default_color || !mgr->set_trans_key ||
++ !mgr->enable_trans_key) {
++ r = -ENODEV;
++ goto err;
++ }
++
++ *ck = omapfb_color_keys[mgr->id];
++err:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static int omapfb_memory_read(struct fb_info *fbi,
++ struct omapfb_memory_read *mr)
++{
++ struct omap_display *display = fb2display(fbi);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ void *buf;
++ int r;
++
++ if (!display || !display->memory_read)
++ return -ENOENT;
++
++ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
++ return -EFAULT;
++
++ if (mr->w * mr->h * 3 > mr->buffer_size)
++ return -EINVAL;
++
++ buf = vmalloc(mr->buffer_size);
++ if (!buf) {
++ DBG("vmalloc failed\n");
++ return -ENOMEM;
++ }
++
++ omapfb_lock(fbdev);
++
++ r = display->memory_read(display, buf, mr->buffer_size,
++ mr->x, mr->y, mr->w, mr->h);
++
++ if (r > 0) {
++ if (copy_to_user(mr->buffer, buf, mr->buffer_size))
++ r = -EFAULT;
++ }
++
++ vfree(buf);
++
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++
++ union {
++ struct omapfb_update_window_old uwnd_o;
++ struct omapfb_update_window uwnd;
++ struct omapfb_plane_info plane_info;
++ struct omapfb_caps caps;
++ struct omapfb_mem_info mem_info;
++ struct omapfb_color_key color_key;
++ enum omapfb_update_mode update_mode;
++ int test_num;
++ struct omapfb_memory_read memory_read;
++ } p;
++
++ int r = 0;
++
++ switch (cmd) {
++ case OMAPFB_SYNC_GFX:
++ DBG("ioctl SYNC_GFX\n");
++ if (!display || !display->sync) {
++ /* DSS1 never returns an error here, so we neither */
++ /*r = -EINVAL;*/
++ break;
++ }
++
++ omapfb_lock(fbdev);
++ r = display->sync(display);
++ omapfb_unlock(fbdev);
++ break;
++
++ case OMAPFB_UPDATE_WINDOW_OLD:
++ DBG("ioctl UPDATE_WINDOW_OLD\n");
++ if (!display || !display->update) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&p.uwnd_o,
++ (void __user *)arg,
++ sizeof(p.uwnd_o))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
++ p.uwnd_o.width, p.uwnd_o.height);
++ break;
++
++ case OMAPFB_UPDATE_WINDOW:
++ DBG("ioctl UPDATE_WINDOW\n");
++ if (!display || !display->update) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&p.uwnd, (void __user *)arg,
++ sizeof(p.uwnd))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
++ p.uwnd.width, p.uwnd.height);
++ break;
++
++ case OMAPFB_SETUP_PLANE:
++ DBG("ioctl SETUP_PLANE\n");
++ if (copy_from_user(&p.plane_info, (void __user *)arg,
++ sizeof(p.plane_info)))
++ r = -EFAULT;
++ else
++ r = omapfb_setup_plane(fbi, &p.plane_info);
++ break;
++
++ case OMAPFB_QUERY_PLANE:
++ DBG("ioctl QUERY_PLANE\n");
++ r = omapfb_query_plane(fbi, &p.plane_info);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.plane_info,
++ sizeof(p.plane_info)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SETUP_MEM:
++ DBG("ioctl SETUP_MEM\n");
++ if (copy_from_user(&p.mem_info, (void __user *)arg,
++ sizeof(p.mem_info)))
++ r = -EFAULT;
++ else
++ r = omapfb_setup_mem(fbi, &p.mem_info);
++ break;
++
++ case OMAPFB_QUERY_MEM:
++ DBG("ioctl QUERY_MEM\n");
++ r = omapfb_query_mem(fbi, &p.mem_info);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.mem_info,
++ sizeof(p.mem_info)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_GET_CAPS:
++ DBG("ioctl GET_CAPS\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ p.caps.ctrl = display->caps;
++
++ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SET_UPDATE_MODE:
++ DBG("ioctl SET_UPDATE_MODE\n");
++ if (get_user(p.update_mode, (int __user *)arg))
++ r = -EFAULT;
++ else
++ r = omapfb_set_update_mode(fbi, p.update_mode);
++ break;
++
++ case OMAPFB_GET_UPDATE_MODE:
++ DBG("ioctl GET_UPDATE_MODE\n");
++ r = omapfb_get_update_mode(fbi, &p.update_mode);
++ if (r)
++ break;
++ if (put_user(p.update_mode,
++ (enum omapfb_update_mode __user *)arg))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_SET_COLOR_KEY:
++ DBG("ioctl SET_COLOR_KEY\n");
++ if (copy_from_user(&p.color_key, (void __user *)arg,
++ sizeof(p.color_key)))
++ r = -EFAULT;
++ else
++ r = omapfb_set_color_key(fbi, &p.color_key);
++ break;
++
++ case OMAPFB_GET_COLOR_KEY:
++ DBG("ioctl GET_COLOR_KEY\n");
++ if ((r = omapfb_get_color_key(fbi, &p.color_key)) < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.color_key,
++ sizeof(p.color_key)))
++ r = -EFAULT;
++ break;
++
++ case OMAPFB_WAITFORVSYNC:
++ DBG("ioctl WAITFORVSYNC\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->wait_vsync(display);
++ break;
++
++ /* LCD and CTRL tests do the same thing for backward
++ * compatibility */
++ case OMAPFB_LCD_TEST:
++ DBG("ioctl LCD_TEST\n");
++ if (get_user(p.test_num, (int __user *)arg)) {
++ r = -EFAULT;
++ break;
++ }
++ if (!display || !display->run_test) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->run_test(display, p.test_num);
++
++ break;
++
++ case OMAPFB_CTRL_TEST:
++ DBG("ioctl CTRL_TEST\n");
++ if (get_user(p.test_num, (int __user *)arg)) {
++ r = -EFAULT;
++ break;
++ }
++ if (!display || !display->run_test) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = display->run_test(display, p.test_num);
++
++ break;
++
++ case OMAPFB_MEMORY_READ:
++ DBG("ioctl MEMORY_READ\n");
++
++ if (copy_from_user(&p.memory_read, (void __user *)arg,
++ sizeof(p.memory_read))) {
++ r = -EFAULT;
++ break;
++ }
++
++ r = omapfb_memory_read(fbi, &p.memory_read);
++
++ break;
++
++ default:
++ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
++ r = -EINVAL;
++ }
++
++ if (r < 0)
++ DBG("ioctl failed: %d\n", r);
++
++ return r;
++}
++
++
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+new file mode 100644
+index 0000000..852abe5
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -0,0 +1,2010 @@
++/*
++ * linux/drivers/video/omap2/omapfb-main.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/omapfb.h>
++
++#include <mach/display.h>
++#include <mach/vram.h>
++#include <mach/vrfb.h>
++
++#include "omapfb.h"
++
++#define MODULE_NAME "omapfb"
++
++static char *def_mode;
++static char *def_vram;
++static int def_vrfb;
++static int def_rotate;
++static int def_mirror;
++
++#ifdef DEBUG
++unsigned int omapfb_debug;
++module_param_named(debug, omapfb_debug, bool, 0644);
++static unsigned int omapfb_test_pattern;
++module_param_named(test, omapfb_test_pattern, bool, 0644);
++#endif
++
++#ifdef DEBUG
++static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ void __iomem *addr = fbi->screen_base;
++ const unsigned bytespp = var->bits_per_pixel >> 3;
++ const unsigned line_len = fix->line_length / bytespp;
++
++ int r = (color >> 16) & 0xff;
++ int g = (color >> 8) & 0xff;
++ int b = (color >> 0) & 0xff;
++
++ if (var->bits_per_pixel == 16) {
++ u16 __iomem *p = (u16 __iomem *)addr;
++ p += y * line_len + x;
++
++ r = r * 32 / 256;
++ g = g * 64 / 256;
++ b = b * 32 / 256;
++
++ __raw_writew((r << 11) | (g << 5) | (b << 0), p);
++ } else if (var->bits_per_pixel == 24) {
++ u8 __iomem *p = (u8 __iomem *)addr;
++ p += (y * line_len + x) * 3;
++
++ __raw_writeb(b, p + 0);
++ __raw_writeb(g, p + 1);
++ __raw_writeb(r, p + 2);
++ } else if (var->bits_per_pixel == 32) {
++ u32 __iomem *p = (u32 __iomem *)addr;
++ p += y * line_len + x;
++ __raw_writel(color, p);
++ }
++}
++
++static void fill_fb(struct fb_info *fbi)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ const short w = var->xres_virtual;
++ const short h = var->yres_virtual;
++ void __iomem *addr = fbi->screen_base;
++ int y, x;
++
++ if (!addr)
++ return;
++
++ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
++
++ for (y = 0; y < h; y++) {
++ for (x = 0; x < w; x++) {
++ if (x < 20 && y < 20)
++ draw_pixel(fbi, x, y, 0xffffff);
++ else if (x < 20 && (y > 20 && y < h - 20))
++ draw_pixel(fbi, x, y, 0xff);
++ else if (y < 20 && (x > 20 && x < w - 20))
++ draw_pixel(fbi, x, y, 0xff00);
++ else if (x > w - 20 && (y > 20 && y < h - 20))
++ draw_pixel(fbi, x, y, 0xff0000);
++ else if (y > h - 20 && (x > 20 && x < w - 20))
++ draw_pixel(fbi, x, y, 0xffff00);
++ else if (x == 20 || x == w - 20 ||
++ y == 20 || y == h - 20)
++ draw_pixel(fbi, x, y, 0xffffff);
++ else if (x == y || w - x == h - y)
++ draw_pixel(fbi, x, y, 0xff00ff);
++ else if (w - x == y || x == h - y)
++ draw_pixel(fbi, x, y, 0x00ffff);
++ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
++ int t = x * 3 / w;
++ unsigned r = 0, g = 0, b = 0;
++ unsigned c;
++ if (var->bits_per_pixel == 16) {
++ if (t == 0)
++ b = (y % 32) * 256 / 32;
++ else if (t == 1)
++ g = (y % 64) * 256 / 64;
++ else if (t == 2)
++ r = (y % 32) * 256 / 32;
++ } else {
++ if (t == 0)
++ b = (y % 256);
++ else if (t == 1)
++ g = (y % 256);
++ else if (t == 2)
++ r = (y % 256);
++ }
++ c = (r << 16) | (g << 8) | (b << 0);
++ draw_pixel(fbi, x, y, c);
++ } else {
++ draw_pixel(fbi, x, y, 0);
++ }
++ }
++ }
++}
++#endif
++
++static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
++{
++ struct vrfb *vrfb = &ofbi->region.vrfb;
++ unsigned offset;
++
++ switch (rot) {
++ case FB_ROTATE_UR:
++ offset = 0;
++ break;
++ case FB_ROTATE_CW:
++ offset = vrfb->yoffset;
++ break;
++ case FB_ROTATE_UD:
++ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
++ break;
++ case FB_ROTATE_CCW:
++ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
++ break;
++ default:
++ BUG();
++ }
++
++ offset *= vrfb->bytespp;
++
++ return offset;
++}
++
++static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
++{
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ unsigned offset;
++ int rot;
++
++ rot = ofbi->rotation;
++
++ offset = omapfb_get_vrfb_offset(ofbi, rot);
++
++ return ofbi->region.vrfb.paddr[rot] + offset;
++ } else {
++ return ofbi->region.paddr;
++ }
++}
++
++u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
++{
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ return ofbi->region.vrfb.paddr[0];
++ else
++ return ofbi->region.paddr;
++}
++
++void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
++{
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ return ofbi->region.vrfb.vaddr[0];
++ else
++ return ofbi->region.vaddr;
++}
++
++static struct omapfb_colormode omapfb_colormodes[] = {
++ {
++ .dssmode = OMAP_DSS_COLOR_UYVY,
++ .bits_per_pixel = 16,
++ .nonstd = OMAPFB_COLOR_YUV422,
++ }, {
++ .dssmode = OMAP_DSS_COLOR_YUV2,
++ .bits_per_pixel = 16,
++ .nonstd = OMAPFB_COLOR_YUY422,
++ }, {
++ .dssmode = OMAP_DSS_COLOR_ARGB16,
++ .bits_per_pixel = 16,
++ .red = { .length = 4, .offset = 8, .msb_right = 0 },
++ .green = { .length = 4, .offset = 4, .msb_right = 0 },
++ .blue = { .length = 4, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 4, .offset = 12, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB16,
++ .bits_per_pixel = 16,
++ .red = { .length = 5, .offset = 11, .msb_right = 0 },
++ .green = { .length = 6, .offset = 5, .msb_right = 0 },
++ .blue = { .length = 5, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB24P,
++ .bits_per_pixel = 24,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGB24U,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_ARGB32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 16, .msb_right = 0 },
++ .green = { .length = 8, .offset = 8, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 0, .msb_right = 0 },
++ .transp = { .length = 8, .offset = 24, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGBA32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 24, .msb_right = 0 },
++ .green = { .length = 8, .offset = 16, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
++ .transp = { .length = 8, .offset = 0, .msb_right = 0 },
++ }, {
++ .dssmode = OMAP_DSS_COLOR_RGBX32,
++ .bits_per_pixel = 32,
++ .red = { .length = 8, .offset = 24, .msb_right = 0 },
++ .green = { .length = 8, .offset = 16, .msb_right = 0 },
++ .blue = { .length = 8, .offset = 8, .msb_right = 0 },
++ .transp = { .length = 0, .offset = 0, .msb_right = 0 },
++ },
++};
++
++static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
++ struct omapfb_colormode *color)
++{
++ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
++ {
++ return f1->length == f2->length &&
++ f1->offset == f2->offset &&
++ f1->msb_right == f2->msb_right;
++ }
++
++ if (var->bits_per_pixel == 0 ||
++ var->red.length == 0 ||
++ var->blue.length == 0 ||
++ var->green.length == 0)
++ return 0;
++
++ return var->bits_per_pixel == color->bits_per_pixel &&
++ cmp_component(&var->red, &color->red) &&
++ cmp_component(&var->green, &color->green) &&
++ cmp_component(&var->blue, &color->blue) &&
++ cmp_component(&var->transp, &color->transp);
++}
++
++static void assign_colormode_to_var(struct fb_var_screeninfo *var,
++ struct omapfb_colormode *color)
++{
++ var->bits_per_pixel = color->bits_per_pixel;
++ var->nonstd = color->nonstd;
++ var->red = color->red;
++ var->green = color->green;
++ var->blue = color->blue;
++ var->transp = color->transp;
++}
++
++static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
++{
++ enum omap_color_mode dssmode;
++ int i;
++
++ /* first match with nonstd field */
++ if (var->nonstd) {
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (var->nonstd == mode->nonstd) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ return -EINVAL;
++ }
++
++ /* then try exact match of bpp and colors */
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (cmp_var_to_colormode(var, mode)) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ /* match with bpp if user has not filled color fields
++ * properly */
++ switch (var->bits_per_pixel) {
++ case 1:
++ dssmode = OMAP_DSS_COLOR_CLUT1;
++ break;
++ case 2:
++ dssmode = OMAP_DSS_COLOR_CLUT2;
++ break;
++ case 4:
++ dssmode = OMAP_DSS_COLOR_CLUT4;
++ break;
++ case 8:
++ dssmode = OMAP_DSS_COLOR_CLUT8;
++ break;
++ case 12:
++ dssmode = OMAP_DSS_COLOR_RGB12U;
++ break;
++ case 16:
++ dssmode = OMAP_DSS_COLOR_RGB16;
++ break;
++ case 24:
++ dssmode = OMAP_DSS_COLOR_RGB24P;
++ break;
++ case 32:
++ dssmode = OMAP_DSS_COLOR_RGB24U;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (dssmode == mode->dssmode) {
++ assign_colormode_to_var(var, mode);
++ return mode->dssmode;
++ }
++ }
++
++ return -EINVAL;
++}
++
++void set_fb_fix(struct fb_info *fbi)
++{
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_mem_region *rg = &ofbi->region;
++
++ DBG("set_fb_fix\n");
++
++ /* used by open/write in fbmem.c */
++ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
++
++ /* used by mmap in fbmem.c */
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ fix->line_length =
++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
++ else
++ fix->line_length =
++ (var->xres_virtual * var->bits_per_pixel) >> 3;
++ fix->smem_start = omapfb_get_region_paddr(ofbi);
++ fix->smem_len = rg->size;
++
++ fix->type = FB_TYPE_PACKED_PIXELS;
++
++ if (var->nonstd)
++ fix->visual = FB_VISUAL_PSEUDOCOLOR;
++ else {
++ switch (var->bits_per_pixel) {
++ case 32:
++ case 24:
++ case 16:
++ case 12:
++ fix->visual = FB_VISUAL_TRUECOLOR;
++ /* 12bpp is stored in 16 bits */
++ break;
++ case 1:
++ case 2:
++ case 4:
++ case 8:
++ fix->visual = FB_VISUAL_PSEUDOCOLOR;
++ break;
++ }
++ }
++
++ fix->accel = FB_ACCEL_NONE;
++
++ fix->xpanstep = 1;
++ fix->ypanstep = 1;
++
++ if (rg->size) {
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ omap_vrfb_setup(&rg->vrfb, rg->paddr,
++ var->xres_virtual, var->yres_virtual,
++ var->bits_per_pixel >> 3);
++ }
++}
++
++/* check new var and possibly modify it to be ok */
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omap_display *display = fb2display(fbi);
++ unsigned long max_frame_size;
++ unsigned long line_size;
++ int xres_min, yres_min;
++ int xres_max, yres_max;
++ enum omap_color_mode mode = 0;
++ int i;
++ int bytespp;
++
++ DBG("check_fb_var %d\n", ofbi->id);
++
++ if (ofbi->region.size == 0)
++ return 0;
++
++ mode = fb_mode_to_dss_mode(var);
++ if (mode < 0) {
++ DBG("cannot convert var to omap dss mode\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
++ DBG("invalid mode\n");
++ return -EINVAL;
++ }
++ }
++
++ if (var->rotate < 0 || var->rotate > 3)
++ return -EINVAL;
++
++ if (var->rotate != fbi->var.rotate) {
++ DBG("rotation changing\n");
++
++ ofbi->rotation = var->rotate;
++
++ if (abs(var->rotate - fbi->var.rotate) != 2) {
++ int tmp;
++ DBG("rotate changing 90/270 degrees. "
++ "swapping x/y res\n");
++
++ tmp = var->yres;
++ var->yres = var->xres;
++ var->xres = tmp;
++
++ tmp = var->yres_virtual;
++ var->yres_virtual = var->xres_virtual;
++ var->xres_virtual = tmp;
++ }
++ }
++
++ xres_min = OMAPFB_PLANE_XRES_MIN;
++ xres_max = 2048;
++ yres_min = OMAPFB_PLANE_YRES_MIN;
++ yres_max = 2048;
++
++ bytespp = var->bits_per_pixel >> 3;
++
++ /* XXX: some applications seem to set virtual res to 0. */
++ if (var->xres_virtual == 0)
++ var->xres_virtual = var->xres;
++
++ if (var->yres_virtual == 0)
++ var->yres_virtual = var->yres;
++
++ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
++ return -EINVAL;
++
++ if (var->xres < xres_min)
++ var->xres = xres_min;
++ if (var->yres < yres_min)
++ var->yres = yres_min;
++ if (var->xres > xres_max)
++ var->xres = xres_max;
++ if (var->yres > yres_max)
++ var->yres = yres_max;
++
++ if (var->xres > var->xres_virtual)
++ var->xres = var->xres_virtual;
++ if (var->yres > var->yres_virtual)
++ var->yres = var->yres_virtual;
++
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ line_size = OMAP_VRFB_LINE_LEN * bytespp;
++ else
++ line_size = var->xres_virtual * bytespp;
++
++ max_frame_size = ofbi->region.size;
++
++ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("can't fit FB into memory, reducing y\n");
++ var->yres_virtual = max_frame_size / line_size;
++
++ if (var->yres_virtual < yres_min)
++ var->yres_virtual = yres_min;
++
++ if (var->yres > var->yres_virtual)
++ var->yres = var->yres_virtual;
++ }
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("can't fit FB into memory, reducing x\n");
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ return -EINVAL;
++
++ var->xres_virtual = max_frame_size / var->yres_virtual /
++ bytespp;
++
++ if (var->xres_virtual < xres_min)
++ var->xres_virtual = xres_min;
++
++ if (var->xres > var->xres_virtual)
++ var->xres = var->xres_virtual;
++
++ line_size = var->xres_virtual * bytespp;
++ }
++
++ if (line_size * var->yres_virtual > max_frame_size) {
++ DBG("cannot fit FB to memory\n");
++ return -EINVAL;
++ }
++
++ if (var->xres + var->xoffset > var->xres_virtual)
++ var->xoffset = var->xres_virtual - var->xres;
++ if (var->yres + var->yoffset > var->yres_virtual)
++ var->yoffset = var->yres_virtual - var->yres;
++
++ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
++ var->xres, var->yres,
++ var->xres_virtual, var->yres_virtual);
++
++ var->height = -1;
++ var->width = -1;
++ var->grayscale = 0;
++
++ if (display && display->get_timings) {
++ struct omap_video_timings timings;
++ display->get_timings(display, &timings);
++
++ /* pixclock in ps, the rest in pixclock */
++ var->pixclock = timings.pixel_clock != 0 ?
++ KHZ2PICOS(timings.pixel_clock) :
++ 0;
++ var->left_margin = timings.hfp;
++ var->right_margin = timings.hbp;
++ var->upper_margin = timings.vfp;
++ var->lower_margin = timings.vbp;
++ var->hsync_len = timings.hsw;
++ var->vsync_len = timings.vsw;
++ } else {
++ var->pixclock = 0;
++ var->left_margin = 0;
++ var->right_margin = 0;
++ var->upper_margin = 0;
++ var->lower_margin = 0;
++ var->hsync_len = 0;
++ var->vsync_len = 0;
++ }
++
++ /* TODO: get these from panel->config */
++ var->vmode = FB_VMODE_NONINTERLACED;
++ var->sync = 0;
++
++ return 0;
++}
++
++/*
++ * ---------------------------------------------------------------------------
++ * fbdev framework callbacks
++ * ---------------------------------------------------------------------------
++ */
++static int omapfb_open(struct fb_info *fbi, int user)
++{
++ return 0;
++}
++
++static int omapfb_release(struct fb_info *fbi, int user)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++
++ DBG("Closing fb with plane index %d\n", ofbi->id);
++
++ omapfb_lock(fbdev);
++#if 1
++ if (display && display->get_update_mode && display->update) {
++ /* XXX this update should be removed, I think. But it's
++ * good for debugging */
++ if (display->get_update_mode(display) ==
++ OMAP_DSS_UPDATE_MANUAL) {
++ u16 w, h;
++
++ if (display->sync)
++ display->sync(display);
++
++ display->get_resolution(display, &w, &h);
++ display->update(display, 0, 0, w, h);
++ }
++ }
++#endif
++
++ if (display && display->sync)
++ display->sync(display);
++
++ omapfb_unlock(fbdev);
++
++ return 0;
++}
++
++/* setup overlay according to the fb */
++static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
++ u16 posx, u16 posy, u16 outw, u16 outh)
++{
++ int r = 0;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ enum omap_color_mode mode = 0;
++ int offset;
++ u32 data_start_p;
++ void __iomem *data_start_v;
++ struct omap_overlay_info info;
++ int xres, yres;
++ int screen_width;
++ int rot, mirror;
++
++ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
++ posx, posy, outw, outh);
++
++ if (ofbi->rotation == FB_ROTATE_CW || ofbi->rotation == FB_ROTATE_CCW) {
++ xres = var->yres;
++ yres = var->xres;
++ } else {
++ xres = var->xres;
++ yres = var->yres;
++ }
++
++ offset = ((var->yoffset * var->xres_virtual +
++ var->xoffset) * var->bits_per_pixel) >> 3;
++
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ data_start_p = omapfb_get_region_rot_paddr(ofbi);
++ data_start_v = NULL;
++ } else {
++ data_start_p = omapfb_get_region_paddr(ofbi);
++ data_start_v = omapfb_get_region_vaddr(ofbi);
++ }
++
++ data_start_p += offset;
++ data_start_v += offset;
++
++ mode = fb_mode_to_dss_mode(var);
++
++ if (mode == -EINVAL) {
++ DBG("fb_mode_to_dss_mode failed");
++ r = -EINVAL;
++ goto err;
++ }
++
++ screen_width = fix->line_length / (var->bits_per_pixel >> 3);
++
++ ovl->get_overlay_info(ovl, &info);
++
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ rot = 0;
++ mirror = 0;
++ } else {
++ rot = ofbi->rotation;
++ mirror = ofbi->mirror;
++ }
++
++ info.paddr = data_start_p;
++ info.vaddr = data_start_v;
++ info.screen_width = screen_width;
++ info.width = xres;
++ info.height = yres;
++ info.color_mode = mode;
++ info.rotation = rot;
++ info.mirror = mirror;
++
++ info.pos_x = posx;
++ info.pos_y = posy;
++ info.out_width = outw;
++ info.out_height = outh;
++
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r) {
++ DBG("ovl->setup_overlay_info failed\n");
++ goto err;
++ }
++
++ return 0;
++
++err:
++ DBG("setup_overlay failed\n");
++ return r;
++}
++
++/* apply var to the overlay */
++int omapfb_apply_changes(struct fb_info *fbi, int init)
++{
++ int r = 0;
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct omap_overlay *ovl;
++ u16 posx, posy;
++ u16 outw, outh;
++ int i;
++
++#ifdef DEBUG
++ if (omapfb_test_pattern)
++ fill_fb(fbi);
++#endif
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ ovl = ofbi->overlays[i];
++
++ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
++
++ if (ofbi->region.size == 0) {
++ /* the fb is not available. disable the overlay */
++ omapfb_overlay_enable(ovl, 0);
++ if (!init && ovl->manager)
++ ovl->manager->apply(ovl->manager);
++ continue;
++ }
++
++ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
++ if (ofbi->rotation == FB_ROTATE_CW ||
++ ofbi->rotation == FB_ROTATE_CCW) {
++ outw = var->yres;
++ outh = var->xres;
++ } else {
++ outw = var->xres;
++ outh = var->yres;
++ }
++ } else {
++ outw = ovl->info.out_width;
++ outh = ovl->info.out_height;
++ }
++
++ if (init) {
++ posx = 0;
++ posy = 0;
++ } else {
++ posx = ovl->info.pos_x;
++ posy = ovl->info.pos_y;
++ }
++
++ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
++ if (r)
++ goto err;
++
++ if (!init && ovl->manager)
++ ovl->manager->apply(ovl->manager);
++ }
++ return 0;
++err:
++ DBG("apply_changes failed\n");
++ return r;
++}
++
++/* checks var and eventually tweaks it to something supported,
++ * DO NOT MODIFY PAR */
++static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
++{
++ int r;
++
++ DBG("check_var(%d)\n", FB2OFB(fbi)->id);
++
++ r = check_fb_var(fbi, var);
++
++ return r;
++}
++
++/* set the video mode according to info->var */
++static int omapfb_set_par(struct fb_info *fbi)
++{
++ int r;
++
++ DBG("set_par(%d)\n", FB2OFB(fbi)->id);
++
++ set_fb_fix(fbi);
++ r = omapfb_apply_changes(fbi, 0);
++
++ return r;
++}
++
++static int omapfb_pan_display(struct fb_var_screeninfo *var,
++ struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ int r = 0;
++
++ DBG("pan_display(%d)\n", ofbi->id);
++
++ omapfb_lock(fbdev);
++
++ if (var->xoffset != fbi->var.xoffset ||
++ var->yoffset != fbi->var.yoffset) {
++ struct fb_var_screeninfo new_var;
++
++ new_var = fbi->var;
++ new_var.xoffset = var->xoffset;
++ new_var.yoffset = var->yoffset;
++
++ r = check_fb_var(fbi, &new_var);
++
++ if (r == 0) {
++ fbi->var = new_var;
++ set_fb_fix(fbi);
++ r = omapfb_apply_changes(fbi, 0);
++ }
++ }
++
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static void mmap_user_open(struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++ atomic_inc(&ofbi->map_count);
++}
++
++static void mmap_user_close(struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
++
++ atomic_dec(&ofbi->map_count);
++}
++
++static struct vm_operations_struct mmap_user_ops = {
++ .open = mmap_user_open,
++ .close = mmap_user_close,
++};
++
++static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ unsigned long off;
++ unsigned long start;
++ u32 len;
++
++ if (vma->vm_end - vma->vm_start == 0)
++ return 0;
++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
++ return -EINVAL;
++ off = vma->vm_pgoff << PAGE_SHIFT;
++
++ start = omapfb_get_region_paddr(ofbi);
++ len = fix->smem_len;
++ if (off >= len)
++ return -EINVAL;
++ if ((vma->vm_end - vma->vm_start + off) > len)
++ return -EINVAL;
++
++ off += start;
++
++ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
++
++ vma->vm_pgoff = off >> PAGE_SHIFT;
++ vma->vm_flags |= VM_IO | VM_RESERVED;
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ vma->vm_ops = &mmap_user_ops;
++ vma->vm_private_data = ofbi;
++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot))
++ return -EAGAIN;
++ /* vm_ops.open won't be called for mmap itself. */
++ atomic_inc(&ofbi->map_count);
++ return 0;
++}
++
++/* Store a single color palette entry into a pseudo palette or the hardware
++ * palette if one is available. For now we support only 16bpp and thus store
++ * the entry only to the pseudo palette.
++ */
++static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
++ u_int blue, u_int transp, int update_hw_pal)
++{
++ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
++ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
++ struct fb_var_screeninfo *var = &fbi->var;
++ int r = 0;
++
++ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
++
++ /*switch (plane->color_mode) {*/
++ switch (mode) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUV420:
++ case OMAPFB_COLOR_YUY422:
++ r = -EINVAL;
++ break;
++ case OMAPFB_COLOR_CLUT_8BPP:
++ case OMAPFB_COLOR_CLUT_4BPP:
++ case OMAPFB_COLOR_CLUT_2BPP:
++ case OMAPFB_COLOR_CLUT_1BPP:
++ /*
++ if (fbdev->ctrl->setcolreg)
++ r = fbdev->ctrl->setcolreg(regno, red, green, blue,
++ transp, update_hw_pal);
++ */
++ /* Fallthrough */
++ r = -EINVAL;
++ break;
++ case OMAPFB_COLOR_RGB565:
++ case OMAPFB_COLOR_RGB444:
++ case OMAPFB_COLOR_RGB24P:
++ case OMAPFB_COLOR_RGB24U:
++ if (r != 0)
++ break;
++
++ if (regno < 0) {
++ r = -EINVAL;
++ break;
++ }
++
++ if (regno < 16) {
++ u16 pal;
++ pal = ((red >> (16 - var->red.length)) <<
++ var->red.offset) |
++ ((green >> (16 - var->green.length)) <<
++ var->green.offset) |
++ (blue >> (16 - var->blue.length));
++ ((u32 *)(fbi->pseudo_palette))[regno] = pal;
++ }
++ break;
++ default:
++ BUG();
++ }
++ return r;
++}
++
++static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++ u_int transp, struct fb_info *info)
++{
++ DBG("setcolreg\n");
++
++ return _setcolreg(info, regno, red, green, blue, transp, 1);
++}
++
++static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
++{
++ int count, index, r;
++ u16 *red, *green, *blue, *transp;
++ u16 trans = 0xffff;
++
++ DBG("setcmap\n");
++
++ red = cmap->red;
++ green = cmap->green;
++ blue = cmap->blue;
++ transp = cmap->transp;
++ index = cmap->start;
++
++ for (count = 0; count < cmap->len; count++) {
++ if (transp)
++ trans = *transp++;
++ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
++ count == cmap->len - 1);
++ if (r != 0)
++ return r;
++ }
++
++ return 0;
++}
++
++static int omapfb_blank(int blank, struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ int do_update = 0;
++ int r = 0;
++
++ omapfb_lock(fbdev);
++
++ switch (blank) {
++ case FB_BLANK_UNBLANK:
++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ goto exit;
++
++ if (display->resume)
++ r = display->resume(display);
++
++ if (r == 0 && display->get_update_mode &&
++ display->get_update_mode(display) ==
++ OMAP_DSS_UPDATE_MANUAL)
++ do_update = 1;
++
++ break;
++
++ case FB_BLANK_NORMAL:
++ /* FB_BLANK_NORMAL could be implemented.
++ * Needs DSS additions. */
++ case FB_BLANK_VSYNC_SUSPEND:
++ case FB_BLANK_HSYNC_SUSPEND:
++ case FB_BLANK_POWERDOWN:
++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto exit;
++
++ if (display->suspend)
++ r = display->suspend(display);
++
++ break;
++
++ default:
++ r = -EINVAL;
++ }
++
++exit:
++ omapfb_unlock(fbdev);
++
++ if (r == 0 && do_update && display->update) {
++ u16 w, h;
++ display->get_resolution(display, &w, &h);
++
++ r = display->update(display, 0, 0, w, h);
++ }
++
++ return r;
++}
++
++#if 0
++/* XXX fb_read and fb_write are needed for VRFB */
++ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
++ // XXX needed for VRFB
++ return count;
++}
++#endif
++
++static struct fb_ops omapfb_ops = {
++ .owner = THIS_MODULE,
++ .fb_open = omapfb_open,
++ .fb_release = omapfb_release,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_blank = omapfb_blank,
++ .fb_ioctl = omapfb_ioctl,
++ .fb_check_var = omapfb_check_var,
++ .fb_set_par = omapfb_set_par,
++ .fb_pan_display = omapfb_pan_display,
++ .fb_mmap = omapfb_mmap,
++ .fb_setcolreg = omapfb_setcolreg,
++ .fb_setcmap = omapfb_setcmap,
++ //.fb_write = omapfb_write,
++};
++
++static void omapfb_free_fbmem(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++
++ rg = &ofbi->region;
++
++ if (rg->paddr)
++ if (omap_vram_free(rg->paddr, rg->size))
++ dev_err(fbdev->dev, "VRAM FREE failed\n");
++
++ if (rg->vaddr)
++ iounmap(rg->vaddr);
++
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ /* unmap the 0 angle rotation */
++ if (rg->vrfb.vaddr[0]) {
++ iounmap(rg->vrfb.vaddr[0]);
++ omap_vrfb_release_ctx(&rg->vrfb);
++ }
++ }
++
++ rg->vaddr = NULL;
++ rg->paddr = 0;
++ rg->alloc = 0;
++ rg->size = 0;
++}
++
++static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ DBG("free all fbmem\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct fb_info *fbi = fbdev->fbs[i];
++ omapfb_free_fbmem(fbi);
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ }
++
++ return 0;
++}
++
++static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
++ unsigned long paddr)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omapfb2_mem_region *rg;
++ void __iomem *vaddr;
++ int r;
++ int clear = 0;
++
++ rg = &ofbi->region;
++ memset(rg, 0, sizeof(*rg));
++
++ size = PAGE_ALIGN(size);
++
++ if (!paddr) {
++ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
++ r = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
++ clear = 1;
++ } else {
++ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
++ ofbi->id);
++ r = omap_vram_reserve(paddr, size);
++ }
++
++ if (r) {
++ dev_err(fbdev->dev, "failed to allocate framebuffer\n");
++ return -ENOMEM;
++ }
++
++ if (ofbi->rotation_type != OMAPFB_ROT_VRFB) {
++ vaddr = ioremap_wc(paddr, size);
++
++ if (!vaddr) {
++ dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
++ omap_vram_free(paddr, size);
++ return -ENOMEM;
++ }
++
++ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
++
++ if (clear)
++ memset_io(vaddr, 0, size);
++ } else {
++ void __iomem *va;
++
++ r = omap_vrfb_request_ctx(&rg->vrfb);
++ if (r) {
++ dev_err(fbdev->dev, "vrfb create ctx failed\n");
++ return r;
++ }
++
++ /* only ioremap the 0 angle view */
++ va = ioremap_wc(rg->vrfb.paddr[0], size);
++
++ if(!va) {
++ printk(KERN_ERR "vrfb: ioremap failed\n");
++ return -ENOMEM;
++ }
++
++ DBG("ioremapped vrfb area 0 to %p\n", va);
++
++ rg->vrfb.vaddr[0] = va;
++
++ vaddr = NULL;
++
++ if (clear)
++ memset_io(va, 0, size);
++ }
++
++ rg->paddr = paddr;
++ rg->vaddr = vaddr;
++ rg->size = size;
++ rg->alloc = 1;
++
++ return 0;
++}
++
++/* allocate fbmem using display resolution as reference */
++static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
++ unsigned long paddr)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omap_display *display;
++ int bytespp;
++
++ display = fb2display(fbi);
++
++ if (!display)
++ return 0;
++
++ switch (display->get_recommended_bpp(display)) {
++ case 16:
++ bytespp = 2;
++ break;
++ case 24:
++ bytespp = 4;
++ break;
++ default:
++ bytespp = 4;
++ break;
++ }
++
++ if (!size) {
++ u16 w, h;
++
++ display->get_resolution(display, &w, &h);
++
++ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ int oldw = w, oldh = h;
++
++ omap_vrfb_adjust_size(&w, &h, bytespp);
++
++ /* Because we change the resolution of the 0 degree view,
++ * we need to alloc max(w, h) for height */
++ h = max(w, h);
++ w = OMAP_VRFB_LINE_LEN;
++
++ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n",
++ oldw, oldh, w, h);
++ }
++
++ size = w * h * bytespp;
++ }
++
++ return omapfb_alloc_fbmem(fbi, size, paddr);
++}
++
++static int omapfb_parse_vram_param(const char *param, int max_entries,
++ unsigned long *sizes, unsigned long *paddrs)
++{
++ int fbnum;
++ unsigned long size;
++ unsigned long paddr = 0;
++ char *p, *start;
++
++ start = (char *)param;
++
++ while (1) {
++ p = start;
++
++ fbnum = simple_strtoul(p, &p, 10);
++
++ if (p == param)
++ return -EINVAL;
++
++ if (*p != ':')
++ return -EINVAL;
++
++ if (fbnum >= max_entries)
++ return -EINVAL;
++
++ size = memparse(p + 1, &p);
++
++ if (!size)
++ return -EINVAL;
++
++ paddr = 0;
++
++ if (*p == '@') {
++ paddr = simple_strtoul(p + 1, &p, 16);
++
++ if (!paddr)
++ return -EINVAL;
++
++ }
++
++ paddrs[fbnum] = paddr;
++ sizes[fbnum] = size;
++
++ if (*p == 0)
++ break;
++
++ if (*p != ',')
++ return -EINVAL;
++
++ ++p;
++
++ start = p;
++ }
++
++ return 0;
++}
++
++static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
++{
++ int i, r;
++ unsigned long vram_sizes[10];
++ unsigned long vram_paddrs[10];
++
++ memset(&vram_sizes, 0, sizeof(vram_sizes));
++ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
++
++ if (def_vram && omapfb_parse_vram_param(def_vram, 10,
++ vram_sizes, vram_paddrs)) {
++ dev_err(fbdev->dev, "failed to parse vram parameter\n");
++
++ memset(&vram_sizes, 0, sizeof(vram_sizes));
++ memset(&vram_paddrs, 0, sizeof(vram_paddrs));
++ }
++
++ if (fbdev->dev->platform_data) {
++ struct omapfb_platform_data *opd;
++ opd = fbdev->dev->platform_data;
++ for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
++ if (!vram_sizes[i]) {
++ unsigned long size;
++ unsigned long paddr;
++
++ size = opd->mem_desc.region[i].size;
++ paddr = opd->mem_desc.region[i].paddr;
++
++ vram_sizes[i] = size;
++ vram_paddrs[i] = paddr;
++ }
++ }
++ }
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ /* allocate memory automatically only for fb0, or if
++ * excplicitly defined with vram or plat data option */
++ if (i == 0 || vram_sizes[i] != 0) {
++ r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
++ vram_sizes[i], vram_paddrs[i]);
++
++ if (r)
++ return r;
++ }
++ }
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++ struct omapfb2_mem_region *rg;
++ rg = &ofbi->region;
++
++ DBG("region%d phys %08x virt %p size=%lu\n",
++ i,
++ rg->paddr,
++ rg->vaddr,
++ rg->size);
++ }
++
++ return 0;
++}
++
++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_display *display = fb2display(fbi);
++ struct omapfb2_mem_region *rg = &ofbi->region;
++ unsigned long old_size = rg->size;
++ unsigned long old_paddr = rg->paddr;
++ int old_type = rg->type;
++ int r;
++
++ if (type > OMAPFB_MEMTYPE_MAX)
++ return -EINVAL;
++
++ size = PAGE_ALIGN(size);
++
++ if (old_size == size && old_type == type)
++ return 0;
++
++ if (display && display->sync)
++ display->sync(display);
++
++ omapfb_free_fbmem(fbi);
++
++ if (size == 0) {
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ return 0;
++ }
++
++ r = omapfb_alloc_fbmem(fbi, size, 0);
++
++ if (r) {
++ if (old_size)
++ omapfb_alloc_fbmem(fbi, old_size, old_paddr);
++
++ if (rg->size == 0) {
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ }
++
++ return r;
++ }
++
++ if (old_size == size)
++ return 0;
++
++ if (old_size == 0) {
++ DBG("initializing fb %d\n", ofbi->id);
++ r = omapfb_fb_init(fbdev, fbi);
++ if (r) {
++ DBG("omapfb_fb_init failed\n");
++ goto err;
++ }
++ r = omapfb_apply_changes(fbi, 1);
++ if (r) {
++ DBG("omapfb_apply_changes failed\n");
++ goto err;
++ }
++ } else {
++ struct fb_var_screeninfo new_var;
++ memcpy(&new_var, &fbi->var, sizeof(new_var));
++ r = check_fb_var(fbi, &new_var);
++ if (r)
++ goto err;
++ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
++ set_fb_fix(fbi);
++ }
++
++ return 0;
++err:
++ omapfb_free_fbmem(fbi);
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ return r;
++}
++
++/* initialize fb_info, var, fix to something sane based on the display */
++int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
++{
++ struct fb_var_screeninfo *var = &fbi->var;
++ struct fb_fix_screeninfo *fix = &fbi->fix;
++ struct omap_display *display = fb2display(fbi);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int r = 0;
++
++ fbi->fbops = &omapfb_ops;
++ fbi->flags = FBINFO_FLAG_DEFAULT;
++ fbi->pseudo_palette = fbdev->pseudo_palette;
++
++ strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
++
++ if (ofbi->region.size == 0) {
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ return 0;
++ }
++
++ var->nonstd = 0;
++
++ var->rotate = ofbi->rotation;
++
++ if (display) {
++ u16 w, h;
++ display->get_resolution(display, &w, &h);
++
++ if (ofbi->rotation == FB_ROTATE_CW ||
++ ofbi->rotation == FB_ROTATE_CCW) {
++ var->xres = h;
++ var->yres = w;
++ } else {
++ var->xres = w;
++ var->yres = h;
++ }
++
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++
++ switch (display->get_recommended_bpp(display)) {
++ case 16:
++ var->bits_per_pixel = 16;
++ break;
++ case 24:
++ var->bits_per_pixel = 32;
++ break;
++ default:
++ dev_err(fbdev->dev, "illegal display bpp\n");
++ return -EINVAL;
++ }
++ } else {
++ /* if there's no display, let's just guess some basic values */
++ var->xres = 320;
++ var->yres = 240;
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++ var->bits_per_pixel = 16;
++ }
++
++ r = check_fb_var(fbi, var);
++ if (r)
++ goto err;
++
++ set_fb_fix(fbi);
++err:
++ return r;
++}
++
++static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
++{
++ fb_dealloc_cmap(&fbi->cmap);
++}
++
++
++static void omapfb_free_resources(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ DBG("free_resources\n");
++
++ if (fbdev == NULL)
++ return;
++
++ for (i = 0; i < fbdev->num_fbs; i++)
++ unregister_framebuffer(fbdev->fbs[i]);
++
++ /* free the reserved fbmem */
++ omapfb_free_all_fbmem(fbdev);
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ fbinfo_cleanup(fbdev, fbdev->fbs[i]);
++ framebuffer_release(fbdev->fbs[i]);
++ }
++
++ for (i = 0; i < fbdev->num_displays; i++) {
++ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
++ fbdev->displays[i]->disable(fbdev->displays[i]);
++
++ omap_dss_put_display(fbdev->displays[i]);
++ }
++
++ dev_set_drvdata(fbdev->dev, NULL);
++ kfree(fbdev);
++}
++
++static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
++{
++ int r, i;
++
++ fbdev->num_fbs = 0;
++
++ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
++
++ /* allocate fb_infos */
++ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
++ struct fb_info *fbi;
++ struct omapfb_info *ofbi;
++
++ fbi = framebuffer_alloc(sizeof(struct omapfb_info),
++ fbdev->dev);
++
++ if (fbi == NULL) {
++ dev_err(fbdev->dev,
++ "unable to allocate memory for plane info\n");
++ return -ENOMEM;
++ }
++
++ fbdev->fbs[i] = fbi;
++
++ ofbi = FB2OFB(fbi);
++ ofbi->fbdev = fbdev;
++ ofbi->id = i;
++
++ /* assign these early, so that fb alloc can use them */
++ ofbi->rotation_type = def_vrfb ? OMAPFB_ROT_VRFB :
++ OMAPFB_ROT_DMA;
++ ofbi->rotation = def_rotate;
++ ofbi->mirror = def_mirror;
++
++ fbdev->num_fbs++;
++ }
++
++ DBG("fb_infos allocated\n");
++
++ /* assign overlays for the fbs */
++ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ ofbi->overlays[0] = fbdev->overlays[i];
++ ofbi->num_overlays = 1;
++ }
++
++ /* allocate fb memories */
++ r = omapfb_allocate_all_fbs(fbdev);
++ if (r) {
++ dev_err(fbdev->dev, "failed to allocate fbmem\n");
++ return r;
++ }
++
++ DBG("fbmems allocated\n");
++
++ /* setup fb_infos */
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
++ if (r) {
++ dev_err(fbdev->dev, "failed to setup fb_info\n");
++ return r;
++ }
++ }
++
++ DBG("fb_infos initialized\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = register_framebuffer(fbdev->fbs[i]);
++ if (r != 0) {
++ dev_err(fbdev->dev,
++ "registering framebuffer %d failed\n", i);
++ return r;
++ }
++ }
++
++ DBG("framebuffers registered\n");
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ r = omapfb_apply_changes(fbdev->fbs[i], 1);
++ if (r) {
++ dev_err(fbdev->dev, "failed to change mode\n");
++ return r;
++ }
++ }
++
++ DBG("create sysfs for fbs\n");
++ r = omapfb_create_sysfs(fbdev);
++ if (r) {
++ dev_err(fbdev->dev, "failed to create sysfs entries\n");
++ return r;
++ }
++
++ /* Enable fb0 */
++ if (fbdev->num_fbs > 0) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
++
++ if (ofbi->num_overlays > 0 ) {
++ struct omap_overlay *ovl = ofbi->overlays[0];
++
++ r = omapfb_overlay_enable(ovl, 1);
++
++ if (r) {
++ dev_err(fbdev->dev,
++ "failed to enable overlay\n");
++ return r;
++ }
++ }
++ }
++
++ DBG("create_framebuffers done\n");
++
++ return 0;
++}
++
++int omapfb_mode_to_timings(const char *mode_str,
++ struct omap_video_timings *timings, u8 *bpp)
++{
++ struct fb_info fbi;
++ struct fb_var_screeninfo var;
++ struct fb_ops fbops;
++ int r;
++
++#ifdef CONFIG_OMAP2_DSS_VENC
++ if (strcmp(mode_str, "pal") == 0) {
++ *timings = omap_dss_pal_timings;
++ *bpp = 0;
++ return 0;
++ } else if (strcmp(mode_str, "ntsc") == 0) {
++ *timings = omap_dss_ntsc_timings;
++ *bpp = 0;
++ return 0;
++ }
++#endif
++
++ /* this is quite a hack, but I wanted to use the modedb and for
++ * that we need fb_info and var, so we create dummy ones */
++
++ memset(&fbi, 0, sizeof(fbi));
++ memset(&var, 0, sizeof(var));
++ memset(&fbops, 0, sizeof(fbops));
++ fbi.fbops = &fbops;
++
++ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
++
++ if (r != 0) {
++ timings->pixel_clock = PICOS2KHZ(var.pixclock);
++ timings->hfp = var.left_margin;
++ timings->hbp = var.right_margin;
++ timings->vfp = var.upper_margin;
++ timings->vbp = var.lower_margin;
++ timings->hsw = var.hsync_len;
++ timings->vsw = var.vsync_len;
++ timings->x_res = var.xres;
++ timings->y_res = var.yres;
++
++ switch (var.bits_per_pixel) {
++ case 16:
++ *bpp = 16;
++ break;
++ case 24:
++ case 32:
++ default:
++ *bpp = 24;
++ break;
++ }
++
++ return 0;
++ } else {
++ return -EINVAL;
++ }
++}
++
++static int omapfb_set_def_mode(struct omap_display *display, char *mode_str)
++{
++ int r;
++ u8 bpp;
++ struct omap_video_timings timings;
++
++ r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
++ if (r)
++ return r;
++
++ display->panel->recommended_bpp = bpp;
++
++ if (!display->check_timings || !display->set_timings)
++ return -EINVAL;
++
++ r = display->check_timings(display, &timings);
++ if (r)
++ return r;
++
++ display->set_timings(display, &timings);
++
++ return 0;
++}
++
++static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
++{
++ char *str, *options, *this_opt;
++ int r = 0;
++
++ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
++ strcpy(str, def_mode);
++ options = str;
++
++ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
++ char *p, *display_str, *mode_str;
++ struct omap_display *display;
++ int i;
++
++ p = strchr(this_opt, ':');
++ if (!p) {
++ r = -EINVAL;
++ break;
++ }
++
++ *p = 0;
++ display_str = this_opt;
++ mode_str = p + 1;
++
++ display = NULL;
++ for (i = 0; i < fbdev->num_displays; ++i) {
++ if (strcmp(fbdev->displays[i]->name,
++ display_str) == 0) {
++ display = fbdev->displays[i];
++ break;
++ }
++ }
++
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = omapfb_set_def_mode(display, mode_str);
++ if (r)
++ break;
++ }
++
++ kfree(str);
++
++ return r;
++}
++
++static int omapfb_probe(struct platform_device *pdev)
++{
++ struct omapfb2_device *fbdev = NULL;
++ int r = 0;
++ int i, t;
++ struct omap_overlay *ovl;
++ struct omap_display *def_display;
++
++ DBG("omapfb_probe\n");
++
++ if (pdev->num_resources != 0) {
++ dev_err(&pdev->dev, "probed for an unknown device\n");
++ r = -ENODEV;
++ goto err0;
++ }
++
++ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
++ if (fbdev == NULL) {
++ r = -ENOMEM;
++ goto err0;
++ }
++
++ mutex_init(&fbdev->mtx);
++
++ fbdev->dev = &pdev->dev;
++ platform_set_drvdata(pdev, fbdev);
++
++ fbdev->num_displays = 0;
++ t = omap_dss_get_num_displays();
++ for (i = 0; i < t; i++) {
++ struct omap_display *display;
++ display = omap_dss_get_display(i);
++ if (!display) {
++ dev_err(&pdev->dev, "can't get display %d\n", i);
++ r = -EINVAL;
++ goto cleanup;
++ }
++
++ fbdev->displays[fbdev->num_displays++] = display;
++ }
++
++ if (fbdev->num_displays == 0) {
++ dev_err(&pdev->dev, "no displays\n");
++ r = -EINVAL;
++ goto cleanup;
++ }
++
++ fbdev->num_overlays = omap_dss_get_num_overlays();
++ for (i = 0; i < fbdev->num_overlays; i++)
++ fbdev->overlays[i] = omap_dss_get_overlay(i);
++
++ fbdev->num_managers = omap_dss_get_num_overlay_managers();
++ for (i = 0; i < fbdev->num_managers; i++)
++ fbdev->managers[i] = omap_dss_get_overlay_manager(i);
++
++
++ /* gfx overlay should be the default one. find a display
++ * connected to that, and use it as default display */
++ ovl = omap_dss_get_overlay(0);
++ if (ovl->manager && ovl->manager->display) {
++ def_display = ovl->manager->display;
++ } else {
++ dev_err(&pdev->dev, "cannot find default display\n");
++ r = -EINVAL;
++ goto cleanup;
++ }
++
++ if (def_mode && strlen(def_mode) > 0) {
++ if (omapfb_parse_def_modes(fbdev))
++ dev_err(&pdev->dev, "cannot parse default modes\n");
++ }
++
++ r = omapfb_create_framebuffers(fbdev);
++ if (r)
++ goto cleanup;
++
++ for (i = 0; i < fbdev->num_managers; i++) {
++ struct omap_overlay_manager *mgr;
++ mgr = fbdev->managers[i];
++ r = mgr->apply(mgr);
++ if (r) {
++ dev_err(fbdev->dev, "failed to apply dispc config\n");
++ goto cleanup;
++ }
++ }
++
++ DBG("mgr->apply'ed\n");
++
++ r = def_display->enable(def_display);
++ if (r) {
++ dev_err(fbdev->dev, "Failed to enable display '%s'\n",
++ def_display->name);
++ goto cleanup;
++ }
++
++ /* set the update mode */
++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 1);
++#else
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_MANUAL);
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 0);
++#endif
++ } else {
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++ }
++
++ for (i = 0; i < fbdev->num_displays; i++) {
++ struct omap_display *display = fbdev->displays[i];
++ u16 w, h;
++
++ if (!display->get_update_mode || !display->update)
++ continue;
++
++ if (display->get_update_mode(display) ==
++ OMAP_DSS_UPDATE_MANUAL) {
++
++ display->get_resolution(display, &w, &h);
++ display->update(display, 0, 0, w, h);
++ }
++ }
++
++ DBG("display->updated\n");
++
++ return 0;
++
++cleanup:
++ omapfb_free_resources(fbdev);
++err0:
++ dev_err(&pdev->dev, "failed to setup omapfb\n");
++ return r;
++}
++
++static int omapfb_remove(struct platform_device *pdev)
++{
++ struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
++
++ /* FIXME: wait till completion of pending events */
++
++ omapfb_remove_sysfs(fbdev);
++
++ omapfb_free_resources(fbdev);
++
++ return 0;
++}
++
++static struct platform_driver omapfb_driver = {
++ .probe = omapfb_probe,
++ .remove = omapfb_remove,
++ .driver = {
++ .name = "omapfb",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init omapfb_init(void)
++{
++ DBG("omapfb_init\n");
++
++ if (platform_driver_register(&omapfb_driver)) {
++ printk(KERN_ERR "failed to register omapfb driver\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static void __exit omapfb_exit(void)
++{
++ DBG("omapfb_exit\n");
++ platform_driver_unregister(&omapfb_driver);
++}
++
++module_param_named(mode, def_mode, charp, 0);
++module_param_named(vram, def_vram, charp, 0);
++module_param_named(rotate, def_rotate, int, 0);
++module_param_named(vrfb, def_vrfb, bool, 0);
++module_param_named(mirror, def_mirror, bool, 0);
++
++/* late_initcall to let panel/ctrl drivers loaded first.
++ * I guess better option would be a more dynamic approach,
++ * so that omapfb reacts to new panels when they are loaded */
++late_initcall(omapfb_init);
++/*module_init(omapfb_init);*/
++module_exit(omapfb_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+new file mode 100644
+index 0000000..2c88718
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -0,0 +1,371 @@
++/*
++ * linux/drivers/video/omap2/omapfb-sysfs.c
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/fb.h>
++#include <linux/sysfs.h>
++#include <linux/device.h>
++#include <linux/uaccess.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/omapfb.h>
++
++#include <mach/display.h>
++#include <mach/vrfb.h>
++
++#include "omapfb.h"
++
++static ssize_t show_rotate_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
++}
++
++static ssize_t show_mirror(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
++}
++
++static ssize_t store_mirror(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ bool mirror;
++ int r;
++ struct fb_var_screeninfo new_var;
++
++ mirror = simple_strtoul(buf, NULL, 0);
++
++ if (mirror != 0 && mirror != 1)
++ return -EINVAL;
++
++ omapfb_lock(fbdev);
++
++ ofbi->mirror = mirror;
++
++ memcpy(&new_var, &fbi->var, sizeof(new_var));
++ r = check_fb_var(fbi, &new_var);
++ if (r)
++ goto out;
++ memcpy(&fbi->var, &new_var, sizeof(fbi->var));
++
++ set_fb_fix(fbi);
++
++ r = omapfb_apply_changes(fbi, 0);
++ if (r)
++ goto out;
++
++ r = count;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static ssize_t show_overlays(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ ssize_t l = 0;
++ int t;
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ struct omap_overlay *ovl = ofbi->overlays[t];
++ int ovlnum;
++
++ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
++ if (ovl == fbdev->overlays[ovlnum])
++ break;
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
++ t == 0 ? "" : ",", ovlnum);
++ }
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
++
++ return l;
++}
++
++static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
++ struct omap_overlay *ovl)
++{
++ int i, t;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ if (ofbi->overlays[t] == ovl)
++ return ofbi;
++ }
++ }
++
++ return NULL;
++}
++
++static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
++ struct omap_overlay *ovl;
++ int num_ovls, r, i;
++ int len;
++
++ num_ovls = 0;
++
++ len = strlen(buf);
++ if (buf[len - 1] == '\n')
++ len = len - 1;
++
++ omapfb_lock(fbdev);
++
++ if (len > 0) {
++ char *p = (char *)buf;
++ int ovlnum;
++
++ while (p < buf + len) {
++ int found;
++ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ ovlnum = simple_strtoul(p, &p, 0);
++ if (ovlnum > fbdev->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ found = 0;
++ for (i = 0; i < num_ovls; ++i) {
++ if (ovls[i] == fbdev->overlays[ovlnum]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ ovls[num_ovls++] = fbdev->overlays[ovlnum];
++
++ p++;
++ }
++ }
++
++ for (i = 0; i < num_ovls; ++i) {
++ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
++ if (ofbi2 && ofbi2 != ofbi) {
++ dev_err(fbdev->dev, "overlay already in use\n");
++ r = -EINVAL;
++ goto out;
++ }
++ }
++
++ /* detach unused overlays */
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ int t, found;
++
++ ovl = ofbi->overlays[i];
++
++ found = 0;
++
++ for (t = 0; t < num_ovls; ++t) {
++ if (ovl == ovls[t]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (found)
++ continue;
++
++ DBG("detaching %d\n", ofbi->overlays[i]->id);
++
++ omapfb_overlay_enable(ovl, 0);
++
++ if (ovl->manager)
++ ovl->manager->apply(ovl->manager);
++
++ for (t = i + 1; t < ofbi->num_overlays; t++)
++ ofbi->overlays[t-1] = ofbi->overlays[t];
++
++ ofbi->num_overlays--;
++ i--;
++ }
++
++ for (i = 0; i < num_ovls; ++i) {
++ int t, found;
++
++ ovl = ovls[i];
++
++ found = 0;
++
++ for (t = 0; t < ofbi->num_overlays; ++t) {
++ if (ovl == ofbi->overlays[t]) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (found)
++ continue;
++
++ ofbi->overlays[ofbi->num_overlays++] = ovl;
++
++ r = omapfb_apply_changes(fbi, 1);
++ if (r)
++ goto out;
++
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ goto out;
++ }
++ }
++
++ r = count;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static ssize_t show_size(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
++}
++
++static ssize_t store_size(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ unsigned long size;
++ int r;
++ int i;
++
++ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
++
++ omapfb_lock(fbdev);
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->info.enabled) {
++ r = -EBUSY;
++ goto out;
++ }
++ }
++
++ if (size != ofbi->region.size) {
++ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
++ if (r) {
++ dev_err(dev, "realloc fbmem failed\n");
++ goto out;
++ }
++ }
++
++ r = count;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++static ssize_t show_phys(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
++}
++
++static ssize_t show_virt(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++
++ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
++}
++
++static struct device_attribute omapfb_attrs[] = {
++ __ATTR(rotate_type, S_IRUGO, show_rotate_type, NULL),
++ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
++ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
++ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
++ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
++ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
++};
++
++int omapfb_create_sysfs(struct omapfb2_device *fbdev)
++{
++ int i;
++ int r;
++
++ DBG("create sysfs for fbs\n");
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ int t;
++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
++ r = device_create_file(fbdev->fbs[i]->dev,
++ &omapfb_attrs[t]);
++
++ if (r) {
++ dev_err(fbdev->dev, "failed to create sysfs file\n");
++ return r;
++ }
++ }
++ }
++
++ return 0;
++}
++
++void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
++{
++ int i, t;
++
++ DBG("remove sysfs for fbs\n");
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
++ device_remove_file(fbdev->fbs[i]->dev,
++ &omapfb_attrs[t]);
++ }
++}
++
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+new file mode 100644
+index 0000000..65e9e6e
+--- /dev/null
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -0,0 +1,153 @@
++/*
++ * linux/drivers/video/omap2/omapfb.h
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * Some code and ideas taken from drivers/video/omap/ driver
++ * by Imre Deak.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
++#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
++
++#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
++#define DEBUG
++#endif
++
++#ifdef DEBUG
++extern unsigned int omapfb_debug;
++#define DBG(format, ...) \
++ if (omapfb_debug) \
++ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
++
++/* max number of overlays to which a framebuffer data can be direct */
++#define OMAPFB_MAX_OVL_PER_FB 3
++
++struct omapfb2_mem_region {
++ u32 paddr;
++ void __iomem *vaddr;
++ struct vrfb vrfb;
++ unsigned long size;
++ u8 type; /* OMAPFB_PLANE_MEM_* */
++ bool alloc; /* allocated by the driver */
++ bool map; /* kernel mapped by the driver */
++};
++
++enum omapfb_rotation_type {
++ OMAPFB_ROT_DMA = 0,
++ OMAPFB_ROT_VRFB = 1,
++};
++
++/* appended to fb_info */
++struct omapfb_info {
++ int id;
++ struct omapfb2_mem_region region;
++ atomic_t map_count;
++ int num_overlays;
++ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
++ struct omapfb2_device *fbdev;
++ enum omapfb_rotation_type rotation_type;
++ u8 rotation;
++ bool mirror;
++};
++
++struct omapfb2_device {
++ struct device *dev;
++ struct mutex mtx;
++
++ u32 pseudo_palette[17];
++
++ int state;
++
++ unsigned num_fbs;
++ struct fb_info *fbs[10];
++
++ unsigned num_displays;
++ struct omap_display *displays[10];
++ unsigned num_overlays;
++ struct omap_overlay *overlays[10];
++ unsigned num_managers;
++ struct omap_overlay_manager *managers[10];
++};
++
++struct omapfb_colormode {
++ enum omap_color_mode dssmode;
++ u32 bits_per_pixel;
++ u32 nonstd;
++ struct fb_bitfield red;
++ struct fb_bitfield green;
++ struct fb_bitfield blue;
++ struct fb_bitfield transp;
++};
++
++u32 omapfb_get_region_paddr(struct omapfb_info *ofbi);
++void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi);
++
++void set_fb_fix(struct fb_info *fbi);
++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
++int omapfb_apply_changes(struct fb_info *fbi, int init);
++int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
++
++int omapfb_create_sysfs(struct omapfb2_device *fbdev);
++void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
++
++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
++
++int omapfb_mode_to_timings(const char *mode_str,
++ struct omap_video_timings *timings, u8 *bpp);
++
++/* find the display connected to this fb, if any */
++static inline struct omap_display *fb2display(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int i;
++
++ /* XXX: returns the display connected to first attached overlay */
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ofbi->overlays[i]->manager)
++ return ofbi->overlays[i]->manager->display;
++ }
++
++ return NULL;
++}
++
++static inline void omapfb_lock(struct omapfb2_device *fbdev)
++{
++ mutex_lock(&fbdev->mtx);
++}
++
++static inline void omapfb_unlock(struct omapfb2_device *fbdev)
++{
++ mutex_unlock(&fbdev->mtx);
++}
++
++static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
++ int enable)
++{
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++ info.enabled = enable;
++ return ovl->set_overlay_info(ovl, &info);
++}
++
++#endif
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index b226bdf..96190b2 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -50,6 +50,8 @@
+ #define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window)
+ #define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info)
+ #define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
++#define OMAPFB_WAITFORVSYNC OMAP_IO(57)
++#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
+
+ #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+ #define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+@@ -90,6 +92,13 @@ enum omapfb_color_format {
+ OMAPFB_COLOR_CLUT_1BPP,
+ OMAPFB_COLOR_RGB444,
+ OMAPFB_COLOR_YUY422,
++
++ OMAPFB_COLOR_ARGB16,
++ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */
++ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */
++ OMAPFB_COLOR_ARGB32,
++ OMAPFB_COLOR_RGBA32,
++ OMAPFB_COLOR_RGBX32,
+ };
+
+ struct omapfb_update_window {
+@@ -161,6 +170,15 @@ enum omapfb_update_mode {
+ OMAPFB_MANUAL_UPDATE
+ };
+
++struct omapfb_memory_read {
++ __u16 x;
++ __u16 y;
++ __u16 w;
++ __u16 h;
++ size_t buffer_size;
++ void __user *buffer;
++};
++
+ #ifdef __KERNEL__
+
+ #include <linux/completion.h>
+@@ -376,6 +394,8 @@ extern struct lcd_ctrl omap1_lcd_ctrl;
+ extern struct lcd_ctrl omap2_disp_ctrl;
+ #endif
+
++extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
++
+ extern void omapfb_reserve_sdram(void);
+ extern void omapfb_register_panel(struct lcd_panel *panel);
+ extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0004-DSS2-Add-panel-drivers.patch b/recipes/linux/linux-omap-pm/dss2/0004-DSS2-Add-panel-drivers.patch
new file mode 100644
index 0000000000..47b52269aa
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0004-DSS2-Add-panel-drivers.patch
@@ -0,0 +1,396 @@
+From 7764c7b96f5c101584226238b799cb89bca80749 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 10:29:56 +0300
+Subject: [PATCH 004/146] DSS2: Add panel drivers
+
+- Generic panel
+- Samsung LTE430WQ-F0C LCD Panel
+- Sharp LS037V7DW01 LCD Panel
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/displays/Kconfig | 21 ++++
+ drivers/video/omap2/displays/Makefile | 3 +
+ drivers/video/omap2/displays/panel-generic.c | 96 +++++++++++++++++
+ .../omap2/displays/panel-samsung-lte430wq-f0c.c | 108 +++++++++++++++++++
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 112 ++++++++++++++++++++
+ 5 files changed, 340 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/displays/Kconfig
+ create mode 100644 drivers/video/omap2/displays/Makefile
+ create mode 100644 drivers/video/omap2/displays/panel-generic.c
+ create mode 100644 drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+ create mode 100644 drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+
+diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
+new file mode 100644
+index 0000000..0419ec8
+--- /dev/null
++++ b/drivers/video/omap2/displays/Kconfig
+@@ -0,0 +1,21 @@
++menu "OMAP2/3 Display Device Drivers"
++ depends on OMAP2_DSS
++
++config PANEL_GENERIC
++ tristate "Generic Panel"
++ help
++ Generic panel driver.
++ Used for DVI output for Beagle and OMAP3 SDP.
++
++config PANEL_SAMSUNG_LTE430WQ_F0C
++ tristate "Samsung LTE430WQ-F0C LCD Panel"
++ depends on OMAP2_DSS
++ help
++ LCD Panel used on Overo Palo43
++
++config PANEL_SHARP_LS037V7DW01
++ tristate "Sharp LS037V7DW01 LCD Panel"
++ depends on OMAP2_DSS
++ help
++ LCD Panel used in TI's SDP3430 and EVM boards
++endmenu
+diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
+new file mode 100644
+index 0000000..a26bbd2
+--- /dev/null
++++ b/drivers/video/omap2/displays/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
++obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
++obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
+new file mode 100644
+index 0000000..8382acb
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-generic.c
+@@ -0,0 +1,96 @@
++/*
++ * Generic panel support
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static int generic_panel_init(struct omap_display *display)
++{
++ return 0;
++}
++
++static int generic_panel_enable(struct omap_display *display)
++{
++ int r = 0;
++
++ if (display->hw_config.panel_enable)
++ r = display->hw_config.panel_enable(display);
++
++ return r;
++}
++
++static void generic_panel_disable(struct omap_display *display)
++{
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++}
++
++static int generic_panel_suspend(struct omap_display *display)
++{
++ generic_panel_disable(display);
++ return 0;
++}
++
++static int generic_panel_resume(struct omap_display *display)
++{
++ return generic_panel_enable(display);
++}
++
++static struct omap_panel generic_panel = {
++ .owner = THIS_MODULE,
++ .name = "panel-generic",
++ .init = generic_panel_init,
++ .enable = generic_panel_enable,
++ .disable = generic_panel_disable,
++ .suspend = generic_panel_suspend,
++ .resume = generic_panel_resume,
++
++ .timings = {
++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
++ .x_res = 640,
++ .y_res = 480,
++ .pixel_clock = 23500,
++ .hfp = 48,
++ .hsw = 32,
++ .hbp = 80,
++ .vfp = 3,
++ .vsw = 4,
++ .vbp = 7,
++ },
++
++ .config = OMAP_DSS_LCD_TFT,
++};
++
++
++static int __init generic_panel_drv_init(void)
++{
++ omap_dss_register_panel(&generic_panel);
++ return 0;
++}
++
++static void __exit generic_panel_drv_exit(void)
++{
++ omap_dss_unregister_panel(&generic_panel);
++}
++
++module_init(generic_panel_drv_init);
++module_exit(generic_panel_drv_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+new file mode 100644
+index 0000000..e4bb781
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+@@ -0,0 +1,108 @@
++/*
++ * LCD panel driver for Samsung LTE430WQ-F0C
++ *
++ * Author: Steve Sakoman <steve@sakoman.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static int samsung_lte_panel_init(struct omap_display *display)
++{
++ return 0;
++}
++
++static void samsung_lte_panel_cleanup(struct omap_display *display)
++{
++}
++
++static int samsung_lte_panel_enable(struct omap_display *display)
++{
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ if (display->hw_config.panel_enable)
++ r = display->hw_config.panel_enable(display);
++
++ return r;
++}
++
++static void samsung_lte_panel_disable(struct omap_display *display)
++{
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++ msleep(100);
++}
++
++static int samsung_lte_panel_suspend(struct omap_display *display)
++{
++ samsung_lte_panel_disable(display);
++ return 0;
++}
++
++static int samsung_lte_panel_resume(struct omap_display *display)
++{
++ return samsung_lte_panel_enable(display);
++}
++
++static struct omap_panel samsung_lte_panel = {
++ .owner = THIS_MODULE,
++ .name = "samsung-lte430wq-f0c",
++ .init = samsung_lte_panel_init,
++ .cleanup = samsung_lte_panel_cleanup,
++ .enable = samsung_lte_panel_enable,
++ .disable = samsung_lte_panel_disable,
++ .suspend = samsung_lte_panel_suspend,
++ .resume = samsung_lte_panel_resume,
++
++ .timings = {
++ .x_res = 480,
++ .y_res = 272,
++
++ .pixel_clock = 9200,
++
++ .hsw = 41,
++ .hfp = 8,
++ .hbp = 45-41,
++
++ .vsw = 10,
++ .vfp = 4,
++ .vbp = 12-10,
++ },
++
++ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS,
++};
++
++
++static int __init samsung_lte_panel_drv_init(void)
++{
++ omap_dss_register_panel(&samsung_lte_panel);
++ return 0;
++}
++
++static void __exit samsung_lte_panel_drv_exit(void)
++{
++ omap_dss_unregister_panel(&samsung_lte_panel);
++}
++
++module_init(samsung_lte_panel_drv_init);
++module_exit(samsung_lte_panel_drv_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+new file mode 100644
+index 0000000..1f99150
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+@@ -0,0 +1,112 @@
++/*
++ * LCD panel driver for Sharp LS037V7DW01
++ *
++ * Copyright (C) 2008 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/display.h>
++
++static int sharp_ls_panel_init(struct omap_display *display)
++{
++ return 0;
++}
++
++static void sharp_ls_panel_cleanup(struct omap_display *display)
++{
++}
++
++static int sharp_ls_panel_enable(struct omap_display *display)
++{
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ if (display->hw_config.panel_enable)
++ r = display->hw_config.panel_enable(display);
++
++ return r;
++}
++
++static void sharp_ls_panel_disable(struct omap_display *display)
++{
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++
++ msleep(100);
++}
++
++static int sharp_ls_panel_suspend(struct omap_display *display)
++{
++ sharp_ls_panel_disable(display);
++ return 0;
++}
++
++static int sharp_ls_panel_resume(struct omap_display *display)
++{
++ return sharp_ls_panel_enable(display);
++}
++
++static struct omap_panel sharp_ls_panel = {
++ .owner = THIS_MODULE,
++ .name = "sharp-ls037v7dw01",
++ .init = sharp_ls_panel_init,
++ .cleanup = sharp_ls_panel_cleanup,
++ .enable = sharp_ls_panel_enable,
++ .disable = sharp_ls_panel_disable,
++ .suspend = sharp_ls_panel_suspend,
++ .resume = sharp_ls_panel_resume,
++
++ .timings = {
++ .x_res = 480,
++ .y_res = 640,
++
++ .pixel_clock = 19200,
++
++ .hsw = 2,
++ .hfp = 1,
++ .hbp = 28,
++
++ .vsw = 1,
++ .vfp = 1,
++ .vbp = 1,
++ },
++
++ .acb = 0x28,
++
++ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
++};
++
++
++static int __init sharp_ls_panel_drv_init(void)
++{
++ omap_dss_register_panel(&sharp_ls_panel);
++ return 0;
++}
++
++static void __exit sharp_ls_panel_drv_exit(void)
++{
++ omap_dss_unregister_panel(&sharp_ls_panel);
++}
++
++module_init(sharp_ls_panel_drv_init);
++module_exit(sharp_ls_panel_drv_exit);
++MODULE_LICENSE("GPL");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0005-DSS2-HACK-Add-DSS2-support-for-N800.patch b/recipes/linux/linux-omap-pm/dss2/0005-DSS2-HACK-Add-DSS2-support-for-N800.patch
new file mode 100644
index 0000000000..5dd90a4f22
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0005-DSS2-HACK-Add-DSS2-support-for-N800.patch
@@ -0,0 +1,1079 @@
+From 0fb0c230f94ff7e513db42dae9765c0b86234de8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 10:31:57 +0300
+Subject: [PATCH 005/146] DSS2: HACK: Add DSS2 support for N800
+
+Works, but it an ugly quick hack.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/mach-omap2/board-n800.c | 216 +++++++++++---
+ drivers/video/omap2/displays/Kconfig | 10 +
+ drivers/video/omap2/displays/Makefile | 3 +
+ drivers/video/omap2/displays/ctrl-blizzard.c | 279 +++++++++++++++++
+ drivers/video/omap2/displays/panel-n800.c | 435 ++++++++++++++++++++++++++
+ 5 files changed, 905 insertions(+), 38 deletions(-)
+ create mode 100644 drivers/video/omap2/displays/ctrl-blizzard.c
+ create mode 100644 drivers/video/omap2/displays/panel-n800.c
+
+diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
+index e2907ac..3f1071b 100644
+--- a/arch/arm/mach-omap2/board-n800.c
++++ b/arch/arm/mach-omap2/board-n800.c
+@@ -38,6 +38,8 @@
+ #include <mach/blizzard.h>
+ #include <mach/onenand.h>
+ #include <mach/board-nokia.h>
++#include <mach/display.h>
++#include <mach/vram.h>
+
+ #include <../drivers/cbus/tahvo.h>
+ #include <../drivers/media/video/tcm825x.h>
+@@ -98,23 +100,176 @@ static struct omap_uart_config n800_uart_config __initdata = {
+
+ #include "../../../drivers/cbus/retu.h"
+
+-static struct omap_fbmem_config n800_fbmem0_config __initdata = {
+- .size = 752 * 1024,
++static struct omap_tmp105_config n800_tmp105_config __initdata = {
++ .tmp105_irq_pin = 125,
++ .set_power = n800_tmp105_set_power,
+ };
+
+-static struct omap_fbmem_config n800_fbmem1_config __initdata = {
+- .size = 752 * 1024,
+-};
+
+-static struct omap_fbmem_config n800_fbmem2_config __initdata = {
+- .size = 752 * 1024,
++
++
++/* DISPLAY */
++static struct {
++ struct clk *sys_ck;
++} blizzard;
++
++static int blizzard_get_clocks(void)
++{
++ blizzard.sys_ck = clk_get(0, "osc_ck");
++ if (IS_ERR(blizzard.sys_ck)) {
++ printk(KERN_ERR "can't get Blizzard clock\n");
++ return PTR_ERR(blizzard.sys_ck);
++ }
++ return 0;
++}
++
++static unsigned long blizzard_get_clock_rate(void)
++{
++ return clk_get_rate(blizzard.sys_ck);
++}
++
++static int n800_pn800_enable(struct omap_display *display)
++{
++ if (display->hw_config.panel_reset_gpio != -1) {
++ printk("enabling panel gpio\n");
++ gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
++ }
++
++ return 0;
++}
++
++static void n800_pn800_disable(struct omap_display *display)
++{
++ if (display->hw_config.panel_reset_gpio != -1) {
++ printk("disabling panel gpio\n");
++ gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
++ msleep(120);
++ }
++}
++
++static int n800_blizzard_enable(struct omap_display *display)
++{
++ printk("enabling bliz powers\n");
++
++ /* Vcore to 1.475V */
++ tahvo_set_clear_reg_bits(0x07, 0, 0xf);
++ msleep(10);
++
++ clk_enable(blizzard.sys_ck);
++
++ if (display->hw_config.ctrl_reset_gpio != -1)
++ gpio_direction_output(display->hw_config.ctrl_reset_gpio, 1);
++
++ printk("osc_ck %lu\n", blizzard_get_clock_rate());
++
++ return 0;
++}
++
++static void n800_blizzard_disable(struct omap_display *display)
++{
++ printk("disabling bliz powers\n");
++
++ if (display->hw_config.ctrl_reset_gpio != -1)
++ gpio_direction_output(display->hw_config.ctrl_reset_gpio, 0);
++
++ clk_disable(blizzard.sys_ck);
++
++ /* Vcore to 1.005V */
++ tahvo_set_clear_reg_bits(0x07, 0xf, 0);
++}
++
++static int n800_set_backlight_level(struct omap_display *display, int level)
++{
++ return 0;
++}
++
++static struct omap_dss_display_config n800_dsi_display_data = {
++ .type = OMAP_DISPLAY_TYPE_DBI,
++ .name = "lcd",
++ .ctrl_name = "ctrl-blizzard",
++ .panel_name = "panel-pn800",
++ .panel_reset_gpio = -1,
++ .ctrl_reset_gpio = N800_BLIZZARD_POWERDOWN_GPIO,
++ .panel_enable = n800_pn800_enable,
++ .panel_disable = n800_pn800_disable,
++ .ctrl_enable = n800_blizzard_enable,
++ .ctrl_disable = n800_blizzard_disable,
++ .set_backlight = n800_set_backlight_level,
++ .u.rfbi = {
++ .channel = 0,
++ /* 8 for cmd mode, 16 for pixel data. ctrl-blizzard handles switching */
++ .data_lines = 8,
++ },
++ .panel_data = 0, // XXX used for panel datalines
++};
++static struct omap_dss_board_info n800_dss_data = {
++ .num_displays = 1,
++ .displays = {
++ &n800_dsi_display_data,
++ },
+ };
+
+-static struct omap_tmp105_config n800_tmp105_config __initdata = {
+- .tmp105_irq_pin = 125,
+- .set_power = n800_tmp105_set_power,
++static struct platform_device n800_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &n800_dss_data,
++ },
+ };
+
++static void __init n800_display_init(void)
++{
++ int r;
++ const struct omap_lcd_config *conf;
++
++ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
++ if (conf != NULL) {
++ n800_dsi_display_data.panel_reset_gpio = conf->nreset_gpio;
++ n800_dsi_display_data.panel_data =
++ (void*)(u32)conf->data_lines; // XXX
++ //printk("\n\nTULI %d\n\n", conf->data_lines);
++ } else {
++ printk("\n\nEI TULLU MIOTÄÄÄ\n\n");
++ }
++
++ blizzard_get_clocks();
++ clk_enable(blizzard.sys_ck); // XXX always enable
++
++ //omapfb_set_ctrl_platform_data(&n800_blizzard_data);
++ //
++ if (n800_dsi_display_data.ctrl_reset_gpio != -1) {
++ r = gpio_request(n800_dsi_display_data.ctrl_reset_gpio,
++ "Blizzard pd");
++ if (r < 0) {
++ n800_dsi_display_data.ctrl_reset_gpio = -1;
++ printk(KERN_ERR "Unable to get Blizzard GPIO\n");
++ } else {
++ gpio_direction_output(n800_dsi_display_data.ctrl_reset_gpio,
++ 1);
++ // XXX always enable
++ }
++ }
++
++ if (n800_dsi_display_data.panel_reset_gpio != -1) {
++ r = gpio_request(n800_dsi_display_data.panel_reset_gpio,
++ "panel reset");
++ if (r < 0) {
++ n800_dsi_display_data.panel_reset_gpio = -1;
++ printk(KERN_ERR "Unable to get pn800 GPIO\n");
++ } else {
++ gpio_direction_output(n800_dsi_display_data.panel_reset_gpio,
++ 1);
++ // XXX always enable
++ }
++ }
++}
++
++/* DISPLAY END */
++
++
++
++
++
+ static void mipid_shutdown(struct mipid_platform_data *pdata)
+ {
+ if (pdata->nreset_gpio != -1) {
+@@ -128,6 +283,7 @@ static struct mipid_platform_data n800_mipid_platform_data = {
+ .shutdown = mipid_shutdown,
+ };
+
++#if 0
+ static void __init mipid_dev_init(void)
+ {
+ const struct omap_lcd_config *conf;
+@@ -138,26 +294,9 @@ static void __init mipid_dev_init(void)
+ n800_mipid_platform_data.data_lines = conf->data_lines;
+ }
+ }
++#endif
+
+-static struct {
+- struct clk *sys_ck;
+-} blizzard;
+-
+-static int blizzard_get_clocks(void)
+-{
+- blizzard.sys_ck = clk_get(0, "osc_ck");
+- if (IS_ERR(blizzard.sys_ck)) {
+- printk(KERN_ERR "can't get Blizzard clock\n");
+- return PTR_ERR(blizzard.sys_ck);
+- }
+- return 0;
+-}
+-
+-static unsigned long blizzard_get_clock_rate(struct device *dev)
+-{
+- return clk_get_rate(blizzard.sys_ck);
+-}
+-
++#if 0
+ static void blizzard_enable_clocks(int enable)
+ {
+ if (enable)
+@@ -202,14 +341,12 @@ static void __init blizzard_dev_init(void)
+ gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1);
+
+ blizzard_get_clocks();
+- omapfb_set_ctrl_platform_data(&n800_blizzard_data);
++ //omapfb_set_ctrl_platform_data(&n800_blizzard_data);
+ }
++#endif
+
+ static struct omap_board_config_kernel n800_config[] __initdata = {
+ { OMAP_TAG_UART, &n800_uart_config },
+- { OMAP_TAG_FBMEM, &n800_fbmem0_config },
+- { OMAP_TAG_FBMEM, &n800_fbmem1_config },
+- { OMAP_TAG_FBMEM, &n800_fbmem2_config },
+ { OMAP_TAG_TMP105, &n800_tmp105_config },
+ };
+
+@@ -257,7 +394,7 @@ static struct omap2_mcspi_device_config cx3110x_mcspi_config = {
+
+ static struct spi_board_info n800_spi_board_info[] __initdata = {
+ {
+- .modalias = "lcd_mipid",
++ .modalias = "panel-n800",
+ .bus_num = 1,
+ .chip_select = 1,
+ .max_speed_hz = 4000000,
+@@ -281,7 +418,7 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
+
+ static struct spi_board_info n810_spi_board_info[] __initdata = {
+ {
+- .modalias = "lcd_mipid",
++ .modalias = "panel-n800",
+ .bus_num = 1,
+ .chip_select = 1,
+ .max_speed_hz = 4000000,
+@@ -390,6 +527,7 @@ static struct platform_device *n800_devices[] __initdata = {
+ #if defined(CONFIG_CBUS_RETU_HEADSET)
+ &retu_headset_device,
+ #endif
++ &n800_dss_device,
+ };
+
+ #ifdef CONFIG_MENELAUS
+@@ -554,9 +692,10 @@ void __init nokia_n800_common_init(void)
+ if (machine_is_nokia_n810())
+ i2c_register_board_info(2, n810_i2c_board_info_2,
+ ARRAY_SIZE(n810_i2c_board_info_2));
+-
+- mipid_dev_init();
+- blizzard_dev_init();
++
++ //mipid_dev_init();
++ //blizzard_dev_init();
++ n800_display_init();
+ board_onenand_init();
+ }
+
+@@ -575,6 +714,7 @@ void __init nokia_n800_map_io(void)
+ omap_board_config_size = ARRAY_SIZE(n800_config);
+
+ omap2_set_globals_242x();
++ omap2_set_sdram_vram(800 * 480 * 2 * 3, 0);
+ omap2_map_common_io();
+ }
+
+diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
+index 0419ec8..356ceb1 100644
+--- a/drivers/video/omap2/displays/Kconfig
++++ b/drivers/video/omap2/displays/Kconfig
+@@ -18,4 +18,14 @@ config PANEL_SHARP_LS037V7DW01
+ depends on OMAP2_DSS
+ help
+ LCD Panel used in TI's SDP3430 and EVM boards
++
++config PANEL_N800
++ tristate "Panel N8x0"
++ help
++ N8x0 LCD (hack)
++
++config CTRL_BLIZZARD
++ tristate "Blizzard Controller"
++ help
++ Blizzard Controller (hack)
+ endmenu
+diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
+index a26bbd2..1b74b7e 100644
+--- a/drivers/video/omap2/displays/Makefile
++++ b/drivers/video/omap2/displays/Makefile
+@@ -1,3 +1,6 @@
+ obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
+ obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
+ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
++
++obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
++obj-$(CONFIG_PANEL_N800) += panel-n800.o
+diff --git a/drivers/video/omap2/displays/ctrl-blizzard.c b/drivers/video/omap2/displays/ctrl-blizzard.c
+new file mode 100644
+index 0000000..6698e4d
+--- /dev/null
++++ b/drivers/video/omap2/displays/ctrl-blizzard.c
+@@ -0,0 +1,279 @@
++
++//#define DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++
++#include <mach/display.h>
++#include <mach/dma.h>
++
++#ifdef DEBUG
++#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++#define BLIZZARD_REV_CODE 0x00
++#define BLIZZARD_CONFIG 0x02
++#define BLIZZARD_PLL_DIV 0x04
++#define BLIZZARD_PLL_LOCK_RANGE 0x06
++#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
++#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
++#define BLIZZARD_PLL_MODE 0x0c
++#define BLIZZARD_CLK_SRC 0x0e
++#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
++#define BLIZZARD_MEM_BANK0_STATUS 0x14
++#define BLIZZARD_PANEL_CONFIGURATION 0x28
++#define BLIZZARD_HDISP 0x2a
++#define BLIZZARD_HNDP 0x2c
++#define BLIZZARD_VDISP0 0x2e
++#define BLIZZARD_VDISP1 0x30
++#define BLIZZARD_VNDP 0x32
++#define BLIZZARD_HSW 0x34
++#define BLIZZARD_VSW 0x38
++#define BLIZZARD_DISPLAY_MODE 0x68
++#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
++#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
++#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
++#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
++#define BLIZZARD_POWER_SAVE 0xE6
++#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
++
++/* Data source select */
++/* For S1D13745 */
++#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
++#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
++#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
++#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
++/* For S1D13744 */
++#define BLIZZARD_SRC_WRITE_LCD 0x00
++#define BLIZZARD_SRC_BLT_LCD 0x06
++
++#define BLIZZARD_COLOR_RGB565 0x01
++#define BLIZZARD_COLOR_YUV420 0x09
++
++#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
++#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
++
++#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
++
++
++
++static struct {
++ int version;
++} blizzard;
++
++
++static inline void blizzard_cmd(u8 cmd)
++{
++ omap_rfbi_write_command(&cmd, 1);
++}
++
++static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
++{
++ omap_rfbi_write_command(&cmd, 1);
++ omap_rfbi_write_data(buf, len);
++}
++
++static inline void blizzard_read(u8 cmd, u8 *buf, int len)
++{
++ omap_rfbi_write_command(&cmd, 1);
++ omap_rfbi_read_data(buf, len);
++}
++
++static u8 blizzard_read_reg(u8 cmd)
++{
++ u8 data;
++ blizzard_read(cmd, &data, 1);
++ return data;
++}
++
++static int blizzard_ctrl_init(struct omap_display *display)
++{
++ DBG("blizzard_ctrl_init\n");
++
++ return 0;
++}
++
++
++static int blizzard_ctrl_enable(struct omap_display *display)
++{
++ int r = 0;
++ u8 rev, conf;
++
++ DBG("blizzard_ctrl_enable\n");
++
++ if (display->hw_config.ctrl_enable) {
++ r = display->hw_config.ctrl_enable(display);
++ if (r)
++ return r;
++ }
++
++ msleep(100);
++
++ rev = blizzard_read_reg(BLIZZARD_CLK_SRC);
++ printk("CLK_SRC %x\n", rev);
++
++ rev = blizzard_read_reg(BLIZZARD_PLL_DIV);
++ printk("PLLDIV %x\n", rev);
++
++ rev = blizzard_read_reg(BLIZZARD_REV_CODE);
++ conf = blizzard_read_reg(BLIZZARD_CONFIG);
++
++ printk("rev %x, conf %x\n", rev, conf);
++
++ switch (rev & 0xfc) {
++ case 0x9c:
++ blizzard.version = BLIZZARD_VERSION_S1D13744;
++ pr_info("omapfb: s1d13744 LCD controller rev %d "
++ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
++ break;
++ case 0xa4:
++ blizzard.version = BLIZZARD_VERSION_S1D13745;
++ pr_info("omapfb: s1d13745 LCD controller rev %d "
++ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
++ break;
++ default:
++ printk("invalid s1d1374x revision %02x\n",
++ rev);
++ r = -ENODEV;
++ }
++
++ return r;
++}
++
++static void blizzard_ctrl_disable(struct omap_display *display)
++{
++ DBG("blizzard_ctrl_disable\n");
++
++ if (display->hw_config.ctrl_disable)
++ display->hw_config.ctrl_disable(display);
++}
++
++int rfbi_configure(int rfbi_module, int bpp, int lines);
++
++static void blizzard_ctrl_setup_update(struct omap_display *display,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ u8 tmp[18];
++ int x_end, y_end;
++
++ DBG("blizzard_ctrl_setup_update\n");
++
++ x_end = x + w - 1;
++ y_end = y + h - 1;
++
++ tmp[0] = x;
++ tmp[1] = x >> 8;
++ tmp[2] = y;
++ tmp[3] = y >> 8;
++ tmp[4] = x_end;
++ tmp[5] = x_end >> 8;
++ tmp[6] = y_end;
++ tmp[7] = y_end >> 8;
++
++ /* scaling? */
++ tmp[8] = x;
++ tmp[9] = x >> 8;
++ tmp[10] = y;
++ tmp[11] = y >> 8;
++ tmp[12] = x_end;
++ tmp[13] = x_end >> 8;
++ tmp[14] = y_end;
++ tmp[15] = y_end >> 8;
++
++ tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode;
++
++ if (blizzard.version == BLIZZARD_VERSION_S1D13745)
++ tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
++ else
++ tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
++ BLIZZARD_SRC_WRITE_LCD :
++ BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
++
++ rfbi_configure(display->hw_config.u.rfbi.channel,
++ 16,
++ 8);
++
++ blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
++
++ rfbi_configure(display->hw_config.u.rfbi.channel,
++ 16,
++ 16);
++}
++
++static int blizzard_ctrl_enable_te(struct omap_display *display, bool enable)
++{
++ return 0;
++}
++
++static int blizzard_ctrl_rotate(struct omap_display *display, u8 rotate)
++{
++ return 0;
++}
++
++static int blizzard_ctrl_mirror(struct omap_display *display, bool enable)
++{
++ return 0;
++}
++
++static int blizzard_run_test(struct omap_display *display, int test_num)
++{
++ return 0;
++}
++
++static struct omap_ctrl blizzard_ctrl = {
++ .owner = THIS_MODULE,
++ .name = "ctrl-blizzard",
++ .init = blizzard_ctrl_init,
++ .enable = blizzard_ctrl_enable,
++ .disable = blizzard_ctrl_disable,
++ .setup_update = blizzard_ctrl_setup_update,
++ .enable_te = blizzard_ctrl_enable_te,
++ .set_rotate = blizzard_ctrl_rotate,
++ .set_mirror = blizzard_ctrl_mirror,
++ .run_test = blizzard_run_test,
++ .pixel_size = 16,
++
++ .timings = {
++ .cs_on_time = 0,
++
++ .we_on_time = 9000,
++ .we_off_time = 18000,
++ .we_cycle_time = 36000,
++
++ .re_on_time = 9000,
++ .re_off_time = 27000,
++ .re_cycle_time = 36000,
++
++ .access_time = 27000,
++ .cs_off_time = 36000,
++
++ .cs_pulse_width = 0,
++ },
++};
++
++
++static int __init blizzard_init(void)
++{
++ DBG("blizzard_init\n");
++ omap_dss_register_ctrl(&blizzard_ctrl);
++ return 0;
++}
++
++static void __exit blizzard_exit(void)
++{
++ DBG("blizzard_exit\n");
++
++ omap_dss_unregister_ctrl(&blizzard_ctrl);
++}
++
++module_init(blizzard_init);
++module_exit(blizzard_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("Blizzard Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-n800.c b/drivers/video/omap2/displays/panel-n800.c
+new file mode 100644
+index 0000000..91d3e37
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-n800.c
+@@ -0,0 +1,435 @@
++
++/*#define DEBUG*/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/spi/spi.h>
++#include <linux/jiffies.h>
++#include <linux/sched.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++
++#include <mach/display.h>
++#include <mach/dma.h>
++
++#define MIPID_CMD_READ_DISP_ID 0x04
++#define MIPID_CMD_READ_RED 0x06
++#define MIPID_CMD_READ_GREEN 0x07
++#define MIPID_CMD_READ_BLUE 0x08
++#define MIPID_CMD_READ_DISP_STATUS 0x09
++#define MIPID_CMD_RDDSDR 0x0F
++#define MIPID_CMD_SLEEP_IN 0x10
++#define MIPID_CMD_SLEEP_OUT 0x11
++#define MIPID_CMD_DISP_OFF 0x28
++#define MIPID_CMD_DISP_ON 0x29
++
++#define MIPID_VER_LPH8923 3
++#define MIPID_VER_LS041Y3 4
++
++#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
++
++#ifdef DEBUG
++#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__)
++#else
++#define DBG(format, ...)
++#endif
++
++struct pn800_device {
++ struct backlight_device *bl_dev;
++ int enabled;
++ int model;
++ int revision;
++ u8 display_id[3];
++ unsigned int saved_bklight_level;
++ unsigned long hw_guard_end; /* next value of jiffies
++ when we can issue the
++ next sleep in/out command */
++ unsigned long hw_guard_wait; /* max guard time in jiffies */
++
++ struct spi_device *spi;
++ struct mutex mutex;
++ struct omap_panel panel;
++ struct omap_display *display;
++};
++
++
++static void pn800_transfer(struct pn800_device *md, int cmd,
++ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
++{
++ struct spi_message m;
++ struct spi_transfer *x, xfer[4];
++ u16 w;
++ int r;
++
++ BUG_ON(md->spi == NULL);
++
++ spi_message_init(&m);
++
++ memset(xfer, 0, sizeof(xfer));
++ x = &xfer[0];
++
++ cmd &= 0xff;
++ x->tx_buf = &cmd;
++ x->bits_per_word = 9;
++ x->len = 2;
++ spi_message_add_tail(x, &m);
++
++ if (wlen) {
++ x++;
++ x->tx_buf = wbuf;
++ x->len = wlen;
++ x->bits_per_word = 9;
++ spi_message_add_tail(x, &m);
++ }
++
++ if (rlen) {
++ x++;
++ x->rx_buf = &w;
++ x->len = 1;
++ spi_message_add_tail(x, &m);
++
++ if (rlen > 1) {
++ /* Arrange for the extra clock before the first
++ * data bit.
++ */
++ x->bits_per_word = 9;
++ x->len = 2;
++
++ x++;
++ x->rx_buf = &rbuf[1];
++ x->len = rlen - 1;
++ spi_message_add_tail(x, &m);
++ }
++ }
++
++ r = spi_sync(md->spi, &m);
++ if (r < 0)
++ dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
++
++ if (rlen)
++ rbuf[0] = w & 0xff;
++}
++
++static inline void pn800_cmd(struct pn800_device *md, int cmd)
++{
++ pn800_transfer(md, cmd, NULL, 0, NULL, 0);
++}
++
++static inline void pn800_write(struct pn800_device *md,
++ int reg, const u8 *buf, int len)
++{
++ pn800_transfer(md, reg, buf, len, NULL, 0);
++}
++
++static inline void pn800_read(struct pn800_device *md,
++ int reg, u8 *buf, int len)
++{
++ pn800_transfer(md, reg, NULL, 0, buf, len);
++}
++
++static void set_data_lines(struct pn800_device *md, int data_lines)
++{
++ u16 par;
++
++ switch (data_lines) {
++ case 16:
++ par = 0x150;
++ break;
++ case 18:
++ par = 0x160;
++ break;
++ case 24:
++ par = 0x170;
++ break;
++ }
++ pn800_write(md, 0x3a, (u8 *)&par, 2);
++}
++
++static void send_init_string(struct pn800_device *md)
++{
++ u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
++ int data_lines;
++
++ pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
++
++ data_lines = (int)md->display->hw_config.panel_data; // XXX
++
++ set_data_lines(md, data_lines);
++}
++
++static void hw_guard_start(struct pn800_device *md, int guard_msec)
++{
++ md->hw_guard_wait = msecs_to_jiffies(guard_msec);
++ md->hw_guard_end = jiffies + md->hw_guard_wait;
++}
++
++static void hw_guard_wait(struct pn800_device *md)
++{
++ unsigned long wait = md->hw_guard_end - jiffies;
++
++ if ((long)wait > 0 && wait <= md->hw_guard_wait) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(wait);
++ }
++}
++
++static void set_sleep_mode(struct pn800_device *md, int on)
++{
++ int cmd, sleep_time = 50;
++
++ if (on)
++ cmd = MIPID_CMD_SLEEP_IN;
++ else
++ cmd = MIPID_CMD_SLEEP_OUT;
++ hw_guard_wait(md);
++ pn800_cmd(md, cmd);
++ hw_guard_start(md, 120);
++ /*
++ * When we enable the panel, it seems we _have_ to sleep
++ * 120 ms before sending the init string. When disabling the
++ * panel we'll sleep for the duration of 2 frames, so that the
++ * controller can still provide the PCLK,HS,VS signals. */
++ if (!on)
++ sleep_time = 120;
++ msleep(sleep_time);
++}
++
++static void set_display_state(struct pn800_device *md, int enabled)
++{
++ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
++
++ pn800_cmd(md, cmd);
++}
++
++static int panel_enabled(struct pn800_device *md)
++{
++ u32 disp_status;
++ int enabled;
++
++ pn800_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
++ disp_status = __be32_to_cpu(disp_status);
++ enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
++ dev_dbg(&md->spi->dev,
++ "LCD panel %s enabled by bootloader (status 0x%04x)\n",
++ enabled ? "" : "not ", disp_status);
++ DBG("status %#08x\n", disp_status);
++ return enabled;
++}
++
++static int panel_detect(struct pn800_device *md)
++{
++ pn800_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
++ dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
++ md->display_id[0], md->display_id[1], md->display_id[2]);
++
++ switch (md->display_id[0]) {
++ case 0x45:
++ md->model = MIPID_VER_LPH8923;
++ md->panel.name = "lph8923";
++ break;
++ case 0x83:
++ md->model = MIPID_VER_LS041Y3;
++ md->panel.name = "ls041y3";
++ //md->esd_check = ls041y3_esd_check;
++ break;
++ default:
++ md->panel.name = "unknown";
++ dev_err(&md->spi->dev, "invalid display ID\n");
++ return -ENODEV;
++ }
++
++ md->revision = md->display_id[1];
++ pr_info("omapfb: %s rev %02x LCD detected\n",
++ md->panel.name, md->revision);
++
++ return 0;
++}
++
++
++
++static int pn800_panel_enable(struct omap_display *display)
++{
++ int r;
++ struct pn800_device *md =
++ (struct pn800_device *)display->panel->priv;
++
++ DBG("pn800_panel_enable\n");
++
++ mutex_lock(&md->mutex);
++
++ if (display->hw_config.panel_enable)
++ display->hw_config.panel_enable(display);
++
++ msleep(50); // wait for power up
++
++ r = panel_detect(md);
++ if (r) {
++ mutex_unlock(&md->mutex);
++ return r;
++ }
++
++ md->enabled = panel_enabled(md);
++
++ if (md->enabled) {
++ DBG("panel already enabled\n");
++ ; /*pn800_esd_start_check(md);*/
++ } else {
++ ; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
++ }
++
++
++ if (md->enabled) {
++ mutex_unlock(&md->mutex);
++ return 0;
++ }
++
++ set_sleep_mode(md, 0);
++ md->enabled = 1;
++ send_init_string(md);
++ set_display_state(md, 1);
++ //mipid_set_bklight_level(panel, md->saved_bklight_level);
++ //mipid_esd_start_check(md);
++
++ mutex_unlock(&md->mutex);
++ return 0;
++}
++
++static void pn800_panel_disable(struct omap_display *display)
++{
++ struct pn800_device *md =
++ (struct pn800_device *)display->panel->priv;
++
++ DBG("pn800_panel_disable\n");
++
++ mutex_lock(&md->mutex);
++
++ if (!md->enabled) {
++ mutex_unlock(&md->mutex);
++ return;
++ }
++ /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
++ /*pn800_set_bklight_level(panel, 0);*/
++
++ set_display_state(md, 0);
++ set_sleep_mode(md, 1);
++ md->enabled = 0;
++
++
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++
++ mutex_unlock(&md->mutex);
++}
++
++static int pn800_panel_init(struct omap_display *display)
++{
++ struct pn800_device *md =
++ (struct pn800_device *)display->panel->priv;
++
++ DBG("pn800_panel_init\n");
++
++ mutex_init(&md->mutex);
++ md->display = display;
++
++ return 0;
++}
++
++static int pn800_run_test(struct omap_display *display, int test_num)
++{
++ return 0;
++}
++
++static struct omap_panel pn800_panel = {
++ .owner = THIS_MODULE,
++ .name = "panel-pn800",
++ .init = pn800_panel_init,
++ /*.remove = pn800_cleanup,*/
++ .enable = pn800_panel_enable,
++ .disable = pn800_panel_disable,
++ //.set_mode = pn800_set_mode,
++ .run_test = pn800_run_test,
++
++ .timings = {
++ .x_res = 800,
++ .y_res = 480,
++
++ .pixel_clock = 21940,
++ .hsw = 50,
++ .hfp = 20,
++ .hbp = 15,
++
++ .vsw = 2,
++ .vfp = 1,
++ .vbp = 3,
++ },
++ .config = OMAP_DSS_LCD_TFT,
++};
++
++static int pn800_spi_probe(struct spi_device *spi)
++{
++ struct pn800_device *md;
++
++ DBG("pn800_spi_probe\n");
++
++ md = kzalloc(sizeof(*md), GFP_KERNEL);
++ if (md == NULL) {
++ dev_err(&spi->dev, "out of memory\n");
++ return -ENOMEM;
++ }
++
++ spi->mode = SPI_MODE_0;
++ md->spi = spi;
++ dev_set_drvdata(&spi->dev, md);
++ md->panel = pn800_panel;
++ pn800_panel.priv = md;
++
++ omap_dss_register_panel(&pn800_panel);
++
++ return 0;
++}
++
++static int pn800_spi_remove(struct spi_device *spi)
++{
++ struct pn800_device *md = dev_get_drvdata(&spi->dev);
++
++ DBG("pn800_spi_remove\n");
++
++ omap_dss_unregister_panel(&pn800_panel);
++
++ /*pn800_disable(&md->panel);*/
++ kfree(md);
++
++ return 0;
++}
++
++static struct spi_driver pn800_spi_driver = {
++ .driver = {
++ .name = "panel-n800",
++ .bus = &spi_bus_type,
++ .owner = THIS_MODULE,
++ },
++ .probe = pn800_spi_probe,
++ .remove = __devexit_p(pn800_spi_remove),
++};
++
++static int __init pn800_init(void)
++{
++ DBG("pn800_init\n");
++ return spi_register_driver(&pn800_spi_driver);
++}
++
++static void __exit pn800_exit(void)
++{
++ DBG("pn800_exit\n");
++ spi_unregister_driver(&pn800_spi_driver);
++}
++
++module_init(pn800_init);
++module_exit(pn800_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("N800 LCD Driver");
++MODULE_LICENSE("GPL");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0006-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch b/recipes/linux/linux-omap-pm/dss2/0006-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch
new file mode 100644
index 0000000000..6073d22d20
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0006-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch
@@ -0,0 +1,5703 @@
+From 9b34ebb747ba53f9c0c90c21764dbc1e1d967ad3 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 10:36:05 +0300
+Subject: [PATCH 006/146] DSS2: Add DSS2 support for SDP, Beagle, Overo, EVM
+
+Also custom dss_*_defconfigs as an example.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/configs/dss_omap3_beagle_defconfig | 1371 ++++++++++++++++++++
+ arch/arm/configs/dss_omap_3430sdp_defconfig | 1634 +++++++++++++++++++++++
+ arch/arm/configs/dss_overo_defconfig | 1862 +++++++++++++++++++++++++++
+ arch/arm/mach-omap2/board-3430sdp.c | 227 ++++-
+ arch/arm/mach-omap2/board-omap3beagle.c | 91 ++-
+ arch/arm/mach-omap2/board-omap3evm.c | 217 +++-
+ arch/arm/mach-omap2/board-overo.c | 98 ++-
+ 7 files changed, 5475 insertions(+), 25 deletions(-)
+ create mode 100644 arch/arm/configs/dss_omap3_beagle_defconfig
+ create mode 100644 arch/arm/configs/dss_omap_3430sdp_defconfig
+ create mode 100644 arch/arm/configs/dss_overo_defconfig
+
+diff --git a/arch/arm/configs/dss_omap3_beagle_defconfig b/arch/arm/configs/dss_omap3_beagle_defconfig
+new file mode 100644
+index 0000000..7143168
+--- /dev/null
++++ b/arch/arm/configs/dss_omap3_beagle_defconfig
+@@ -0,0 +1,1371 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29-omap1
++# Thu Apr 2 11:24:09 2009
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_COMPAT_BRK=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_W90X900 is not set
++
++#
++# TI OMAP Implementations
++#
++CONFIG_ARCH_OMAP_OTG=y
++# CONFIG_ARCH_OMAP1 is not set
++# CONFIG_ARCH_OMAP2 is not set
++CONFIG_ARCH_OMAP3=y
++
++#
++# OMAP Feature Selections
++#
++# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
++# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
++# CONFIG_OMAP_SMARTREFLEX is not set
++# CONFIG_OMAP_RESET_CLOCKS is not set
++CONFIG_OMAP_BOOT_TAG=y
++CONFIG_OMAP_BOOT_REASON=y
++# CONFIG_OMAP_COMPONENT_VERSION is not set
++# CONFIG_OMAP_GPIO_SWITCH is not set
++# CONFIG_OMAP_MUX is not set
++# CONFIG_OMAP_MCBSP is not set
++# CONFIG_OMAP_MBOX_FWK is not set
++# CONFIG_OMAP_MPU_TIMER is not set
++CONFIG_OMAP_32K_TIMER=y
++CONFIG_OMAP_32K_TIMER_HZ=128
++CONFIG_OMAP_TICK_GPTIMER=12
++CONFIG_OMAP_DM_TIMER=y
++# CONFIG_OMAP_LL_DEBUG_UART1 is not set
++# CONFIG_OMAP_LL_DEBUG_UART2 is not set
++CONFIG_OMAP_LL_DEBUG_UART3=y
++CONFIG_ARCH_OMAP34XX=y
++CONFIG_ARCH_OMAP3430=y
++
++#
++# OMAP Board Type
++#
++# CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_LDP is not set
++# CONFIG_MACH_OMAP_3430SDP is not set
++# CONFIG_MACH_OMAP3EVM is not set
++CONFIG_MACH_OMAP3_BEAGLE=y
++# CONFIG_MACH_OVERO is not set
++# CONFIG_MACH_OMAP3_PANDORA is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_IFAR=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_ARM_THUMBEE is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++CONFIG_HAS_TLS_REG=y
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.2.14:/tftpboot/rootfs ip=192.168.2.15 nolock,rsize=1024,wsize=1024 rw"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++CONFIG_VFPv3=y
++# CONFIG_NEON is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_MISC=y
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++# CONFIG_SUSPEND is not set
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_LIB80211 is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_OMAP2=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_LIBFC is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=32
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_OMAP=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TWL4030_MADC is not set
++# CONFIG_TWL4030_POWEROFF is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++# CONFIG_DEBUG_GPIO is not set
++# CONFIG_GPIO_SYSFS is not set
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++CONFIG_GPIO_TWL4030=y
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_TPS65010 is not set
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_POWER is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_PCF50633 is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=m
++CONFIG_FB_CFB_COPYAREA=m
++CONFIG_FB_CFB_IMAGEBLIT=m
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
++CONFIG_OMAP2_DSS=m
++CONFIG_OMAP2_DSS_VRAM_SIZE=12
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_RFBI is not set
++CONFIG_OMAP2_DSS_VENC=y
++# CONFIG_OMAP2_DSS_SDI is not set
++# CONFIG_OMAP2_DSS_DSI is not set
++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC=m
++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
++# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
++# CONFIG_PANEL_N800 is not set
++# CONFIG_CTRL_BLIZZARD is not set
++CONFIG_FB_OMAP2=m
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
++CONFIG_FB_OMAP2_NUM_FBS=3
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++CONFIG_USB_MUSB_HDRC=y
++CONFIG_USB_MUSB_SOC=y
++
++#
++# OMAP 343x high speed USB support
++#
++# CONFIG_USB_MUSB_HOST is not set
++CONFIG_USB_MUSB_PERIPHERAL=y
++# CONFIG_USB_MUSB_OTG is not set
++CONFIG_USB_GADGET_MUSB_HDRC=y
++# CONFIG_MUSB_PIO_ONLY is not set
++CONFIG_USB_INVENTRA_DMA=y
++# CONFIG_USB_TI_CPPI_DMA is not set
++# CONFIG_USB_MUSB_DEBUG is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++# CONFIG_USB_GADGET_DEBUG_FS is not set
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_PXA25X is not set
++# CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_IMX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_QE is not set
++# CONFIG_USB_GADGET_CI13XXX is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++
++#
++# OTG and related infrastructure
++#
++CONFIG_USB_OTG_UTILS=y
++# CONFIG_USB_GPIO_VBUS is not set
++# CONFIG_ISP1301_OMAP is not set
++CONFIG_TWL4030_USB=y
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_OMAP_HS=y
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_BQ24022 is not set
++CONFIG_REGULATOR_TWL4030=y
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# CBUS support
++#
++# CONFIG_CBUS is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++CONFIG_QUOTA_TREE=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_FUNCTION_TRACER is not set
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_BOOT_TRACER is not set
++# CONFIG_TRACE_BRANCH_PROFILING is not set
++# CONFIG_STACK_TRACER is not set
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/dss_omap_3430sdp_defconfig b/arch/arm/configs/dss_omap_3430sdp_defconfig
+new file mode 100644
+index 0000000..dc30dce
+--- /dev/null
++++ b/arch/arm/configs/dss_omap_3430sdp_defconfig
+@@ -0,0 +1,1634 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29-omap1
++# Thu Apr 2 11:11:24 2009
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_COMPAT_BRK=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_W90X900 is not set
++
++#
++# TI OMAP Implementations
++#
++CONFIG_ARCH_OMAP_OTG=y
++# CONFIG_ARCH_OMAP1 is not set
++# CONFIG_ARCH_OMAP2 is not set
++CONFIG_ARCH_OMAP3=y
++
++#
++# OMAP Feature Selections
++#
++# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
++# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
++CONFIG_OMAP_SMARTREFLEX=y
++# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
++CONFIG_OMAP_RESET_CLOCKS=y
++CONFIG_OMAP_BOOT_TAG=y
++CONFIG_OMAP_BOOT_REASON=y
++# CONFIG_OMAP_COMPONENT_VERSION is not set
++# CONFIG_OMAP_GPIO_SWITCH is not set
++CONFIG_OMAP_MUX=y
++CONFIG_OMAP_MUX_DEBUG=y
++CONFIG_OMAP_MUX_WARNINGS=y
++# CONFIG_OMAP_MCBSP is not set
++# CONFIG_OMAP_MBOX_FWK is not set
++# CONFIG_OMAP_MPU_TIMER is not set
++CONFIG_OMAP_32K_TIMER=y
++CONFIG_OMAP_32K_TIMER_HZ=128
++CONFIG_OMAP_TICK_GPTIMER=1
++CONFIG_OMAP_DM_TIMER=y
++CONFIG_OMAP_LL_DEBUG_UART1=y
++# CONFIG_OMAP_LL_DEBUG_UART2 is not set
++# CONFIG_OMAP_LL_DEBUG_UART3 is not set
++CONFIG_OMAP_SERIAL_WAKE=y
++CONFIG_ARCH_OMAP34XX=y
++CONFIG_ARCH_OMAP3430=y
++
++#
++# OMAP Board Type
++#
++# CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_LDP is not set
++CONFIG_MACH_OMAP_3430SDP=y
++# CONFIG_MACH_OMAP3EVM is not set
++# CONFIG_MACH_OMAP3_BEAGLE is not set
++# CONFIG_MACH_OVERO is not set
++# CONFIG_MACH_OMAP3_PANDORA is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_IFAR=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_ARM_THUMBEE is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++CONFIG_HAS_TLS_REG=y
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++CONFIG_VFPv3=y
++# CONFIG_NEON is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_MISC=y
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_LIB80211 is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++CONFIG_MTD_OMAP_NOR=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_ECC_SMC=y
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_OMAP2=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_ONENAND=y
++CONFIG_MTD_ONENAND_VERIFY_WRITE=y
++# CONFIG_MTD_ONENAND_GENERIC is not set
++CONFIG_MTD_ONENAND_OMAP2=y
++# CONFIG_MTD_ONENAND_OTP is not set
++# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
++# CONFIG_MTD_ONENAND_SIM is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_ICS932S401 is not set
++# CONFIG_OMAP_STI is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++# CONFIG_EEPROM_AT24 is not set
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_LIBFC is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_AX88796 is not set
++CONFIG_SMC91X=y
++# CONFIG_DM9000 is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_SMC911X is not set
++# CONFIG_SMSC911X is not set
++# CONFIG_DNET is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_TWL4030=y
++# CONFIG_KEYBOARD_GPIO is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_INEXIO is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_TSC2005 is not set
++# CONFIG_TOUCHSCREEN_TSC210X is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=32
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_OMAP=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TWL4030_MADC is not set
++# CONFIG_TWL4030_POWEROFF is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_BITBANG is not set
++# CONFIG_SPI_GPIO is not set
++CONFIG_SPI_OMAP24XX=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_TSC210X is not set
++# CONFIG_SPI_TSC2301 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++# CONFIG_DEBUG_GPIO is not set
++# CONFIG_GPIO_SYSFS is not set
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++CONFIG_GPIO_TWL4030=y
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_OMAP_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_TPS65010 is not set
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_POWER is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_PCF50633 is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=m
++CONFIG_FB_CFB_COPYAREA=m
++CONFIG_FB_CFB_IMAGEBLIT=m
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_FB_OMAP_LCD_VGA is not set
++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
++CONFIG_OMAP2_DSS=m
++CONFIG_OMAP2_DSS_VRAM_SIZE=8
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_RFBI is not set
++CONFIG_OMAP2_DSS_VENC=y
++# CONFIG_OMAP2_DSS_SDI is not set
++# CONFIG_OMAP2_DSS_DSI is not set
++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC=m
++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
++CONFIG_PANEL_SHARP_LS037V7DW01=m
++# CONFIG_PANEL_N800 is not set
++# CONFIG_CTRL_BLIZZARD is not set
++CONFIG_FB_OMAP2=m
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
++CONFIG_FB_OMAP2_NUM_FBS=3
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++# CONFIG_HID_A4TECH is not set
++# CONFIG_HID_APPLE is not set
++# CONFIG_HID_BELKIN is not set
++# CONFIG_HID_CHERRY is not set
++# CONFIG_HID_CHICONY is not set
++# CONFIG_HID_CYPRESS is not set
++# CONFIG_HID_EZKEY is not set
++# CONFIG_HID_GYRATION is not set
++# CONFIG_HID_LOGITECH is not set
++# CONFIG_HID_MICROSOFT is not set
++# CONFIG_HID_MONTEREY is not set
++# CONFIG_HID_NTRIG is not set
++# CONFIG_HID_PANTHERLORD is not set
++# CONFIG_HID_PETALYNX is not set
++# CONFIG_HID_SAMSUNG is not set
++# CONFIG_HID_SONY is not set
++# CONFIG_HID_SUNPLUS is not set
++# CONFIG_GREENASIA_FF is not set
++# CONFIG_HID_TOPSEED is not set
++# CONFIG_THRUSTMASTER_FF is not set
++# CONFIG_ZEROPLUS_FF is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++CONFIG_USB_SUSPEND=y
++CONFIG_USB_OTG=y
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++CONFIG_USB_MON=y
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=m
++CONFIG_OMAP_EHCI_PHY_MODE=y
++# CONFIG_OMAP_EHCI_TLL_MODE is not set
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_OXU210HP_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++CONFIG_USB_MUSB_HDRC=y
++CONFIG_USB_MUSB_SOC=y
++
++#
++# OMAP 343x high speed USB support
++#
++# CONFIG_USB_MUSB_HOST is not set
++# CONFIG_USB_MUSB_PERIPHERAL is not set
++CONFIG_USB_MUSB_OTG=y
++CONFIG_USB_GADGET_MUSB_HDRC=y
++CONFIG_USB_MUSB_HDRC_HCD=y
++# CONFIG_MUSB_PIO_ONLY is not set
++CONFIG_USB_INVENTRA_DMA=y
++# CONFIG_USB_TI_CPPI_DMA is not set
++# CONFIG_USB_MUSB_DEBUG is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE_DEBUG=y
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++CONFIG_USB_TEST=y
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++CONFIG_USB_GADGET=y
++CONFIG_USB_GADGET_DEBUG=y
++CONFIG_USB_GADGET_DEBUG_FILES=y
++# CONFIG_USB_GADGET_DEBUG_FS is not set
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_PXA25X is not set
++# CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_IMX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_QE is not set
++# CONFIG_USB_GADGET_CI13XXX is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++CONFIG_USB_ZERO=m
++# CONFIG_USB_ZERO_HNPTEST is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++
++#
++# OTG and related infrastructure
++#
++CONFIG_USB_OTG_UTILS=y
++# CONFIG_USB_GPIO_VBUS is not set
++# CONFIG_ISP1301_OMAP is not set
++CONFIG_TWL4030_USB=y
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_OMAP_HS=m
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_BQ24022 is not set
++CONFIG_REGULATOR_TWL4030=y
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# CBUS support
++#
++# CONFIG_CBUS is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++CONFIG_QUOTA_TREE=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_FUNCTION_TRACER is not set
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_BOOT_TRACER is not set
++# CONFIG_TRACE_BRANCH_PROFILING is not set
++# CONFIG_STACK_TRACER is not set
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/dss_overo_defconfig b/arch/arm/configs/dss_overo_defconfig
+new file mode 100644
+index 0000000..755a1b6
+--- /dev/null
++++ b/arch/arm/configs/dss_overo_defconfig
+@@ -0,0 +1,1862 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29-omap1
++# Thu Apr 2 11:30:57 2009
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_OPROFILE_ARMV7=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++# CONFIG_ELF_CORE is not set
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_COMPAT_BRK is not set
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++# CONFIG_MARKERS is not set
++CONFIG_OPROFILE=y
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_W90X900 is not set
++
++#
++# TI OMAP Implementations
++#
++CONFIG_ARCH_OMAP_OTG=y
++# CONFIG_ARCH_OMAP1 is not set
++# CONFIG_ARCH_OMAP2 is not set
++CONFIG_ARCH_OMAP3=y
++
++#
++# OMAP Feature Selections
++#
++# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
++# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
++CONFIG_OMAP_SMARTREFLEX=y
++# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
++# CONFIG_OMAP_RESET_CLOCKS is not set
++CONFIG_OMAP_BOOT_TAG=y
++CONFIG_OMAP_BOOT_REASON=y
++# CONFIG_OMAP_COMPONENT_VERSION is not set
++# CONFIG_OMAP_GPIO_SWITCH is not set
++# CONFIG_OMAP_MUX is not set
++CONFIG_OMAP_MCBSP=y
++# CONFIG_OMAP_MBOX_FWK is not set
++# CONFIG_OMAP_MPU_TIMER is not set
++CONFIG_OMAP_32K_TIMER=y
++CONFIG_OMAP_32K_TIMER_HZ=128
++CONFIG_OMAP_TICK_GPTIMER=1
++CONFIG_OMAP_DM_TIMER=y
++# CONFIG_OMAP_LL_DEBUG_UART1 is not set
++# CONFIG_OMAP_LL_DEBUG_UART2 is not set
++CONFIG_OMAP_LL_DEBUG_UART3=y
++CONFIG_ARCH_OMAP34XX=y
++CONFIG_ARCH_OMAP3430=y
++
++#
++# OMAP Board Type
++#
++# CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_LDP is not set
++# CONFIG_MACH_OMAP_3430SDP is not set
++# CONFIG_MACH_OMAP3EVM is not set
++# CONFIG_MACH_OMAP3_BEAGLE is not set
++CONFIG_MACH_OVERO=y
++# CONFIG_MACH_OMAP3_PANDORA is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_IFAR=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++CONFIG_ARM_THUMBEE=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++CONFIG_HAS_TLS_REG=y
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_AEABI=y
++# CONFIG_OABI_COMPAT is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_LEDS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.2.14:/tftpboot/rootfs ip=192.168.2.15 nolock,rsize=1024,wsize=1024 rw"
++# CONFIG_XIP_KERNEL is not set
++CONFIG_KEXEC=y
++CONFIG_ATAGS_PROC=y
++
++#
++# CPU Power Management
++#
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_STAT_DETAILS=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_VFP=y
++CONFIG_VFPv3=y
++CONFIG_NEON=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=m
++CONFIG_BINFMT_MISC=y
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=y
++CONFIG_BT_L2CAP=y
++CONFIG_BT_SCO=y
++CONFIG_BT_RFCOMM=y
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=y
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=y
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIBTSDIO is not set
++CONFIG_BT_HCIUART=y
++CONFIG_BT_HCIUART_H4=y
++CONFIG_BT_HCIUART_BCSP=y
++# CONFIG_BT_HCIUART_LL is not set
++# CONFIG_BT_HCIBRF6150 is not set
++# CONFIG_BT_HCIH4P is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++CONFIG_CFG80211=y
++# CONFIG_CFG80211_REG_DEBUG is not set
++CONFIG_NL80211=y
++CONFIG_WIRELESS_OLD_REGULATORY=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_WIRELESS_EXT_SYSFS=y
++CONFIG_LIB80211=y
++CONFIG_LIB80211_CRYPT_WEP=m
++CONFIG_LIB80211_CRYPT_CCMP=m
++CONFIG_LIB80211_CRYPT_TKIP=m
++# CONFIG_LIB80211_DEBUG is not set
++CONFIG_MAC80211=y
++
++#
++# Rate control algorithm selection
++#
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_RC_MINSTREL=y
++CONFIG_MAC80211_RC_DEFAULT_PID=y
++# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
++CONFIG_MAC80211_RC_DEFAULT="pid"
++# CONFIG_MAC80211_MESH is not set
++CONFIG_MAC80211_LEDS=y
++# CONFIG_MAC80211_DEBUGFS is not set
++# CONFIG_MAC80211_DEBUG_MENU is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_OMAP2=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_CDROM_PKTCDVD_BUFFERS=8
++# CONFIG_CDROM_PKTCDVD_WCACHE is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_ICS932S401 is not set
++# CONFIG_OMAP_STI is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++# CONFIG_EEPROM_AT24 is not set
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++CONFIG_EEPROM_93CX6=m
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_RAID_ATTRS=m
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_LIBFC is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=m
++CONFIG_MD_LINEAR=m
++CONFIG_MD_RAID0=m
++CONFIG_MD_RAID1=m
++CONFIG_MD_RAID10=m
++CONFIG_MD_RAID456=m
++CONFIG_MD_RAID5_RESHAPE=y
++CONFIG_MD_MULTIPATH=m
++CONFIG_MD_FAULTY=m
++CONFIG_BLK_DEV_DM=m
++# CONFIG_DM_DEBUG is not set
++CONFIG_DM_CRYPT=m
++CONFIG_DM_SNAPSHOT=m
++CONFIG_DM_MIRROR=m
++CONFIG_DM_ZERO=m
++CONFIG_DM_MULTIPATH=m
++CONFIG_DM_DELAY=m
++# CONFIG_DM_UEVENT is not set
++CONFIG_NETDEVICES=y
++CONFIG_DUMMY=m
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++CONFIG_WLAN_80211=y
++CONFIG_LIBERTAS=y
++CONFIG_LIBERTAS_SDIO=y
++CONFIG_LIBERTAS_DEBUG=y
++# CONFIG_LIBERTAS_THINFIRM is not set
++# CONFIG_MAC80211_HWSIM is not set
++CONFIG_P54_COMMON=m
++# CONFIG_IWLWIFI_LEDS is not set
++CONFIG_HOSTAP=m
++CONFIG_HOSTAP_FIRMWARE=y
++CONFIG_HOSTAP_FIRMWARE_NVRAM=y
++# CONFIG_B43 is not set
++# CONFIG_B43LEGACY is not set
++# CONFIG_RT2X00 is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_MPPE=m
++CONFIG_PPPOE=m
++# CONFIG_PPPOL2TP is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_TWL4030 is not set
++# CONFIG_KEYBOARD_LM8323 is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++CONFIG_VT_HW_CONSOLE_BINDING=y
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=32
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_OMAP=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++CONFIG_TWL4030_MADC=m
++CONFIG_TWL4030_POWEROFF=y
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_SENSORS_TSL2563 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_BITBANG is not set
++# CONFIG_SPI_GPIO is not set
++CONFIG_SPI_OMAP24XX=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_TSC210X is not set
++# CONFIG_SPI_TSC2301 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_DEBUG_GPIO=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++CONFIG_GPIO_TWL4030=y
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++CONFIG_POWER_SUPPLY=m
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++# CONFIG_PDA_POWER is not set
++# CONFIG_BATTERY_DS2760 is not set
++# CONFIG_TWL4030_BCI_BATTERY is not set
++# CONFIG_BATTERY_BQ27x00 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ADT7475 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_TSC210X is not set
++CONFIG_SENSORS_OMAP34XX=y
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_OMAP_WATCHDOG=y
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_TPS65010 is not set
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_POWER is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_PCF50633 is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++CONFIG_VIDEO_DEV=m
++CONFIG_VIDEO_V4L2_COMMON=m
++CONFIG_VIDEO_ALLOW_V4L1=y
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_DVB_CORE=m
++CONFIG_VIDEO_MEDIA=m
++
++#
++# Multimedia drivers
++#
++CONFIG_MEDIA_ATTACH=y
++CONFIG_MEDIA_TUNER=m
++# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
++CONFIG_MEDIA_TUNER_SIMPLE=m
++CONFIG_MEDIA_TUNER_TDA8290=m
++CONFIG_MEDIA_TUNER_TDA9887=m
++CONFIG_MEDIA_TUNER_TEA5761=m
++CONFIG_MEDIA_TUNER_TEA5767=m
++CONFIG_MEDIA_TUNER_MT20XX=m
++CONFIG_MEDIA_TUNER_XC2028=m
++CONFIG_MEDIA_TUNER_XC5000=m
++CONFIG_VIDEO_V4L2=m
++CONFIG_VIDEO_V4L1=m
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_VIVI is not set
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_SOC_CAMERA is not set
++CONFIG_RADIO_ADAPTERS=y
++# CONFIG_RADIO_TEA5764 is not set
++# CONFIG_DVB_DYNAMIC_MINORS is not set
++CONFIG_DVB_CAPTURE_DRIVERS=y
++# CONFIG_TTPCI_EEPROM is not set
++# CONFIG_DVB_B2C2_FLEXCOP is not set
++
++#
++# Supported DVB Frontends
++#
++
++#
++# Customise DVB Frontends
++#
++# CONFIG_DVB_FE_CUSTOMISE is not set
++
++#
++# Multistandard (satellite) frontends
++#
++# CONFIG_DVB_STB0899 is not set
++# CONFIG_DVB_STB6100 is not set
++
++#
++# DVB-S (satellite) frontends
++#
++CONFIG_DVB_CX24110=m
++CONFIG_DVB_CX24123=m
++CONFIG_DVB_MT312=m
++CONFIG_DVB_S5H1420=m
++# CONFIG_DVB_STV0288 is not set
++# CONFIG_DVB_STB6000 is not set
++CONFIG_DVB_STV0299=m
++CONFIG_DVB_TDA8083=m
++CONFIG_DVB_TDA10086=m
++# CONFIG_DVB_TDA8261 is not set
++CONFIG_DVB_VES1X93=m
++CONFIG_DVB_TUNER_ITD1000=m
++# CONFIG_DVB_TUNER_CX24113 is not set
++CONFIG_DVB_TDA826X=m
++CONFIG_DVB_TUA6100=m
++# CONFIG_DVB_CX24116 is not set
++# CONFIG_DVB_SI21XX is not set
++
++#
++# DVB-T (terrestrial) frontends
++#
++CONFIG_DVB_SP8870=m
++CONFIG_DVB_SP887X=m
++CONFIG_DVB_CX22700=m
++CONFIG_DVB_CX22702=m
++# CONFIG_DVB_DRX397XD is not set
++CONFIG_DVB_L64781=m
++CONFIG_DVB_TDA1004X=m
++CONFIG_DVB_NXT6000=m
++CONFIG_DVB_MT352=m
++CONFIG_DVB_ZL10353=m
++CONFIG_DVB_DIB3000MB=m
++CONFIG_DVB_DIB3000MC=m
++CONFIG_DVB_DIB7000M=m
++CONFIG_DVB_DIB7000P=m
++CONFIG_DVB_TDA10048=m
++
++#
++# DVB-C (cable) frontends
++#
++CONFIG_DVB_VES1820=m
++CONFIG_DVB_TDA10021=m
++CONFIG_DVB_TDA10023=m
++CONFIG_DVB_STV0297=m
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++CONFIG_DVB_NXT200X=m
++# CONFIG_DVB_OR51211 is not set
++# CONFIG_DVB_OR51132 is not set
++CONFIG_DVB_BCM3510=m
++CONFIG_DVB_LGDT330X=m
++# CONFIG_DVB_LGDT3304 is not set
++CONFIG_DVB_S5H1409=m
++CONFIG_DVB_AU8522=m
++CONFIG_DVB_S5H1411=m
++
++#
++# ISDB-T (terrestrial) frontends
++#
++# CONFIG_DVB_S921 is not set
++
++#
++# Digital terrestrial only tuners/PLL
++#
++CONFIG_DVB_PLL=m
++CONFIG_DVB_TUNER_DIB0070=m
++
++#
++# SEC control devices for DVB-S
++#
++CONFIG_DVB_LNBP21=m
++# CONFIG_DVB_ISL6405 is not set
++CONFIG_DVB_ISL6421=m
++# CONFIG_DVB_LGS8GL5 is not set
++
++#
++# Tools to develop new frontends
++#
++# CONFIG_DVB_DUMMY_FE is not set
++# CONFIG_DVB_AF9013 is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=m
++CONFIG_FB_CFB_COPYAREA=m
++CONFIG_FB_CFB_IMAGEBLIT=m
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
++CONFIG_OMAP2_DSS=m
++CONFIG_OMAP2_DSS_VRAM_SIZE=12
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_RFBI is not set
++CONFIG_OMAP2_DSS_VENC=y
++# CONFIG_OMAP2_DSS_SDI is not set
++# CONFIG_OMAP2_DSS_DSI is not set
++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC=m
++CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
++# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
++# CONFIG_PANEL_N800 is not set
++# CONFIG_CTRL_BLIZZARD is not set
++CONFIG_FB_OMAP2=m
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
++CONFIG_FB_OMAP2_NUM_FBS=3
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
++CONFIG_SOUND=y
++CONFIG_SOUND_OSS_CORE=y
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_SEQUENCER=m
++# CONFIG_SND_SEQ_DUMMY is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++CONFIG_SND_SEQUENCER_OSS=y
++# CONFIG_SND_HRTIMER is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++# CONFIG_SND_DEBUG_VERBOSE is not set
++# CONFIG_SND_PCM_XRUN_DEBUG is not set
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_VIRMIDI is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++CONFIG_SND_ARM=y
++CONFIG_SND_SPI=y
++CONFIG_SND_SOC=y
++CONFIG_SND_OMAP_SOC=y
++CONFIG_SND_OMAP_SOC_MCBSP=y
++CONFIG_SND_OMAP_SOC_OVERO=y
++CONFIG_SND_SOC_I2C_AND_SPI=y
++# CONFIG_SND_SOC_ALL_CODECS is not set
++CONFIG_SND_SOC_TWL4030=y
++# CONFIG_SOUND_PRIME is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++# CONFIG_HID_PID is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++# CONFIG_HID_APPLE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++CONFIG_USB_MUSB_HDRC=y
++CONFIG_USB_MUSB_SOC=y
++
++#
++# OMAP 343x high speed USB support
++#
++# CONFIG_USB_MUSB_HOST is not set
++CONFIG_USB_MUSB_PERIPHERAL=y
++# CONFIG_USB_MUSB_OTG is not set
++CONFIG_USB_GADGET_MUSB_HDRC=y
++# CONFIG_MUSB_PIO_ONLY is not set
++CONFIG_USB_INVENTRA_DMA=y
++# CONFIG_USB_TI_CPPI_DMA is not set
++# CONFIG_USB_MUSB_DEBUG is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++# CONFIG_USB_GADGET_DEBUG_FS is not set
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_PXA25X is not set
++# CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_IMX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_QE is not set
++# CONFIG_USB_GADGET_CI13XXX is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++
++#
++# OTG and related infrastructure
++#
++CONFIG_USB_OTG_UTILS=y
++# CONFIG_USB_GPIO_VBUS is not set
++# CONFIG_ISP1301_OMAP is not set
++CONFIG_TWL4030_USB=y
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_UNSAFE_RESUME=y
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++CONFIG_SDIO_UART=y
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_OMAP_HS=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_OMAP_DEBUG is not set
++# CONFIG_LEDS_OMAP is not set
++# CONFIG_LEDS_OMAP_PWM is not set
++# CONFIG_LEDS_PCA9532 is not set
++CONFIG_LEDS_GPIO=y
++# CONFIG_LEDS_LP5521 is not set
++# CONFIG_LEDS_PCA955X is not set
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
++# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_BQ24022 is not set
++CONFIG_REGULATOR_TWL4030=y
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# CBUS support
++#
++# CONFIG_CBUS is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++CONFIG_XFS_FS=m
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_POSIX_ACL is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_DEBUG is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++CONFIG_QUOTA_TREE=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=m
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_FS_POSIX_ACL=y
++CONFIG_JFFS2_FS_SECURITY=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_LZO=y
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=m
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_SCHED_DEBUG=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_NOP_TRACER=y
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_RING_BUFFER=y
++CONFIG_TRACING=y
++
++#
++# Tracers
++#
++# CONFIG_FUNCTION_TRACER is not set
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_BOOT_TRACER is not set
++# CONFIG_TRACE_BRANCH_PROFILING is not set
++# CONFIG_STACK_TRACER is not set
++# CONFIG_FTRACE_STARTUP_TEST is not set
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_XOR_BLOCKS=m
++CONFIG_ASYNC_CORE=m
++CONFIG_ASYNC_MEMCPY=m
++CONFIG_ASYNC_XOR=m
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_NULL=m
++CONFIG_CRYPTO_CRYPTD=m
++# CONFIG_CRYPTO_AUTHENC is not set
++CONFIG_CRYPTO_TEST=m
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_LRW=m
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=m
++CONFIG_CRYPTO_XCBC=m
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=y
++CONFIG_CRYPTO_MD4=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_MICHAEL_MIC=y
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=m
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_WP512=m
++
++#
++# Ciphers
++#
++CONFIG_CRYPTO_AES=y
++CONFIG_CRYPTO_ANUBIS=m
++CONFIG_CRYPTO_ARC4=y
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_CAMELLIA=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_FCRYPT=m
++CONFIG_CRYPTO_KHAZAD=m
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=m
++CONFIG_CRC_T10DIF=y
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++CONFIG_CRC7=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
+index 21b4a52..2ee6cbb 100644
+--- a/arch/arm/mach-omap2/board-3430sdp.c
++++ b/arch/arm/mach-omap2/board-3430sdp.c
+@@ -36,6 +36,7 @@
+ #include <mach/common.h>
+ #include <mach/dma.h>
+ #include <mach/gpmc.h>
++#include <mach/display.h>
+
+ #include <mach/control.h>
+ #include <mach/keypad.h>
+@@ -148,6 +149,35 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
+ },
+ };
+
++
++#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
++#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
++#if 0
++#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
++#define SDP3430_LCD_PANEL_ENABLE_GPIO 28
++#else
++#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8
++#define SDP3430_LCD_PANEL_ENABLE_GPIO 5
++#endif
++
++#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
++#define ENABLE_VAUX2_DEDICATED 0x09
++#define ENABLE_VAUX2_DEV_GRP 0x20
++#define ENABLE_VAUX3_DEDICATED 0x03
++#define ENABLE_VAUX3_DEV_GRP 0x20
++
++#define ENABLE_VPLL2_DEDICATED 0x05
++#define ENABLE_VPLL2_DEV_GRP 0xE0
++#define TWL4030_VPLL2_DEV_GRP 0x33
++#define TWL4030_VPLL2_DEDICATED 0x36
++
++#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
++
++static unsigned backlight_gpio;
++static unsigned enable_gpio;
++static int lcd_enabled;
++static int dvi_enabled;
++
+ static struct platform_device sdp3430_lcd_device = {
+ .name = "sdp2430_lcd",
+ .id = -1,
+@@ -163,8 +193,197 @@ static struct regulator_consumer_supply sdp3430_vdvi_supply = {
+ .dev = &sdp3430_lcd_device.dev,
+ };
+
++static void enable_vpll2(int enable)
++{
++ u8 ded_val, grp_val;
++
++ if (enable) {
++ ded_val = ENABLE_VPLL2_DEDICATED;
++ grp_val = ENABLE_VPLL2_DEV_GRP;
++ } else {
++ ded_val = 0;
++ grp_val = 0;
++ }
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ded_val, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ grp_val, TWL4030_VPLL2_DEV_GRP);
++}
++
++static int sdp3430_dsi_power_up(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(1);
++ return 0;
++}
++
++static void sdp3430_dsi_power_down(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(0);
++}
++
++static void __init sdp3430_display_init(void)
++{
++ int r;
++
++ enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
++ backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
++
++ r = gpio_request(enable_gpio, "LCD reset");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD reset GPIO\n");
++ goto err0;
++ }
++
++ r = gpio_request(backlight_gpio, "LCD Backlight");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD backlight GPIO\n");
++ goto err1;
++ }
++
++ gpio_direction_output(enable_gpio, 0);
++ gpio_direction_output(backlight_gpio, 0);
++
++ return;
++err1:
++ gpio_free(enable_gpio);
++err0:
++ return;
++}
++
++static int sdp3430_panel_enable_lcd(struct omap_display *display)
++{
++ u8 ded_val, ded_reg;
++ u8 grp_val, grp_reg;
++
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++
++ ded_reg = TWL4030_VAUX3_DEDICATED;
++ ded_val = ENABLE_VAUX3_DEDICATED;
++ grp_reg = TWL4030_VAUX3_DEV_GRP;
++ grp_val = ENABLE_VAUX3_DEV_GRP;
++
++ gpio_direction_output(enable_gpio, 1);
++ gpio_direction_output(backlight_gpio, 1);
++
++ if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
++ return -EIO;
++ if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
++ return -EIO;
++
++ sdp3430_dsi_power_up();
++
++ lcd_enabled = 1;
++
++ return 0;
++}
++
++static void sdp3430_panel_disable_lcd(struct omap_display *display)
++{
++ lcd_enabled = 0;
++
++ sdp3430_dsi_power_down();
++
++ gpio_direction_output(enable_gpio, 0);
++ gpio_direction_output(backlight_gpio, 0);
++}
++
++static struct omap_dss_display_config sdp3430_display_data = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .panel_name = "sharp-ls037v7dw01",
++ .u.dpi.data_lines = 16,
++ .panel_enable = sdp3430_panel_enable_lcd,
++ .panel_disable = sdp3430_panel_disable_lcd,
++};
++
++static int sdp3430_panel_enable_dvi(struct omap_display *display)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++
++ sdp3430_dsi_power_up();
++
++ dvi_enabled = 1;
++
++ return 0;
++}
++
++static void sdp3430_panel_disable_dvi(struct omap_display *display)
++{
++ sdp3430_dsi_power_down();
++
++ dvi_enabled = 0;
++}
++
++
++static struct omap_dss_display_config sdp3430_display_data_dvi = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .panel_name = "panel-generic",
++ .u.dpi.data_lines = 24,
++ .panel_enable = sdp3430_panel_enable_dvi,
++ .panel_disable = sdp3430_panel_disable_dvi,
++};
++
++static int sdp3430_panel_enable_tv(struct omap_display *display)
++{
++#define ENABLE_VDAC_DEDICATED 0x03
++#define ENABLE_VDAC_DEV_GRP 0x20
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEDICATED,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
++
++ return 0;
++}
++
++static void sdp3430_panel_disable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEV_GRP);
++}
++
++static struct omap_dss_display_config sdp3430_display_data_tv = {
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .name = "tv",
++ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .panel_enable = sdp3430_panel_enable_tv,
++ .panel_disable = sdp3430_panel_disable_tv,
++};
++
++static struct omap_dss_board_info sdp3430_dss_data = {
++ .dsi_power_up = sdp3430_dsi_power_up,
++ .dsi_power_down = sdp3430_dsi_power_down,
++ .num_displays = 3,
++ .displays = {
++ &sdp3430_display_data,
++ &sdp3430_display_data_dvi,
++ &sdp3430_display_data_tv,
++ }
++};
++
++static struct platform_device sdp3430_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &sdp3430_dss_data,
++ },
++};
++
+ static struct platform_device *sdp3430_devices[] __initdata = {
+- &sdp3430_lcd_device,
++ &sdp3430_dss_device,
+ };
+
+ static void __init omap_3430sdp_init_irq(void)
+@@ -178,13 +397,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+ };
+
+-static struct omap_lcd_config sdp3430_lcd_config __initdata = {
+- .ctrl_name = "internal",
+-};
+-
+ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
+ { OMAP_TAG_UART, &sdp3430_uart_config },
+- { OMAP_TAG_LCD, &sdp3430_lcd_config },
+ };
+
+ static int sdp3430_batt_table[] = {
+@@ -496,6 +710,7 @@ static void __init omap_3430sdp_init(void)
+ usb_musb_init();
+ board_smc91x_init();
+ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
++ sdp3430_display_init();
+ }
+
+ static void __init omap_3430sdp_map_io(void)
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index b6a68d5..c2c76b0 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -30,6 +30,7 @@
+
+ #include <linux/regulator/machine.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/omapfb.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -44,6 +45,7 @@
+ #include <mach/mux.h>
+ #include <mach/usb.h>
+ #include <mach/timer-gp.h>
++#include <mach/display.h>
+
+ #include "mmc-twl4030.h"
+
+@@ -343,13 +345,94 @@ static struct platform_device keys_gpio = {
+ },
+ };
+
++/* DSS */
++
++static int beagle_enable_dvi(struct omap_display *display)
++{
++ if (display->hw_config.panel_reset_gpio != -1)
++ gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
++
++ return 0;
++}
++
++static void beagle_disable_dvi(struct omap_display *display)
++{
++ if (display->hw_config.panel_reset_gpio != -1)
++ gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
++}
++
++static struct omap_dss_display_config beagle_display_data_dvi = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .panel_name = "panel-generic",
++ .u.dpi.data_lines = 24,
++ .panel_reset_gpio = 170,
++ .panel_enable = beagle_enable_dvi,
++ .panel_disable = beagle_disable_dvi,
++};
++
++
++static int beagle_panel_enable_tv(struct omap_display *display)
++{
++#define ENABLE_VDAC_DEDICATED 0x03
++#define ENABLE_VDAC_DEV_GRP 0x20
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEDICATED,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
++
++ return 0;
++}
++
++static void beagle_panel_disable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEV_GRP);
++}
++
++static struct omap_dss_display_config beagle_display_data_tv = {
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .name = "tv",
++ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .panel_enable = beagle_panel_enable_tv,
++ .panel_disable = beagle_panel_disable_tv,
++};
++
++static struct omap_dss_board_info beagle_dss_data = {
++ .num_displays = 2,
++ .displays = {
++ &beagle_display_data_dvi,
++ &beagle_display_data_tv,
++ }
++};
++
++static struct platform_device beagle_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &beagle_dss_data,
++ },
++};
++
++static void __init beagle_display_init(void)
++{
++ int r;
++
++ r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
++ if (r < 0)
++ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
++}
++
+ static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_beagle_uart_config },
+- { OMAP_TAG_LCD, &omap3_beagle_lcd_config },
+ };
+
+ static struct platform_device *omap3_beagle_devices[] __initdata = {
+- &omap3_beagle_lcd_device,
++ &beagle_dss_device,
+ &leds_gpio,
+ &keys_gpio,
+ };
+@@ -402,13 +485,11 @@ static void __init omap3_beagle_init(void)
+ omap_serial_init();
+
+ omap_cfg_reg(J25_34XX_GPIO170);
+- gpio_request(170, "DVI_nPD");
+- /* REVISIT leave DVI powered down until it's needed ... */
+- gpio_direction_output(170, true);
+
+ usb_musb_init();
+ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
+ omap3beagle_flash_init();
++ beagle_display_init();
+ }
+
+ static void __init omap3_beagle_map_io(void)
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index 595beac..dffb8b9 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -37,6 +37,7 @@
+ #include <mach/common.h>
+ #include <mach/mcspi.h>
+ #include <mach/keypad.h>
++#include <mach/display.h>
+
+ #include "sdram-micron-mt46h32m32lf-6.h"
+ #include "mmc-twl4030.h"
+@@ -222,13 +223,215 @@ static int __init omap3_evm_i2c_init(void)
+ return 0;
+ }
+
+-static struct platform_device omap3_evm_lcd_device = {
+- .name = "omap3evm_lcd",
+- .id = -1,
++#define LCD_PANEL_LR 2
++#define LCD_PANEL_UD 3
++#define LCD_PANEL_INI 152
++#define LCD_PANEL_ENABLE_GPIO 153
++#define LCD_PANEL_QVGA 154
++#define LCD_PANEL_RESB 155
++
++#define ENABLE_VDAC_DEDICATED 0x03
++#define ENABLE_VDAC_DEV_GRP 0x20
++#define ENABLE_VPLL2_DEDICATED 0x05
++#define ENABLE_VPLL2_DEV_GRP 0xE0
++
++#define TWL4030_GPIODATA_IN3 0x03
++#define TWL4030_GPIODATA_DIR3 0x06
++#define TWL4030_VPLL2_DEV_GRP 0x33
++#define TWL4030_VPLL2_DEDICATED 0x36
++
++static int lcd_enabled;
++static int dvi_enabled;
++
++static void __init omap3_evm_display_init(void)
++{
++ int r;
++ r = gpio_request(LCD_PANEL_LR, "lcd_panel_lr");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_LR\n");
++ return;
++ }
++ r = gpio_request(LCD_PANEL_UD, "lcd_panel_ud");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_UD\n");
++ goto err_1;
++ }
++
++ r = gpio_request(LCD_PANEL_INI, "lcd_panel_ini");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_INI\n");
++ goto err_2;
++ }
++ r = gpio_request(LCD_PANEL_RESB, "lcd_panel_resb");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_RESB\n");
++ goto err_3;
++ }
++ r = gpio_request(LCD_PANEL_QVGA, "lcd_panel_qvga");
++ if (r) {
++ printk(KERN_ERR "failed to get LCD_PANEL_QVGA\n");
++ goto err_4;
++ }
++
++ gpio_direction_output(LCD_PANEL_LR, 0);
++ gpio_direction_output(LCD_PANEL_UD, 0);
++ gpio_direction_output(LCD_PANEL_INI, 0);
++ gpio_direction_output(LCD_PANEL_RESB, 0);
++ gpio_direction_output(LCD_PANEL_QVGA, 0);
++
++#define TWL_LED_LEDEN 0x00
++#define TWL_PWMA_PWMAON 0x00
++#define TWL_PWMA_PWMAOFF 0x01
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
++
++ gpio_direction_output(LCD_PANEL_RESB, 1);
++ gpio_direction_output(LCD_PANEL_INI, 1);
++ gpio_direction_output(LCD_PANEL_QVGA, 0);
++ gpio_direction_output(LCD_PANEL_LR, 1);
++ gpio_direction_output(LCD_PANEL_UD, 1);
++
++ return;
++
++err_4:
++ gpio_free(LCD_PANEL_RESB);
++err_3:
++ gpio_free(LCD_PANEL_INI);
++err_2:
++ gpio_free(LCD_PANEL_UD);
++err_1:
++ gpio_free(LCD_PANEL_LR);
++
++}
++
++static int omap3_evm_panel_enable_lcd(struct omap_display *display)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
++ }
++ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
++ lcd_enabled = 1;
++ return 0;
++}
++
++static void omap3_evm_panel_disable_lcd(struct omap_display *display)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEV_GRP);
++ }
++ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
++ lcd_enabled = 0;
++}
++
++static struct omap_dss_display_config omap3_evm_display_data = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .panel_name = "sharp-ls037v7dw01",
++ .u.dpi.data_lines = 18,
++ .panel_enable = omap3_evm_panel_enable_lcd,
++ .panel_disable = omap3_evm_panel_disable_lcd,
+ };
+
+-static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
+- .ctrl_name = "internal",
++static int omap3_evm_panel_enable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEDICATED, TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
++ return 0;
++}
++
++static void omap3_evm_panel_disable_tv(struct omap_display *display)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEV_GRP);
++}
++
++static struct omap_dss_display_config omap3_evm_display_data_tv = {
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .name = "tv",
++ .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .panel_enable = omap3_evm_panel_enable_tv,
++ .panel_disable = omap3_evm_panel_disable_tv,
++};
++
++
++static int omap3_evm_panel_enable_dvi(struct omap_display *display)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
++ }
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
++ TWL4030_GPIODATA_IN3);
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
++ TWL4030_GPIODATA_DIR3);
++ dvi_enabled = 1;
++
++ return 0;
++}
++
++static void omap3_evm_panel_disable_dvi(struct omap_display *display)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0) {
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
++ TWL4030_VPLL2_DEV_GRP);
++ }
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
++ TWL4030_GPIODATA_IN3);
++ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
++ TWL4030_GPIODATA_DIR3);
++ dvi_enabled = 0;
++}
++
++
++static struct omap_dss_display_config omap3_evm_display_data_dvi = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .panel_name = "panel-generic",
++ .u.dpi.data_lines = 24,
++ .panel_enable = omap3_evm_panel_enable_dvi,
++ .panel_disable = omap3_evm_panel_disable_dvi,
++};
++
++static struct omap_dss_board_info omap3_evm_dss_data = {
++ .num_displays = 3,
++ .displays = {
++ &omap3_evm_display_data,
++ &omap3_evm_display_data_dvi,
++ &omap3_evm_display_data_tv,
++ }
++};
++static struct platform_device omap3_evm_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &omap3_evm_dss_data,
++ },
+ };
+
+ static void ads7846_dev_init(void)
+@@ -287,11 +490,10 @@ static void __init omap3_evm_init_irq(void)
+
+ static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_evm_uart_config },
+- { OMAP_TAG_LCD, &omap3_evm_lcd_config },
+ };
+
+ static struct platform_device *omap3_evm_devices[] __initdata = {
+- &omap3_evm_lcd_device,
++ &omap3_evm_dss_device,
+ &omap3evm_smc911x_device,
+ };
+
+@@ -310,6 +512,7 @@ static void __init omap3_evm_init(void)
+ usb_musb_init();
+ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
+ ads7846_dev_init();
++ omap3_evm_display_init();
+ }
+
+ static void __init omap3_evm_map_io(void)
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index 501d020..7bcac03 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -40,6 +40,7 @@
+
+ #include <mach/board.h>
+ #include <mach/common.h>
++#include <mach/display.h>
+ #include <mach/gpio.h>
+ #include <mach/gpmc.h>
+ #include <mach/hardware.h>
+@@ -182,6 +183,9 @@ static inline void __init overo_init_smsc911x(void)
+ static inline void __init overo_init_smsc911x(void) { return; }
+ #endif
+
++static int lcd_enabled;
++static int dvi_enabled;
++
+ static struct mtd_partition overo_nand_partitions[] = {
+ {
+ .name = "xloader",
+@@ -365,22 +369,101 @@ static void __init overo_init_irq(void)
+ omap_gpio_init();
+ }
+
+-static struct platform_device overo_lcd_device = {
+- .name = "overo_lcd",
+- .id = -1,
++/* DSS */
++
++#define OVERO_GPIO_LCD_EN 144
++
++static void __init overo_display_init(void)
++{
++ int r;
++
++ r = gpio_request(OVERO_GPIO_LCD_EN, "display enable");
++ if (r)
++ printk("fail1\n");
++ r = gpio_direction_output(OVERO_GPIO_LCD_EN, 1);
++ if (r)
++ printk("fail2\n");
++ gpio_export(OVERO_GPIO_LCD_EN, 0);
++}
++
++static int overo_panel_enable_dvi(struct omap_display *display)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++ dvi_enabled = 1;
++
++ gpio_set_value(OVERO_GPIO_LCD_EN, 1);
++
++ return 0;
++}
++
++static void overo_panel_disable_dvi(struct omap_display *display)
++{
++ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
++
++ dvi_enabled = 0;
++}
++
++static struct omap_dss_display_config overo_display_data_dvi = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .panel_name = "panel-generic",
++ .u.dpi.data_lines = 24,
++ .panel_enable = overo_panel_enable_dvi,
++ .panel_disable = overo_panel_disable_dvi,
+ };
+
+-static struct omap_lcd_config overo_lcd_config __initdata = {
+- .ctrl_name = "internal",
++static int overo_panel_enable_lcd(struct omap_display *display)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++
++ gpio_set_value(OVERO_GPIO_LCD_EN, 1);
++ lcd_enabled = 1;
++ return 0;
++}
++
++static void overo_panel_disable_lcd(struct omap_display *display)
++{
++ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
++ lcd_enabled = 0;
++}
++
++static struct omap_dss_display_config overo_display_data_lcd = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .panel_name = "samsung-lte430wq-f0c",
++ .u.dpi.data_lines = 24,
++ .panel_enable = overo_panel_enable_lcd,
++ .panel_disable = overo_panel_disable_lcd,
++ };
++
++static struct omap_dss_board_info overo_dss_data = {
++ .num_displays = 2,
++ .displays = {
++ &overo_display_data_dvi,
++ &overo_display_data_lcd,
++ }
++};
++
++static struct platform_device overo_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &overo_dss_data,
++ },
+ };
+
+ static struct omap_board_config_kernel overo_config[] __initdata = {
+ { OMAP_TAG_UART, &overo_uart_config },
+- { OMAP_TAG_LCD, &overo_lcd_config },
+ };
+
+ static struct platform_device *overo_devices[] __initdata = {
+- &overo_lcd_device,
++ &overo_dss_device,
+ };
+
+ static void __init overo_init(void)
+@@ -395,6 +478,7 @@ static void __init overo_init(void)
+ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, 183, -EINVAL);
+ overo_ads7846_init();
+ overo_init_smsc911x();
++ overo_display_init();
+
+ if ((gpio_request(OVERO_GPIO_W2W_NRESET,
+ "OVERO_GPIO_W2W_NRESET") == 0) &&
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-function-to-display-object-to-get-the-back.patch b/recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-function-to-display-object-to-get-the-back.patch
new file mode 100644
index 0000000000..98537e0ebf
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0007-DSS2-Add-function-to-display-object-to-get-the-back.patch
@@ -0,0 +1,39 @@
+From 5d32a2ba9289a16d950db719330ee57dc9ffa60a Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 1 Apr 2009 14:36:39 +0200
+Subject: [PATCH 007/146] DSS2: Add function to display object to get the backlight level
+
+This is needed by an upcoming patch that changes the backlight
+initialization to use the backlight level set by the bootloader.
+
+Also add a field for the maximum backlight level.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 6288353..6b702c7 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -211,6 +211,8 @@ struct omap_dss_display_config {
+ int panel_reset_gpio;
+ int ctrl_reset_gpio;
+
++ int max_backlight_level;
++
+ const char *name; /* for debug */
+ const char *ctrl_name;
+ const char *panel_name;
+@@ -225,6 +227,7 @@ struct omap_dss_display_config {
+ void (*ctrl_disable)(struct omap_display *display);
+ int (*set_backlight)(struct omap_display *display,
+ int level);
++ int (*get_backlight)(struct omap_display *display);
+ };
+
+ struct device;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-acx565akm-panel.patch b/recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-acx565akm-panel.patch
new file mode 100644
index 0000000000..042a792029
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0008-DSS2-Add-acx565akm-panel.patch
@@ -0,0 +1,778 @@
+From 7591138400ae9112bb5f5d4f4b62b3a1adb69874 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Thu, 2 Apr 2009 11:47:13 +0300
+Subject: [PATCH 008/146] DSS2: Add acx565akm panel
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/displays/Kconfig | 8 +
+ drivers/video/omap2/displays/Makefile | 2 +
+ drivers/video/omap2/displays/panel-acx565akm.c | 712 ++++++++++++++++++++++++
+ drivers/video/omap2/displays/panel-acx565akm.h | 9 +
+ 4 files changed, 731 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/omap2/displays/panel-acx565akm.c
+ create mode 100644 drivers/video/omap2/displays/panel-acx565akm.h
+
+diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
+index 356ceb1..3feecee 100644
+--- a/drivers/video/omap2/displays/Kconfig
++++ b/drivers/video/omap2/displays/Kconfig
+@@ -28,4 +28,12 @@ config CTRL_BLIZZARD
+ tristate "Blizzard Controller"
+ help
+ Blizzard Controller (hack)
++
++config PANEL_ACX565AKM
++ tristate "ACX565AKM LCD Panel"
++ depends on OMAP2_DSS_SDI
++ select BACKLIGHT_CLASS_DEVICE
++ help
++ LCD Panel used in RX51
++
+ endmenu
+diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
+index 1b74b7e..9bafcb6 100644
+--- a/drivers/video/omap2/displays/Makefile
++++ b/drivers/video/omap2/displays/Makefile
+@@ -4,3 +4,5 @@ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+
+ obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
+ obj-$(CONFIG_PANEL_N800) += panel-n800.o
++
++obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
+new file mode 100644
+index 0000000..2679d6c
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-acx565akm.c
+@@ -0,0 +1,712 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/spi/spi.h>
++#include <linux/jiffies.h>
++#include <linux/sched.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++
++#include <mach/display.h>
++#include <mach/dma.h>
++
++#include "panel-acx565akm.h"
++
++#define MIPID_CMD_READ_DISP_ID 0x04
++#define MIPID_CMD_READ_RED 0x06
++#define MIPID_CMD_READ_GREEN 0x07
++#define MIPID_CMD_READ_BLUE 0x08
++#define MIPID_CMD_READ_DISP_STATUS 0x09
++#define MIPID_CMD_RDDSDR 0x0F
++#define MIPID_CMD_SLEEP_IN 0x10
++#define MIPID_CMD_SLEEP_OUT 0x11
++#define MIPID_CMD_DISP_OFF 0x28
++#define MIPID_CMD_DISP_ON 0x29
++#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
++#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
++#define MIPID_CMD_WRITE_CTRL_DISP 0x53
++
++#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
++#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
++#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
++#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
++
++#define MIPID_CMD_READ_CTRL_DISP 0x54
++#define MIPID_CMD_WRITE_CABC 0x55
++#define MIPID_CMD_READ_CABC 0x56
++
++#define MIPID_VER_LPH8923 3
++#define MIPID_VER_LS041Y3 4
++#define MIPID_VER_L4F00311 8
++#define MIPID_VER_ACX565AKM 9
++
++struct acx565akm_device {
++ struct backlight_device *bl_dev;
++ int enabled;
++ int model;
++ int revision;
++ u8 display_id[3];
++ int has_bc:1;
++ int has_cabc:1;
++ unsigned int saved_bklight_level;
++ unsigned long hw_guard_end; /* next value of jiffies
++ when we can issue the
++ next sleep in/out command */
++ unsigned long hw_guard_wait; /* max guard time in jiffies */
++
++ struct spi_device *spi;
++ struct mutex mutex;
++ struct omap_panel panel;
++ struct omap_display *display;
++};
++
++static int acx565akm_bl_update_status(struct backlight_device *dev);
++
++static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
++ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
++{
++ struct spi_message m;
++ struct spi_transfer *x, xfer[5];
++ int r;
++
++ BUG_ON(md->spi == NULL);
++
++ spi_message_init(&m);
++
++ memset(xfer, 0, sizeof(xfer));
++ x = &xfer[0];
++
++ cmd &= 0xff;
++ x->tx_buf = &cmd;
++ x->bits_per_word = 9;
++ x->len = 2;
++
++ if (rlen > 1 && wlen == 0) {
++ /*
++ * Between the command and the response data there is a
++ * dummy clock cycle. Add an extra bit after the command
++ * word to account for this.
++ */
++ x->bits_per_word = 10;
++ cmd <<= 1;
++ }
++ spi_message_add_tail(x, &m);
++
++ if (wlen) {
++ x++;
++ x->tx_buf = wbuf;
++ x->len = wlen;
++ x->bits_per_word = 9;
++ spi_message_add_tail(x, &m);
++ }
++
++ if (rlen) {
++ x++;
++ x->rx_buf = rbuf;
++ x->len = rlen;
++ spi_message_add_tail(x, &m);
++ }
++
++ r = spi_sync(md->spi, &m);
++ if (r < 0)
++ dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
++}
++
++static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
++{
++ acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
++}
++
++static inline void acx565akm_write(struct acx565akm_device *md,
++ int reg, const u8 *buf, int len)
++{
++ acx565akm_transfer(md, reg, buf, len, NULL, 0);
++}
++
++static inline void acx565akm_read(struct acx565akm_device *md,
++ int reg, u8 *buf, int len)
++{
++ acx565akm_transfer(md, reg, NULL, 0, buf, len);
++}
++
++static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
++{
++ md->hw_guard_wait = msecs_to_jiffies(guard_msec);
++ md->hw_guard_end = jiffies + md->hw_guard_wait;
++}
++
++static void hw_guard_wait(struct acx565akm_device *md)
++{
++ unsigned long wait = md->hw_guard_end - jiffies;
++
++ if ((long)wait > 0 && wait <= md->hw_guard_wait) {
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(wait);
++ }
++}
++
++static void set_sleep_mode(struct acx565akm_device *md, int on)
++{
++ int cmd, sleep_time = 50;
++
++ if (on)
++ cmd = MIPID_CMD_SLEEP_IN;
++ else
++ cmd = MIPID_CMD_SLEEP_OUT;
++ hw_guard_wait(md);
++ acx565akm_cmd(md, cmd);
++ hw_guard_start(md, 120);
++ /*
++ * When we enable the panel, it seems we _have_ to sleep
++ * 120 ms before sending the init string. When disabling the
++ * panel we'll sleep for the duration of 2 frames, so that the
++ * controller can still provide the PCLK,HS,VS signals. */
++ if (!on)
++ sleep_time = 120;
++ msleep(sleep_time);
++}
++
++static void set_display_state(struct acx565akm_device *md, int enabled)
++{
++ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
++
++ acx565akm_cmd(md, cmd);
++}
++
++static int panel_enabled(struct acx565akm_device *md)
++{
++ u32 disp_status;
++ int enabled;
++
++ acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
++ disp_status = __be32_to_cpu(disp_status);
++ enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
++ dev_dbg(&md->spi->dev,
++ "LCD panel %senabled by bootloader (status 0x%04x)\n",
++ enabled ? "" : "not ", disp_status);
++ return enabled;
++}
++
++static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
++{
++ u16 ctrl;
++
++ acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
++ if (enable) {
++ ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
++ CTRL_DISP_BACKLIGHT_ON;
++ } else {
++ ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
++ CTRL_DISP_BACKLIGHT_ON);
++ }
++
++ ctrl |= 1 << 8;
++ acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
++}
++
++static void set_cabc_mode(struct acx565akm_device *md, int mode)
++{
++ u16 cabc_ctrl;
++
++ cabc_ctrl = 0;
++ acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
++ cabc_ctrl &= ~3;
++ cabc_ctrl |= (1 << 8) | (mode & 3);
++ acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
++}
++
++static int get_cabc_mode(struct acx565akm_device *md)
++{
++ u8 cabc_ctrl;
++
++ acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
++ return cabc_ctrl & 3;
++}
++
++static int panel_detect(struct acx565akm_device *md)
++{
++ acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
++ dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
++ md->display_id[0], md->display_id[1], md->display_id[2]);
++
++ switch (md->display_id[0]) {
++ case 0x10:
++ md->model = MIPID_VER_ACX565AKM;
++ md->panel.name = "acx565akm";
++ md->has_bc = 1;
++ md->has_cabc = 1;
++ break;
++ case 0x29:
++ md->model = MIPID_VER_L4F00311;
++ md->panel.name = "l4f00311";
++ break;
++ case 0x45:
++ md->model = MIPID_VER_LPH8923;
++ md->panel.name = "lph8923";
++ break;
++ case 0x83:
++ md->model = MIPID_VER_LS041Y3;
++ md->panel.name = "ls041y3";
++ break;
++ default:
++ md->panel.name = "unknown";
++ dev_err(&md->spi->dev, "invalid display ID\n");
++ return -ENODEV;
++ }
++
++ md->revision = md->display_id[1];
++
++ pr_info("omapfb: %s rev %02x LCD detected\n",
++ md->panel.name, md->revision);
++
++ return 0;
++}
++
++static int acx565akm_panel_enable(struct omap_display *display)
++{
++ struct acx565akm_device *md =
++ (struct acx565akm_device *)display->panel->priv;
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ mutex_lock(&md->mutex);
++
++ if (display->hw_config.panel_enable)
++ display->hw_config.panel_enable(display);
++
++ md->enabled = panel_enabled(md);
++
++ if (md->enabled) {
++ dev_dbg(&md->spi->dev, "panel already enabled\n");
++ mutex_unlock(&md->mutex);
++ return 0;
++ }
++
++ set_sleep_mode(md, 0);
++ md->enabled = 1;
++ set_display_state(md, 1);
++
++ mutex_unlock(&md->mutex);
++
++ return acx565akm_bl_update_status(md->bl_dev);
++}
++
++static void acx565akm_panel_disable(struct omap_display *display)
++{
++ struct acx565akm_device *md =
++ (struct acx565akm_device *)display->panel->priv;
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ mutex_lock(&md->mutex);
++
++ if (!md->enabled) {
++ mutex_unlock(&md->mutex);
++ return;
++ }
++ set_display_state(md, 0);
++ set_sleep_mode(md, 1);
++ md->enabled = 0;
++
++ if (display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++
++ mutex_unlock(&md->mutex);
++}
++
++#if 0
++static void acx565akm_set_mode(struct omap_display *display,
++ int x_res, int y_res, int bpp)
++{
++ struct acx565akm_device *md =
++ (struct acx565akm_device *)display->panel->priv;
++ u16 par;
++
++ switch (bpp) {
++ case 16:
++ par = 0x150;
++ break;
++ case 18:
++ par = 0x160;
++ break;
++ case 24:
++ par = 0x170;
++ break;
++ }
++
++ acx565akm_write(md, 0x3a, (u8 *)&par, 2);
++}
++#endif
++
++static int acx565akm_panel_suspend(struct omap_display *display)
++{
++ acx565akm_panel_disable(display);
++ return 0;
++}
++
++static int acx565akm_panel_resume(struct omap_display *display)
++{
++ return acx565akm_panel_enable(display);
++}
++
++static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
++{
++ int bv;
++
++ bv = level | (1 << 8);
++ acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
++
++ if (level)
++ enable_backlight_ctrl(md, 1);
++ else
++ enable_backlight_ctrl(md, 0);
++}
++
++static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
++{
++ u8 bv;
++
++ acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
++
++ return bv;
++}
++
++static int acx565akm_bl_update_status(struct backlight_device *dev)
++{
++ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
++ struct omap_display *display = md->display;
++ int r;
++ int level;
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ if (display->hw_config.set_backlight == NULL)
++ return -ENODEV;
++
++ mutex_lock(&md->mutex);
++
++ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
++ dev->props.power == FB_BLANK_UNBLANK)
++ level = dev->props.brightness;
++ else
++ level = 0;
++
++ r = 0;
++ if (md->has_bc)
++ acx565akm_set_brightness(md, level);
++ else
++ if (display->hw_config.set_backlight != NULL)
++ r = display->hw_config.set_backlight(display, level);
++ else
++ r = -ENODEV;
++
++ mutex_unlock(&md->mutex);
++
++ return r;
++}
++
++static int acx565akm_bl_get_intensity(struct backlight_device *dev)
++{
++ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
++ struct omap_display *display = md->display;
++
++ dev_dbg(&dev->dev, "%s\n", __func__);
++
++ if (md->has_bc && display->hw_config.set_backlight == NULL)
++ return -ENODEV;
++
++ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
++ dev->props.power == FB_BLANK_UNBLANK) {
++ if (md->has_bc)
++ return acx565akm_get_actual_brightness(md);
++ else
++ return dev->props.brightness;
++ }
++
++ return 0;
++}
++
++static struct backlight_ops acx565akm_bl_ops = {
++ .get_brightness = acx565akm_bl_get_intensity,
++ .update_status = acx565akm_bl_update_status,
++};
++
++static const char *cabc_modes[] = {
++ "off", /* used also always when CABC is not supported */
++ "ui",
++ "still-image",
++ "moving-image",
++};
++
++static ssize_t show_cabc_mode(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct acx565akm_device *md = dev_get_drvdata(dev);
++ const char *mode_str;
++ int mode;
++ int len;
++
++ if (!md->has_cabc)
++ mode = 0;
++ else
++ mode = get_cabc_mode(md);
++ mode_str = "unknown";
++ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
++ mode_str = cabc_modes[mode];
++ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
++
++ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
++}
++
++static ssize_t store_cabc_mode(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct acx565akm_device *md = dev_get_drvdata(dev);
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
++ const char *mode_str = cabc_modes[i];
++ int cmp_len = strlen(mode_str);
++
++ if (count > 0 && buf[count - 1] == '\n')
++ count--;
++ if (count != cmp_len)
++ continue;
++
++ if (strncmp(buf, mode_str, cmp_len) == 0)
++ break;
++ }
++
++ if (i == ARRAY_SIZE(cabc_modes))
++ return -EINVAL;
++
++ if (!md->has_cabc && i != 0)
++ return -EINVAL;
++
++ mutex_lock(&md->mutex);
++ set_cabc_mode(md, i);
++ mutex_unlock(&md->mutex);
++
++ return count;
++}
++
++static ssize_t show_cabc_available_modes(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct acx565akm_device *md = dev_get_drvdata(dev);
++ int len;
++ int i;
++
++ if (!md->has_cabc)
++ return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
++
++ for (i = 0, len = 0;
++ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
++ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
++ i ? " " : "", cabc_modes[i],
++ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
++
++ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
++}
++
++static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
++ show_cabc_mode, store_cabc_mode);
++static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
++ show_cabc_available_modes, NULL);
++
++static struct attribute *bldev_attrs[] = {
++ &dev_attr_cabc_mode.attr,
++ &dev_attr_cabc_available_modes.attr,
++ NULL,
++};
++
++static struct attribute_group bldev_attr_group = {
++ .attrs = bldev_attrs,
++};
++
++static int acx565akm_panel_init(struct omap_display *display)
++{
++ struct omap_panel *panel = display->panel;
++ struct acx565akm_panel_data *panel_data = display->hw_config.panel_data;
++ struct acx565akm_device *md = (struct acx565akm_device *)panel->priv;
++
++ struct backlight_device *bldev;
++ int brightness;
++ int max_brightness;
++ int r;
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ if (!panel_data) {
++ dev_err(&md->spi->dev, "no panel data\n");
++ return -ENODEV;
++ }
++
++ mutex_init(&md->mutex);
++ md->display = display;
++
++ if (display->hw_config.panel_enable)
++ display->hw_config.panel_enable(display);
++
++ md->enabled = panel_enabled(md);
++
++ r = panel_detect(md);
++ if (r) {
++ if (!md->enabled && display->hw_config.panel_disable)
++ display->hw_config.panel_disable(display);
++ mutex_unlock(&md->mutex);
++ return r;
++ }
++
++ if (!panel_data->bc_connected) {
++ md->has_bc = 0;
++ md->has_cabc = 0;
++ }
++
++#if 0
++ acx565akm_set_mode(display, panel->timings.x_res, panel->timings.y_res,
++ panel->bpp);
++#endif
++
++ if (!md->enabled)
++ display->hw_config.panel_disable(display);
++
++ bldev = backlight_device_register("acx565akm", &md->spi->dev,
++ md, &acx565akm_bl_ops);
++ md->bl_dev = bldev;
++
++ if (md->has_cabc) {
++ r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
++ if (r) {
++ dev_err(&bldev->dev, "failed to create sysfs files\n");
++ backlight_device_unregister(bldev);
++ return r;
++ }
++ }
++
++ bldev->props.fb_blank = FB_BLANK_UNBLANK;
++ bldev->props.power = FB_BLANK_UNBLANK;
++
++ if (md->has_bc)
++ max_brightness = 255;
++ else
++ max_brightness = display->hw_config.max_backlight_level;
++
++ if (md->has_bc)
++ brightness = acx565akm_get_actual_brightness(md);
++ else {
++ if (display->hw_config.get_backlight != NULL)
++ brightness = display->hw_config.get_backlight(display);
++ else
++ brightness = 0;
++ }
++
++ bldev->props.max_brightness = max_brightness;
++ bldev->props.brightness = brightness;
++ acx565akm_bl_update_status(bldev);
++
++ return 0;
++}
++
++static struct omap_panel acx565akm_panel = {
++ .name = "panel-acx565akm",
++ .init = acx565akm_panel_init,
++ .suspend = acx565akm_panel_suspend,
++ .resume = acx565akm_panel_resume,
++ .enable = acx565akm_panel_enable,
++ .disable = acx565akm_panel_disable,
++
++ .timings = {
++ .x_res = 800,
++ .y_res = 480,
++
++ .pixel_clock = 24000,
++
++ .hsw = 4,
++ .hfp = 16,
++ .hbp = 12,
++
++ .vsw = 3,
++ .vfp = 3,
++ .vbp = 3,
++ },
++
++ .config = OMAP_DSS_LCD_TFT,
++
++ .recommended_bpp = 16,
++
++ /*
++ * supported modes: 12bpp(444), 16bpp(565), 18bpp(666), 24bpp(888)
++ * resolutions.
++ */
++};
++
++static int acx565akm_spi_probe(struct spi_device *spi)
++{
++ struct acx565akm_device *md;
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ md = kzalloc(sizeof(*md), GFP_KERNEL);
++ if (md == NULL) {
++ dev_err(&spi->dev, "out of memory\n");
++ return -ENOMEM;
++ }
++
++ spi->mode = SPI_MODE_3;
++ md->spi = spi;
++ dev_set_drvdata(&spi->dev, md);
++ md->panel = acx565akm_panel;
++ acx565akm_panel.priv = md;
++
++ omap_dss_register_panel(&acx565akm_panel);
++
++ return 0;
++}
++
++static int acx565akm_spi_remove(struct spi_device *spi)
++{
++ struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
++
++ dev_dbg(&md->spi->dev, "%s\n", __func__);
++
++ sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
++ backlight_device_unregister(md->bl_dev);
++ omap_dss_unregister_panel(&acx565akm_panel);
++
++ kfree(md);
++
++ return 0;
++}
++
++static struct spi_driver acx565akm_spi_driver = {
++ .driver = {
++ .name = "acx565akm",
++ .bus = &spi_bus_type,
++ .owner = THIS_MODULE,
++ },
++ .probe = acx565akm_spi_probe,
++ .remove = __devexit_p(acx565akm_spi_remove),
++};
++
++static int __init acx565akm_init(void)
++{
++ return spi_register_driver(&acx565akm_spi_driver);
++}
++
++static void __exit acx565akm_exit(void)
++{
++ spi_unregister_driver(&acx565akm_spi_driver);
++}
++
++module_init(acx565akm_init);
++module_exit(acx565akm_exit);
++
++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
++MODULE_DESCRIPTION("acx565akm LCD Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/omap2/displays/panel-acx565akm.h b/drivers/video/omap2/displays/panel-acx565akm.h
+new file mode 100644
+index 0000000..6d3727b
+--- /dev/null
++++ b/drivers/video/omap2/displays/panel-acx565akm.h
+@@ -0,0 +1,9 @@
++#ifndef __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
++#define __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
++
++struct acx565akm_panel_data {
++ unsigned bc_connected:1;
++};
++
++#endif
++
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0009-DSS2-Small-VRFB-context-allocation-bug-fixed.patch b/recipes/linux/linux-omap-pm/dss2/0009-DSS2-Small-VRFB-context-allocation-bug-fixed.patch
new file mode 100644
index 0000000000..916e57c27a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0009-DSS2-Small-VRFB-context-allocation-bug-fixed.patch
@@ -0,0 +1,28 @@
+From 8caea38adca77b8aa14721f07810d4802272bd05 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Tue, 31 Mar 2009 18:47:32 +0530
+Subject: [PATCH 009/146] DSS2: Small VRFB context allocation bug fixed
+
+This is minor bug while requesting and mapping memory for
+VRFB space.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 852abe5..44febef 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1193,6 +1193,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+
+ if(!va) {
+ printk(KERN_ERR "vrfb: ioremap failed\n");
++ omap_vrfb_release_ctx(&rg->vrfb);
+ return -ENOMEM;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0010-DSS2-Allocated-memory-for-Color-Look-up-table.patch b/recipes/linux/linux-omap-pm/dss2/0010-DSS2-Allocated-memory-for-Color-Look-up-table.patch
new file mode 100644
index 0000000000..8b2f21f561
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0010-DSS2-Allocated-memory-for-Color-Look-up-table.patch
@@ -0,0 +1,37 @@
+From 9a88005a530cd311fa0ffd0d07f7ae7a73dbf7d5 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Tue, 31 Mar 2009 18:38:31 +0530
+Subject: [PATCH 010/146] DSS2: Allocated memory for Color Look-up-table
+
+We were not allocating memory for CMAP buffer and due to that
+G_CMAP was failing, since it does check for size of CMAP buffer.
+
+Called "fb_alloc_cmap" for llocating memory for CMAP.
+
+We are currently not supporting 1,2,4,8 bpp, so meaning less
+for us as of now. But for completeness this is required.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 44febef..afe40a9 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1525,6 +1525,11 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ goto err;
+
+ set_fb_fix(fbi);
++
++ r = fb_alloc_cmap(&fbi->cmap, 256, 0);
++ if (r)
++ dev_err(fbdev->dev, "unable to allocate color map memory\n");
++
+ err:
+ return r;
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0011-DSS2-Fix-DMA-rotation.patch b/recipes/linux/linux-omap-pm/dss2/0011-DSS2-Fix-DMA-rotation.patch
new file mode 100644
index 0000000000..006c2346f7
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0011-DSS2-Fix-DMA-rotation.patch
@@ -0,0 +1,65 @@
+From 5563b1d969aa8227919e35c3d4ceb738b3bf7a39 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 13:47:11 +0300
+Subject: [PATCH 011/146] DSS2: Fix DMA rotation
+
+u16 was not a good type for offsets. First, they need to be signed,
+and second, 16 bits is not enough.
+---
+ drivers/video/omap2/dss/dispc.c | 12 ++++++------
+ 1 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index ffb5648..6cea545 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -778,7 +778,7 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+ dispc_write_reg(vsi_reg[plane-1], val);
+ }
+
+-static void _dispc_set_pix_inc(enum omap_plane plane, u16 inc)
++static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+ {
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
+ DISPC_VID_PIXEL_INC(0),
+@@ -787,7 +787,7 @@ static void _dispc_set_pix_inc(enum omap_plane plane, u16 inc)
+ dispc_write_reg(ri_reg[plane], inc);
+ }
+
+-static void _dispc_set_row_inc(enum omap_plane plane, u16 inc)
++static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
+ {
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
+ DISPC_VID_ROW_INC(0),
+@@ -1123,7 +1123,7 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ }
+ }
+
+-static int pixinc(int pixels, u8 ps)
++static s32 pixinc(int pixels, u8 ps)
+ {
+ if (pixels == 1)
+ return 1;
+@@ -1140,7 +1140,7 @@ static void calc_rotation_offset(u8 rotation, bool mirror,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+ unsigned *offset0, unsigned *offset1,
+- u16 *row_inc, u16 *pix_inc)
++ s32 *row_inc, s32 *pix_inc)
+ {
+ u8 ps;
+ u16 fbw, fbh;
+@@ -1298,8 +1298,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ bool fieldmode = 0;
+ int cconv = 0;
+ unsigned offset0, offset1;
+- u16 row_inc;
+- u16 pix_inc;
++ s32 row_inc;
++ s32 pix_inc;
+
+ if (plane == OMAP_DSS_GFX) {
+ if (width != out_width || height != out_height)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0012-DSS2-Verify-that-overlay-paddr-0.patch b/recipes/linux/linux-omap-pm/dss2/0012-DSS2-Verify-that-overlay-paddr-0.patch
new file mode 100644
index 0000000000..869a27b81e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0012-DSS2-Verify-that-overlay-paddr-0.patch
@@ -0,0 +1,41 @@
+From 24ae439174e570101d8d80fdc4b605de0040f88a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 14:21:12 +0300
+Subject: [PATCH 012/146] DSS2: Verify that overlay paddr != 0
+
+---
+ drivers/video/omap2/dss/dispc.c | 3 +++
+ drivers/video/omap2/dss/overlay.c | 3 +++
+ 2 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 6cea545..2480a03 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1301,6 +1301,9 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ s32 row_inc;
+ s32 pix_inc;
+
++ if (paddr == 0)
++ return -EINVAL;
++
+ if (plane == OMAP_DSS_GFX) {
+ if (width != out_width || height != out_height)
+ return -EINVAL;
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 968edbe..9209acf 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -331,6 +331,9 @@ static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
+ int r;
+ struct omap_overlay_info old_info;
+
++ if (info->paddr == 0)
++ return -EINVAL;
++
+ old_info = ovl->info;
+ ovl->info = *info;
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0013-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch b/recipes/linux/linux-omap-pm/dss2/0013-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch
new file mode 100644
index 0000000000..781af9c7eb
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0013-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch
@@ -0,0 +1,51 @@
+From 22e54d90b60675e8584d92d92493e0579e69e589 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 16:48:41 +0300
+Subject: [PATCH 013/146] DSS2: Add function to get DSS logic clock rate
+
+---
+ drivers/video/omap2/dss/dispc.c | 15 +++++++++++++++
+ drivers/video/omap2/dss/dss.h | 1 +
+ 2 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 2480a03..1bc23f7 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1850,6 +1850,21 @@ unsigned long dispc_fclk_rate(void)
+ return r;
+ }
+
++unsigned long dispc_lclk_rate(void)
++{
++ int lcd;
++ unsigned long r;
++ u32 l;
++
++ l = dispc_read_reg(DISPC_DIVISOR);
++
++ lcd = FLD_GET(l, 23, 16);
++
++ r = dispc_fclk_rate();
++
++ return r / lcd;
++}
++
+ unsigned long dispc_pclk_rate(void)
+ {
+ int lcd, pcd;
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index bac5ece..0be42b6 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -294,6 +294,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch);
+
+ void dispc_set_lcd_timings(struct omap_video_timings *timings);
+ unsigned long dispc_fclk_rate(void);
++unsigned long dispc_lclk_rate(void);
+ unsigned long dispc_pclk_rate(void);
+ void dispc_set_pol_freq(struct omap_panel *panel);
+ void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0014-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch b/recipes/linux/linux-omap-pm/dss2/0014-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch
new file mode 100644
index 0000000000..090a9ea68c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0014-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch
@@ -0,0 +1,68 @@
+From ea00b61dccecbcddadc0c69d18a220d563a56754 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 16:49:27 +0300
+Subject: [PATCH 014/146] DSS2: DSI: calculate VP_CLK_RATIO properly
+
+---
+ drivers/video/omap2/dss/dsi.c | 17 +++++++++++------
+ 1 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 4442931..aecb89d 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1104,7 +1104,10 @@ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+- /* configure dispc fck and pixel clock to something sane */
++ /* XXX this should be calculated depending on the screen size,
++ * required framerate and DSI speed.
++ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
++ * with two lanes */
+ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
+ if (r)
+ goto err0;
+@@ -1119,7 +1122,7 @@ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+ if (r)
+ goto err0;
+
+- /* PLL does not come out of reset without this... */
++ /* XXX PLL does not come out of reset without this... */
+ dispc_pck_free_enable(1);
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
+@@ -1128,8 +1131,8 @@ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+ goto err1;
+ }
+
+- /* ... but if left on, we get problems when planes do not
+- * fill the whole display. No idea about this XXX */
++ /* XXX ... but if left on, we get problems when planes do not
++ * fill the whole display. No idea about this */
+ dispc_pck_free_enable(0);
+
+ if (enable_hsclk && enable_hsdiv)
+@@ -2214,6 +2217,7 @@ static int dsi_proto_config(struct omap_display *display)
+ {
+ u32 r;
+ int buswidth = 0;
++ int div;
+
+ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
+ DSI_FIFO_SIZE_0,
+@@ -2254,8 +2258,9 @@ static int dsi_proto_config(struct omap_display *display)
+ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
+ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
+ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
+- /* XXX what should the ratio be */
+- r = FLD_MOD(r, 0, 4, 4); /* VP_CLK_RATIO, VP_PCLK = VP_CLK/2 */
++
++ div = dispc_lclk_rate() / dispc_pclk_rate();
++ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
+ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
+ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
+ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-improve-packet-len-calculation.patch b/recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-improve-packet-len-calculation.patch
new file mode 100644
index 0000000000..9fc0f8cbcf
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0015-DSS2-DSI-improve-packet-len-calculation.patch
@@ -0,0 +1,58 @@
+From 539f93c4bc0119abf79d9a25955e863309ae6771 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Apr 2009 17:42:26 +0300
+Subject: [PATCH 015/146] DSS2: DSI: improve packet len calculation
+
+---
+ drivers/video/omap2/dss/dsi.c | 21 ++++++++++++++++-----
+ 1 files changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index aecb89d..66ac6ea 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2624,17 +2624,28 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+ int bytespp = 3;
++ int len;
+ int total_len;
+- int line_packet_len;
++ int packet_payload;
++ int packet_len;
+ u32 l;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+ x, y, w, h);
+
+- /* TODO: one packet could be longer, I think? Max is the line buffer */
+- line_packet_len = w * bytespp + 1; /* 1 byte for DCS cmd */
+- total_len = line_packet_len * h;
++ len = w * h * bytespp;
++
++ /* XXX: one packet could be longer, I think? Line buffer is
++ * 1024 x 24bits, but we have to put DCS cmd there also.
++ * 1023 * 3 should work, but causes strange color effects. */
++ packet_payload = min(w, (u16)1020) * bytespp;
++
++ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
++ total_len = (len / packet_payload) * packet_len;
++
++ if (len % packet_payload)
++ total_len += (len % packet_payload) + 1;
+
+ display->ctrl->setup_update(display, x, y, w, h);
+
+@@ -2646,7 +2657,7 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+ dsi_write_reg(DSI_VC_TE(1), l);
+
+- dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, line_packet_len, 0);
++ dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
+
+ if (dsi.use_te)
+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0016-DSS2-Disable-video-planes-on-sync-lost-error.patch b/recipes/linux/linux-omap-pm/dss2/0016-DSS2-Disable-video-planes-on-sync-lost-error.patch
new file mode 100644
index 0000000000..8d33f7f5ff
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0016-DSS2-Disable-video-planes-on-sync-lost-error.patch
@@ -0,0 +1,103 @@
+From adc4913d614b6b523dfe5ba115d2690043ab8ee9 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 3 Apr 2009 19:09:20 +0200
+Subject: [PATCH 016/146] DSS2: Disable video planes on sync lost error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When encountering the sync lost error disable the display and all video
+planes on the affected manager. Afterwards re-enable the display.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 50 +++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 50 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 1bc23f7..41734f3 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2518,29 +2518,79 @@ static void dispc_error_worker(struct work_struct *work)
+ }
+
+ if (errors & DISPC_IRQ_SYNC_LOST) {
++ struct omap_overlay_manager *manager = NULL;
++ bool enable = false;
++
+ DSSERR("SYNC_LOST, disabling LCD\n");
++
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
++ manager = mgr;
++ enable = mgr->display->state ==
++ OMAP_DSS_DISPLAY_ACTIVE;
+ mgr->display->disable(mgr->display);
+ break;
+ }
+ }
++
++ if (manager) {
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id != 0 && ovl->manager == manager)
++ dispc_enable_plane(ovl->id, 0);
++ }
++
++ dispc_go(manager->id);
++ mdelay(50);
++ if (enable)
++ manager->display->enable(manager->display);
++ }
+ }
+
+ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
++ struct omap_overlay_manager *manager = NULL;
++ bool enable = false;
++
+ DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
++
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
++ manager = mgr;
++ enable = mgr->display->state ==
++ OMAP_DSS_DISPLAY_ACTIVE;
+ mgr->display->disable(mgr->display);
+ break;
+ }
+ }
++
++ if (manager) {
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ continue;
++
++ if (ovl->id != 0 && ovl->manager == manager)
++ dispc_enable_plane(ovl->id, 0);
++ }
++
++ dispc_go(manager->id);
++ mdelay(50);
++ if (enable)
++ manager->display->enable(manager->display);
++ }
+ }
+
+ if (errors & DISPC_IRQ_OCP_ERR) {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0017-DSS2-check-for-ovl-paddr-only-when-enabling.patch b/recipes/linux/linux-omap-pm/dss2/0017-DSS2-check-for-ovl-paddr-only-when-enabling.patch
new file mode 100644
index 0000000000..1e9e4f4b78
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0017-DSS2-check-for-ovl-paddr-only-when-enabling.patch
@@ -0,0 +1,40 @@
+From 79d7d58e0fe8b0fb2c7b68116be30f37d3389f2f Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 7 Apr 2009 10:01:58 +0300
+Subject: [PATCH 017/146] DSS2: check for ovl paddr only when enabling
+
+It seems Xvideo uses SETUP_PLANE ioctl even when
+the fb memory has not been allocated. Sigh.
+---
+ drivers/video/omap2/dss/overlay.c | 8 +++++---
+ 1 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 9209acf..c047206 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -281,6 +281,11 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display)
+
+ info = &ovl->info;
+
++ if (info->paddr == 0) {
++ DSSDBG("check_overlay failed: paddr 0\n");
++ return -EINVAL;
++ }
++
+ display->get_resolution(display, &dw, &dh);
+
+ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
+@@ -331,9 +336,6 @@ static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
+ int r;
+ struct omap_overlay_info old_info;
+
+- if (info->paddr == 0)
+- return -EINVAL;
+-
+ old_info = ovl->info;
+ ovl->info = *info;
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0018-DSS2-Check-fclk-limits-when-configuring-video-plane.patch b/recipes/linux/linux-omap-pm/dss2/0018-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
new file mode 100644
index 0000000000..8ae7666a7d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0018-DSS2-Check-fclk-limits-when-configuring-video-plane.patch
@@ -0,0 +1,183 @@
+From ca0485ad7fcd29a0190eccd6b58bcd22794d4a7d Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 6 Apr 2009 17:32:04 +0200
+Subject: [PATCH 018/146] DSS2: Check fclk limits when configuring video planes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Check that the currect functional clock is fast enough to support
+the requested scaling ratios. Also check if 5-tap filtering can be
+used even though the downscaling ratio is less than 1:2 since the
+functional clock rate required for 5-tap filtering can be less than
+the requirement for 3-tap filtering, and 5-tap filtering should look
+better.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 104 ++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 97 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 41734f3..61861d8 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1026,11 +1026,11 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+ static void _dispc_set_scaling(enum omap_plane plane,
+ u16 orig_width, u16 orig_height,
+ u16 out_width, u16 out_height,
+- bool ilace)
++ bool ilace, bool five_taps)
+ {
+ int fir_hinc;
+ int fir_vinc;
+- int hscaleup, vscaleup, five_taps;
++ int hscaleup, vscaleup;
+ int fieldmode = 0;
+ int accu0 = 0;
+ int accu1 = 0;
+@@ -1040,7 +1040,6 @@ static void _dispc_set_scaling(enum omap_plane plane,
+
+ hscaleup = orig_width <= out_width;
+ vscaleup = orig_height <= out_height;
+- five_taps = orig_height > out_height * 2;
+
+ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
+
+@@ -1283,6 +1282,73 @@ static void calc_rotation_offset(u8 rotation, bool mirror,
+ }
+ }
+
++static unsigned long calc_fclk_five_taps(u16 width, u16 height,
++ u16 out_width, u16 out_height, enum omap_color_mode color_mode)
++{
++ u32 fclk = 0;
++ /* FIXME venc pclk? */
++ u64 tmp, pclk = dispc_pclk_rate();
++
++ if (height > out_height) {
++ /* FIXME get real display PPL */
++ unsigned int ppl = 800;
++
++ tmp = pclk * height * out_width;
++ do_div(tmp, 2 * out_height * ppl);
++ fclk = tmp;
++
++ if (height > 2 * out_height) {
++ tmp = pclk * (height - 2 * out_height) * out_width;
++ do_div(tmp, 2 * out_height * (ppl - out_width));
++ fclk = max(fclk, (u32) tmp);
++ }
++ }
++
++ if (width > out_width) {
++ tmp = pclk * width;
++ do_div(tmp, out_width);
++ fclk = max(fclk, (u32) tmp);
++
++ if (color_mode == OMAP_DSS_COLOR_RGB24U)
++ fclk <<= 1;
++ }
++
++ return fclk;
++}
++
++static unsigned long calc_fclk(u16 width, u16 height,
++ u16 out_width, u16 out_height,
++ enum omap_color_mode color_mode, bool five_taps)
++{
++ unsigned int hf, vf;
++
++ if (five_taps)
++ return calc_fclk_five_taps(width, height,
++ out_width, out_height, color_mode);
++
++ /*
++ * FIXME how to determine the 'A' factor
++ * for the no downscaling case ?
++ */
++
++ if (width > 3 * out_width)
++ hf = 4;
++ else if (width > 2 * out_width)
++ hf = 3;
++ else if (width > out_width)
++ hf = 2;
++ else
++ hf = 1;
++
++ if (height > out_height)
++ vf = 2;
++ else
++ vf = 1;
++
++ /* FIXME venc pclk? */
++ return dispc_pclk_rate() * vf * hf;
++}
++
+ static int _dispc_setup_plane(enum omap_plane plane,
+ enum omap_channel channel_out,
+ u32 paddr, u16 screen_width,
+@@ -1294,7 +1360,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ u8 rotation, int mirror)
+ {
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+- bool five_taps = height > out_height * 2;
++ bool five_taps = 0;
+ bool fieldmode = 0;
+ int cconv = 0;
+ unsigned offset0, offset1;
+@@ -1323,8 +1389,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ }
+ } else {
+ /* video plane */
+- if (width > (2048 >> five_taps))
+- return -EINVAL;
++
++ unsigned long fclk;
+
+ if (out_width < width / maxdownscale ||
+ out_width > width * 8)
+@@ -1356,6 +1422,30 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ default:
+ return -EINVAL;
+ }
++
++ /* Must use 5-tap filter? */
++ five_taps = height > out_height * 2;
++
++ /* Try to use 5-tap filter whenever possible. */
++ if (cpu_is_omap34xx() && !five_taps &&
++ height > out_height && width <= 1024) {
++ fclk = calc_fclk_five_taps(width, height,
++ out_width, out_height, color_mode);
++ if (fclk <= dispc_fclk_rate())
++ five_taps = true;
++ }
++
++ if (width > (2048 >> five_taps))
++ return -EINVAL;
++
++ fclk = calc_fclk(width, height, out_width, out_height,
++ color_mode, five_taps);
++
++ DSSDBG("required fclk rate = %lu Hz\n", fclk);
++ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
++
++ if (fclk > dispc_fclk_rate())
++ return -EINVAL;
+ }
+
+ if (ilace && height >= out_height)
+@@ -1399,7 +1489,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ if (plane != OMAP_DSS_GFX) {
+ _dispc_set_scaling(plane, width, height,
+ out_width, out_height,
+- ilace);
++ ilace, five_taps);
+ _dispc_set_vid_size(plane, out_width, out_height);
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-scaling-limits-against-proper-values.patch b/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-scaling-limits-against-proper-values.patch
new file mode 100644
index 0000000000..47541f6c98
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0019-DSS2-Check-scaling-limits-against-proper-values.patch
@@ -0,0 +1,79 @@
+From 16b86930f796436e4f440626980a25df71b6a8ec Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 6 Apr 2009 17:32:05 +0200
+Subject: [PATCH 019/146] DSS2: Check scaling limits against proper values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Move the ilace and fieldmode related height adjustments to be performed
+before checking the scaling limits.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 31 ++++++++++++++++---------------
+ 1 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 61861d8..ae7be3d 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1366,10 +1366,25 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ unsigned offset0, offset1;
+ s32 row_inc;
+ s32 pix_inc;
++ u16 frame_height = height;
+
+ if (paddr == 0)
+ return -EINVAL;
+
++ if (ilace && height >= out_height)
++ fieldmode = 1;
++
++ if (ilace) {
++ if (fieldmode)
++ height /= 2;
++ pos_y /= 2;
++ out_height /= 2;
++
++ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
++ "out_height %d\n",
++ height, pos_y, out_height);
++ }
++
+ if (plane == OMAP_DSS_GFX) {
+ if (width != out_width || height != out_height)
+ return -EINVAL;
+@@ -1448,28 +1463,14 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ return -EINVAL;
+ }
+
+- if (ilace && height >= out_height)
+- fieldmode = 1;
+-
+ calc_rotation_offset(rotation, mirror,
+- screen_width, width, height, color_mode,
++ screen_width, width, frame_height, color_mode,
+ fieldmode,
+ &offset0, &offset1, &row_inc, &pix_inc);
+
+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+ offset0, offset1, row_inc, pix_inc);
+
+- if (ilace) {
+- if (fieldmode)
+- height /= 2;
+- pos_y /= 2;
+- out_height /= 2;
+-
+- DSSDBG("adjusting for ilace: height %d, pos_y %d, "
+- "out_height %d\n",
+- height, pos_y, out_height);
+- }
+-
+ _dispc_set_channel_out(plane, channel_out);
+ _dispc_set_color_mode(plane, color_mode);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0020-DSS2-Add-venc-register-dump.patch b/recipes/linux/linux-omap-pm/dss2/0020-DSS2-Add-venc-register-dump.patch
new file mode 100644
index 0000000000..bf63b3a058
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0020-DSS2-Add-venc-register-dump.patch
@@ -0,0 +1,96 @@
+From c36a2e49cae0ae5e1068e68dee23987df763ca0e Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 6 Apr 2009 17:32:06 +0200
+Subject: [PATCH 020/146] DSS2: Add venc register dump
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Add a new file to debugfs to dump the VENC registers. The function
+prototype was already there but the implementation was missing.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/venc.c | 55 ++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 55 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index aceed9f..b655df4 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -30,6 +30,7 @@
+ #include <linux/completion.h>
+ #include <linux/delay.h>
+ #include <linux/string.h>
++#include <linux/seq_file.h>
+
+ #include <mach/display.h>
+ #include <mach/cpu.h>
+@@ -81,6 +82,7 @@
+ #define VENC_TVDETGP_INT_START_STOP_Y 0xB4
+ #define VENC_GEN_CTRL 0xB8
+ #define VENC_OUTPUT_CONTROL 0xC4
++#define VENC_OUTPUT_TEST 0xC8
+ #define VENC_DAC_B__DAC_C 0xC8
+
+ struct venc_config {
+@@ -598,3 +600,56 @@ void venc_init_display(struct omap_display *display)
+ display->set_timings = venc_set_timings;
+ display->check_timings = venc_check_timings;
+ }
++
++void venc_dump_regs(struct seq_file *s)
++{
++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
++
++ venc_enable_clocks(1);
++
++ DUMPREG(VENC_F_CONTROL);
++ DUMPREG(VENC_VIDOUT_CTRL);
++ DUMPREG(VENC_SYNC_CTRL);
++ DUMPREG(VENC_LLEN);
++ DUMPREG(VENC_FLENS);
++ DUMPREG(VENC_HFLTR_CTRL);
++ DUMPREG(VENC_CC_CARR_WSS_CARR);
++ DUMPREG(VENC_C_PHASE);
++ DUMPREG(VENC_GAIN_U);
++ DUMPREG(VENC_GAIN_V);
++ DUMPREG(VENC_GAIN_Y);
++ DUMPREG(VENC_BLACK_LEVEL);
++ DUMPREG(VENC_BLANK_LEVEL);
++ DUMPREG(VENC_X_COLOR);
++ DUMPREG(VENC_M_CONTROL);
++ DUMPREG(VENC_BSTAMP_WSS_DATA);
++ DUMPREG(VENC_S_CARR);
++ DUMPREG(VENC_LINE21);
++ DUMPREG(VENC_LN_SEL);
++ DUMPREG(VENC_L21__WC_CTL);
++ DUMPREG(VENC_HTRIGGER_VTRIGGER);
++ DUMPREG(VENC_SAVID__EAVID);
++ DUMPREG(VENC_FLEN__FAL);
++ DUMPREG(VENC_LAL__PHASE_RESET);
++ DUMPREG(VENC_HS_INT_START_STOP_X);
++ DUMPREG(VENC_HS_EXT_START_STOP_X);
++ DUMPREG(VENC_VS_INT_START_X);
++ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
++ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
++ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
++ DUMPREG(VENC_VS_EXT_STOP_Y);
++ DUMPREG(VENC_AVID_START_STOP_X);
++ DUMPREG(VENC_AVID_START_STOP_Y);
++ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
++ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
++ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
++ DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
++ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
++ DUMPREG(VENC_GEN_CTRL);
++ DUMPREG(VENC_OUTPUT_CONTROL);
++ DUMPREG(VENC_OUTPUT_TEST);
++
++ venc_enable_clocks(0);
++
++#undef DUMPREG
++}
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0021-DSS2-FB-remove-unused-var-warning.patch b/recipes/linux/linux-omap-pm/dss2/0021-DSS2-FB-remove-unused-var-warning.patch
new file mode 100644
index 0000000000..736c7e6e1e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0021-DSS2-FB-remove-unused-var-warning.patch
@@ -0,0 +1,27 @@
+From 4b1e929ef1d15f565d166fa19ffd501f547b8eb0 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Mon, 6 Apr 2009 22:26:04 +0200
+Subject: [PATCH 021/146] DSS2: FB: remove unused var warning
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index afe40a9..12ce0c3 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1246,7 +1246,9 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ display->get_resolution(display, &w, &h);
+
+ if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++#ifdef DEBUG
+ int oldw = w, oldh = h;
++#endif
+
+ omap_vrfb_adjust_size(&w, &h, bytespp);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0022-DSS2-pass-the-default-FB-color-format-through-board.patch b/recipes/linux/linux-omap-pm/dss2/0022-DSS2-pass-the-default-FB-color-format-through-board.patch
new file mode 100644
index 0000000000..0dcff125de
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0022-DSS2-pass-the-default-FB-color-format-through-board.patch
@@ -0,0 +1,214 @@
+From 353b8aba981b1ebc892d84e4c40b1fd4201079db Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 8 Apr 2009 12:51:46 +0200
+Subject: [PATCH 022/146] DSS2: pass the default FB color format through board info
+
+Add a field to the FB memory region platform data, so that board
+init code can pass a default color format to the driver. Set this
+format as an initial setting for the given FB.
+
+This is needed for an upcoming patch that adds detection of the
+color format set by the bootloader.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 121 +++++++++++++++++++++++++++---
+ drivers/video/omap2/omapfb/omapfb.h | 2 +
+ include/linux/omapfb.h | 5 +
+ 3 files changed, 117 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 12ce0c3..67c67c2 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -370,6 +370,21 @@ static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
+ return -EINVAL;
+ }
+
++static int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
++ struct fb_var_screeninfo *var)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
++ struct omapfb_colormode *mode = &omapfb_colormodes[i];
++ if (dssmode == mode->dssmode) {
++ assign_colormode_to_var(var, mode);
++ return 0;
++ }
++ }
++ return -ENOENT;
++}
++
+ void set_fb_fix(struct fb_info *fbi)
+ {
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+@@ -1267,6 +1282,60 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ return omapfb_alloc_fbmem(fbi, size, paddr);
+ }
+
++static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format format)
++{
++ enum omap_color_mode mode;
++
++ switch (format) {
++ case OMAPFB_COLOR_RGB565:
++ mode = OMAP_DSS_COLOR_RGB16;
++ break;
++ case OMAPFB_COLOR_YUV422:
++ mode = OMAP_DSS_COLOR_YUV2;
++ break;
++ case OMAPFB_COLOR_CLUT_8BPP:
++ mode = OMAP_DSS_COLOR_CLUT8;
++ break;
++ case OMAPFB_COLOR_CLUT_4BPP:
++ mode = OMAP_DSS_COLOR_CLUT4;
++ break;
++ case OMAPFB_COLOR_CLUT_2BPP:
++ mode = OMAP_DSS_COLOR_CLUT2;
++ break;
++ case OMAPFB_COLOR_CLUT_1BPP:
++ mode = OMAP_DSS_COLOR_CLUT1;
++ break;
++ case OMAPFB_COLOR_RGB444:
++ mode = OMAP_DSS_COLOR_RGB12U;
++ break;
++ case OMAPFB_COLOR_YUY422:
++ mode = OMAP_DSS_COLOR_UYVY;
++ break;
++ case OMAPFB_COLOR_ARGB16:
++ mode = OMAP_DSS_COLOR_ARGB16;
++ break;
++ case OMAPFB_COLOR_RGB24U:
++ mode = OMAP_DSS_COLOR_RGB24U;
++ break;
++ case OMAPFB_COLOR_RGB24P:
++ mode = OMAP_DSS_COLOR_RGB24P;
++ break;
++ case OMAPFB_COLOR_ARGB32:
++ mode = OMAP_DSS_COLOR_ARGB32;
++ break;
++ case OMAPFB_COLOR_RGBA32:
++ mode = OMAP_DSS_COLOR_RGBA32;
++ break;
++ case OMAPFB_COLOR_RGBX32:
++ mode = OMAP_DSS_COLOR_RGBX32;
++ break;
++ default:
++ mode = -EINVAL;
++ }
++
++ return mode;
++}
++
+ static int omapfb_parse_vram_param(const char *param, int max_entries,
+ unsigned long *sizes, unsigned long *paddrs)
+ {
+@@ -1483,9 +1552,36 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ }
+
+ var->nonstd = 0;
++ var->bits_per_pixel = 0;
+
+ var->rotate = ofbi->rotation;
+
++ /*
++ * Check if there is a default color format set in the board file,
++ * and use this format instead the default deducted from the
++ * display bpp.
++ */
++ if (fbdev->dev->platform_data) {
++ struct omapfb_platform_data *opd;
++ int id = ofbi->id;
++
++ opd = fbdev->dev->platform_data;
++ if (opd->mem_desc.region[id].format_used) {
++ enum omap_color_mode mode;
++ enum omapfb_color_format format;
++
++ format = opd->mem_desc.region[id].format;
++ mode = fb_format_to_dss_mode(format);
++ if (mode < 0) {
++ r = mode;
++ goto err;
++ }
++ r = dss_mode_to_fb_mode(mode, var);
++ if (r < 0)
++ goto err;
++ }
++ }
++
+ if (display) {
+ u16 w, h;
+ display->get_resolution(display, &w, &h);
+@@ -1502,16 +1598,18 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+- switch (display->get_recommended_bpp(display)) {
+- case 16:
+- var->bits_per_pixel = 16;
+- break;
+- case 24:
+- var->bits_per_pixel = 32;
+- break;
+- default:
+- dev_err(fbdev->dev, "illegal display bpp\n");
+- return -EINVAL;
++ if (!var->bits_per_pixel) {
++ switch (display->get_recommended_bpp(display)) {
++ case 16:
++ var->bits_per_pixel = 16;
++ break;
++ case 24:
++ var->bits_per_pixel = 32;
++ break;
++ default:
++ dev_err(fbdev->dev, "illegal display bpp\n");
++ return -EINVAL;
++ }
+ }
+ } else {
+ /* if there's no display, let's just guess some basic values */
+@@ -1519,7 +1617,8 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ var->yres = 240;
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+- var->bits_per_pixel = 16;
++ if (!var->bits_per_pixel)
++ var->bits_per_pixel = 16;
+ }
+
+ r = check_fb_var(fbi, var);
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+index 65e9e6e..2607def 100644
+--- a/drivers/video/omap2/omapfb/omapfb.h
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -27,6 +27,8 @@
+ #define DEBUG
+ #endif
+
++#include <mach/display.h>
++
+ #ifdef DEBUG
+ extern unsigned int omapfb_debug;
+ #define DBG(format, ...) \
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index 96190b2..7a34f22 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -298,6 +298,11 @@ struct omapfb_mem_region {
+ void __iomem *vaddr;
+ unsigned long size;
+ u8 type; /* OMAPFB_PLANE_MEM_* */
++ enum omapfb_color_format format;/* OMAPFB_COLOR_* */
++ unsigned format_used:1; /* Must be set when format is set.
++ * Needed b/c of the badly chosen 0
++ * base for OMAPFB_COLOR_* values
++ */
+ unsigned alloc:1; /* allocated by the driver */
+ unsigned map:1; /* kernel mapped by the driver */
+ };
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0023-DSS2-Beagle-Use-gpio_set_value.patch b/recipes/linux/linux-omap-pm/dss2/0023-DSS2-Beagle-Use-gpio_set_value.patch
new file mode 100644
index 0000000000..568c4fb00c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0023-DSS2-Beagle-Use-gpio_set_value.patch
@@ -0,0 +1,48 @@
+From c01ef38cc851f53008c0f1491f568b8554270441 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 9 Apr 2009 12:10:46 +0300
+Subject: [PATCH 023/146] DSS2: Beagle: Use gpio_set_value
+
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 10 +++++++---
+ 1 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index c2c76b0..4ab7396 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -350,7 +350,7 @@ static struct platform_device keys_gpio = {
+ static int beagle_enable_dvi(struct omap_display *display)
+ {
+ if (display->hw_config.panel_reset_gpio != -1)
+- gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
++ gpio_set_value(display->hw_config.panel_reset_gpio, 1);
+
+ return 0;
+ }
+@@ -358,7 +358,7 @@ static int beagle_enable_dvi(struct omap_display *display)
+ static void beagle_disable_dvi(struct omap_display *display)
+ {
+ if (display->hw_config.panel_reset_gpio != -1)
+- gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
++ gpio_set_value(display->hw_config.panel_reset_gpio, 0);
+ }
+
+ static struct omap_dss_display_config beagle_display_data_dvi = {
+@@ -423,8 +423,12 @@ static void __init beagle_display_init(void)
+ int r;
+
+ r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+- if (r < 0)
++ if (r < 0) {
+ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
++ return;
++ }
++
++ gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+ }
+
+ static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0024-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch b/recipes/linux/linux-omap-pm/dss2/0024-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch
new file mode 100644
index 0000000000..2f7d475c49
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0024-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch
@@ -0,0 +1,28 @@
+From 5ba7dbfd877bf8c345419b2985e5b26c2934d1d3 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Mon, 13 Apr 2009 18:50:24 +0530
+Subject: [PATCH 024/146] DSS2: VRFB: Macro for calculating base address of the VRFB context was faulty
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/vrfb.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 7e0f8fc..d68065f 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -16,8 +16,8 @@
+
+ #define SMS_ROT_VIRT_BASE(context, rot) \
+ (((context >= 4) ? 0xD0000000 : 0x70000000) \
+- | 0x4000000 * (context) \
+- | 0x1000000 * (rot))
++ + (0x4000000 * (context)) \
++ + (0x1000000 * (rot)))
+
+ #define OMAP_VRFB_SIZE (2048 * 2048 * 4)
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0025-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch b/recipes/linux/linux-omap-pm/dss2/0025-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch
new file mode 100644
index 0000000000..dde493b544
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0025-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch
@@ -0,0 +1,78 @@
+From 76650cba4f338e9a15f6cb4bab56580802632dd0 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 15 Apr 2009 14:06:54 +0300
+Subject: [PATCH 025/146] DSS2: DSI: sidlemode to noidle while sending frame
+
+DISPC interrupts are not wake-up capable. Smart-idle in DISPC_SIDLEMODE
+causes DSS interface to go to idle at the end of the frame, and the
+FRAMEDONE interrupt is then delayed until something wakes up the DSS
+interface.
+
+So we set SIDLEMODE to no-idle when we start sending the frame, and
+set it back to smart-idle after receiving FRAMEDONE.
+---
+ drivers/video/omap2/dss/dispc.c | 10 ++++++++++
+ drivers/video/omap2/dss/dsi.c | 4 ++++
+ drivers/video/omap2/dss/dss.h | 3 +++
+ 3 files changed, 17 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index ae7be3d..16c68b8 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2791,6 +2791,16 @@ static void _omap_dispc_initialize_irq(void)
+ omap_dispc_set_irqs();
+ }
+
++void dispc_enable_sidle(void)
++{
++ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
++}
++
++void dispc_disable_sidle(void)
++{
++ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
++}
++
+ static void _omap_dispc_initial_config(void)
+ {
+ u32 l;
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 66ac6ea..50af925 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2665,6 +2665,8 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+ dsi_write_reg(DSI_VC_TE(1), l);
+
++ dispc_disable_sidle();
++
+ dispc_enable_lcd_out(1);
+
+ if (dsi.use_te)
+@@ -2678,6 +2680,8 @@ static void framedone_callback(void *data, u32 mask)
+ return;
+ }
+
++ dispc_enable_sidle();
++
+ dsi.framedone_scheduled = 1;
+
+ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 0be42b6..d0917a8 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -244,6 +244,9 @@ void dispc_fake_vsync_irq(void);
+ void dispc_save_context(void);
+ void dispc_restore_context(void);
+
++void dispc_enable_sidle(void);
++void dispc_disable_sidle(void);
++
+ void dispc_lcd_enable_signal_polarity(bool act_high);
+ void dispc_lcd_enable_signal(bool enable);
+ void dispc_pck_free_enable(bool enable);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0026-DSS2-VRFB-rotation-and-mirroring-implemented.patch b/recipes/linux/linux-omap-pm/dss2/0026-DSS2-VRFB-rotation-and-mirroring-implemented.patch
new file mode 100644
index 0000000000..52c2942fde
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0026-DSS2-VRFB-rotation-and-mirroring-implemented.patch
@@ -0,0 +1,324 @@
+From 684d15b8505257b465ec26e473882560383471b8 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 9 Apr 2009 12:09:44 +0530
+Subject: [PATCH 026/146] DSS2: VRFB rotation and mirroring implemented.
+
+DSS2 modified to accept the rotation_type input
+to get the dma or VRFB rotation.
+
+DSS2: VRFB: Changed to pass DSS mode to vrfb_setup instead of Bpp.
+
+VRFB size registers requires the width to be halved when the
+mode is YUV or UYVY. So modifed to pass the mode to omap_vrfb_setup
+function.
+
+Code added by Tim Yamin for few bug fixes
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 6 ++
+ arch/arm/plat-omap/include/mach/vrfb.h | 3 +-
+ arch/arm/plat-omap/vrfb.c | 36 +++++++++-
+ drivers/video/omap2/dss/dispc.c | 109 +++++++++++++++++++++++++++--
+ drivers/video/omap2/dss/dss.h | 1 +
+ drivers/video/omap2/dss/manager.c | 1 +
+ 6 files changed, 144 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 6b702c7..b0a6272 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -341,6 +341,11 @@ enum omap_dss_overlay_managers {
+
+ struct omap_overlay_manager;
+
++enum omap_dss_rotation_type {
++ OMAP_DSS_ROT_DMA = 0,
++ OMAP_DSS_ROT_VRFB = 1,
++};
++
+ struct omap_overlay_info {
+ bool enabled;
+
+@@ -351,6 +356,7 @@ struct omap_overlay_info {
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
++ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+
+ u16 pos_x;
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index 2047862..12c7fab 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -24,6 +24,7 @@
+ #ifndef __VRFB_H
+ #define __VRFB_H
+
++#include <mach/display.h>
+ #define OMAP_VRFB_LINE_LEN 2048
+
+ struct vrfb
+@@ -42,6 +43,6 @@ extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp);
+ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+- u8 bytespp);
++ enum omap_color_mode color_mode);
+
+ #endif /* __VRFB_H */
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index d68065f..2f08f6d 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -5,7 +5,6 @@
+
+ #include <mach/io.h>
+ #include <mach/vrfb.h>
+-
+ /*#define DEBUG*/
+
+ #ifdef DEBUG
+@@ -50,19 +49,48 @@ EXPORT_SYMBOL(omap_vrfb_adjust_size);
+
+ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+- u8 bytespp)
++ enum omap_color_mode color_mode)
+ {
+ unsigned pixel_size_exp;
+ u16 vrfb_width;
+ u16 vrfb_height;
+ u8 ctx = vrfb->context;
++ u8 bytespp;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+ width, height, bytespp);
+
+- if (bytespp == 4)
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ bytespp = 2;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ bytespp = 3;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ bytespp = 4;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY)
++ width >>= 1;
++
++ if (bytespp == 4) {
+ pixel_size_exp = 2;
+- else if (bytespp == 2)
++ } else if (bytespp == 2)
+ pixel_size_exp = 1;
+ else
+ BUG();
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 16c68b8..23a8155 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1106,7 +1106,7 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ case 0: vidrot = 0; break;
+ case 1: vidrot = 1; break;
+ case 2: vidrot = 2; break;
+- case 3: vidrot = 1; break;
++ case 3: vidrot = 3; break;
+ }
+ }
+
+@@ -1134,7 +1134,92 @@ static s32 pixinc(int pixels, u8 ps)
+ BUG();
+ }
+
+-static void calc_rotation_offset(u8 rotation, bool mirror,
++static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
++ u16 screen_width,
++ u16 width, u16 height,
++ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned *offset0, unsigned *offset1,
++ s32 *row_inc, s32 *pix_inc)
++{
++ u8 ps;
++
++ switch (color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ ps = 2;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ ps = 3;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ ps = 4;
++ break;
++
++ default:
++ BUG();
++ return;
++ }
++
++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
++ width, height);
++ switch (rotation + mirror * 4) {
++ case 0:
++ case 2:
++ /*
++ * If the pixel format is YUV or UYVY divide the width
++ * of the image by 2 for 0 and 180 degree rotation.
++ */
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY)
++ width = width >> 1;
++ case 1:
++ case 3:
++ *offset0 = 0;
++ if (fieldmode)
++ *offset1 = screen_width * ps;
++ else
++ *offset1 = 0;
++
++ *row_inc = pixinc(1 + (screen_width - width) +
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ case 4:
++ case 6:
++ /* If the pixel format is YUV or UYVY divide the width
++ * of the image by 2 for 0 degree and 180 degree
++ */
++ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
++ color_mode == OMAP_DSS_COLOR_UYVY)
++ width = width >> 1;
++ case 5:
++ case 7:
++ *offset0 = 0;
++ if (fieldmode)
++ *offset1 = screen_width * ps;
++ else
++ *offset1 = 0;
++ *row_inc = pixinc(1 - (screen_width + width) -
++ (fieldmode ? screen_width : 0),
++ ps);
++ *pix_inc = pixinc(1, ps);
++ break;
++
++ default:
++ BUG();
++ }
++}
++
++static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+@@ -1357,6 +1442,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, int mirror)
+ {
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+@@ -1463,10 +1549,16 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ return -EINVAL;
+ }
+
+- calc_rotation_offset(rotation, mirror,
+- screen_width, width, frame_height, color_mode,
+- fieldmode,
+- &offset0, &offset1, &row_inc, &pix_inc);
++ if (rotation_type == OMAP_DSS_ROT_DMA)
++ calc_dma_rotation_offset(rotation, mirror,
++ screen_width, width, frame_height, color_mode,
++ fieldmode,
++ &offset0, &offset1, &row_inc, &pix_inc);
++ else
++ calc_vrfb_rotation_offset(rotation, mirror,
++ screen_width, width, frame_height, color_mode,
++ fieldmode,
++ &offset0, &offset1, &row_inc, &pix_inc);
+
+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+ offset0, offset1, row_inc, pix_inc);
+@@ -2889,6 +2981,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror)
+ {
+ int r = 0;
+@@ -2909,6 +3002,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ width, height,
+ out_width, out_height,
+ color_mode, ilace,
++ rotation_type,
+ rotation, mirror);
+
+ enable_clocks(0);
+@@ -3122,7 +3216,8 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ pw, ph,
+ pow, poh,
+ pi->color_mode, 0,
+- pi->rotation, // XXX rotation probably wrong
++ pi->rotation_type,
++ pi->rotation,
+ pi->mirror);
+
+ dispc_enable_plane(ovl->id, 1);
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index d0917a8..584dce6 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -272,6 +272,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
++ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror);
+
+ void dispc_go(enum omap_channel channel);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index b0fee80..8ca0bbb 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -395,6 +395,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ outh,
+ ovl->info.color_mode,
+ ilace,
++ ovl->info.rotation_type,
+ ovl->info.rotation,
+ ovl->info.mirror);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0027-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch b/recipes/linux/linux-omap-pm/dss2/0027-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch
new file mode 100644
index 0000000000..e451fb1910
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0027-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch
@@ -0,0 +1,236 @@
+From c90771a625b91517a178008b83ca1925d8f8d1dd Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 9 Apr 2009 12:13:07 +0530
+Subject: [PATCH 027/146] DSS2: OMAPFB: Added support for the YUV VRFB rotation and mirroring.
+
+DSS2 now requires roatation_type to be specified by driver.
+Added support for that.
+DSS2 OMAPFB: Modified to pass the dss mode to omap_vrfb_setup function.
+
+VRFB size register requires the width to be halved when the
+mode is YUV or UYVY. So VRFB is modifed to pass the mode to omap_vrfb_setup
+function.
+
+Few changes done by Tim Yamin
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/vrfb.c | 4 +-
+ drivers/video/omap2/omapfb/omapfb-main.c | 59 ++++++++++++++----------------
+ drivers/video/omap2/omapfb/omapfb.h | 7 +---
+ 3 files changed, 30 insertions(+), 40 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 2f08f6d..2ae0d68 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -88,9 +88,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width >>= 1;
+
+- if (bytespp == 4) {
++ if (bytespp == 4)
+ pixel_size_exp = 2;
+- } else if (bytespp == 2)
++ else if (bytespp == 2)
+ pixel_size_exp = 1;
+ else
+ BUG();
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 67c67c2..57f5900 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -176,15 +176,9 @@ static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
+
+ static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
+ {
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+- unsigned offset;
+- int rot;
+-
+- rot = ofbi->rotation;
+-
+- offset = omapfb_get_vrfb_offset(ofbi, rot);
+-
+- return ofbi->region.vrfb.paddr[rot] + offset;
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ return ofbi->region.vrfb.paddr[ofbi->rotation]
++ + omapfb_get_vrfb_offset(ofbi, ofbi->rotation);
+ } else {
+ return ofbi->region.paddr;
+ }
+@@ -192,7 +186,7 @@ static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
+
+ u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
+ {
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return ofbi->region.vrfb.paddr[0];
+ else
+ return ofbi->region.paddr;
+@@ -200,7 +194,7 @@ u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
+
+ void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
+ {
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return ofbi->region.vrfb.vaddr[0];
+ else
+ return ofbi->region.vaddr;
+@@ -398,7 +392,7 @@ void set_fb_fix(struct fb_info *fbi)
+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
+ /* used by mmap in fbmem.c */
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ fix->line_length =
+ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+ else
+@@ -434,11 +428,14 @@ void set_fb_fix(struct fb_info *fbi)
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+
+- if (rg->size) {
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+- omap_vrfb_setup(&rg->vrfb, rg->paddr,
+- var->xres_virtual, var->yres_virtual,
+- var->bits_per_pixel >> 3);
++ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ enum omap_color_mode mode = 0;
++ mode = fb_mode_to_dss_mode(var);
++
++ omap_vrfb_setup(&rg->vrfb, rg->paddr,
++ var->xres_virtual,
++ var->yres_virtual,
++ mode);
+ }
+ }
+
+@@ -527,7 +524,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+ if (var->yres > var->yres_virtual)
+ var->yres = var->yres_virtual;
+
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ line_size = OMAP_VRFB_LINE_LEN * bytespp;
+ else
+ line_size = var->xres_virtual * bytespp;
+@@ -549,7 +546,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+
+ if (line_size * var->yres_virtual > max_frame_size) {
+ DBG("can't fit FB into memory, reducing x\n");
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ return -EINVAL;
+
+ var->xres_virtual = max_frame_size / var->yres_virtual /
+@@ -672,7 +669,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ struct omap_overlay_info info;
+ int xres, yres;
+ int screen_width;
+- int rot, mirror;
++ int mirror;
+
+ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
+ posx, posy, outw, outh);
+@@ -688,7 +685,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ offset = ((var->yoffset * var->xres_virtual +
+ var->xoffset) * var->bits_per_pixel) >> 3;
+
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ data_start_p = omapfb_get_region_rot_paddr(ofbi);
+ data_start_v = NULL;
+ } else {
+@@ -711,13 +708,10 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+
+ ovl->get_overlay_info(ovl, &info);
+
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+- rot = 0;
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ mirror = 0;
+- } else {
+- rot = ofbi->rotation;
++ else
+ mirror = ofbi->mirror;
+- }
+
+ info.paddr = data_start_p;
+ info.vaddr = data_start_v;
+@@ -725,7 +719,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ info.width = xres;
+ info.height = yres;
+ info.color_mode = mode;
+- info.rotation = rot;
++ info.rotation_type = ofbi->rotation_type;
++ info.rotation = ofbi->rotation;
+ info.mirror = mirror;
+
+ info.pos_x = posx;
+@@ -1121,7 +1116,7 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
+ if (rg->vaddr)
+ iounmap(rg->vaddr);
+
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ /* unmap the 0 angle rotation */
+ if (rg->vrfb.vaddr[0]) {
+ iounmap(rg->vrfb.vaddr[0]);
+@@ -1181,7 +1176,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ return -ENOMEM;
+ }
+
+- if (ofbi->rotation_type != OMAPFB_ROT_VRFB) {
++ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
+ vaddr = ioremap_wc(paddr, size);
+
+ if (!vaddr) {
+@@ -1260,7 +1255,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+
+ display->get_resolution(display, &w, &h);
+
+- if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ #ifdef DEBUG
+ int oldw = w, oldh = h;
+ #endif
+@@ -1701,8 +1696,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+ ofbi->id = i;
+
+ /* assign these early, so that fb alloc can use them */
+- ofbi->rotation_type = def_vrfb ? OMAPFB_ROT_VRFB :
+- OMAPFB_ROT_DMA;
++ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
++ OMAP_DSS_ROT_DMA;
+ ofbi->rotation = def_rotate;
+ ofbi->mirror = def_mirror;
+
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+index 2607def..43f6922 100644
+--- a/drivers/video/omap2/omapfb/omapfb.h
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -53,11 +53,6 @@ struct omapfb2_mem_region {
+ bool map; /* kernel mapped by the driver */
+ };
+
+-enum omapfb_rotation_type {
+- OMAPFB_ROT_DMA = 0,
+- OMAPFB_ROT_VRFB = 1,
+-};
+-
+ /* appended to fb_info */
+ struct omapfb_info {
+ int id;
+@@ -66,7 +61,7 @@ struct omapfb_info {
+ int num_overlays;
+ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
+ struct omapfb2_device *fbdev;
+- enum omapfb_rotation_type rotation_type;
++ enum omap_dss_rotation_type rotation_type;
+ u8 rotation;
+ bool mirror;
+ };
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch b/recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch
new file mode 100644
index 0000000000..148fc661d8
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0028-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch
@@ -0,0 +1,61 @@
+From 2e22c28ba3d4dd6c07e0c51903c8827c9a199c5e Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Mon, 13 Apr 2009 13:57:42 -0700
+Subject: [PATCH 028/146] DSS2: OMAPFB: Set line_length correctly for YUV with VRFB.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 30 +++++++++++++++++++++++++-----
+ 1 files changed, 25 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 57f5900..cd63740 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -392,10 +392,19 @@ void set_fb_fix(struct fb_info *fbi)
+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
+ /* used by mmap in fbmem.c */
+- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+- fix->line_length =
+- (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+- else
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ switch (var->nonstd) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUY422:
++ fix->line_length =
++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
++ break;
++ default:
++ fix->line_length =
++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
++ break;
++ }
++ } else
+ fix->line_length =
+ (var->xres_virtual * var->bits_per_pixel) >> 3;
+ fix->smem_start = omapfb_get_region_paddr(ofbi);
+@@ -704,7 +713,18 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ goto err;
+ }
+
+- screen_width = fix->line_length / (var->bits_per_pixel >> 3);
++ switch (var->nonstd) {
++ case OMAPFB_COLOR_YUV422:
++ case OMAPFB_COLOR_YUY422:
++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
++ screen_width = fix->line_length
++ / (var->bits_per_pixel >> 2);
++ break;
++ }
++ default:
++ screen_width = fix->line_length / (var->bits_per_pixel >> 3);
++ break;
++ }
+
+ ovl->get_overlay_info(ovl, &info);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0029-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch b/recipes/linux/linux-omap-pm/dss2/0029-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch
new file mode 100644
index 0000000000..1f7e9d826e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0029-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch
@@ -0,0 +1,29 @@
+From d005d1318e9ac306432f562bd74c6efebd577981 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Wed, 15 Apr 2009 17:05:18 +0530
+Subject: [PATCH 029/146] DSS2: dispc_get_trans_key was returning wrong key type
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/dss/dispc.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 23a8155..076d3d4 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1826,9 +1826,9 @@ void dispc_get_trans_key(enum omap_channel ch,
+ enable_clocks(1);
+ if (type) {
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+- *type = REG_GET(DISPC_CONFIG, 11, 11) >> 11;
++ *type = REG_GET(DISPC_CONFIG, 11, 11);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+- *type = REG_GET(DISPC_CONFIG, 13, 13) >> 13;
++ *type = REG_GET(DISPC_CONFIG, 13, 13);
+ else
+ BUG();
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0030-DSS2-do-bootmem-reserve-for-exclusive-access.patch b/recipes/linux/linux-omap-pm/dss2/0030-DSS2-do-bootmem-reserve-for-exclusive-access.patch
new file mode 100644
index 0000000000..0436458564
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0030-DSS2-do-bootmem-reserve-for-exclusive-access.patch
@@ -0,0 +1,33 @@
+From 18386ebea56159305014c898ffaf034b95bb7ac5 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 14 Apr 2009 14:50:11 +0200
+Subject: [PATCH 030/146] DSS2: do bootmem reserve for exclusive access
+
+BOOTMEM_DEFAULT would allow multiple reservations for the same location,
+we need to reserve the region for our exclusive use. Also check if the
+reserve succeeded.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vram.c | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index f24a110..520f260 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -524,7 +524,10 @@ void __init omapfb_reserve_sdram(void)
+ return;
+ }
+
+- reserve_bootmem(paddr, size, BOOTMEM_DEFAULT);
++ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
++ pr_err("FB: failed to reserve VRAM\n");
++ return;
++ }
+ } else {
+ if (size > sdram_size) {
+ printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0031-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch b/recipes/linux/linux-omap-pm/dss2/0031-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch
new file mode 100644
index 0000000000..b9e030619a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0031-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch
@@ -0,0 +1,35 @@
+From fe2a2cf84ab84bab840c0d2b8c92d95f1d9d6d84 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Thu, 9 Apr 2009 15:04:44 +0200
+Subject: [PATCH 031/146] DSS2: Fix DISPC_VID_FIR value for omap34xx
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The msbs of the DISPC_VID_FIR fields were incorrectly masked out on
+omap34xx and thus 4:1 downscale did not work correctly.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 076d3d4..b8a3329 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -994,7 +994,10 @@ static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+- val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
++ if (cpu_is_omap24xx())
++ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
++ else
++ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+ dispc_write_reg(fir_reg[plane-1], val);
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0032-DSS2-Prefer-3-tap-filter.patch b/recipes/linux/linux-omap-pm/dss2/0032-DSS2-Prefer-3-tap-filter.patch
new file mode 100644
index 0000000000..20156fd00e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0032-DSS2-Prefer-3-tap-filter.patch
@@ -0,0 +1,82 @@
+From d6fb2501311709ce820c3fb62c50259374c39dc5 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Thu, 9 Apr 2009 15:04:43 +0200
+Subject: [PATCH 032/146] DSS2: Prefer 3-tap filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The 5-tap filter seems rather unstable. With some scaling settings it
+works and with some it doesn't even though the functional clock remains
+within the TRM limits. So prefer the 3-tap filter unless the functional
+clock required for it is too high.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 27 ++++++++++++---------------
+ 1 files changed, 12 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b8a3329..b631dd8 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1405,15 +1405,10 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height,
+ }
+
+ static unsigned long calc_fclk(u16 width, u16 height,
+- u16 out_width, u16 out_height,
+- enum omap_color_mode color_mode, bool five_taps)
++ u16 out_width, u16 out_height)
+ {
+ unsigned int hf, vf;
+
+- if (five_taps)
+- return calc_fclk_five_taps(width, height,
+- out_width, out_height, color_mode);
+-
+ /*
+ * FIXME how to determine the 'A' factor
+ * for the no downscaling case ?
+@@ -1494,7 +1489,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ } else {
+ /* video plane */
+
+- unsigned long fclk;
++ unsigned long fclk = 0;
+
+ if (out_width < width / maxdownscale ||
+ out_width > width * 8)
+@@ -1530,20 +1525,22 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ /* Must use 5-tap filter? */
+ five_taps = height > out_height * 2;
+
+- /* Try to use 5-tap filter whenever possible. */
+- if (cpu_is_omap34xx() && !five_taps &&
+- height > out_height && width <= 1024) {
+- fclk = calc_fclk_five_taps(width, height,
+- out_width, out_height, color_mode);
+- if (fclk <= dispc_fclk_rate())
++ if (!five_taps) {
++ fclk = calc_fclk(width, height,
++ out_width, out_height);
++
++ /* Try 5-tap filter if 3-tap fclk is too high */
++ if (cpu_is_omap34xx() && height > out_height &&
++ fclk > dispc_fclk_rate())
+ five_taps = true;
+ }
+
+ if (width > (2048 >> five_taps))
+ return -EINVAL;
+
+- fclk = calc_fclk(width, height, out_width, out_height,
+- color_mode, five_taps);
++ if (five_taps)
++ fclk = calc_fclk_five_taps(width, height,
++ out_width, out_height, color_mode);
+
+ DSSDBG("required fclk rate = %lu Hz\n", fclk);
+ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0033-DSS2-VRAM-improve-omap_vram_add_region.patch b/recipes/linux/linux-omap-pm/dss2/0033-DSS2-VRAM-improve-omap_vram_add_region.patch
new file mode 100644
index 0000000000..458d4913a0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0033-DSS2-VRAM-improve-omap_vram_add_region.patch
@@ -0,0 +1,135 @@
+From 76d1928e53bbb506ddccd1f48f31c672f281c127 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 16 Apr 2009 17:56:00 +0300
+Subject: [PATCH 033/146] DSS2: VRAM: improve omap_vram_add_region()
+
+Combine postponed and non-posponed versions of omap_vram_add_region.
+Make the func non-static, so it can be called from board files.
+---
+ arch/arm/plat-omap/include/mach/vram.h | 1 +
+ arch/arm/plat-omap/vram.c | 54 +++++++++++++------------------
+ 2 files changed, 24 insertions(+), 31 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index f176562..8639e08 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -24,6 +24,7 @@
+
+ #include <asm/types.h>
+
++extern int omap_vram_add_region(unsigned long paddr, size_t size);
+ extern int omap_vram_free(unsigned long paddr, size_t size);
+ extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+ extern int omap_vram_reserve(unsigned long paddr, size_t size);
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 520f260..8e9fe77 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -60,6 +60,7 @@
+ * time when we cannot yet allocate the region list */
+ #define MAX_POSTPONED_REGIONS 10
+
++static bool vram_initialized;
+ static int postponed_cnt __initdata;
+ static struct {
+ unsigned long paddr;
+@@ -145,39 +146,32 @@ static void omap_vram_free_allocation(struct vram_alloc *va)
+ kfree(va);
+ }
+
+-static __init int omap_vram_add_region_postponed(unsigned long paddr,
+- size_t size)
+-{
+- if (postponed_cnt == MAX_POSTPONED_REGIONS)
+- return -ENOMEM;
+-
+- postponed_regions[postponed_cnt].paddr = paddr;
+- postponed_regions[postponed_cnt].size = size;
+-
+- ++postponed_cnt;
+-
+- return 0;
+-}
+-
+-/* add/remove_region can be exported if there's need to add/remove regions
+- * runtime */
+-static int omap_vram_add_region(unsigned long paddr, size_t size)
++int omap_vram_add_region(unsigned long paddr, size_t size)
+ {
+ struct vram_region *rm;
+ unsigned pages;
+
+- DBG("adding region paddr %08lx size %d\n",
+- paddr, size);
++ if (vram_initialized) {
++ DBG("adding region paddr %08lx size %d\n",
++ paddr, size);
+
+- size &= PAGE_MASK;
+- pages = size >> PAGE_SHIFT;
++ size &= PAGE_MASK;
++ pages = size >> PAGE_SHIFT;
+
+- rm = omap_vram_create_region(paddr, pages);
+- if (rm == NULL)
+- return -ENOMEM;
++ rm = omap_vram_create_region(paddr, pages);
++ if (rm == NULL)
++ return -ENOMEM;
++
++ list_add(&rm->list, &region_list);
++ } else {
++ if (postponed_cnt == MAX_POSTPONED_REGIONS)
++ return -ENOMEM;
+
+- list_add(&rm->list, &region_list);
++ postponed_regions[postponed_cnt].paddr = paddr;
++ postponed_regions[postponed_cnt].size = size;
+
++ ++postponed_cnt;
++ }
+ return 0;
+ }
+
+@@ -438,6 +432,8 @@ static __init int omap_vram_init(void)
+ {
+ int i, r;
+
++ vram_initialized = 1;
++
+ for (i = 0; i < postponed_cnt; i++)
+ omap_vram_add_region(postponed_regions[i].paddr,
+ postponed_regions[i].size);
+@@ -472,10 +468,6 @@ static void __init omapfb_early_vram(char **p)
+ omapfb_def_sdram_vram_size = memparse(*p, p);
+ if (**p == ',')
+ omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
+-
+- printk("omapfb_early_vram, %d, 0x%x\n",
+- omapfb_def_sdram_vram_size,
+- omapfb_def_sdram_vram_start);
+ }
+ __early_param("vram=", omapfb_early_vram);
+
+@@ -538,7 +530,7 @@ void __init omapfb_reserve_sdram(void)
+ BUG_ON(paddr & ~PAGE_MASK);
+ }
+
+- omap_vram_add_region_postponed(paddr, size);
++ omap_vram_add_region(paddr, size);
+
+ pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
+ }
+@@ -594,7 +586,7 @@ unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+ reserved = pend_avail - paddr;
+ size_avail = pend_avail - reserved - pstart_avail;
+
+- omap_vram_add_region_postponed(paddr, size);
++ omap_vram_add_region(paddr, size);
+
+ if (reserved)
+ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0034-DSS2-Added-the-function-pointer-for-getting-default.patch b/recipes/linux/linux-omap-pm/dss2/0034-DSS2-Added-the-function-pointer-for-getting-default.patch
new file mode 100644
index 0000000000..5242142ac1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0034-DSS2-Added-the-function-pointer-for-getting-default.patch
@@ -0,0 +1,66 @@
+From 45d3e5f313f3c617100ef0b6a7f10771acfb76a8 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 16 Apr 2009 18:47:49 +0530
+Subject: [PATCH 034/146] DSS2: Added the function pointer for getting default color.
+
+V4L2 Framework has a CID for getting/setting default color.
+So added the function pointer for doing same.
+SYSFS based getting the default color will remain same
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/manager.c | 11 +++++++----
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index b0a6272..073cdda 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -414,6 +414,7 @@ struct omap_overlay_manager {
+ int (*apply)(struct omap_overlay_manager *mgr);
+
+ void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
++ u32 (*get_default_color)(struct omap_overlay_manager *mgr);
+ void (*set_trans_key)(struct omap_overlay_manager *mgr,
+ enum omap_dss_color_key_type type,
+ u32 trans_key);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 8ca0bbb..12cf7b0 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -98,10 +98,8 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const cha
+ static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- u32 default_color;
+-
+- default_color = dispc_get_default_color(mgr->id);
+- return snprintf(buf, PAGE_SIZE, "%d", default_color);
++ return snprintf(buf, PAGE_SIZE, "%d",
++ mgr->get_default_color(mgr));
+ }
+
+ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+@@ -470,6 +468,10 @@ static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
+ {
+ dispc_enable_trans_key(mgr->id, enable);
+ }
++static u32 omap_dss_mgr_get_default_color(struct omap_overlay_manager *mgr)
++{
++ return dispc_get_default_color(mgr->id);
++}
+
+ static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
+ {
+@@ -512,6 +514,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ mgr->set_default_color = &omap_dss_mgr_set_def_color,
+ mgr->set_trans_key = &omap_dss_mgr_set_trans_key,
+ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
++ mgr->get_default_color = &omap_dss_mgr_get_default_color;
+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
+
+ dss_overlay_setup_dispc_manager(mgr);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-support-for-setting-and-querying-alpha-b.patch b/recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-support-for-setting-and-querying-alpha-b.patch
new file mode 100644
index 0000000000..8ec00b8c0c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0035-DSS2-Added-support-for-setting-and-querying-alpha-b.patch
@@ -0,0 +1,118 @@
+From cccb6206195978ab8ff0b08958b44a0d88e8bc94 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 16 Apr 2009 19:00:11 +0530
+Subject: [PATCH 035/146] DSS2: Added support for setting and querying alpha blending.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 3 +++
+ drivers/video/omap2/dss/dispc.c | 26 ++++++++++++++++++++++++++
+ drivers/video/omap2/dss/dss.h | 2 ++
+ drivers/video/omap2/dss/manager.c | 14 ++++++++++++++
+ 4 files changed, 45 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 073cdda..e1f615a 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -415,11 +415,14 @@ struct omap_overlay_manager {
+
+ void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
+ u32 (*get_default_color)(struct omap_overlay_manager *mgr);
++ bool (*get_alpha_blending_status)(struct omap_overlay_manager *mgr);
+ void (*set_trans_key)(struct omap_overlay_manager *mgr,
+ enum omap_dss_color_key_type type,
+ u32 trans_key);
+ void (*enable_trans_key)(struct omap_overlay_manager *mgr,
+ bool enable);
++ void (*enable_alpha_blending)(struct omap_overlay_manager *mgr,
++ bool enable);
+ };
+
+ enum omap_display_caps {
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b631dd8..7e551c2 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1847,6 +1847,32 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
+ enable_clocks(0);
+ }
++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
++{
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
++ else /* OMAP_DSS_CHANNEL_DIGIT */
++ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
++ enable_clocks(0);
++}
++bool dispc_alpha_blending_enabled(enum omap_channel ch)
++{
++ bool enabled;
++
++ enable_clocks(1);
++ if (ch == OMAP_DSS_CHANNEL_LCD)
++ enabled = REG_GET(DISPC_CONFIG, 18, 18);
++ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
++ enabled = REG_GET(DISPC_CONFIG, 18, 18);
++ else
++ BUG();
++ enable_clocks(0);
++
++ return enabled;
++
++}
++
+
+ bool dispc_trans_key_enabled(enum omap_channel ch)
+ {
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 584dce6..1d01ff6 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -294,7 +294,9 @@ void dispc_get_trans_key(enum omap_channel ch,
+ enum omap_dss_color_key_type *type,
+ u32 *trans_key);
+ void dispc_enable_trans_key(enum omap_channel ch, bool enable);
++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
+ bool dispc_trans_key_enabled(enum omap_channel ch);
++bool dispc_alpha_blending_enabled(enum omap_channel ch);
+
+ void dispc_set_lcd_timings(struct omap_video_timings *timings);
+ unsigned long dispc_fclk_rate(void);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 12cf7b0..90acd28 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -468,6 +468,16 @@ static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
+ {
+ dispc_enable_trans_key(mgr->id, enable);
+ }
++static void omap_dss_mgr_enable_alpha_blending(struct omap_overlay_manager *mgr,
++ bool enable)
++{
++ dispc_enable_alpha_blending(mgr->id, enable);
++}
++static bool omap_dss_mgr_get_alpha_blending_status(
++ struct omap_overlay_manager *mgr)
++{
++ return dispc_alpha_blending_enabled(mgr->id);
++}
+ static u32 omap_dss_mgr_get_default_color(struct omap_overlay_manager *mgr)
+ {
+ return dispc_get_default_color(mgr->id);
+@@ -514,6 +524,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ mgr->set_default_color = &omap_dss_mgr_set_def_color,
+ mgr->set_trans_key = &omap_dss_mgr_set_trans_key,
+ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
++ mgr->enable_alpha_blending =
++ &omap_dss_mgr_enable_alpha_blending;
++ mgr->get_alpha_blending_status =
++ omap_dss_mgr_get_alpha_blending_status;
+ mgr->get_default_color = &omap_dss_mgr_get_default_color;
+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-querying-color-keying.patch b/recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-querying-color-keying.patch
new file mode 100644
index 0000000000..1afe7b42f9
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0036-DSS2-Added-support-for-querying-color-keying.patch
@@ -0,0 +1,150 @@
+From c6f6a968cb089237a092d4c1a294dbe79671bb3c Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 17 Apr 2009 09:42:36 +0530
+Subject: [PATCH 036/146] DSS2: Added support for querying color keying.
+
+V4L2 Framework has a ioctl for getting/setting color keying.
+So added the function manager pointers for doing same.
+
+Modifed the color keying sysfs entries to use manager
+function pointer. Earlier they were calling direcly
+dispc function to set/enable color keying.
+
+Some of color-keying function pointers in the overlay_manager
+structure re-named to be more specific.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 6 ++++-
+ drivers/video/omap2/dss/manager.c | 36 +++++++++++++++++++++--------
+ 2 files changed, 31 insertions(+), 11 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index e1f615a..d0b4c83 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -416,7 +416,11 @@ struct omap_overlay_manager {
+ void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
+ u32 (*get_default_color)(struct omap_overlay_manager *mgr);
+ bool (*get_alpha_blending_status)(struct omap_overlay_manager *mgr);
+- void (*set_trans_key)(struct omap_overlay_manager *mgr,
++ bool (*get_trans_key_status)(struct omap_overlay_manager *mgr);
++ void (*get_trans_key_type_and_value)(struct omap_overlay_manager *mgr,
++ enum omap_dss_color_key_type *type,
++ u32 *trans_key);
++ void (*set_trans_key_type_and_value)(struct omap_overlay_manager *mgr,
+ enum omap_dss_color_key_type type,
+ u32 trans_key);
+ void (*enable_trans_key)(struct omap_overlay_manager *mgr,
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 90acd28..e0501c4 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -124,7 +124,7 @@ static ssize_t manager_color_key_type_show(struct omap_overlay_manager *mgr,
+ {
+ enum omap_dss_color_key_type key_type;
+
+- dispc_get_trans_key(mgr->id, &key_type, NULL);
++ mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
+ BUG_ON(key_type >= ARRAY_SIZE(color_key_type_str));
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", color_key_type_str[key_type]);
+@@ -143,8 +143,8 @@ static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
+ }
+ if (key_type == ARRAY_SIZE(color_key_type_str))
+ return -EINVAL;
+- dispc_get_trans_key(mgr->id, NULL, &key_value);
+- dispc_set_trans_key(mgr->id, key_type, key_value);
++ mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
++ mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
+
+ return size;
+ }
+@@ -154,7 +154,7 @@ static ssize_t manager_color_key_value_show(struct omap_overlay_manager *mgr,
+ {
+ u32 key_value;
+
+- dispc_get_trans_key(mgr->id, NULL, &key_value);
++ mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", key_value);
+ }
+@@ -167,8 +167,8 @@ static ssize_t manager_color_key_value_store(struct omap_overlay_manager *mgr,
+
+ if (sscanf(buf, "%d", &key_value) != 1)
+ return -EINVAL;
+- dispc_get_trans_key(mgr->id, &key_type, NULL);
+- dispc_set_trans_key(mgr->id, key_type, key_value);
++ mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
++ mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
+
+ return size;
+ }
+@@ -177,7 +177,7 @@ static ssize_t manager_color_key_enabled_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- dispc_trans_key_enabled(mgr->id));
++ mgr->get_trans_key_status(mgr));
+ }
+
+ static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
+@@ -188,7 +188,7 @@ static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
+- dispc_enable_trans_key(mgr->id, enable);
++ mgr->enable_trans_key(mgr, enable);
+
+ return size;
+ }
+@@ -456,12 +456,20 @@ static void omap_dss_mgr_set_def_color(struct omap_overlay_manager *mgr,
+ dispc_set_default_color(mgr->id, color);
+ }
+
+-static void omap_dss_mgr_set_trans_key(struct omap_overlay_manager *mgr,
++static void omap_dss_mgr_set_trans_key_type_and_value(
++ struct omap_overlay_manager *mgr,
+ enum omap_dss_color_key_type type,
+ u32 trans_key)
+ {
+ dispc_set_trans_key(mgr->id, type, trans_key);
+ }
++static void omap_dss_mgr_get_trans_key_type_and_value(
++ struct omap_overlay_manager *mgr,
++ enum omap_dss_color_key_type *type,
++ u32 *trans_key)
++{
++ dispc_get_trans_key(mgr->id, type, trans_key);
++}
+
+ static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
+ bool enable)
+@@ -482,6 +490,10 @@ static u32 omap_dss_mgr_get_default_color(struct omap_overlay_manager *mgr)
+ {
+ return dispc_get_default_color(mgr->id);
+ }
++static bool omap_dss_mgr_get_trans_key_status(struct omap_overlay_manager *mgr)
++{
++ return dispc_trans_key_enabled(mgr->id);
++}
+
+ static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
+ {
+@@ -522,8 +534,12 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ mgr->unset_display = &omap_dss_unset_display,
+ mgr->apply = &omap_dss_mgr_apply,
+ mgr->set_default_color = &omap_dss_mgr_set_def_color,
+- mgr->set_trans_key = &omap_dss_mgr_set_trans_key,
++ mgr->set_trans_key_type_and_value =
++ &omap_dss_mgr_set_trans_key_type_and_value,
++ mgr->get_trans_key_type_and_value =
++ &omap_dss_mgr_get_trans_key_type_and_value,
+ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
++ mgr->get_trans_key_status = &omap_dss_mgr_get_trans_key_status,
+ mgr->enable_alpha_blending =
+ &omap_dss_mgr_enable_alpha_blending;
+ mgr->get_alpha_blending_status =
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0037-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch b/recipes/linux/linux-omap-pm/dss2/0037-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch
new file mode 100644
index 0000000000..85b21b4e26
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0037-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch
@@ -0,0 +1,56 @@
+From a68284a6285a035a9572b6e0c5178751826db75f Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 17 Apr 2009 09:51:25 +0530
+Subject: [PATCH 037/146] DSS2:OMAPFB: Some color keying pointerd renamed in DSS2. Replicated in FB
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 11 +++++++----
+ 1 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 7f18d2a..79d8916 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -288,7 +288,8 @@ static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ {
+ enum omap_dss_color_key_type kt;
+
+- if(!mgr->set_default_color || !mgr->set_trans_key ||
++ if (!mgr->set_default_color ||
++ !mgr->set_trans_key_type_and_value ||
+ !mgr->enable_trans_key)
+ return 0;
+
+@@ -310,7 +311,7 @@ static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ }
+
+ mgr->set_default_color(mgr, ck->background);
+- mgr->set_trans_key(mgr, kt, ck->trans_key);
++ mgr->set_trans_key_type_and_value(mgr, kt, ck->trans_key);
+ mgr->enable_trans_key(mgr, 1);
+
+ omapfb_color_keys[mgr->id] = *ck;
+@@ -341,7 +342,8 @@ static int omapfb_set_color_key(struct fb_info *fbi,
+ goto err;
+ }
+
+- if(!mgr->set_default_color || !mgr->set_trans_key ||
++ if (!mgr->set_default_color ||
++ !mgr->set_trans_key_type_and_value ||
+ !mgr->enable_trans_key) {
+ r = -ENODEV;
+ goto err;
+@@ -377,7 +379,8 @@ static int omapfb_get_color_key(struct fb_info *fbi,
+ goto err;
+ }
+
+- if(!mgr->set_default_color || !mgr->set_trans_key ||
++ if (!mgr->set_default_color ||
++ !mgr->set_trans_key_type_and_value ||
+ !mgr->enable_trans_key) {
+ r = -ENODEV;
+ goto err;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0038-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch b/recipes/linux/linux-omap-pm/dss2/0038-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch
new file mode 100644
index 0000000000..fa5c658ae1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0038-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch
@@ -0,0 +1,59 @@
+From b10751409130b1260992ab2b96d4d50f9f375f7f Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 17 Apr 2009 13:58:21 +0530
+Subject: [PATCH 038/146] DSS2: Add sysfs entry to for the alpha blending support.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/dss/manager.c | 21 +++++++++++++++++++++
+ 1 files changed, 21 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index e0501c4..7965a84 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -192,6 +192,22 @@ static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
+
+ return size;
+ }
++static ssize_t manager_alpha_blending_enabled_show(
++ struct omap_overlay_manager *mgr, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ mgr->get_alpha_blending_status(mgr));
++}
++static ssize_t manager_alpha_blending_enabled_store(
++ struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
++{
++ int enable;
++ if (sscanf(buf, "%d", &enable) != 1)
++ return -EINVAL;
++ mgr->enable_alpha_blending(mgr, enable);
++ return size;
++}
+
+
+ struct manager_attribute {
+@@ -215,6 +231,10 @@ static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
+ manager_color_key_value_show, manager_color_key_value_store);
+ static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
+ manager_color_key_enabled_show, manager_color_key_enabled_store);
++static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
++ manager_alpha_blending_enabled_show,
++ manager_alpha_blending_enabled_store);
++
+
+ static struct attribute *manager_sysfs_attrs[] = {
+ &manager_attr_name.attr,
+@@ -223,6 +243,7 @@ static struct attribute *manager_sysfs_attrs[] = {
+ &manager_attr_color_key_type.attr,
+ &manager_attr_color_key_value.attr,
+ &manager_attr_color_key_enabled.attr,
++ &manager_attr_alpha_blending_enabled.attr,
+ NULL
+ };
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0039-DSS2-Provided-proper-exclusion-for-destination-colo.patch b/recipes/linux/linux-omap-pm/dss2/0039-DSS2-Provided-proper-exclusion-for-destination-colo.patch
new file mode 100644
index 0000000000..7193209c42
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0039-DSS2-Provided-proper-exclusion-for-destination-colo.patch
@@ -0,0 +1,97 @@
+From 3a26967466a00e8a0727ecf6b9b4a42b949867de Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 17 Apr 2009 14:24:46 +0530
+Subject: [PATCH 039/146] DSS2: Provided proper exclusion for destination color keying and alpha blending.
+
+OMAP does not support destination color key and alpha blending
+simultaneously. So this patch does not allow the user
+so set both at a time.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/dss/manager.c | 50 ++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 49 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 7965a84..108489c 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -137,12 +137,26 @@ static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
+ u32 key_value;
+
+ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+- key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
++ key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
+ if (sysfs_streq(buf, color_key_type_str[key_type]))
+ break;
+ }
+ if (key_type == ARRAY_SIZE(color_key_type_str))
+ return -EINVAL;
++ /* OMAP does not support destination color key and alpha blending
++ * simultaneously. So if alpha blending and color keying both are
++ * enabled then refrain from setting the color key type to
++ * gfx-destination
++ */
++ if (!key_type) {
++ bool color_key_enabled;
++ bool alpha_blending_enabled;
++ color_key_enabled = mgr->get_trans_key_status(mgr);
++ alpha_blending_enabled = mgr->get_alpha_blending_status(mgr);
++ if (color_key_enabled && alpha_blending_enabled)
++ return -EINVAL;
++ }
++
+ mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
+ mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
+
+@@ -188,6 +202,23 @@ static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
++ /* OMAP does not support destination color keying and
++ * alpha blending simultaneously. so if alpha blending
++ * is enabled refrain from enabling destination color
++ * keying.
++ */
++ if (enable) {
++ bool enabled;
++ enabled = mgr->get_alpha_blending_status(mgr);
++ if (enabled) {
++ enum omap_dss_color_key_type key_type;
++ mgr->get_trans_key_type_and_value(mgr,
++ &key_type, NULL);
++ if (!key_type)
++ return -EINVAL;
++ }
++
++ }
+ mgr->enable_trans_key(mgr, enable);
+
+ return size;
+@@ -205,6 +236,23 @@ static ssize_t manager_alpha_blending_enabled_store(
+ int enable;
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
++ /* OMAP does not support destination color keying and
++ * alpha blending simultaneously. so if destination
++ * color keying is enabled refrain from enabling
++ * alpha blending
++ */
++ if (enable) {
++ bool enabled;
++ enabled = mgr->get_trans_key_status(mgr);
++ if (enabled) {
++ enum omap_dss_color_key_type key_type;
++ mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
++ if (!key_type)
++ return -EINVAL;
++
++ }
++
++ }
+ mgr->enable_alpha_blending(mgr, enable);
+ return size;
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0040-DSS2-Disable-vertical-offset-with-fieldmode.patch b/recipes/linux/linux-omap-pm/dss2/0040-DSS2-Disable-vertical-offset-with-fieldmode.patch
new file mode 100644
index 0000000000..e153c9c5a4
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0040-DSS2-Disable-vertical-offset-with-fieldmode.patch
@@ -0,0 +1,71 @@
+From a2649a29d782112aa5e853f71992314f631762e2 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 20 Apr 2009 16:26:18 +0200
+Subject: [PATCH 040/146] DSS2: Disable vertical offset with fieldmode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When using fieldmode each field is basically a separate picture so the
+vertical filter should start at phase 0 for both fields.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 23 +++++++++--------------
+ 1 files changed, 9 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 7e551c2..f15614b 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1029,12 +1029,12 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+ static void _dispc_set_scaling(enum omap_plane plane,
+ u16 orig_width, u16 orig_height,
+ u16 out_width, u16 out_height,
+- bool ilace, bool five_taps)
++ bool ilace, bool five_taps,
++ bool fieldmode)
+ {
+ int fir_hinc;
+ int fir_vinc;
+ int hscaleup, vscaleup;
+- int fieldmode = 0;
+ int accu0 = 0;
+ int accu1 = 0;
+ u32 l;
+@@ -1072,17 +1072,12 @@ static void _dispc_set_scaling(enum omap_plane plane,
+
+ dispc_write_reg(dispc_reg_att[plane], l);
+
+- if (ilace) {
+- if (fieldmode) {
+- accu0 = fir_vinc / 2;
+- accu1 = 0;
+- } else {
+- accu0 = 0;
+- accu1 = fir_vinc / 2;
+- if (accu1 >= 1024/2) {
+- accu0 = 1024/2;
+- accu1 -= accu0;
+- }
++ if (ilace && !fieldmode) {
++ accu0 = 0;
++ accu1 = fir_vinc / 2;
++ if (accu1 >= 1024/2) {
++ accu0 = 1024/2;
++ accu1 -= accu0;
+ }
+ }
+
+@@ -1582,7 +1577,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ if (plane != OMAP_DSS_GFX) {
+ _dispc_set_scaling(plane, width, height,
+ out_width, out_height,
+- ilace, five_taps);
++ ilace, five_taps, fieldmode);
+ _dispc_set_vid_size(plane, out_width, out_height);
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0041-DSS2-Don-t-enable-fieldmode-automatically.patch b/recipes/linux/linux-omap-pm/dss2/0041-DSS2-Don-t-enable-fieldmode-automatically.patch
new file mode 100644
index 0000000000..fe0e27ec4a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0041-DSS2-Don-t-enable-fieldmode-automatically.patch
@@ -0,0 +1,34 @@
+From 9e4341c229dd7e78a5612b8b9259f1dcf19a7f84 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 20 Apr 2009 16:26:19 +0200
+Subject: [PATCH 041/146] DSS2: Don't enable fieldmode automatically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The only case where enabling fieldmode automatically seems reasonable
+is when source and destination heights are equal. Some kind of user
+controllable knob should be added so the user could enable field mode
+when the source is interlaced.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index f15614b..1c036c1 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1450,7 +1450,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ if (paddr == 0)
+ return -EINVAL;
+
+- if (ilace && height >= out_height)
++ if (ilace && height == out_height)
+ fieldmode = 1;
+
+ if (ilace) {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0042-DSS2-Swap-field-0-and-field-1-registers.patch b/recipes/linux/linux-omap-pm/dss2/0042-DSS2-Swap-field-0-and-field-1-registers.patch
new file mode 100644
index 0000000000..d56a39a5a6
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0042-DSS2-Swap-field-0-and-field-1-registers.patch
@@ -0,0 +1,170 @@
+From 8f69b9dbb2783e69c2a30c73fe2b2b1dc5b1dd52 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 20 Apr 2009 16:26:20 +0200
+Subject: [PATCH 042/146] DSS2: Swap field 0 and field 1 registers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The values for the registers which have alternate values for each field
+were reveresed to what the hardware expects. For the hardware field 0
+is the even field or the bottom field, field 1 is the odd field or the
+top field. So simply swap the register values.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 66 ++++++++++++++++++++++-----------------
+ 1 files changed, 37 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 1c036c1..9bab6cf 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1072,12 +1072,16 @@ static void _dispc_set_scaling(enum omap_plane plane,
+
+ dispc_write_reg(dispc_reg_att[plane], l);
+
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
+ if (ilace && !fieldmode) {
+- accu0 = 0;
+- accu1 = fir_vinc / 2;
+- if (accu1 >= 1024/2) {
+- accu0 = 1024/2;
+- accu1 -= accu0;
++ accu1 = 0;
++ accu0 = fir_vinc / 2;
++ if (accu0 >= 1024/2) {
++ accu1 = 1024/2;
++ accu0 -= accu1;
+ }
+ }
+
+@@ -1266,34 +1270,38 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ fbh = width;
+ }
+
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
+ switch (rotation + mirror * 4) {
+ case 0:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = screen_width * ps;
++ *offset0 = screen_width * ps;
+ else
+- *offset1 = 0;
++ *offset0 = 0;
+ *row_inc = pixinc(1 + (screen_width - fbw) +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+ case 1:
+- *offset0 = screen_width * (fbh - 1) * ps;
++ *offset1 = screen_width * (fbh - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 + ps;
++ *offset0 = *offset1 + ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(-screen_width, ps);
+ break;
+ case 2:
+- *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 - screen_width * ps;
++ *offset0 = *offset1 - screen_width * ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(-1 -
+ (screen_width - fbw) -
+ (fieldmode ? screen_width : 0),
+@@ -1301,11 +1309,11 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ *pix_inc = pixinc(-1, ps);
+ break;
+ case 3:
+- *offset0 = (fbw - 1) * ps;
++ *offset1 = (fbw - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 - ps;
++ *offset0 = *offset1 - ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(screen_width, ps);
+@@ -1313,11 +1321,11 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+
+ /* mirroring */
+ case 0 + 4:
+- *offset0 = (fbw - 1) * ps;
++ *offset1 = (fbw - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 + screen_width * ps;
++ *offset0 = *offset1 + screen_width * ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * 2 - 1 +
+ (fieldmode ? screen_width : 0),
+ ps);
+@@ -1325,11 +1333,11 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+
+ case 1 + 4:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = *offset0 + screen_width * ps;
++ *offset0 = *offset1 + screen_width * ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0),
+ ps);
+@@ -1337,11 +1345,11 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+
+ case 2 + 4:
+- *offset0 = screen_width * (fbh - 1) * ps;
++ *offset1 = screen_width * (fbh - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 + screen_width * ps;
++ *offset0 = *offset1 + screen_width * ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(1 - screen_width * 2 -
+ (fieldmode ? screen_width : 0),
+ ps);
+@@ -1349,11 +1357,11 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+
+ case 3 + 4:
+- *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (fieldmode)
+- *offset1 = *offset0 + screen_width * ps;
++ *offset0 = *offset1 + screen_width * ps;
+ else
+- *offset1 = *offset0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0),
+ ps);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0043-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch b/recipes/linux/linux-omap-pm/dss2/0043-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch
new file mode 100644
index 0000000000..1dd9176001
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0043-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch
@@ -0,0 +1,76 @@
+From 99cf62779ad75224b9b8ea6490733ac5557d1763 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Mon, 20 Apr 2009 14:55:33 +0200
+Subject: [PATCH 043/146] DSS2: add sysfs entry for seting the rotate type
+
+This can help in utilizing VRAM memory better. Since with VRFB rotation
+we waste a lot of physical memory due to the VRFB HW design, provide the
+possibility to turn it off and free the extra memory for the use by other
+planes for example.
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 42 ++++++++++++++++++++++++++++-
+ 1 files changed, 41 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 2c88718..4e3da42 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -43,6 +43,46 @@ static ssize_t show_rotate_type(struct device *dev,
+ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
+ }
+
++static ssize_t store_rotate_type(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ enum omap_dss_rotation_type rot_type;
++ int r;
++
++ rot_type = simple_strtoul(buf, NULL, 0);
++
++ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
++ return -EINVAL;
++
++ omapfb_lock(fbdev);
++
++ r = 0;
++ if (rot_type == ofbi->rotation_type)
++ goto out;
++
++ r = -EBUSY;
++ if (ofbi->region.size)
++ goto out;
++
++ ofbi->rotation_type = rot_type;
++
++ /*
++ * Since the VRAM for this FB is not allocated at the moment we don't need to
++ * do any further parameter checking at this point.
++ */
++
++ r = count;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
++
+ static ssize_t show_mirror(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -327,7 +367,7 @@ static ssize_t show_virt(struct device *dev,
+ }
+
+ static struct device_attribute omapfb_attrs[] = {
+- __ATTR(rotate_type, S_IRUGO, show_rotate_type, NULL),
++ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, store_rotate_type),
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0044-DSS2-Fixed-line-endings-from-to.patch b/recipes/linux/linux-omap-pm/dss2/0044-DSS2-Fixed-line-endings-from-to.patch
new file mode 100644
index 0000000000..39baba371f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0044-DSS2-Fixed-line-endings-from-to.patch
@@ -0,0 +1,48 @@
+From d4e33a71922c6e2c13a70428a5d3118fb827fce7 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 21 Apr 2009 09:25:16 +0300
+Subject: [PATCH 044/146] DSS2: Fixed line endings from , to ;
+
+---
+ drivers/video/omap2/dss/manager.c | 18 +++++++++---------
+ 1 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 108489c..bf059e0 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -599,22 +599,22 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ break;
+ }
+
+- mgr->set_display = &omap_dss_set_display,
+- mgr->unset_display = &omap_dss_unset_display,
+- mgr->apply = &omap_dss_mgr_apply,
+- mgr->set_default_color = &omap_dss_mgr_set_def_color,
++ mgr->set_display = &omap_dss_set_display;
++ mgr->unset_display = &omap_dss_unset_display;
++ mgr->apply = &omap_dss_mgr_apply;
++ mgr->set_default_color = &omap_dss_mgr_set_def_color;
+ mgr->set_trans_key_type_and_value =
+- &omap_dss_mgr_set_trans_key_type_and_value,
++ &omap_dss_mgr_set_trans_key_type_and_value;
+ mgr->get_trans_key_type_and_value =
+- &omap_dss_mgr_get_trans_key_type_and_value,
+- mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
+- mgr->get_trans_key_status = &omap_dss_mgr_get_trans_key_status,
++ &omap_dss_mgr_get_trans_key_type_and_value;
++ mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key;
++ mgr->get_trans_key_status = &omap_dss_mgr_get_trans_key_status;
+ mgr->enable_alpha_blending =
+ &omap_dss_mgr_enable_alpha_blending;
+ mgr->get_alpha_blending_status =
+ omap_dss_mgr_get_alpha_blending_status;
+ mgr->get_default_color = &omap_dss_mgr_get_default_color;
+- mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
++ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+
+ dss_overlay_setup_dispc_manager(mgr);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0045-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch b/recipes/linux/linux-omap-pm/dss2/0045-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch
new file mode 100644
index 0000000000..298095d214
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0045-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch
@@ -0,0 +1,26 @@
+From 23ee17c38e6762ff59dda729ffae8d9bf483f9c5 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 21 Apr 2009 10:11:55 +0300
+Subject: [PATCH 045/146] DSS2: DSI: decrease sync timeout from 60s to 2s
+
+The framedone-problem should be ok now, so we shouldn't get long waits.
+---
+ drivers/video/omap2/dss/dsi.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 50af925..d59ad38 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -3216,7 +3216,7 @@ static void dsi_push_set_mirror(struct omap_display *display, int mirror)
+
+ static int dsi_wait_sync(struct omap_display *display)
+ {
+- long wait = msecs_to_jiffies(60000);
++ long wait = msecs_to_jiffies(2000);
+ struct completion compl;
+
+ DSSDBGF("");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0046-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch b/recipes/linux/linux-omap-pm/dss2/0046-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch
new file mode 100644
index 0000000000..50b4fea0f0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0046-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch
@@ -0,0 +1,44 @@
+From 18c8d0ed7236cca6a52a701001337131d7e066e7 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 21 Apr 2009 15:18:36 +0200
+Subject: [PATCH 046/146] DSS2: fix return value for rotate_type sysfs function
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 9 ++++-----
+ 1 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 4e3da42..13028ae 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -64,9 +64,10 @@ static ssize_t store_rotate_type(struct device *dev,
+ if (rot_type == ofbi->rotation_type)
+ goto out;
+
+- r = -EBUSY;
+- if (ofbi->region.size)
++ if (ofbi->region.size) {
++ r = -EBUSY;
+ goto out;
++ }
+
+ ofbi->rotation_type = rot_type;
+
+@@ -74,12 +75,10 @@ static ssize_t store_rotate_type(struct device *dev,
+ * Since the VRAM for this FB is not allocated at the moment we don't need to
+ * do any further parameter checking at this point.
+ */
+-
+- r = count;
+ out:
+ omapfb_unlock(fbdev);
+
+- return r;
++ return r ? r : count;
+ }
+
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0047-DSS2-VRAM-clear-allocated-area-with-DMA.patch b/recipes/linux/linux-omap-pm/dss2/0047-DSS2-VRAM-clear-allocated-area-with-DMA.patch
new file mode 100644
index 0000000000..40748784c8
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0047-DSS2-VRAM-clear-allocated-area-with-DMA.patch
@@ -0,0 +1,101 @@
+From 1850c0c28d013be68d398cac330a0dcfbb7a1ed6 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 22 Apr 2009 10:25:20 +0300
+Subject: [PATCH 047/146] DSS2: VRAM: clear allocated area with DMA
+
+Use DMA constant fill feature to clear VRAM area when
+someone allocates it.
+---
+ arch/arm/plat-omap/vram.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 57 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 8e9fe77..90276ac 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -31,11 +31,13 @@
+ #include <linux/seq_file.h>
+ #include <linux/bootmem.h>
+ #include <linux/omapfb.h>
++#include <linux/completion.h>
+
+ #include <asm/setup.h>
+
+ #include <mach/sram.h>
+ #include <mach/vram.h>
++#include <mach/dma.h>
+
+ #ifdef DEBUG
+ #define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
+@@ -276,6 +278,59 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
+ }
+ EXPORT_SYMBOL(omap_vram_reserve);
+
++static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
++{
++ struct completion *compl = data;
++ complete(compl);
++}
++
++static int _omap_vram_clear(u32 paddr, unsigned pages)
++{
++ struct completion compl;
++ unsigned elem_count;
++ unsigned frame_count;
++ int r;
++ int lch;
++
++ init_completion(&compl);
++
++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
++ _omap_vram_dma_cb,
++ &compl, &lch);
++ if (r) {
++ pr_err("VRAM: request_dma failed for memory clear\n");
++ return -EBUSY;
++ }
++
++ elem_count = pages * PAGE_SIZE / 4;
++ frame_count = 1;
++
++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
++ elem_count, frame_count,
++ OMAP_DMA_SYNC_ELEMENT,
++ 0, 0);
++
++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
++ paddr, 0, 0);
++
++ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
++
++ omap_start_dma(lch);
++
++ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
++ omap_stop_dma(lch);
++ pr_err("VRAM: dma timeout while clearing memory\n");
++ r = -EIO;
++ goto err;
++ }
++
++ r = 0;
++err:
++ omap_free_dma(lch);
++
++ return r;
++}
++
+ static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
+ {
+ struct vram_region *rm;
+@@ -313,6 +368,8 @@ found:
+
+ *paddr = start;
+
++ _omap_vram_clear(start, pages);
++
+ return 0;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0048-DSS2-OMAPFB-remove-fb-clearing-code.patch b/recipes/linux/linux-omap-pm/dss2/0048-DSS2-OMAPFB-remove-fb-clearing-code.patch
new file mode 100644
index 0000000000..9348a075a3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0048-DSS2-OMAPFB-remove-fb-clearing-code.patch
@@ -0,0 +1,53 @@
+From ca06a6b885058df4fc7f2033e2ea569789dc0883 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 22 Apr 2009 10:26:06 +0300
+Subject: [PATCH 048/146] DSS2: OMAPFB: remove fb clearing code
+
+VRAM manager does the clearing now when the area is allocated.
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 8 --------
+ 1 files changed, 0 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index cd63740..76e7c6c 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1174,7 +1174,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ struct omapfb2_mem_region *rg;
+ void __iomem *vaddr;
+ int r;
+- int clear = 0;
+
+ rg = &ofbi->region;
+ memset(rg, 0, sizeof(*rg));
+@@ -1184,7 +1183,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ if (!paddr) {
+ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+ r = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
+- clear = 1;
+ } else {
+ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
+ ofbi->id);
+@@ -1206,9 +1204,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ }
+
+ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
+-
+- if (clear)
+- memset_io(vaddr, 0, size);
+ } else {
+ void __iomem *va;
+
+@@ -1232,9 +1227,6 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ rg->vrfb.vaddr[0] = va;
+
+ vaddr = NULL;
+-
+- if (clear)
+- memset_io(va, 0, size);
+ }
+
+ rg->paddr = paddr;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-use-debugfs-not-procfs.patch b/recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-use-debugfs-not-procfs.patch
new file mode 100644
index 0000000000..6bf78ce442
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0049-DSS2-VRAM-use-debugfs-not-procfs.patch
@@ -0,0 +1,170 @@
+From e9199bfc627213a53ff149dc5334d3881c749cfa Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 22 Apr 2009 14:11:52 +0300
+Subject: [PATCH 049/146] DSS2: VRAM: use debugfs, not procfs
+
+---
+ arch/arm/plat-omap/vram.c | 103 +++++++++++++++------------------------------
+ 1 files changed, 34 insertions(+), 69 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 90276ac..e847579 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -27,11 +27,11 @@
+ #include <linux/mm.h>
+ #include <linux/list.h>
+ #include <linux/dma-mapping.h>
+-#include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/bootmem.h>
+ #include <linux/omapfb.h>
+ #include <linux/completion.h>
++#include <linux/debugfs.h>
+
+ #include <asm/setup.h>
+
+@@ -398,88 +398,54 @@ int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
+ }
+ EXPORT_SYMBOL(omap_vram_alloc);
+
+-#ifdef CONFIG_PROC_FS
+-static void *r_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+- struct list_head *l = v;
+-
+- (*pos)++;
+-
+- if (list_is_last(l, &region_list))
+- return NULL;
+-
+- return l->next;
+-}
+-
+-static void *r_start(struct seq_file *m, loff_t *pos)
+-{
+- loff_t p = *pos;
+- struct list_head *l = &region_list;
+-
+- mutex_lock(&region_mutex);
+-
+- do {
+- l = l->next;
+- if (l == &region_list)
+- return NULL;
+- } while (p--);
+-
+- return l;
+-}
+-
+-static void r_stop(struct seq_file *m, void *v)
+-{
+- mutex_unlock(&region_mutex);
+-}
+-
+-static int r_show(struct seq_file *m, void *v)
++#if defined(CONFIG_DEBUG_FS)
++static int vram_debug_show(struct seq_file *s, void *unused)
+ {
+ struct vram_region *vr;
+ struct vram_alloc *va;
+ unsigned size;
+
+- vr = list_entry(v, struct vram_region, list);
+-
+- size = vr->pages << PAGE_SHIFT;
+-
+- seq_printf(m, "%08lx-%08lx (%d bytes)\n",
+- vr->paddr, vr->paddr + size - 1,
+- size);
++ mutex_lock(&region_mutex);
+
+- list_for_each_entry(va, &vr->alloc_list, list) {
+- size = va->pages << PAGE_SHIFT;
+- seq_printf(m, " %08lx-%08lx (%d bytes)\n",
+- va->paddr, va->paddr + size - 1,
++ list_for_each_entry(vr, &region_list, list) {
++ size = vr->pages << PAGE_SHIFT;
++ seq_printf(s, "%08lx-%08lx (%d bytes)\n",
++ vr->paddr, vr->paddr + size - 1,
+ size);
+- }
+
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ size = va->pages << PAGE_SHIFT;
++ seq_printf(s, " %08lx-%08lx (%d bytes)\n",
++ va->paddr, va->paddr + size - 1,
++ size);
++ }
++ }
+
++ mutex_unlock(&region_mutex);
+
+ return 0;
+ }
+
+-static const struct seq_operations resource_op = {
+- .start = r_start,
+- .next = r_next,
+- .stop = r_stop,
+- .show = r_show,
+-};
+-
+-static int vram_open(struct inode *inode, struct file *file)
++static int vram_debug_open(struct inode *inode, struct file *file)
+ {
+- return seq_open(file, &resource_op);
++ return single_open(file, vram_debug_show, inode->i_private);
+ }
+
+-static const struct file_operations proc_vram_operations = {
+- .open = vram_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = seq_release,
++static const struct file_operations vram_debug_fops = {
++ .open = vram_debug_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
+ };
+
+-static int __init omap_vram_create_proc(void)
++static int __init omap_vram_create_debugfs(void)
+ {
+- proc_create("omap-vram", 0, NULL, &proc_vram_operations);
++ struct dentry *d;
++
++ d = debugfs_create_file("vram", S_IRUGO, NULL,
++ NULL, &vram_debug_fops);
++ if (IS_ERR(d))
++ return PTR_ERR(d);
+
+ return 0;
+ }
+@@ -487,7 +453,7 @@ static int __init omap_vram_create_proc(void)
+
+ static __init int omap_vram_init(void)
+ {
+- int i, r;
++ int i;
+
+ vram_initialized = 1;
+
+@@ -495,10 +461,9 @@ static __init int omap_vram_init(void)
+ omap_vram_add_region(postponed_regions[i].paddr,
+ postponed_regions[i].size);
+
+-#ifdef CONFIG_PROC_FS
+- r = omap_vram_create_proc();
+- if (r)
+- return -ENOMEM;
++#ifdef CONFIG_DEBUG_FS
++ if (omap_vram_create_debugfs())
++ pr_err("VRAM: Failed to create debugfs file\n");
+ #endif
+
+ return 0;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0050-DSS2-VRAM-fix-section-mismatch-warning.patch b/recipes/linux/linux-omap-pm/dss2/0050-DSS2-VRAM-fix-section-mismatch-warning.patch
new file mode 100644
index 0000000000..43f5c8b811
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0050-DSS2-VRAM-fix-section-mismatch-warning.patch
@@ -0,0 +1,34 @@
+From 174cc52b0c4dd551ff80ba25568ed9a9d678ea79 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Wed, 22 Apr 2009 14:40:48 +0200
+Subject: [PATCH 050/146] DSS2: VRAM: fix section mismatch warning
+
+postponed_regions are accessed from the non __init
+omap_vram_add_region().
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vram.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index e847579..b126a64 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -63,11 +63,11 @@
+ #define MAX_POSTPONED_REGIONS 10
+
+ static bool vram_initialized;
+-static int postponed_cnt __initdata;
++static int postponed_cnt;
+ static struct {
+ unsigned long paddr;
+ size_t size;
+-} postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
++} postponed_regions[MAX_POSTPONED_REGIONS];
+
+ struct vram_alloc {
+ struct list_head list;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0051-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch b/recipes/linux/linux-omap-pm/dss2/0051-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch
new file mode 100644
index 0000000000..61dfbc1740
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0051-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch
@@ -0,0 +1,41 @@
+From 96cedf8bb26d2a50da506051da87ee24d8e3d7fc Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 23 Apr 2009 10:46:53 +0300
+Subject: [PATCH 051/146] DSS2: disable LCD & DIGIT before resetting DSS
+
+This seems to fix the synclost problem that we get, if the bootloader
+starts the DSS and the kernel resets it.
+---
+ drivers/video/omap2/dss/dss.c | 8 +++++---
+ 1 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
+index adc1f34..aab9758 100644
+--- a/drivers/video/omap2/dss/dss.c
++++ b/drivers/video/omap2/dss/dss.c
+@@ -285,6 +285,11 @@ int dss_init(bool skip_init)
+ }
+
+ if (!skip_init) {
++ /* disable LCD and DIGIT output. This seems to fix the synclost
++ * problem that we get, if the bootloader starts the DSS and
++ * the kernel resets it */
++ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
++
+ /* We need to wait here a bit, otherwise we sometimes start to
+ * get synclost errors, and after that only power cycle will
+ * restore DSS functionality. I have no idea why this happens.
+@@ -294,10 +299,7 @@ int dss_init(bool skip_init)
+ msleep(50);
+
+ _omap_dss_reset();
+-
+ }
+- else
+- printk("DSS SKIP RESET\n");
+
+ /* autoidle */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0052-DSS2-DSI-more-error-handling.patch b/recipes/linux/linux-omap-pm/dss2/0052-DSS2-DSI-more-error-handling.patch
new file mode 100644
index 0000000000..1b0035317a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0052-DSS2-DSI-more-error-handling.patch
@@ -0,0 +1,85 @@
+From bbf1f63b3b6fa18a33b70ad85729dad6bd280c16 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 27 Apr 2009 11:06:16 +0300
+Subject: [PATCH 052/146] DSS2: DSI: more error handling
+
+---
+ drivers/video/omap2/dss/dsi.c | 27 +++++++++++++++++++++++++++
+ 1 files changed, 27 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index d59ad38..d8df353 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -289,6 +289,8 @@ static struct
+
+ bool autoupdate_setup;
+
++ u32 errors;
++ spinlock_t errors_lock;
+ #ifdef DEBUG
+ ktime_t perf_setup_time;
+ ktime_t perf_start_time;
+@@ -541,6 +543,9 @@ void dsi_irq_handler(void)
+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
+ DSSERR("DSI error, irqstatus %x\n", irqstatus);
+ print_irq_status(irqstatus);
++ spin_lock(&dsi.errors_lock);
++ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
++ spin_unlock(&dsi.errors_lock);
+ } else if (debug_irq) {
+ print_irq_status(irqstatus);
+ }
+@@ -616,6 +621,17 @@ static void _dsi_initialize_irq(void)
+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
+ }
+
++static u32 dsi_get_errors(void)
++{
++ unsigned long flags;
++ u32 e;
++ spin_lock_irqsave(&dsi.errors_lock, flags);
++ e = dsi.errors;
++ dsi.errors = 0;
++ spin_unlock_irqrestore(&dsi.errors_lock, flags);
++ return e;
++}
++
+ static void dsi_vc_enable_bta_irq(int channel)
+ {
+ u32 l;
+@@ -1807,6 +1823,7 @@ static int dsi_vc_send_bta(int channel)
+ static int dsi_vc_send_bta_sync(int channel)
+ {
+ int r = 0;
++ u32 err;
+
+ init_completion(&dsi.bta_completion);
+
+@@ -1822,6 +1839,13 @@ static int dsi_vc_send_bta_sync(int channel)
+ r = -EIO;
+ goto err;
+ }
++
++ err = dsi_get_errors();
++ if (err) {
++ DSSERR("Error while sending BTA: %x\n", err);
++ r = -EIO;
++ goto err;
++ }
+ err:
+ dsi_vc_disable_bta_irq(channel);
+
+@@ -3720,6 +3744,9 @@ int dsi_init(void)
+ {
+ u32 rev;
+
++ spin_lock_init(&dsi.errors_lock);
++ dsi.errors = 0;
++
+ spin_lock_init(&dsi.cmd_lock);
+ dsi.cmd_fifo = kfifo_alloc(
+ DSI_CMD_FIFO_LEN * sizeof(struct dsi_cmd_item),
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0053-DSS2-Added-global-alpha-support.patch b/recipes/linux/linux-omap-pm/dss2/0053-DSS2-Added-global-alpha-support.patch
new file mode 100644
index 0000000000..0a5a213789
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0053-DSS2-Added-global-alpha-support.patch
@@ -0,0 +1,230 @@
+From 3aae3ce190cbdf64bcfe9768ef4d20cdd2ddbd6a Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 24 Apr 2009 15:29:06 +0530
+Subject: [PATCH 053/146] DSS2: Added global alpha support.
+
+global_alpha sysfs entry for video1 plane will always show 255 as
+it does not support global_alpha.
+Initliazied the global alpha field for all the overlays
+to 255 (fully opaque).
+Documentation also updated.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ Documentation/arm/OMAP/DSS | 1 +
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/dispc.c | 25 ++++++++++++++++---
+ drivers/video/omap2/dss/dss.h | 3 +-
+ drivers/video/omap2/dss/manager.c | 3 +-
+ drivers/video/omap2/dss/overlay.c | 37 +++++++++++++++++++++++++++++
+ 6 files changed, 64 insertions(+), 6 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 9e902a2..249e1a3 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -133,6 +133,7 @@ name
+ output_size width,height
+ position x,y
+ screen_width width
++global_alpha global alpha 0-255 0=transparent 255=opaque
+
+ /sys/devices/platform/omapdss/manager? directory:
+ display Destination display
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index d0b4c83..45b16ca 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -363,6 +363,7 @@ struct omap_overlay_info {
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
++ u8 global_alpha;
+ };
+
+ enum omap_overlay_caps {
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 9bab6cf..b6a39f5 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -778,6 +778,17 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+ dispc_write_reg(vsi_reg[plane-1], val);
+ }
+
++static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
++{
++
++ BUG_ON(plane == OMAP_DSS_VIDEO1);
++
++ if (plane == OMAP_DSS_GFX)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
++ else if (plane == OMAP_DSS_VIDEO2)
++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
++}
++
+ static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+ {
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
+@@ -1444,7 +1455,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, int mirror)
++ u8 rotation, int mirror,
++ u8 global_alpha)
+ {
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+ bool five_taps = 0;
+@@ -1592,6 +1604,9 @@ static int _dispc_setup_plane(enum omap_plane plane,
+
+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+
++ if (plane != OMAP_DSS_VIDEO1)
++ _dispc_setup_global_alpha(plane, global_alpha);
++
+ return 0;
+ }
+
+@@ -3011,7 +3026,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, bool mirror)
++ u8 rotation, bool mirror, u8 global_alpha)
+ {
+ int r = 0;
+
+@@ -3032,7 +3047,8 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+- rotation, mirror);
++ rotation, mirror,
++ global_alpha);
+
+ enable_clocks(0);
+
+@@ -3247,7 +3263,8 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ pi->color_mode, 0,
+ pi->rotation_type,
+ pi->rotation,
+- pi->mirror);
++ pi->mirror,
++ pi->global_alpha);
+
+ dispc_enable_plane(ovl->id, 1);
+ }
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 1d01ff6..20cef0a 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -273,7 +273,8 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+- u8 rotation, bool mirror);
++ u8 rotation, bool mirror,
++ u8 global_alpha);
+
+ void dispc_go(enum omap_channel channel);
+ void dispc_enable_lcd_out(bool enable);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index bf059e0..1e6cd8d 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -464,7 +464,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ ilace,
+ ovl->info.rotation_type,
+ ovl->info.rotation,
+- ovl->info.mirror);
++ ovl->info.mirror,
++ ovl->info.global_alpha);
+
+ if (r) {
+ DSSERR("dispc_setup_plane failed for ovl %d\n",
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index c047206..035a57a 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -194,6 +194,37 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+ return size;
+ }
+
++static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
++{
++ return snprintf(buf, PAGE_SIZE, "%d\n",
++ ovl->info.global_alpha);
++}
++
++static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
++ const char *buf, size_t size)
++{
++ int r;
++ struct omap_overlay_info info;
++
++ ovl->get_overlay_info(ovl, &info);
++
++ /* Video1 plane does not support global alpha
++ * to always make it 255 completely opaque
++ */
++ if (ovl->id == OMAP_DSS_VIDEO1)
++ info.global_alpha = 255;
++ else
++ info.global_alpha = simple_strtoul(buf, NULL, 10);
++
++ if ((r = ovl->set_overlay_info(ovl, &info)))
++ return r;
++
++ if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
++ return r;
++
++ return size;
++}
++
+ struct overlay_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay *, char *);
+@@ -215,6 +246,8 @@ static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+ overlay_output_size_show, overlay_output_size_store);
+ static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+ overlay_enabled_show, overlay_enabled_store);
++static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
++ overlay_global_alpha_show, overlay_global_alpha_store);
+
+ static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_name.attr,
+@@ -224,6 +257,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
+ &overlay_attr_position.attr,
+ &overlay_attr_output_size.attr,
+ &overlay_attr_enabled.attr,
++ &overlay_attr_global_alpha.attr,
+ NULL
+ };
+
+@@ -444,6 +478,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->id = OMAP_DSS_GFX;
+ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ case 1:
+ ovl->name = "vid1";
+@@ -451,6 +486,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ case 2:
+ ovl->name = "vid2";
+@@ -458,6 +494,7 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3;
+ ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
+ OMAP_DSS_OVL_CAP_DISPC;
++ ovl->info.global_alpha = 255;
+ break;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0054-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch b/recipes/linux/linux-omap-pm/dss2/0054-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch
new file mode 100644
index 0000000000..6b28f17db5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0054-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch
@@ -0,0 +1,35 @@
+From 08a8816f1b41c331073a3144dbb90b4fe9eeec05 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Fri, 24 Apr 2009 14:33:48 +0530
+Subject: [PATCH 054/146] DSS2: Rotation attrs for YUV need not to be reversed for 90 and 270
+
+DSS2 supports horizontal mirroing. so only 180 and 0 degree attributes needs
+to be reversed for mirroring.
+Slight corrupt image is seen with 90 ad 270 degree rotation with mirroring
+when the image height and widht is not 32-pixels aligned. To be specific
+resolution is 168X192.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ drivers/video/omap2/dss/dispc.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b6a39f5..f79decb 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1110,9 +1110,9 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ if (mirroring) {
+ switch (rotation) {
+ case 0: vidrot = 2; break;
+- case 1: vidrot = 3; break;
++ case 1: vidrot = 1; break;
+ case 2: vidrot = 0; break;
+- case 3: vidrot = 1; break;
++ case 3: vidrot = 3; break;
+ }
+ } else {
+ switch (rotation) {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0055-DSS2-Documentation-update-for-new-sysfs-entries-in.patch b/recipes/linux/linux-omap-pm/dss2/0055-DSS2-Documentation-update-for-new-sysfs-entries-in.patch
new file mode 100644
index 0000000000..24033a2c76
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0055-DSS2-Documentation-update-for-new-sysfs-entries-in.patch
@@ -0,0 +1,32 @@
+From 188cf22d913a2fab84e77e95651a99e70a78ec20 Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Mon, 27 Apr 2009 13:15:07 +0530
+Subject: [PATCH 055/146] DSS2: Documentation update for new sysfs entries in omapdss/manager
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ Documentation/arm/OMAP/DSS | 7 ++++++-
+ 1 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 249e1a3..751000b 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -136,8 +136,13 @@ screen_width width
+ global_alpha global alpha 0-255 0=transparent 255=opaque
+
+ /sys/devices/platform/omapdss/manager? directory:
+-display Destination display
++display Destination display
+ name
++alpha_blending_enabled 0=off 1=on
++color_key_enabled 0=off 1=on
++color_key_type gfx-destination video-source
++color_key_value 0 to 2^24
++default_color default background color RGB24 0 to 2^24
+
+ /sys/devices/platform/omapdss/display? directory:
+ ctrl_name Controller name
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0056-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch b/recipes/linux/linux-omap-pm/dss2/0056-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch
new file mode 100644
index 0000000000..a35e4d78eb
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0056-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch
@@ -0,0 +1,56 @@
+From eede63f63b5c8b932b938b9b65725918e8f42775 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 17 Apr 2009 18:34:33 +0200
+Subject: [PATCH 056/146] DSS2: Don't touch plane coordinates when changing fb->ovl mapping
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When attaching overlays to a framebuffer via the 'overlays' sysfs file
+do not touch the planes' coordinates. Without this change attaching
+VID2 to a framebuffer which already has VID1 attached would cause VID1
+to be reset to position 0,0 and scaled to 1:1 size. Also call
+omapfb_apply_changes() only once after all the overlays have been
+attached to avoid fiddling with all the overlays several times.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 13 ++++++-------
+ 1 files changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 13028ae..702199d 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -183,6 +183,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+ struct omap_overlay *ovl;
+ int num_ovls, r, i;
+ int len;
++ bool added = false;
+
+ num_ovls = 0;
+
+@@ -284,15 +285,13 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+
+ ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+- r = omapfb_apply_changes(fbi, 1);
++ added = true;
++ }
++
++ if (added) {
++ r = omapfb_apply_changes(fbi, 0);
+ if (r)
+ goto out;
+-
+- if (ovl->manager) {
+- r = ovl->manager->apply(ovl->manager);
+- if (r)
+- goto out;
+- }
+ }
+
+ r = count;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0057-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch b/recipes/linux/linux-omap-pm/dss2/0057-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch
new file mode 100644
index 0000000000..9699e07869
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0057-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch
@@ -0,0 +1,97 @@
+From c843753f9a84739e7e81f6da3e29c7d5bdf3abc1 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 29 Apr 2009 17:26:30 +0300
+Subject: [PATCH 057/146] DSS2: DSI: configure ENTER/EXIT_HS_MODE_LATENCY
+
+---
+ drivers/video/omap2/dss/dsi.c | 49 ++++++++++++++++++++++++++++++++--------
+ 1 files changed, 39 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index d8df353..5225ed6 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2309,15 +2309,26 @@ static int dsi_proto_config(struct omap_display *display)
+ return 0;
+ }
+
+-static void dsi_proto_timings(void)
+-{
+- int tlpx_half, tclk_zero, tclk_prepare, tclk_trail;
+- int tclk_pre, tclk_post;
+- int ddr_clk_pre, ddr_clk_post;
++static void dsi_proto_timings(struct omap_display *display)
++{
++ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
++ unsigned tclk_pre, tclk_post;
++ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
++ unsigned ths_trail, ths_exit;
++ unsigned ddr_clk_pre, ddr_clk_post;
++ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
++ unsigned ths_eot;
+ u32 r;
+
++ r = dsi_read_reg(DSI_DSIPHY_CFG0);
++ ths_prepare = FLD_GET(r, 31, 24);
++ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
++ ths_zero = ths_prepare_ths_zero - ths_prepare;
++ ths_trail = FLD_GET(r, 15, 8);
++ ths_exit = FLD_GET(r, 7, 0);
++
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+- tlpx_half = FLD_GET(r, 22, 16);
++ tlpx = FLD_GET(r, 22, 16) * 2;
+ tclk_trail = FLD_GET(r, 15, 8);
+ tclk_zero = FLD_GET(r, 7, 0);
+
+@@ -2329,17 +2340,35 @@ static void dsi_proto_timings(void)
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
+- ddr_clk_pre = (tclk_pre + tlpx_half*2 + tclk_zero + tclk_prepare) / 4;
+- ddr_clk_post = (tclk_post + tclk_trail) / 4;
++ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
++ 4);
++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
+ dsi_write_reg(DSI_CLK_TIMING, r);
+
+- DSSDBG("ddr_clk_pre %d, ddr_clk_post %d\n",
++ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
+ ddr_clk_pre,
+ ddr_clk_post);
++
++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
++ if (display->hw_config.u.dsi.data1_lane != 0 &&
++ display->hw_config.u.dsi.data2_lane != 0)
++ ths_eot = 2;
++ else
++ ths_eot = 4;
++
++ enter_hs_mode_lat = DIV_ROUND_UP(tlpx + ths_prepare + ths_zero, 4) + 4;
++ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
++
++ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
++ FLD_VAL(exit_hs_mode_lat, 15, 0);
++ dsi_write_reg(DSI_VM_TIMING7, r);
++
++ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
++ enter_hs_mode_lat, exit_hs_mode_lat);
+ }
+
+
+@@ -3340,7 +3369,7 @@ static int dsi_display_init_dsi(struct omap_display *display)
+
+ _dsi_print_reset_status();
+
+- dsi_proto_timings();
++ dsi_proto_timings(display);
+ dsi_set_lp_clk_divisor();
+
+ if (1)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0058-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch b/recipes/linux/linux-omap-pm/dss2/0058-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch
new file mode 100644
index 0000000000..c8b5f7fe83
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0058-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch
@@ -0,0 +1,34 @@
+From 7afd9adb31922a0b3b16c92df3f767f78f7cdc68 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 4 May 2009 16:18:30 +0200
+Subject: [PATCH 058/146] DSS2: Avoid div by zero when calculating required fclk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When calculating the required fclk rate for five tap filtering if the
+display width and output width are equal div by zero could occur. The
+TRM doesn't actually specify how this case should be handled but for
+now just skip the calculation which would trigger the div by zero.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index f79decb..5fc9457 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1399,7 +1399,7 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height,
+ do_div(tmp, 2 * out_height * ppl);
+ fclk = tmp;
+
+- if (height > 2 * out_height) {
++ if (height > 2 * out_height && ppl != out_width) {
+ tmp = pclk * (height - 2 * out_height) * out_width;
+ do_div(tmp, 2 * out_height * (ppl - out_width));
+ fclk = max(fclk, (u32) tmp);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0059-DSS2-VRFB-save-restore-context.patch b/recipes/linux/linux-omap-pm/dss2/0059-DSS2-VRFB-save-restore-context.patch
new file mode 100644
index 0000000000..ce2a65777e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0059-DSS2-VRFB-save-restore-context.patch
@@ -0,0 +1,106 @@
+From 482644bbb2e168002d8a004d1553f5da994276c2 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 09:05:12 +0300
+Subject: [PATCH 059/146] DSS2: VRFB: save / restore context
+
+The VRFB is part of the SMS and supplied by the core power domain; do
+the context saving while VRFB is configured and restore it along with
+the rest of the domain context.
+
+This patch only implements the restore functionality, but not the
+actual call to the restore. That belongs to PM functionality.
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 1 +
+ arch/arm/plat-omap/vrfb.c | 50 ++++++++++++++++++++++++++-----
+ 2 files changed, 43 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index 12c7fab..ee6c062 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -44,5 +44,6 @@ extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode);
++extern void omap_vrfb_restore_context(void);
+
+ #endif /* __VRFB_H */
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 2ae0d68..649803e 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -39,6 +39,33 @@
+ /* bitmap of reserved contexts */
+ static unsigned ctx_map;
+
++/*
++ * Access to this happens from client drivers or the PM core after wake-up.
++ * For the first case we require locking at the driver level, for the second
++ * we don't need locking, since no drivers will run until after the wake-up
++ * has finished.
++ */
++struct {
++ u32 physical_ba;
++ u32 control;
++ u32 size;
++} vrfb_hw_context[VRFB_NUM_CTXS];
++
++void omap_vrfb_restore_context(void)
++{
++ int i;
++
++ for (i = 0; i < VRFB_NUM_CTXS; i++) {
++ /* Restore only the active contexts */
++ if (!(ctx_map & (1 << i)))
++ continue;
++ omap_writel(vrfb_hw_context[i].control, SMS_ROT_CONTROL(i));
++ omap_writel(vrfb_hw_context[i].size, SMS_ROT_SIZE(i));
++ omap_writel(vrfb_hw_context[i].physical_ba,
++ SMS_ROT_PHYSICAL_BA(i));
++ }
++}
++
+ void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp)
+ {
+@@ -56,6 +83,8 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u16 vrfb_height;
+ u8 ctx = vrfb->context;
+ u8 bytespp;
++ u32 size;
++ u32 control;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+ width, height, bytespp);
+@@ -100,15 +129,20 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+
+ DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
+
++ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
++ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
++
++ control = pixel_size_exp << SMS_PS_OFFSET;
++ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
++ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
++
++ vrfb_hw_context[ctx].physical_ba = paddr;
++ vrfb_hw_context[ctx].size = size;
++ vrfb_hw_context[ctx].control = control;
++
+ omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
+- omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
+- (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
+- SMS_ROT_SIZE(ctx));
+-
+- omap_writel(pixel_size_exp << SMS_PS_OFFSET |
+- VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
+- VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
+- SMS_ROT_CONTROL(ctx));
++ omap_writel(size, SMS_ROT_SIZE(ctx));
++ omap_writel(control, SMS_ROT_CONTROL(ctx));
+
+ DBG("vrfb offset pixels %d, %d\n",
+ vrfb_width - width, vrfb_height - height);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0060-DSS2-VRAM-Fix-indentation.patch b/recipes/linux/linux-omap-pm/dss2/0060-DSS2-VRAM-Fix-indentation.patch
new file mode 100644
index 0000000000..c9eef730ea
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0060-DSS2-VRAM-Fix-indentation.patch
@@ -0,0 +1,65 @@
+From a12a2e16a3403ffd3c4def1bb53760f8b1538adf Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 6 May 2009 09:03:43 +0300
+Subject: [PATCH 060/146] DSS2: VRAM: Fix indentation
+
+---
+ arch/arm/plat-omap/vram.c | 26 +++++++++++++-------------
+ 1 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index b126a64..f3ce849 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -287,35 +287,35 @@ static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
+ static int _omap_vram_clear(u32 paddr, unsigned pages)
+ {
+ struct completion compl;
+- unsigned elem_count;
+- unsigned frame_count;
++ unsigned elem_count;
++ unsigned frame_count;
+ int r;
+ int lch;
+
+ init_completion(&compl);
+
+- r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
+ _omap_vram_dma_cb,
+- &compl, &lch);
+- if (r) {
++ &compl, &lch);
++ if (r) {
+ pr_err("VRAM: request_dma failed for memory clear\n");
+ return -EBUSY;
+ }
+
+- elem_count = pages * PAGE_SIZE / 4;
+- frame_count = 1;
++ elem_count = pages * PAGE_SIZE / 4;
++ frame_count = 1;
+
+- omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
+- elem_count, frame_count,
+- OMAP_DMA_SYNC_ELEMENT,
+- 0, 0);
++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
++ elem_count, frame_count,
++ OMAP_DMA_SYNC_ELEMENT,
++ 0, 0);
+
+- omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
+ paddr, 0, 0);
+
+ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
+
+- omap_start_dma(lch);
++ omap_start_dma(lch);
+
+ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
+ omap_stop_dma(lch);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0061-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch b/recipes/linux/linux-omap-pm/dss2/0061-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch
new file mode 100644
index 0000000000..8b3b962df3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0061-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch
@@ -0,0 +1,82 @@
+From 0196f7d35fd6780c07646aefbb4f3985794518db Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 19:00:19 +0200
+Subject: [PATCH 061/146] DSS2: fix the usage of get_last_off_on_transaction_id
+
+The function returns int not unsigned since it can fail. Handle the
+failing case as if the context had been lost. So now:
+
+1. No get_last_off_on_transaction_id func in platform data->
+ never restore the context
+2. Return val < 0 -> force the restore
+3. Return val >= 0 do the restore only if the counter has changed.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 +-
+ drivers/video/omap2/dss/core.c | 18 ++++++++++++------
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 45b16ca..31ebb96 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -234,7 +234,7 @@ struct device;
+
+ /* Board specific data */
+ struct omap_dss_board_info {
+- unsigned (*get_last_off_on_transaction_id)(struct device *dev);
++ int (*get_last_off_on_transaction_id)(struct device *dev);
+ int (*dsi_power_up)(void);
+ void (*dsi_power_down)(void);
+ int num_displays;
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index ae7cd06..6d11b04 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -38,7 +38,7 @@
+
+ static struct {
+ struct platform_device *pdev;
+- unsigned ctx_id;
++ int ctx_id;
+
+ struct clk *dss_ick;
+ struct clk *dss1_fck;
+@@ -63,22 +63,28 @@ module_param_named(debug, dss_debug, bool, 0644);
+ #endif
+
+ /* CONTEXT */
+-static unsigned dss_get_ctx_id(void)
++static int dss_get_ctx_id(void)
+ {
+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++ int r;
+
+ if (!pdata->get_last_off_on_transaction_id)
+ return 0;
+-
+- return pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
++ if (r < 0) {
++ dev_err(&core.pdev->dev,
++ "getting transaction ID failed, will force context restore\n");
++ r = -1;
++ }
++ return r;
+ }
+
+ int dss_need_ctx_restore(void)
+ {
+ int id = dss_get_ctx_id();
+
+- if (id != core.ctx_id) {
+- DSSDBG("ctx id %u -> id %u\n",
++ if (id < 0 || id != core.ctx_id) {
++ DSSDBG("ctx id %d -> id %d\n",
+ core.ctx_id, id);
+ core.ctx_id = id;
+ return 1;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0062-VRFB-fix-debug-messages.patch b/recipes/linux/linux-omap-pm/dss2/0062-VRFB-fix-debug-messages.patch
new file mode 100644
index 0000000000..989b8cfece
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0062-VRFB-fix-debug-messages.patch
@@ -0,0 +1,35 @@
+From ad6c07cb298391adfbbb286606cca98738675119 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 11:16:14 +0200
+Subject: [PATCH 062/146] VRFB: fix debug messages
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 649803e..289fc8a 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -87,7 +87,7 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ u32 control;
+
+ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
+- width, height, bytespp);
++ width, height, color_mode);
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+@@ -127,7 +127,7 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
+
+- DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
++ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
+
+ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
+ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0063-VRFB-add-suspend-resume-functionality.patch b/recipes/linux/linux-omap-pm/dss2/0063-VRFB-add-suspend-resume-functionality.patch
new file mode 100644
index 0000000000..d2b9346a93
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0063-VRFB-add-suspend-resume-functionality.patch
@@ -0,0 +1,216 @@
+From c26aa6e5aab9d145b343a2a71243508378e59621 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 5 May 2009 11:16:13 +0200
+Subject: [PATCH 063/146] VRFB: add suspend/resume functionality
+
+At the moment the VRFB context is restored at each core power domain
+OFF->ON transition. This is not optimal since the VRFB might be unused
+temporarily for example when the screen is blanked. Add a suspend /
+resume function to mark these unused periods during which we'll avoid
+thea the context restore.
+
+Use atomic bitops for ctx_map for consistency.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 2 +
+ arch/arm/plat-omap/vrfb.c | 75 ++++++++++++++++++++++++-----
+ drivers/video/omap2/omapfb/omapfb-main.c | 28 +++++++++++
+ 3 files changed, 92 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index ee6c062..9647d82 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -39,6 +39,8 @@ struct vrfb
+
+ extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
+ extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb);
++extern void omap_vrfb_resume_ctx(struct vrfb *vrfb);
+ extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+ u8 bytespp);
+ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 289fc8a..29f04e2 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -1,7 +1,9 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/ioport.h>
++
+ #include <asm/io.h>
++#include <asm/bitops.h>
+
+ #include <mach/io.h>
+ #include <mach/vrfb.h>
+@@ -37,7 +39,9 @@
+
+ #define VRFB_NUM_CTXS 12
+ /* bitmap of reserved contexts */
+-static unsigned ctx_map;
++static unsigned long ctx_map;
++/* bitmap of contexts for which we have to keep the HW context valid */
++static unsigned long ctx_map_active;
+
+ /*
+ * Access to this happens from client drivers or the PM core after wake-up.
+@@ -51,18 +55,23 @@ struct {
+ u32 size;
+ } vrfb_hw_context[VRFB_NUM_CTXS];
+
++static void inline restore_hw_context(int ctx)
++{
++ omap_writel(vrfb_hw_context[ctx].control, SMS_ROT_CONTROL(ctx));
++ omap_writel(vrfb_hw_context[ctx].size, SMS_ROT_SIZE(ctx));
++ omap_writel(vrfb_hw_context[ctx].physical_ba, SMS_ROT_PHYSICAL_BA(ctx));
++}
++
+ void omap_vrfb_restore_context(void)
+ {
+ int i;
++ unsigned long map = ctx_map_active;
+
+- for (i = 0; i < VRFB_NUM_CTXS; i++) {
+- /* Restore only the active contexts */
+- if (!(ctx_map & (1 << i)))
+- continue;
+- omap_writel(vrfb_hw_context[i].control, SMS_ROT_CONTROL(i));
+- omap_writel(vrfb_hw_context[i].size, SMS_ROT_SIZE(i));
+- omap_writel(vrfb_hw_context[i].physical_ba,
+- SMS_ROT_PHYSICAL_BA(i));
++ for (i = ffs(map); i; i = ffs(map)) {
++ /* i=1..32 */
++ i--;
++ map &= ~(1 << i);
++ restore_hw_context(i);
+ }
+ }
+
+@@ -156,13 +165,20 @@ EXPORT_SYMBOL(omap_vrfb_setup);
+ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ {
+ int rot;
++ int ctx = vrfb->context;
+
+- if (vrfb->context == 0xff)
++ if (ctx == 0xff)
+ return;
+
+- DBG("release ctx %d\n", vrfb->context);
++ DBG("release ctx %d\n", ctx);
+
+- ctx_map &= ~(1 << vrfb->context);
++ if (!(ctx_map & (1 << ctx))) {
++ BUG();
++ return;
++ }
++ WARN_ON(!(ctx_map_active & (1 << ctx)));
++ clear_bit(ctx, &ctx_map_active);
++ clear_bit(ctx, &ctx_map);
+
+ for (rot = 0; rot < 4; ++rot) {
+ if(vrfb->paddr[rot]) {
+@@ -194,7 +210,9 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+
+ DBG("found free ctx %d\n", ctx);
+
+- ctx_map |= 1 << ctx;
++ set_bit(ctx, &ctx_map);
++ WARN_ON(ctx_map_active & (1 << ctx));
++ set_bit(ctx, &ctx_map_active);
+
+ memset(vrfb, 0, sizeof(*vrfb));
+
+@@ -219,3 +237,34 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ }
+ EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
++void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
++{
++ DBG("suspend ctx %d\n", vrfb->context);
++ if (vrfb->context >= VRFB_NUM_CTXS ||
++ (!(1 << vrfb->context) & ctx_map_active)) {
++ BUG();
++ return;
++ }
++ clear_bit(vrfb->context, &ctx_map_active);
++}
++EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
++
++void omap_vrfb_resume_ctx(struct vrfb *vrfb)
++{
++ DBG("resume ctx %d\n", vrfb->context);
++ if (vrfb->context >= VRFB_NUM_CTXS ||
++ ((1 << vrfb->context) & ctx_map_active)) {
++ BUG();
++ return;
++ }
++ /*
++ * omap_vrfb_restore_context is normally called by the core domain
++ * save / restore logic, but since this VRFB context was suspended
++ * those calls didn't actually restore the context and now we might
++ * have an invalid context. Do an explicit restore here.
++ */
++ restore_hw_context(vrfb->context);
++ set_bit(vrfb->context, &ctx_map_active);
++}
++EXPORT_SYMBOL(omap_vrfb_resume_ctx);
++
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 76e7c6c..4bb74b7 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1036,6 +1036,30 @@ static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+ return 0;
+ }
+
++static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_suspend_ctx(&ofbi->region.vrfb);
++ }
++}
++
++static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev)
++{
++ int i;
++
++ for (i = 0; i < fbdev->num_fbs; i++) {
++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
++
++ if (ofbi->region.vrfb.vaddr[0])
++ omap_vrfb_resume_ctx(&ofbi->region.vrfb);
++ }
++}
++
+ static int omapfb_blank(int blank, struct fb_info *fbi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+@@ -1051,6 +1075,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
+ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ goto exit;
+
++ omapfb_vrfb_resume_all(fbdev);
++
+ if (display->resume)
+ r = display->resume(display);
+
+@@ -1073,6 +1099,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
+ if (display->suspend)
+ r = display->suspend(display);
+
++ omapfb_vrfb_suspend_all(fbdev);
++
+ break;
+
+ default:
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0064-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch b/recipes/linux/linux-omap-pm/dss2/0064-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch
new file mode 100644
index 0000000000..02588ba453
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0064-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch
@@ -0,0 +1,92 @@
+From 2666676c1db8b6c50cd97e668c773e5b072de188 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 7 May 2009 14:32:55 +0300
+Subject: [PATCH 064/146] DSS2: DSI: tune the timings to be more relaxed
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 37 +++++++++++++++++++++----------------
+ 1 files changed, 21 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 5225ed6..67ecfcf 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1396,28 +1396,28 @@ static void dsi_complexio_timings(void)
+ /* 1 * DDR_CLK = 2 * UI */
+
+ /* min 40ns + 4*UI max 85ns + 6*UI */
+- ths_prepare = ns2ddr(59) + 2;
++ ths_prepare = ns2ddr(70) + 2;
+
+ /* min 145ns + 10*UI */
+- ths_prepare_ths_zero = ns2ddr(145) + 5;
++ ths_prepare_ths_zero = ns2ddr(175) + 2;
+
+ /* min max(8*UI, 60ns+4*UI) */
+- ths_trail = max((unsigned)4, ns2ddr(60) + 2);
++ ths_trail = ns2ddr(60) + 5;
+
+ /* min 100ns */
+- ths_exit = ns2ddr(100);
++ ths_exit = ns2ddr(145);
+
+ /* tlpx min 50n */
+ tlpx_half = ns2ddr(25);
+
+ /* min 60ns */
+- tclk_trail = ns2ddr(60);
++ tclk_trail = ns2ddr(60) + 2;
+
+ /* min 38ns, max 95ns */
+- tclk_prepare = ns2ddr(38);
++ tclk_prepare = ns2ddr(65);
+
+ /* min tclk-prepare + tclk-zero = 300ns */
+- tclk_zero = ns2ddr(300 - 38);
++ tclk_zero = ns2ddr(260);
+
+ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
+ ths_prepare, ddr2ns(ths_prepare),
+@@ -2340,9 +2340,19 @@ static void dsi_proto_timings(struct omap_display *display)
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
++ if (display->hw_config.u.dsi.data1_lane != 0 &&
++ display->hw_config.u.dsi.data2_lane != 0)
++ ths_eot = 2;
++ else
++ ths_eot = 4;
++
+ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
+ 4);
+- ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4);
++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
++
++ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
++ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+@@ -2353,14 +2363,9 @@ static void dsi_proto_timings(struct omap_display *display)
+ ddr_clk_pre,
+ ddr_clk_post);
+
+- /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
+- if (display->hw_config.u.dsi.data1_lane != 0 &&
+- display->hw_config.u.dsi.data2_lane != 0)
+- ths_eot = 2;
+- else
+- ths_eot = 4;
+-
+- enter_hs_mode_lat = DIV_ROUND_UP(tlpx + ths_prepare + ths_zero, 4) + 4;
++ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
++ DIV_ROUND_UP(ths_prepare, 4) +
++ DIV_ROUND_UP(ths_zero + 3, 4);
+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0065-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch b/recipes/linux/linux-omap-pm/dss2/0065-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch
new file mode 100644
index 0000000000..915dad4def
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0065-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch
@@ -0,0 +1,29 @@
+From d60b50b5248b9badf996119c80136503b1d68ed7 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Mon, 11 May 2009 15:15:52 +0200
+Subject: [PATCH 065/146] DSS2: VRFB: don't WARN when releasing inactive ctx
+
+Releasing an inactive context is valid, it can happen when
+the application first blanks the screen then frees the
+framebuffer.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 29f04e2..34395c2 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -176,7 +176,6 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ BUG();
+ return;
+ }
+- WARN_ON(!(ctx_map_active & (1 << ctx)));
+ clear_bit(ctx, &ctx_map_active);
+ clear_bit(ctx, &ctx_map);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0066-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch b/recipes/linux/linux-omap-pm/dss2/0066-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch
new file mode 100644
index 0000000000..3e3dd6e1af
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0066-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch
@@ -0,0 +1,65 @@
+From 949c60b7fa5c016478dd403fab96b7dd1c701fc7 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Tue, 12 May 2009 14:38:05 +0200
+Subject: [PATCH 066/146] DSS2: Swap field offset values w/ VRFB rotation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+The field 0 and field 1 offset values were still incorrect when VRFB
+rotation is used. Swap them to put the fields into proper order.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 17 +++++++++++------
+ 1 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 5fc9457..b0e4960 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1182,6 +1182,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+
+ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+ width, height);
++
++ /*
++ * field 0 = even field = bottom field
++ * field 1 = odd field = top field
++ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ case 2:
+@@ -1194,11 +1199,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ width = width >> 1;
+ case 1:
+ case 3:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = screen_width * ps;
++ *offset0 = screen_width * ps;
+ else
+- *offset1 = 0;
++ *offset0 = 0;
+
+ *row_inc = pixinc(1 + (screen_width - width) +
+ (fieldmode ? screen_width : 0),
+@@ -1216,11 +1221,11 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ width = width >> 1;
+ case 5:
+ case 7:
+- *offset0 = 0;
++ *offset1 = 0;
+ if (fieldmode)
+- *offset1 = screen_width * ps;
++ *offset0 = screen_width * ps;
+ else
+- *offset1 = 0;
++ *offset0 = 0;
+ *row_inc = pixinc(1 - (screen_width + width) -
+ (fieldmode ? screen_width : 0),
+ ps);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0067-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch b/recipes/linux/linux-omap-pm/dss2/0067-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch
new file mode 100644
index 0000000000..5b86244e1f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0067-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch
@@ -0,0 +1,125 @@
+From d82606b114e4bab4f425f0180741bd2b1cd8e04a Mon Sep 17 00:00:00 2001
+From: Hardik Shah <hardik.shah@ti.com>
+Date: Thu, 14 May 2009 15:04:17 +0530
+Subject: [PATCH 067/146] DSS2: OMAP3EVM: Added DSI powerup and powerdown functions
+
+Copied fom 3430sdp implementation.
+
+Signed-off-by: Hardik Shah <hardik.shah@ti.com>
+---
+ arch/arm/mach-omap2/board-omap3evm.c | 62 +++++++++++++++++++++-------------
+ 1 files changed, 38 insertions(+), 24 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index dffb8b9..6c9f11b 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -243,6 +243,38 @@ static int __init omap3_evm_i2c_init(void)
+ static int lcd_enabled;
+ static int dvi_enabled;
+
++static void enable_vpll2(int enable)
++{
++ u8 ded_val, grp_val;
++
++ if (enable) {
++ ded_val = ENABLE_VPLL2_DEDICATED;
++ grp_val = ENABLE_VPLL2_DEV_GRP;
++ } else {
++ ded_val = 0;
++ grp_val = 0;
++ }
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ded_val, TWL4030_VPLL2_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ grp_val, TWL4030_VPLL2_DEV_GRP);
++}
++
++static int omap3evm_dsi_power_up(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(1);
++ return 0;
++}
++
++static void omap3evm_dsi_power_down(void)
++{
++ if (omap_rev() > OMAP3430_REV_ES1_0)
++ enable_vpll2(0);
++}
++
++
+ static void __init omap3_evm_display_init(void)
+ {
+ int r;
+@@ -312,12 +344,7 @@ static int omap3_evm_panel_enable_lcd(struct omap_display *display)
+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+ return -EINVAL;
+ }
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
+- }
++ omap3evm_dsi_power_up();
+ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
+ lcd_enabled = 1;
+ return 0;
+@@ -325,12 +352,7 @@ static int omap3_evm_panel_enable_lcd(struct omap_display *display)
+
+ static void omap3_evm_panel_disable_lcd(struct omap_display *display)
+ {
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEV_GRP);
+- }
++ omap3evm_dsi_power_down();
+ gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
+ lcd_enabled = 0;
+ }
+@@ -376,13 +398,8 @@ static int omap3_evm_panel_enable_dvi(struct omap_display *display)
+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+ return -EINVAL;
+ }
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEDICATED, TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VPLL2_DEV_GRP, TWL4030_VPLL2_DEV_GRP);
+- }
+
++ omap3evm_dsi_power_up();
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+ TWL4030_GPIODATA_IN3);
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80,
+@@ -394,13 +411,8 @@ static int omap3_evm_panel_enable_dvi(struct omap_display *display)
+
+ static void omap3_evm_panel_disable_dvi(struct omap_display *display)
+ {
+- if (omap_rev() > OMAP3430_REV_ES1_0) {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x0,
+- TWL4030_VPLL2_DEV_GRP);
+- }
+
++ omap3evm_dsi_power_down();
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+ TWL4030_GPIODATA_IN3);
+ twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x00,
+@@ -419,6 +431,8 @@ static struct omap_dss_display_config omap3_evm_display_data_dvi = {
+ };
+
+ static struct omap_dss_board_info omap3_evm_dss_data = {
++ .dsi_power_up = omap3evm_dsi_power_up,
++ .dsi_power_down = omap3evm_dsi_power_down,
+ .num_displays = 3,
+ .displays = {
+ &omap3_evm_display_data,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0068-DSS2-DSI-Improve-perf-measurement-output.patch b/recipes/linux/linux-omap-pm/dss2/0068-DSS2-DSI-Improve-perf-measurement-output.patch
new file mode 100644
index 0000000000..f090aa8d51
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0068-DSS2-DSI-Improve-perf-measurement-output.patch
@@ -0,0 +1,127 @@
+From ba927a58cb0bc990839f4278e0fc71529cb4dc70 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 22 May 2009 12:59:41 +0300
+Subject: [PATCH 068/146] DSS2: DSI: Improve perf-measurement output
+
+---
+ drivers/video/omap2/dss/dsi.c | 67 +++++++++++++++++++++++++++++-----------
+ 1 files changed, 48 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 67ecfcf..057b057 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -294,6 +294,7 @@ static struct
+ #ifdef DEBUG
+ ktime_t perf_setup_time;
+ ktime_t perf_start_time;
++ ktime_t perf_start_time_auto;
+ int perf_measure_frames;
+
+ struct {
+@@ -360,13 +361,16 @@ static void perf_mark_start(void)
+ dsi.perf_start_time = ktime_get();
+ }
+
++static void perf_mark_start_auto(void)
++{
++ dsi.perf_start_time_auto = ktime_get();
++}
++
+ static void perf_show(const char *name)
+ {
+ ktime_t t, setup_time, trans_time;
+ u32 total_bytes;
+ u32 setup_us, trans_us, total_us;
+- const int numframes = 100;
+- static u32 s_trans_us, s_min_us = 0xffffffff, s_max_us;
+
+ if (!dsi_perf)
+ return;
+@@ -393,34 +397,57 @@ static void perf_show(const char *name)
+ dsi.update_region.bytespp;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
++ static u32 s_total_trans_us, s_total_setup_us;
++ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
++ static u32 s_max_trans_us, s_max_setup_us;
++ const int numframes = 100;
++ ktime_t total_time_auto;
++ u32 total_time_auto_us;
++
+ dsi.perf_measure_frames++;
+
+- if (trans_us < s_min_us)
+- s_min_us = trans_us;
++ if (setup_us < s_min_setup_us)
++ s_min_setup_us = setup_us;
++
++ if (setup_us > s_max_setup_us)
++ s_max_setup_us = setup_us;
+
+- if (trans_us > s_max_us)
+- s_max_us = trans_us;
++ s_total_setup_us += setup_us;
+
+- s_trans_us += trans_us;
++ if (trans_us < s_min_trans_us)
++ s_min_trans_us = trans_us;
++
++ if (trans_us > s_max_trans_us)
++ s_max_trans_us = trans_us;
++
++ s_total_trans_us += trans_us;
+
+ if (dsi.perf_measure_frames < numframes)
+ return;
+
+- DSSINFO("%s update: %d frames in %u us "
+- "(min/max/avg %u/%u/%u), %u fps\n",
+- name, numframes,
+- s_trans_us,
+- s_min_us,
+- s_max_us,
+- s_trans_us / numframes,
+- 1000*1000 / (s_trans_us / numframes));
++ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
++ total_time_auto_us = (u32)ktime_to_us(total_time_auto);
++
++ printk("DSI(%s): %u fps, setup %u/%u/%u, trans %u/%u/%u\n",
++ name,
++ 1000 * 1000 * numframes / total_time_auto_us,
++ s_min_setup_us,
++ s_max_setup_us,
++ s_total_setup_us / numframes,
++ s_min_trans_us,
++ s_max_trans_us,
++ s_total_trans_us / numframes);
+
+ dsi.perf_measure_frames = 0;
+- s_trans_us = 0;
+- s_min_us = 0xffffffff;
+- s_max_us = 0;
++ s_total_setup_us = 0;
++ s_min_setup_us = 0xffffffff;
++ s_max_setup_us = 0;
++ s_total_trans_us = 0;
++ s_min_trans_us = 0xffffffff;
++ s_max_trans_us = 0;
++ perf_mark_start_auto();
+ } else {
+- DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
++ printk("DSI(%s): %u us + %u us = %u us (%uHz), %u bytes, "
+ "%u kbytes/sec\n",
+ name,
+ setup_us,
+@@ -2814,6 +2841,8 @@ static void dsi_start_auto_update(struct omap_display *display)
+ dsi.autoupdate_setup = 1;
+
+ dsi_push_autoupdate(display);
++
++ perf_mark_start_auto();
+ }
+
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0069-DSS2-DSI-Add-support-for-external-TE-signal.patch b/recipes/linux/linux-omap-pm/dss2/0069-DSS2-DSI-Add-support-for-external-TE-signal.patch
new file mode 100644
index 0000000000..e32f8ad04a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0069-DSS2-DSI-Add-support-for-external-TE-signal.patch
@@ -0,0 +1,110 @@
+From da9828702ab1cf29401f9a93f1e950505bfa2b76 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 22 May 2009 13:43:26 +0300
+Subject: [PATCH 069/146] DSS2: DSI: Add support for external TE signal
+
+I hope this can be removed when the DSI displays work properly.
+---
+ arch/arm/plat-omap/include/mach/display.h | 4 ++++
+ drivers/video/omap2/dss/dsi.c | 29 +++++++++++++++++++----------
+ 2 files changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 31ebb96..dccc660 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -201,6 +201,9 @@ struct omap_dss_display_config {
+ u8 data2_lane;
+ u8 data2_pol;
+ unsigned long ddr_clk_hz;
++
++ bool ext_te;
++ u8 ext_te_gpio;
+ } dsi;
+
+ struct {
+@@ -256,6 +259,7 @@ struct omap_ctrl {
+ u16 x, u16 y, u16 w, u16 h);
+
+ int (*enable_te)(struct omap_display *display, bool enable);
++ int (*wait_for_te)(struct omap_display *display);
+
+ u8 (*get_rotate)(struct omap_display *display);
+ int (*set_rotate)(struct omap_display *display, u8 rotate);
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 057b057..f39c890 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -274,7 +274,8 @@ static struct
+ enum omap_dss_update_mode user_update_mode;
+ enum omap_dss_update_mode target_update_mode;
+ enum omap_dss_update_mode update_mode;
+- int use_te;
++ bool use_te;
++ bool use_ext_te;
+ int framedone_scheduled; /* helps to catch strange framedone bugs */
+
+ unsigned long cache_req_pck;
+@@ -2734,6 +2735,9 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+
+ display->ctrl->setup_update(display, x, y, w, h);
+
++ if (dsi.use_ext_te && display->ctrl->wait_for_te)
++ display->ctrl->wait_for_te(display);
++
+ if (0)
+ dsi_vc_print_status(1);
+
+@@ -3001,19 +3005,24 @@ end:
+
+ static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
+ {
+- dsi.use_te = enable;
++ if (!display->hw_config.u.dsi.ext_te)
++ dsi.use_te = enable;
++ else
++ dsi.use_ext_te = enable;
+
+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ display->ctrl->enable_te(display, enable);
+
+- if (enable) {
+- /* disable LP_RX_TO, so that we can receive TE.
+- * Time to wait for TE is longer than the timer allows */
+- REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+- } else {
+- REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++ if (!display->hw_config.u.dsi.ext_te) {
++ if (enable) {
++ /* disable LP_RX_TO, so that we can receive TE.
++ * Time to wait for TE is longer than the timer allows */
++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
++ } else {
++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++ }
+ }
+ }
+
+@@ -3508,7 +3517,7 @@ static int dsi_display_enable(struct omap_display *display)
+
+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+- if (dsi.use_te)
++ if (dsi.use_te || dsi.use_ext_te)
+ dsi_push_set_te(display, 1);
+
+ dsi_push_set_update_mode(display, dsi.user_update_mode);
+@@ -3641,7 +3650,7 @@ static int dsi_display_enable_te(struct omap_display *display, bool enable)
+
+ static int dsi_display_get_te(struct omap_display *display)
+ {
+- return dsi.use_te;
++ return dsi.use_te | dsi.use_ext_te;
+ }
+
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0070-DSS2-DSI-Fix-LP-clock.patch b/recipes/linux/linux-omap-pm/dss2/0070-DSS2-DSI-Fix-LP-clock.patch
new file mode 100644
index 0000000000..a5267c816f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0070-DSS2-DSI-Fix-LP-clock.patch
@@ -0,0 +1,78 @@
+From 8f6e8ec77ffe7b13623046648cdeea33d836169c Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 22 May 2009 14:14:23 +0300
+Subject: [PATCH 070/146] DSS2: DSI: Fix LP clock
+
+Outgoing LP clock is actually DSI fclk / 2 / clk_divisor.
+
+Also don't use hardcoded LP clock frequency, but get it from
+the board file.
+---
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/dsi.c | 18 +++++++++---------
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index dccc660..5ac1ae7 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -200,6 +200,7 @@ struct omap_dss_display_config {
+ u8 data1_pol;
+ u8 data2_lane;
+ u8 data2_pol;
++ unsigned long lp_clk_hz;
+ unsigned long ddr_clk_hz;
+
+ bool ext_te;
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index f39c890..c45140f 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -763,19 +763,19 @@ static unsigned long dsi_fclk_rate(void)
+ return r;
+ }
+
+-static int dsi_set_lp_clk_divisor(void)
++static int dsi_set_lp_clk_divisor(struct omap_display *display)
+ {
+- int n;
++ unsigned n;
+ unsigned long dsi_fclk;
+- unsigned long mhz;
+-
+- /* LP_CLK_DIVISOR, DSI fclk/n, should be 20MHz - 32kHz */
++ unsigned long lp_clk, lp_clk_req;
+
+ dsi_fclk = dsi_fclk_rate();
+
++ lp_clk_req = display->hw_config.u.dsi.lp_clk_hz;
++
+ for (n = 1; n < (1 << 13) - 1; ++n) {
+- mhz = dsi_fclk / n;
+- if (mhz <= 20*1000*1000)
++ lp_clk = dsi_fclk / 2 / n;
++ if (lp_clk <= lp_clk_req)
+ break;
+ }
+
+@@ -784,7 +784,7 @@ static int dsi_set_lp_clk_divisor(void)
+ return -EINVAL;
+ }
+
+- DSSDBG("LP_CLK_DIV %d, LP_CLK %ld\n", n, mhz);
++ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
+
+ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
+ if (dsi_fclk > 30*1000*1000)
+@@ -3413,7 +3413,7 @@ static int dsi_display_init_dsi(struct omap_display *display)
+ _dsi_print_reset_status();
+
+ dsi_proto_timings(display);
+- dsi_set_lp_clk_divisor();
++ dsi_set_lp_clk_divisor(display);
+
+ if (1)
+ _dsi_print_reset_status();
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0071-DSS2-Do-not-swap-xres-yres-or-change-rotation-in-ch.patch b/recipes/linux/linux-omap-pm/dss2/0071-DSS2-Do-not-swap-xres-yres-or-change-rotation-in-ch.patch
new file mode 100644
index 0000000000..fb5a8213d3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0071-DSS2-Do-not-swap-xres-yres-or-change-rotation-in-ch.patch
@@ -0,0 +1,68 @@
+From cff6ff96f2b280924e7a2bb453bc8d6d9bbb67f0 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Thu, 14 May 2009 15:03:48 +0200
+Subject: [PATCH 071/146] DSS2: Do not swap xres/yres or change rotation in check_fb_var()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Do not to change the actual rotation setting in check_fb_var() and
+also remove the xres/yres swap from the same place. Applications must
+now specify var.xres and var.yres in framebuffer coordinates. Eg. if
+you have a 480x800 framebuffer and want it rotated cw/ccw to a 800x480
+display xres must be 480 and yres must be 800. So the application
+doesn't have to know if it's dealing with a 480x800 unrotated display
+or a 800x480 rotated display.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 26 ++++++--------------------
+ 1 files changed, 6 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 4bb74b7..0cdf36e 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -391,6 +391,12 @@ void set_fb_fix(struct fb_info *fbi)
+ /* used by open/write in fbmem.c */
+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
++ if (ofbi->rotation != var->rotate) {
++ DBG("changing rotation %d -> %d\n",
++ ofbi->rotation, var->rotate);
++ ofbi->rotation = var->rotate;
++ }
++
+ /* used by mmap in fbmem.c */
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ switch (var->nonstd) {
+@@ -482,26 +488,6 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+ if (var->rotate < 0 || var->rotate > 3)
+ return -EINVAL;
+
+- if (var->rotate != fbi->var.rotate) {
+- DBG("rotation changing\n");
+-
+- ofbi->rotation = var->rotate;
+-
+- if (abs(var->rotate - fbi->var.rotate) != 2) {
+- int tmp;
+- DBG("rotate changing 90/270 degrees. "
+- "swapping x/y res\n");
+-
+- tmp = var->yres;
+- var->yres = var->xres;
+- var->xres = tmp;
+-
+- tmp = var->yres_virtual;
+- var->yres_virtual = var->xres_virtual;
+- var->xres_virtual = tmp;
+- }
+- }
+-
+ xres_min = OMAPFB_PLANE_XRES_MIN;
+ xres_max = 2048;
+ yres_min = OMAPFB_PLANE_YRES_MIN;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0072-DSS2-Allow-independent-rotation-for-each-plane.patch b/recipes/linux/linux-omap-pm/dss2/0072-DSS2-Allow-independent-rotation-for-each-plane.patch
new file mode 100644
index 0000000000..4fccaa65d1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0072-DSS2-Allow-independent-rotation-for-each-plane.patch
@@ -0,0 +1,277 @@
+From d2bb6e5832085247afc9a925ce2c4fc76a84db0e Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Thu, 14 May 2009 15:03:50 +0200
+Subject: [PATCH 072/146] DSS2: Allow independent rotation for each plane
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Allow overlays attached to the same framebuffer to have different
+rotation settings. A new sysfs file overlays_rotate can be used to
+configure the rotation settings for each overlay. The total rotation
+for a single overlay is now '(var.rotate + overlays_rotate) % 4'.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 42 ++++++++-----
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 91 ++++++++++++++++++++++++++++-
+ drivers/video/omap2/omapfb/omapfb.h | 2 +-
+ 3 files changed, 115 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 0cdf36e..c4bd081 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -174,11 +174,11 @@ static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
+ return offset;
+ }
+
+-static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
++static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
+ {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+- return ofbi->region.vrfb.paddr[ofbi->rotation]
+- + omapfb_get_vrfb_offset(ofbi, ofbi->rotation);
++ return ofbi->region.vrfb.paddr[rot]
++ + omapfb_get_vrfb_offset(ofbi, rot);
+ } else {
+ return ofbi->region.paddr;
+ }
+@@ -391,11 +391,7 @@ void set_fb_fix(struct fb_info *fbi)
+ /* used by open/write in fbmem.c */
+ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
+- if (ofbi->rotation != var->rotate) {
+- DBG("changing rotation %d -> %d\n",
+- ofbi->rotation, var->rotate);
+- ofbi->rotation = var->rotate;
+- }
++ DBG("changing rotation to %d\n", var->rotate);
+
+ /* used by mmap in fbmem.c */
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+@@ -665,11 +661,21 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ int xres, yres;
+ int screen_width;
+ int mirror;
++ int rotation = var->rotate;
++ int i;
++
++ for (i = 0; i < ofbi->num_overlays; i++) {
++ if (ovl != ofbi->overlays[i])
++ continue;
++
++ rotation = (rotation + ofbi->rotation[i]) % 4;
++ break;
++ }
+
+ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
+ posx, posy, outw, outh);
+
+- if (ofbi->rotation == FB_ROTATE_CW || ofbi->rotation == FB_ROTATE_CCW) {
++ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
+ xres = var->yres;
+ yres = var->xres;
+ } else {
+@@ -681,7 +687,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ var->xoffset) * var->bits_per_pixel) >> 3;
+
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+- data_start_p = omapfb_get_region_rot_paddr(ofbi);
++ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+ data_start_v = NULL;
+ } else {
+ data_start_p = omapfb_get_region_paddr(ofbi);
+@@ -726,7 +732,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+ info.height = yres;
+ info.color_mode = mode;
+ info.rotation_type = ofbi->rotation_type;
+- info.rotation = ofbi->rotation;
++ info.rotation = rotation;
+ info.mirror = mirror;
+
+ info.pos_x = posx;
+@@ -777,8 +783,9 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
+ }
+
+ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+- if (ofbi->rotation == FB_ROTATE_CW ||
+- ofbi->rotation == FB_ROTATE_CCW) {
++ int rotation = (var->rotate + ofbi->rotation[i]) % 4;
++ if (rotation == FB_ROTATE_CW ||
++ rotation == FB_ROTATE_CCW) {
+ outw = var->yres;
+ outh = var->xres;
+ } else {
+@@ -1575,7 +1582,7 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ var->nonstd = 0;
+ var->bits_per_pixel = 0;
+
+- var->rotate = ofbi->rotation;
++ var->rotate = def_rotate;
+
+ /*
+ * Check if there is a default color format set in the board file,
+@@ -1605,10 +1612,12 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+
+ if (display) {
+ u16 w, h;
++ int rotation = (var->rotate + ofbi->rotation[0]) % 4;
++
+ display->get_resolution(display, &w, &h);
+
+- if (ofbi->rotation == FB_ROTATE_CW ||
+- ofbi->rotation == FB_ROTATE_CCW) {
++ if (rotation == FB_ROTATE_CW ||
++ rotation == FB_ROTATE_CCW) {
+ var->xres = h;
+ var->yres = w;
+ } else {
+@@ -1724,7 +1733,6 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+ /* assign these early, so that fb alloc can use them */
+ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
+ OMAP_DSS_ROT_DMA;
+- ofbi->rotation = def_rotate;
+ ofbi->mirror = def_mirror;
+
+ fbdev->num_fbs++;
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 702199d..dcec42b 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -259,8 +259,10 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+ if (ovl->manager)
+ ovl->manager->apply(ovl->manager);
+
+- for (t = i + 1; t < ofbi->num_overlays; t++)
++ for (t = i + 1; t < ofbi->num_overlays; t++) {
++ ofbi->rotation[t-1] = ofbi->rotation[t];
+ ofbi->overlays[t-1] = ofbi->overlays[t];
++ }
+
+ ofbi->num_overlays--;
+ i--;
+@@ -282,7 +284,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+
+ if (found)
+ continue;
+-
++ ofbi->rotation[ofbi->num_overlays] = 0;
+ ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+ added = true;
+@@ -301,6 +303,90 @@ out:
+ return r;
+ }
+
++static ssize_t show_overlays_rotate(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ ssize_t l = 0;
++ int t;
++
++ for (t = 0; t < ofbi->num_overlays; t++) {
++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
++ t == 0 ? "" : ",", ofbi->rotation[t]);
++ }
++
++ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
++
++ return l;
++}
++
++static ssize_t store_overlays_rotate(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *fbi = dev_get_drvdata(dev);
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ struct omapfb2_device *fbdev = ofbi->fbdev;
++ int num_ovls = 0, r, i;
++ int len;
++ bool changed = false;
++ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
++
++ len = strlen(buf);
++ if (buf[len - 1] == '\n')
++ len = len - 1;
++
++ omapfb_lock(fbdev);
++
++ if (len > 0) {
++ char *p = (char *)buf;
++
++ while (p < buf + len) {
++ int rot;
++
++ if (num_ovls == ofbi->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ rot = simple_strtoul(p, &p, 0);
++ if (rot < 0 || rot > 3) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ if (ofbi->rotation[num_ovls] != rot)
++ changed = true;
++
++ rotation[num_ovls++] = rot;
++
++ p++;
++ }
++ }
++
++ if (num_ovls != ofbi->num_overlays) {
++ r = -EINVAL;
++ goto out;
++ }
++
++ if (changed) {
++ for (i = 0; i < num_ovls; ++i)
++ ofbi->rotation[i] = rotation[i];
++
++ r = omapfb_apply_changes(fbi, 0);
++ if (r)
++ goto out;
++
++ /* FIXME error handling? */
++ }
++
++ r = count;
++out:
++ omapfb_unlock(fbdev);
++
++ return r;
++}
++
+ static ssize_t show_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -369,6 +455,7 @@ static struct device_attribute omapfb_attrs[] = {
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
++ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, store_overlays_rotate),
+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+ };
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+index 43f6922..f40fcce 100644
+--- a/drivers/video/omap2/omapfb/omapfb.h
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -62,7 +62,7 @@ struct omapfb_info {
+ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
+ struct omapfb2_device *fbdev;
+ enum omap_dss_rotation_type rotation_type;
+- u8 rotation;
++ u8 rotation[OMAPFB_MAX_OVL_PER_FB];
+ bool mirror;
+ };
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0073-DSS2-DISPC-fix-irq-handling-locking.patch b/recipes/linux/linux-omap-pm/dss2/0073-DSS2-DISPC-fix-irq-handling-locking.patch
new file mode 100644
index 0000000000..e68f6458a0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0073-DSS2-DISPC-fix-irq-handling-locking.patch
@@ -0,0 +1,225 @@
+From a4df82191832d6b384da9b6a07328ac404db9393 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Sat, 23 May 2009 18:00:21 +0300
+Subject: [PATCH 073/146] DSS2: DISPC: fix irq handling locking
+
+---
+ drivers/video/omap2/dss/dispc.c | 74 +++++++++++++++++++++++---------------
+ 1 files changed, 45 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b0e4960..b3685b2 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -154,23 +154,20 @@ static struct {
+
+ struct clk *dpll4_m4_ck;
+
+- spinlock_t irq_lock;
+-
+ unsigned long cache_req_pck;
+ unsigned long cache_prate;
+ struct dispc_clock_info cache_cinfo;
+
+- u32 irq_error_mask;
++ spinlock_t irq_lock;
++ u32 irq_error_mask;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+-
+- spinlock_t error_lock;
+ u32 error_irqs;
+ struct work_struct error_work;
+
+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+ } dispc;
+
+-static void omap_dispc_set_irqs(void);
++static void _omap_dispc_set_irqs(void);
+
+ static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
+ {
+@@ -1691,10 +1688,13 @@ void dispc_enable_digit_out(bool enable)
+ }
+
+ if (enable) {
++ unsigned long flags;
+ /* When we enable digit output, we'll get an extra digit
+ * sync lost interrupt, that we need to ignore */
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ /* When we disable digit output, we need to wait until fields are done.
+@@ -1728,9 +1728,12 @@ void dispc_enable_digit_out(bool enable)
+ DSSERR("failed to unregister EVSYNC isr\n");
+
+ if (enable) {
++ unsigned long flags;
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ enable_clocks(0);
+@@ -2508,14 +2511,14 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+ return 0;
+ }
+
+-static void omap_dispc_set_irqs(void)
++/* dispc.irq_lock has to be locked by the caller */
++static void _omap_dispc_set_irqs(void)
+ {
+- unsigned long flags;
+- u32 mask = dispc.irq_error_mask;
++ u32 mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+- spin_lock_irqsave(&dispc.irq_lock, flags);
++ mask = dispc.irq_error_mask;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+@@ -2528,9 +2531,8 @@ static void omap_dispc_set_irqs(void)
+
+ enable_clocks(1);
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+- enable_clocks(0);
+
+- spin_unlock_irqrestore(&dispc.irq_lock, flags);
++ enable_clocks(0);
+ }
+
+ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+@@ -2571,11 +2573,14 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+
+ break;
+ }
+-err:
++
++ _omap_dispc_set_irqs();
++
+ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+- if (ret == 0)
+- omap_dispc_set_irqs();
++ return 0;
++err:
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+ }
+@@ -2606,10 +2611,10 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+ break;
+ }
+
+- spin_unlock_irqrestore(&dispc.irq_lock, flags);
+-
+ if (ret == 0)
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ return ret;
+ }
+@@ -2645,11 +2650,15 @@ static void print_irq_status(u32 status)
+ void dispc_irq_handler(void)
+ {
+ int i;
+- u32 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++ u32 irqstatus;
+ u32 handledirqs = 0;
+ u32 unhandled_errors;
+ struct omap_dispc_isr_data *isr_data;
+
++ spin_lock(&dispc.irq_lock);
++
++ irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
++
+ #ifdef DEBUG
+ if (dss_debug)
+ print_irq_status(irqstatus);
+@@ -2673,15 +2682,15 @@ void dispc_irq_handler(void)
+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
+
+ if (unhandled_errors) {
+- spin_lock(&dispc.error_lock);
+ dispc.error_irqs |= unhandled_errors;
+- spin_unlock(&dispc.error_lock);
+
+ dispc.irq_error_mask &= ~unhandled_errors;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
+
+ schedule_work(&dispc.error_work);
+ }
++
++ spin_unlock(&dispc.irq_lock);
+ }
+
+ static void dispc_error_worker(struct work_struct *work)
+@@ -2690,10 +2699,10 @@ static void dispc_error_worker(struct work_struct *work)
+ u32 errors;
+ unsigned long flags;
+
+- spin_lock_irqsave(&dispc.error_lock, flags);
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ errors = dispc.error_irqs;
+ dispc.error_irqs = 0;
+- spin_unlock_irqrestore(&dispc.error_lock, flags);
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
+ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
+@@ -2836,8 +2845,10 @@ static void dispc_error_worker(struct work_struct *work)
+ }
+ }
+
++ spin_lock_irqsave(&dispc.irq_lock, flags);
+ dispc.irq_error_mask |= errors;
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
+@@ -2921,6 +2932,10 @@ void dispc_fake_vsync_irq(void)
+
+ static void _omap_dispc_initialize_irq(void)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc.irq_lock, flags);
++
+ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
+
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+@@ -2929,7 +2944,9 @@ static void _omap_dispc_initialize_irq(void)
+ * so clear it */
+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+
+- omap_dispc_set_irqs();
++ _omap_dispc_set_irqs();
++
++ spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ }
+
+ void dispc_enable_sidle(void)
+@@ -2970,7 +2987,6 @@ int dispc_init(void)
+ u32 rev;
+
+ spin_lock_init(&dispc.irq_lock);
+- spin_lock_init(&dispc.error_lock);
+
+ INIT_WORK(&dispc.error_work, dispc_error_worker);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0074-DSS2-DISPC-clear-irqstatus-for-newly-enabled-irqs.patch b/recipes/linux/linux-omap-pm/dss2/0074-DSS2-DISPC-clear-irqstatus-for-newly-enabled-irqs.patch
new file mode 100644
index 0000000000..fed108627a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0074-DSS2-DISPC-clear-irqstatus-for-newly-enabled-irqs.patch
@@ -0,0 +1,39 @@
+From c6aecc828455ea996ae1804f166581b6d0040e84 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Sat, 23 May 2009 18:00:00 +0300
+Subject: [PATCH 074/146] DSS2: DISPC: clear irqstatus for newly enabled irqs
+
+This fixes the problem that when requesting a new irq
+we could get the isr called too early in case irqstatus
+already had that irq flag on.
+---
+ drivers/video/omap2/dss/dispc.c | 6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index b3685b2..2471cfe 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2515,6 +2515,7 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+ static void _omap_dispc_set_irqs(void)
+ {
+ u32 mask;
++ u32 old_mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+@@ -2530,6 +2531,11 @@ static void _omap_dispc_set_irqs(void)
+ }
+
+ enable_clocks(1);
++
++ old_mask = dispc_read_reg(DISPC_IRQENABLE);
++ /* clear the irqstatus for newly enabled irqs */
++ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
++
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+
+ enable_clocks(0);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0075-DSS2-Add-WSS-support.patch b/recipes/linux/linux-omap-pm/dss2/0075-DSS2-Add-WSS-support.patch
new file mode 100644
index 0000000000..0f9c28a49f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0075-DSS2-Add-WSS-support.patch
@@ -0,0 +1,172 @@
+From 3b453993217ece5b38170727e8240869c12b89ea Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 22 May 2009 17:23:56 +0200
+Subject: [PATCH 075/146] DSS2: Add WSS support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Add support for setting the widescreen signalling (WSS) data via sysfs.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 3 ++
+ drivers/video/omap2/dss/display.c | 36 +++++++++++++++++++++++++++
+ drivers/video/omap2/dss/venc.c | 38 ++++++++++++++++++++++++++++-
+ 3 files changed, 76 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 5ac1ae7..2031dd5 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -514,6 +514,9 @@ struct omap_display {
+ u16 x, u16 y, u16 w, u16 h);
+
+ void (*configure_overlay)(struct omap_overlay *overlay);
++
++ int (*set_wss)(struct omap_display *display, u32 wss);
++ u32 (*get_wss)(struct omap_display *display);
+ };
+
+ int omap_dss_get_num_displays(void);
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 9aaf392..50ced29 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -239,6 +239,39 @@ struct display_attribute {
+ ssize_t (*store)(struct omap_display *, const char *, size_t);
+ };
+
++static ssize_t display_wss_show(struct omap_display *display, char *buf)
++{
++ unsigned int wss;
++
++ if (!display->get_wss)
++ return -ENOENT;
++
++ wss = display->get_wss(display);
++
++ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
++}
++
++static ssize_t display_wss_store(struct omap_display *display,
++ const char *buf, size_t size)
++{
++ unsigned long wss;
++ int r;
++
++ if (!display->get_wss || !display->set_wss)
++ return -ENOENT;
++
++ if (strict_strtoul(buf, 0, &wss))
++ return -EINVAL;
++
++ if (wss > 0xfffff)
++ return -EINVAL;
++
++ if ((r = display->set_wss(display, wss)))
++ return r;
++
++ return size;
++}
++
+ #define DISPLAY_ATTR(_name, _mode, _show, _store) \
+ struct display_attribute display_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+@@ -258,6 +291,8 @@ static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
+ display_mirror_show, display_mirror_store);
+ static DISPLAY_ATTR(panel_name, S_IRUGO, display_panel_name_show, NULL);
+ static DISPLAY_ATTR(ctrl_name, S_IRUGO, display_ctrl_name_show, NULL);
++static DISPLAY_ATTR(wss, S_IRUGO|S_IWUSR,
++ display_wss_show, display_wss_store);
+
+ static struct attribute *display_sysfs_attrs[] = {
+ &display_attr_name.attr,
+@@ -269,6 +304,7 @@ static struct attribute *display_sysfs_attrs[] = {
+ &display_attr_mirror.attr,
+ &display_attr_panel_name.attr,
+ &display_attr_ctrl_name.attr,
++ &display_attr_wss.attr,
+ NULL
+ };
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index b655df4..0cbba9f 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -289,6 +289,7 @@ EXPORT_SYMBOL(omap_dss_ntsc_timings);
+ static struct {
+ void __iomem *base;
+ struct mutex venc_lock;
++ u32 wss_data;
+ } venc;
+
+ static struct omap_panel venc_panel = {
+@@ -320,7 +321,7 @@ static void venc_write_config(const struct venc_config *config)
+ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
+ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
+ venc_write_reg(VENC_M_CONTROL, config->m_control);
+- venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data);
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | venc.wss_data);
+ venc_write_reg(VENC_S_CARR, config->s_carr);
+ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
+ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
+@@ -482,6 +483,8 @@ static int venc_enable_display(struct omap_display *display)
+ goto err;
+ }
+
++ venc.wss_data = 0;
++
+ venc_power_on(display);
+
+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
+@@ -589,6 +592,37 @@ static int venc_check_timings(struct omap_display *display,
+ return -EINVAL;
+ }
+
++static u32 venc_get_wss(struct omap_display *display)
++{
++ /* Invert due to VENC_L21_WC_CTL:INV=1 */
++ return (venc.wss_data >> 8) ^ 0xfffff;
++}
++
++static int venc_set_wss(struct omap_display *display,
++ u32 wss)
++{
++ const struct venc_config *config;
++
++ DSSDBG("venc_set_wss\n");
++
++ mutex_lock(&venc.venc_lock);
++
++ config = venc_timings_to_config(&display->panel->timings);
++
++ /* Invert due to VENC_L21_WC_CTL:INV=1 */
++ venc.wss_data = (wss ^ 0xfffff) << 8;
++
++ venc_enable_clocks(1);
++
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | venc.wss_data);
++
++ venc_enable_clocks(0);
++
++ mutex_unlock(&venc.venc_lock);
++
++ return 0;
++}
++
+ void venc_init_display(struct omap_display *display)
+ {
+ display->panel = &venc_panel;
+@@ -599,6 +633,8 @@ void venc_init_display(struct omap_display *display)
+ display->get_timings = venc_get_timings;
+ display->set_timings = venc_set_timings;
+ display->check_timings = venc_check_timings;
++ display->get_wss = venc_get_wss;
++ display->set_wss = venc_set_wss;
+ }
+
+ void venc_dump_regs(struct seq_file *s)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0076-DSS2-Fix-PAL-NTSC-timings.patch b/recipes/linux/linux-omap-pm/dss2/0076-DSS2-Fix-PAL-NTSC-timings.patch
new file mode 100644
index 0000000000..28ae3ec5ac
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0076-DSS2-Fix-PAL-NTSC-timings.patch
@@ -0,0 +1,68 @@
+From f41bc6591494db0698b5f0f6bcf01ee6050c732f Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 22 May 2009 17:23:57 +0200
+Subject: [PATCH 076/146] DSS2: Fix PAL/NTSC timings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Fix the PAL/NTSC video timings. Only some of these values are actually
+specified for digital video, the rest were calculated based on the the
+analog timings. The analog timings differ from the digital timings
+anyway but these should be close to the truth. These values aren't
+actually needed by the VENC but it doesn't hurt to make them a bit more
+accurate.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/venc.c | 28 ++++++++++++++--------------
+ 1 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index 0cbba9f..02286b8 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -263,26 +263,26 @@ static const struct venc_config venc_config_pal_bdghi = {
+ const struct omap_video_timings omap_dss_pal_timings = {
+ .x_res = 720,
+ .y_res = 574,
+- .pixel_clock = 26181,
+- .hsw = 32,
+- .hfp = 80,
+- .hbp = 48,
+- .vsw = 7,
+- .vfp = 3,
+- .vbp = 6,
++ .pixel_clock = 13500,
++ .hsw = 64,
++ .hfp = 12,
++ .hbp = 68,
++ .vsw = 5,
++ .vfp = 5,
++ .vbp = 41,
+ };
+ EXPORT_SYMBOL(omap_dss_pal_timings);
+
+ const struct omap_video_timings omap_dss_ntsc_timings = {
+ .x_res = 720,
+ .y_res = 482,
+- .pixel_clock = 22153,
+- .hsw = 32,
+- .hfp = 80,
+- .hbp = 48,
+- .vsw = 10,
+- .vfp = 3,
+- .vbp = 6,
++ .pixel_clock = 13500,
++ .hsw = 64,
++ .hfp = 16,
++ .hbp = 58,
++ .vsw = 6,
++ .vfp = 6,
++ .vbp = 31,
+ };
+ EXPORT_SYMBOL(omap_dss_ntsc_timings);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0077-DSS2-Add-venc-debugfs-file.patch b/recipes/linux/linux-omap-pm/dss2/0077-DSS2-Add-venc-debugfs-file.patch
new file mode 100644
index 0000000000..713c72533e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0077-DSS2-Add-venc-debugfs-file.patch
@@ -0,0 +1,34 @@
+From d0d9b920dcf074ca854f11a9bb80d3a7fcf83b97 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Fri, 22 May 2009 17:23:58 +0200
+Subject: [PATCH 077/146] DSS2: Add venc debugfs file
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Actually make the venc register dump file visible in debugfs. Somehow
+this hunk got dropped when the venc debugfs file was originally added.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/core.c | 4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index 6d11b04..2a38507 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -396,6 +396,10 @@ static int dss_initialize_debugfs(void)
+ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
+ &dsi_dump_regs, &dss_debug_fops);
+ #endif
++#ifdef CONFIG_OMAP2_DSS_VENC
++ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
++ &venc_dump_regs, &dss_debug_fops);
++#endif
+ return 0;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0078-DSS2-Enable-replication-logic-feature.patch b/recipes/linux/linux-omap-pm/dss2/0078-DSS2-Enable-replication-logic-feature.patch
new file mode 100644
index 0000000000..ac502112fd
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0078-DSS2-Enable-replication-logic-feature.patch
@@ -0,0 +1,138 @@
+From 8d239b2c7f05acf2f732d292f5d7c5abc3c7ce1a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 26 May 2009 10:49:24 +0300
+Subject: [PATCH 078/146] DSS2: Enable replication logic feature
+
+Replication logic will make colors a bit better on active matrix LCD
+when the fb is in 16bpp mode and the LCD interface is 18/24bpp.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 19 +++++++++++++++++++
+ drivers/video/omap2/dss/display.c | 34 ++++++++++++++++++++++++++++++++++
+ drivers/video/omap2/dss/dss.h | 3 +++
+ drivers/video/omap2/dss/manager.c | 5 +++++
+ 4 files changed, 61 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 2471cfe..e936c59 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -908,6 +908,20 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
+ dispc_write_reg(dispc_reg_att[plane], val);
+ }
+
++void dispc_enable_replication(enum omap_plane plane, bool enable)
++{
++ int bit;
++
++ if (plane == OMAP_DSS_GFX)
++ bit = 5;
++ else
++ bit = 10;
++
++ enable_clocks(1);
++ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
++ enable_clocks(0);
++}
++
+ void dispc_set_lcd_size(u16 width, u16 height)
+ {
+ u32 val;
+@@ -3293,6 +3307,11 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ pi->mirror,
+ pi->global_alpha);
+
++ if (dss_use_replication(display, ovl->info.color_mode))
++ dispc_enable_replication(ovl->id, true);
++ else
++ dispc_enable_replication(ovl->id, false);
++
+ dispc_enable_plane(ovl->id, 1);
+ }
+
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 50ced29..77a6dc4 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -411,6 +411,40 @@ static int default_get_recommended_bpp(struct omap_display *display)
+ }
+ }
+
++/* Checks if replication logic should be used. Only use for active matrix,
++ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
++ * 18bpp or 24bpp */
++bool dss_use_replication(struct omap_display *display,
++ enum omap_color_mode mode)
++{
++ int bpp;
++
++ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
++ return false;
++
++ if (display->type == OMAP_DISPLAY_TYPE_DPI &&
++ (display->panel->config & OMAP_DSS_LCD_TFT) == 0)
++ return false;
++
++ switch (display->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ bpp = display->hw_config.u.dpi.data_lines;
++ break;
++ case OMAP_DISPLAY_TYPE_VENC:
++ case OMAP_DISPLAY_TYPE_SDI:
++ bpp = 24;
++ break;
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DSI:
++ bpp = display->ctrl->pixel_size;
++ break;
++ default:
++ BUG();
++ }
++
++ return bpp > 16;
++}
++
+ void dss_init_displays(struct platform_device *pdev)
+ {
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 20cef0a..d51ffe4 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -173,6 +173,8 @@ void dss_uninit_displays(struct platform_device *pdev);
+ int dss_suspend_all_displays(void);
+ int dss_resume_all_displays(void);
+ struct omap_display *dss_get_display(int no);
++bool dss_use_replication(struct omap_display *display,
++ enum omap_color_mode mode);
+
+ /* manager */
+ int dss_init_overlay_managers(struct platform_device *pdev);
+@@ -280,6 +282,7 @@ void dispc_go(enum omap_channel channel);
+ void dispc_enable_lcd_out(bool enable);
+ void dispc_enable_digit_out(bool enable);
+ int dispc_enable_plane(enum omap_plane plane, bool enable);
++void dispc_enable_replication(enum omap_plane plane, bool enable);
+
+ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
+ void dispc_set_tft_data_lines(u8 data_lines);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 1e6cd8d..8d5d00f 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -474,6 +474,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ continue;
+ }
+
++ if (dss_use_replication(display, ovl->info.color_mode))
++ dispc_enable_replication(ovl->id, true);
++ else
++ dispc_enable_replication(ovl->id, false);
++
+ dispc_enable_plane(ovl->id, 1);
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0079-DSS2-support-for-querying-the-supported-overlay-col.patch b/recipes/linux/linux-omap-pm/dss2/0079-DSS2-support-for-querying-the-supported-overlay-col.patch
new file mode 100644
index 0000000000..3bc96874e6
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0079-DSS2-support-for-querying-the-supported-overlay-col.patch
@@ -0,0 +1,180 @@
+From 31204dee400ffa13900eedef77ec78234a0bbbf9 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 26 May 2009 16:42:16 +0200
+Subject: [PATCH 079/146] DSS2: support for querying the supported overlay color modes
+
+Adds an IOCTL through which an application can iterate through the
+color modes supported by an overlay. Instead of a simple mode ID
+this will give the parameters needed to setup the FB, as this is what
+the application will do anyway.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 62 +++++++++++++++++++++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c | 4 +-
+ drivers/video/omap2/omapfb/omapfb.h | 2 +
+ include/linux/omapfb.h | 15 ++++++-
+ 4 files changed, 80 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 79d8916..980e3db 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -434,6 +434,52 @@ static int omapfb_memory_read(struct fb_info *fbi,
+ return r;
+ }
+
++int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
++ struct omapfb_ovl_colormode *mode)
++{
++ int ovl_idx = mode->overlay_idx;
++ int mode_idx = mode->mode_idx;
++ struct omap_overlay *ovl;
++ enum omap_color_mode supported_modes;
++ struct fb_var_screeninfo var;
++ int i;
++
++ if (ovl_idx >= fbdev->num_overlays)
++ return -ENODEV;
++ ovl = fbdev->overlays[ovl_idx];
++ supported_modes = ovl->supported_modes;
++
++ mode_idx = mode->mode_idx;
++
++ for (i = 0; i < sizeof(supported_modes) * 8; i++) {
++ if (!(supported_modes & (1 << i)))
++ continue;
++ /*
++ * It's possible that the FB doesn't support a mode
++ * that is supported by the overlay, so call the
++ * following here.
++ */
++ if (dss_mode_to_fb_mode(1 << i, &var) < 0)
++ continue;
++
++ mode_idx--;
++ if (mode_idx < 0)
++ break;
++ }
++
++ if (i == sizeof(supported_modes) * 8)
++ return -ENOENT;
++
++ mode->bits_per_pixel = var.bits_per_pixel;
++ mode->nonstd = var.nonstd;
++ mode->red = var.red;
++ mode->green = var.green;
++ mode->blue = var.blue;
++ mode->transp = var.transp;
++
++ return 0;
++}
++
+ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+@@ -447,6 +493,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ struct omapfb_caps caps;
+ struct omapfb_mem_info mem_info;
+ struct omapfb_color_key color_key;
++ struct omapfb_ovl_colormode ovl_colormode;
+ enum omapfb_update_mode update_mode;
+ int test_num;
+ struct omapfb_memory_read memory_read;
+@@ -554,6 +601,21 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ r = -EFAULT;
+ break;
+
++ case OMAPFB_GET_OVERLAY_COLORMODE:
++ DBG("ioctl GET_OVERLAY_COLORMODE\n");
++ if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
++ sizeof(p.ovl_colormode))) {
++ r = -EFAULT;
++ break;
++ }
++ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
++ if (r < 0)
++ break;
++ if (copy_to_user((void __user *)arg, &p.ovl_colormode,
++ sizeof(p.ovl_colormode)))
++ r = -EFAULT;
++ break;
++
+ case OMAPFB_SET_UPDATE_MODE:
+ DBG("ioctl SET_UPDATE_MODE\n");
+ if (get_user(p.update_mode, (int __user *)arg))
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index c4bd081..c3690b8 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -364,8 +364,8 @@ static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var)
+ return -EINVAL;
+ }
+
+-static int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+- struct fb_var_screeninfo *var)
++int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
++ struct fb_var_screeninfo *var)
+ {
+ int i;
+
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+index f40fcce..e750bc0 100644
+--- a/drivers/video/omap2/omapfb/omapfb.h
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -111,6 +111,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
+
+ int omapfb_mode_to_timings(const char *mode_str,
+ struct omap_video_timings *timings, u8 *bpp);
++int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
++ struct fb_var_screeninfo *var);
+
+ /* find the display connected to this fb, if any */
+ static inline struct omap_display *fb2display(struct fb_info *fbi)
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index 7a34f22..fd522d3 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -24,6 +24,8 @@
+ #ifndef __OMAPFB_H
+ #define __OMAPFB_H
+
++#include <linux/fb.h>
++
+ #include <asm/ioctl.h>
+ #include <asm/types.h>
+
+@@ -52,6 +54,7 @@
+ #define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info)
+ #define OMAPFB_WAITFORVSYNC OMAP_IO(57)
+ #define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
++#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
+
+ #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+ #define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+@@ -179,11 +182,21 @@ struct omapfb_memory_read {
+ void __user *buffer;
+ };
+
++struct omapfb_ovl_colormode {
++ __u8 overlay_idx;
++ __u8 mode_idx;
++ __u32 bits_per_pixel;
++ __u32 nonstd;
++ struct fb_bitfield red;
++ struct fb_bitfield green;
++ struct fb_bitfield blue;
++ struct fb_bitfield transp;
++};
++
+ #ifdef __KERNEL__
+
+ #include <linux/completion.h>
+ #include <linux/interrupt.h>
+-#include <linux/fb.h>
+ #include <linux/mutex.h>
+
+ #include <mach/board.h>
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0080-DSS2-fix-uninitialized-var-in-OMAPFB_GET_CAPS-IOCTL.patch b/recipes/linux/linux-omap-pm/dss2/0080-DSS2-fix-uninitialized-var-in-OMAPFB_GET_CAPS-IOCTL.patch
new file mode 100644
index 0000000000..4454bbae1f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0080-DSS2-fix-uninitialized-var-in-OMAPFB_GET_CAPS-IOCTL.patch
@@ -0,0 +1,26 @@
+From 5069f20f593bc6b0bdeb1913130be894a2a3d071 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@nokia.com>
+Date: Tue, 26 May 2009 16:53:46 +0200
+Subject: [PATCH 080/146] DSS2: fix uninitialized var in OMAPFB_GET_CAPS IOCTL
+
+Spotted-by: Ville Syrjala <ville.syrjala@nokia.com>
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 980e3db..123f5dc 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -595,6 +595,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ break;
+ }
+
++ memset(&p.caps, 0, sizeof(p.caps));
+ p.caps.ctrl = display->caps;
+
+ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0081-DSS2-Reset-WSS-data-only-when-changing-TV-standard.patch b/recipes/linux/linux-omap-pm/dss2/0081-DSS2-Reset-WSS-data-only-when-changing-TV-standard.patch
new file mode 100644
index 0000000000..239465729e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0081-DSS2-Reset-WSS-data-only-when-changing-TV-standard.patch
@@ -0,0 +1,54 @@
+From 6a853312fa903f4369af3ea485c86753aca556fc Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Tue, 26 May 2009 16:14:49 +0200
+Subject: [PATCH 081/146] DSS2: Reset WSS data only when changing TV standard
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Do not reset the the WSS data every time the display is enabled. Only
+reset it when the TV standard changes since PAL and NTSC use different
+WSS data layouts.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/venc.c | 9 +++++++--
+ 1 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index 02286b8..b0f0795 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -406,6 +406,8 @@ int venc_init(void)
+
+ mutex_init(&venc.venc_lock);
+
++ venc.wss_data = 0;
++
+ venc_panel.timings = omap_dss_pal_timings;
+
+ venc.base = ioremap(VENC_BASE, SZ_1K);
+@@ -483,8 +485,6 @@ static int venc_enable_display(struct omap_display *display)
+ goto err;
+ }
+
+- venc.wss_data = 0;
+-
+ venc_power_on(display);
+
+ display->state = OMAP_DSS_DISPLAY_ACTIVE;
+@@ -570,6 +570,11 @@ static void venc_set_timings(struct omap_display *display,
+ struct omap_video_timings *timings)
+ {
+ DSSDBG("venc_set_timings\n");
++
++ /* Reset WSS data when the TV standard changes. */
++ if (memcmp(&display->panel->timings, timings, sizeof(*timings)))
++ venc.wss_data = 0;
++
+ display->panel->timings = *timings;
+ if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ /* turn the venc off and on to get new timings to use */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0082-DSS2-DSI-implement-timeout-for-DSI-transfer.patch b/recipes/linux/linux-omap-pm/dss2/0082-DSS2-DSI-implement-timeout-for-DSI-transfer.patch
new file mode 100644
index 0000000000..6d211adc92
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0082-DSS2-DSI-implement-timeout-for-DSI-transfer.patch
@@ -0,0 +1,78 @@
+From d8745c631cfcbf6b91b7ffd1c228b1c27f6d1917 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 27 May 2009 12:00:20 +0300
+Subject: [PATCH 082/146] DSS2: DSI: implement timeout for DSI transfer
+
+Proper transfer shutdown is still missing.
+---
+ drivers/video/omap2/dss/dsi.c | 27 +++++++++++++++++++++++++++
+ 1 files changed, 27 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index c45140f..38d3807 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -269,6 +269,7 @@ static struct
+
+ struct work_struct framedone_work;
+ struct work_struct process_work;
++ struct delayed_work framedone_timeout_work;
+ struct workqueue_struct *workqueue;
+
+ enum omap_dss_update_mode user_update_mode;
+@@ -2756,12 +2757,34 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+
+ dispc_disable_sidle();
+
++ queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work,
++ msecs_to_jiffies(1000));
++
+ dispc_enable_lcd_out(1);
+
+ if (dsi.use_te)
+ dsi_vc_send_bta(1);
+ }
+
++static void framedone_timeout_callback(struct work_struct *work)
++{
++ DSSERR("framedone timeout\n");
++
++ dispc_enable_lcd_out(0);
++
++ /* XXX TODO: cancel the transfer properly */
++
++ /* XXX check that fifo is not full. otherwise we would sleep and never
++ * get to process_cmd_fifo below */
++ /* We check for target_update_mode, not update_mode. No reason to push
++ * new updates if we're turning auto update off */
++ if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_push_autoupdate(dsi.vc[1].display);
++
++ atomic_set(&dsi.cmd_pending, 0);
++ dsi_process_cmd_fifo(NULL);
++}
++
+ static void framedone_callback(void *data, u32 mask)
+ {
+ if (dsi.framedone_scheduled) {
+@@ -2769,6 +2792,8 @@ static void framedone_callback(void *data, u32 mask)
+ return;
+ }
+
++ cancel_delayed_work(&dsi.framedone_timeout_work);
++
+ dispc_enable_sidle();
+
+ dsi.framedone_scheduled = 1;
+@@ -3834,6 +3859,8 @@ int dsi_init(void)
+ dsi.workqueue = create_singlethread_workqueue("dsi");
+ INIT_WORK(&dsi.framedone_work, framedone_worker);
+ INIT_WORK(&dsi.process_work, dsi_process_cmd_fifo);
++ INIT_DELAYED_WORK(&dsi.framedone_timeout_work,
++ framedone_timeout_callback);
+
+ mutex_init(&dsi.lock);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0083-DSS2-DSI-reset-perf-frame-counter-when-starting-au.patch b/recipes/linux/linux-omap-pm/dss2/0083-DSS2-DSI-reset-perf-frame-counter-when-starting-au.patch
new file mode 100644
index 0000000000..e3838f0d51
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0083-DSS2-DSI-reset-perf-frame-counter-when-starting-au.patch
@@ -0,0 +1,32 @@
+From 26e96637277d8631372a14e82e43b4023b75eff7 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 27 May 2009 16:19:28 +0300
+Subject: [PATCH 083/146] DSS2: DSI: reset perf frame counter when starting autoupdate
+
+---
+ drivers/video/omap2/dss/dsi.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 38d3807..a845ea6 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -365,6 +365,7 @@ static void perf_mark_start(void)
+
+ static void perf_mark_start_auto(void)
+ {
++ dsi.perf_measure_frames = 0;
+ dsi.perf_start_time_auto = ktime_get();
+ }
+
+@@ -440,7 +441,6 @@ static void perf_show(const char *name)
+ s_max_trans_us,
+ s_total_trans_us / numframes);
+
+- dsi.perf_measure_frames = 0;
+ s_total_setup_us = 0;
+ s_min_setup_us = 0xffffffff;
+ s_max_setup_us = 0;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0084-DSS2-DSI-Implement-DSI-bus-lock.patch b/recipes/linux/linux-omap-pm/dss2/0084-DSS2-DSI-Implement-DSI-bus-lock.patch
new file mode 100644
index 0000000000..457fb19221
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0084-DSS2-DSI-Implement-DSI-bus-lock.patch
@@ -0,0 +1,265 @@
+From b666333651cbb1e60a84b6be8b9d45b3104ca804 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 27 May 2009 16:34:54 +0300
+Subject: [PATCH 084/146] DSS2: DSI: Implement DSI bus lock
+
+DSI bus lock protects the DSI bus. Normally dsi driver acquires the
+lock, but if display drivers have their own workqueues, or similar,
+they need to acquire the bus lock before sending data.
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 +
+ drivers/video/omap2/dss/dsi.c | 61 +++++++++++++++++++++++++++++
+ 2 files changed, 63 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 2031dd5..d36f730 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -169,6 +169,8 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
+ int hs_pol_inv, int vs_pol_inv, int extif_div);
+
+ /* DSI */
++void dsi_bus_lock(void);
++void dsi_bus_unlock(void);
+ int dsi_vc_dcs_write(int channel, u8 *data, int len);
+ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
+ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index a845ea6..a06fb75 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -262,6 +262,7 @@ static struct
+ } vc[4];
+
+ struct mutex lock;
++ struct mutex bus_lock;
+
+ unsigned pll_locked;
+
+@@ -339,6 +340,18 @@ void dsi_restore_context(void)
+ {
+ }
+
++void dsi_bus_lock(void)
++{
++ mutex_lock(&dsi.bus_lock);
++}
++EXPORT_SYMBOL(dsi_bus_lock);
++
++void dsi_bus_unlock(void)
++{
++ mutex_unlock(&dsi.bus_lock);
++}
++EXPORT_SYMBOL(dsi_bus_unlock);
++
+ static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
+ int value)
+ {
+@@ -1887,6 +1900,8 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type,
+ u32 val;
+ u8 data_id;
+
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
++
+ /*data_id = data_type | channel << 6; */
+ data_id = data_type | dsi.vc[channel].dest_per << 6;
+
+@@ -1978,6 +1993,8 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
+ u32 r;
+ u8 data_id;
+
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
++
+ if (dsi.debug_write)
+ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
+ channel,
+@@ -2478,6 +2495,8 @@ static int dsi_update_screen_l4(struct omap_display *display,
+
+ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
+
++ dsi_bus_lock();
++
+ display->ctrl->setup_update(display, x, y, w, h);
+
+ pixels_left = w * h;
+@@ -2514,6 +2533,7 @@ static int dsi_update_screen_l4(struct omap_display *display,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
++ dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2526,6 +2546,7 @@ static int dsi_update_screen_l4(struct omap_display *display,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
++ dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2536,6 +2557,7 @@ static int dsi_update_screen_l4(struct omap_display *display,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
++ dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2568,6 +2590,8 @@ static int dsi_update_screen_l4(struct omap_display *display,
+
+ perf_show("L4");
+
++ dsi_bus_unlock();
++
+ return 0;
+ }
+
+@@ -2734,6 +2758,8 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+ if (len % packet_payload)
+ total_len += (len % packet_payload) + 1;
+
++ dsi_bus_lock();
++
+ display->ctrl->setup_update(display, x, y, w, h);
+
+ if (dsi.use_ext_te && display->ctrl->wait_for_te)
+@@ -2774,6 +2800,12 @@ static void framedone_timeout_callback(struct work_struct *work)
+
+ /* XXX TODO: cancel the transfer properly */
+
++ dsi_bus_unlock();
++
++ /* Schedule, so that other threads that want dsi-bus-lock can get it.
++ * Otherwise with autoupdate we may be holding it all the time */
++ schedule();
++
+ /* XXX check that fifo is not full. otherwise we would sleep and never
+ * get to process_cmd_fifo below */
+ /* We check for target_update_mode, not update_mode. No reason to push
+@@ -2852,6 +2884,12 @@ static void framedone_worker(struct work_struct *work)
+ #endif
+ dsi.framedone_scheduled = 0;
+
++ dsi_bus_unlock();
++
++ /* Schedule, so that other threads that want dsi-bus-lock can get it.
++ * Otherwise with autoupdate we may be holding it all the time */
++ schedule();
++
+ /* XXX check that fifo is not full. otherwise we would sleep and never
+ * get to process_cmd_fifo below */
+ /* We check for target_update_mode, not update_mode. No reason to push
+@@ -2970,6 +3008,9 @@ static void dsi_do_cmd_mem_read(struct omap_display *display,
+ struct dsi_cmd_mem_read *mem_read)
+ {
+ int r;
++
++ dsi_bus_lock();
++
+ r = display->ctrl->memory_read(display,
+ mem_read->buf,
+ mem_read->size,
+@@ -2978,6 +3019,8 @@ static void dsi_do_cmd_mem_read(struct omap_display *display,
+ mem_read->w,
+ mem_read->h);
+
++ dsi_bus_unlock();
++
+ *mem_read->ret_size = (size_t)r;
+ complete(mem_read->completion);
+ }
+@@ -2992,6 +3035,8 @@ static void dsi_do_cmd_test(struct omap_display *display,
+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
++ dsi_bus_lock();
++
+ /* run test first in low speed mode */
+ dsi_vc_enable_hs(0, 0);
+
+@@ -3022,6 +3067,8 @@ static void dsi_do_cmd_test(struct omap_display *display,
+ end:
+ dsi_vc_enable_hs(0, 1);
+
++ dsi_bus_unlock();
++
+ *test->result = r;
+ complete(test->completion);
+
+@@ -3038,7 +3085,9 @@ static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
+ if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
++ dsi_bus_lock();
+ display->ctrl->enable_te(display, enable);
++ dsi_bus_unlock();
+
+ if (!display->hw_config.u.dsi.ext_te) {
+ if (enable) {
+@@ -3148,13 +3197,17 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+ break;
+
+ case DSI_CMD_SET_ROTATE:
++ dsi_bus_lock();
+ display->ctrl->set_rotate(display, p.u.rotate);
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+ dsi.autoupdate_setup = 1;
++ dsi_bus_unlock();
+ break;
+
+ case DSI_CMD_SET_MIRROR:
++ dsi_bus_lock();
+ display->ctrl->set_mirror(display, p.u.mirror);
++ dsi_bus_unlock();
+ break;
+
+ default:
+@@ -3417,6 +3470,8 @@ static int dsi_display_init_dsi(struct omap_display *display)
+
+ _dsi_print_reset_status();
+
++ dsi_bus_lock();
++
+ r = dsi_pll_init(1, 0);
+ if (r)
+ goto err0;
+@@ -3468,6 +3523,8 @@ static int dsi_display_init_dsi(struct omap_display *display)
+ /* enable high-speed after initial config */
+ dsi_vc_enable_hs(0, 1);
+
++ dsi_bus_unlock();
++
+ return 0;
+ err4:
+ if (display->ctrl && display->ctrl->disable)
+@@ -3479,15 +3536,18 @@ err2:
+ err1:
+ dsi_pll_uninit();
+ err0:
++ dsi_bus_unlock();
+ return r;
+ }
+
+ static void dsi_display_uninit_dsi(struct omap_display *display)
+ {
++ dsi_bus_lock();
+ if (display->panel && display->panel->disable)
+ display->panel->disable(display);
+ if (display->ctrl && display->ctrl->disable)
+ display->ctrl->disable(display);
++ dsi_bus_unlock();
+
+ dsi_complexio_uninit();
+ dsi_pll_uninit();
+@@ -3863,6 +3923,7 @@ int dsi_init(void)
+ framedone_timeout_callback);
+
+ mutex_init(&dsi.lock);
++ mutex_init(&dsi.bus_lock);
+
+ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0085-DSS2-OMAPFB-omapfb_get_ovl_colormode-to-static.patch b/recipes/linux/linux-omap-pm/dss2/0085-DSS2-OMAPFB-omapfb_get_ovl_colormode-to-static.patch
new file mode 100644
index 0000000000..da0c155c2b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0085-DSS2-OMAPFB-omapfb_get_ovl_colormode-to-static.patch
@@ -0,0 +1,26 @@
+From 5e7b8aa4d0c904556af01085a82f50ad895a59d5 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 28 May 2009 15:26:08 +0300
+Subject: [PATCH 085/146] DSS2: OMAPFB: omapfb_get_ovl_colormode to static
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 123f5dc..57e6287 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -434,7 +434,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
+ return r;
+ }
+
+-int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
++static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
+ struct omapfb_ovl_colormode *mode)
+ {
+ int ovl_idx = mode->overlay_idx;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0086-DSS2-VRFB-make-vrfb_hw_context-static.patch b/recipes/linux/linux-omap-pm/dss2/0086-DSS2-VRFB-make-vrfb_hw_context-static.patch
new file mode 100644
index 0000000000..ed817f2e9a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0086-DSS2-VRFB-make-vrfb_hw_context-static.patch
@@ -0,0 +1,25 @@
+From 989ad2f5d7ce459332ecaca7e0c5ffa0e24218b9 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 1 Jun 2009 14:08:12 +0300
+Subject: [PATCH 086/146] DSS2: VRFB: make vrfb_hw_context static
+
+---
+ arch/arm/plat-omap/vrfb.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 34395c2..59ac66a 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -49,7 +49,7 @@ static unsigned long ctx_map_active;
+ * we don't need locking, since no drivers will run until after the wake-up
+ * has finished.
+ */
+-struct {
++static struct {
+ u32 physical_ba;
+ u32 control;
+ u32 size;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0087-DSS2-new-device-driver-model.patch b/recipes/linux/linux-omap-pm/dss2/0087-DSS2-new-device-driver-model.patch
new file mode 100644
index 0000000000..ecc51227f2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0087-DSS2-new-device-driver-model.patch
@@ -0,0 +1,5336 @@
+From 63614d959a4558c552a9d9aec693018fb6eece63 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 1 Jun 2009 14:15:13 +0300
+Subject: [PATCH 087/146] DSS2: new device/driver model
+
+Use better model for handling DSS devices and drivers.
+
+Remove omap_display, omap_ctrl and omap_panel structs, and add
+omap_dss_device and omap_dss_driver. DSS devices are added to DSS bus.
+
+The commit changes almost every part of DSS2, even if actual
+functionality should be changed only in few parts.
+---
+ arch/arm/plat-omap/include/mach/display.h | 400 ++++++++----------
+ drivers/video/omap2/dss/core.c | 306 +++++++++++++-
+ drivers/video/omap2/dss/dispc.c | 36 +-
+ drivers/video/omap2/dss/display.c | 654 ++++++++++++-----------------
+ drivers/video/omap2/dss/dpi.c | 150 ++++---
+ drivers/video/omap2/dss/dsi.c | 584 ++++++++++++--------------
+ drivers/video/omap2/dss/dss.h | 44 ++-
+ drivers/video/omap2/dss/manager.c | 108 +++---
+ drivers/video/omap2/dss/overlay.c | 93 ++---
+ drivers/video/omap2/dss/rfbi.c | 104 +++---
+ drivers/video/omap2/dss/sdi.c | 115 +++---
+ drivers/video/omap2/dss/venc.c | 192 ++++++---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 12 +-
+ drivers/video/omap2/omapfb/omapfb-main.c | 49 +--
+ drivers/video/omap2/omapfb/omapfb.h | 6 +-
+ 15 files changed, 1526 insertions(+), 1327 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index d36f730..57bb8ff 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -22,6 +22,7 @@
+
+ #include <linux/list.h>
+ #include <linux/kobject.h>
++#include <linux/device.h>
+ #include <asm/atomic.h>
+
+ #define DISPC_IRQ_FRAMEDONE (1 << 0)
+@@ -42,6 +43,9 @@
+ #define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
+ #define DISPC_IRQ_WAKEUP (1 << 16)
+
++struct omap_dss_device;
++struct omap_overlay_manager;
++
+ enum omap_display_type {
+ OMAP_DISPLAY_TYPE_NONE = 0,
+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
+@@ -132,9 +136,41 @@ enum omap_dss_venc_type {
+ OMAP_DSS_VENC_TYPE_SVIDEO,
+ };
+
+-struct omap_display;
+-struct omap_panel;
+-struct omap_ctrl;
++enum omap_display_caps {
++ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
++};
++
++enum omap_dss_update_mode {
++ OMAP_DSS_UPDATE_DISABLED = 0,
++ OMAP_DSS_UPDATE_AUTO,
++ OMAP_DSS_UPDATE_MANUAL,
++};
++
++enum omap_dss_display_state {
++ OMAP_DSS_DISPLAY_DISABLED = 0,
++ OMAP_DSS_DISPLAY_ACTIVE,
++ OMAP_DSS_DISPLAY_SUSPENDED,
++};
++
++/* XXX perhaps this should be removed */
++enum omap_dss_overlay_managers {
++ OMAP_DSS_OVL_MGR_LCD,
++ OMAP_DSS_OVL_MGR_TV,
++};
++
++enum omap_dss_rotation_type {
++ OMAP_DSS_ROT_DMA = 0,
++ OMAP_DSS_ROT_VRFB = 1,
++};
++
++enum omap_overlay_caps {
++ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
++ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
++};
++
++enum omap_overlay_manager_caps {
++ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
++};
+
+ /* RFBI */
+
+@@ -178,108 +214,13 @@ int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
+ int dsi_vc_send_null(int channel);
+
+ /* Board specific data */
+-struct omap_dss_display_config {
+- enum omap_display_type type;
+-
+- union {
+- struct {
+- u8 data_lines;
+- } dpi;
+-
+- struct {
+- u8 channel;
+- u8 data_lines;
+- } rfbi;
+-
+- struct {
+- u8 datapairs;
+- } sdi;
+-
+- struct {
+- u8 clk_lane;
+- u8 clk_pol;
+- u8 data1_lane;
+- u8 data1_pol;
+- u8 data2_lane;
+- u8 data2_pol;
+- unsigned long lp_clk_hz;
+- unsigned long ddr_clk_hz;
+-
+- bool ext_te;
+- u8 ext_te_gpio;
+- } dsi;
+-
+- struct {
+- enum omap_dss_venc_type type;
+- } venc;
+- } u;
+-
+- int panel_reset_gpio;
+- int ctrl_reset_gpio;
+-
+- int max_backlight_level;
+-
+- const char *name; /* for debug */
+- const char *ctrl_name;
+- const char *panel_name;
+-
+- void *panel_data;
+- void *ctrl_data;
+-
+- /* platform specific enable/disable */
+- int (*panel_enable)(struct omap_display *display);
+- void (*panel_disable)(struct omap_display *display);
+- int (*ctrl_enable)(struct omap_display *display);
+- void (*ctrl_disable)(struct omap_display *display);
+- int (*set_backlight)(struct omap_display *display,
+- int level);
+- int (*get_backlight)(struct omap_display *display);
+-};
+-
+-struct device;
+-
+-/* Board specific data */
+-struct omap_dss_board_info {
++struct omap_dss_board_info {
+ int (*get_last_off_on_transaction_id)(struct device *dev);
++ int num_devices;
++ struct omap_dss_device **devices;
++ struct omap_dss_device *default_device;
+ int (*dsi_power_up)(void);
+ void (*dsi_power_down)(void);
+- int num_displays;
+- struct omap_dss_display_config *displays[];
+-};
+-
+-struct omap_ctrl {
+- struct module *owner;
+-
+- const char *name;
+-
+- int (*init)(struct omap_display *display);
+- void (*cleanup)(struct omap_display *display);
+- int (*enable)(struct omap_display *display);
+- void (*disable)(struct omap_display *display);
+- int (*suspend)(struct omap_display *display);
+- int (*resume)(struct omap_display *display);
+- void (*setup_update)(struct omap_display *display,
+- u16 x, u16 y, u16 w, u16 h);
+-
+- int (*enable_te)(struct omap_display *display, bool enable);
+- int (*wait_for_te)(struct omap_display *display);
+-
+- u8 (*get_rotate)(struct omap_display *display);
+- int (*set_rotate)(struct omap_display *display, u8 rotate);
+-
+- bool (*get_mirror)(struct omap_display *display);
+- int (*set_mirror)(struct omap_display *display, bool enable);
+-
+- int (*run_test)(struct omap_display *display, int test);
+- int (*memory_read)(struct omap_display *display,
+- void *buf, size_t size,
+- u16 x, u16 y, u16 w, u16 h);
+-
+- u8 pixel_size;
+-
+- struct rfbi_timings timings;
+-
+- void *priv;
+ };
+
+ struct omap_video_timings {
+@@ -301,7 +242,6 @@ struct omap_video_timings {
+ u16 vfp; /* Vertical front porch */
+ /* Unit: line clocks */
+ u16 vbp; /* Vertical back porch */
+-
+ };
+
+ #ifdef CONFIG_OMAP2_DSS_VENC
+@@ -313,46 +253,6 @@ const extern struct omap_video_timings omap_dss_pal_timings;
+ const extern struct omap_video_timings omap_dss_ntsc_timings;
+ #endif
+
+-struct omap_panel {
+- struct module *owner;
+-
+- const char *name;
+-
+- int (*init)(struct omap_display *display);
+- void (*cleanup)(struct omap_display *display);
+- int (*remove)(struct omap_display *display);
+- int (*enable)(struct omap_display *display);
+- void (*disable)(struct omap_display *display);
+- int (*suspend)(struct omap_display *display);
+- int (*resume)(struct omap_display *display);
+- int (*run_test)(struct omap_display *display, int test);
+-
+- struct omap_video_timings timings;
+-
+- int acbi; /* ac-bias pin transitions per interrupt */
+- /* Unit: line clocks */
+- int acb; /* ac-bias pin frequency */
+-
+- enum omap_panel_config config;
+-
+- u8 recommended_bpp;
+-
+- void *priv;
+-};
+-
+-/* XXX perhaps this should be removed */
+-enum omap_dss_overlay_managers {
+- OMAP_DSS_OVL_MGR_LCD,
+- OMAP_DSS_OVL_MGR_TV,
+-};
+-
+-struct omap_overlay_manager;
+-
+-enum omap_dss_rotation_type {
+- OMAP_DSS_ROT_DMA = 0,
+- OMAP_DSS_ROT_VRFB = 1,
+-};
+-
+ struct omap_overlay_info {
+ bool enabled;
+
+@@ -373,11 +273,6 @@ struct omap_overlay_info {
+ u8 global_alpha;
+ };
+
+-enum omap_overlay_caps {
+- OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
+- OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
+-};
+-
+ struct omap_overlay {
+ struct kobject kobj;
+ struct list_head list;
+@@ -399,10 +294,6 @@ struct omap_overlay {
+ struct omap_overlay_info *info);
+ };
+
+-enum omap_overlay_manager_caps {
+- OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
+-};
+-
+ struct omap_overlay_manager {
+ struct kobject kobj;
+ struct list_head list;
+@@ -410,14 +301,14 @@ struct omap_overlay_manager {
+ const char *name;
+ int id;
+ enum omap_overlay_manager_caps caps;
+- struct omap_display *display;
++ struct omap_dss_device *device;
+ int num_overlays;
+ struct omap_overlay **overlays;
+ enum omap_display_type supported_displays;
+
+- int (*set_display)(struct omap_overlay_manager *mgr,
+- struct omap_display *display);
+- int (*unset_display)(struct omap_overlay_manager *mgr);
++ int (*set_device)(struct omap_overlay_manager *mgr,
++ struct omap_dss_device *dssdev);
++ int (*unset_device)(struct omap_overlay_manager *mgr);
+
+ int (*apply)(struct omap_overlay_manager *mgr);
+
+@@ -437,99 +328,183 @@ struct omap_overlay_manager {
+ bool enable);
+ };
+
+-enum omap_display_caps {
+- OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
+-};
++struct omap_dss_device {
++ struct device dev;
+
+-enum omap_dss_update_mode {
+- OMAP_DSS_UPDATE_DISABLED = 0,
+- OMAP_DSS_UPDATE_AUTO,
+- OMAP_DSS_UPDATE_MANUAL,
+-};
++ enum omap_display_type type;
+
+-enum omap_dss_display_state {
+- OMAP_DSS_DISPLAY_DISABLED = 0,
+- OMAP_DSS_DISPLAY_ACTIVE,
+- OMAP_DSS_DISPLAY_SUSPENDED,
+-};
++ union {
++ struct {
++ u8 data_lines;
++ } dpi;
+
+-struct omap_display {
+- struct kobject kobj;
+- struct list_head list;
++ struct {
++ u8 channel;
++ u8 data_lines;
++ } rfbi;
+
+- /*atomic_t ref_count;*/
+- int ref_count;
+- /* helper variable for driver suspend/resume */
+- int activate_after_resume;
++ struct {
++ u8 datapairs;
++ } sdi;
++
++ struct {
++ u8 clk_lane;
++ u8 clk_pol;
++ u8 data1_lane;
++ u8 data1_pol;
++ u8 data2_lane;
++ u8 data2_pol;
++ unsigned long lp_clk_hz;
++ unsigned long ddr_clk_hz;
++
++ bool ext_te;
++ u8 ext_te_gpio;
++ } dsi;
++
++ struct {
++ enum omap_dss_venc_type type;
++ } venc;
++ } phy;
++
++ struct {
++ struct omap_video_timings timings;
++
++ int acbi; /* ac-bias pin transitions per interrupt */
++ /* Unit: line clocks */
++ int acb; /* ac-bias pin frequency */
++
++ enum omap_panel_config config;
++
++ u8 recommended_bpp;
++
++ struct omap_dss_device *ctrl;
++ } panel;
++
++ struct {
++ u8 pixel_size;
++ struct rfbi_timings rfbi_timings;
++ struct omap_dss_device *panel;
++ } ctrl;
++
++ int reset_gpio;
++
++ int max_backlight_level;
+
+- enum omap_display_type type;
+ const char *name;
+
++ /* used to match device to driver */
++ const char *driver_name;
++
++ void *data;
++
++ struct omap_dss_driver *driver;
++
++ /* helper variable for driver suspend/resume */
++ bool activate_after_resume;
++
+ enum omap_display_caps caps;
+
+ struct omap_overlay_manager *manager;
+
+ enum omap_dss_display_state state;
+
+- struct omap_dss_display_config hw_config; /* board specific data */
+- struct omap_ctrl *ctrl; /* static common data */
+- struct omap_panel *panel; /* static common data */
+-
+- int (*enable)(struct omap_display *display);
+- void (*disable)(struct omap_display *display);
++ int (*enable)(struct omap_dss_device *dssdev);
++ void (*disable)(struct omap_dss_device *dssdev);
+
+- int (*suspend)(struct omap_display *display);
+- int (*resume)(struct omap_display *display);
++ int (*suspend)(struct omap_dss_device *dssdev);
++ int (*resume)(struct omap_dss_device *dssdev);
+
+- void (*get_resolution)(struct omap_display *display,
++ void (*get_resolution)(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres);
+- int (*get_recommended_bpp)(struct omap_display *display);
++ int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
+
+- int (*check_timings)(struct omap_display *display,
++ int (*check_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+- void (*set_timings)(struct omap_display *display,
++ void (*set_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+- void (*get_timings)(struct omap_display *display,
++ void (*get_timings)(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings);
+- int (*update)(struct omap_display *display,
++ int (*update)(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h);
+- int (*sync)(struct omap_display *display);
+- int (*wait_vsync)(struct omap_display *display);
++ int (*sync)(struct omap_dss_device *dssdev);
++ int (*wait_vsync)(struct omap_dss_device *dssdev);
+
+- int (*set_update_mode)(struct omap_display *display,
++ int (*set_update_mode)(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode);
+ enum omap_dss_update_mode (*get_update_mode)
+- (struct omap_display *display);
++ (struct omap_dss_device *dssdev);
+
+- int (*enable_te)(struct omap_display *display, bool enable);
+- int (*get_te)(struct omap_display *display);
++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
++ int (*get_te)(struct omap_dss_device *dssdev);
++ int (*wait_for_te)(struct omap_dss_device *dssdev);
+
+- u8 (*get_rotate)(struct omap_display *display);
+- int (*set_rotate)(struct omap_display *display, u8 rotate);
++ u8 (*get_rotate)(struct omap_dss_device *dssdev);
++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
+
+- bool (*get_mirror)(struct omap_display *display);
+- int (*set_mirror)(struct omap_display *display, bool enable);
++ bool (*get_mirror)(struct omap_dss_device *dssdev);
++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
+
+- int (*run_test)(struct omap_display *display, int test);
+- int (*memory_read)(struct omap_display *display,
++ int (*run_test)(struct omap_dss_device *dssdev, int test);
++ int (*memory_read)(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h);
+
+ void (*configure_overlay)(struct omap_overlay *overlay);
+
+- int (*set_wss)(struct omap_display *display, u32 wss);
+- u32 (*get_wss)(struct omap_display *display);
++ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
++ u32 (*get_wss)(struct omap_dss_device *dssdev);
++
++ /* platform specific */
++ int (*platform_enable)(struct omap_dss_device *dssdev);
++ void (*platform_disable)(struct omap_dss_device *dssdev);
++ int (*set_backlight)(struct omap_dss_device *dssdev, int level);
++ int (*get_backlight)(struct omap_dss_device *dssdev);
+ };
+
+-int omap_dss_get_num_displays(void);
+-struct omap_display *omap_dss_get_display(int no);
+-void omap_dss_put_display(struct omap_display *display);
++struct omap_dss_driver {
++ struct device_driver driver;
++
++ int (*probe)(struct omap_dss_device *);
++ void (*remove)(struct omap_dss_device *);
+
+-void omap_dss_register_ctrl(struct omap_ctrl *ctrl);
+-void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl);
++ int (*enable)(struct omap_dss_device *display);
++ void (*disable)(struct omap_dss_device *display);
++ int (*suspend)(struct omap_dss_device *display);
++ int (*resume)(struct omap_dss_device *display);
++ int (*run_test)(struct omap_dss_device *display, int test);
+
+-void omap_dss_register_panel(struct omap_panel *panel);
+-void omap_dss_unregister_panel(struct omap_panel *panel);
++ void (*setup_update)(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h);
++
++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
++ int (*wait_for_te)(struct omap_dss_device *dssdev);
++
++ u8 (*get_rotate)(struct omap_dss_device *dssdev);
++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
++
++ bool (*get_mirror)(struct omap_dss_device *dssdev);
++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
++
++ int (*memory_read)(struct omap_dss_device *dssdev,
++ void *buf, size_t size,
++ u16 x, u16 y, u16 w, u16 h);
++};
++
++int omap_dss_register_driver(struct omap_dss_driver *);
++void omap_dss_unregister_driver(struct omap_dss_driver *);
++
++int omap_dss_register_device(struct omap_dss_device *);
++void omap_dss_unregister_device(struct omap_dss_device *);
++
++void omap_dss_get_device(struct omap_dss_device *dssdev);
++void omap_dss_put_device(struct omap_dss_device *dssdev);
++#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
++struct omap_dss_device *omap_dss_find_device(void *data,
++ int (*match)(struct omap_dss_device *dssdev, void *data));
++
++int omap_dss_start_device(struct omap_dss_device *dssdev);
++void omap_dss_stop_device(struct omap_dss_device *dssdev);
+
+ int omap_dss_get_num_overlay_managers(void);
+ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
+@@ -544,5 +519,4 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+ int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
+ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout);
+-
+ #endif
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index 2a38507..c56c431 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -30,6 +30,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/debugfs.h>
+ #include <linux/io.h>
++#include <linux/device.h>
+
+ #include <mach/display.h>
+ #include <mach/clock.h>
+@@ -437,11 +438,16 @@ void dss_dsi_power_down(void)
+ /* PLATFORM DEVICE */
+ static int omap_dss_probe(struct platform_device *pdev)
+ {
++ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+ int skip_init = 0;
+ int r;
++ int i;
+
+ core.pdev = pdev;
+
++ dss_init_overlay_managers(pdev);
++ dss_init_overlays(pdev);
++
+ r = dss_get_clocks();
+ if (r)
+ goto fail0;
+@@ -483,7 +489,7 @@ static int omap_dss_probe(struct platform_device *pdev)
+ goto fail0;
+ }
+ #ifdef CONFIG_OMAP2_DSS_VENC
+- r = venc_init();
++ r = venc_init(pdev);
+ if (r) {
+ DSSERR("Failed to initialize venc\n");
+ goto fail0;
+@@ -498,7 +504,7 @@ static int omap_dss_probe(struct platform_device *pdev)
+ }
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_DSI
+- r = dsi_init();
++ r = dsi_init(pdev);
+ if (r) {
+ DSSERR("Failed to initialize DSI\n");
+ goto fail0;
+@@ -512,9 +518,16 @@ static int omap_dss_probe(struct platform_device *pdev)
+ goto fail0;
+ #endif
+
+- dss_init_displays(pdev);
+- dss_init_overlay_managers(pdev);
+- dss_init_overlays(pdev, def_disp_name);
++ for (i = 0; i < pdata->num_devices; ++i) {
++ struct omap_dss_device *dssdev = pdata->devices[i];
++
++ r = omap_dss_register_device(dssdev);
++ if (r)
++ DSSERR("device reg failed %d\n", i);
++
++ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
++ pdata->default_device = dssdev;
++ }
+
+ dss_clk_disable_all();
+
+@@ -527,12 +540,10 @@ fail0:
+
+ static int omap_dss_remove(struct platform_device *pdev)
+ {
++ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
++ int i;
+ int c;
+
+- dss_uninit_overlays(pdev);
+- dss_uninit_overlay_managers(pdev);
+- dss_uninit_displays(pdev);
+-
+ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+ dss_uninitialize_debugfs();
+ #endif
+@@ -597,6 +608,12 @@ static int omap_dss_remove(struct platform_device *pdev)
+
+ dss_put_clocks();
+
++ dss_uninit_overlays(pdev);
++ dss_uninit_overlay_managers(pdev);
++
++ for (i = 0; i < pdata->num_devices; ++i)
++ omap_dss_unregister_device(pdata->devices[i]);
++
+ return 0;
+ }
+
+@@ -609,14 +626,14 @@ static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+ DSSDBG("suspend %d\n", state.event);
+
+- return dss_suspend_all_displays();
++ return dss_suspend_all_devices();
+ }
+
+ static int omap_dss_resume(struct platform_device *pdev)
+ {
+ DSSDBG("resume\n");
+
+- return dss_resume_all_displays();
++ return dss_resume_all_devices();
+ }
+
+ static struct platform_driver omap_dss_driver = {
+@@ -631,19 +648,282 @@ static struct platform_driver omap_dss_driver = {
+ },
+ };
+
++/* BUS */
++static int dss_bus_match(struct device *dev, struct device_driver *driver)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ DSSDBG("bus_match. dev %s/%s, drv %s\n",
++ dev_name(dev), dssdev->driver_name, driver->name);
++
++ return strcmp(dssdev->driver_name, driver->name) == 0;
++}
++
++static ssize_t device_name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ dssdev->name ?
++ dssdev->name : "");
++}
++
++static struct device_attribute default_dev_attrs[] = {
++ __ATTR(name, S_IRUGO, device_name_show, NULL),
++ __ATTR_NULL,
++};
++
++static ssize_t driver_name_show(struct device_driver *drv, char *buf)
++{
++ struct omap_dss_driver *dssdrv = to_dss_driver(drv);
++ return snprintf(buf, PAGE_SIZE, "%s\n",
++ dssdrv->driver.name ?
++ dssdrv->driver.name : "");
++}
++static struct driver_attribute default_drv_attrs[] = {
++ __ATTR(name, S_IRUGO, driver_name_show, NULL),
++ __ATTR_NULL,
++};
++
++static struct bus_type dss_bus_type = {
++ .name = "omapdss",
++ .match = dss_bus_match,
++ .dev_attrs = default_dev_attrs,
++ .drv_attrs = default_drv_attrs,
++};
++
++static void dss_bus_release(struct device *dev)
++{
++ DSSDBG("bus_release\n");
++}
++
++static struct device dss_bus = {
++ .release = dss_bus_release,
++};
++
++struct bus_type *dss_get_bus(void)
++{
++ return &dss_bus_type;
++}
++
++/* DRIVER */
++static int dss_driver_probe(struct device *dev)
++{
++ int r;
++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
++ bool force;
++
++ DSSDBG("driver_probe: dev %s/%s, drv %s\n",
++ dev_name(dev), dssdev->driver_name,
++ dssdrv->driver.name);
++
++ dss_init_device(core.pdev, dssdev);
++
++ /* skip this if the device is behind a ctrl */
++ if (!dssdev->panel.ctrl) {
++ force = pdata->default_device == dssdev;
++ dss_recheck_connections(dssdev, force);
++ }
++
++ r = dssdrv->probe(dssdev);
++
++ if (r) {
++ DSSERR("driver probe failed: %d\n", r);
++ return r;
++ }
++
++ DSSDBG("probe done for device %s\n", dev_name(dev));
++
++ dssdev->driver = dssdrv;
++
++ return 0;
++}
++
++static int dss_driver_remove(struct device *dev)
++{
++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++
++ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
++ dssdev->driver_name);
++
++ dssdrv->remove(dssdev);
++
++ dss_uninit_device(core.pdev, dssdev);
++
++ dssdev->driver = NULL;
++
++ return 0;
++}
++
++int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
++{
++ dssdriver->driver.bus = &dss_bus_type;
++ dssdriver->driver.probe = dss_driver_probe;
++ dssdriver->driver.remove = dss_driver_remove;
++ return driver_register(&dssdriver->driver);
++}
++EXPORT_SYMBOL(omap_dss_register_driver);
++
++void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
++{
++ driver_unregister(&dssdriver->driver);
++}
++EXPORT_SYMBOL(omap_dss_unregister_driver);
++
++/* DEVICE */
++static void reset_device(struct device *dev, int check)
++{
++ u8 *dev_p = (u8 *)dev;
++ u8 *dev_end = dev_p + sizeof(*dev);
++ void *saved_pdata;
++
++ saved_pdata = dev->platform_data;
++ if (check) {
++ /*
++ * Check if there is any other setting than platform_data
++ * in struct device; warn that these will be reset by our
++ * init.
++ */
++ dev->platform_data = NULL;
++ while (dev_p < dev_end) {
++ if (*dev_p) {
++ WARN("%s: struct device fields will be discarded\n",
++ __func__);
++ break;
++ }
++ dev_p++;
++ }
++ }
++ memset(dev, 0, sizeof(*dev));
++ dev->platform_data = saved_pdata;
++}
++
++
++static void omap_dss_dev_release(struct device *dev)
++{
++ reset_device(dev, 0);
++}
++
++int omap_dss_register_device(struct omap_dss_device *dssdev)
++{
++ static int dev_num;
++ static int panel_num;
++ int r;
++
++ WARN_ON(!dssdev->driver_name);
++
++ reset_device(&dssdev->dev, 1);
++ dssdev->dev.bus = &dss_bus_type;
++ dssdev->dev.parent = &dss_bus;
++ dssdev->dev.release = omap_dss_dev_release;
++ dev_set_name(&dssdev->dev, "display%d", dev_num++);
++ r = device_register(&dssdev->dev);
++ if (r)
++ return r;
++
++ if (dssdev->ctrl.panel) {
++ struct omap_dss_device *panel = dssdev->ctrl.panel;
++
++ panel->panel.ctrl = dssdev;
++
++ reset_device(&panel->dev, 1);
++ panel->dev.bus = &dss_bus_type;
++ panel->dev.parent = &dssdev->dev;
++ panel->dev.release = omap_dss_dev_release;
++ dev_set_name(&panel->dev, "panel%d", panel_num++);
++ r = device_register(&panel->dev);
++ if (r)
++ return r;
++ }
++
++ return 0;
++}
++
++void omap_dss_unregister_device(struct omap_dss_device *dssdev)
++{
++ device_unregister(&dssdev->dev);
++
++ if (dssdev->ctrl.panel) {
++ struct omap_dss_device *panel = dssdev->ctrl.panel;
++ device_unregister(&panel->dev);
++ }
++}
++
++/* BUS */
++static int omap_dss_bus_register(void)
++{
++ int r;
++
++ r = bus_register(&dss_bus_type);
++ if (r) {
++ DSSERR("bus register failed\n");
++ return r;
++ }
++
++ dev_set_name(&dss_bus, "omapdss");
++ r = device_register(&dss_bus);
++ if (r) {
++ DSSERR("bus driver register failed\n");
++ bus_unregister(&dss_bus_type);
++ return r;
++ }
++
++ return 0;
++}
++
++/* INIT */
++
++#ifdef CONFIG_OMAP2_DSS_MODULE
++static void omap_dss_bus_unregister(void)
++{
++ device_unregister(&dss_bus);
++
++ bus_unregister(&dss_bus_type);
++}
++
+ static int __init omap_dss_init(void)
+ {
+- return platform_driver_register(&omap_dss_driver);
++ int r;
++
++ r = omap_dss_bus_register();
++ if (r)
++ return r;
++
++ r = platform_driver_register(&omap_dss_driver);
++ if (r) {
++ omap_dss_bus_unregister();
++ return r;
++ }
++
++ return 0;
+ }
+
+ static void __exit omap_dss_exit(void)
+ {
+ platform_driver_unregister(&omap_dss_driver);
++
++ omap_dss_bus_unregister();
+ }
+
+-subsys_initcall(omap_dss_init);
++module_init(omap_dss_init);
+ module_exit(omap_dss_exit);
++#else
++static int __init omap_dss_init(void)
++{
++ return omap_dss_bus_register();
++}
++
++static int __init omap_dss_init2(void)
++{
++ return platform_driver_register(&omap_dss_driver);
++}
+
++core_initcall(omap_dss_init);
++device_initcall(omap_dss_init2);
++#endif
+
+ MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+ MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index e936c59..52170f8 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2319,15 +2319,15 @@ static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
+ enable_clocks(0);
+ }
+
+-void dispc_set_pol_freq(struct omap_panel *panel)
++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
+ {
+- _dispc_set_pol_freq((panel->config & OMAP_DSS_LCD_ONOFF) != 0,
+- (panel->config & OMAP_DSS_LCD_RF) != 0,
+- (panel->config & OMAP_DSS_LCD_IEO) != 0,
+- (panel->config & OMAP_DSS_LCD_IPC) != 0,
+- (panel->config & OMAP_DSS_LCD_IHS) != 0,
+- (panel->config & OMAP_DSS_LCD_IVS) != 0,
+- panel->acbi, panel->acb);
++ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
++ (config & OMAP_DSS_LCD_RF) != 0,
++ (config & OMAP_DSS_LCD_IEO) != 0,
++ (config & OMAP_DSS_LCD_IPC) != 0,
++ (config & OMAP_DSS_LCD_IHS) != 0,
++ (config & OMAP_DSS_LCD_IVS) != 0,
++ acbi, acb);
+ }
+
+ void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+@@ -2790,9 +2790,9 @@ static void dispc_error_worker(struct work_struct *work)
+
+ if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
+ manager = mgr;
+- enable = mgr->display->state ==
++ enable = mgr->device->state ==
+ OMAP_DSS_DISPLAY_ACTIVE;
+- mgr->display->disable(mgr->display);
++ mgr->device->disable(mgr->device);
+ break;
+ }
+ }
+@@ -2812,7 +2812,7 @@ static void dispc_error_worker(struct work_struct *work)
+ dispc_go(manager->id);
+ mdelay(50);
+ if (enable)
+- manager->display->enable(manager->display);
++ manager->device->enable(manager->device);
+ }
+ }
+
+@@ -2828,9 +2828,9 @@ static void dispc_error_worker(struct work_struct *work)
+
+ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
+ manager = mgr;
+- enable = mgr->display->state ==
++ enable = mgr->device->state ==
+ OMAP_DSS_DISPLAY_ACTIVE;
+- mgr->display->disable(mgr->display);
++ mgr->device->disable(mgr->device);
+ break;
+ }
+ }
+@@ -2850,7 +2850,7 @@ static void dispc_error_worker(struct work_struct *work)
+ dispc_go(manager->id);
+ mdelay(50);
+ if (enable)
+- manager->display->enable(manager->display);
++ manager->device->enable(manager->device);
+ }
+ }
+
+@@ -2861,7 +2861,7 @@ static void dispc_error_worker(struct work_struct *work)
+ mgr = omap_dss_get_overlay_manager(i);
+
+ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
+- mgr->display->disable(mgr->display);
++ mgr->device->disable(mgr->device);
+ }
+ }
+
+@@ -3126,7 +3126,7 @@ static int dispc_is_overlay_scaled(struct omap_overlay_info *pi)
+ }
+
+ /* returns the area that needs updating */
+-void dispc_setup_partial_planes(struct omap_display *display,
++void dispc_setup_partial_planes(struct omap_dss_device *dssdev,
+ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
+ {
+ struct omap_overlay_manager *mgr;
+@@ -3143,7 +3143,7 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ *xi, *yi, *wi, *hi);
+
+
+- mgr = display->manager;
++ mgr = dssdev->manager;
+
+ if (!mgr) {
+ DSSDBG("no manager\n");
+@@ -3307,7 +3307,7 @@ void dispc_setup_partial_planes(struct omap_display *display,
+ pi->mirror,
+ pi->global_alpha);
+
+- if (dss_use_replication(display, ovl->info.color_mode))
++ if (dss_use_replication(dssdev, ovl->info.color_mode))
+ dispc_enable_replication(ovl->id, true);
+ else
+ dispc_enable_replication(ovl->id, false);
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 77a6dc4..2251bff 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -31,52 +31,54 @@
+ #include <mach/display.h>
+ #include "dss.h"
+
+-static int num_displays;
+ static LIST_HEAD(display_list);
+
+-static ssize_t display_name_show(struct omap_display *display, char *buf)
++static ssize_t display_enabled_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%s\n", display->name);
+-}
+-
+-static ssize_t display_enabled_show(struct omap_display *display, char *buf)
+-{
+- bool enabled = display->state != OMAP_DSS_DISPLAY_DISABLED;
++ struct omap_dss_device *dssdev = to_dss_device(dev);
++ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+ }
+
+-static ssize_t display_enabled_store(struct omap_display *display,
++static ssize_t display_enabled_store(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ bool enabled, r;
+
+ enabled = simple_strtoul(buf, NULL, 10);
+
+- if (enabled != (display->state != OMAP_DSS_DISPLAY_DISABLED)) {
++ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
+ if (enabled) {
+- r = display->enable(display);
++ r = dssdev->enable(dssdev);
+ if (r)
+ return r;
+ } else {
+- display->disable(display);
++ dssdev->disable(dssdev);
+ }
+ }
+
+ return size;
+ }
+
+-static ssize_t display_upd_mode_show(struct omap_display *display, char *buf)
++static ssize_t display_upd_mode_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
+- if (display->get_update_mode)
+- mode = display->get_update_mode(display);
++ if (dssdev->get_update_mode)
++ mode = dssdev->get_update_mode(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+ }
+
+-static ssize_t display_upd_mode_store(struct omap_display *display,
++static ssize_t display_upd_mode_store(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int val, r;
+ enum omap_dss_update_mode mode;
+
+@@ -92,43 +94,48 @@ static ssize_t display_upd_mode_store(struct omap_display *display,
+ return -EINVAL;
+ }
+
+- if ((r = display->set_update_mode(display, mode)))
++ if ((r = dssdev->set_update_mode(dssdev, mode)))
+ return r;
+
+ return size;
+ }
+
+-static ssize_t display_tear_show(struct omap_display *display, char *buf)
++static ssize_t display_tear_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- display->get_te ? display->get_te(display) : 0);
++ dssdev->get_te ? dssdev->get_te(dssdev) : 0);
+ }
+
+-static ssize_t display_tear_store(struct omap_display *display,
+- const char *buf, size_t size)
++static ssize_t display_tear_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long te;
+ int r;
+
+- if (!display->enable_te || !display->get_te)
++ if (!dssdev->enable_te || !dssdev->get_te)
+ return -ENOENT;
+
+ te = simple_strtoul(buf, NULL, 0);
+
+- if ((r = display->enable_te(display, te)))
++ if ((r = dssdev->enable_te(dssdev, te)))
+ return r;
+
+ return size;
+ }
+
+-static ssize_t display_timings_show(struct omap_display *display, char *buf)
++static ssize_t display_timings_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t;
+
+- if (!display->get_timings)
++ if (!dssdev->get_timings)
+ return -ENOENT;
+
+- display->get_timings(display, &t);
++ dssdev->get_timings(dssdev, &t);
+
+ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+ t.pixel_clock,
+@@ -136,13 +143,14 @@ static ssize_t display_timings_show(struct omap_display *display, char *buf)
+ t.y_res, t.vfp, t.vbp, t.vsw);
+ }
+
+-static ssize_t display_timings_store(struct omap_display *display,
+- const char *buf, size_t size)
++static ssize_t display_timings_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t;
+ int r, found;
+
+- if (!display->set_timings || !display->check_timings)
++ if (!dssdev->set_timings || !dssdev->check_timings)
+ return -ENOENT;
+
+ found = 0;
+@@ -161,103 +169,94 @@ static ssize_t display_timings_store(struct omap_display *display,
+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+ return -EINVAL;
+
+- if ((r = display->check_timings(display, &t)))
++ if ((r = dssdev->check_timings(dssdev, &t)))
+ return r;
+
+- display->set_timings(display, &t);
++ dssdev->set_timings(dssdev, &t);
+
+ return size;
+ }
+
+-static ssize_t display_rotate_show(struct omap_display *display, char *buf)
++static ssize_t display_rotate_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int rotate;
+- if (!display->get_rotate)
++ if (!dssdev->get_rotate)
+ return -ENOENT;
+- rotate = display->get_rotate(display);
++ rotate = dssdev->get_rotate(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+ }
+
+-static ssize_t display_rotate_store(struct omap_display *display,
+- const char *buf, size_t size)
++static ssize_t display_rotate_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long rot;
+ int r;
+
+- if (!display->set_rotate || !display->get_rotate)
++ if (!dssdev->set_rotate || !dssdev->get_rotate)
+ return -ENOENT;
+
+ rot = simple_strtoul(buf, NULL, 0);
+
+- if ((r = display->set_rotate(display, rot)))
++ if ((r = dssdev->set_rotate(dssdev, rot)))
+ return r;
+
+ return size;
+ }
+
+-static ssize_t display_mirror_show(struct omap_display *display, char *buf)
++static ssize_t display_mirror_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int mirror;
+- if (!display->get_mirror)
++ if (!dssdev->get_mirror)
+ return -ENOENT;
+- mirror = display->get_mirror(display);
++ mirror = dssdev->get_mirror(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+ }
+
+-static ssize_t display_mirror_store(struct omap_display *display,
+- const char *buf, size_t size)
++static ssize_t display_mirror_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long mirror;
+ int r;
+
+- if (!display->set_mirror || !display->get_mirror)
++ if (!dssdev->set_mirror || !dssdev->get_mirror)
+ return -ENOENT;
+
+ mirror = simple_strtoul(buf, NULL, 0);
+
+- if ((r = display->set_mirror(display, mirror)))
++ if ((r = dssdev->set_mirror(dssdev, mirror)))
+ return r;
+
+ return size;
+ }
+
+-static ssize_t display_panel_name_show(struct omap_display *display, char *buf)
+-{
+- return snprintf(buf, PAGE_SIZE, "%s\n",
+- display->panel ? display->panel->name : "");
+-}
+-
+-static ssize_t display_ctrl_name_show(struct omap_display *display, char *buf)
+-{
+- return snprintf(buf, PAGE_SIZE, "%s\n",
+- display->ctrl ? display->ctrl->name : "");
+-}
+-
+-struct display_attribute {
+- struct attribute attr;
+- ssize_t (*show)(struct omap_display *, char *);
+- ssize_t (*store)(struct omap_display *, const char *, size_t);
+-};
+-
+-static ssize_t display_wss_show(struct omap_display *display, char *buf)
++static ssize_t display_wss_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned int wss;
+
+- if (!display->get_wss)
++ if (!dssdev->get_wss)
+ return -ENOENT;
+
+- wss = display->get_wss(display);
++ wss = dssdev->get_wss(dssdev);
+
+ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+ }
+
+-static ssize_t display_wss_store(struct omap_display *display,
+- const char *buf, size_t size)
++static ssize_t display_wss_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
+ {
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned long wss;
+ int r;
+
+- if (!display->get_wss || !display->set_wss)
++ if (!dssdev->get_wss || !dssdev->set_wss)
+ return -ENOENT;
+
+ if (strict_strtoul(buf, 0, &wss))
+@@ -266,92 +265,43 @@ static ssize_t display_wss_store(struct omap_display *display,
+ if (wss > 0xfffff)
+ return -EINVAL;
+
+- if ((r = display->set_wss(display, wss)))
++ if ((r = dssdev->set_wss(dssdev, wss)))
+ return r;
+
+ return size;
+ }
+
+-#define DISPLAY_ATTR(_name, _mode, _show, _store) \
+- struct display_attribute display_attr_##_name = \
+- __ATTR(_name, _mode, _show, _store)
+-
+-static DISPLAY_ATTR(name, S_IRUGO, display_name_show, NULL);
+-static DISPLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+ display_enabled_show, display_enabled_store);
+-static DISPLAY_ATTR(update_mode, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
+ display_upd_mode_show, display_upd_mode_store);
+-static DISPLAY_ATTR(tear_elim, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+ display_tear_show, display_tear_store);
+-static DISPLAY_ATTR(timings, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+ display_timings_show, display_timings_store);
+-static DISPLAY_ATTR(rotate, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+ display_rotate_show, display_rotate_store);
+-static DISPLAY_ATTR(mirror, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+ display_mirror_show, display_mirror_store);
+-static DISPLAY_ATTR(panel_name, S_IRUGO, display_panel_name_show, NULL);
+-static DISPLAY_ATTR(ctrl_name, S_IRUGO, display_ctrl_name_show, NULL);
+-static DISPLAY_ATTR(wss, S_IRUGO|S_IWUSR,
++static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+ display_wss_show, display_wss_store);
+
+-static struct attribute *display_sysfs_attrs[] = {
+- &display_attr_name.attr,
+- &display_attr_enabled.attr,
+- &display_attr_update_mode.attr,
+- &display_attr_tear_elim.attr,
+- &display_attr_timings.attr,
+- &display_attr_rotate.attr,
+- &display_attr_mirror.attr,
+- &display_attr_panel_name.attr,
+- &display_attr_ctrl_name.attr,
+- &display_attr_wss.attr,
++static struct device_attribute *display_sysfs_attrs[] = {
++ &dev_attr_enabled,
++ &dev_attr_update_mode,
++ &dev_attr_tear_elim,
++ &dev_attr_timings,
++ &dev_attr_rotate,
++ &dev_attr_mirror,
++ &dev_attr_wss,
+ NULL
+ };
+
+-static ssize_t display_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+-{
+- struct omap_display *display;
+- struct display_attribute *display_attr;
+-
+- display = container_of(kobj, struct omap_display, kobj);
+- display_attr = container_of(attr, struct display_attribute, attr);
+-
+- if (!display_attr->show)
+- return -ENOENT;
+-
+- return display_attr->show(display, buf);
+-}
+-
+-static ssize_t display_attr_store(struct kobject *kobj, struct attribute *attr,
+- const char *buf, size_t size)
+-{
+- struct omap_display *display;
+- struct display_attribute *display_attr;
+-
+- display = container_of(kobj, struct omap_display, kobj);
+- display_attr = container_of(attr, struct display_attribute, attr);
+-
+- if (!display_attr->store)
+- return -ENOENT;
+-
+- return display_attr->store(display, buf, size);
+-}
+-
+-static struct sysfs_ops display_sysfs_ops = {
+- .show = display_attr_show,
+- .store = display_attr_store,
+-};
+-
+-static struct kobj_type display_ktype = {
+- .sysfs_ops = &display_sysfs_ops,
+- .default_attrs = display_sysfs_attrs,
+-};
+-
+-static void default_get_resolution(struct omap_display *display,
++static void default_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres)
+ {
+- *xres = display->panel->timings.x_res;
+- *yres = display->panel->timings.y_res;
++ *xres = dssdev->panel.timings.x_res;
++ *yres = dssdev->panel.timings.y_res;
+ }
+
+ static void default_configure_overlay(struct omap_overlay *ovl)
+@@ -371,12 +321,12 @@ static void default_configure_overlay(struct omap_overlay *ovl)
+ dispc_setup_plane_fifo(plane, low, high);
+ }
+
+-static int default_wait_vsync(struct omap_display *display)
++static int default_wait_vsync(struct omap_dss_device *dssdev)
+ {
+ unsigned long timeout = msecs_to_jiffies(500);
+ u32 irq;
+
+- if (display->type == OMAP_DISPLAY_TYPE_VENC)
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+ irq = DISPC_IRQ_EVSYNC_ODD;
+ else
+ irq = DISPC_IRQ_VSYNC;
+@@ -384,21 +334,21 @@ static int default_wait_vsync(struct omap_display *display)
+ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ }
+
+-static int default_get_recommended_bpp(struct omap_display *display)
++static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
+ {
+- if (display->panel->recommended_bpp)
+- return display->panel->recommended_bpp;
++ if (dssdev->panel.recommended_bpp)
++ return dssdev->panel.recommended_bpp;
+
+- switch (display->type) {
++ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+- if (display->hw_config.u.dpi.data_lines == 24)
++ if (dssdev->phy.dpi.data_lines == 24)
+ return 24;
+ else
+ return 16;
+
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_DSI:
+- if (display->ctrl->pixel_size == 24)
++ if (dssdev->ctrl.pixel_size == 24)
+ return 24;
+ else
+ return 16;
+@@ -414,7 +364,7 @@ static int default_get_recommended_bpp(struct omap_display *display)
+ /* Checks if replication logic should be used. Only use for active matrix,
+ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
+ * 18bpp or 24bpp */
+-bool dss_use_replication(struct omap_display *display,
++bool dss_use_replication(struct omap_dss_device *dssdev,
+ enum omap_color_mode mode)
+ {
+ int bpp;
+@@ -422,13 +372,13 @@ bool dss_use_replication(struct omap_display *display,
+ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
+ return false;
+
+- if (display->type == OMAP_DISPLAY_TYPE_DPI &&
+- (display->panel->config & OMAP_DSS_LCD_TFT) == 0)
++ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
++ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
+ return false;
+
+- switch (display->type) {
++ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+- bpp = display->hw_config.u.dpi.data_lines;
++ bpp = dssdev->phy.dpi.data_lines;
+ break;
+ case OMAP_DISPLAY_TYPE_VENC:
+ case OMAP_DISPLAY_TYPE_SDI:
+@@ -436,7 +386,7 @@ bool dss_use_replication(struct omap_display *display,
+ break;
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_DSI:
+- bpp = display->ctrl->pixel_size;
++ bpp = dssdev->ctrl.pixel_size;
+ break;
+ default:
+ BUG();
+@@ -445,319 +395,259 @@ bool dss_use_replication(struct omap_display *display,
+ return bpp > 16;
+ }
+
+-void dss_init_displays(struct platform_device *pdev)
++void dss_init_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev)
+ {
+- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+- int i, r;
+-
+- INIT_LIST_HEAD(&display_list);
+-
+- num_displays = 0;
+-
+- for (i = 0; i < pdata->num_displays; ++i) {
+- struct omap_display *display;
++ struct device_attribute *attr;
++ int i;
++ int r;
+
+- switch (pdata->displays[i]->type) {
+- case OMAP_DISPLAY_TYPE_DPI:
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
+ #ifdef CONFIG_OMAP2_DSS_RFBI
+- case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_DBI:
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_SDI
+- case OMAP_DISPLAY_TYPE_SDI:
++ case OMAP_DISPLAY_TYPE_SDI:
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_DSI
+- case OMAP_DISPLAY_TYPE_DSI:
++ case OMAP_DISPLAY_TYPE_DSI:
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_VENC
+- case OMAP_DISPLAY_TYPE_VENC:
++ case OMAP_DISPLAY_TYPE_VENC:
+ #endif
+- break;
+- default:
+- DSSERR("Support for display '%s' not compiled in.\n",
+- pdata->displays[i]->name);
+- continue;
+- }
+-
+- display = kzalloc(sizeof(*display), GFP_KERNEL);
+-
+- /*atomic_set(&display->ref_count, 0);*/
+- display->ref_count = 0;
+-
+- display->hw_config = *pdata->displays[i];
+- display->type = pdata->displays[i]->type;
+- display->name = pdata->displays[i]->name;
++ break;
++ default:
++ DSSERR("Support for display '%s' not compiled in.\n",
++ dssdev->name);
++ return;
++ }
+
+- display->get_resolution = default_get_resolution;
+- display->get_recommended_bpp = default_get_recommended_bpp;
+- display->configure_overlay = default_configure_overlay;
+- display->wait_vsync = default_wait_vsync;
++ dssdev->get_resolution = default_get_resolution;
++ dssdev->get_recommended_bpp = default_get_recommended_bpp;
++ dssdev->configure_overlay = default_configure_overlay;
++ dssdev->wait_vsync = default_wait_vsync;
+
+- switch (display->type) {
+- case OMAP_DISPLAY_TYPE_DPI:
+- dpi_init_display(display);
+- break;
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ dpi_init_display(dssdev);
++ break;
+ #ifdef CONFIG_OMAP2_DSS_RFBI
+- case OMAP_DISPLAY_TYPE_DBI:
+- rfbi_init_display(display);
+- break;
++ case OMAP_DISPLAY_TYPE_DBI:
++ rfbi_init_display(dssdev);
++ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_VENC
+- case OMAP_DISPLAY_TYPE_VENC:
+- venc_init_display(display);
+- break;
++ case OMAP_DISPLAY_TYPE_VENC:
++ venc_init_display(dssdev);
++ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_SDI
+- case OMAP_DISPLAY_TYPE_SDI:
+- sdi_init_display(display);
+- break;
++ case OMAP_DISPLAY_TYPE_SDI:
++ sdi_init_display(dssdev);
++ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_DSI
+- case OMAP_DISPLAY_TYPE_DSI:
+- dsi_init_display(display);
+- break;
++ case OMAP_DISPLAY_TYPE_DSI:
++ dsi_init_display(dssdev);
++ break;
+ #endif
+- default:
+- BUG();
+- }
+-
+- r = kobject_init_and_add(&display->kobj, &display_ktype,
+- &pdev->dev.kobj, "display%d", num_displays);
++ default:
++ BUG();
++ }
+
+- if (r) {
++ /* create device sysfs files */
++ i = 0;
++ while ((attr = display_sysfs_attrs[i++]) != NULL) {
++ r = device_create_file(&dssdev->dev, attr);
++ if (r)
+ DSSERR("failed to create sysfs file\n");
+- continue;
+- }
+-
+- num_displays++;
+-
+- list_add_tail(&display->list, &display_list);
+ }
++
++ /* create display? sysfs links */
++ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
++ dev_name(&dssdev->dev));
++ if (r)
++ DSSERR("failed to create sysfs display link\n");
+ }
+
+-void dss_uninit_displays(struct platform_device *pdev)
++void dss_uninit_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev)
+ {
+- struct omap_display *display;
+-
+- while (!list_empty(&display_list)) {
+- display = list_first_entry(&display_list,
+- struct omap_display, list);
+- list_del(&display->list);
+- kobject_del(&display->kobj);
+- kobject_put(&display->kobj);
+- kfree(display);
+- }
++ struct device_attribute *attr;
++ int i = 0;
++
++ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
++
++ while ((attr = display_sysfs_attrs[i++]) != NULL)
++ device_remove_file(&dssdev->dev, attr);
+
+- num_displays = 0;
++ if (dssdev->manager)
++ dssdev->manager->unset_device(dssdev->manager);
+ }
+
+-int dss_suspend_all_displays(void)
++static int dss_suspend_device(struct device *dev, void *data)
+ {
+ int r;
+- struct omap_display *display;
+-
+- list_for_each_entry(display, &display_list, list) {
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
+- display->activate_after_resume = 0;
+- continue;
+- }
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+- if (!display->suspend) {
+- DSSERR("display '%s' doesn't implement suspend\n",
+- display->name);
+- r = -ENOSYS;
+- goto err;
+- }
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ dssdev->activate_after_resume = false;
++ return 0;
++ }
+
+- r = display->suspend(display);
++ if (!dssdev->suspend) {
++ DSSERR("display '%s' doesn't implement suspend\n",
++ dssdev->name);
++ return -ENOSYS;
++ }
+
+- if (r)
+- goto err;
++ r = dssdev->suspend(dssdev);
++ if (r)
++ return r;
+
+- display->activate_after_resume = 1;
+- }
++ dssdev->activate_after_resume = true;
+
+ return 0;
+-err:
+- /* resume all displays that were suspended */
+- dss_resume_all_displays();
+- return r;
+ }
+
+-int dss_resume_all_displays(void)
++int dss_suspend_all_devices(void)
+ {
+ int r;
+- struct omap_display *display;
+-
+- list_for_each_entry(display, &display_list, list) {
+- if (display->activate_after_resume && display->resume) {
+- r = display->resume(display);
+- if (r)
+- return r;
+- }
++ struct bus_type *bus = dss_get_bus();
+
+- display->activate_after_resume = 0;
++ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
++ if (r) {
++ /* resume all displays that were suspended */
++ dss_resume_all_devices();
++ return r;
+ }
+
+ return 0;
+ }
+
+-int omap_dss_get_num_displays(void)
+-{
+- return num_displays;
+-}
+-EXPORT_SYMBOL(omap_dss_get_num_displays);
+-
+-struct omap_display *dss_get_display(int no)
++static int dss_resume_device(struct device *dev, void *data)
+ {
+- int i = 0;
+- struct omap_display *display;
++ int r;
++ struct omap_dss_device *dssdev = to_dss_device(dev);
+
+- list_for_each_entry(display, &display_list, list) {
+- if (i++ == no)
+- return display;
++ if (dssdev->activate_after_resume && dssdev->resume) {
++ r = dssdev->resume(dssdev);
++ if (r)
++ return r;
+ }
+
+- return NULL;
++ dssdev->activate_after_resume = false;
++
++ return 0;
+ }
+
+-struct omap_display *omap_dss_get_display(int no)
++int dss_resume_all_devices(void)
+ {
+- struct omap_display *display;
++ struct bus_type *bus = dss_get_bus();
+
+- display = dss_get_display(no);
++ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
++}
+
+- if (!display)
+- return NULL;
+
+- switch (display->type) {
+- case OMAP_DISPLAY_TYPE_VENC:
+- break;
++void omap_dss_get_device(struct omap_dss_device *dssdev)
++{
++ get_device(&dssdev->dev);
++}
++EXPORT_SYMBOL(omap_dss_get_device);
+
+- case OMAP_DISPLAY_TYPE_DPI:
+- case OMAP_DISPLAY_TYPE_SDI:
+- if (display->panel == NULL)
+- return NULL;
+- break;
++void omap_dss_put_device(struct omap_dss_device *dssdev)
++{
++ put_device(&dssdev->dev);
++}
++EXPORT_SYMBOL(omap_dss_put_device);
+
+- case OMAP_DISPLAY_TYPE_DBI:
+- case OMAP_DISPLAY_TYPE_DSI:
+- if (display->panel == NULL || display->ctrl == NULL)
+- return NULL;
+- break;
++/* ref count of the found device is incremented. ref count
++ * of from-device is decremented. */
++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
++{
++ struct device *dev;
++ struct device *dev_start = NULL;
++ struct omap_dss_device *dssdev = NULL;
+
+- default:
+- return NULL;
++ int match(struct device *dev, void *data)
++ {
++ /* skip panels connected to controllers */
++ if (to_dss_device(dev)->panel.ctrl)
++ return 0;
++
++ return 1;
+ }
+
+- if (display->ctrl) {
+- if (!try_module_get(display->ctrl->owner))
+- goto err0;
++ if (from)
++ dev_start = &from->dev;
++ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
++ if (dev)
++ dssdev = to_dss_device(dev);
++ if (from)
++ put_device(&from->dev);
+
+- if (display->ctrl->init)
+- if (display->ctrl->init(display) != 0)
+- goto err1;
+- }
++ return dssdev;
++}
++EXPORT_SYMBOL(omap_dss_get_next_device);
+
+- if (display->panel) {
+- if (!try_module_get(display->panel->owner))
+- goto err2;
++struct omap_dss_device *omap_dss_find_device(void *data,
++ int (*match)(struct omap_dss_device *dssdev, void *data))
++{
++ struct omap_dss_device *dssdev = NULL;
+
+- if (display->panel->init)
+- if (display->panel->init(display) != 0)
+- goto err3;
++ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL)
++ {
++ if (match(dssdev, data))
++ return dssdev;
+ }
+
+- display->ref_count++;
+- /*
+- if (atomic_cmpxchg(&display->ref_count, 0, 1) != 0)
+- return 0;
+-*/
+-
+- return display;
+-err3:
+- if (display->panel)
+- module_put(display->panel->owner);
+-err2:
+- if (display->ctrl && display->ctrl->cleanup)
+- display->ctrl->cleanup(display);
+-err1:
+- if (display->ctrl)
+- module_put(display->ctrl->owner);
+-err0:
+ return NULL;
+ }
+-EXPORT_SYMBOL(omap_dss_get_display);
++EXPORT_SYMBOL(omap_dss_find_device);
+
+-void omap_dss_put_display(struct omap_display *display)
++int omap_dss_start_device(struct omap_dss_device *dssdev)
+ {
+- if (--display->ref_count > 0)
+- return;
+-/*
+- if (atomic_cmpxchg(&display->ref_count, 1, 0) != 1)
+- return;
+-*/
+- if (display->ctrl) {
+- if (display->ctrl->cleanup)
+- display->ctrl->cleanup(display);
+- module_put(display->ctrl->owner);
+- }
++ int r;
+
+- if (display->panel) {
+- if (display->panel->cleanup)
+- display->panel->cleanup(display);
+- module_put(display->panel->owner);
++ if (!dssdev->driver) {
++ DSSDBG("no driver\n");
++ r = -ENODEV;
++ goto err0;
+ }
+-}
+-EXPORT_SYMBOL(omap_dss_put_display);
+-
+-void omap_dss_register_ctrl(struct omap_ctrl *ctrl)
+-{
+- struct omap_display *display;
+
+- list_for_each_entry(display, &display_list, list) {
+- if (display->hw_config.ctrl_name &&
+- strcmp(display->hw_config.ctrl_name, ctrl->name) == 0) {
+- display->ctrl = ctrl;
+- DSSDBG("ctrl '%s' registered\n", ctrl->name);
+- }
++ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
++ DSSDBG("no panel driver\n");
++ r = -ENODEV;
++ goto err0;
+ }
+-}
+-EXPORT_SYMBOL(omap_dss_register_ctrl);
+
+-void omap_dss_register_panel(struct omap_panel *panel)
+-{
+- struct omap_display *display;
++ if(!try_module_get(dssdev->dev.driver->owner)) {
++ r = -ENODEV;
++ goto err0;
++ }
+
+- list_for_each_entry(display, &display_list, list) {
+- if (display->hw_config.panel_name &&
+- strcmp(display->hw_config.panel_name, panel->name) == 0) {
+- display->panel = panel;
+- DSSDBG("panel '%s' registered\n", panel->name);
++ if (dssdev->ctrl.panel) {
++ if(!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
++ r = -ENODEV;
++ goto err1;
+ }
+ }
+-}
+-EXPORT_SYMBOL(omap_dss_register_panel);
+
+-void omap_dss_unregister_ctrl(struct omap_ctrl *ctrl)
+-{
+- struct omap_display *display;
+-
+- list_for_each_entry(display, &display_list, list) {
+- if (display->hw_config.ctrl_name &&
+- strcmp(display->hw_config.ctrl_name, ctrl->name) == 0)
+- display->ctrl = NULL;
+- }
++ return 0;
++err1:
++ module_put(dssdev->dev.driver->owner);
++err0:
++ return r;
+ }
+-EXPORT_SYMBOL(omap_dss_unregister_ctrl);
++EXPORT_SYMBOL(omap_dss_start_device);
+
+-void omap_dss_unregister_panel(struct omap_panel *panel)
++void omap_dss_stop_device(struct omap_dss_device *dssdev)
+ {
+- struct omap_display *display;
++ if (dssdev->ctrl.panel)
++ module_put(dssdev->ctrl.panel->dev.driver->owner);
+
+- list_for_each_entry(display, &display_list, list) {
+- if (display->hw_config.panel_name &&
+- strcmp(display->hw_config.panel_name, panel->name) == 0)
+- display->panel = NULL;
+- }
++ module_put(dssdev->dev.driver->owner);
+ }
+-EXPORT_SYMBOL(omap_dss_unregister_panel);
++EXPORT_SYMBOL(omap_dss_stop_device);
++
+diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
+index 71fffca..f5867cf 100644
+--- a/drivers/video/omap2/dss/dpi.c
++++ b/drivers/video/omap2/dss/dpi.c
+@@ -20,6 +20,8 @@
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#define DSS_SUBSYS_NAME "DPI"
++
+ #include <linux/kernel.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+@@ -83,9 +85,9 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
+ }
+ #endif
+
+-static int dpi_set_mode(struct omap_display *display)
++static int dpi_set_mode(struct omap_dss_device *dssdev)
+ {
+- struct omap_panel *panel = display->panel;
++ struct omap_video_timings *t = &dssdev->panel.timings;
+ int lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+@@ -94,15 +96,16 @@ static int dpi_set_mode(struct omap_display *display)
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- dispc_set_pol_freq(panel);
++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
++ dssdev->panel.acb);
+
+- is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+ #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+- r = dpi_set_dsi_clk(is_tft, panel->timings.pixel_clock * 1000,
++ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
+ &fck, &lck_div, &pck_div);
+ #else
+- r = dpi_set_dispc_clk(is_tft, panel->timings.pixel_clock * 1000,
++ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
+ &fck, &lck_div, &pck_div);
+ #endif
+ if (r)
+@@ -110,97 +113,106 @@ static int dpi_set_mode(struct omap_display *display)
+
+ pck = fck / lck_div / pck_div / 1000;
+
+- if (pck != panel->timings.pixel_clock) {
++ if (pck != t->pixel_clock) {
+ DSSWARN("Could not find exact pixel clock. "
+ "Requested %d kHz, got %lu kHz\n",
+- panel->timings.pixel_clock, pck);
++ t->pixel_clock, pck);
+
+- panel->timings.pixel_clock = pck;
++ t->pixel_clock = pck;
+ }
+
+- dispc_set_lcd_timings(&panel->timings);
++ dispc_set_lcd_timings(t);
+
+ err0:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ return r;
+ }
+
+-static int dpi_basic_init(struct omap_display *display)
++static int dpi_basic_init(struct omap_dss_device *dssdev)
+ {
+ bool is_tft;
+
+- is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
+ OMAP_DSS_LCD_DISPLAY_STN);
+- dispc_set_tft_data_lines(display->hw_config.u.dpi.data_lines);
++ dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
+
+ return 0;
+ }
+
+-static int dpi_display_enable(struct omap_display *display)
++static int dpi_display_enable(struct omap_dss_device *dssdev)
+ {
+- struct omap_panel *panel = display->panel;
+ int r;
+
+- if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ DSSERR("display already enabled\n");
+- return -EINVAL;
++ r = -EINVAL;
++ goto err1;
+ }
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- r = dpi_basic_init(display);
++ r = dpi_basic_init(dssdev);
+ if (r)
+- goto err0;
++ goto err2;
+
+ #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ dss_clk_enable(DSS_CLK_FCK2);
+ r = dsi_pll_init(0, 1);
+ if (r)
+- goto err1;
++ goto err3;
+ #endif
+- r = dpi_set_mode(display);
++ r = dpi_set_mode(dssdev);
+ if (r)
+- goto err2;
++ goto err4;
+
+ mdelay(2);
+
+ dispc_enable_lcd_out(1);
+
+- r = panel->enable(display);
++ r = dssdev->driver->enable(dssdev);
+ if (r)
+- goto err3;
++ goto err5;
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+
+-err3:
++err5:
+ dispc_enable_lcd_out(0);
+-err2:
++err4:
+ #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ dsi_pll_uninit();
+-err1:
++err3:
+ dss_clk_disable(DSS_CLK_FCK2);
+ #endif
+-err0:
++err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
+ return r;
+ }
+
+-static int dpi_display_resume(struct omap_display *display);
++static int dpi_display_resume(struct omap_dss_device *dssdev);
+
+-static void dpi_display_disable(struct omap_display *display)
++static void dpi_display_disable(struct omap_dss_device *dssdev)
+ {
+- if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ return;
+
+- if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
+- dpi_display_resume(display);
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ dpi_display_resume(dssdev);
+
+- display->panel->disable(display);
++ dssdev->driver->disable(dssdev);
+
+ dispc_enable_lcd_out(0);
+
+@@ -212,31 +224,33 @@ static void dpi_display_disable(struct omap_display *display)
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ omap_dss_stop_device(dssdev);
+ }
+
+-static int dpi_display_suspend(struct omap_display *display)
++static int dpi_display_suspend(struct omap_dss_device *dssdev)
+ {
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EINVAL;
+
+ DSSDBG("dpi_display_suspend\n");
+
+- if (display->panel->suspend)
+- display->panel->suspend(display);
++ if (dssdev->driver->suspend)
++ dssdev->driver->suspend(dssdev);
+
+ dispc_enable_lcd_out(0);
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ return 0;
+ }
+
+-static int dpi_display_resume(struct omap_display *display)
++static int dpi_display_resume(struct omap_dss_device *dssdev)
+ {
+- if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
+ DSSDBG("dpi_display_resume\n");
+@@ -245,26 +259,26 @@ static int dpi_display_resume(struct omap_display *display)
+
+ dispc_enable_lcd_out(1);
+
+- if (display->panel->resume)
+- display->panel->resume(display);
++ if (dssdev->driver->resume)
++ dssdev->driver->resume(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+ }
+
+-static void dpi_set_timings(struct omap_display *display,
++static void dpi_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+ DSSDBG("dpi_set_timings\n");
+- display->panel->timings = *timings;
+- if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
+- dpi_set_mode(display);
++ dssdev->panel.timings = *timings;
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ dpi_set_mode(dssdev);
+ dispc_go(OMAP_DSS_CHANNEL_LCD);
+ }
+ }
+
+-static int dpi_check_timings(struct omap_display *display,
++static int dpi_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+ bool is_tft;
+@@ -300,7 +314,7 @@ static int dpi_check_timings(struct omap_display *display,
+ if (timings->pixel_clock == 0)
+ return -EINVAL;
+
+- is_tft = (display->panel->config & OMAP_DSS_LCD_TFT) != 0;
++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
+
+ #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+ {
+@@ -337,13 +351,13 @@ static int dpi_check_timings(struct omap_display *display,
+ return 0;
+ }
+
+-static void dpi_get_timings(struct omap_display *display,
++static void dpi_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+- *timings = display->panel->timings;
++ *timings = dssdev->panel.timings;
+ }
+
+-static int dpi_display_set_update_mode(struct omap_display *display,
++static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+ {
+ if (mode == OMAP_DSS_UPDATE_MANUAL)
+@@ -361,25 +375,25 @@ static int dpi_display_set_update_mode(struct omap_display *display,
+ }
+
+ static enum omap_dss_update_mode dpi_display_get_update_mode(
+- struct omap_display *display)
++ struct omap_dss_device *dssdev)
+ {
+ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+ OMAP_DSS_UPDATE_DISABLED;
+ }
+
+-void dpi_init_display(struct omap_display *display)
++void dpi_init_display(struct omap_dss_device *dssdev)
+ {
+- DSSDBG("DPI init_display\n");
+-
+- display->enable = dpi_display_enable;
+- display->disable = dpi_display_disable;
+- display->suspend = dpi_display_suspend;
+- display->resume = dpi_display_resume;
+- display->set_timings = dpi_set_timings;
+- display->check_timings = dpi_check_timings;
+- display->get_timings = dpi_get_timings;
+- display->set_update_mode = dpi_display_set_update_mode;
+- display->get_update_mode = dpi_display_get_update_mode;
++ DSSDBG("init_display\n");
++
++ dssdev->enable = dpi_display_enable;
++ dssdev->disable = dpi_display_disable;
++ dssdev->suspend = dpi_display_suspend;
++ dssdev->resume = dpi_display_resume;
++ dssdev->set_timings = dpi_set_timings;
++ dssdev->check_timings = dpi_check_timings;
++ dssdev->get_timings = dpi_get_timings;
++ dssdev->set_update_mode = dpi_display_set_update_mode;
++ dssdev->get_update_mode = dpi_display_get_update_mode;
+ }
+
+ int dpi_init(void)
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index a06fb75..fb2f7f0 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -30,6 +30,7 @@
+ #include <linux/mutex.h>
+ #include <linux/seq_file.h>
+ #include <linux/kfifo.h>
++#include <linux/platform_device.h>
+
+ #include <mach/board.h>
+ #include <mach/display.h>
+@@ -230,7 +231,7 @@ enum dsi_cmd {
+ };
+
+ struct dsi_cmd_item {
+- struct omap_display *display;
++ struct omap_dss_device *dssdev;
+
+ enum dsi_cmd cmd;
+
+@@ -256,7 +257,7 @@ static struct
+ unsigned long ddr_clk; /* Hz */
+
+ struct {
+- struct omap_display *display;
++ struct omap_dss_device *dssdev;
+ enum fifo_size fifo_size;
+ int dest_per; /* destination peripheral 0-3 */
+ } vc[4];
+@@ -317,9 +318,9 @@ module_param_named(dsi_perf, dsi_perf, bool, 0644);
+ #endif
+
+ static void dsi_process_cmd_fifo(struct work_struct *work);
+-static void dsi_push_update(struct omap_display *display,
++static void dsi_push_update(struct omap_dss_device *dssdev,
+ int x, int y, int w, int h);
+-static void dsi_push_autoupdate(struct omap_display *display);
++static void dsi_push_autoupdate(struct omap_dss_device *dssdev);
+
+ static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
+ {
+@@ -777,7 +778,7 @@ static unsigned long dsi_fclk_rate(void)
+ return r;
+ }
+
+-static int dsi_set_lp_clk_divisor(struct omap_display *display)
++static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
+ {
+ unsigned n;
+ unsigned long dsi_fclk;
+@@ -785,7 +786,7 @@ static int dsi_set_lp_clk_divisor(struct omap_display *display)
+
+ dsi_fclk = dsi_fclk_rate();
+
+- lp_clk_req = display->hw_config.u.dsi.lp_clk_hz;
++ lp_clk_req = dssdev->phy.dsi.lp_clk_hz;
+
+ for (n = 1; n < (1 << 13) - 1; ++n) {
+ lp_clk = dsi_fclk / 2 / n;
+@@ -1376,16 +1377,16 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state)
+ return 0;
+ }
+
+-static void dsi_complexio_config(struct omap_display *display)
++static void dsi_complexio_config(struct omap_dss_device *dssdev)
+ {
+ u32 r;
+
+- int clk_lane = display->hw_config.u.dsi.clk_lane;
+- int data1_lane = display->hw_config.u.dsi.data1_lane;
+- int data2_lane = display->hw_config.u.dsi.data2_lane;
+- int clk_pol = display->hw_config.u.dsi.clk_pol;
+- int data1_pol = display->hw_config.u.dsi.data1_pol;
+- int data2_pol = display->hw_config.u.dsi.data2_pol;
++ int clk_lane = dssdev->phy.dsi.clk_lane;
++ int data1_lane = dssdev->phy.dsi.data1_lane;
++ int data2_lane = dssdev->phy.dsi.data2_lane;
++ int clk_pol = dssdev->phy.dsi.clk_pol;
++ int data1_pol = dssdev->phy.dsi.data1_pol;
++ int data2_pol = dssdev->phy.dsi.data2_pol;
+
+ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+ r = FLD_MOD(r, clk_lane, 2, 0);
+@@ -1497,7 +1498,7 @@ static void dsi_complexio_timings(void)
+ }
+
+
+-static int dsi_complexio_init(struct omap_display *display)
++static int dsi_complexio_init(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+@@ -1517,7 +1518,7 @@ static int dsi_complexio_init(struct omap_display *display)
+ goto err;
+ }
+
+- dsi_complexio_config(display);
++ dsi_complexio_config(dssdev);
+
+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+
+@@ -2283,7 +2284,7 @@ static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
+
+ return 0;
+ }
+-static int dsi_proto_config(struct omap_display *display)
++static int dsi_proto_config(struct omap_dss_device *dssdev)
+ {
+ u32 r;
+ int buswidth = 0;
+@@ -2310,7 +2311,7 @@ static int dsi_proto_config(struct omap_display *display)
+ /* 10000ns * 4 */
+ dsi_set_hs_tx_timeout(10000, 1, 0);
+
+- switch (display->ctrl->pixel_size) {
++ switch (dssdev->ctrl.pixel_size) {
+ case 16:
+ buswidth = 0;
+ break;
+@@ -2355,7 +2356,7 @@ static int dsi_proto_config(struct omap_display *display)
+ return 0;
+ }
+
+-static void dsi_proto_timings(struct omap_display *display)
++static void dsi_proto_timings(struct omap_dss_device *dssdev)
+ {
+ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
+ unsigned tclk_pre, tclk_post;
+@@ -2387,8 +2388,8 @@ static void dsi_proto_timings(struct omap_display *display)
+ tclk_post = ns2ddr(60) + 26;
+
+ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
+- if (display->hw_config.u.dsi.data1_lane != 0 &&
+- display->hw_config.u.dsi.data2_lane != 0)
++ if (dssdev->phy.dsi.data1_lane != 0 &&
++ dssdev->phy.dsi.data2_lane != 0)
+ ths_eot = 2;
+ else
+ ths_eot = 4;
+@@ -2412,6 +2413,7 @@ static void dsi_proto_timings(struct omap_display *display)
+ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
+ DIV_ROUND_UP(ths_prepare, 4) +
+ DIV_ROUND_UP(ths_zero + 3, 4);
++
+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+@@ -2441,7 +2443,7 @@ static void dsi_proto_timings(struct omap_display *display)
+ DSI_FLUSH(ch); \
+ } while (0)
+
+-static int dsi_update_screen_l4(struct omap_display *display,
++static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ int x, int y, int w, int h)
+ {
+ /* Note: supports only 24bit colors in 32bit container */
+@@ -2464,12 +2466,12 @@ static int dsi_update_screen_l4(struct omap_display *display,
+ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
+ x, y, w, h);
+
+- ovl = display->manager->overlays[0];
++ ovl = dssdev->manager->overlays[0];
+
+ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
+ return -EINVAL;
+
+- if (display->ctrl->pixel_size != 24)
++ if (dssdev->ctrl.pixel_size != 24)
+ return -EINVAL;
+
+ scr_width = ovl->info.screen_width;
+@@ -2497,7 +2499,7 @@ static int dsi_update_screen_l4(struct omap_display *display,
+
+ dsi_bus_lock();
+
+- display->ctrl->setup_update(display, x, y, w, h);
++ dssdev->driver->setup_update(dssdev, x, y, w, h);
+
+ pixels_left = w * h;
+
+@@ -2595,101 +2597,7 @@ static int dsi_update_screen_l4(struct omap_display *display,
+ return 0;
+ }
+
+-#if 0
+-static void dsi_clear_screen_l4(struct omap_display *display,
+- int x, int y, int w, int h)
+-{
+- int first = 1;
+- int fifo_stalls = 0;
+- int max_dsi_packet_size;
+- int max_data_per_packet;
+- int max_pixels_per_packet;
+- int pixels_left;
+- int bytespp = 3;
+- int pixnum;
+-
+- debug_irq = 0;
+-
+- DSSDBG("dsi_clear_screen_l4 (%d,%d %dx%d)\n",
+- x, y, w, h);
+-
+- if (display->ctrl->bpp != 24)
+- return -EINVAL;
+-
+- /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp)
+- * bytes in fifo */
+-
+- /* When using CPU, max long packet size is TX buffer size */
+- max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
+-
+- max_data_per_packet = max_dsi_packet_size - 4 - 1;
+-
+- max_pixels_per_packet = max_data_per_packet / bytespp;
+-
+- enable_clocks(1);
+-
+- display->ctrl->setup_update(display, x, y, w, h);
+-
+- pixels_left = w * h;
+-
+- dsi.update_region.x = x;
+- dsi.update_region.y = y;
+- dsi.update_region.w = w;
+- dsi.update_region.h = h;
+- dsi.update_region.bytespp = bytespp;
+-
+- start_measuring();
+-
+- pixnum = 0;
+-
+- while (pixels_left > 0) {
+- /* 0x2c = write_memory_start */
+- /* 0x3c = write_memory_continue */
+- u8 dcs_cmd = first ? 0x2c : 0x3c;
+- int pixels;
+- DSI_DECL_VARS;
+- first = 0;
+-
+- /* TX_FIFO_NOT_EMPTY */
+- while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
+- fifo_stalls++;
+- if (fifo_stalls > 0xfffff) {
+- DSSERR("fifo stalls overflow\n");
+- dsi_if_enable(0);
+- enable_clocks(0);
+- return;
+- }
+- }
+-
+- pixels = min(max_pixels_per_packet, pixels_left);
+-
+- pixels_left -= pixels;
+-
+- dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
+- 1 + pixels * bytespp, 0);
+-
+- DSI_PUSH(0, dcs_cmd);
+-
+- while (pixels-- > 0) {
+- u32 pix;
+-
+- pix = 0x000000;
+-
+- DSI_PUSH(0, (pix >> 16) & 0xff);
+- DSI_PUSH(0, (pix >> 8) & 0xff);
+- DSI_PUSH(0, (pix >> 0) & 0xff);
+- }
+-
+- DSI_FLUSH(0);
+- }
+-
+- enable_clocks(0);
+-
+- end_measuring("L4 CLEAR");
+-}
+-#endif
+-
+-static void dsi_setup_update_dispc(struct omap_display *display,
++static void dsi_setup_update_dispc(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+ DSSDBG("dsi_setup_update_dispc(%d,%d %dx%d)\n",
+@@ -2703,16 +2611,16 @@ static void dsi_setup_update_dispc(struct omap_display *display,
+ dsi.update_region.bytespp = 3; // XXX
+ #endif
+
+- dispc_setup_partial_planes(display, &x, &y, &w, &h);
++ dispc_setup_partial_planes(dssdev, &x, &y, &w, &h);
+
+ dispc_set_lcd_size(w, h);
+ }
+
+-static void dsi_setup_autoupdate_dispc(struct omap_display *display)
++static void dsi_setup_autoupdate_dispc(struct omap_dss_device *dssdev)
+ {
+ u16 w, h;
+
+- display->get_resolution(display, &w, &h);
++ dssdev->get_resolution(dssdev, &w, &h);
+
+ #ifdef DEBUG
+ dsi.update_region.x = 0;
+@@ -2724,14 +2632,14 @@ static void dsi_setup_autoupdate_dispc(struct omap_display *display)
+
+ /* the overlay settings may not have been applied, if we were in manual
+ * mode earlier, so do it here */
+- display->manager->apply(display->manager);
++ dssdev->manager->apply(dssdev->manager);
+
+ dispc_set_lcd_size(w, h);
+
+ dsi.autoupdate_setup = 0;
+ }
+
+-static void dsi_update_screen_dispc(struct omap_display *display,
++static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+ int bytespp = 3;
+@@ -2760,10 +2668,10 @@ static void dsi_update_screen_dispc(struct omap_display *display,
+
+ dsi_bus_lock();
+
+- display->ctrl->setup_update(display, x, y, w, h);
++ dssdev->driver->setup_update(dssdev, x, y, w, h);
+
+- if (dsi.use_ext_te && display->ctrl->wait_for_te)
+- display->ctrl->wait_for_te(display);
++ if (dsi.use_ext_te && dssdev->wait_for_te)
++ dssdev->wait_for_te(dssdev);
+
+ if (0)
+ dsi_vc_print_status(1);
+@@ -2811,7 +2719,7 @@ static void framedone_timeout_callback(struct work_struct *work)
+ /* We check for target_update_mode, not update_mode. No reason to push
+ * new updates if we're turning auto update off */
+ if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_push_autoupdate(dsi.vc[1].display);
++ dsi_push_autoupdate(dsi.vc[1].dssdev);
+
+ atomic_set(&dsi.cmd_pending, 0);
+ dsi_process_cmd_fifo(NULL);
+@@ -2895,19 +2803,19 @@ static void framedone_worker(struct work_struct *work)
+ /* We check for target_update_mode, not update_mode. No reason to push
+ * new updates if we're turning auto update off */
+ if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_push_autoupdate(dsi.vc[1].display);
++ dsi_push_autoupdate(dsi.vc[1].dssdev);
+
+ atomic_set(&dsi.cmd_pending, 0);
+ dsi_process_cmd_fifo(NULL);
+ }
+
+-static void dsi_start_auto_update(struct omap_display *display)
++static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("starting auto update\n");
+
+ dsi.autoupdate_setup = 1;
+
+- dsi_push_autoupdate(display);
++ dsi_push_autoupdate(dssdev);
+
+ perf_mark_start_auto();
+ }
+@@ -2936,7 +2844,7 @@ static void dsi_signal_fifo_waiters(void)
+ }
+
+ /* returns 1 for async op, and 0 for sync op */
+-static int dsi_do_update(struct omap_display *display,
++static int dsi_do_update(struct omap_dss_device *dssdev,
+ struct dsi_cmd_update *upd)
+ {
+ int r;
+@@ -2946,10 +2854,10 @@ static int dsi_do_update(struct omap_display *display,
+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+ return 0;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+- display->get_resolution(display, &dw, &dh);
++ dssdev->get_resolution(dssdev, &dw, &dh);
+ if (x > dw || y > dh)
+ return 0;
+
+@@ -2963,12 +2871,12 @@ static int dsi_do_update(struct omap_display *display,
+
+ perf_mark_setup();
+
+- if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+- dsi_setup_update_dispc(display, x, y, w, h);
+- dsi_update_screen_dispc(display, x, y, w, h);
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ dsi_setup_update_dispc(dssdev, x, y, w, h);
++ dsi_update_screen_dispc(dssdev, x, y, w, h);
+ return 1;
+ } else {
+- r = dsi_update_screen_l4(display, x, y, w, h);
++ r = dsi_update_screen_l4(dssdev, x, y, w, h);
+ if (r)
+ DSSERR("L4 update failed\n");
+ return 0;
+@@ -2976,7 +2884,7 @@ static int dsi_do_update(struct omap_display *display,
+ }
+
+ /* returns 1 for async op, and 0 for sync op */
+-static int dsi_do_autoupdate(struct omap_display *display)
++static int dsi_do_autoupdate(struct omap_dss_device *dssdev)
+ {
+ int r;
+ u16 w, h;
+@@ -2984,34 +2892,34 @@ static int dsi_do_autoupdate(struct omap_display *display)
+ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+ return 0;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+- display->get_resolution(display, &w, &h);
++ dssdev->get_resolution(dssdev, &w, &h);
+
+ perf_mark_setup();
+
+- if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ if (dsi.autoupdate_setup)
+- dsi_setup_autoupdate_dispc(display);
+- dsi_update_screen_dispc(display, 0, 0, w, h);
++ dsi_setup_autoupdate_dispc(dssdev);
++ dsi_update_screen_dispc(dssdev, 0, 0, w, h);
+ return 1;
+ } else {
+- r = dsi_update_screen_l4(display, 0, 0, w, h);
++ r = dsi_update_screen_l4(dssdev, 0, 0, w, h);
+ if (r)
+ DSSERR("L4 update failed\n");
+ return 0;
+ }
+ }
+
+-static void dsi_do_cmd_mem_read(struct omap_display *display,
++static void dsi_do_cmd_mem_read(struct omap_dss_device *dssdev,
+ struct dsi_cmd_mem_read *mem_read)
+ {
+ int r;
+
+ dsi_bus_lock();
+
+- r = display->ctrl->memory_read(display,
++ r = dssdev->driver->memory_read(dssdev,
+ mem_read->buf,
+ mem_read->size,
+ mem_read->x,
+@@ -3025,14 +2933,14 @@ static void dsi_do_cmd_mem_read(struct omap_display *display,
+ complete(mem_read->completion);
+ }
+
+-static void dsi_do_cmd_test(struct omap_display *display,
++static void dsi_do_cmd_test(struct omap_dss_device *dssdev,
+ struct dsi_cmd_test *test)
+ {
+ int r = 0;
+
+ DSSDBGF("");
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ dsi_bus_lock();
+@@ -3040,14 +2948,8 @@ static void dsi_do_cmd_test(struct omap_display *display,
+ /* run test first in low speed mode */
+ dsi_vc_enable_hs(0, 0);
+
+- if (display->ctrl->run_test) {
+- r = display->ctrl->run_test(display, test->test_num);
+- if (r)
+- goto end;
+- }
+-
+- if (display->panel->run_test) {
+- r = display->panel->run_test(display, test->test_num);
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test->test_num);
+ if (r)
+ goto end;
+ }
+@@ -3055,15 +2957,12 @@ static void dsi_do_cmd_test(struct omap_display *display,
+ /* then in high speed */
+ dsi_vc_enable_hs(0, 1);
+
+- if (display->ctrl->run_test) {
+- r = display->ctrl->run_test(display, test->test_num);
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test->test_num);
+ if (r)
+ goto end;
+ }
+
+- if (display->panel->run_test)
+- r = display->panel->run_test(display, test->test_num);
+-
+ end:
+ dsi_vc_enable_hs(0, 1);
+
+@@ -3075,21 +2974,21 @@ end:
+ DSSDBG("test end\n");
+ }
+
+-static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
++static void dsi_do_cmd_set_te(struct omap_dss_device *dssdev, bool enable)
+ {
+- if (!display->hw_config.u.dsi.ext_te)
++ if (!dssdev->phy.dsi.ext_te)
+ dsi.use_te = enable;
+ else
+ dsi.use_ext_te = enable;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ dsi_bus_lock();
+- display->ctrl->enable_te(display, enable);
++ dssdev->driver->enable_te(dssdev, enable);
+ dsi_bus_unlock();
+
+- if (!display->hw_config.u.dsi.ext_te) {
++ if (!dssdev->phy.dsi.ext_te) {
+ if (enable) {
+ /* disable LP_RX_TO, so that we can receive TE.
+ * Time to wait for TE is longer than the timer allows */
+@@ -3100,16 +2999,16 @@ static void dsi_do_cmd_set_te(struct omap_display *display, bool enable)
+ }
+ }
+
+-static void dsi_do_cmd_set_update_mode(struct omap_display *display,
++static void dsi_do_cmd_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+ {
+ dsi.update_mode = mode;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ if (mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_start_auto_update(display);
++ dsi_start_auto_update(dssdev);
+ }
+
+ static void dsi_process_cmd_fifo(struct work_struct *work)
+@@ -3117,7 +3016,7 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+ int len;
+ struct dsi_cmd_item p;
+ unsigned long flags;
+- struct omap_display *display;
++ struct omap_dss_device *dssdev;
+ int exit = 0;
+
+ if (dsi.debug_process)
+@@ -3146,14 +3045,14 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+
+ BUG_ON(len != sizeof(p));
+
+- display = p.display;
++ dssdev = p.dssdev;
+
+ if (dsi.debug_process)
+ DSSDBG("processing cmd %d\n", p.cmd);
+
+ switch (p.cmd) {
+ case DSI_CMD_UPDATE:
+- if (dsi_do_update(display, &p.u.r)) {
++ if (dsi_do_update(dssdev, &p.u.r)) {
+ if (dsi.debug_process)
+ DSSDBG("async update\n");
+ exit = 1;
+@@ -3164,7 +3063,7 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+ break;
+
+ case DSI_CMD_AUTOUPDATE:
+- if (dsi_do_autoupdate(display)) {
++ if (dsi_do_autoupdate(dssdev)) {
+ if (dsi.debug_process)
+ DSSDBG("async autoupdate\n");
+ exit = 1;
+@@ -3181,24 +3080,24 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+ break;
+
+ case DSI_CMD_MEM_READ:
+- dsi_do_cmd_mem_read(display, &p.u.mem_read);
++ dsi_do_cmd_mem_read(dssdev, &p.u.mem_read);
+ break;
+
+ case DSI_CMD_TEST:
+- dsi_do_cmd_test(display, &p.u.test);
++ dsi_do_cmd_test(dssdev, &p.u.test);
+ break;
+
+ case DSI_CMD_SET_TE:
+- dsi_do_cmd_set_te(display, p.u.te);
++ dsi_do_cmd_set_te(dssdev, p.u.te);
+ break;
+
+ case DSI_CMD_SET_UPDATE_MODE:
+- dsi_do_cmd_set_update_mode(display, p.u.update_mode);
++ dsi_do_cmd_set_update_mode(dssdev, p.u.update_mode);
+ break;
+
+ case DSI_CMD_SET_ROTATE:
+ dsi_bus_lock();
+- display->ctrl->set_rotate(display, p.u.rotate);
++ dssdev->driver->set_rotate(dssdev, p.u.rotate);
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+ dsi.autoupdate_setup = 1;
+ dsi_bus_unlock();
+@@ -3206,7 +3105,7 @@ static void dsi_process_cmd_fifo(struct work_struct *work)
+
+ case DSI_CMD_SET_MIRROR:
+ dsi_bus_lock();
+- display->ctrl->set_mirror(display, p.u.mirror);
++ dssdev->driver->set_mirror(dssdev, p.u.mirror);
+ dsi_bus_unlock();
+ break;
+
+@@ -3263,12 +3162,12 @@ static void dsi_push_cmd(struct dsi_cmd_item *p)
+ queue_work(dsi.workqueue, &dsi.process_work);
+ }
+
+-static void dsi_push_update(struct omap_display *display,
++static void dsi_push_update(struct omap_dss_device *dssdev,
+ int x, int y, int w, int h)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_UPDATE;
+
+ p.u.r.x = x;
+@@ -3281,22 +3180,22 @@ static void dsi_push_update(struct omap_display *display,
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_autoupdate(struct omap_display *display)
++static void dsi_push_autoupdate(struct omap_dss_device *dssdev)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_AUTOUPDATE;
+
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_sync(struct omap_display *display,
++static void dsi_push_sync(struct omap_dss_device *dssdev,
+ struct completion *sync_comp)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_SYNC;
+ p.u.sync = sync_comp;
+
+@@ -3305,12 +3204,12 @@ static void dsi_push_sync(struct omap_display *display,
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_mem_read(struct omap_display *display,
++static void dsi_push_mem_read(struct omap_dss_device *dssdev,
+ struct dsi_cmd_mem_read *mem_read)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_MEM_READ;
+ p.u.mem_read = *mem_read;
+
+@@ -3319,12 +3218,12 @@ static void dsi_push_mem_read(struct omap_display *display,
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_test(struct omap_display *display, int test_num,
++static void dsi_push_test(struct omap_dss_device *dssdev, int test_num,
+ int *result, struct completion *completion)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_TEST;
+ p.u.test.test_num = test_num;
+ p.u.test.result = result;
+@@ -3335,11 +3234,11 @@ static void dsi_push_test(struct omap_display *display, int test_num,
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_set_te(struct omap_display *display, bool enable)
++static void dsi_push_set_te(struct omap_dss_device *dssdev, bool enable)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_SET_TE;
+ p.u.te = enable;
+
+@@ -3348,12 +3247,12 @@ static void dsi_push_set_te(struct omap_display *display, bool enable)
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_set_update_mode(struct omap_display *display,
++static void dsi_push_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_SET_UPDATE_MODE;
+ p.u.update_mode = mode;
+
+@@ -3362,11 +3261,11 @@ static void dsi_push_set_update_mode(struct omap_display *display,
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_set_rotate(struct omap_display *display, int rotate)
++static void dsi_push_set_rotate(struct omap_dss_device *dssdev, int rotate)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_SET_ROTATE;
+ p.u.rotate = rotate;
+
+@@ -3375,11 +3274,11 @@ static void dsi_push_set_rotate(struct omap_display *display, int rotate)
+ dsi_push_cmd(&p);
+ }
+
+-static void dsi_push_set_mirror(struct omap_display *display, int mirror)
++static void dsi_push_set_mirror(struct omap_dss_device *dssdev, int mirror)
+ {
+ struct dsi_cmd_item p;
+
+- p.display = display;
++ p.dssdev = dssdev;
+ p.cmd = DSI_CMD_SET_MIRROR;
+ p.u.mirror = mirror;
+
+@@ -3388,7 +3287,7 @@ static void dsi_push_set_mirror(struct omap_display *display, int mirror)
+ dsi_push_cmd(&p);
+ }
+
+-static int dsi_wait_sync(struct omap_display *display)
++static int dsi_wait_sync(struct omap_dss_device *dssdev)
+ {
+ long wait = msecs_to_jiffies(2000);
+ struct completion compl;
+@@ -3396,7 +3295,7 @@ static int dsi_wait_sync(struct omap_display *display)
+ DSSDBGF("");
+
+ init_completion(&compl);
+- dsi_push_sync(display, &compl);
++ dsi_push_sync(dssdev, &compl);
+
+ DSSDBG("Waiting for SYNC to happen...\n");
+ wait = wait_for_completion_timeout(&compl, wait);
+@@ -3423,7 +3322,7 @@ static int dsi_wait_sync(struct omap_display *display)
+
+ /* Display funcs */
+
+-static int dsi_display_init_dispc(struct omap_display *display)
++static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
+ {
+ int r;
+
+@@ -3439,7 +3338,7 @@ static int dsi_display_init_dispc(struct omap_display *display)
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
+ dispc_enable_fifohandcheck(1);
+
+- dispc_set_tft_data_lines(display->ctrl->pixel_size);
++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
+
+ {
+ struct omap_video_timings timings = {
+@@ -3457,13 +3356,13 @@ static int dsi_display_init_dispc(struct omap_display *display)
+ return 0;
+ }
+
+-static void dsi_display_uninit_dispc(struct omap_display *display)
++static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
+ {
+ omap_dispc_unregister_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ }
+
+-static int dsi_display_init_dsi(struct omap_display *display)
++static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+ {
+ struct dsi_clock_info cinfo;
+ int r;
+@@ -3476,7 +3375,7 @@ static int dsi_display_init_dsi(struct omap_display *display)
+ if (r)
+ goto err0;
+
+- r = dsi_pll_calc_ddrfreq(display->hw_config.u.dsi.ddr_clk_hz, &cinfo);
++ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo);
+ if (r)
+ goto err1;
+
+@@ -3486,19 +3385,19 @@ static int dsi_display_init_dsi(struct omap_display *display)
+
+ DSSDBG("PLL OK\n");
+
+- r = dsi_complexio_init(display);
++ r = dsi_complexio_init(dssdev);
+ if (r)
+ goto err1;
+
+ _dsi_print_reset_status();
+
+- dsi_proto_timings(display);
+- dsi_set_lp_clk_divisor(display);
++ dsi_proto_timings(dssdev);
++ dsi_set_lp_clk_divisor(dssdev);
+
+ if (1)
+ _dsi_print_reset_status();
+
+- r = dsi_proto_config(display);
++ r = dsi_proto_config(dssdev);
+ if (r)
+ goto err2;
+
+@@ -3508,27 +3407,18 @@ static int dsi_display_init_dsi(struct omap_display *display)
+ dsi_if_enable(1);
+ dsi_force_tx_stop_mode_io();
+
+- if (display->ctrl && display->ctrl->enable) {
+- r = display->ctrl->enable(display);
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err3;
+ }
+
+- if (display->panel && display->panel->enable) {
+- r = display->panel->enable(display);
+- if (r)
+- goto err4;
+- }
+-
+ /* enable high-speed after initial config */
+ dsi_vc_enable_hs(0, 1);
+
+ dsi_bus_unlock();
+
+ return 0;
+-err4:
+- if (display->ctrl && display->ctrl->disable)
+- display->ctrl->disable(display);
+ err3:
+ dsi_if_enable(0);
+ err2:
+@@ -3540,13 +3430,11 @@ err0:
+ return r;
+ }
+
+-static void dsi_display_uninit_dsi(struct omap_display *display)
++static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
+ {
+ dsi_bus_lock();
+- if (display->panel && display->panel->disable)
+- display->panel->disable(display);
+- if (display->ctrl && display->ctrl->disable)
+- display->ctrl->disable(display);
++ if (dssdev->driver->disable)
++ dssdev->driver->disable(dssdev);
+ dsi_bus_unlock();
+
+ dsi_complexio_uninit();
+@@ -3569,7 +3457,7 @@ static int dsi_core_init(void)
+ return 0;
+ }
+
+-static int dsi_display_enable(struct omap_display *display)
++static int dsi_display_enable(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+@@ -3577,101 +3465,177 @@ static int dsi_display_enable(struct omap_display *display)
+
+ mutex_lock(&dsi.lock);
+
+- if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+- DSSERR("display already enabled\n");
+- r = -EINVAL;
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
+ goto err0;
+ }
+
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("dssdev already enabled\n");
++ r = -EINVAL;
++ goto err1;
++ }
++
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ r = _dsi_reset();
+ if (r)
+- return r;
++ goto err2;
+
+ dsi_core_init();
+
+- r = dsi_display_init_dispc(display);
++ r = dsi_display_init_dispc(dssdev);
+ if (r)
+- goto err1;
++ goto err2;
+
+- r = dsi_display_init_dsi(display);
++ r = dsi_display_init_dsi(dssdev);
+ if (r)
+- goto err2;
++ goto err3;
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ if (dsi.use_te || dsi.use_ext_te)
+- dsi_push_set_te(display, 1);
++ dsi_push_set_te(dssdev, 1);
+
+- dsi_push_set_update_mode(display, dsi.user_update_mode);
++ dsi_push_set_update_mode(dssdev, dsi.user_update_mode);
+ dsi.target_update_mode = dsi.user_update_mode;
+
+ mutex_unlock(&dsi.lock);
+
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+
++err3:
++ dsi_display_uninit_dispc(dssdev);
+ err2:
+- dsi_display_uninit_dispc(display);
+-err1:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
++err1:
++ omap_dss_stop_device(dssdev);
+ err0:
+ mutex_unlock(&dsi.lock);
+ DSSDBG("dsi_display_enable FAILED\n");
+ return r;
+ }
+
+-static void dsi_display_disable(struct omap_display *display)
++static void dsi_display_disable(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("dsi_display_disable\n");
+
+ mutex_lock(&dsi.lock);
+
+- if (display->state == OMAP_DSS_DISPLAY_DISABLED ||
+- display->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ goto end;
+
+ if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
+- dsi_push_set_update_mode(display, OMAP_DSS_UPDATE_DISABLED);
++ dsi_push_set_update_mode(dssdev, OMAP_DSS_UPDATE_DISABLED);
+ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
+ }
+
+- dsi_wait_sync(display);
++ dsi_wait_sync(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+- dsi_display_uninit_dispc(display);
++ dsi_display_uninit_dispc(dssdev);
+
+- dsi_display_uninit_dsi(display);
++ dsi_display_uninit_dsi(dssdev);
+
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
++
++ omap_dss_stop_device(dssdev);
+ end:
+ mutex_unlock(&dsi.lock);
+ }
+
+-static int dsi_display_suspend(struct omap_display *display)
++static int dsi_display_suspend(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("dsi_display_suspend\n");
+
+- dsi_display_disable(display);
++ mutex_lock(&dsi.lock);
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ goto end;
+
+- display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++ if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
++ dsi_push_set_update_mode(dssdev, OMAP_DSS_UPDATE_DISABLED);
++ dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
++ }
++
++ dsi_wait_sync(dssdev);
++
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
++
++ dsi_display_uninit_dispc(dssdev);
++
++ dsi_display_uninit_dsi(dssdev);
++
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++end:
++ mutex_unlock(&dsi.lock);
+
+ return 0;
+ }
+
+-static int dsi_display_resume(struct omap_display *display)
++static int dsi_display_resume(struct omap_dss_device *dssdev)
+ {
++ int r;
++
+ DSSDBG("dsi_display_resume\n");
+
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
+- return dsi_display_enable(display);
++ mutex_lock(&dsi.lock);
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
++ DSSERR("dssdev not suspended\n");
++ r = -EINVAL;
++ goto err0;
++ }
++
++ enable_clocks(1);
++ dsi_enable_pll_clock(1);
++
++ r = _dsi_reset();
++ if (r)
++ goto err1;
++
++ dsi_core_init();
++
++ r = dsi_display_init_dispc(dssdev);
++ if (r)
++ goto err1;
++
++ r = dsi_display_init_dsi(dssdev);
++ if (r)
++ goto err2;
++
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
++
++ if (dsi.use_te || dsi.use_ext_te)
++ dsi_push_set_te(dssdev, 1);
++
++ dsi_push_set_update_mode(dssdev, dsi.user_update_mode);
++ dsi.target_update_mode = dsi.user_update_mode;
++
++ mutex_unlock(&dsi.lock);
++
++ return dsi_wait_sync(dssdev);
++
++err2:
++ dsi_display_uninit_dispc(dssdev);
++err1:
++ enable_clocks(0);
++ dsi_enable_pll_clock(0);
++err0:
++ mutex_unlock(&dsi.lock);
++ DSSDBG("dsi_display_resume FAILED\n");
++ return r;
+ }
+
+-static int dsi_display_update(struct omap_display *display,
++static int dsi_display_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
+@@ -3682,7 +3646,7 @@ static int dsi_display_update(struct omap_display *display,
+ mutex_lock(&dsi.lock);
+
+ if (dsi.target_update_mode == OMAP_DSS_UPDATE_MANUAL)
+- dsi_push_update(display, x, y, w, h);
++ dsi_push_update(dssdev, x, y, w, h);
+ /* XXX else return error? */
+
+ mutex_unlock(&dsi.lock);
+@@ -3690,13 +3654,13 @@ static int dsi_display_update(struct omap_display *display,
+ return 0;
+ }
+
+-static int dsi_display_sync(struct omap_display *display)
++static int dsi_display_sync(struct omap_dss_device *dssdev)
+ {
+ DSSDBGF("");
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+ }
+
+-static int dsi_display_set_update_mode(struct omap_display *display,
++static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+ {
+ DSSDBGF("%d", mode);
+@@ -3704,7 +3668,7 @@ static int dsi_display_set_update_mode(struct omap_display *display,
+ mutex_lock(&dsi.lock);
+
+ if (dsi.target_update_mode != mode) {
+- dsi_push_set_update_mode(display, mode);
++ dsi_push_set_update_mode(dssdev, mode);
+
+ dsi.target_update_mode = mode;
+ dsi.user_update_mode = mode;
+@@ -3712,88 +3676,88 @@ static int dsi_display_set_update_mode(struct omap_display *display,
+
+ mutex_unlock(&dsi.lock);
+
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+ }
+
+ static enum omap_dss_update_mode dsi_display_get_update_mode(
+- struct omap_display *display)
++ struct omap_dss_device *dssdev)
+ {
+ return dsi.update_mode;
+ }
+
+-static int dsi_display_enable_te(struct omap_display *display, bool enable)
++static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ {
+ DSSDBGF("%d", enable);
+
+- if (!display->ctrl->enable_te)
++ if (!dssdev->driver->enable_te)
+ return -ENOENT;
+
+- dsi_push_set_te(display, enable);
++ dsi_push_set_te(dssdev, enable);
+
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+ }
+
+-static int dsi_display_get_te(struct omap_display *display)
++static int dsi_display_get_te(struct omap_dss_device *dssdev)
+ {
+ return dsi.use_te | dsi.use_ext_te;
+ }
+
+
+
+-static int dsi_display_set_rotate(struct omap_display *display, u8 rotate)
++static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
+ {
+ DSSDBGF("%d", rotate);
+
+- if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return -EINVAL;
+
+- dsi_push_set_rotate(display, rotate);
++ dsi_push_set_rotate(dssdev, rotate);
+
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+ }
+
+-static u8 dsi_display_get_rotate(struct omap_display *display)
++static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
+ {
+- if (!display->ctrl->set_rotate || !display->ctrl->get_rotate)
++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return 0;
+
+- return display->ctrl->get_rotate(display);
++ return dssdev->driver->get_rotate(dssdev);
+ }
+
+-static int dsi_display_set_mirror(struct omap_display *display, bool mirror)
++static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
+ {
+ DSSDBGF("%d", mirror);
+
+- if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return -EINVAL;
+
+- dsi_push_set_mirror(display, mirror);
++ dsi_push_set_mirror(dssdev, mirror);
+
+- return dsi_wait_sync(display);
++ return dsi_wait_sync(dssdev);
+ }
+
+-static bool dsi_display_get_mirror(struct omap_display *display)
++static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
+ {
+- if (!display->ctrl->set_mirror || !display->ctrl->get_mirror)
++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return 0;
+
+- return display->ctrl->get_mirror(display);
++ return dssdev->driver->get_mirror(dssdev);
+ }
+
+-static int dsi_display_run_test(struct omap_display *display, int test_num)
++static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
+ {
+ long wait = msecs_to_jiffies(60000);
+ struct completion compl;
+ int result;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+ DSSDBGF("%d", test_num);
+
+ init_completion(&compl);
+
+- dsi_push_test(display, test_num, &result, &compl);
++ dsi_push_test(dssdev, test_num, &result, &compl);
+
+ DSSDBG("Waiting for SYNC to happen...\n");
+ wait = wait_for_completion_timeout(&compl, wait);
+@@ -3807,7 +3771,7 @@ static int dsi_display_run_test(struct omap_display *display, int test_num)
+ return result;
+ }
+
+-static int dsi_display_memory_read(struct omap_display *display,
++static int dsi_display_memory_read(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+@@ -3818,10 +3782,10 @@ static int dsi_display_memory_read(struct omap_display *display,
+
+ DSSDBGF("");
+
+- if (!display->ctrl->memory_read)
++ if (!dssdev->driver->memory_read)
+ return -EINVAL;
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+ init_completion(&compl);
+@@ -3835,7 +3799,7 @@ static int dsi_display_memory_read(struct omap_display *display,
+ mem_read.ret_size = &ret_size;
+ mem_read.completion = &compl;
+
+- dsi_push_mem_read(display, &mem_read);
++ dsi_push_mem_read(dssdev, &mem_read);
+
+ DSSDBG("Waiting for SYNC to happen...\n");
+ wait = wait_for_completion_timeout(&compl, wait);
+@@ -3865,39 +3829,39 @@ static void dsi_configure_overlay(struct omap_overlay *ovl)
+ dispc_setup_plane_fifo(plane, low, high);
+ }
+
+-void dsi_init_display(struct omap_display *display)
++void dsi_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("DSI init\n");
+
+- display->enable = dsi_display_enable;
+- display->disable = dsi_display_disable;
+- display->suspend = dsi_display_suspend;
+- display->resume = dsi_display_resume;
+- display->update = dsi_display_update;
+- display->sync = dsi_display_sync;
+- display->set_update_mode = dsi_display_set_update_mode;
+- display->get_update_mode = dsi_display_get_update_mode;
+- display->enable_te = dsi_display_enable_te;
+- display->get_te = dsi_display_get_te;
++ dssdev->enable = dsi_display_enable;
++ dssdev->disable = dsi_display_disable;
++ dssdev->suspend = dsi_display_suspend;
++ dssdev->resume = dsi_display_resume;
++ dssdev->update = dsi_display_update;
++ dssdev->sync = dsi_display_sync;
++ dssdev->set_update_mode = dsi_display_set_update_mode;
++ dssdev->get_update_mode = dsi_display_get_update_mode;
++ dssdev->enable_te = dsi_display_enable_te;
++ dssdev->get_te = dsi_display_get_te;
+
+- display->get_rotate = dsi_display_get_rotate;
+- display->set_rotate = dsi_display_set_rotate;
++ dssdev->get_rotate = dsi_display_get_rotate;
++ dssdev->set_rotate = dsi_display_set_rotate;
+
+- display->get_mirror = dsi_display_get_mirror;
+- display->set_mirror = dsi_display_set_mirror;
++ dssdev->get_mirror = dsi_display_get_mirror;
++ dssdev->set_mirror = dsi_display_set_mirror;
+
+- display->run_test = dsi_display_run_test;
+- display->memory_read = dsi_display_memory_read;
++ dssdev->run_test = dsi_display_run_test;
++ dssdev->memory_read = dsi_display_memory_read;
+
+- display->configure_overlay = dsi_configure_overlay;
++ dssdev->configure_overlay = dsi_configure_overlay;
+
+- display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+- dsi.vc[0].display = display;
+- dsi.vc[1].display = display;
++ dsi.vc[0].dssdev = dssdev;
++ dsi.vc[1].dssdev = dssdev;
+ }
+
+-int dsi_init(void)
++int dsi_init(struct platform_device *pdev)
+ {
+ u32 rev;
+
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index d51ffe4..6180968 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -163,17 +163,22 @@ void dss_clk_disable(enum dss_clock clks);
+ unsigned long dss_clk_get_rate(enum dss_clock clk);
+ int dss_need_ctx_restore(void);
+ void dss_dump_clocks(struct seq_file *s);
+-
++struct bus_type *dss_get_bus(void);
+ int dss_dsi_power_up(void);
+ void dss_dsi_power_down(void);
+
++#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
++#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
++
+ /* display */
+-void dss_init_displays(struct platform_device *pdev);
+-void dss_uninit_displays(struct platform_device *pdev);
+-int dss_suspend_all_displays(void);
+-int dss_resume_all_displays(void);
+-struct omap_display *dss_get_display(int no);
+-bool dss_use_replication(struct omap_display *display,
++int dss_suspend_all_devices(void);
++int dss_resume_all_devices(void);
++
++void dss_init_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev);
++void dss_uninit_device(struct platform_device *pdev,
++ struct omap_dss_device *dssdev);
++bool dss_use_replication(struct omap_dss_device *dssdev,
+ enum omap_color_mode mode);
+
+ /* manager */
+@@ -181,10 +186,11 @@ int dss_init_overlay_managers(struct platform_device *pdev);
+ void dss_uninit_overlay_managers(struct platform_device *pdev);
+
+ /* overlay */
+-void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name);
++void dss_init_overlays(struct platform_device *pdev);
+ void dss_uninit_overlays(struct platform_device *pdev);
+-int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display);
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
+ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
+
+ /* DSS */
+ int dss_init(bool skip_init);
+@@ -208,10 +214,10 @@ void dss_set_dac_pwrdn_bgz(bool enable);
+ /* SDI */
+ int sdi_init(bool skip_init);
+ void sdi_exit(void);
+-void sdi_init_display(struct omap_display *display);
++void sdi_init_display(struct omap_dss_device *display);
+
+ /* DSI */
+-int dsi_init(void);
++int dsi_init(struct platform_device *pdev);
+ void dsi_exit(void);
+
+ void dsi_dump_clocks(struct seq_file *s);
+@@ -220,7 +226,7 @@ void dsi_dump_regs(struct seq_file *s);
+ void dsi_save_context(void);
+ void dsi_restore_context(void);
+
+-void dsi_init_display(struct omap_display *display);
++void dsi_init_display(struct omap_dss_device *display);
+ void dsi_irq_handler(void);
+ unsigned long dsi_get_dsi1_pll_rate(void);
+ unsigned long dsi_get_dsi2_pll_rate(void);
+@@ -233,7 +239,7 @@ void dsi_pll_uninit(void);
+ /* DPI */
+ int dpi_init(void);
+ void dpi_exit(void);
+-void dpi_init_display(struct omap_display *display);
++void dpi_init_display(struct omap_dss_device *dssdev);
+
+ /* DISPC */
+ int dispc_init(void);
+@@ -306,7 +312,7 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings);
+ unsigned long dispc_fclk_rate(void);
+ unsigned long dispc_lclk_rate(void);
+ unsigned long dispc_pclk_rate(void);
+-void dispc_set_pol_freq(struct omap_panel *panel);
++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
+ void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+ u16 *lck_div, u16 *pck_div);
+ int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
+@@ -315,16 +321,16 @@ int dispc_set_clock_div(struct dispc_clock_info *cinfo);
+ int dispc_get_clock_div(struct dispc_clock_info *cinfo);
+ void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
+
+-void dispc_setup_partial_planes(struct omap_display *display,
++void dispc_setup_partial_planes(struct omap_dss_device *dssdev,
+ u16 *x, u16 *y, u16 *w, u16 *h);
+-void dispc_draw_partial_planes(struct omap_display *display);
++void dispc_draw_partial_planes(struct omap_dss_device *dssdev);
+
+
+ /* VENC */
+-int venc_init(void);
++int venc_init(struct platform_device *pdev);
+ void venc_exit(void);
+ void venc_dump_regs(struct seq_file *s);
+-void venc_init_display(struct omap_display *display);
++void venc_init_display(struct omap_dss_device *display);
+
+ /* RFBI */
+ int rfbi_init(void);
+@@ -337,6 +343,6 @@ void rfbi_transfer_area(u16 width, u16 height,
+ void (callback)(void *data), void *data);
+ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
+ unsigned long rfbi_get_max_tx_rate(void);
+-void rfbi_init_display(struct omap_display *display);
++void rfbi_init_display(struct omap_dss_device *display);
+
+ #endif
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 8d5d00f..c68b9af 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -41,58 +41,68 @@ static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
+ static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+- mgr->display ? mgr->display->name : "<none>");
++ mgr->device ? mgr->device->name : "<none>");
+ }
+
+ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const char *buf, size_t size)
+ {
+- int r, i;
+- int len = size;
+- struct omap_display *display = NULL;
++ int r = 0;
++ size_t len = size;
++ struct omap_dss_device *dssdev = NULL;
++
++ int match(struct omap_dss_device *dssdev, void *data)
++ {
++ const char *str = data;
++ return strcmp(dssdev->name, str) == 0;
++ }
+
+ if (buf[size-1] == '\n')
+ --len;
+
+ if (len > 0) {
+- for (i = 0; i < omap_dss_get_num_displays(); ++i) {
+- display = dss_get_display(i);
++ char name[64];
++ int n;
+
+- if (strncmp(buf, display->name, len) == 0)
+- break;
++ n = min(len, sizeof(name) - 1);
++ strncpy(name, buf, n);
++ name[n - 1] = 0;
+
+- display = NULL;
+- }
++ dssdev = omap_dss_find_device(name, match);
+ }
+
+- if (len > 0 && display == NULL)
++ if (len > 0 && dssdev == NULL)
+ return -EINVAL;
+
+- if (display)
+- DSSDBG("display %s found\n", display->name);
++ if (dssdev)
++ DSSDBG("display %s found\n", dssdev->name);
+
+- if (mgr->display) {
+- r = mgr->unset_display(mgr);
++ if (mgr->device) {
++ r = mgr->unset_device(mgr);
+ if (r) {
+ DSSERR("failed to unset display\n");
+- return r;
++ goto put_device;
+ }
+ }
+
+- if (display) {
+- r = mgr->set_display(mgr, display);
++ if (dssdev) {
++ r = mgr->set_device(mgr, dssdev);
+ if (r) {
+ DSSERR("failed to set manager\n");
+- return r;
++ goto put_device;
+ }
+
+ r = mgr->apply(mgr);
+ if (r) {
+ DSSERR("failed to apply dispc config\n");
+- return r;
++ goto put_device;
+ }
+ }
+
+- return size;
++put_device:
++ if (dssdev)
++ omap_dss_put_device(dssdev);
++
++ return r ? r : size;
+ }
+
+ static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+@@ -334,21 +344,21 @@ static struct kobj_type manager_ktype = {
+ .default_attrs = manager_sysfs_attrs,
+ };
+
+-static int omap_dss_set_display(struct omap_overlay_manager *mgr,
+- struct omap_display *display)
++static int omap_dss_set_device(struct omap_overlay_manager *mgr,
++ struct omap_dss_device *dssdev)
+ {
+ int i;
+ int r;
+
+- if (display->manager) {
++ if (dssdev->manager) {
+ DSSERR("display '%s' already has a manager '%s'\n",
+- display->name, display->manager->name);
++ dssdev->name, dssdev->manager->name);
+ return -EINVAL;
+ }
+
+- if ((mgr->supported_displays & display->type) == 0) {
++ if ((mgr->supported_displays & dssdev->type) == 0) {
+ DSSERR("display '%s' does not support manager '%s'\n",
+- display->name, mgr->name);
++ dssdev->name, mgr->name);
+ return -EINVAL;
+ }
+
+@@ -358,26 +368,26 @@ static int omap_dss_set_display(struct omap_overlay_manager *mgr,
+ if (ovl->manager != mgr || !ovl->info.enabled)
+ continue;
+
+- r = dss_check_overlay(ovl, display);
++ r = dss_check_overlay(ovl, dssdev);
+ if (r)
+ return r;
+ }
+
+- display->manager = mgr;
+- mgr->display = display;
++ dssdev->manager = mgr;
++ mgr->device = dssdev;
+
+ return 0;
+ }
+
+-static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
++static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
+ {
+- if (!mgr->display) {
++ if (!mgr->device) {
+ DSSERR("failed to unset display, display not set.\n");
+ return -EINVAL;
+ }
+
+- mgr->display->manager = NULL;
+- mgr->display = NULL;
++ mgr->device->manager = NULL;
++ mgr->device = NULL;
+
+ return 0;
+ }
+@@ -385,7 +395,7 @@ static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
+
+ static int overlay_enabled(struct omap_overlay *ovl)
+ {
+- return ovl->info.enabled && ovl->manager && ovl->manager->display;
++ return ovl->info.enabled && ovl->manager && ovl->manager->device;
+ }
+
+ /* We apply settings to both managers here so that we can use optimizations
+@@ -396,7 +406,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ int i;
+ int ret = 0;
+ enum omap_dss_update_mode mode;
+- struct omap_display *display;
++ struct omap_dss_device *dssdev;
+ struct omap_overlay *ovl;
+ bool ilace = 0;
+ int outw, outh;
+@@ -419,9 +429,9 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ continue;
+ }
+
+- display = ovl->manager->display;
++ dssdev = ovl->manager->device;
+
+- if (dss_check_overlay(ovl, display)) {
++ if (dss_check_overlay(ovl, dssdev)) {
+ dispc_enable_plane(ovl->id, 0);
+ continue;
+ }
+@@ -431,14 +441,14 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ /* On a manual update display, in manual update mode, update()
+ * handles configuring planes */
+ mode = OMAP_DSS_UPDATE_AUTO;
+- if (display->get_update_mode)
+- mode = display->get_update_mode(mgr->display);
++ if (dssdev->get_update_mode)
++ mode = dssdev->get_update_mode(dssdev);
+
+- if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ mode != OMAP_DSS_UPDATE_AUTO)
+ continue;
+
+- if (display->type == OMAP_DISPLAY_TYPE_VENC)
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+ ilace = 1;
+
+ if (ovl->info.out_width == 0)
+@@ -474,7 +484,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ continue;
+ }
+
+- if (dss_use_replication(display, ovl->info.color_mode))
++ if (dss_use_replication(dssdev, ovl->info.color_mode))
+ dispc_enable_replication(ovl->id, true);
+ else
+ dispc_enable_replication(ovl->id, false);
+@@ -498,7 +508,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ continue;
+ }
+
+- ovl->manager->display->configure_overlay(ovl);
++ ovl->manager->device->configure_overlay(ovl);
+ }
+
+ /* Issue GO for managers */
+@@ -506,15 +516,15 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
+ continue;
+
+- display = mgr->display;
++ dssdev = mgr->device;
+
+- if (!display)
++ if (!dssdev)
+ continue;
+
+ /* We don't need GO with manual update display. LCD iface will
+ * always be turned off after frame, and new settings will
+ * be taken in to use at next update */
+- if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+ continue;
+
+ dispc_go(mgr->id);
+@@ -605,8 +615,8 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ break;
+ }
+
+- mgr->set_display = &omap_dss_set_display;
+- mgr->unset_display = &omap_dss_unset_display;
++ mgr->set_device = &omap_dss_set_device;
++ mgr->unset_device = &omap_dss_unset_device;
+ mgr->apply = &omap_dss_mgr_apply;
+ mgr->set_default_color = &omap_dss_mgr_set_def_color;
+ mgr->set_trans_key_type_and_value =
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 035a57a..3704727 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -301,13 +301,13 @@ static struct kobj_type overlay_ktype = {
+ };
+
+ /* Check if overlay parameters are compatible with display */
+-int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display)
++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
+ {
+ struct omap_overlay_info *info;
+ u16 outw, outh;
+ u16 dw, dh;
+
+- if (!display)
++ if (!dssdev)
+ return 0;
+
+ if (!ovl->info.enabled)
+@@ -320,7 +320,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_display *display)
+ return -EINVAL;
+ }
+
+- display->get_resolution(display, &dw, &dh);
++ dssdev->get_resolution(dssdev, &dw, &dh);
+
+ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
+ ovl->id,
+@@ -374,7 +374,7 @@ static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
+ ovl->info = *info;
+
+ if (ovl->manager) {
+- r = dss_check_overlay(ovl, ovl->manager->display);
++ r = dss_check_overlay(ovl, ovl->manager->device);
+ if (r) {
+ ovl->info = old_info;
+ return r;
+@@ -400,7 +400,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
+ ovl->name, ovl->manager->name);
+ }
+
+- r = dss_check_overlay(ovl, mgr->display);
++ r = dss_check_overlay(ovl, mgr->device);
+ if (r)
+ return r;
+
+@@ -455,12 +455,9 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
+ mgr->overlays = dispc_overlays;
+ }
+
+-void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
++void dss_init_overlays(struct platform_device *pdev)
+ {
+ int i, r;
+- struct omap_overlay_manager *lcd_mgr;
+- struct omap_overlay_manager *tv_mgr;
+- struct omap_overlay_manager *def_mgr = NULL;
+
+ INIT_LIST_HEAD(&overlay_list);
+
+@@ -515,71 +512,49 @@ void dss_init_overlays(struct platform_device *pdev, const char *def_disp_name)
+
+ dispc_overlays[i] = ovl;
+ }
++}
++
++/* connect overlays to the new device, if not already connected. if force
++ * selected, connect always. */
++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
++{
++ int i;
++ struct omap_overlay_manager *lcd_mgr;
++ struct omap_overlay_manager *tv_mgr;
++ struct omap_overlay_manager *mgr = NULL;
+
+ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
+ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
+
+- if (def_disp_name) {
+- for (i = 0; i < omap_dss_get_num_displays() ; i++) {
+- struct omap_display *display = dss_get_display(i);
+-
+- if (strcmp(display->name, def_disp_name) == 0) {
+- if (display->type != OMAP_DISPLAY_TYPE_VENC) {
+- lcd_mgr->set_display(lcd_mgr, display);
+- def_mgr = lcd_mgr;
+- } else {
+- lcd_mgr->set_display(tv_mgr, display);
+- def_mgr = tv_mgr;
+- }
+-
+- break;
+- }
+- }
+-
+- if (!def_mgr)
+- DSSWARN("default display %s not found\n",
+- def_disp_name);
+- }
+-
+- if (def_mgr != lcd_mgr) {
+- /* connect lcd manager to first non-VENC display found */
+- for (i = 0; i < omap_dss_get_num_displays(); i++) {
+- struct omap_display *display = dss_get_display(i);
+- if (display->type != OMAP_DISPLAY_TYPE_VENC) {
+- lcd_mgr->set_display(lcd_mgr, display);
+-
+- if (!def_mgr)
+- def_mgr = lcd_mgr;
+-
+- break;
+- }
++ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
++ if (!lcd_mgr->device || force) {
++ if (lcd_mgr->device)
++ lcd_mgr->unset_device(lcd_mgr);
++ lcd_mgr->set_device(lcd_mgr, dssdev);
++ mgr = lcd_mgr;
+ }
+ }
+
+- if (def_mgr != tv_mgr) {
+- /* connect tv manager to first VENC display found */
+- for (i = 0; i < omap_dss_get_num_displays(); i++) {
+- struct omap_display *display = dss_get_display(i);
+- if (display->type == OMAP_DISPLAY_TYPE_VENC) {
+- tv_mgr->set_display(tv_mgr, display);
+-
+- if (!def_mgr)
+- def_mgr = tv_mgr;
+-
+- break;
+- }
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
++ if (!tv_mgr->device || force) {
++ if (tv_mgr->device)
++ tv_mgr->unset_device(tv_mgr);
++ tv_mgr->set_device(tv_mgr, dssdev);
++ mgr = tv_mgr;
+ }
+ }
+
+- /* connect all dispc overlays to def_mgr */
+- if (def_mgr) {
++ if (mgr) {
+ for (i = 0; i < 3; i++) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+- omap_dss_set_manager(ovl, def_mgr);
++ if (!ovl->manager || force) {
++ if (ovl->manager)
++ omap_dss_unset_manager(ovl);
++ omap_dss_set_manager(ovl, mgr);
++ }
+ }
+ }
+-
+ #ifdef L4_EXAMPLE
+ /* setup L4 overlay as an example */
+ {
+diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
+index 3e9ae1e..e3cf799 100644
+--- a/drivers/video/omap2/dss/rfbi.c
++++ b/drivers/video/omap2/dss/rfbi.c
+@@ -119,7 +119,7 @@ static struct {
+ void (*framedone_callback)(void *data);
+ void *framedone_callback_data;
+
+- struct omap_display *display[2];
++ struct omap_dss_device *dssdev[2];
+
+ struct kfifo *cmd_fifo;
+ spinlock_t cmd_lock;
+@@ -938,12 +938,12 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
+ }
+ EXPORT_SYMBOL(rfbi_configure);
+
+-static int rfbi_find_display(struct omap_display *disp)
++static int rfbi_find_display(struct omap_dss_device *dssdev)
+ {
+- if (disp == rfbi.display[0])
++ if (dssdev == rfbi.dssdev[0])
+ return 0;
+
+- if (disp == rfbi.display[1])
++ if (dssdev == rfbi.dssdev[1])
+ return 1;
+
+ BUG();
+@@ -961,7 +961,7 @@ static void signal_fifo_waiters(void)
+ }
+
+ /* returns 1 for async op, and 0 for sync op */
+-static int do_update(struct omap_display *display, struct update_region *upd)
++static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
+ {
+ u16 x = upd->x;
+ u16 y = upd->y;
+@@ -970,18 +970,18 @@ static int do_update(struct omap_display *display, struct update_region *upd)
+
+ perf_mark_setup();
+
+- if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+- /*display->ctrl->enable_te(display, 1); */
+- dispc_setup_partial_planes(display, &x, &y, &w, &h);
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ /*dssdev->driver->enable_te(dssdev, 1); */
++ dispc_setup_partial_planes(dssdev, &x, &y, &w, &h);
+ }
+
+ #ifdef MEASURE_PERF
+ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
+ #endif
+
+- display->ctrl->setup_update(display, x, y, w, h);
++ dssdev->driver->setup_update(dssdev, x, y, w, h);
+
+- if (display->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ rfbi_transfer_area(w, h, NULL, NULL);
+ return 1;
+ } else {
+@@ -989,7 +989,7 @@ static int do_update(struct omap_display *display, struct update_region *upd)
+ void __iomem *addr;
+ int scr_width;
+
+- ovl = display->manager->overlays[0];
++ ovl = dssdev->manager->overlays[0];
+ scr_width = ovl->info.screen_width;
+ addr = ovl->info.vaddr;
+
+@@ -1005,7 +1005,7 @@ static void process_cmd_fifo(void)
+ {
+ int len;
+ struct update_param p;
+- struct omap_display *display;
++ struct omap_dss_device *dssdev;
+ unsigned long flags;
+
+ if (atomic_inc_return(&rfbi.cmd_pending) != 1)
+@@ -1030,10 +1030,10 @@ static void process_cmd_fifo(void)
+ BUG_ON(len != sizeof(struct update_param));
+ BUG_ON(p.rfbi_module > 1);
+
+- display = rfbi.display[p.rfbi_module];
++ dssdev = rfbi.dssdev[p.rfbi_module];
+
+ if (p.cmd == RFBI_CMD_UPDATE) {
+- if (do_update(display, &p.par.r))
++ if (do_update(dssdev, &p.par.r))
+ break; /* async op */
+ } else if (p.cmd == RFBI_CMD_SYNC) {
+ DSSDBG("Signaling SYNC done!\n");
+@@ -1203,7 +1203,7 @@ void rfbi_exit(void)
+ }
+
+ /* struct omap_display support */
+-static int rfbi_display_update(struct omap_display *display,
++static int rfbi_display_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+ int rfbi_module;
+@@ -1211,19 +1211,19 @@ static int rfbi_display_update(struct omap_display *display,
+ if (w == 0 || h == 0)
+ return 0;
+
+- rfbi_module = rfbi_find_display(display);
++ rfbi_module = rfbi_find_display(dssdev);
+
+ rfbi_push_update(rfbi_module, x, y, w, h);
+
+ return 0;
+ }
+
+-static int rfbi_display_sync(struct omap_display *display)
++static int rfbi_display_sync(struct omap_dss_device *dssdev)
+ {
+ struct completion sync_comp;
+ int rfbi_module;
+
+- rfbi_module = rfbi_find_display(display);
++ rfbi_module = rfbi_find_display(dssdev);
+
+ init_completion(&sync_comp);
+ rfbi_push_sync(rfbi_module, &sync_comp);
+@@ -1233,72 +1233,76 @@ static int rfbi_display_sync(struct omap_display *display)
+ return 0;
+ }
+
+-static int rfbi_display_enable_te(struct omap_display *display, bool enable)
++static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ {
+- display->ctrl->enable_te(display, enable);
++ dssdev->driver->enable_te(dssdev, enable);
+ return 0;
+ }
+
+-static int rfbi_display_enable(struct omap_display *display)
++static int rfbi_display_enable(struct omap_dss_device *dssdev)
+ {
+ int r;
+
+- BUG_ON(display->panel == NULL || display->ctrl == NULL);
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
+
+ r = omap_dispc_register_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ if (r) {
+ DSSERR("can't get FRAMEDONE irq\n");
+- return r;
++ goto err1;
+ }
+
+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
+
+- dispc_set_tft_data_lines(display->ctrl->pixel_size);
++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
+
+- rfbi_configure(display->hw_config.u.rfbi.channel,
+- display->ctrl->pixel_size,
+- display->hw_config.u.rfbi.data_lines);
++ rfbi_configure(dssdev->phy.rfbi.channel,
++ dssdev->ctrl.pixel_size,
++ dssdev->phy.rfbi.data_lines);
+
+- rfbi_set_timings(display->hw_config.u.rfbi.channel,
+- &display->ctrl->timings);
++ rfbi_set_timings(dssdev->phy.rfbi.channel,
++ &dssdev->ctrl.rfbi_timings);
+
+
+- if (display->ctrl && display->ctrl->enable) {
+- r = display->ctrl->enable(display);
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
+ if (r)
+- goto err;
+- }
+-
+- if (display->panel && display->panel->enable) {
+- r = display->panel->enable(display);
+- if (r)
+- goto err;
++ goto err2;
+ }
+
+ return 0;
+-err:
+- return -ENODEV;
++err2:
++ omap_dispc_unregister_isr(framedone_callback, NULL,
++ DISPC_IRQ_FRAMEDONE);
++err1:
++ omap_dss_stop_device(dssdev);
++err0:
++ return r;
+ }
+
+-static void rfbi_display_disable(struct omap_display *display)
++static void rfbi_display_disable(struct omap_dss_device *dssdev)
+ {
+- display->ctrl->disable(display);
++ dssdev->driver->disable(dssdev);
+ omap_dispc_unregister_isr(framedone_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
++ omap_dss_stop_device(dssdev);
+ }
+
+-void rfbi_init_display(struct omap_display *display)
++void rfbi_init_display(struct omap_dss_device *dssdev)
+ {
+- display->enable = rfbi_display_enable;
+- display->disable = rfbi_display_disable;
+- display->update = rfbi_display_update;
+- display->sync = rfbi_display_sync;
+- display->enable_te = rfbi_display_enable_te;
++ dssdev->enable = rfbi_display_enable;
++ dssdev->disable = rfbi_display_disable;
++ dssdev->update = rfbi_display_update;
++ dssdev->sync = rfbi_display_sync;
++ dssdev->enable_te = rfbi_display_enable_te;
+
+- rfbi.display[display->hw_config.u.rfbi.channel] = display;
++ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
+
+- display->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+ }
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+index fbff2b2..393fcd5 100644
+--- a/drivers/video/omap2/dss/sdi.c
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -43,18 +43,25 @@ static void sdi_basic_init(void)
+ dispc_lcd_enable_signal_polarity(1);
+ }
+
+-static int sdi_display_enable(struct omap_display *display)
++static int sdi_display_enable(struct omap_dss_device *dssdev)
+ {
++ struct omap_video_timings *t = &dssdev->panel.timings;
+ struct dispc_clock_info cinfo;
+ u16 lck_div, pck_div;
+ unsigned long fck;
+- struct omap_panel *panel = display->panel;
+ unsigned long pck;
+ int r;
+
+- if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
+- DSSERR("display already enabled\n");
+- return -EINVAL;
++ r = omap_dss_start_device(dssdev);
++ if (r) {
++ DSSERR("failed to start device\n");
++ goto err0;
++ }
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
++ DSSERR("dssdev already enabled\n");
++ r = -EINVAL;
++ goto err1;
+ }
+
+ /* In case of skip_init sdi_init has already enabled the clocks */
+@@ -64,18 +71,19 @@ static int sdi_display_enable(struct omap_display *display)
+ sdi_basic_init();
+
+ /* 15.5.9.1.2 */
+- panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
++ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
+
+- dispc_set_pol_freq(panel);
++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
++ dssdev->panel.acb);
+
+ if (!sdi.skip_init)
+- r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
++ r = dispc_calc_clock_div(1, t->pixel_clock * 1000,
+ &cinfo);
+ else
+ r = dispc_get_clock_div(&cinfo);
+
+ if (r)
+- goto err0;
++ goto err2;
+
+ fck = cinfo.fck;
+ lck_div = cinfo.lck_div;
+@@ -83,57 +91,62 @@ static int sdi_display_enable(struct omap_display *display)
+
+ pck = fck / lck_div / pck_div / 1000;
+
+- if (pck != panel->timings.pixel_clock) {
++ if (pck != t->pixel_clock) {
+ DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
+ "got %lu kHz\n",
+- panel->timings.pixel_clock, pck);
++ t->pixel_clock, pck);
+
+- panel->timings.pixel_clock = pck;
++ t->pixel_clock = pck;
+ }
+
+
+- dispc_set_lcd_timings(&panel->timings);
++ dispc_set_lcd_timings(t);
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r)
+- goto err1;
++ goto err2;
+
+ if (!sdi.skip_init) {
+- dss_sdi_init(display->hw_config.u.sdi.datapairs);
++ dss_sdi_init(dssdev->phy.sdi.datapairs);
+ dss_sdi_enable();
+ mdelay(2);
+ }
+
+ dispc_enable_lcd_out(1);
+
+- r = panel->enable(display);
+- if (r)
+- goto err2;
++ if (dssdev->driver->enable) {
++ r = dssdev->driver->enable(dssdev);
++ if (r)
++ goto err3;
++ }
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ sdi.skip_init = 0;
+
+ return 0;
+-err2:
++err3:
+ dispc_enable_lcd_out(0);
++err2:
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ err1:
++ omap_dss_stop_device(dssdev);
+ err0:
+- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ return r;
+ }
+
+-static int sdi_display_resume(struct omap_display *display);
++static int sdi_display_resume(struct omap_dss_device *dssdev);
+
+-static void sdi_display_disable(struct omap_display *display)
++static void sdi_display_disable(struct omap_dss_device *dssdev)
+ {
+- if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ return;
+
+- if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
+- sdi_display_resume(display);
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
++ sdi_display_resume(dssdev);
+
+- display->panel->disable(display);
++ if (dssdev->driver->disable)
++ dssdev->driver->disable(dssdev);
+
+ dispc_enable_lcd_out(0);
+
+@@ -141,16 +154,18 @@ static void sdi_display_disable(struct omap_display *display)
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
++
++ omap_dss_stop_device(dssdev);
+ }
+
+-static int sdi_display_suspend(struct omap_display *display)
++static int sdi_display_suspend(struct omap_dss_device *dssdev)
+ {
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EINVAL;
+
+- if (display->panel->suspend)
+- display->panel->suspend(display);
++ if (dssdev->driver->suspend)
++ dssdev->driver->suspend(dssdev);
+
+ dispc_enable_lcd_out(0);
+
+@@ -158,14 +173,14 @@ static int sdi_display_suspend(struct omap_display *display)
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ return 0;
+ }
+
+-static int sdi_display_resume(struct omap_display *display)
++static int sdi_display_resume(struct omap_dss_device *dssdev)
+ {
+- if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+@@ -175,15 +190,15 @@ static int sdi_display_resume(struct omap_display *display)
+
+ dispc_enable_lcd_out(1);
+
+- if (display->panel->resume)
+- display->panel->resume(display);
++ if (dssdev->driver->resume)
++ dssdev->driver->resume(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+ }
+
+-static int sdi_display_set_update_mode(struct omap_display *display,
++static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+ {
+ if (mode == OMAP_DSS_UPDATE_MANUAL)
+@@ -201,29 +216,29 @@ static int sdi_display_set_update_mode(struct omap_display *display,
+ }
+
+ static enum omap_dss_update_mode sdi_display_get_update_mode(
+- struct omap_display *display)
++ struct omap_dss_device *dssdev)
+ {
+ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
+ OMAP_DSS_UPDATE_DISABLED;
+ }
+
+-static void sdi_get_timings(struct omap_display *display,
++static void sdi_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+- *timings = display->panel->timings;
++ *timings = dssdev->panel.timings;
+ }
+
+-void sdi_init_display(struct omap_display *display)
++void sdi_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("SDI init\n");
+
+- display->enable = sdi_display_enable;
+- display->disable = sdi_display_disable;
+- display->suspend = sdi_display_suspend;
+- display->resume = sdi_display_resume;
+- display->set_update_mode = sdi_display_set_update_mode;
+- display->get_update_mode = sdi_display_get_update_mode;
+- display->get_timings = sdi_get_timings;
++ dssdev->enable = sdi_display_enable;
++ dssdev->disable = sdi_display_disable;
++ dssdev->suspend = sdi_display_suspend;
++ dssdev->resume = sdi_display_resume;
++ dssdev->set_update_mode = sdi_display_set_update_mode;
++ dssdev->get_update_mode = sdi_display_get_update_mode;
++ dssdev->get_timings = sdi_get_timings;
+ }
+
+ int sdi_init(bool skip_init)
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index b0f0795..a83d170 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -31,6 +31,7 @@
+ #include <linux/delay.h>
+ #include <linux/string.h>
+ #include <linux/seq_file.h>
++#include <linux/platform_device.h>
+
+ #include <mach/display.h>
+ #include <mach/cpu.h>
+@@ -292,10 +293,6 @@ static struct {
+ u32 wss_data;
+ } venc;
+
+-static struct omap_panel venc_panel = {
+- .name = "tv-out",
+-};
+-
+ static inline void venc_write_reg(int idx, u32 val)
+ {
+ __raw_writel(val, venc.base + idx);
+@@ -400,7 +397,76 @@ static const struct venc_config *venc_timings_to_config(
+ BUG();
+ }
+
+-int venc_init(void)
++
++
++
++
++/* driver */
++static int venc_panel_probe(struct omap_dss_device *dssdev)
++{
++ //dssdev->name = "tv-out";
++ dssdev->panel.timings = omap_dss_pal_timings;
++
++ return 0;
++}
++
++static void venc_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++static int venc_panel_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ return r;
++}
++
++static void venc_panel_disable(struct omap_dss_device *dssdev)
++{
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++
++ /* wait at least 5 vsyncs after disabling the LCD */
++
++ msleep(100);
++}
++
++static int venc_panel_suspend(struct omap_dss_device *dssdev)
++{
++ venc_panel_disable(dssdev);
++ return 0;
++}
++
++static int venc_panel_resume(struct omap_dss_device *dssdev)
++{
++ return venc_panel_enable(dssdev);
++}
++
++static struct omap_dss_driver venc_driver = {
++ .probe = venc_panel_probe,
++ .remove = venc_panel_remove,
++
++ .enable = venc_panel_enable,
++ .disable = venc_panel_disable,
++ .suspend = venc_panel_suspend,
++ .resume = venc_panel_resume,
++
++ .driver = {
++ .name = "venc",
++ .owner = THIS_MODULE,
++ },
++};
++/* driver end */
++
++
++
++int venc_init(struct platform_device *pdev)
+ {
+ u8 rev_id;
+
+@@ -408,8 +474,6 @@ int venc_init(void)
+
+ venc.wss_data = 0;
+
+- venc_panel.timings = omap_dss_pal_timings;
+-
+ venc.base = ioremap(VENC_BASE, SZ_1K);
+ if (!venc.base) {
+ DSSERR("can't ioremap VENC\n");
+@@ -423,25 +487,29 @@ int venc_init(void)
+
+ venc_enable_clocks(0);
+
+- return 0;
++ return omap_dss_register_driver(&venc_driver);
++
++ //return 0;
+ }
+
+ void venc_exit(void)
+ {
++ omap_dss_unregister_driver(&venc_driver);
++
+ iounmap(venc.base);
+ }
+
+-static void venc_power_on(struct omap_display *display)
++static void venc_power_on(struct omap_dss_device *dssdev)
+ {
+ venc_enable_clocks(1);
+
+ venc_reset();
+- venc_write_config(venc_timings_to_config(&display->panel->timings));
++ venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
+
+- dss_set_venc_output(display->hw_config.u.venc.type);
++ dss_set_venc_output(dssdev->phy.venc.type);
+ dss_set_dac_pwrdn_bgz(1);
+
+- if (display->hw_config.u.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
++ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
+ if (cpu_is_omap24xx())
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
+ else
+@@ -450,29 +518,29 @@ static void venc_power_on(struct omap_display *display)
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
+ }
+
+- dispc_set_digit_size(display->panel->timings.x_res,
+- display->panel->timings.y_res/2);
++ dispc_set_digit_size(dssdev->panel.timings.x_res,
++ dssdev->panel.timings.y_res/2);
+
+- if (display->hw_config.panel_enable)
+- display->hw_config.panel_enable(display);
++ if (dssdev->platform_enable)
++ dssdev->platform_enable(dssdev);
+
+ dispc_enable_digit_out(1);
+ }
+
+-static void venc_power_off(struct omap_display *display)
++static void venc_power_off(struct omap_dss_device *dssdev)
+ {
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+ dss_set_dac_pwrdn_bgz(0);
+
+ dispc_enable_digit_out(0);
+
+- if (display->hw_config.panel_disable)
+- display->hw_config.panel_disable(display);
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
+
+ venc_enable_clocks(0);
+ }
+
+-static int venc_enable_display(struct omap_display *display)
++static int venc_enable_display(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+@@ -480,43 +548,45 @@ static int venc_enable_display(struct omap_display *display)
+
+ mutex_lock(&venc.venc_lock);
+
+- if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ r = -EINVAL;
+ goto err;
+ }
+
+- venc_power_on(display);
++ venc_power_on(dssdev);
++
++ venc.wss_data = 0;
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+ err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+ }
+
+-static void venc_disable_display(struct omap_display *display)
++static void venc_disable_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("venc_disable_display\n");
+
+ mutex_lock(&venc.venc_lock);
+
+- if (display->state == OMAP_DSS_DISPLAY_DISABLED)
++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+ goto end;
+
+- if (display->state == OMAP_DSS_DISPLAY_SUSPENDED) {
++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
+ /* suspended is the same as disabled with venc */
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+ goto end;
+ }
+
+- venc_power_off(display);
++ venc_power_off(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_DISABLED;
++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+ end:
+ mutex_unlock(&venc.venc_lock);
+ }
+
+-static int venc_display_suspend(struct omap_display *display)
++static int venc_display_suspend(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+@@ -524,21 +594,21 @@ static int venc_display_suspend(struct omap_display *display)
+
+ mutex_lock(&venc.venc_lock);
+
+- if (display->state != OMAP_DSS_DISPLAY_ACTIVE) {
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ r = -EINVAL;
+ goto err;
+ }
+
+- venc_power_off(display);
++ venc_power_off(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_SUSPENDED;
++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+ err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+ }
+
+-static int venc_display_resume(struct omap_display *display)
++static int venc_display_resume(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+@@ -546,44 +616,44 @@ static int venc_display_resume(struct omap_display *display)
+
+ mutex_lock(&venc.venc_lock);
+
+- if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) {
++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+ r = -EINVAL;
+ goto err;
+ }
+
+- venc_power_on(display);
++ venc_power_on(dssdev);
+
+- display->state = OMAP_DSS_DISPLAY_ACTIVE;
++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+ err:
+ mutex_unlock(&venc.venc_lock);
+
+ return r;
+ }
+
+-static void venc_get_timings(struct omap_display *display,
++static void venc_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+- *timings = venc_panel.timings;
++ *timings = dssdev->panel.timings;
+ }
+
+-static void venc_set_timings(struct omap_display *display,
++static void venc_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+ DSSDBG("venc_set_timings\n");
+
+ /* Reset WSS data when the TV standard changes. */
+- if (memcmp(&display->panel->timings, timings, sizeof(*timings)))
++ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
+ venc.wss_data = 0;
+
+- display->panel->timings = *timings;
+- if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
++ dssdev->panel.timings = *timings;
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ /* turn the venc off and on to get new timings to use */
+- venc_disable_display(display);
+- venc_enable_display(display);
++ venc_disable_display(dssdev);
++ venc_enable_display(dssdev);
+ }
+ }
+
+-static int venc_check_timings(struct omap_display *display,
++static int venc_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+ {
+ DSSDBG("venc_check_timings\n");
+@@ -597,14 +667,13 @@ static int venc_check_timings(struct omap_display *display,
+ return -EINVAL;
+ }
+
+-static u32 venc_get_wss(struct omap_display *display)
++static u32 venc_get_wss(struct omap_dss_device *dssdev)
+ {
+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
+ return (venc.wss_data >> 8) ^ 0xfffff;
+ }
+
+-static int venc_set_wss(struct omap_display *display,
+- u32 wss)
++static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+ {
+ const struct venc_config *config;
+
+@@ -612,7 +681,7 @@ static int venc_set_wss(struct omap_display *display,
+
+ mutex_lock(&venc.venc_lock);
+
+- config = venc_timings_to_config(&display->panel->timings);
++ config = venc_timings_to_config(&dssdev->panel.timings);
+
+ /* Invert due to VENC_L21_WC_CTL:INV=1 */
+ venc.wss_data = (wss ^ 0xfffff) << 8;
+@@ -628,18 +697,19 @@ static int venc_set_wss(struct omap_display *display,
+ return 0;
+ }
+
+-void venc_init_display(struct omap_display *display)
++void venc_init_display(struct omap_dss_device *dssdev)
+ {
+- display->panel = &venc_panel;
+- display->enable = venc_enable_display;
+- display->disable = venc_disable_display;
+- display->suspend = venc_display_suspend;
+- display->resume = venc_display_resume;
+- display->get_timings = venc_get_timings;
+- display->set_timings = venc_set_timings;
+- display->check_timings = venc_check_timings;
+- display->get_wss = venc_get_wss;
+- display->set_wss = venc_set_wss;
++ DSSDBG("init_display\n");
++
++ dssdev->enable = venc_enable_display;
++ dssdev->disable = venc_disable_display;
++ dssdev->suspend = venc_display_suspend;
++ dssdev->resume = venc_display_resume;
++ dssdev->get_timings = venc_get_timings;
++ dssdev->set_timings = venc_set_timings;
++ dssdev->check_timings = venc_check_timings;
++ dssdev->get_wss = venc_get_wss;
++ dssdev->set_wss = venc_set_wss;
+ }
+
+ void venc_dump_regs(struct seq_file *s)
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 57e6287..0ca57db 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -37,7 +37,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ struct omap_overlay *ovl;
+ struct omap_overlay_info info;
+ int r = 0;
+@@ -191,7 +191,7 @@ static int omapfb_update_window(struct fb_info *fbi,
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ u16 dw, dh;
+
+ if (!display)
+@@ -217,7 +217,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode um;
+ int r;
+
+@@ -253,7 +253,7 @@ static int omapfb_get_update_mode(struct fb_info *fbi,
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode m;
+
+ if (!display || !display->get_update_mode)
+@@ -396,7 +396,7 @@ err:
+ static int omapfb_memory_read(struct fb_info *fbi,
+ struct omapfb_memory_read *mr)
+ {
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ void *buf;
+@@ -484,7 +484,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+
+ union {
+ struct omapfb_update_window_old uwnd_o;
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index c3690b8..df5ede3 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -454,7 +454,7 @@ void set_fb_fix(struct fb_info *fbi)
+ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ unsigned long max_frame_size;
+ unsigned long line_size;
+ int xres_min, yres_min;
+@@ -615,7 +615,7 @@ static int omapfb_release(struct fb_info *fbi, int user)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+
+ DBG("Closing fb with plane index %d\n", ofbi->id);
+
+@@ -1057,7 +1057,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ int do_update = 0;
+ int r = 0;
+
+@@ -1263,7 +1263,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ unsigned long paddr)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omap_display *display;
++ struct omap_dss_device *display;
+ int bytespp;
+
+ display = fb2display(fbi);
+@@ -1307,6 +1307,9 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ size = w * h * bytespp;
+ }
+
++ if (!size)
++ return 0;
++
+ return omapfb_alloc_fbmem(fbi, size, paddr);
+ }
+
+@@ -1485,7 +1488,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb2_mem_region *rg = &ofbi->region;
+ unsigned long old_size = rg->size;
+ unsigned long old_paddr = rg->paddr;
+@@ -1563,7 +1566,7 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ {
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+- struct omap_display *display = fb2display(fbi);
++ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int r = 0;
+
+@@ -1695,7 +1698,7 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
+ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
+ fbdev->displays[i]->disable(fbdev->displays[i]);
+
+- omap_dss_put_display(fbdev->displays[i]);
++ omap_dss_put_device(fbdev->displays[i]);
+ }
+
+ dev_set_drvdata(fbdev->dev, NULL);
+@@ -1874,7 +1877,7 @@ int omapfb_mode_to_timings(const char *mode_str,
+ }
+ }
+
+-static int omapfb_set_def_mode(struct omap_display *display, char *mode_str)
++static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
+ {
+ int r;
+ u8 bpp;
+@@ -1884,7 +1887,7 @@ static int omapfb_set_def_mode(struct omap_display *display, char *mode_str)
+ if (r)
+ return r;
+
+- display->panel->recommended_bpp = bpp;
++ display->panel.recommended_bpp = bpp;
+
+ if (!display->check_timings || !display->set_timings)
+ return -EINVAL;
+@@ -1909,7 +1912,7 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
+
+ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+ char *p, *display_str, *mode_str;
+- struct omap_display *display;
++ struct omap_dss_device *display;
+ int i;
+
+ p = strchr(this_opt, ':');
+@@ -1950,9 +1953,10 @@ static int omapfb_probe(struct platform_device *pdev)
+ {
+ struct omapfb2_device *fbdev = NULL;
+ int r = 0;
+- int i, t;
++ int i;
+ struct omap_overlay *ovl;
+- struct omap_display *def_display;
++ struct omap_dss_device *def_display;
++ struct omap_dss_device *dssdev;
+
+ DBG("omapfb_probe\n");
+
+@@ -1974,17 +1978,10 @@ static int omapfb_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, fbdev);
+
+ fbdev->num_displays = 0;
+- t = omap_dss_get_num_displays();
+- for (i = 0; i < t; i++) {
+- struct omap_display *display;
+- display = omap_dss_get_display(i);
+- if (!display) {
+- dev_err(&pdev->dev, "can't get display %d\n", i);
+- r = -EINVAL;
+- goto cleanup;
+- }
+-
+- fbdev->displays[fbdev->num_displays++] = display;
++ dssdev = NULL;
++ for_each_dss_dev(dssdev) {
++ omap_dss_get_device(dssdev);
++ fbdev->displays[fbdev->num_displays++] = dssdev;
+ }
+
+ if (fbdev->num_displays == 0) {
+@@ -2005,8 +2002,8 @@ static int omapfb_probe(struct platform_device *pdev)
+ /* gfx overlay should be the default one. find a display
+ * connected to that, and use it as default display */
+ ovl = omap_dss_get_overlay(0);
+- if (ovl->manager && ovl->manager->display) {
+- def_display = ovl->manager->display;
++ if (ovl->manager && ovl->manager->device) {
++ def_display = ovl->manager->device;
+ } else {
+ dev_err(&pdev->dev, "cannot find default display\n");
+ r = -EINVAL;
+@@ -2063,7 +2060,7 @@ static int omapfb_probe(struct platform_device *pdev)
+ }
+
+ for (i = 0; i < fbdev->num_displays; i++) {
+- struct omap_display *display = fbdev->displays[i];
++ struct omap_dss_device *display = fbdev->displays[i];
+ u16 w, h;
+
+ if (!display->get_update_mode || !display->update)
+diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
+index e750bc0..6ca8ba6 100644
+--- a/drivers/video/omap2/omapfb/omapfb.h
++++ b/drivers/video/omap2/omapfb/omapfb.h
+@@ -78,7 +78,7 @@ struct omapfb2_device {
+ struct fb_info *fbs[10];
+
+ unsigned num_displays;
+- struct omap_display *displays[10];
++ struct omap_dss_device *displays[10];
+ unsigned num_overlays;
+ struct omap_overlay *overlays[10];
+ unsigned num_managers;
+@@ -115,7 +115,7 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+ struct fb_var_screeninfo *var);
+
+ /* find the display connected to this fb, if any */
+-static inline struct omap_display *fb2display(struct fb_info *fbi)
++static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int i;
+@@ -123,7 +123,7 @@ static inline struct omap_display *fb2display(struct fb_info *fbi)
+ /* XXX: returns the display connected to first attached overlay */
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->manager)
+- return ofbi->overlays[i]->manager->display;
++ return ofbi->overlays[i]->manager->device;
+ }
+
+ return NULL;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0088-DSS2-Board-file-changes-for-new-device-model.patch b/recipes/linux/linux-omap-pm/dss2/0088-DSS2-Board-file-changes-for-new-device-model.patch
new file mode 100644
index 0000000000..fbab306f97
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0088-DSS2-Board-file-changes-for-new-device-model.patch
@@ -0,0 +1,496 @@
+From 026ceab45d93841cabd7a0fc734a919171543c46 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 28 May 2009 13:27:43 +0300
+Subject: [PATCH 088/146] DSS2: Board file changes for new device model
+
+Changes to Beagle, SDP, Overo board files
+---
+ arch/arm/mach-omap2/board-3430sdp.c | 102 ++++++++--------
+ arch/arm/mach-omap2/board-omap3beagle.c | 195 ++++++++++++++++---------------
+ arch/arm/mach-omap2/board-overo.c | 43 ++++---
+ 3 files changed, 173 insertions(+), 167 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
+index 2ee6cbb..ec0c358 100644
+--- a/arch/arm/mach-omap2/board-3430sdp.c
++++ b/arch/arm/mach-omap2/board-3430sdp.c
+@@ -178,21 +178,6 @@ static unsigned enable_gpio;
+ static int lcd_enabled;
+ static int dvi_enabled;
+
+-static struct platform_device sdp3430_lcd_device = {
+- .name = "sdp2430_lcd",
+- .id = -1,
+-};
+-
+-static struct regulator_consumer_supply sdp3430_vdac_supply = {
+- .supply = "vdac",
+- .dev = &sdp3430_lcd_device.dev,
+-};
+-
+-static struct regulator_consumer_supply sdp3430_vdvi_supply = {
+- .supply = "vdvi",
+- .dev = &sdp3430_lcd_device.dev,
+-};
+-
+ static void enable_vpll2(int enable)
+ {
+ u8 ded_val, grp_val;
+@@ -253,7 +238,7 @@ err0:
+ return;
+ }
+
+-static int sdp3430_panel_enable_lcd(struct omap_display *display)
++static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
+ {
+ u8 ded_val, ded_reg;
+ u8 grp_val, grp_reg;
+@@ -283,7 +268,7 @@ static int sdp3430_panel_enable_lcd(struct omap_display *display)
+ return 0;
+ }
+
+-static void sdp3430_panel_disable_lcd(struct omap_display *display)
++static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
+ {
+ lcd_enabled = 0;
+
+@@ -293,16 +278,7 @@ static void sdp3430_panel_disable_lcd(struct omap_display *display)
+ gpio_direction_output(backlight_gpio, 0);
+ }
+
+-static struct omap_dss_display_config sdp3430_display_data = {
+- .type = OMAP_DISPLAY_TYPE_DPI,
+- .name = "lcd",
+- .panel_name = "sharp-ls037v7dw01",
+- .u.dpi.data_lines = 16,
+- .panel_enable = sdp3430_panel_enable_lcd,
+- .panel_disable = sdp3430_panel_disable_lcd,
+-};
+-
+-static int sdp3430_panel_enable_dvi(struct omap_display *display)
++static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
+ {
+ if (lcd_enabled) {
+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+@@ -316,24 +292,14 @@ static int sdp3430_panel_enable_dvi(struct omap_display *display)
+ return 0;
+ }
+
+-static void sdp3430_panel_disable_dvi(struct omap_display *display)
++static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
+ {
+ sdp3430_dsi_power_down();
+
+ dvi_enabled = 0;
+ }
+
+-
+-static struct omap_dss_display_config sdp3430_display_data_dvi = {
+- .type = OMAP_DISPLAY_TYPE_DPI,
+- .name = "dvi",
+- .panel_name = "panel-generic",
+- .u.dpi.data_lines = 24,
+- .panel_enable = sdp3430_panel_enable_dvi,
+- .panel_disable = sdp3430_panel_disable_dvi,
+-};
+-
+-static int sdp3430_panel_enable_tv(struct omap_display *display)
++static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
+ {
+ #define ENABLE_VDAC_DEDICATED 0x03
+ #define ENABLE_VDAC_DEV_GRP 0x20
+@@ -347,7 +313,7 @@ static int sdp3430_panel_enable_tv(struct omap_display *display)
+ return 0;
+ }
+
+-static void sdp3430_panel_disable_tv(struct omap_display *display)
++static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
+ {
+ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+ TWL4030_VDAC_DEDICATED);
+@@ -355,23 +321,47 @@ static void sdp3430_panel_disable_tv(struct omap_display *display)
+ TWL4030_VDAC_DEV_GRP);
+ }
+
+-static struct omap_dss_display_config sdp3430_display_data_tv = {
+- .type = OMAP_DISPLAY_TYPE_VENC,
++
++static struct omap_dss_device sdp3430_lcd_device = {
++ .name = "lcd",
++ .driver_name = "sharp_ls_panel",
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .phy.dpi.data_lines = 16,
++ .platform_enable = sdp3430_panel_enable_lcd,
++ .platform_disable = sdp3430_panel_disable_lcd,
++};
++
++static struct omap_dss_device sdp3430_dvi_device = {
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .phy.dpi.data_lines = 24,
++ .platform_enable = sdp3430_panel_enable_dvi,
++ .platform_disable = sdp3430_panel_disable_dvi,
++};
++
++static struct omap_dss_device sdp3430_tv_device = {
+ .name = "tv",
+- .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+- .panel_enable = sdp3430_panel_enable_tv,
+- .panel_disable = sdp3430_panel_disable_tv,
++ .driver_name = "venc",
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .platform_enable = sdp3430_panel_enable_tv,
++ .platform_disable = sdp3430_panel_disable_tv,
++};
++
++
++static struct omap_dss_device *sdp3430_dss_devices[] = {
++ &sdp3430_lcd_device,
++ &sdp3430_dvi_device,
++ &sdp3430_tv_device,
+ };
+
+ static struct omap_dss_board_info sdp3430_dss_data = {
++ .num_devices = ARRAY_SIZE(sdp3430_dss_devices),
++ .devices = sdp3430_dss_devices,
++ .default_device = &sdp3430_lcd_device,
+ .dsi_power_up = sdp3430_dsi_power_up,
+ .dsi_power_down = sdp3430_dsi_power_down,
+- .num_displays = 3,
+- .displays = {
+- &sdp3430_display_data,
+- &sdp3430_display_data_dvi,
+- &sdp3430_display_data_tv,
+- }
+ };
+
+ static struct platform_device sdp3430_dss_device = {
+@@ -382,6 +372,16 @@ static struct platform_device sdp3430_dss_device = {
+ },
+ };
+
++static struct regulator_consumer_supply sdp3430_vdac_supply = {
++ .supply = "vdac",
++ .dev = &sdp3430_dss_device.dev,
++};
++
++static struct regulator_consumer_supply sdp3430_vdvi_supply = {
++ .supply = "vdvi",
++ .dev = &sdp3430_dss_device.dev,
++};
++
+ static struct platform_device *sdp3430_devices[] __initdata = {
+ &sdp3430_dss_device,
+ };
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 4ab7396..67e1d5c 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -108,6 +108,105 @@ static struct platform_device omap3beagle_nand_device = {
+ .resource = &omap3beagle_nand_resource,
+ };
+
++/* DSS */
++
++static int beagle_enable_dvi(struct omap_dss_device *dssdev)
++{
++ if (dssdev->reset_gpio != -1)
++ gpio_set_value(dssdev->reset_gpio, 1);
++
++ return 0;
++}
++
++static void beagle_disable_dvi(struct omap_dss_device *dssdev)
++{
++ if (dssdev->reset_gpio != -1)
++ gpio_set_value(dssdev->reset_gpio, 0);
++}
++
++static struct omap_dss_device beagle_dvi_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .phy.dpi.data_lines = 24,
++ .reset_gpio = 170,
++ .platform_enable = beagle_enable_dvi,
++ .platform_disable = beagle_disable_dvi,
++};
++
++static int beagle_panel_enable_tv(struct omap_dss_device *dssdev)
++{
++#define ENABLE_VDAC_DEDICATED 0x03
++#define ENABLE_VDAC_DEV_GRP 0x20
++
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEDICATED,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
++ ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
++
++ return 0;
++}
++
++static void beagle_panel_disable_tv(struct omap_dss_device *dssdev)
++{
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEDICATED);
++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
++ TWL4030_VDAC_DEV_GRP);
++}
++
++static struct omap_dss_device beagle_tv_device = {
++ .name = "tv",
++ .driver_name = "venc",
++ .type = OMAP_DISPLAY_TYPE_VENC,
++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
++ .platform_enable = beagle_panel_enable_tv,
++ .platform_disable = beagle_panel_disable_tv,
++};
++
++static struct omap_dss_device *beagle_dss_devices[] = {
++ &beagle_dvi_device,
++ &beagle_tv_device,
++};
++
++static struct omap_dss_board_info beagle_dss_data = {
++ .num_devices = ARRAY_SIZE(beagle_dss_devices),
++ .devices = beagle_dss_devices,
++ .default_device = &beagle_dvi_device,
++};
++
++static struct platform_device beagle_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &beagle_dss_data,
++ },
++};
++
++static struct regulator_consumer_supply beagle_vdac_supply = {
++ .supply = "vdac",
++ .dev = &beagle_dss_device.dev,
++};
++
++static struct regulator_consumer_supply beagle_vdvi_supply = {
++ .supply = "vdvi",
++ .dev = &beagle_dss_device.dev,
++};
++
++static void __init beagle_display_init(void)
++{
++ int r;
++
++ r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset");
++ if (r < 0) {
++ printk(KERN_ERR "Unable to get DVI reset GPIO\n");
++ return;
++ }
++
++ gpio_direction_output(beagle_dvi_device.reset_gpio, 0);
++}
++
+ #include "sdram-micron-mt46h32m32lf-6.h"
+
+ static struct omap_uart_config omap3_beagle_uart_config __initdata = {
+@@ -182,16 +281,6 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = {
+ .setup = beagle_twl_gpio_setup,
+ };
+
+-static struct regulator_consumer_supply beagle_vdac_supply = {
+- .supply = "vdac",
+- .dev = &omap3_beagle_lcd_device.dev,
+-};
+-
+-static struct regulator_consumer_supply beagle_vdvi_supply = {
+- .supply = "vdvi",
+- .dev = &omap3_beagle_lcd_device.dev,
+-};
+-
+ /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+ static struct regulator_init_data beagle_vmmc1 = {
+ .constraints = {
+@@ -345,92 +434,6 @@ static struct platform_device keys_gpio = {
+ },
+ };
+
+-/* DSS */
+-
+-static int beagle_enable_dvi(struct omap_display *display)
+-{
+- if (display->hw_config.panel_reset_gpio != -1)
+- gpio_set_value(display->hw_config.panel_reset_gpio, 1);
+-
+- return 0;
+-}
+-
+-static void beagle_disable_dvi(struct omap_display *display)
+-{
+- if (display->hw_config.panel_reset_gpio != -1)
+- gpio_set_value(display->hw_config.panel_reset_gpio, 0);
+-}
+-
+-static struct omap_dss_display_config beagle_display_data_dvi = {
+- .type = OMAP_DISPLAY_TYPE_DPI,
+- .name = "dvi",
+- .panel_name = "panel-generic",
+- .u.dpi.data_lines = 24,
+- .panel_reset_gpio = 170,
+- .panel_enable = beagle_enable_dvi,
+- .panel_disable = beagle_disable_dvi,
+-};
+-
+-
+-static int beagle_panel_enable_tv(struct omap_display *display)
+-{
+-#define ENABLE_VDAC_DEDICATED 0x03
+-#define ENABLE_VDAC_DEV_GRP 0x20
+-
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEDICATED,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+-
+- return 0;
+-}
+-
+-static void beagle_panel_disable_tv(struct omap_display *display)
+-{
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEV_GRP);
+-}
+-
+-static struct omap_dss_display_config beagle_display_data_tv = {
+- .type = OMAP_DISPLAY_TYPE_VENC,
+- .name = "tv",
+- .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+- .panel_enable = beagle_panel_enable_tv,
+- .panel_disable = beagle_panel_disable_tv,
+-};
+-
+-static struct omap_dss_board_info beagle_dss_data = {
+- .num_displays = 2,
+- .displays = {
+- &beagle_display_data_dvi,
+- &beagle_display_data_tv,
+- }
+-};
+-
+-static struct platform_device beagle_dss_device = {
+- .name = "omapdss",
+- .id = -1,
+- .dev = {
+- .platform_data = &beagle_dss_data,
+- },
+-};
+-
+-static void __init beagle_display_init(void)
+-{
+- int r;
+-
+- r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+- if (r < 0) {
+- printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+- return;
+- }
+-
+- gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+-}
+-
+ static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+ { OMAP_TAG_UART, &omap3_beagle_uart_config },
+ };
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index 7bcac03..39f95f5 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -386,7 +386,7 @@ static void __init overo_display_init(void)
+ gpio_export(OVERO_GPIO_LCD_EN, 0);
+ }
+
+-static int overo_panel_enable_dvi(struct omap_display *display)
++static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
+ {
+ if (lcd_enabled) {
+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+@@ -399,23 +399,23 @@ static int overo_panel_enable_dvi(struct omap_display *display)
+ return 0;
+ }
+
+-static void overo_panel_disable_dvi(struct omap_display *display)
++static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
+ {
+ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+
+ dvi_enabled = 0;
+ }
+
+-static struct omap_dss_display_config overo_display_data_dvi = {
++static struct omap_dss_device overo_dvi_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "dvi",
+- .panel_name = "panel-generic",
+- .u.dpi.data_lines = 24,
+- .panel_enable = overo_panel_enable_dvi,
+- .panel_disable = overo_panel_disable_dvi,
++ .driver_name = "panel_generic",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = overo_panel_enable_dvi,
++ .platform_disable = overo_panel_disable_dvi,
+ };
+
+-static int overo_panel_enable_lcd(struct omap_display *display)
++static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
+ {
+ if (dvi_enabled) {
+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+@@ -427,27 +427,30 @@ static int overo_panel_enable_lcd(struct omap_display *display)
+ return 0;
+ }
+
+-static void overo_panel_disable_lcd(struct omap_display *display)
++static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
+ {
+ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+ lcd_enabled = 0;
+ }
+
+-static struct omap_dss_display_config overo_display_data_lcd = {
++static struct omap_dss_device overo_lcd_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "lcd",
+- .panel_name = "samsung-lte430wq-f0c",
+- .u.dpi.data_lines = 24,
+- .panel_enable = overo_panel_enable_lcd,
+- .panel_disable = overo_panel_disable_lcd,
+- };
++ .driver_name = "samsung-lte430wq-f0c",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = overo_panel_enable_lcd,
++ .platform_disable = overo_panel_disable_lcd,
++};
++
++static struct omap_dss_device *overo_dss_devices[] = {
++ &overo_dvi_device,
++ &overo_lcd_device,
++};
+
+ static struct omap_dss_board_info overo_dss_data = {
+- .num_displays = 2,
+- .displays = {
+- &overo_display_data_dvi,
+- &overo_display_data_lcd,
+- }
++ .num_devices = ARRAY_SIZE(overo_dss_devices),
++ .devices = overo_dss_devices,
++ .default_device = &overo_dvi_device,
+ };
+
+ static struct platform_device overo_dss_device = {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0089-DSS2-Panel-driver-changes-for-new-device-model.patch b/recipes/linux/linux-omap-pm/dss2/0089-DSS2-Panel-driver-changes-for-new-device-model.patch
new file mode 100644
index 0000000000..97098e1554
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0089-DSS2-Panel-driver-changes-for-new-device-model.patch
@@ -0,0 +1,400 @@
+From 449ff8409e92f76f71baf538867f600a832f92e3 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 28 May 2009 13:29:55 +0300
+Subject: [PATCH 089/146] DSS2: Panel driver changes for new device model
+
+Changes to generic, samsung and sharp panel drivers
+---
+ drivers/video/omap2/displays/panel-generic.c | 72 ++++++++++--------
+ .../omap2/displays/panel-samsung-lte430wq-f0c.c | 77 ++++++++++---------
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 79 ++++++++++----------
+ 3 files changed, 122 insertions(+), 106 deletions(-)
+
+diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
+index 8382acb..738147e 100644
+--- a/drivers/video/omap2/displays/panel-generic.c
++++ b/drivers/video/omap2/displays/panel-generic.c
+@@ -22,73 +22,81 @@
+
+ #include <mach/display.h>
+
+-static int generic_panel_init(struct omap_display *display)
++static struct omap_video_timings generic_panel_timings = {
++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
++ .x_res = 640,
++ .y_res = 480,
++ .pixel_clock = 23500,
++ .hfp = 48,
++ .hsw = 32,
++ .hbp = 80,
++ .vfp = 3,
++ .vsw = 4,
++ .vbp = 7,
++};
++
++static int generic_panel_probe(struct omap_dss_device *dssdev)
+ {
++ dssdev->panel.config = OMAP_DSS_LCD_TFT;
++ dssdev->panel.timings = generic_panel_timings;
++
+ return 0;
+ }
+
+-static int generic_panel_enable(struct omap_display *display)
++static void generic_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++static int generic_panel_enable(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+- if (display->hw_config.panel_enable)
+- r = display->hw_config.panel_enable(display);
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
+
+ return r;
+ }
+
+-static void generic_panel_disable(struct omap_display *display)
++static void generic_panel_disable(struct omap_dss_device *dssdev)
+ {
+- if (display->hw_config.panel_disable)
+- display->hw_config.panel_disable(display);
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
+ }
+
+-static int generic_panel_suspend(struct omap_display *display)
++static int generic_panel_suspend(struct omap_dss_device *dssdev)
+ {
+- generic_panel_disable(display);
++ generic_panel_disable(dssdev);
+ return 0;
+ }
+
+-static int generic_panel_resume(struct omap_display *display)
++static int generic_panel_resume(struct omap_dss_device *dssdev)
+ {
+- return generic_panel_enable(display);
++ return generic_panel_enable(dssdev);
+ }
+
+-static struct omap_panel generic_panel = {
+- .owner = THIS_MODULE,
+- .name = "panel-generic",
+- .init = generic_panel_init,
++static struct omap_dss_driver generic_driver = {
++ .probe = generic_panel_probe,
++ .remove = generic_panel_remove,
++
+ .enable = generic_panel_enable,
+ .disable = generic_panel_disable,
+ .suspend = generic_panel_suspend,
+ .resume = generic_panel_resume,
+
+- .timings = {
+- /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
+- .x_res = 640,
+- .y_res = 480,
+- .pixel_clock = 23500,
+- .hfp = 48,
+- .hsw = 32,
+- .hbp = 80,
+- .vfp = 3,
+- .vsw = 4,
+- .vbp = 7,
++ .driver = {
++ .name = "generic_panel",
++ .owner = THIS_MODULE,
+ },
+-
+- .config = OMAP_DSS_LCD_TFT,
+ };
+
+-
+ static int __init generic_panel_drv_init(void)
+ {
+- omap_dss_register_panel(&generic_panel);
+- return 0;
++ return omap_dss_register_driver(&generic_driver);
+ }
+
+ static void __exit generic_panel_drv_exit(void)
+ {
+- omap_dss_unregister_panel(&generic_panel);
++ omap_dss_unregister_driver(&generic_driver);
+ }
+
+ module_init(generic_panel_drv_init);
+diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+index e4bb781..eafe581 100644
+--- a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
++++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
+@@ -21,86 +21,91 @@
+
+ #include <mach/display.h>
+
+-static int samsung_lte_panel_init(struct omap_display *display)
++static struct omap_video_timings samsung_lte_timings = {
++ .x_res = 480,
++ .y_res = 272,
++
++ .pixel_clock = 9200,
++
++ .hsw = 41,
++ .hfp = 8,
++ .hbp = 45-41,
++
++ .vsw = 10,
++ .vfp = 4,
++ .vbp = 12-10,
++};
++
++static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
+ {
++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
++ OMAP_DSS_LCD_IHS;
++ dssdev->panel.timings = samsung_lte_timings;
++
+ return 0;
+ }
+
+-static void samsung_lte_panel_cleanup(struct omap_display *display)
++static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
+ {
+ }
+
+-static int samsung_lte_panel_enable(struct omap_display *display)
++static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
+- if (display->hw_config.panel_enable)
+- r = display->hw_config.panel_enable(display);
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
+
+ return r;
+ }
+
+-static void samsung_lte_panel_disable(struct omap_display *display)
++static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
+ {
+- if (display->hw_config.panel_disable)
+- display->hw_config.panel_disable(display);
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
+
+ /* wait at least 5 vsyncs after disabling the LCD */
++
+ msleep(100);
+ }
+
+-static int samsung_lte_panel_suspend(struct omap_display *display)
++static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
+ {
+- samsung_lte_panel_disable(display);
++ samsung_lte_panel_disable(dssdev);
+ return 0;
+ }
+
+-static int samsung_lte_panel_resume(struct omap_display *display)
++static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
+ {
+- return samsung_lte_panel_enable(display);
++ return samsung_lte_panel_enable(dssdev);
+ }
+
+-static struct omap_panel samsung_lte_panel = {
+- .owner = THIS_MODULE,
+- .name = "samsung-lte430wq-f0c",
+- .init = samsung_lte_panel_init,
+- .cleanup = samsung_lte_panel_cleanup,
++static struct omap_dss_driver samsung_lte_driver = {
++ .probe = samsung_lte_panel_probe,
++ .remove = samsung_lte_panel_remove,
++
+ .enable = samsung_lte_panel_enable,
+ .disable = samsung_lte_panel_disable,
+ .suspend = samsung_lte_panel_suspend,
+ .resume = samsung_lte_panel_resume,
+
+- .timings = {
+- .x_res = 480,
+- .y_res = 272,
+-
+- .pixel_clock = 9200,
+-
+- .hsw = 41,
+- .hfp = 8,
+- .hbp = 45-41,
+-
+- .vsw = 10,
+- .vfp = 4,
+- .vbp = 12-10,
++ .driver = {
++ .name = "samsung_lte_panel",
++ .owner = THIS_MODULE,
+ },
+-
+- .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS,
+ };
+
+-
+ static int __init samsung_lte_panel_drv_init(void)
+ {
+- omap_dss_register_panel(&samsung_lte_panel);
+- return 0;
++ return omap_dss_register_driver(&samsung_lte_driver);
+ }
+
+ static void __exit samsung_lte_panel_drv_exit(void)
+ {
+- omap_dss_unregister_panel(&samsung_lte_panel);
++ omap_dss_unregister_driver(&samsung_lte_driver);
+ }
+
+ module_init(samsung_lte_panel_drv_init);
+diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+index 1f99150..6b93ea5 100644
+--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+@@ -22,89 +22,92 @@
+
+ #include <mach/display.h>
+
+-static int sharp_ls_panel_init(struct omap_display *display)
++static struct omap_video_timings sharp_ls_timings = {
++ .x_res = 480,
++ .y_res = 640,
++
++ .pixel_clock = 19200,
++
++ .hsw = 2,
++ .hfp = 1,
++ .hbp = 28,
++
++ .vsw = 1,
++ .vfp = 1,
++ .vbp = 1,
++};
++
++static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
+ {
++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
++ OMAP_DSS_LCD_IHS;
++ dssdev->panel.acb = 0x28;
++ dssdev->panel.timings = sharp_ls_timings;
++
+ return 0;
+ }
+
+-static void sharp_ls_panel_cleanup(struct omap_display *display)
++static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
+ {
+ }
+
+-static int sharp_ls_panel_enable(struct omap_display *display)
++static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+ {
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
+- if (display->hw_config.panel_enable)
+- r = display->hw_config.panel_enable(display);
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
+
+ return r;
+ }
+
+-static void sharp_ls_panel_disable(struct omap_display *display)
++static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
+ {
+- if (display->hw_config.panel_disable)
+- display->hw_config.panel_disable(display);
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
+
+ /* wait at least 5 vsyncs after disabling the LCD */
+
+ msleep(100);
+ }
+
+-static int sharp_ls_panel_suspend(struct omap_display *display)
++static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
+ {
+- sharp_ls_panel_disable(display);
++ sharp_ls_panel_disable(dssdev);
+ return 0;
+ }
+
+-static int sharp_ls_panel_resume(struct omap_display *display)
++static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
+ {
+- return sharp_ls_panel_enable(display);
++ return sharp_ls_panel_enable(dssdev);
+ }
+
+-static struct omap_panel sharp_ls_panel = {
+- .owner = THIS_MODULE,
+- .name = "sharp-ls037v7dw01",
+- .init = sharp_ls_panel_init,
+- .cleanup = sharp_ls_panel_cleanup,
++static struct omap_dss_driver sharp_ls_driver = {
++ .probe = sharp_ls_panel_probe,
++ .remove = sharp_ls_panel_remove,
++
+ .enable = sharp_ls_panel_enable,
+ .disable = sharp_ls_panel_disable,
+ .suspend = sharp_ls_panel_suspend,
+ .resume = sharp_ls_panel_resume,
+
+- .timings = {
+- .x_res = 480,
+- .y_res = 640,
+-
+- .pixel_clock = 19200,
+-
+- .hsw = 2,
+- .hfp = 1,
+- .hbp = 28,
+-
+- .vsw = 1,
+- .vfp = 1,
+- .vbp = 1,
++ .driver = {
++ .name = "sharp_ls_panel",
++ .owner = THIS_MODULE,
+ },
+-
+- .acb = 0x28,
+-
+- .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS,
+ };
+
+-
+ static int __init sharp_ls_panel_drv_init(void)
+ {
+- omap_dss_register_panel(&sharp_ls_panel);
+- return 0;
++ return omap_dss_register_driver(&sharp_ls_driver);
+ }
+
+ static void __exit sharp_ls_panel_drv_exit(void)
+ {
+- omap_dss_unregister_panel(&sharp_ls_panel);
++ omap_dss_unregister_driver(&sharp_ls_driver);
+ }
+
+ module_init(sharp_ls_panel_drv_init);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0090-DSS2-VENC-venc-uses-regulator-framework.patch b/recipes/linux/linux-omap-pm/dss2/0090-DSS2-VENC-venc-uses-regulator-framework.patch
new file mode 100644
index 0000000000..91870fe489
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0090-DSS2-VENC-venc-uses-regulator-framework.patch
@@ -0,0 +1,74 @@
+From 5c06f74553d932aee9cba73ca2620a16f1bb610e Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 28 May 2009 17:01:35 +0300
+Subject: [PATCH 090/146] DSS2: VENC: venc uses regulator framework
+
+Venc needs vdda_dac regulator
+---
+ drivers/video/omap2/dss/venc.c | 15 +++++++++++++++
+ 1 files changed, 15 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index a83d170..d06dc38 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -32,6 +32,7 @@
+ #include <linux/string.h>
+ #include <linux/seq_file.h>
+ #include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
+
+ #include <mach/display.h>
+ #include <mach/cpu.h>
+@@ -291,6 +292,7 @@ static struct {
+ void __iomem *base;
+ struct mutex venc_lock;
+ u32 wss_data;
++ struct regulator *vdda_dac_reg;
+ } venc;
+
+ static inline void venc_write_reg(int idx, u32 val)
+@@ -480,6 +482,13 @@ int venc_init(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
++ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
++ if (IS_ERR(venc.vdda_dac_reg)) {
++ iounmap(venc.base);
++ DSSERR("can't get VDDA_DAC regulator\n");
++ return PTR_ERR(venc.vdda_dac_reg);
++ }
++
+ venc_enable_clocks(1);
+
+ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+@@ -496,6 +505,8 @@ void venc_exit(void)
+ {
+ omap_dss_unregister_driver(&venc_driver);
+
++ regulator_put(venc.vdda_dac_reg);
++
+ iounmap(venc.base);
+ }
+
+@@ -521,6 +532,8 @@ static void venc_power_on(struct omap_dss_device *dssdev)
+ dispc_set_digit_size(dssdev->panel.timings.x_res,
+ dssdev->panel.timings.y_res/2);
+
++ regulator_enable(venc.vdda_dac_reg);
++
+ if (dssdev->platform_enable)
+ dssdev->platform_enable(dssdev);
+
+@@ -537,6 +550,8 @@ static void venc_power_off(struct omap_dss_device *dssdev)
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
++ regulator_disable(venc.vdda_dac_reg);
++
+ venc_enable_clocks(0);
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0091-DSS2-DSI-Use-regulator-framework.patch b/recipes/linux/linux-omap-pm/dss2/0091-DSS2-DSI-Use-regulator-framework.patch
new file mode 100644
index 0000000000..a9dbe70560
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0091-DSS2-DSI-Use-regulator-framework.patch
@@ -0,0 +1,134 @@
+From d643b84bbc463075017b5ec61406455ad8e55374 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 28 May 2009 17:19:48 +0300
+Subject: [PATCH 091/146] DSS2: DSI: Use regulator framework
+
+DSI needs vdds_dsi regulator
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 --
+ drivers/video/omap2/dss/core.c | 24 ------------------------
+ drivers/video/omap2/dss/dsi.c | 18 +++++++++++++++---
+ 3 files changed, 15 insertions(+), 29 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 57bb8ff..94585ba 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -219,8 +219,6 @@ struct omap_dss_board_info {
+ int num_devices;
+ struct omap_dss_device **devices;
+ struct omap_dss_device *default_device;
+- int (*dsi_power_up)(void);
+- void (*dsi_power_down)(void);
+ };
+
+ struct omap_video_timings {
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index c56c431..212b774 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -411,30 +411,6 @@ static void dss_uninitialize_debugfs(void)
+ }
+ #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+
+-
+-/* DSI powers */
+-int dss_dsi_power_up(void)
+-{
+- struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+-
+- if (!pdata->dsi_power_up)
+- return 0; /* presume power is always on then */
+-
+- return pdata->dsi_power_up();
+-}
+-
+-void dss_dsi_power_down(void)
+-{
+- struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+-
+- if (!pdata->dsi_power_down)
+- return;
+-
+- pdata->dsi_power_down();
+-}
+-
+-
+-
+ /* PLATFORM DEVICE */
+ static int omap_dss_probe(struct platform_device *pdev)
+ {
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index fb2f7f0..9c8488e 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -31,6 +31,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/kfifo.h>
+ #include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
+
+ #include <mach/board.h>
+ #include <mach/display.h>
+@@ -256,6 +257,8 @@ static struct
+ unsigned long dsiphy; /* Hz */
+ unsigned long ddr_clk; /* Hz */
+
++ struct regulator *vdds_dsi_reg;
++
+ struct {
+ struct omap_dss_device *dssdev;
+ enum fifo_size fifo_size;
+@@ -1177,7 +1180,7 @@ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+ goto err0;
+ }
+
+- r = dss_dsi_power_up();
++ r = regulator_enable(dsi.vdds_dsi_reg);
+ if (r)
+ goto err0;
+
+@@ -1212,7 +1215,7 @@ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+
+ return 0;
+ err1:
+- dss_dsi_power_down();
++ regulator_disable(dsi.vdds_dsi_reg);
+ err0:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+@@ -1226,7 +1229,7 @@ void dsi_pll_uninit(void)
+
+ dsi.pll_locked = 0;
+ dsi_pll_power(DSI_PLL_POWER_OFF);
+- dss_dsi_power_down();
++ regulator_disable(dsi.vdds_dsi_reg);
+ DSSDBG("PLL uninit done\n");
+ }
+
+@@ -3898,6 +3901,13 @@ int dsi_init(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
++ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
++ if (IS_ERR(dsi.vdds_dsi_reg)) {
++ iounmap(dsi.base);
++ DSSERR("can't get VDDS_DSI regulator\n");
++ return PTR_ERR(dsi.vdds_dsi_reg);
++ }
++
+ enable_clocks(1);
+
+ rev = dsi_read_reg(DSI_REVISION);
+@@ -3914,6 +3924,8 @@ void dsi_exit(void)
+ flush_workqueue(dsi.workqueue);
+ destroy_workqueue(dsi.workqueue);
+
++ regulator_put(dsi.vdds_dsi_reg);
++
+ iounmap(dsi.base);
+
+ kfifo_free(dsi.cmd_fifo);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0092-DSS2-SDP-regulators-for-VDAC-DSI.patch b/recipes/linux/linux-omap-pm/dss2/0092-DSS2-SDP-regulators-for-VDAC-DSI.patch
new file mode 100644
index 0000000000..76e0710032
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0092-DSS2-SDP-regulators-for-VDAC-DSI.patch
@@ -0,0 +1,225 @@
+From 5243c9ebcadbb074a381769fab9dff266c9d6a84 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 29 May 2009 12:07:07 +0300
+Subject: [PATCH 092/146] DSS2: SDP: regulators for VDAC, DSI
+
+---
+ arch/arm/mach-omap2/board-3430sdp.c | 114 +++++-----------------------------
+ 1 files changed, 17 insertions(+), 97 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
+index ec0c358..ef8cf4f 100644
+--- a/arch/arm/mach-omap2/board-3430sdp.c
++++ b/arch/arm/mach-omap2/board-3430sdp.c
+@@ -150,65 +150,14 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
+ };
+
+
+-#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
+-#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
+-#if 0
+-#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
+-#define SDP3430_LCD_PANEL_ENABLE_GPIO 28
+-#else
+ #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8
+ #define SDP3430_LCD_PANEL_ENABLE_GPIO 5
+-#endif
+-
+-#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
+-#define ENABLE_VAUX2_DEDICATED 0x09
+-#define ENABLE_VAUX2_DEV_GRP 0x20
+-#define ENABLE_VAUX3_DEDICATED 0x03
+-#define ENABLE_VAUX3_DEV_GRP 0x20
+-
+-#define ENABLE_VPLL2_DEDICATED 0x05
+-#define ENABLE_VPLL2_DEV_GRP 0xE0
+-#define TWL4030_VPLL2_DEV_GRP 0x33
+-#define TWL4030_VPLL2_DEDICATED 0x36
+-
+-#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
+
+ static unsigned backlight_gpio;
+ static unsigned enable_gpio;
+ static int lcd_enabled;
+ static int dvi_enabled;
+
+-static void enable_vpll2(int enable)
+-{
+- u8 ded_val, grp_val;
+-
+- if (enable) {
+- ded_val = ENABLE_VPLL2_DEDICATED;
+- grp_val = ENABLE_VPLL2_DEV_GRP;
+- } else {
+- ded_val = 0;
+- grp_val = 0;
+- }
+-
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ded_val, TWL4030_VPLL2_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- grp_val, TWL4030_VPLL2_DEV_GRP);
+-}
+-
+-static int sdp3430_dsi_power_up(void)
+-{
+- if (omap_rev() > OMAP3430_REV_ES1_0)
+- enable_vpll2(1);
+- return 0;
+-}
+-
+-static void sdp3430_dsi_power_down(void)
+-{
+- if (omap_rev() > OMAP3430_REV_ES1_0)
+- enable_vpll2(0);
+-}
+-
+ static void __init sdp3430_display_init(void)
+ {
+ int r;
+@@ -240,29 +189,14 @@ err0:
+
+ static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev)
+ {
+- u8 ded_val, ded_reg;
+- u8 grp_val, grp_reg;
+-
+ if (dvi_enabled) {
+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+ return -EINVAL;
+ }
+
+- ded_reg = TWL4030_VAUX3_DEDICATED;
+- ded_val = ENABLE_VAUX3_DEDICATED;
+- grp_reg = TWL4030_VAUX3_DEV_GRP;
+- grp_val = ENABLE_VAUX3_DEV_GRP;
+-
+ gpio_direction_output(enable_gpio, 1);
+ gpio_direction_output(backlight_gpio, 1);
+
+- if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
+- return -EIO;
+- if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
+- return -EIO;
+-
+- sdp3430_dsi_power_up();
+-
+ lcd_enabled = 1;
+
+ return 0;
+@@ -272,8 +206,6 @@ static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev)
+ {
+ lcd_enabled = 0;
+
+- sdp3430_dsi_power_down();
+-
+ gpio_direction_output(enable_gpio, 0);
+ gpio_direction_output(backlight_gpio, 0);
+ }
+@@ -285,8 +217,6 @@ static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
+ return -EINVAL;
+ }
+
+- sdp3430_dsi_power_up();
+-
+ dvi_enabled = 1;
+
+ return 0;
+@@ -294,31 +224,16 @@ static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev)
+
+ static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev)
+ {
+- sdp3430_dsi_power_down();
+-
+ dvi_enabled = 0;
+ }
+
+ static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev)
+ {
+-#define ENABLE_VDAC_DEDICATED 0x03
+-#define ENABLE_VDAC_DEV_GRP 0x20
+-
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEDICATED,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+-
+ return 0;
+ }
+
+ static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev)
+ {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEV_GRP);
+ }
+
+
+@@ -360,8 +275,6 @@ static struct omap_dss_board_info sdp3430_dss_data = {
+ .num_devices = ARRAY_SIZE(sdp3430_dss_devices),
+ .devices = sdp3430_dss_devices,
+ .default_device = &sdp3430_lcd_device,
+- .dsi_power_up = sdp3430_dsi_power_up,
+- .dsi_power_down = sdp3430_dsi_power_down,
+ };
+
+ static struct platform_device sdp3430_dss_device = {
+@@ -372,13 +285,8 @@ static struct platform_device sdp3430_dss_device = {
+ },
+ };
+
+-static struct regulator_consumer_supply sdp3430_vdac_supply = {
+- .supply = "vdac",
+- .dev = &sdp3430_dss_device.dev,
+-};
+-
+-static struct regulator_consumer_supply sdp3430_vdvi_supply = {
+- .supply = "vdvi",
++static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
++ .supply = "vdda_dac",
+ .dev = &sdp3430_dss_device.dev,
+ };
+
+@@ -605,22 +513,34 @@ static struct regulator_init_data sdp3430_vdac = {
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+- .consumer_supplies = &sdp3430_vdac_supply,
++ .consumer_supplies = &sdp3430_vdda_dac_supply,
+ };
+
+ /* VPLL2 for digital video outputs */
++static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
++ {
++ .supply = "vdvi",
++ .dev = &sdp3430_lcd_device.dev,
++ },
++ {
++ .supply = "vdds_dsi",
++ .dev = &sdp3430_dss_device.dev,
++ }
++};
++
+ static struct regulator_init_data sdp3430_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
++ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+- .num_consumer_supplies = 1,
+- .consumer_supplies = &sdp3430_vdvi_supply,
++ .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies),
++ .consumer_supplies = sdp3430_vpll2_supplies,
+ };
+
+ static struct twl4030_platform_data sdp3430_twldata = {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0093-DSS2-Sharp-panel-use-regulator-fw.patch b/recipes/linux/linux-omap-pm/dss2/0093-DSS2-Sharp-panel-use-regulator-fw.patch
new file mode 100644
index 0000000000..933a22dc36
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0093-DSS2-Sharp-panel-use-regulator-fw.patch
@@ -0,0 +1,100 @@
+From feaf5b69b627c85e3ea40accf50ab5771125cf00 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 29 May 2009 12:07:27 +0300
+Subject: [PATCH 093/146] DSS2: Sharp panel: use regulator fw
+
+---
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 38 ++++++++++++++++++++
+ 1 files changed, 38 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+index 6b93ea5..cb8ce34 100644
+--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+@@ -19,9 +19,20 @@
+
+ #include <linux/module.h>
+ #include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/err.h>
+
+ #include <mach/display.h>
+
++struct sharp_data {
++ /* XXX This regulator should actually be in SDP board file, not here,
++ * as it doesn't actually power the LCD, but something else that
++ * affects the output to LCD (I think. Somebody clarify). It doesn't do
++ * harm here, as SDP is the only board using this currently */
++ struct regulator *vdvi_reg;
++};
++
+ static struct omap_video_timings sharp_ls_timings = {
+ .x_res = 480,
+ .y_res = 640,
+@@ -39,25 +50,48 @@ static struct omap_video_timings sharp_ls_timings = {
+
+ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
+ {
++ struct sharp_data *sd;
++
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.acb = 0x28;
+ dssdev->panel.timings = sharp_ls_timings;
+
++ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
++ if (!sd)
++ return -ENOMEM;
++
++ dev_set_drvdata(&dssdev->dev, sd);
++
++ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
++ if (IS_ERR(sd->vdvi_reg)) {
++ kfree(sd);
++ printk("failed to get VDVI regulator\n");
++ return PTR_ERR(sd->vdvi_reg);
++ }
++
+ return 0;
+ }
+
+ static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
+ {
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
++
++ regulator_put(sd->vdvi_reg);
++
++ kfree(sd);
+ }
+
+ static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+ {
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
+ int r = 0;
+
+ /* wait couple of vsyncs until enabling the LCD */
+ msleep(50);
+
++ regulator_enable(sd->vdvi_reg);
++
+ if (dssdev->platform_enable)
+ r = dssdev->platform_enable(dssdev);
+
+@@ -66,9 +100,13 @@ static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+
+ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
+ {
++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
++
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
++ regulator_disable(sd->vdvi_reg);
++
+ /* wait at least 5 vsyncs after disabling the LCD */
+
+ msleep(100);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0094-DSS2-Beagle-regulators-for-VDAC-DSI.patch b/recipes/linux/linux-omap-pm/dss2/0094-DSS2-Beagle-regulators-for-VDAC-DSI.patch
new file mode 100644
index 0000000000..e57a433e3a
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0094-DSS2-Beagle-regulators-for-VDAC-DSI.patch
@@ -0,0 +1,52 @@
+From bf864e242e238f99124d63be457d2783d28894c9 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 29 May 2009 13:52:50 +0300
+Subject: [PATCH 094/146] DSS2: Beagle: regulators for VDAC, DSI
+
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 12 ++++++------
+ 1 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 67e1d5c..977bbbe 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -184,13 +184,13 @@ static struct platform_device beagle_dss_device = {
+ },
+ };
+
+-static struct regulator_consumer_supply beagle_vdac_supply = {
+- .supply = "vdac",
++static struct regulator_consumer_supply beagle_vdda_dac_supply = {
++ .supply = "vdda_dac",
+ .dev = &beagle_dss_device.dev,
+ };
+
+-static struct regulator_consumer_supply beagle_vdvi_supply = {
+- .supply = "vdvi",
++static struct regulator_consumer_supply beagle_vdds_dsi_supply = {
++ .supply = "vdds_dsi",
+ .dev = &beagle_dss_device.dev,
+ };
+
+@@ -322,7 +322,7 @@ static struct regulator_init_data beagle_vdac = {
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+- .consumer_supplies = &beagle_vdac_supply,
++ .consumer_supplies = &beagle_vdda_dac_supply,
+ };
+
+ /* VPLL2 for digital video outputs */
+@@ -337,7 +337,7 @@ static struct regulator_init_data beagle_vpll2 = {
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+- .consumer_supplies = &beagle_vdvi_supply,
++ .consumer_supplies = &beagle_vdds_dsi_supply,
+ };
+
+ static struct twl4030_platform_data beagle_twldata = {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0095-DSS2-Fix-checkpatch-complaints.patch b/recipes/linux/linux-omap-pm/dss2/0095-DSS2-Fix-checkpatch-complaints.patch
new file mode 100644
index 0000000000..3c5959d4f5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0095-DSS2-Fix-checkpatch-complaints.patch
@@ -0,0 +1,740 @@
+From 978ac67a1c8f75579548ee692312fb69986e6cb0 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 1 Jun 2009 18:02:00 +0300
+Subject: [PATCH 095/146] DSS2: Fix checkpatch complaints
+
+---
+ arch/arm/plat-omap/vrfb.c | 9 ++---
+ drivers/video/omap2/dss/core.c | 9 +++--
+ drivers/video/omap2/dss/dispc.c | 35 +++++++++++++-----
+ drivers/video/omap2/dss/display.c | 39 +++++++++++---------
+ drivers/video/omap2/dss/dsi.c | 32 ++++++++++------
+ drivers/video/omap2/dss/manager.c | 12 ++++---
+ drivers/video/omap2/dss/overlay.c | 56 ++++++++++++++++++++---------
+ drivers/video/omap2/dss/venc.c | 9 ++---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 5 ++-
+ drivers/video/omap2/omapfb/omapfb-main.c | 35 +++++++++---------
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 17 +++++----
+ 11 files changed, 158 insertions(+), 100 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 59ac66a..0c7d943 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -1,9 +1,8 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/ioport.h>
+-
+-#include <asm/io.h>
+-#include <asm/bitops.h>
++#include <linux/io.h>
++#include <linux/bitops.h>
+
+ #include <mach/io.h>
+ #include <mach/vrfb.h>
+@@ -55,7 +54,7 @@ static struct {
+ u32 size;
+ } vrfb_hw_context[VRFB_NUM_CTXS];
+
+-static void inline restore_hw_context(int ctx)
++static inline void restore_hw_context(int ctx)
+ {
+ omap_writel(vrfb_hw_context[ctx].control, SMS_ROT_CONTROL(ctx));
+ omap_writel(vrfb_hw_context[ctx].size, SMS_ROT_SIZE(ctx));
+@@ -180,7 +179,7 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ clear_bit(ctx, &ctx_map);
+
+ for (rot = 0; rot < 4; ++rot) {
+- if(vrfb->paddr[rot]) {
++ if (vrfb->paddr[rot]) {
+ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
+ vrfb->paddr[rot] = 0;
+ }
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index 212b774..3f544dc 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -73,8 +73,8 @@ static int dss_get_ctx_id(void)
+ return 0;
+ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
+ if (r < 0) {
+- dev_err(&core.pdev->dev,
+- "getting transaction ID failed, will force context restore\n");
++ dev_err(&core.pdev->dev, "getting transaction ID failed, "
++ "will force context restore\n");
+ r = -1;
+ }
+ return r;
+@@ -157,7 +157,7 @@ static int dss_get_clocks(void)
+ char *omap2_name;
+ char *omap3_name;
+ } clocks[5] = {
+- { &core.dss_ick, "dss_ick", "dss_ick" }, /* L3 & L4 ick */
++ { &core.dss_ick, "dss_ick", "dss_ick" }, /* L3 & L4 ick */
+ { &core.dss1_fck, "dss1_fck", "dss1_alwon_fck" },
+ { &core.dss2_fck, "dss2_fck", "dss2_alwon_fck" },
+ { &core.dss_54m_fck, "dss_54m_fck", "dss_tv_fck" },
+@@ -766,7 +766,8 @@ static void reset_device(struct device *dev, int check)
+ dev->platform_data = NULL;
+ while (dev_p < dev_end) {
+ if (*dev_p) {
+- WARN("%s: struct device fields will be discarded\n",
++ WARN("%s: struct device fields will be "
++ "discarded\n",
+ __func__);
+ break;
+ }
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 52170f8..229c4b1 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1120,17 +1120,33 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+
+ if (mirroring) {
+ switch (rotation) {
+- case 0: vidrot = 2; break;
+- case 1: vidrot = 1; break;
+- case 2: vidrot = 0; break;
+- case 3: vidrot = 3; break;
++ case 0:
++ vidrot = 2;
++ break;
++ case 1:
++ vidrot = 1;
++ break;
++ case 2:
++ vidrot = 0;
++ break;
++ case 3:
++ vidrot = 3;
++ break;
+ }
+ } else {
+ switch (rotation) {
+- case 0: vidrot = 0; break;
+- case 1: vidrot = 1; break;
+- case 2: vidrot = 2; break;
+- case 3: vidrot = 3; break;
++ case 0:
++ vidrot = 0;
++ break;
++ case 1:
++ vidrot = 1;
++ break;
++ case 2:
++ vidrot = 2;
++ break;
++ case 3:
++ vidrot = 3;
++ break;
+ }
+ }
+
+@@ -1923,7 +1939,8 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
+ enabled = REG_GET(DISPC_CONFIG, 10, 10);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 12, 12);
+- else BUG();
++ else
++ BUG();
+ enable_clocks(0);
+
+ return enabled;
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 2251bff..20fb1ca 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -85,16 +85,17 @@ static ssize_t display_upd_mode_store(struct device *dev,
+ val = simple_strtoul(buf, NULL, 10);
+
+ switch (val) {
+- case OMAP_DSS_UPDATE_DISABLED:
+- case OMAP_DSS_UPDATE_AUTO:
+- case OMAP_DSS_UPDATE_MANUAL:
+- mode = (enum omap_dss_update_mode)val;
+- break;
+- default:
+- return -EINVAL;
++ case OMAP_DSS_UPDATE_DISABLED:
++ case OMAP_DSS_UPDATE_AUTO:
++ case OMAP_DSS_UPDATE_MANUAL:
++ mode = (enum omap_dss_update_mode)val;
++ break;
++ default:
++ return -EINVAL;
+ }
+
+- if ((r = dssdev->set_update_mode(dssdev, mode)))
++ r = dssdev->set_update_mode(dssdev, mode);
++ if (r)
+ return r;
+
+ return size;
+@@ -120,7 +121,8 @@ static ssize_t display_tear_store(struct device *dev,
+
+ te = simple_strtoul(buf, NULL, 0);
+
+- if ((r = dssdev->enable_te(dssdev, te)))
++ r = dssdev->enable_te(dssdev, te);
++ if (r)
+ return r;
+
+ return size;
+@@ -169,7 +171,8 @@ static ssize_t display_timings_store(struct device *dev,
+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+ return -EINVAL;
+
+- if ((r = dssdev->check_timings(dssdev, &t)))
++ r = dssdev->check_timings(dssdev, &t);
++ if (r)
+ return r;
+
+ dssdev->set_timings(dssdev, &t);
+@@ -200,7 +203,8 @@ static ssize_t display_rotate_store(struct device *dev,
+
+ rot = simple_strtoul(buf, NULL, 0);
+
+- if ((r = dssdev->set_rotate(dssdev, rot)))
++ r = dssdev->set_rotate(dssdev, rot);
++ if (r)
+ return r;
+
+ return size;
+@@ -229,7 +233,8 @@ static ssize_t display_mirror_store(struct device *dev,
+
+ mirror = simple_strtoul(buf, NULL, 0);
+
+- if ((r = dssdev->set_mirror(dssdev, mirror)))
++ r = dssdev->set_mirror(dssdev, mirror);
++ if (r)
+ return r;
+
+ return size;
+@@ -265,7 +270,8 @@ static ssize_t display_wss_store(struct device *dev,
+ if (wss > 0xfffff)
+ return -EINVAL;
+
+- if ((r = dssdev->set_wss(dssdev, wss)))
++ r = dssdev->set_wss(dssdev, wss);
++ if (r)
+ return r;
+
+ return size;
+@@ -596,8 +602,7 @@ struct omap_dss_device *omap_dss_find_device(void *data,
+ {
+ struct omap_dss_device *dssdev = NULL;
+
+- while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL)
+- {
++ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
+ if (match(dssdev, data))
+ return dssdev;
+ }
+@@ -622,13 +627,13 @@ int omap_dss_start_device(struct omap_dss_device *dssdev)
+ goto err0;
+ }
+
+- if(!try_module_get(dssdev->dev.driver->owner)) {
++ if (!try_module_get(dssdev->dev.driver->owner)) {
+ r = -ENODEV;
+ goto err0;
+ }
+
+ if (dssdev->ctrl.panel) {
+- if(!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
++ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
+ r = -ENODEV;
+ goto err1;
+ }
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 9c8488e..9181a45 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -448,7 +448,8 @@ static void perf_show(const char *name)
+ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
+ total_time_auto_us = (u32)ktime_to_us(total_time_auto);
+
+- printk("DSI(%s): %u fps, setup %u/%u/%u, trans %u/%u/%u\n",
++ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
++ "trans %u/%u/%u\n",
+ name,
+ 1000 * 1000 * numframes / total_time_auto_us,
+ s_min_setup_us,
+@@ -466,8 +467,8 @@ static void perf_show(const char *name)
+ s_max_trans_us = 0;
+ perf_mark_start_auto();
+ } else {
+- printk("DSI(%s): %u us + %u us = %u us (%uHz), %u bytes, "
+- "%u kbytes/sec\n",
++ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
++ "%u bytes, %u kbytes/sec\n",
+ name,
+ setup_us,
+ trans_us,
+@@ -844,9 +845,12 @@ int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ struct dsi_clock_info cur, best;
+ int min_fck_per_pck;
+ int match = 0;
++ unsigned long dss_clk_fck2;
++
++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
+
+ if (req_pck == dsi.cache_req_pck &&
+- dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
++ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ DSSDBG("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+@@ -868,7 +872,7 @@ retry:
+ memset(&best, 0, sizeof(best));
+
+ memset(&cur, 0, sizeof(cur));
+- cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
++ cur.clkin = dss_clk_fck2;
+ cur.use_dss2_fck = 1;
+ cur.highfreq = 0;
+
+@@ -973,11 +977,14 @@ static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
+ struct dsi_clock_info cur, best;
+ const bool use_dss2_fck = 1;
+ unsigned long datafreq;
++ unsigned long dss_clk_fck2;
+
+ DSSDBG("dsi_pll_calc_ddrfreq\n");
+
++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
++
+ if (clk_freq == dsi.cache_clk_freq &&
+- dsi.cache_cinfo.clkin == dss_clk_get_rate(DSS_CLK_FCK2)) {
++ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ DSSDBG("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+@@ -990,7 +997,7 @@ static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
+ memset(&cur, 0, sizeof(cur));
+ cur.use_dss2_fck = use_dss2_fck;
+ if (use_dss2_fck) {
+- cur.clkin = dss_clk_get_rate(DSS_CLK_FCK2);
++ cur.clkin = dss_clk_fck2;
+ cur.highfreq = 0;
+ } else {
+ cur.clkin = dispc_pclk_rate();
+@@ -2081,7 +2088,8 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
+ if (r)
+ return r;
+
+- if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { /* RX_FIFO_NOT_EMPTY */
++ /* RX_FIFO_NOT_EMPTY */
++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
+ DSSERR("RX fifo empty when trying to read.\n");
+ return -EIO;
+ }
+@@ -2611,7 +2619,7 @@ static void dsi_setup_update_dispc(struct omap_dss_device *dssdev,
+ dsi.update_region.y = y;
+ dsi.update_region.w = w;
+ dsi.update_region.h = h;
+- dsi.update_region.bytespp = 3; // XXX
++ dsi.update_region.bytespp = 3; /* XXX */
+ #endif
+
+ dispc_setup_partial_planes(dssdev, &x, &y, &w, &h);
+@@ -2630,7 +2638,7 @@ static void dsi_setup_autoupdate_dispc(struct omap_dss_device *dssdev)
+ dsi.update_region.y = 0;
+ dsi.update_region.w = w;
+ dsi.update_region.h = h;
+- dsi.update_region.bytespp = 3; // XXX
++ dsi.update_region.bytespp = 3; /* XXX */
+ #endif
+
+ /* the overlay settings may not have been applied, if we were in manual
+@@ -2993,8 +3001,8 @@ static void dsi_do_cmd_set_te(struct omap_dss_device *dssdev, bool enable)
+
+ if (!dssdev->phy.dsi.ext_te) {
+ if (enable) {
+- /* disable LP_RX_TO, so that we can receive TE.
+- * Time to wait for TE is longer than the timer allows */
++ /* disable LP_RX_TO, so that we can receive TE. Time
++ * to wait for TE is longer than the timer allows */
+ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+ } else {
+ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index c68b9af..e183fcc 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -44,7 +44,8 @@ static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
+ mgr->device ? mgr->device->name : "<none>");
+ }
+
+-static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const char *buf, size_t size)
++static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
++ const char *buf, size_t size)
+ {
+ int r = 0;
+ size_t len = size;
+@@ -288,7 +289,8 @@ static MANAGER_ATTR(color_key_type, S_IRUGO|S_IWUSR,
+ static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
+ manager_color_key_value_show, manager_color_key_value_store);
+ static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
+- manager_color_key_enabled_show, manager_color_key_enabled_store);
++ manager_color_key_enabled_show,
++ manager_color_key_enabled_store);
+ static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+ manager_alpha_blending_enabled_show,
+ manager_alpha_blending_enabled_store);
+@@ -305,7 +307,8 @@ static struct attribute *manager_sysfs_attrs[] = {
+ NULL
+ };
+
+-static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
++static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
+ {
+ struct omap_overlay_manager *manager;
+ struct manager_attribute *manager_attr;
+@@ -504,9 +507,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+- if (!overlay_enabled(ovl)) {
++ if (!overlay_enabled(ovl))
+ continue;
+- }
+
+ ovl->manager->device->configure_overlay(ovl);
+ }
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 3704727..31385f3 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -47,7 +47,8 @@ static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
+ ovl->manager ? ovl->manager->name : "<none>");
+ }
+
+-static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, size_t size)
++static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
++ size_t size)
+ {
+ int i, r;
+ struct omap_overlay_manager *mgr = NULL;
+@@ -92,8 +93,11 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+ }
+ }
+
+- if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
+- return r;
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
+
+ return size;
+ }
+@@ -131,11 +135,15 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
+
+ info.pos_y = simple_strtoul(last, &last, 10);
+
+- if ((r = ovl->set_overlay_info(ovl, &info)))
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
+ return r;
+
+- if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
+- return r;
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
+
+ return size;
+ }
+@@ -162,11 +170,15 @@ static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
+
+ info.out_height = simple_strtoul(last, &last, 10);
+
+- if ((r = ovl->set_overlay_info(ovl, &info)))
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
+ return r;
+
+- if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
+- return r;
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
+
+ return size;
+ }
+@@ -176,7 +188,8 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
+ }
+
+-static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, size_t size)
++static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
++ size_t size)
+ {
+ int r;
+ struct omap_overlay_info info;
+@@ -185,11 +198,15 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+
+ info.enabled = simple_strtoul(buf, NULL, 10);
+
+- if ((r = ovl->set_overlay_info(ovl, &info)))
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
+ return r;
+
+- if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
+- return r;
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
+
+ return size;
+ }
+@@ -216,11 +233,15 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
+ else
+ info.global_alpha = simple_strtoul(buf, NULL, 10);
+
+- if ((r = ovl->set_overlay_info(ovl, &info)))
++ r = ovl->set_overlay_info(ovl, &info);
++ if (r)
+ return r;
+
+- if (ovl->manager && (r = ovl->manager->apply(ovl->manager)))
+- return r;
++ if (ovl->manager) {
++ r = ovl->manager->apply(ovl->manager);
++ if (r)
++ return r;
++ }
+
+ return size;
+ }
+@@ -261,7 +282,8 @@ static struct attribute *overlay_sysfs_attrs[] = {
+ NULL
+ };
+
+-static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
++static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
+ {
+ struct omap_overlay *overlay;
+ struct overlay_attribute *overlay_attr;
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index d06dc38..740c8c0 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -320,7 +320,8 @@ static void venc_write_config(const struct venc_config *config)
+ venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
+ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
+ venc_write_reg(VENC_M_CONTROL, config->m_control);
+- venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | venc.wss_data);
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
++ venc.wss_data);
+ venc_write_reg(VENC_S_CARR, config->s_carr);
+ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
+ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
+@@ -406,7 +407,6 @@ static const struct venc_config *venc_timings_to_config(
+ /* driver */
+ static int venc_panel_probe(struct omap_dss_device *dssdev)
+ {
+- //dssdev->name = "tv-out";
+ dssdev->panel.timings = omap_dss_pal_timings;
+
+ return 0;
+@@ -497,8 +497,6 @@ int venc_init(struct platform_device *pdev)
+ venc_enable_clocks(0);
+
+ return omap_dss_register_driver(&venc_driver);
+-
+- //return 0;
+ }
+
+ void venc_exit(void)
+@@ -703,7 +701,8 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+
+ venc_enable_clocks(1);
+
+- venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | venc.wss_data);
++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
++ venc.wss_data);
+
+ venc_enable_clocks(0);
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 0ca57db..806b4e7 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -299,7 +299,7 @@ static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ return 0;
+ }
+
+- switch(ck->key_type) {
++ switch (ck->key_type) {
+ case OMAPFB_COLOR_KEY_GFX_DST:
+ kt = OMAP_DSS_COLOR_KEY_GFX_DST;
+ break;
+@@ -646,7 +646,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+
+ case OMAPFB_GET_COLOR_KEY:
+ DBG("ioctl GET_COLOR_KEY\n");
+- if ((r = omapfb_get_color_key(fbi, &p.color_key)) < 0)
++ r = omapfb_get_color_key(fbi, &p.color_key);
++ if (r)
+ break;
+ if (copy_to_user((void __user *)arg, &p.color_key,
+ sizeof(p.color_key)))
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index df5ede3..4e93bd6 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1119,7 +1119,7 @@ ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
+- // XXX needed for VRFB
++ /* XXX needed for VRFB */
+ return count;
+ }
+ #endif
+@@ -1139,7 +1139,7 @@ static struct fb_ops omapfb_ops = {
+ .fb_mmap = omapfb_mmap,
+ .fb_setcolreg = omapfb_setcolreg,
+ .fb_setcmap = omapfb_setcmap,
+- //.fb_write = omapfb_write,
++ /*.fb_write = omapfb_write,*/
+ };
+
+ static void omapfb_free_fbmem(struct fb_info *fbi)
+@@ -1237,7 +1237,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+ /* only ioremap the 0 angle view */
+ va = ioremap_wc(rg->vrfb.paddr[0], size);
+
+- if(!va) {
++ if (!va) {
+ printk(KERN_ERR "vrfb: ioremap failed\n");
+ omap_vrfb_release_ctx(&rg->vrfb);
+ return -ENOMEM;
+@@ -1295,8 +1295,8 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+
+ omap_vrfb_adjust_size(&w, &h, bytespp);
+
+- /* Because we change the resolution of the 0 degree view,
+- * we need to alloc max(w, h) for height */
++ /* Because we change the resolution of the 0 degree
++ * view, we need to alloc max(w, h) for height */
+ h = max(w, h);
+ w = OMAP_VRFB_LINE_LEN;
+
+@@ -1313,11 +1313,11 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+ return omapfb_alloc_fbmem(fbi, size, paddr);
+ }
+
+-static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format format)
++static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
+ {
+ enum omap_color_mode mode;
+
+- switch (format) {
++ switch (fmt) {
+ case OMAPFB_COLOR_RGB565:
+ mode = OMAP_DSS_COLOR_RGB16;
+ break;
+@@ -1633,15 +1633,16 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+
+ if (!var->bits_per_pixel) {
+ switch (display->get_recommended_bpp(display)) {
+- case 16:
+- var->bits_per_pixel = 16;
+- break;
+- case 24:
+- var->bits_per_pixel = 32;
+- break;
+- default:
+- dev_err(fbdev->dev, "illegal display bpp\n");
+- return -EINVAL;
++ case 16:
++ var->bits_per_pixel = 16;
++ break;
++ case 24:
++ var->bits_per_pixel = 32;
++ break;
++ default:
++ dev_err(fbdev->dev, "illegal display "
++ "bpp\n");
++ return -EINVAL;
+ }
+ }
+ } else {
+@@ -1801,7 +1802,7 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+ if (fbdev->num_fbs > 0) {
+ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
+
+- if (ofbi->num_overlays > 0 ) {
++ if (ofbi->num_overlays > 0) {
+ struct omap_overlay *ovl = ofbi->overlays[0];
+
+ r = omapfb_overlay_enable(ovl, 1);
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index dcec42b..a00f61a 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -72,8 +72,8 @@ static ssize_t store_rotate_type(struct device *dev,
+ ofbi->rotation_type = rot_type;
+
+ /*
+- * Since the VRAM for this FB is not allocated at the moment we don't need to
+- * do any further parameter checking at this point.
++ * Since the VRAM for this FB is not allocated at the moment we don't
++ * need to do any further parameter checking at this point.
+ */
+ out:
+ omapfb_unlock(fbdev);
+@@ -321,8 +321,8 @@ static ssize_t show_overlays_rotate(struct device *dev,
+ return l;
+ }
+
+-static ssize_t store_overlays_rotate(struct device *dev, struct device_attribute *attr,
+- const char *buf, size_t count)
++static ssize_t store_overlays_rotate(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
+ {
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+@@ -451,11 +451,13 @@ static ssize_t show_virt(struct device *dev,
+ }
+
+ static struct device_attribute omapfb_attrs[] = {
+- __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, store_rotate_type),
++ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
++ store_rotate_type),
+ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+- __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, store_overlays_rotate),
++ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
++ store_overlays_rotate),
+ __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+ __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+ };
+@@ -473,7 +475,8 @@ int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+ &omapfb_attrs[t]);
+
+ if (r) {
+- dev_err(fbdev->dev, "failed to create sysfs file\n");
++ dev_err(fbdev->dev, "failed to create sysfs "
++ "file\n");
+ return r;
+ }
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0096-DSS2-Overo-add-vdac-dsi-regulators-fix-panel-name.patch b/recipes/linux/linux-omap-pm/dss2/0096-DSS2-Overo-add-vdac-dsi-regulators-fix-panel-name.patch
new file mode 100644
index 0000000000..c81d79e7ca
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0096-DSS2-Overo-add-vdac-dsi-regulators-fix-panel-name.patch
@@ -0,0 +1,278 @@
+From 1ccb690cf0a478e3bbbf9bf1ee0f03a33918b87e Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 1 Jun 2009 20:17:40 +0300
+Subject: [PATCH 096/146] DSS2: Overo: add vdac/dsi regulators, fix panel names
+
+---
+ arch/arm/mach-omap2/board-overo.c | 224 ++++++++++++++++++++++---------------
+ 1 files changed, 132 insertions(+), 92 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index 39f95f5..07868f9 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -183,9 +183,110 @@ static inline void __init overo_init_smsc911x(void)
+ static inline void __init overo_init_smsc911x(void) { return; }
+ #endif
+
++/* DSS */
+ static int lcd_enabled;
+ static int dvi_enabled;
+
++#define OVERO_GPIO_LCD_EN 144
++
++static void __init overo_display_init(void)
++{
++ int r;
++
++ r = gpio_request(OVERO_GPIO_LCD_EN, "display enable");
++ if (r)
++ printk("fail1\n");
++ r = gpio_direction_output(OVERO_GPIO_LCD_EN, 1);
++ if (r)
++ printk("fail2\n");
++ gpio_export(OVERO_GPIO_LCD_EN, 0);
++}
++
++static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
++{
++ if (lcd_enabled) {
++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
++ return -EINVAL;
++ }
++ dvi_enabled = 1;
++
++ gpio_set_value(OVERO_GPIO_LCD_EN, 1);
++
++ return 0;
++}
++
++static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
++{
++ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
++
++ dvi_enabled = 0;
++}
++
++static struct omap_dss_device overo_dvi_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "dvi",
++ .driver_name = "generic_panel",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = overo_panel_enable_dvi,
++ .platform_disable = overo_panel_disable_dvi,
++};
++
++static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
++{
++ if (dvi_enabled) {
++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
++ return -EINVAL;
++ }
++
++ gpio_set_value(OVERO_GPIO_LCD_EN, 1);
++ lcd_enabled = 1;
++ return 0;
++}
++
++static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
++{
++ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
++ lcd_enabled = 0;
++}
++
++static struct omap_dss_device overo_lcd_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .driver_name = "samsung_lte_panel",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = overo_panel_enable_lcd,
++ .platform_disable = overo_panel_disable_lcd,
++};
++
++static struct omap_dss_device *overo_dss_devices[] = {
++ &overo_dvi_device,
++ &overo_lcd_device,
++};
++
++static struct omap_dss_board_info overo_dss_data = {
++ .num_devices = ARRAY_SIZE(overo_dss_devices),
++ .devices = overo_dss_devices,
++ .default_device = &overo_dvi_device,
++};
++
++static struct platform_device overo_dss_device = {
++ .name = "omapdss",
++ .id = -1,
++ .dev = {
++ .platform_data = &overo_dss_data,
++ },
++};
++
++static struct regulator_consumer_supply overo_vdda_dac_supply = {
++ .supply = "vdda_dac",
++ .dev = &overo_dss_device.dev,
++};
++
++static struct regulator_consumer_supply overo_vdds_dsi_supply = {
++ .supply = "vdds_dsi",
++ .dev = &overo_dss_device.dev,
++};
++
+ static struct mtd_partition overo_nand_partitions[] = {
+ {
+ .name = "xloader",
+@@ -235,7 +336,6 @@ static struct platform_device overo_nand_device = {
+ .resource = &overo_nand_resource,
+ };
+
+-
+ static void __init overo_flash_init(void)
+ {
+ u8 cs = 0;
+@@ -334,6 +434,35 @@ static struct regulator_init_data overo_vmmc1 = {
+ .consumer_supplies = &overo_vmmc1_supply,
+ };
+
++/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
++static struct regulator_init_data overo_vdac = {
++ .constraints = {
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &overo_vdda_dac_supply,
++};
++
++/* VPLL2 for digital video outputs */
++static struct regulator_init_data overo_vpll2 = {
++ .constraints = {
++ .name = "VDVI",
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &overo_vdds_dsi_supply,
++};
++
+ /* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
+
+ static struct twl4030_platform_data overo_twldata = {
+@@ -342,6 +471,8 @@ static struct twl4030_platform_data overo_twldata = {
+ .gpio = &overo_gpio_data,
+ .usb = &overo_usb_data,
+ .vmmc1 = &overo_vmmc1,
++ .vdac = &overo_vdac,
++ .vpll2 = &overo_vpll2,
+ };
+
+ static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
+@@ -369,97 +500,6 @@ static void __init overo_init_irq(void)
+ omap_gpio_init();
+ }
+
+-/* DSS */
+-
+-#define OVERO_GPIO_LCD_EN 144
+-
+-static void __init overo_display_init(void)
+-{
+- int r;
+-
+- r = gpio_request(OVERO_GPIO_LCD_EN, "display enable");
+- if (r)
+- printk("fail1\n");
+- r = gpio_direction_output(OVERO_GPIO_LCD_EN, 1);
+- if (r)
+- printk("fail2\n");
+- gpio_export(OVERO_GPIO_LCD_EN, 0);
+-}
+-
+-static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
+-{
+- if (lcd_enabled) {
+- printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+- return -EINVAL;
+- }
+- dvi_enabled = 1;
+-
+- gpio_set_value(OVERO_GPIO_LCD_EN, 1);
+-
+- return 0;
+-}
+-
+-static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
+-{
+- gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+-
+- dvi_enabled = 0;
+-}
+-
+-static struct omap_dss_device overo_dvi_device = {
+- .type = OMAP_DISPLAY_TYPE_DPI,
+- .name = "dvi",
+- .driver_name = "panel_generic",
+- .phy.dpi.data_lines = 24,
+- .platform_enable = overo_panel_enable_dvi,
+- .platform_disable = overo_panel_disable_dvi,
+-};
+-
+-static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
+-{
+- if (dvi_enabled) {
+- printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+- return -EINVAL;
+- }
+-
+- gpio_set_value(OVERO_GPIO_LCD_EN, 1);
+- lcd_enabled = 1;
+- return 0;
+-}
+-
+-static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
+-{
+- gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+- lcd_enabled = 0;
+-}
+-
+-static struct omap_dss_device overo_lcd_device = {
+- .type = OMAP_DISPLAY_TYPE_DPI,
+- .name = "lcd",
+- .driver_name = "samsung-lte430wq-f0c",
+- .phy.dpi.data_lines = 24,
+- .platform_enable = overo_panel_enable_lcd,
+- .platform_disable = overo_panel_disable_lcd,
+-};
+-
+-static struct omap_dss_device *overo_dss_devices[] = {
+- &overo_dvi_device,
+- &overo_lcd_device,
+-};
+-
+-static struct omap_dss_board_info overo_dss_data = {
+- .num_devices = ARRAY_SIZE(overo_dss_devices),
+- .devices = overo_dss_devices,
+- .default_device = &overo_dvi_device,
+-};
+-
+-static struct platform_device overo_dss_device = {
+- .name = "omapdss",
+- .id = -1,
+- .dev = {
+- .platform_data = &overo_dss_data,
+- },
+-};
+
+ static struct omap_board_config_kernel overo_config[] __initdata = {
+ { OMAP_TAG_UART, &overo_uart_config },
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0097-DSS2-implement-overlay_manager_info.patch b/recipes/linux/linux-omap-pm/dss2/0097-DSS2-implement-overlay_manager_info.patch
new file mode 100644
index 0000000000..34dca0cc0c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0097-DSS2-implement-overlay_manager_info.patch
@@ -0,0 +1,649 @@
+From aaa65c193e129dda3518e1e088ad8b3af68165d0 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 2 Jun 2009 16:51:49 +0300
+Subject: [PATCH 097/146] DSS2: implement overlay_manager_info
+
+Store manager config in similar as overlay config. Config
+is applied with mgr->apply(). Also change transparency color key
+variable names from color_key to trans_key.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ Documentation/arm/OMAP/DSS | 10 +-
+ arch/arm/plat-omap/include/mach/display.h | 31 ++--
+ drivers/video/omap2/dss/dispc.c | 4 +-
+ drivers/video/omap2/dss/dss.h | 4 +-
+ drivers/video/omap2/dss/manager.c | 278 ++++++++++++++---------------
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 49 +++---
+ 6 files changed, 186 insertions(+), 190 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 751000b..958686a 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -138,11 +138,11 @@ global_alpha global alpha 0-255 0=transparent 255=opaque
+ /sys/devices/platform/omapdss/manager? directory:
+ display Destination display
+ name
+-alpha_blending_enabled 0=off 1=on
+-color_key_enabled 0=off 1=on
+-color_key_type gfx-destination video-source
+-color_key_value 0 to 2^24
+-default_color default background color RGB24 0 to 2^24
++alpha_blending_enabled 0=off, 1=on
++trans_key_enabled 0=off, 1=on
++trans_key_type gfx-destination, video-source
++trans_key_value transparency color key (RGB24)
++default_color default background color (RGB24)
+
+ /sys/devices/platform/omapdss/display? directory:
+ ctrl_name Controller name
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 94585ba..4ccbe4c 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -110,7 +110,7 @@ enum omap_dss_load_mode {
+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
+ };
+
+-enum omap_dss_color_key_type {
++enum omap_dss_trans_key_type {
+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+ };
+@@ -292,6 +292,16 @@ struct omap_overlay {
+ struct omap_overlay_info *info);
+ };
+
++struct omap_overlay_manager_info {
++ u32 default_color;
++
++ enum omap_dss_trans_key_type trans_key_type;
++ u32 trans_key;
++ bool trans_enabled;
++
++ bool alpha_enabled;
++};
++
+ struct omap_overlay_manager {
+ struct kobject kobj;
+ struct list_head list;
+@@ -299,6 +309,7 @@ struct omap_overlay_manager {
+ const char *name;
+ int id;
+ enum omap_overlay_manager_caps caps;
++ struct omap_overlay_manager_info info;
+ struct omap_dss_device *device;
+ int num_overlays;
+ struct omap_overlay **overlays;
+@@ -310,20 +321,10 @@ struct omap_overlay_manager {
+
+ int (*apply)(struct omap_overlay_manager *mgr);
+
+- void (*set_default_color)(struct omap_overlay_manager *mgr, u32 color);
+- u32 (*get_default_color)(struct omap_overlay_manager *mgr);
+- bool (*get_alpha_blending_status)(struct omap_overlay_manager *mgr);
+- bool (*get_trans_key_status)(struct omap_overlay_manager *mgr);
+- void (*get_trans_key_type_and_value)(struct omap_overlay_manager *mgr,
+- enum omap_dss_color_key_type *type,
+- u32 *trans_key);
+- void (*set_trans_key_type_and_value)(struct omap_overlay_manager *mgr,
+- enum omap_dss_color_key_type type,
+- u32 trans_key);
+- void (*enable_trans_key)(struct omap_overlay_manager *mgr,
+- bool enable);
+- void (*enable_alpha_blending)(struct omap_overlay_manager *mgr,
+- bool enable);
++ int (*set_manager_info)(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info);
++ void (*get_manager_info)(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info);
+ };
+
+ struct omap_dss_device {
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 229c4b1..5ef9a32 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1856,7 +1856,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
+ }
+
+ void dispc_set_trans_key(enum omap_channel ch,
+- enum omap_dss_color_key_type type,
++ enum omap_dss_trans_key_type type,
+ u32 trans_key)
+ {
+ const struct dispc_reg tr_reg[] = {
+@@ -1873,7 +1873,7 @@ void dispc_set_trans_key(enum omap_channel ch,
+ }
+
+ void dispc_get_trans_key(enum omap_channel ch,
+- enum omap_dss_color_key_type *type,
++ enum omap_dss_trans_key_type *type,
+ u32 *trans_key)
+ {
+ const struct dispc_reg tr_reg[] = {
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 6180968..9a3aea1 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -298,10 +298,10 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode);
+ void dispc_set_default_color(enum omap_channel channel, u32 color);
+ u32 dispc_get_default_color(enum omap_channel channel);
+ void dispc_set_trans_key(enum omap_channel ch,
+- enum omap_dss_color_key_type type,
++ enum omap_dss_trans_key_type type,
+ u32 trans_key);
+ void dispc_get_trans_key(enum omap_channel ch,
+- enum omap_dss_color_key_type *type,
++ enum omap_dss_trans_key_type *type,
+ u32 *trans_key);
+ void dispc_enable_trans_key(enum omap_channel ch, bool enable);
+ void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index e183fcc..6afc1cb 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -109,166 +109,175 @@ put_device:
+ static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d",
+- mgr->get_default_color(mgr));
++ return snprintf(buf, PAGE_SIZE, "%d", mgr->info.default_color);
+ }
+
+ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+ {
+- u32 default_color;
++ struct omap_overlay_manager_info info;
++ u32 color;
++ int r;
+
+- if (sscanf(buf, "%d", &default_color) != 1)
++ if (sscanf(buf, "%d", &color) != 1)
+ return -EINVAL;
+- dispc_set_default_color(mgr->id, default_color);
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.default_color = color;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
+
+ return size;
+ }
+
+-static const char *color_key_type_str[] = {
++static const char *trans_key_type_str[] = {
+ "gfx-destination",
+ "video-source",
+ };
+
+-static ssize_t manager_color_key_type_show(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- enum omap_dss_color_key_type key_type;
++ enum omap_dss_trans_key_type key_type;
+
+- mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
+- BUG_ON(key_type >= ARRAY_SIZE(color_key_type_str));
++ key_type = mgr->info.trans_key_type;
++ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
+
+- return snprintf(buf, PAGE_SIZE, "%s\n", color_key_type_str[key_type]);
++ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
+ }
+
+-static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+ {
+- enum omap_dss_color_key_type key_type;
+- u32 key_value;
++ enum omap_dss_trans_key_type key_type;
++ struct omap_overlay_manager_info info;
++ int r;
+
+ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+- key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
+- if (sysfs_streq(buf, color_key_type_str[key_type]))
++ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
++ if (sysfs_streq(buf, trans_key_type_str[key_type]))
+ break;
+ }
+- if (key_type == ARRAY_SIZE(color_key_type_str))
++
++ if (key_type == ARRAY_SIZE(trans_key_type_str))
+ return -EINVAL;
+- /* OMAP does not support destination color key and alpha blending
+- * simultaneously. So if alpha blending and color keying both are
+- * enabled then refrain from setting the color key type to
+- * gfx-destination
+- */
+- if (!key_type) {
+- bool color_key_enabled;
+- bool alpha_blending_enabled;
+- color_key_enabled = mgr->get_trans_key_status(mgr);
+- alpha_blending_enabled = mgr->get_alpha_blending_status(mgr);
+- if (color_key_enabled && alpha_blending_enabled)
+- return -EINVAL;
+- }
+
+- mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
+- mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
++ mgr->get_manager_info(mgr, &info);
++
++ info.trans_key_type = key_type;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
+
+ return size;
+ }
+
+-static ssize_t manager_color_key_value_show(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- u32 key_value;
+-
+- mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
+-
+- return snprintf(buf, PAGE_SIZE, "%d\n", key_value);
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
+ }
+
+-static ssize_t manager_color_key_value_store(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+ {
+- enum omap_dss_color_key_type key_type;
++ struct omap_overlay_manager_info info;
+ u32 key_value;
++ int r;
+
+ if (sscanf(buf, "%d", &key_value) != 1)
+ return -EINVAL;
+- mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
+- mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
++
++ mgr->get_manager_info(mgr, &info);
++
++ info.trans_key = key_value;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
+
+ return size;
+ }
+
+-static ssize_t manager_color_key_enabled_show(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d\n",
+- mgr->get_trans_key_status(mgr));
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
+ }
+
+-static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
++static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+ {
++ struct omap_overlay_manager_info info;
+ int enable;
++ int r;
+
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+
+- /* OMAP does not support destination color keying and
+- * alpha blending simultaneously. so if alpha blending
+- * is enabled refrain from enabling destination color
+- * keying.
+- */
+- if (enable) {
+- bool enabled;
+- enabled = mgr->get_alpha_blending_status(mgr);
+- if (enabled) {
+- enum omap_dss_color_key_type key_type;
+- mgr->get_trans_key_type_and_value(mgr,
+- &key_type, NULL);
+- if (!key_type)
+- return -EINVAL;
+- }
++ mgr->get_manager_info(mgr, &info);
+
+- }
+- mgr->enable_trans_key(mgr, enable);
++ info.trans_enabled = enable ? true : false;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
+
+ return size;
+ }
++
+ static ssize_t manager_alpha_blending_enabled_show(
+ struct omap_overlay_manager *mgr, char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d\n",
+- mgr->get_alpha_blending_status(mgr));
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
+ }
++
+ static ssize_t manager_alpha_blending_enabled_store(
+ struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+ {
++ struct omap_overlay_manager_info info;
+ int enable;
++ int r;
++
+ if (sscanf(buf, "%d", &enable) != 1)
+ return -EINVAL;
+- /* OMAP does not support destination color keying and
+- * alpha blending simultaneously. so if destination
+- * color keying is enabled refrain from enabling
+- * alpha blending
+- */
+- if (enable) {
+- bool enabled;
+- enabled = mgr->get_trans_key_status(mgr);
+- if (enabled) {
+- enum omap_dss_color_key_type key_type;
+- mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
+- if (!key_type)
+- return -EINVAL;
+
+- }
++ mgr->get_manager_info(mgr, &info);
++
++ info.alpha_enabled = enable ? true : false;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++ if (r)
++ return r;
+
+- }
+- mgr->enable_alpha_blending(mgr, enable);
+ return size;
+ }
+
+-
+ struct manager_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct omap_overlay_manager *, char *);
+@@ -284,13 +293,13 @@ static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
+ manager_display_show, manager_display_store);
+ static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
+ manager_default_color_show, manager_default_color_store);
+-static MANAGER_ATTR(color_key_type, S_IRUGO|S_IWUSR,
+- manager_color_key_type_show, manager_color_key_type_store);
+-static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
+- manager_color_key_value_show, manager_color_key_value_store);
+-static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
+- manager_color_key_enabled_show,
+- manager_color_key_enabled_store);
++static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
++ manager_trans_key_type_show, manager_trans_key_type_store);
++static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
++ manager_trans_key_value_show, manager_trans_key_value_store);
++static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
++ manager_trans_key_enabled_show,
++ manager_trans_key_enabled_store);
+ static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+ manager_alpha_blending_enabled_show,
+ manager_alpha_blending_enabled_store);
+@@ -300,9 +309,9 @@ static struct attribute *manager_sysfs_attrs[] = {
+ &manager_attr_name.attr,
+ &manager_attr_display.attr,
+ &manager_attr_default_color.attr,
+- &manager_attr_color_key_type.attr,
+- &manager_attr_color_key_value.attr,
+- &manager_attr_color_key_enabled.attr,
++ &manager_attr_trans_key_type.attr,
++ &manager_attr_trans_key_value.attr,
++ &manager_attr_trans_key_enabled.attr,
+ &manager_attr_alpha_blending_enabled.attr,
+ NULL
+ };
+@@ -513,7 +522,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ ovl->manager->device->configure_overlay(ovl);
+ }
+
+- /* Issue GO for managers */
++ /* Configure managers, and issue GO */
+ list_for_each_entry(mgr, &manager_list, list) {
+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
+ continue;
+@@ -523,6 +532,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ if (!dssdev)
+ continue;
+
++ dispc_set_trans_key(mgr->id, mgr->info.trans_key_type,
++ mgr->info.trans_key);
++ dispc_enable_trans_key(mgr->id, mgr->info.trans_enabled);
++ dispc_enable_alpha_blending(mgr->id, mgr->info.alpha_enabled);
++
+ /* We don't need GO with manual update display. LCD iface will
+ * always be turned off after frame, and new settings will
+ * be taken in to use at next update */
+@@ -537,49 +551,40 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ return ret;
+ }
+
+-static void omap_dss_mgr_set_def_color(struct omap_overlay_manager *mgr,
+- u32 color)
++static int dss_check_manager(struct omap_overlay_manager *mgr)
+ {
+- dispc_set_default_color(mgr->id, color);
+-}
++ /* OMAP does not support destination color keying and alpha blending
++ * simultaneously. */
+
+-static void omap_dss_mgr_set_trans_key_type_and_value(
+- struct omap_overlay_manager *mgr,
+- enum omap_dss_color_key_type type,
+- u32 trans_key)
+-{
+- dispc_set_trans_key(mgr->id, type, trans_key);
+-}
+-static void omap_dss_mgr_get_trans_key_type_and_value(
+- struct omap_overlay_manager *mgr,
+- enum omap_dss_color_key_type *type,
+- u32 *trans_key)
+-{
+- dispc_get_trans_key(mgr->id, type, trans_key);
+-}
++ if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
++ mgr->info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
++ return -EINVAL;
+
+-static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
+- bool enable)
+-{
+- dispc_enable_trans_key(mgr->id, enable);
+-}
+-static void omap_dss_mgr_enable_alpha_blending(struct omap_overlay_manager *mgr,
+- bool enable)
+-{
+- dispc_enable_alpha_blending(mgr->id, enable);
+-}
+-static bool omap_dss_mgr_get_alpha_blending_status(
+- struct omap_overlay_manager *mgr)
+-{
+- return dispc_alpha_blending_enabled(mgr->id);
++ return 0;
+ }
+-static u32 omap_dss_mgr_get_default_color(struct omap_overlay_manager *mgr)
++
++static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info)
+ {
+- return dispc_get_default_color(mgr->id);
++ int r;
++ struct omap_overlay_manager_info old_info;
++
++ old_info = mgr->info;
++ mgr->info = *info;
++
++ r = dss_check_manager(mgr);
++ if (r) {
++ mgr->info = old_info;
++ return r;
++ }
++
++ return 0;
+ }
+-static bool omap_dss_mgr_get_trans_key_status(struct omap_overlay_manager *mgr)
++
++static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
++ struct omap_overlay_manager_info *info)
+ {
+- return dispc_trans_key_enabled(mgr->id);
++ *info = mgr->info;
+ }
+
+ static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
+@@ -620,18 +625,9 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ mgr->set_device = &omap_dss_set_device;
+ mgr->unset_device = &omap_dss_unset_device;
+ mgr->apply = &omap_dss_mgr_apply;
+- mgr->set_default_color = &omap_dss_mgr_set_def_color;
+- mgr->set_trans_key_type_and_value =
+- &omap_dss_mgr_set_trans_key_type_and_value;
+- mgr->get_trans_key_type_and_value =
+- &omap_dss_mgr_get_trans_key_type_and_value;
+- mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key;
+- mgr->get_trans_key_status = &omap_dss_mgr_get_trans_key_status;
+- mgr->enable_alpha_blending =
+- &omap_dss_mgr_enable_alpha_blending;
+- mgr->get_alpha_blending_status =
+- omap_dss_mgr_get_alpha_blending_status;
+- mgr->get_default_color = &omap_dss_mgr_get_default_color;
++ mgr->set_manager_info = &omap_dss_mgr_set_info;
++ mgr->get_manager_info = &omap_dss_mgr_get_info;
++
+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+
+ dss_overlay_setup_dispc_manager(mgr);
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 806b4e7..c513fe0 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -286,17 +286,23 @@ static struct omapfb_color_key omapfb_color_keys[2];
+ static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ struct omapfb_color_key *ck)
+ {
+- enum omap_dss_color_key_type kt;
++ struct omap_overlay_manager_info info;
++ enum omap_dss_trans_key_type kt;
++ int r;
+
+- if (!mgr->set_default_color ||
+- !mgr->set_trans_key_type_and_value ||
+- !mgr->enable_trans_key)
+- return 0;
++ mgr->get_manager_info(mgr, &info);
+
+ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
+- mgr->enable_trans_key(mgr, 0);
++ info.trans_enabled = false;
+ omapfb_color_keys[mgr->id] = *ck;
+- return 0;
++
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++
++ return r;
+ }
+
+ switch (ck->key_type) {
+@@ -310,13 +316,20 @@ static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+ return -EINVAL;
+ }
+
+- mgr->set_default_color(mgr, ck->background);
+- mgr->set_trans_key_type_and_value(mgr, kt, ck->trans_key);
+- mgr->enable_trans_key(mgr, 1);
++ info.default_color = ck->background;
++ info.trans_key = ck->trans_key;
++ info.trans_key_type = kt;
++ info.trans_enabled = true;
+
+ omapfb_color_keys[mgr->id] = *ck;
+
+- return 0;
++ r = mgr->set_manager_info(mgr, &info);
++ if (r)
++ return r;
++
++ r = mgr->apply(mgr);
++
++ return r;
+ }
+
+ static int omapfb_set_color_key(struct fb_info *fbi,
+@@ -342,13 +355,6 @@ static int omapfb_set_color_key(struct fb_info *fbi,
+ goto err;
+ }
+
+- if (!mgr->set_default_color ||
+- !mgr->set_trans_key_type_and_value ||
+- !mgr->enable_trans_key) {
+- r = -ENODEV;
+- goto err;
+- }
+-
+ r = _omapfb_set_color_key(mgr, ck);
+ err:
+ omapfb_unlock(fbdev);
+@@ -379,13 +385,6 @@ static int omapfb_get_color_key(struct fb_info *fbi,
+ goto err;
+ }
+
+- if (!mgr->set_default_color ||
+- !mgr->set_trans_key_type_and_value ||
+- !mgr->enable_trans_key) {
+- r = -ENODEV;
+- goto err;
+- }
+-
+ *ck = omapfb_color_keys[mgr->id];
+ err:
+ omapfb_unlock(fbdev);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0098-DSS2-use-sysfs_streq-to-compare-display-names.patch b/recipes/linux/linux-omap-pm/dss2/0098-DSS2-use-sysfs_streq-to-compare-display-names.patch
new file mode 100644
index 0000000000..79b3704c1d
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0098-DSS2-use-sysfs_streq-to-compare-display-names.patch
@@ -0,0 +1,43 @@
+From 10b82544210f731f5c02e7bfc277f8ecb57c9263 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 2 Jun 2009 17:11:24 +0300
+Subject: [PATCH 098/146] DSS2: use sysfs_streq() to compare display names
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/manager.c | 14 +++-----------
+ 1 files changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 6afc1cb..798867c 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -54,22 +54,14 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+ int match(struct omap_dss_device *dssdev, void *data)
+ {
+ const char *str = data;
+- return strcmp(dssdev->name, str) == 0;
++ return sysfs_streq(dssdev->name, str);
+ }
+
+ if (buf[size-1] == '\n')
+ --len;
+
+- if (len > 0) {
+- char name[64];
+- int n;
+-
+- n = min(len, sizeof(name) - 1);
+- strncpy(name, buf, n);
+- name[n - 1] = 0;
+-
+- dssdev = omap_dss_find_device(name, match);
+- }
++ if (len > 0)
++ dssdev = omap_dss_find_device((void *)buf, match);
+
+ if (len > 0 && dssdev == NULL)
+ return -EINVAL;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0099-DSS2-Implement-function-to-verify-lcd-timings.patch b/recipes/linux/linux-omap-pm/dss2/0099-DSS2-Implement-function-to-verify-lcd-timings.patch
new file mode 100644
index 0000000000..0ba203f5ee
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0099-DSS2-Implement-function-to-verify-lcd-timings.patch
@@ -0,0 +1,144 @@
+From 875cf440d5450f5d91b2ef1ba6f051f93e77b8eb Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 3 Jun 2009 10:45:54 +0300
+Subject: [PATCH 099/146] DSS2: Implement function to verify lcd timings
+
+---
+ drivers/video/omap2/dss/dispc.c | 52 +++++++++++++++++++++++++++------------
+ drivers/video/omap2/dss/dpi.c | 25 +-----------------
+ drivers/video/omap2/dss/dss.h | 1 +
+ 3 files changed, 39 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 5ef9a32..762a0f1 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2015,34 +2015,49 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
+ enable_clocks(0);
+ }
+
++static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
++ int vsw, int vfp, int vbp)
++{
++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
++ if (hsw < 1 || hsw > 64 ||
++ hfp < 1 || hfp > 256 ||
++ hbp < 1 || hbp > 256 ||
++ vsw < 1 || vsw > 64 ||
++ vfp < 0 || vfp > 255 ||
++ vbp < 0 || vbp > 255)
++ return false;
++ } else {
++ if (hsw < 1 || hsw > 256 ||
++ hfp < 1 || hfp > 4096 ||
++ hbp < 1 || hbp > 4096 ||
++ vsw < 1 || vsw > 256 ||
++ vfp < 0 || vfp > 4095 ||
++ vbp < 0 || vbp > 4095)
++ return false;
++ }
++
++ return true;
++}
++
++bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
++{
++ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
++ timings->hbp, timings->vsw,
++ timings->vfp, timings->vbp);
++}
++
+ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
+ int vsw, int vfp, int vbp)
+ {
+ u32 timing_h, timing_v;
+
+ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+- BUG_ON(hsw < 1 || hsw > 64);
+- BUG_ON(hfp < 1 || hfp > 256);
+- BUG_ON(hbp < 1 || hbp > 256);
+-
+- BUG_ON(vsw < 1 || vsw > 64);
+- BUG_ON(vfp < 0 || vfp > 255);
+- BUG_ON(vbp < 0 || vbp > 255);
+-
+ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
+ FLD_VAL(hbp-1, 27, 20);
+
+ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
+ FLD_VAL(vbp, 27, 20);
+ } else {
+- BUG_ON(hsw < 1 || hsw > 256);
+- BUG_ON(hfp < 1 || hfp > 4096);
+- BUG_ON(hbp < 1 || hbp > 4096);
+-
+- BUG_ON(vsw < 1 || vsw > 256);
+- BUG_ON(vfp < 0 || vfp > 4095);
+- BUG_ON(vbp < 0 || vbp > 4095);
+-
+ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
+ FLD_VAL(hbp-1, 31, 20);
+
+@@ -2062,6 +2077,11 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
+ unsigned xtot, ytot;
+ unsigned long ht, vt;
+
++ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
++ timings->hbp, timings->vsw,
++ timings->vfp, timings->vbp))
++ BUG();
++
+ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
+ timings->vsw, timings->vfp, timings->vbp);
+
+diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
+index f5867cf..d244e54 100644
+--- a/drivers/video/omap2/dss/dpi.c
++++ b/drivers/video/omap2/dss/dpi.c
+@@ -287,29 +287,8 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
+ unsigned long fck;
+ unsigned long pck;
+
+- if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+- if (timings->hsw < 1 || timings->hsw > 64 ||
+- timings->hfp < 1 || timings->hfp > 256 ||
+- timings->hbp < 1 || timings->hbp > 256) {
+- return -EINVAL;
+- }
+-
+- if (timings->vsw < 1 || timings->vsw > 64 ||
+- timings->vfp > 255 || timings->vbp > 255) {
+- return -EINVAL;
+- }
+- } else {
+- if (timings->hsw < 1 || timings->hsw > 256 ||
+- timings->hfp < 1 || timings->hfp > 4096 ||
+- timings->hbp < 1 || timings->hbp > 4096) {
+- return -EINVAL;
+- }
+-
+- if (timings->vsw < 1 || timings->vsw > 64 ||
+- timings->vfp > 4095 || timings->vbp > 4095) {
+- return -EINVAL;
+- }
+- }
++ if (!dispc_lcd_timings_ok(timings))
++ return -EINVAL;
+
+ if (timings->pixel_clock == 0)
+ return -EINVAL;
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 9a3aea1..370c54b 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -308,6 +308,7 @@ void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
+ bool dispc_trans_key_enabled(enum omap_channel ch);
+ bool dispc_alpha_blending_enabled(enum omap_channel ch);
+
++bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
+ void dispc_set_lcd_timings(struct omap_video_timings *timings);
+ unsigned long dispc_fclk_rate(void);
+ unsigned long dispc_lclk_rate(void);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0100-DSS2-Remove-non-existing-dsi-power-funcs-from-dss.h.patch b/recipes/linux/linux-omap-pm/dss2/0100-DSS2-Remove-non-existing-dsi-power-funcs-from-dss.h.patch
new file mode 100644
index 0000000000..b3266cf635
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0100-DSS2-Remove-non-existing-dsi-power-funcs-from-dss.h.patch
@@ -0,0 +1,25 @@
+From 193e9e6c7206d21b9cd3eff752432fd2ce4da38c Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 3 Jun 2009 10:51:49 +0300
+Subject: [PATCH 100/146] DSS2: Remove non-existing dsi power funcs from dss.h
+
+---
+ drivers/video/omap2/dss/dss.h | 2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 370c54b..6608f90 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -164,8 +164,6 @@ unsigned long dss_clk_get_rate(enum dss_clock clk);
+ int dss_need_ctx_restore(void);
+ void dss_dump_clocks(struct seq_file *s);
+ struct bus_type *dss_get_bus(void);
+-int dss_dsi_power_up(void);
+-void dss_dsi_power_down(void);
+
+ #define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
+ #define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0101-DSS2-move-to_dss_driver-and-to_dss_device-to-pu.patch b/recipes/linux/linux-omap-pm/dss2/0101-DSS2-move-to_dss_driver-and-to_dss_device-to-pu.patch
new file mode 100644
index 0000000000..b9597efae1
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0101-DSS2-move-to_dss_driver-and-to_dss_device-to-pu.patch
@@ -0,0 +1,40 @@
+From 76be132d45253ddca015c1bb8653a7ed9f7c684a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 4 Jun 2009 10:58:13 +0300
+Subject: [PATCH 101/146] DSS2: move to_dss_driver() and to_dss_device() to public header
+
+---
+ arch/arm/plat-omap/include/mach/display.h | 4 ++++
+ drivers/video/omap2/dss/dss.h | 3 ---
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 4ccbe4c..3d8ed69 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -518,4 +518,8 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
+ int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
+ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout);
++
++#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
++#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
++
+ #endif
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 6608f90..1e40830 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -165,9 +165,6 @@ int dss_need_ctx_restore(void);
+ void dss_dump_clocks(struct seq_file *s);
+ struct bus_type *dss_get_bus(void);
+
+-#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
+-#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
+-
+ /* display */
+ int dss_suspend_all_devices(void);
+ int dss_resume_all_devices(void);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0102-DSS2-CLK-change-omapfb-omapdss-in-clock-framewo.patch b/recipes/linux/linux-omap-pm/dss2/0102-DSS2-CLK-change-omapfb-omapdss-in-clock-framewo.patch
new file mode 100644
index 0000000000..d63fb58800
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0102-DSS2-CLK-change-omapfb-omapdss-in-clock-framewo.patch
@@ -0,0 +1,53 @@
+From 93859ac92c1f76585c6130e651d79ff14bc10c29 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 4 Jun 2009 15:06:22 +0300
+Subject: [PATCH 102/146] DSS2: CLK: change omapfb -> omapdss in clock framework
+
+---
+ arch/arm/mach-omap2/clock24xx.c | 8 ++++----
+ arch/arm/mach-omap2/clock34xx.c | 10 +++++-----
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
+index 44de027..402a3d4 100644
+--- a/arch/arm/mach-omap2/clock24xx.c
++++ b/arch/arm/mach-omap2/clock24xx.c
+@@ -103,10 +103,10 @@ static struct omap_clk omap24xx_clks[] = {
+ CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
+ CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
+ /* DSS domain clocks */
+- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X),
+- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
+- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
+- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
++ CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X),
++ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X),
++ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X),
++ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X),
+ /* L3 domain clocks */
+ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X),
+ CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X),
+diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
+index 045da92..dd7bba2 100644
+--- a/arch/arm/mach-omap2/clock34xx.c
++++ b/arch/arm/mach-omap2/clock34xx.c
+@@ -200,11 +200,11 @@ static struct omap_clk omap34xx_clks[] = {
+ CLK("omap_rng", "ick", &rng_ick, CK_343X),
+ CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
+ CLK(NULL, "des1_ick", &des1_ick, CK_343X),
+- CLK("omapfb", "dss1_fck", &dss1_alwon_fck, CK_343X),
+- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X),
+- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X),
+- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X),
+- CLK("omapfb", "ick", &dss_ick, CK_343X),
++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck, CK_343X),
++ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
++ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
++ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
++ CLK("omapdss", "ick", &dss_ick, CK_343X),
+ CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
+ CLK(NULL, "cam_ick", &cam_ick, CK_343X),
+ CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0103-DSS2-Use-clkdev.patch b/recipes/linux/linux-omap-pm/dss2/0103-DSS2-Use-clkdev.patch
new file mode 100644
index 0000000000..294380594b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0103-DSS2-Use-clkdev.patch
@@ -0,0 +1,122 @@
+From a41c88224dc74dc2feebe16e579fc5df28ad85a4 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 4 Jun 2009 15:07:14 +0300
+Subject: [PATCH 103/146] DSS2: Use clkdev
+
+---
+ drivers/video/omap2/dss/core.c | 85 ++++++++++++++++++++++------------------
+ 1 files changed, 47 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
+index 3f544dc..e8d430c 100644
+--- a/drivers/video/omap2/dss/core.c
++++ b/drivers/video/omap2/dss/core.c
+@@ -150,58 +150,67 @@ void dss_dump_clocks(struct seq_file *s)
+ }
+ }
+
+-static int dss_get_clocks(void)
++static int dss_get_clock(struct clk **clock, const char *clk_name)
+ {
+- const struct {
+- struct clk **clock;
+- char *omap2_name;
+- char *omap3_name;
+- } clocks[5] = {
+- { &core.dss_ick, "dss_ick", "dss_ick" }, /* L3 & L4 ick */
+- { &core.dss1_fck, "dss1_fck", "dss1_alwon_fck" },
+- { &core.dss2_fck, "dss2_fck", "dss2_alwon_fck" },
+- { &core.dss_54m_fck, "dss_54m_fck", "dss_tv_fck" },
+- { &core.dss_96m_fck, NULL, "dss_96m_fck" },
+- };
++ struct clk *clk;
+
+- int r = 0;
+- int i;
+- const int num_clocks = 5;
++ clk = clk_get(&core.pdev->dev, clk_name);
+
+- for (i = 0; i < num_clocks; i++)
+- *clocks[i].clock = NULL;
++ if (IS_ERR(clk)) {
++ DSSERR("can't get clock %s", clk_name);
++ return PTR_ERR(clk);
++ }
+
+- for (i = 0; i < num_clocks; i++) {
+- struct clk *clk;
+- const char *clk_name;
++ *clock = clk;
+
+- clk_name = cpu_is_omap34xx() ? clocks[i].omap3_name
+- : clocks[i].omap2_name;
++ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
+
+- if (!clk_name)
+- continue;
++ return 0;
++}
+
+- clk = clk_get(NULL, clk_name);
++static int dss_get_clocks(void)
++{
++ int r;
+
+- if (IS_ERR(clk)) {
+- DSSERR("can't get clock %s", clk_name);
+- r = PTR_ERR(clk);
+- goto err;
+- }
++ core.dss_ick = NULL;
++ core.dss1_fck = NULL;
++ core.dss2_fck = NULL;
++ core.dss_54m_fck = NULL;
++ core.dss_96m_fck = NULL;
+
+- DSSDBG("clk %s, rate %ld\n",
+- clk_name, clk_get_rate(clk));
++ r = dss_get_clock(&core.dss_ick, "ick");
++ if (r)
++ goto err;
+
+- *clocks[i].clock = clk;
+- }
++ r = dss_get_clock(&core.dss1_fck, "dss1_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss2_fck, "dss2_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
++ if (r)
++ goto err;
++
++ r = dss_get_clock(&core.dss_96m_fck, "video_fck");
++ if (r)
++ goto err;
+
+ return 0;
+
+ err:
+- for (i = 0; i < num_clocks; i++) {
+- if (!IS_ERR(*clocks[i].clock))
+- clk_put(*clocks[i].clock);
+- }
++ if (core.dss_ick)
++ clk_put(core.dss_ick);
++ if (core.dss1_fck)
++ clk_put(core.dss1_fck);
++ if (core.dss2_fck)
++ clk_put(core.dss2_fck);
++ if (core.dss_54m_fck)
++ clk_put(core.dss_54m_fck);
++ if (core.dss_96m_fck)
++ clk_put(core.dss_96m_fck);
+
+ return r;
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0104-DSS2-Fix-documentation.patch b/recipes/linux/linux-omap-pm/dss2/0104-DSS2-Fix-documentation.patch
new file mode 100644
index 0000000000..479c850127
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0104-DSS2-Fix-documentation.patch
@@ -0,0 +1,38 @@
+From 9b9a9009fbb2d13adf0db67a2c27d27e7d624258 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 5 Jun 2009 11:21:13 +0300
+Subject: [PATCH 104/146] DSS2: Fix documentation
+
+---
+ Documentation/arm/OMAP/DSS | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
+index 958686a..0af0e9e 100644
+--- a/Documentation/arm/OMAP/DSS
++++ b/Documentation/arm/OMAP/DSS
+@@ -195,8 +195,8 @@ FB2 --- VID2 -/ TV ----- TV
+ Example: Switch from LCD to DVI
+ ----------------------
+
+-w=`cat $dvi/horizontal | cut -d "," -f 1`
+-h=`cat $dvi/vertical | cut -d "," -f 1`
++w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
++h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
+
+ echo "0" > $lcd/enabled
+ echo "" > $mgr0/display
+@@ -214,8 +214,8 @@ FB2 --- VID2 -/ TV ----- TV
+ Example: Clone GFX overlay to LCD and TV
+ -------------------------------
+
+-w=`cat $tv/horizontal | cut -d "," -f 1`
+-h=`cat $tv/vertical | cut -d "," -f 1`
++w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
++h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
+
+ echo "0" > $ovl0/enabled
+ echo "0" > $ovl1/enabled
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0105-DSS2-OMAPFB-first-set-TE-then-update-mode.patch b/recipes/linux/linux-omap-pm/dss2/0105-DSS2-OMAPFB-first-set-TE-then-update-mode.patch
new file mode 100644
index 0000000000..40831a0428
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0105-DSS2-OMAPFB-first-set-TE-then-update-mode.patch
@@ -0,0 +1,38 @@
+From f2fecd510357dbfb1f7a235ba9a74f1241b5224f Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 9 Jun 2009 11:50:55 +0300
+Subject: [PATCH 105/146] DSS2: OMAPFB: first set TE, then update mode
+
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 4e93bd6..1fe770c 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -2042,17 +2042,17 @@ static int omapfb_probe(struct platform_device *pdev)
+ /* set the update mode */
+ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ #ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 1);
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(def_display,
+ OMAP_DSS_UPDATE_AUTO);
+- if (def_display->enable_te)
+- def_display->enable_te(def_display, 1);
+ #else
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 0);
+ if (def_display->set_update_mode)
+ def_display->set_update_mode(def_display,
+ OMAP_DSS_UPDATE_MANUAL);
+- if (def_display->enable_te)
+- def_display->enable_te(def_display, 0);
+ #endif
+ } else {
+ if (def_display->set_update_mode)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0106-DSS2-OMAPFB-Disable-forced-display-update-on-fb-cl.patch b/recipes/linux/linux-omap-pm/dss2/0106-DSS2-OMAPFB-Disable-forced-display-update-on-fb-cl.patch
new file mode 100644
index 0000000000..bf7febce2c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0106-DSS2-OMAPFB-Disable-forced-display-update-on-fb-cl.patch
@@ -0,0 +1,48 @@
+From fc26a92aecdb3ea3f72196f4e17bbd55589a75a8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 10 Jun 2009 14:14:35 +0300
+Subject: [PATCH 106/146] DSS2: OMAPFB: Disable forced display update on fb close
+
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 1fe770c..b4ac9ec 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -613,6 +613,7 @@ static int omapfb_open(struct fb_info *fbi, int user)
+
+ static int omapfb_release(struct fb_info *fbi, int user)
+ {
++#if 0
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+@@ -620,7 +621,7 @@ static int omapfb_release(struct fb_info *fbi, int user)
+ DBG("Closing fb with plane index %d\n", ofbi->id);
+
+ omapfb_lock(fbdev);
+-#if 1
++
+ if (display && display->get_update_mode && display->update) {
+ /* XXX this update should be removed, I think. But it's
+ * good for debugging */
+@@ -635,13 +636,12 @@ static int omapfb_release(struct fb_info *fbi, int user)
+ display->update(display, 0, 0, w, h);
+ }
+ }
+-#endif
+
+ if (display && display->sync)
+ display->sync(display);
+
+ omapfb_unlock(fbdev);
+-
++#endif
+ return 0;
+ }
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0107-DSS2-DSI-use-INIT_COMPLETION-not-init_completion.patch b/recipes/linux/linux-omap-pm/dss2/0107-DSS2-DSI-use-INIT_COMPLETION-not-init_completion.patch
new file mode 100644
index 0000000000..d0449bcaba
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0107-DSS2-DSI-use-INIT_COMPLETION-not-init_completion.patch
@@ -0,0 +1,25 @@
+From f33fa27066daa62b038fea897159756f78d5faf8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 11 Jun 2009 09:11:10 +0300
+Subject: [PATCH 107/146] DSS2: DSI: use INIT_COMPLETION, not init_completion
+
+---
+ drivers/video/omap2/dss/dsi.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 9181a45..b0294b8 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1878,7 +1878,7 @@ static int dsi_vc_send_bta_sync(int channel)
+ int r = 0;
+ u32 err;
+
+- init_completion(&dsi.bta_completion);
++ INIT_COMPLETION(dsi.bta_completion);
+
+ dsi_vc_enable_bta_irq(channel);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0108-DSS2-DSI-Rewrite-of-the-DSI-update-and-cmd-queue.patch b/recipes/linux/linux-omap-pm/dss2/0108-DSS2-DSI-Rewrite-of-the-DSI-update-and-cmd-queue.patch
new file mode 100644
index 0000000000..e872bfdda9
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0108-DSS2-DSI-Rewrite-of-the-DSI-update-and-cmd-queue.patch
@@ -0,0 +1,1860 @@
+From 218fd1516751829b239e4c64f71291d291c6bc2c Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 11 Jun 2009 09:11:45 +0300
+Subject: [PATCH 108/146] DSS2: DSI: Rewrite of the DSI update and cmd queue
+
+---
+ drivers/video/omap2/dss/dsi.c | 1157 +++++++++++--------------------------
+ drivers/video/omap2/dss/dss.h | 3 +
+ drivers/video/omap2/dss/manager.c | 45 ++-
+ drivers/video/omap2/dss/overlay.c | 65 ++-
+ 4 files changed, 419 insertions(+), 851 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index b0294b8..f98da6f 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -26,12 +26,12 @@
+ #include <linux/err.h>
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+-#include <linux/workqueue.h>
+ #include <linux/mutex.h>
+ #include <linux/seq_file.h>
+-#include <linux/kfifo.h>
+ #include <linux/platform_device.h>
+ #include <linux/regulator/consumer.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
+
+ #include <mach/board.h>
+ #include <mach/display.h>
+@@ -192,60 +192,10 @@ enum fifo_size {
+ DSI_FIFO_SIZE_128 = 4,
+ };
+
+-#define DSI_CMD_FIFO_LEN 16
+-
+-struct dsi_cmd_update {
+- int bytespp;
+- u16 x;
+- u16 y;
+- u16 w;
+- u16 h;
+-};
+-
+-struct dsi_cmd_mem_read {
+- void *buf;
+- size_t size;
+- u16 x;
+- u16 y;
+- u16 w;
+- u16 h;
+- size_t *ret_size;
+- struct completion *completion;
+-};
+-
+-struct dsi_cmd_test {
+- int test_num;
+- int *result;
+- struct completion *completion;
+-};
+-
+-enum dsi_cmd {
+- DSI_CMD_UPDATE,
+- DSI_CMD_AUTOUPDATE,
+- DSI_CMD_SYNC,
+- DSI_CMD_MEM_READ,
+- DSI_CMD_TEST,
+- DSI_CMD_SET_TE,
+- DSI_CMD_SET_UPDATE_MODE,
+- DSI_CMD_SET_ROTATE,
+- DSI_CMD_SET_MIRROR,
+-};
+-
+-struct dsi_cmd_item {
+- struct omap_dss_device *dssdev;
+-
+- enum dsi_cmd cmd;
+-
+- union {
+- struct dsi_cmd_update r;
+- struct completion *sync;
+- struct dsi_cmd_mem_read mem_read;
+- struct dsi_cmd_test test;
+- int te;
+- enum omap_dss_update_mode update_mode;
+- int rotate;
+- int mirror;
+- } u;
++struct dsi_update_region {
++ bool dirty;
++ u16 x, y, w, h;
++ struct omap_dss_device *device;
+ };
+
+ static struct
+@@ -272,30 +222,24 @@ static struct
+
+ struct completion bta_completion;
+
+- struct work_struct framedone_work;
+- struct work_struct process_work;
+- struct delayed_work framedone_timeout_work;
+- struct workqueue_struct *workqueue;
++ struct task_struct *thread;
++ wait_queue_head_t waitqueue;
++
++ spinlock_t update_lock;
++ bool framedone_received;
++ struct dsi_update_region update_region;
++ struct dsi_update_region active_update_region;
++ struct completion update_completion;
+
+ enum omap_dss_update_mode user_update_mode;
+- enum omap_dss_update_mode target_update_mode;
+ enum omap_dss_update_mode update_mode;
+- bool use_te;
++ bool te_enabled;
+ bool use_ext_te;
+- int framedone_scheduled; /* helps to catch strange framedone bugs */
+
+ unsigned long cache_req_pck;
+ unsigned long cache_clk_freq;
+ struct dsi_clock_info cache_cinfo;
+
+- struct kfifo *cmd_fifo;
+- spinlock_t cmd_lock;
+- struct completion cmd_done;
+- atomic_t cmd_fifo_full;
+- atomic_t cmd_pending;
+-
+- bool autoupdate_setup;
+-
+ u32 errors;
+ spinlock_t errors_lock;
+ #ifdef DEBUG
+@@ -303,14 +247,7 @@ static struct
+ ktime_t perf_start_time;
+ ktime_t perf_start_time_auto;
+ int perf_measure_frames;
+-
+- struct {
+- int x, y, w, h;
+- int bytespp;
+- } update_region;
+-
+ #endif
+- int debug_process;
+ int debug_read;
+ int debug_write;
+ } dsi;
+@@ -320,11 +257,6 @@ static unsigned int dsi_perf;
+ module_param_named(dsi_perf, dsi_perf, bool, 0644);
+ #endif
+
+-static void dsi_process_cmd_fifo(struct work_struct *work);
+-static void dsi_push_update(struct omap_dss_device *dssdev,
+- int x, int y, int w, int h);
+-static void dsi_push_autoupdate(struct omap_dss_device *dssdev);
+-
+ static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
+ {
+ __raw_writel(val, dsi.base + idx.idx);
+@@ -370,23 +302,23 @@ static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
+ }
+
+ #ifdef DEBUG
+-static void perf_mark_setup(void)
++static void dsi_perf_mark_setup(void)
+ {
+ dsi.perf_setup_time = ktime_get();
+ }
+
+-static void perf_mark_start(void)
++static void dsi_perf_mark_start(void)
+ {
+ dsi.perf_start_time = ktime_get();
+ }
+
+-static void perf_mark_start_auto(void)
++static void dsi_perf_mark_start_auto(void)
+ {
+ dsi.perf_measure_frames = 0;
+ dsi.perf_start_time_auto = ktime_get();
+ }
+
+-static void perf_show(const char *name)
++static void dsi_perf_show(const char *name)
+ {
+ ktime_t t, setup_time, trans_time;
+ u32 total_bytes;
+@@ -412,9 +344,9 @@ static void perf_show(const char *name)
+
+ total_us = setup_us + trans_us;
+
+- total_bytes = dsi.update_region.w *
+- dsi.update_region.h *
+- dsi.update_region.bytespp;
++ total_bytes = dsi.active_update_region.w *
++ dsi.active_update_region.h *
++ dsi.active_update_region.device->ctrl.pixel_size / 8;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
+ static u32 s_total_trans_us, s_total_setup_us;
+@@ -465,7 +397,7 @@ static void perf_show(const char *name)
+ s_total_trans_us = 0;
+ s_min_trans_us = 0xffffffff;
+ s_max_trans_us = 0;
+- perf_mark_start_auto();
++ dsi_perf_mark_start_auto();
+ } else {
+ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
+ "%u bytes, %u kbytes/sec\n",
+@@ -479,9 +411,10 @@ static void perf_show(const char *name)
+ }
+ }
+ #else
+-#define perf_mark_setup()
+-#define perf_mark_start()
+-#define perf_show(x)
++#define dsi_perf_mark_setup()
++#define dsi_perf_mark_start()
++#define dsi_perf_mark_start_auto()
++#define dsi_perf_show(x)
+ #endif
+
+ static void print_irq_status(u32 status)
+@@ -2464,7 +2397,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ int max_data_per_packet;
+ int max_pixels_per_packet;
+ int pixels_left;
+- int bytespp = 3;
++ int bytespp = dssdev->ctrl.pixel_size / 8;
+ int scr_width;
+ u32 __iomem *data;
+ int start_offset;
+@@ -2508,26 +2441,12 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+
+ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
+
+- dsi_bus_lock();
+-
+- dssdev->driver->setup_update(dssdev, x, y, w, h);
+-
+ pixels_left = w * h;
+
+ DSSDBG("total pixels %d\n", pixels_left);
+
+ data += start_offset;
+
+-#ifdef DEBUG
+- dsi.update_region.x = x;
+- dsi.update_region.y = y;
+- dsi.update_region.w = w;
+- dsi.update_region.h = h;
+- dsi.update_region.bytespp = bytespp;
+-#endif
+-
+- perf_mark_start();
+-
+ while (pixels_left > 0) {
+ /* 0x2c = write_memory_start */
+ /* 0x3c = write_memory_continue */
+@@ -2546,7 +2465,6 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+- dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2559,7 +2477,6 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+- dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2570,7 +2487,6 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+- dsi_bus_unlock();
+ return -EIO;
+ }
+ }
+@@ -2601,64 +2517,21 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
+ DSI_FLUSH(0);
+ }
+
+- perf_show("L4");
+-
+- dsi_bus_unlock();
+-
+ return 0;
+ }
+
+-static void dsi_setup_update_dispc(struct omap_dss_device *dssdev,
+- u16 x, u16 y, u16 w, u16 h)
+-{
+- DSSDBG("dsi_setup_update_dispc(%d,%d %dx%d)\n",
+- x, y, w, h);
+-
+-#ifdef DEBUG
+- dsi.update_region.x = x;
+- dsi.update_region.y = y;
+- dsi.update_region.w = w;
+- dsi.update_region.h = h;
+- dsi.update_region.bytespp = 3; /* XXX */
+-#endif
+-
+- dispc_setup_partial_planes(dssdev, &x, &y, &w, &h);
+-
+- dispc_set_lcd_size(w, h);
+-}
+-
+-static void dsi_setup_autoupdate_dispc(struct omap_dss_device *dssdev)
+-{
+- u16 w, h;
+-
+- dssdev->get_resolution(dssdev, &w, &h);
+-
+-#ifdef DEBUG
+- dsi.update_region.x = 0;
+- dsi.update_region.y = 0;
+- dsi.update_region.w = w;
+- dsi.update_region.h = h;
+- dsi.update_region.bytespp = 3; /* XXX */
+-#endif
+-
+- /* the overlay settings may not have been applied, if we were in manual
+- * mode earlier, so do it here */
+- dssdev->manager->apply(dssdev->manager);
+-
+- dispc_set_lcd_size(w, h);
+-
+- dsi.autoupdate_setup = 0;
+-}
+-
+ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+- int bytespp = 3;
++ int bytespp = dssdev->ctrl.pixel_size / 8;
+ int len;
+ int total_len;
+ int packet_payload;
+ int packet_len;
+ u32 l;
++ bool use_te_trigger;
++
++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+@@ -2677,24 +2550,15 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ if (len % packet_payload)
+ total_len += (len % packet_payload) + 1;
+
+- dsi_bus_lock();
+-
+- dssdev->driver->setup_update(dssdev, x, y, w, h);
+-
+- if (dsi.use_ext_te && dssdev->wait_for_te)
+- dssdev->wait_for_te(dssdev);
+-
+ if (0)
+ dsi_vc_print_status(1);
+
+- perf_mark_start();
+-
+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+ dsi_write_reg(DSI_VC_TE(1), l);
+
+ dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
+
+- if (dsi.use_te)
++ if (use_te_trigger)
+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+ else
+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+@@ -2702,62 +2566,81 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+
+ dispc_disable_sidle();
+
+- queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work,
+- msecs_to_jiffies(1000));
+-
+ dispc_enable_lcd_out(1);
+
+- if (dsi.use_te)
++ if (use_te_trigger)
+ dsi_vc_send_bta(1);
+ }
+
+-static void framedone_timeout_callback(struct work_struct *work)
++static void dsi_framedone_irq_callback(void *data, u32 mask)
+ {
+- DSSERR("framedone timeout\n");
+-
+- dispc_enable_lcd_out(0);
++ dispc_enable_sidle();
+
+- /* XXX TODO: cancel the transfer properly */
++ dsi.framedone_received = true;
++ wake_up(&dsi.waitqueue);
++}
+
+- dsi_bus_unlock();
++static void dsi_set_update_region(struct omap_dss_device *dssdev,
++ u16 x, u16 y, u16 w, u16 h)
++{
++ spin_lock(&dsi.update_lock);
++ if (dsi.update_region.dirty) {
++ dsi.update_region.x = min(x, dsi.update_region.x);
++ dsi.update_region.y = min(y, dsi.update_region.y);
++ dsi.update_region.w = max(w, dsi.update_region.w);
++ dsi.update_region.h = max(h, dsi.update_region.h);
++ } else {
++ dsi.update_region.x = x;
++ dsi.update_region.y = y;
++ dsi.update_region.w = w;
++ dsi.update_region.h = h;
++ }
+
+- /* Schedule, so that other threads that want dsi-bus-lock can get it.
+- * Otherwise with autoupdate we may be holding it all the time */
+- schedule();
++ dsi.update_region.device = dssdev;
++ dsi.update_region.dirty = true;
+
+- /* XXX check that fifo is not full. otherwise we would sleep and never
+- * get to process_cmd_fifo below */
+- /* We check for target_update_mode, not update_mode. No reason to push
+- * new updates if we're turning auto update off */
+- if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_push_autoupdate(dsi.vc[1].dssdev);
++ spin_unlock(&dsi.update_lock);
+
+- atomic_set(&dsi.cmd_pending, 0);
+- dsi_process_cmd_fifo(NULL);
+ }
+
+-static void framedone_callback(void *data, u32 mask)
++static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+ {
+- if (dsi.framedone_scheduled) {
+- DSSERR("Framedone already scheduled. Bogus FRAMEDONE IRQ?\n");
+- return;
+- }
++ u16 w, h;
++
++ DSSDBG("starting auto update\n");
+
+- cancel_delayed_work(&dsi.framedone_timeout_work);
++ /* In automatic mode the overlay settings are applied like on DPI/SDI.
++ * The overlay settings may not have been applied, if we were in manual
++ * mode earlier, so do it here */
++ dssdev->manager->apply(dssdev->manager);
+
+- dispc_enable_sidle();
++ dssdev->get_resolution(dssdev, &w, &h);
+
+- dsi.framedone_scheduled = 1;
++ dsi_set_update_region(dssdev, 0, 0, w, h);
+
+- /* We get FRAMEDONE when DISPC has finished sending pixels and turns
+- * itself off. However, DSI still has the pixels in its buffers, and
+- * is sending the data. Thus we have to wait until we can do a new
+- * transfer or turn the clocks off. We do that in a separate work
+- * func. */
+- queue_work(dsi.workqueue, &dsi.framedone_work);
++ dsi_perf_mark_start_auto();
++
++ wake_up(&dsi.waitqueue);
+ }
+
+-static void framedone_worker(struct work_struct *work)
++static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
++{
++ dssdev->driver->enable_te(dssdev, enable);
++
++ if (!dsi.use_ext_te) {
++ if (enable) {
++ /* disable LP_RX_TO, so that we can receive TE. Time
++ * to wait for TE is longer than the timer allows */
++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
++ } else {
++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++ }
++ }
++
++ return 0;
++}
++
++static void dsi_handle_framedone(void)
+ {
+ u32 l;
+ unsigned long tmo;
+@@ -2765,17 +2648,21 @@ static void framedone_worker(struct work_struct *work)
+
+ l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
+
+- /* There shouldn't be much stuff in DSI buffers, if any, so we'll
+- * just busyloop */
++ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
++ * itself off. However, DSI still has the pixels in its buffers, and is
++ * sending the data. Thus we have to wait until we can do a new
++ * transfer or turn the clocks off. There shouldn't be much stuff in
++ * DSI buffers, if any, so we'll just busyloop */
+ if (l > 0) {
+ tmo = jiffies + msecs_to_jiffies(50);
+ while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */
+ i++;
+ if (time_after(jiffies, tmo)) {
+- DSSERR("timeout waiting TE_SIZE to zero\n");
++ DSSERR("timeout waiting TE_SIZE to zero: %u\n",
++ REG_GET(DSI_VC_TE(1), 23, 0));
+ break;
+ }
+- cpu_relax();
++ schedule();
+ }
+ }
+
+@@ -2785,8 +2672,6 @@ static void framedone_worker(struct work_struct *work)
+ if (REG_GET(DSI_VC_TE(1), 31, 31))
+ DSSERR("TE_START not zero\n");
+
+- perf_show("DISPC");
+-
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ DSSDBG("FRAMEDONE\n");
+
+@@ -2801,543 +2686,145 @@ static void framedone_worker(struct work_struct *work)
+ #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+ dispc_fake_vsync_irq();
+ #endif
+- dsi.framedone_scheduled = 0;
+-
+- dsi_bus_unlock();
+-
+- /* Schedule, so that other threads that want dsi-bus-lock can get it.
+- * Otherwise with autoupdate we may be holding it all the time */
+- schedule();
+-
+- /* XXX check that fifo is not full. otherwise we would sleep and never
+- * get to process_cmd_fifo below */
+- /* We check for target_update_mode, not update_mode. No reason to push
+- * new updates if we're turning auto update off */
+- if (dsi.target_update_mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_push_autoupdate(dsi.vc[1].dssdev);
+-
+- atomic_set(&dsi.cmd_pending, 0);
+- dsi_process_cmd_fifo(NULL);
+ }
+
+-static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+-{
+- DSSDBG("starting auto update\n");
+-
+- dsi.autoupdate_setup = 1;
+-
+- dsi_push_autoupdate(dssdev);
+-
+- perf_mark_start_auto();
+-}
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-/* FIFO functions */
+-
+-static void dsi_signal_fifo_waiters(void)
++static int dsi_update_thread(void *data)
+ {
+- if (atomic_read(&dsi.cmd_fifo_full) > 0) {
+- DSSDBG("SIGNALING: Fifo not full for waiter!\n");
+- complete(&dsi.cmd_done);
+- atomic_dec(&dsi.cmd_fifo_full);
+- }
+-}
++ unsigned long timeout;
++ struct omap_dss_device *device;
++ u16 x, y, w, h;
+
+-/* returns 1 for async op, and 0 for sync op */
+-static int dsi_do_update(struct omap_dss_device *dssdev,
+- struct dsi_cmd_update *upd)
+-{
+- int r;
+- u16 x = upd->x, y = upd->y, w = upd->w, h = upd->h;
+- u16 dw, dh;
+-
+- if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+- return 0;
+-
+- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+- return 0;
+-
+- dssdev->get_resolution(dssdev, &dw, &dh);
+- if (x > dw || y > dh)
+- return 0;
+-
+- if (x + w > dw)
+- w = dw - x;
+-
+- if (y + h > dh)
+- h = dh - y;
+-
+- DSSDBGF("%d,%d %dx%d", x, y, w, h);
+-
+- perf_mark_setup();
+-
+- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+- dsi_setup_update_dispc(dssdev, x, y, w, h);
+- dsi_update_screen_dispc(dssdev, x, y, w, h);
+- return 1;
+- } else {
+- r = dsi_update_screen_l4(dssdev, x, y, w, h);
+- if (r)
+- DSSERR("L4 update failed\n");
+- return 0;
+- }
+-}
+-
+-/* returns 1 for async op, and 0 for sync op */
+-static int dsi_do_autoupdate(struct omap_dss_device *dssdev)
+-{
+- int r;
+- u16 w, h;
+-
+- if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
+- return 0;
+-
+- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+- return 0;
+-
+- dssdev->get_resolution(dssdev, &w, &h);
+-
+- perf_mark_setup();
+-
+- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+- if (dsi.autoupdate_setup)
+- dsi_setup_autoupdate_dispc(dssdev);
+- dsi_update_screen_dispc(dssdev, 0, 0, w, h);
+- return 1;
+- } else {
+- r = dsi_update_screen_l4(dssdev, 0, 0, w, h);
+- if (r)
+- DSSERR("L4 update failed\n");
+- return 0;
+- }
+-}
+-
+-static void dsi_do_cmd_mem_read(struct omap_dss_device *dssdev,
+- struct dsi_cmd_mem_read *mem_read)
+-{
+- int r;
+-
+- dsi_bus_lock();
+-
+- r = dssdev->driver->memory_read(dssdev,
+- mem_read->buf,
+- mem_read->size,
+- mem_read->x,
+- mem_read->y,
+- mem_read->w,
+- mem_read->h);
+-
+- dsi_bus_unlock();
+-
+- *mem_read->ret_size = (size_t)r;
+- complete(mem_read->completion);
+-}
+-
+-static void dsi_do_cmd_test(struct omap_dss_device *dssdev,
+- struct dsi_cmd_test *test)
+-{
+- int r = 0;
+-
+- DSSDBGF("");
+-
+- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+- return;
+-
+- dsi_bus_lock();
+-
+- /* run test first in low speed mode */
+- dsi_vc_enable_hs(0, 0);
+-
+- if (dssdev->driver->run_test) {
+- r = dssdev->driver->run_test(dssdev, test->test_num);
+- if (r)
+- goto end;
+- }
+-
+- /* then in high speed */
+- dsi_vc_enable_hs(0, 1);
+-
+- if (dssdev->driver->run_test) {
+- r = dssdev->driver->run_test(dssdev, test->test_num);
+- if (r)
+- goto end;
+- }
+-
+-end:
+- dsi_vc_enable_hs(0, 1);
+-
+- dsi_bus_unlock();
+-
+- *test->result = r;
+- complete(test->completion);
+-
+- DSSDBG("test end\n");
+-}
+-
+-static void dsi_do_cmd_set_te(struct omap_dss_device *dssdev, bool enable)
+-{
+- if (!dssdev->phy.dsi.ext_te)
+- dsi.use_te = enable;
+- else
+- dsi.use_ext_te = enable;
+-
+- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+- return;
+-
+- dsi_bus_lock();
+- dssdev->driver->enable_te(dssdev, enable);
+- dsi_bus_unlock();
+-
+- if (!dssdev->phy.dsi.ext_te) {
+- if (enable) {
+- /* disable LP_RX_TO, so that we can receive TE. Time
+- * to wait for TE is longer than the timer allows */
+- REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+- } else {
+- REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+- }
+- }
+-}
+-
+-static void dsi_do_cmd_set_update_mode(struct omap_dss_device *dssdev,
+- enum omap_dss_update_mode mode)
+-{
+- dsi.update_mode = mode;
+-
+- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+- return;
+-
+- if (mode == OMAP_DSS_UPDATE_AUTO)
+- dsi_start_auto_update(dssdev);
+-}
+-
+-static void dsi_process_cmd_fifo(struct work_struct *work)
+-{
+- int len;
+- struct dsi_cmd_item p;
+- unsigned long flags;
+- struct omap_dss_device *dssdev;
+- int exit = 0;
+-
+- if (dsi.debug_process)
+- DSSDBGF("");
+-
+- if (atomic_cmpxchg(&dsi.cmd_pending, 0, 1) == 1) {
+- if (dsi.debug_process)
+- DSSDBG("cmd pending, skip process\n");
+- return;
+- }
+-
+- while (!exit) {
+- spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
+-
+- len = __kfifo_get(dsi.cmd_fifo, (unsigned char *)&p,
+- sizeof(p));
+- if (len == 0) {
+- if (dsi.debug_process)
+- DSSDBG("nothing more in fifo, atomic clear\n");
+- atomic_set(&dsi.cmd_pending, 0);
+- spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
+- break;
+- }
+-
+- spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
+-
+- BUG_ON(len != sizeof(p));
+-
+- dssdev = p.dssdev;
+-
+- if (dsi.debug_process)
+- DSSDBG("processing cmd %d\n", p.cmd);
+-
+- switch (p.cmd) {
+- case DSI_CMD_UPDATE:
+- if (dsi_do_update(dssdev, &p.u.r)) {
+- if (dsi.debug_process)
+- DSSDBG("async update\n");
+- exit = 1;
+- } else {
+- if (dsi.debug_process)
+- DSSDBG("sync update\n");
+- }
+- break;
+-
+- case DSI_CMD_AUTOUPDATE:
+- if (dsi_do_autoupdate(dssdev)) {
+- if (dsi.debug_process)
+- DSSDBG("async autoupdate\n");
+- exit = 1;
+- } else {
+- if (dsi.debug_process)
+- DSSDBG("sync autoupdate\n");
+- }
+- break;
+-
+- case DSI_CMD_SYNC:
+- if (dsi.debug_process)
+- DSSDBG("Signaling SYNC done!\n");
+- complete(p.u.sync);
+- break;
+-
+- case DSI_CMD_MEM_READ:
+- dsi_do_cmd_mem_read(dssdev, &p.u.mem_read);
+- break;
++ while (1) {
++ bool sched;
+
+- case DSI_CMD_TEST:
+- dsi_do_cmd_test(dssdev, &p.u.test);
+- break;
++ wait_event_interruptible(dsi.waitqueue,
++ dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
++ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
++ dsi.update_region.dirty == true) ||
++ kthread_should_stop());
+
+- case DSI_CMD_SET_TE:
+- dsi_do_cmd_set_te(dssdev, p.u.te);
++ if (kthread_should_stop())
+ break;
+
+- case DSI_CMD_SET_UPDATE_MODE:
+- dsi_do_cmd_set_update_mode(dssdev, p.u.update_mode);
+- break;
+-
+- case DSI_CMD_SET_ROTATE:
+- dsi_bus_lock();
+- dssdev->driver->set_rotate(dssdev, p.u.rotate);
+- if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+- dsi.autoupdate_setup = 1;
+- dsi_bus_unlock();
+- break;
++ dsi_bus_lock();
+
+- case DSI_CMD_SET_MIRROR:
+- dsi_bus_lock();
+- dssdev->driver->set_mirror(dssdev, p.u.mirror);
++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
++ kthread_should_stop()) {
+ dsi_bus_unlock();
+ break;
+-
+- default:
+- BUG();
+ }
+- }
+-
+- if (dsi.debug_process)
+- DSSDBG("exit dsi_process_cmd_fifo\n");
+-
+- dsi_signal_fifo_waiters();
+-}
+-
+-static void dsi_push_cmd(struct dsi_cmd_item *p)
+-{
+- int ret;
+
+- if (dsi.debug_process)
+- DSSDBGF("");
++ dsi_perf_mark_setup();
+
+- while (1) {
+- unsigned long flags;
+- unsigned avail, used;
+-
+- spin_lock_irqsave(dsi.cmd_fifo->lock, flags);
+- used = __kfifo_len(dsi.cmd_fifo) / sizeof(struct dsi_cmd_item);
+- avail = DSI_CMD_FIFO_LEN - used;
+-
+- if (dsi.debug_process)
+- DSSDBG("%u/%u items left in fifo\n", avail, used);
+-
+- if (avail == 0) {
+- if (dsi.debug_process)
+- DSSDBG("cmd fifo full, waiting...\n");
+- spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
+- atomic_inc(&dsi.cmd_fifo_full);
+- wait_for_completion(&dsi.cmd_done);
+- if (dsi.debug_process)
+- DSSDBG("cmd fifo not full, woke up\n");
+- continue;
++ if (dsi.update_region.dirty) {
++ spin_lock(&dsi.update_lock);
++ dsi.active_update_region = dsi.update_region;
++ dsi.update_region.dirty = false;
++ spin_unlock(&dsi.update_lock);
+ }
+
+- ret = __kfifo_put(dsi.cmd_fifo, (unsigned char *)p,
+- sizeof(*p));
+-
+- spin_unlock_irqrestore(dsi.cmd_fifo->lock, flags);
+-
+- BUG_ON(ret != sizeof(*p));
+-
+- break;
+- }
+-
+- queue_work(dsi.workqueue, &dsi.process_work);
+-}
+-
+-static void dsi_push_update(struct omap_dss_device *dssdev,
+- int x, int y, int w, int h)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_UPDATE;
+-
+- p.u.r.x = x;
+- p.u.r.y = y;
+- p.u.r.w = w;
+- p.u.r.h = h;
+-
+- DSSDBG("pushing UPDATE %d,%d %dx%d\n", x, y, w, h);
+-
+- dsi_push_cmd(&p);
+-}
+-
+-static void dsi_push_autoupdate(struct omap_dss_device *dssdev)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_AUTOUPDATE;
+-
+- dsi_push_cmd(&p);
+-}
+-
+-static void dsi_push_sync(struct omap_dss_device *dssdev,
+- struct completion *sync_comp)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_SYNC;
+- p.u.sync = sync_comp;
+-
+- DSSDBG("pushing SYNC\n");
+-
+- dsi_push_cmd(&p);
+-}
+-
+-static void dsi_push_mem_read(struct omap_dss_device *dssdev,
+- struct dsi_cmd_mem_read *mem_read)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_MEM_READ;
+- p.u.mem_read = *mem_read;
++ device = dsi.active_update_region.device;
++ x = dsi.active_update_region.x;
++ y = dsi.active_update_region.y;
++ w = dsi.active_update_region.w;
++ h = dsi.active_update_region.h;
+
+- DSSDBG("pushing MEM_READ\n");
+-
+- dsi_push_cmd(&p);
+-}
+-
+-static void dsi_push_test(struct omap_dss_device *dssdev, int test_num,
+- int *result, struct completion *completion)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_TEST;
+- p.u.test.test_num = test_num;
+- p.u.test.result = result;
+- p.u.test.completion = completion;
+-
+- DSSDBG("pushing TEST\n");
+-
+- dsi_push_cmd(&p);
+-}
++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+
+-static void dsi_push_set_te(struct omap_dss_device *dssdev, bool enable)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_SET_TE;
+- p.u.te = enable;
+-
+- DSSDBG("pushing SET_TE\n");
+-
+- dsi_push_cmd(&p);
+-}
+-
+-static void dsi_push_set_update_mode(struct omap_dss_device *dssdev,
+- enum omap_dss_update_mode mode)
+-{
+- struct dsi_cmd_item p;
+-
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_SET_UPDATE_MODE;
+- p.u.update_mode = mode;
+-
+- DSSDBG("pushing SET_UPDATE_MODE\n");
+-
+- dsi_push_cmd(&p);
+-}
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
++ dispc_setup_partial_planes(device,
++ &x, &y, &w, &h);
++#if 1
++ /* XXX there seems to be a bug in this driver
++ * or OMAP hardware. Some updates with certain
++ * widths and x coordinates fail. These widths
++ * are always odd, so "fix" it here for now */
++ if (w & 1) {
++ u16 dw, dh;
++ device->get_resolution(device, &dw, &dh);
++ if (x + w == dw)
++ x &= ~1;
++ ++w;
++
++ dispc_setup_partial_planes(device,
++ &x, &y, &w, &h);
++ }
++#endif
++ }
+
+-static void dsi_push_set_rotate(struct omap_dss_device *dssdev, int rotate)
+-{
+- struct dsi_cmd_item p;
++ dispc_set_lcd_size(w, h);
++ }
+
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_SET_ROTATE;
+- p.u.rotate = rotate;
++ /* XXX We don't need to send the update area coords to the
++ * panel every time. But for some reason TE doesn't work if we
++ * don't send at least a BTA here... */
++#if 0
++ if (dsi.active_update_region.dirty) {
++ dsi.active_update_region.dirty = false;
++ device->driver->setup_update(device, x, y, w, h);
++ }
++#else
++ device->driver->setup_update(device, x, y, w, h);
++#endif
+
+- DSSDBG("pushing SET_ROTATE\n");
++ if (dsi.te_enabled && dsi.use_ext_te && device->wait_for_te)
++ device->wait_for_te(device);
+
+- dsi_push_cmd(&p);
+-}
++ dsi_perf_mark_start();
+
+-static void dsi_push_set_mirror(struct omap_dss_device *dssdev, int mirror)
+-{
+- struct dsi_cmd_item p;
++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ dsi_update_screen_dispc(device, x, y, w, h);
+
+- p.dssdev = dssdev;
+- p.cmd = DSI_CMD_SET_MIRROR;
+- p.u.mirror = mirror;
++ /* wait for framedone */
++ timeout = msecs_to_jiffies(500);
++ timeout = wait_event_timeout(dsi.waitqueue,
++ dsi.framedone_received == true,
++ timeout);
+
+- DSSDBG("pushing SET_MIRROR\n");
++ dsi.framedone_received = false;
+
+- dsi_push_cmd(&p);
+-}
++ if (timeout == 0) {
++ DSSERR("framedone timeout\n");
++ DSSERR("failed update %d,%d %dx%d\n",
++ x, y, w, h);
+
+-static int dsi_wait_sync(struct omap_dss_device *dssdev)
+-{
+- long wait = msecs_to_jiffies(2000);
+- struct completion compl;
++ dispc_enable_sidle();
++ dispc_enable_lcd_out(0);
++ } else {
++ dsi_handle_framedone();
++ dsi_perf_show("DISPC");
++ }
++ } else {
++ dsi_update_screen_l4(device, x, y, w, h);
++ dsi_perf_show("L4");
++ }
+
+- DSSDBGF("");
++ sched = atomic_read(&dsi.bus_lock.count) < 0;
+
+- init_completion(&compl);
+- dsi_push_sync(dssdev, &compl);
++ complete_all(&dsi.update_completion);
+
+- DSSDBG("Waiting for SYNC to happen...\n");
+- wait = wait_for_completion_timeout(&compl, wait);
+- DSSDBG("Released from SYNC\n");
++ dsi_bus_unlock();
+
+- if (wait == 0) {
+- DSSERR("timeout waiting sync\n");
+- return -ETIME;
++ /* XXX We need to give others chance to get the bus lock. Is
++ * there a better way for this? */
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
++ schedule_timeout_interruptible(1);
+ }
+
++ DSSDBG("update thread exiting\n");
++
+ return 0;
+ }
+
+
+
+-
+-
+-
+-
+-
+-
+-
+-
+-
+ /* Display funcs */
+
+ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
+ {
+ int r;
+
+- r = omap_dispc_register_isr(framedone_callback, NULL,
++ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ if (r) {
+ DSSERR("can't get FRAMEDONE irq\n");
+@@ -3369,7 +2856,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
+
+ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
+ {
+- omap_dispc_unregister_isr(framedone_callback, NULL,
++ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+ }
+
+@@ -3380,8 +2867,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+
+ _dsi_print_reset_status();
+
+- dsi_bus_lock();
+-
+ r = dsi_pll_init(1, 0);
+ if (r)
+ goto err0;
+@@ -3427,8 +2912,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+ /* enable high-speed after initial config */
+ dsi_vc_enable_hs(0, 1);
+
+- dsi_bus_unlock();
+-
+ return 0;
+ err3:
+ dsi_if_enable(0);
+@@ -3437,16 +2920,13 @@ err2:
+ err1:
+ dsi_pll_uninit();
+ err0:
+- dsi_bus_unlock();
+ return r;
+ }
+
+ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
+ {
+- dsi_bus_lock();
+ if (dssdev->driver->disable)
+ dssdev->driver->disable(dssdev);
+- dsi_bus_unlock();
+
+ dsi_complexio_uninit();
+ dsi_pll_uninit();
+@@ -3475,6 +2955,7 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
+ DSSDBG("dsi_display_enable\n");
+
+ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
+
+ r = omap_dss_start_device(dssdev);
+ if (r) {
+@@ -3507,15 +2988,17 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+- if (dsi.use_te || dsi.use_ext_te)
+- dsi_push_set_te(dssdev, 1);
++ dsi.use_ext_te = dssdev->phy.dsi.ext_te;
++ dsi_set_te(dssdev, dsi.te_enabled);
+
+- dsi_push_set_update_mode(dssdev, dsi.user_update_mode);
+- dsi.target_update_mode = dsi.user_update_mode;
++ dsi.update_mode = dsi.user_update_mode;
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
+
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+- return dsi_wait_sync(dssdev);
++ return 0;
+
+ err3:
+ dsi_display_uninit_dispc(dssdev);
+@@ -3525,6 +3008,7 @@ err2:
+ err1:
+ omap_dss_stop_device(dssdev);
+ err0:
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+ DSSDBG("dsi_display_enable FAILED\n");
+ return r;
+@@ -3535,18 +3019,13 @@ static void dsi_display_disable(struct omap_dss_device *dssdev)
+ DSSDBG("dsi_display_disable\n");
+
+ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ goto end;
+
+- if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
+- dsi_push_set_update_mode(dssdev, OMAP_DSS_UPDATE_DISABLED);
+- dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
+- }
+-
+- dsi_wait_sync(dssdev);
+-
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ dsi_display_uninit_dispc(dssdev);
+@@ -3558,6 +3037,7 @@ static void dsi_display_disable(struct omap_dss_device *dssdev)
+
+ omap_dss_stop_device(dssdev);
+ end:
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+ }
+
+@@ -3566,18 +3046,13 @@ static int dsi_display_suspend(struct omap_dss_device *dssdev)
+ DSSDBG("dsi_display_suspend\n");
+
+ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ goto end;
+
+- if (dsi.target_update_mode != OMAP_DSS_UPDATE_DISABLED) {
+- dsi_push_set_update_mode(dssdev, OMAP_DSS_UPDATE_DISABLED);
+- dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
+- }
+-
+- dsi_wait_sync(dssdev);
+-
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ dsi_display_uninit_dispc(dssdev);
+@@ -3587,6 +3062,7 @@ static int dsi_display_suspend(struct omap_dss_device *dssdev)
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+ end:
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+ return 0;
+@@ -3599,6 +3075,7 @@ static int dsi_display_resume(struct omap_dss_device *dssdev)
+ DSSDBG("dsi_display_resume\n");
+
+ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+ DSSERR("dssdev not suspended\n");
+@@ -3625,15 +3102,16 @@ static int dsi_display_resume(struct omap_dss_device *dssdev)
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+- if (dsi.use_te || dsi.use_ext_te)
+- dsi_push_set_te(dssdev, 1);
++ dsi_set_te(dssdev, dsi.te_enabled);
+
+- dsi_push_set_update_mode(dssdev, dsi.user_update_mode);
+- dsi.target_update_mode = dsi.user_update_mode;
++ dsi.update_mode = dsi.user_update_mode;
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
+
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+- return dsi_wait_sync(dssdev);
++ return 0;
+
+ err2:
+ dsi_display_uninit_dispc(dssdev);
+@@ -3641,6 +3119,7 @@ err1:
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+ err0:
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+ DSSDBG("dsi_display_resume FAILED\n");
+ return r;
+@@ -3649,26 +3128,68 @@ err0:
+ static int dsi_display_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+ {
++ int r = 0;
++ u16 dw, dh;
++
+ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
+
++ mutex_lock(&dsi.lock);
++
++ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
++ goto end;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto end;
++
++ dssdev->get_resolution(dssdev, &dw, &dh);
++
++ if (x > dw || y > dh)
++ goto end;
++
++ if (x + w > dw)
++ w = dw - x;
++
++ if (y + h > dh)
++ h = dh - y;
++
+ if (w == 0 || h == 0)
+- return 0;
++ goto end;
+
+- mutex_lock(&dsi.lock);
++ dsi_set_update_region(dssdev, x, y, w, h);
+
+- if (dsi.target_update_mode == OMAP_DSS_UPDATE_MANUAL)
+- dsi_push_update(dssdev, x, y, w, h);
+- /* XXX else return error? */
++ wake_up(&dsi.waitqueue);
+
++end:
+ mutex_unlock(&dsi.lock);
+
+- return 0;
++ return r;
+ }
+
+ static int dsi_display_sync(struct omap_dss_device *dssdev)
+ {
+- DSSDBGF("");
+- return dsi_wait_sync(dssdev);
++ bool wait;
++
++ DSSDBG("dsi_display_sync()\n");
++
++ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
++
++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
++ dsi.update_region.dirty) {
++ INIT_COMPLETION(dsi.update_completion);
++ wait = true;
++ } else {
++ wait = false;
++ }
++
++ dsi_bus_unlock();
++ mutex_unlock(&dsi.lock);
++
++ if (wait)
++ wait_for_completion_interruptible(&dsi.update_completion);
++
++ DSSDBG("dsi_display_sync() done\n");
++ return 0;
+ }
+
+ static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
+@@ -3677,17 +3198,21 @@ static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
+ DSSDBGF("%d", mode);
+
+ mutex_lock(&dsi.lock);
++ dsi_bus_lock();
+
+- if (dsi.target_update_mode != mode) {
+- dsi_push_set_update_mode(dssdev, mode);
+-
+- dsi.target_update_mode = mode;
++ if (dsi.update_mode != mode) {
+ dsi.user_update_mode = mode;
++ dsi.update_mode = mode;
++
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
++ mode == OMAP_DSS_UPDATE_AUTO)
++ dsi_start_auto_update(dssdev);
+ }
+
++ dsi_bus_unlock();
+ mutex_unlock(&dsi.lock);
+
+- return dsi_wait_sync(dssdev);
++ return 0;
+ }
+
+ static enum omap_dss_update_mode dsi_display_get_update_mode(
+@@ -3696,6 +3221,7 @@ static enum omap_dss_update_mode dsi_display_get_update_mode(
+ return dsi.update_mode;
+ }
+
++
+ static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ {
+ DSSDBGF("%d", enable);
+@@ -3703,28 +3229,45 @@ static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ if (!dssdev->driver->enable_te)
+ return -ENOENT;
+
+- dsi_push_set_te(dssdev, enable);
++ dsi_bus_lock();
++
++ dsi.te_enabled = enable;
++
++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
++ goto end;
+
+- return dsi_wait_sync(dssdev);
++ dsi_set_te(dssdev, enable);
++end:
++ dsi_bus_unlock();
++
++ return 0;
+ }
+
+ static int dsi_display_get_te(struct omap_dss_device *dssdev)
+ {
+- return dsi.use_te | dsi.use_ext_te;
++ return dsi.te_enabled;
+ }
+
+-
+-
+ static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
+ {
++
+ DSSDBGF("%d", rotate);
+
+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return -EINVAL;
+
+- dsi_push_set_rotate(dssdev, rotate);
++ dsi_bus_lock();
++ dssdev->driver->set_rotate(dssdev, rotate);
++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
++ u16 w, h;
++ /* the display dimensions may have changed, so set a new
++ * update region */
++ dssdev->get_resolution(dssdev, &w, &h);
++ dsi_set_update_region(dssdev, 0, 0, w, h);
++ }
++ dsi_bus_unlock();
+
+- return dsi_wait_sync(dssdev);
++ return 0;
+ }
+
+ static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
+@@ -3742,9 +3285,11 @@ static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return -EINVAL;
+
+- dsi_push_set_mirror(dssdev, mirror);
++ dsi_bus_lock();
++ dssdev->driver->set_mirror(dssdev, mirror);
++ dsi_bus_unlock();
+
+- return dsi_wait_sync(dssdev);
++ return 0;
+ }
+
+ static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
+@@ -3757,39 +3302,46 @@ static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
+
+ static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
+ {
+- long wait = msecs_to_jiffies(60000);
+- struct completion compl;
+- int result;
++ int r;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+ DSSDBGF("%d", test_num);
+
+- init_completion(&compl);
++ dsi_bus_lock();
+
+- dsi_push_test(dssdev, test_num, &result, &compl);
++ /* run test first in low speed mode */
++ dsi_vc_enable_hs(0, 0);
+
+- DSSDBG("Waiting for SYNC to happen...\n");
+- wait = wait_for_completion_timeout(&compl, wait);
+- DSSDBG("Released from SYNC\n");
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test_num);
++ if (r)
++ goto end;
++ }
+
+- if (wait == 0) {
+- DSSERR("timeout waiting test sync\n");
+- return -ETIME;
++ /* then in high speed */
++ dsi_vc_enable_hs(0, 1);
++
++ if (dssdev->driver->run_test) {
++ r = dssdev->driver->run_test(dssdev, test_num);
++ if (r)
++ goto end;
+ }
+
+- return result;
++end:
++ dsi_vc_enable_hs(0, 1);
++
++ dsi_bus_unlock();
++
++ return r;
+ }
+
+ static int dsi_display_memory_read(struct omap_dss_device *dssdev,
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h)
+ {
+- long wait = msecs_to_jiffies(60000);
+- struct completion compl;
+- struct dsi_cmd_mem_read mem_read;
+- size_t ret_size;
++ int r;
+
+ DSSDBGF("");
+
+@@ -3799,29 +3351,14 @@ static int dsi_display_memory_read(struct omap_dss_device *dssdev,
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return -EIO;
+
+- init_completion(&compl);
+-
+- mem_read.x = x;
+- mem_read.y = y;
+- mem_read.w = w;
+- mem_read.h = h;
+- mem_read.buf = buf;
+- mem_read.size = size;
+- mem_read.ret_size = &ret_size;
+- mem_read.completion = &compl;
+-
+- dsi_push_mem_read(dssdev, &mem_read);
++ dsi_bus_lock();
+
+- DSSDBG("Waiting for SYNC to happen...\n");
+- wait = wait_for_completion_timeout(&compl, wait);
+- DSSDBG("Released from SYNC\n");
++ r = dssdev->driver->memory_read(dssdev, buf, size,
++ x, y, w, h);
+
+- if (wait == 0) {
+- DSSERR("timeout waiting mem read sync\n");
+- return -ETIME;
+- }
++ dsi_bus_unlock();
+
+- return ret_size;
++ return r;
+ }
+
+ static void dsi_configure_overlay(struct omap_overlay *ovl)
+@@ -3879,28 +3416,23 @@ int dsi_init(struct platform_device *pdev)
+ spin_lock_init(&dsi.errors_lock);
+ dsi.errors = 0;
+
+- spin_lock_init(&dsi.cmd_lock);
+- dsi.cmd_fifo = kfifo_alloc(
+- DSI_CMD_FIFO_LEN * sizeof(struct dsi_cmd_item),
+- GFP_KERNEL,
+- &dsi.cmd_lock);
+-
+- init_completion(&dsi.cmd_done);
+- atomic_set(&dsi.cmd_fifo_full, 0);
+- atomic_set(&dsi.cmd_pending, 0);
++ /* XXX fail properly */
+
+ init_completion(&dsi.bta_completion);
++ init_completion(&dsi.update_completion);
+
+- dsi.workqueue = create_singlethread_workqueue("dsi");
+- INIT_WORK(&dsi.framedone_work, framedone_worker);
+- INIT_WORK(&dsi.process_work, dsi_process_cmd_fifo);
+- INIT_DELAYED_WORK(&dsi.framedone_timeout_work,
+- framedone_timeout_callback);
++ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
++ if (IS_ERR(dsi.thread)) {
++ DSSERR("cannot create kthread\n");
++ return PTR_ERR(dsi.thread);
++ }
++ init_waitqueue_head(&dsi.waitqueue);
++ spin_lock_init(&dsi.update_lock);
+
+ mutex_init(&dsi.lock);
+ mutex_init(&dsi.bus_lock);
+
+- dsi.target_update_mode = OMAP_DSS_UPDATE_DISABLED;
++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
+
+ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+@@ -3924,20 +3456,19 @@ int dsi_init(struct platform_device *pdev)
+
+ enable_clocks(0);
+
++ wake_up_process(dsi.thread);
++
+ return 0;
+ }
+
+ void dsi_exit(void)
+ {
+- flush_workqueue(dsi.workqueue);
+- destroy_workqueue(dsi.workqueue);
++ kthread_stop(dsi.thread);
+
+ regulator_put(dsi.vdds_dsi_reg);
+
+ iounmap(dsi.base);
+
+- kfifo_free(dsi.cmd_fifo);
+-
+ DSSDBG("omap_dsi_exit\n");
+ }
+
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 1e40830..36f401b 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -185,6 +185,9 @@ void dss_init_overlays(struct platform_device *pdev);
+ void dss_uninit_overlays(struct platform_device *pdev);
+ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
+ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
++#ifdef L4_EXAMPLE
++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
++#endif
+ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
+
+ /* DSS */
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 798867c..eeca3f9 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -635,6 +635,42 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ }
+ }
+
++#ifdef L4_EXAMPLE
++ {
++ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
++ {
++ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
++
++ return 0;
++ }
++
++ struct omap_overlay_manager *mgr;
++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++ BUG_ON(mgr == NULL);
++
++ mgr->name = "l4";
++ mgr->supported_displays =
++ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
++
++ mgr->set_device = &omap_dss_set_device;
++ mgr->unset_device = &omap_dss_unset_device;
++ mgr->apply = &omap_dss_mgr_apply_l4;
++ mgr->set_manager_info = &omap_dss_mgr_set_info;
++ mgr->get_manager_info = &omap_dss_mgr_get_info;
++
++ dss_overlay_setup_l4_manager(mgr);
++
++ omap_dss_add_overlay_manager(mgr);
++
++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
++ &pdev->dev.kobj, "managerl4");
++
++ if (r)
++ DSSERR("failed to create sysfs file\n");
++ }
++#endif
++
+ return 0;
+ }
+
+@@ -674,12 +710,3 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
+ }
+ EXPORT_SYMBOL(omap_dss_get_overlay_manager);
+
+-#ifdef L4_EXAMPLE
+-static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
+-{
+- DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
+-
+- return 0;
+-}
+-#endif
+-
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 31385f3..9f883aa 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -477,6 +477,15 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
+ mgr->overlays = dispc_overlays;
+ }
+
++#ifdef L4_EXAMPLE
++static struct omap_overlay *l4_overlays[1];
++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
++{
++ mgr->num_overlays = 1;
++ mgr->overlays = l4_overlays;
++}
++#endif
++
+ void dss_init_overlays(struct platform_device *pdev)
+ {
+ int i, r;
+@@ -534,6 +543,33 @@ void dss_init_overlays(struct platform_device *pdev)
+
+ dispc_overlays[i] = ovl;
+ }
++
++#ifdef L4_EXAMPLE
++ {
++ struct omap_overlay *ovl;
++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
++
++ BUG_ON(ovl == NULL);
++
++ ovl->name = "l4";
++ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
++
++ ovl->set_manager = &omap_dss_set_manager;
++ ovl->unset_manager = &omap_dss_unset_manager;
++ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
++ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
++
++ omap_dss_add_overlay(ovl);
++
++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
++ &pdev->dev.kobj, "overlayl4");
++
++ if (r)
++ DSSERR("failed to create sysfs file\n");
++
++ l4_overlays[0] = ovl;
++ }
++#endif
+ }
+
+ /* connect overlays to the new device, if not already connected. if force
+@@ -577,35 +613,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
+ }
+ }
+ }
+-#ifdef L4_EXAMPLE
+- /* setup L4 overlay as an example */
+- {
+- static struct omap_overlay ovl = {
+- .name = "l4-ovl",
+- .supported_modes = OMAP_DSS_COLOR_RGB24U,
+- .set_manager = &omap_dss_set_manager,
+- .unset_manager = &omap_dss_unset_manager,
+- .setup_input = &omap_dss_setup_overlay_input,
+- .setup_output = &omap_dss_setup_overlay_output,
+- .enable = &omap_dss_enable_overlay,
+- };
+-
+- static struct omap_overlay_manager mgr = {
+- .name = "l4",
+- .num_overlays = 1,
+- .overlays = &ovl,
+- .set_display = &omap_dss_set_display,
+- .unset_display = &omap_dss_unset_display,
+- .apply = &ovl_mgr_apply_l4,
+- .supported_displays =
+- OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
+- };
+-
+- omap_dss_add_overlay(&ovl);
+- omap_dss_add_overlay_manager(&mgr);
+- omap_dss_set_manager(&ovl, &mgr);
+- }
+-#endif
+ }
+
+ void dss_uninit_overlays(struct platform_device *pdev)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0109-DSS2-let-init_display-return-an-error-code.patch b/recipes/linux/linux-omap-pm/dss2/0109-DSS2-let-init_display-return-an-error-code.patch
new file mode 100644
index 0000000000..5c24815c3f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0109-DSS2-let-init_display-return-an-error-code.patch
@@ -0,0 +1,235 @@
+From 858535f0afbc6d9fa345480408644d4a00584909 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 11:10:14 +0300
+Subject: [PATCH 109/146] DSS2: let init_display return an error code
+
+This is needed by an upcoming patch, in which sdi->init_display can
+fail.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+
+Conflicts:
+
+ drivers/video/omap2/dss/display.c
+ drivers/video/omap2/dss/dpi.c
+ drivers/video/omap2/dss/dsi.c
+ drivers/video/omap2/dss/dss.h
+ drivers/video/omap2/dss/rfbi.c
+ drivers/video/omap2/dss/sdi.c
+ drivers/video/omap2/dss/venc.c
+---
+ drivers/video/omap2/dss/display.c | 15 ++++++++++-----
+ drivers/video/omap2/dss/dpi.c | 4 +++-
+ drivers/video/omap2/dss/dsi.c | 4 +++-
+ drivers/video/omap2/dss/dss.h | 10 +++++-----
+ drivers/video/omap2/dss/rfbi.c | 4 +++-
+ drivers/video/omap2/dss/sdi.c | 4 +++-
+ drivers/video/omap2/dss/venc.c | 4 +++-
+ 7 files changed, 30 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 20fb1ca..1242c39 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -436,32 +436,37 @@ void dss_init_device(struct platform_device *pdev,
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+- dpi_init_display(dssdev);
++ r = dpi_init_display(dssdev);
+ break;
+ #ifdef CONFIG_OMAP2_DSS_RFBI
+ case OMAP_DISPLAY_TYPE_DBI:
+- rfbi_init_display(dssdev);
++ r = rfbi_init_display(dssdev);
+ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_VENC
+ case OMAP_DISPLAY_TYPE_VENC:
+- venc_init_display(dssdev);
++ r = venc_init_display(dssdev);
+ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_SDI
+ case OMAP_DISPLAY_TYPE_SDI:
+- sdi_init_display(dssdev);
++ r = sdi_init_display(dssdev);
+ break;
+ #endif
+ #ifdef CONFIG_OMAP2_DSS_DSI
+ case OMAP_DISPLAY_TYPE_DSI:
+- dsi_init_display(dssdev);
++ r = dsi_init_display(dssdev);
+ break;
+ #endif
+ default:
+ BUG();
+ }
+
++ if (r) {
++ DSSERR("failed to init display %s\n", dssdev->name);
++ return;
++ }
++
+ /* create device sysfs files */
+ i = 0;
+ while ((attr = display_sysfs_attrs[i++]) != NULL) {
+diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
+index d244e54..b6543c8 100644
+--- a/drivers/video/omap2/dss/dpi.c
++++ b/drivers/video/omap2/dss/dpi.c
+@@ -360,7 +360,7 @@ static enum omap_dss_update_mode dpi_display_get_update_mode(
+ OMAP_DSS_UPDATE_DISABLED;
+ }
+
+-void dpi_init_display(struct omap_dss_device *dssdev)
++int dpi_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("init_display\n");
+
+@@ -373,6 +373,8 @@ void dpi_init_display(struct omap_dss_device *dssdev)
+ dssdev->get_timings = dpi_get_timings;
+ dssdev->set_update_mode = dpi_display_set_update_mode;
+ dssdev->get_update_mode = dpi_display_get_update_mode;
++
++ return 0;
+ }
+
+ int dpi_init(void)
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index f98da6f..ffac77b 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -3377,7 +3377,7 @@ static void dsi_configure_overlay(struct omap_overlay *ovl)
+ dispc_setup_plane_fifo(plane, low, high);
+ }
+
+-void dsi_init_display(struct omap_dss_device *dssdev)
++int dsi_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("DSI init\n");
+
+@@ -3407,6 +3407,8 @@ void dsi_init_display(struct omap_dss_device *dssdev)
+
+ dsi.vc[0].dssdev = dssdev;
+ dsi.vc[1].dssdev = dssdev;
++
++ return 0;
+ }
+
+ int dsi_init(struct platform_device *pdev)
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 36f401b..53f0f3d 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -212,7 +212,7 @@ void dss_set_dac_pwrdn_bgz(bool enable);
+ /* SDI */
+ int sdi_init(bool skip_init);
+ void sdi_exit(void);
+-void sdi_init_display(struct omap_dss_device *display);
++int sdi_init_display(struct omap_dss_device *display);
+
+ /* DSI */
+ int dsi_init(struct platform_device *pdev);
+@@ -224,7 +224,7 @@ void dsi_dump_regs(struct seq_file *s);
+ void dsi_save_context(void);
+ void dsi_restore_context(void);
+
+-void dsi_init_display(struct omap_dss_device *display);
++int dsi_init_display(struct omap_dss_device *display);
+ void dsi_irq_handler(void);
+ unsigned long dsi_get_dsi1_pll_rate(void);
+ unsigned long dsi_get_dsi2_pll_rate(void);
+@@ -237,7 +237,7 @@ void dsi_pll_uninit(void);
+ /* DPI */
+ int dpi_init(void);
+ void dpi_exit(void);
+-void dpi_init_display(struct omap_dss_device *dssdev);
++int dpi_init_display(struct omap_dss_device *dssdev);
+
+ /* DISPC */
+ int dispc_init(void);
+@@ -329,7 +329,7 @@ void dispc_draw_partial_planes(struct omap_dss_device *dssdev);
+ int venc_init(struct platform_device *pdev);
+ void venc_exit(void);
+ void venc_dump_regs(struct seq_file *s);
+-void venc_init_display(struct omap_dss_device *display);
++int venc_init_display(struct omap_dss_device *display);
+
+ /* RFBI */
+ int rfbi_init(void);
+@@ -342,6 +342,6 @@ void rfbi_transfer_area(u16 width, u16 height,
+ void (callback)(void *data), void *data);
+ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
+ unsigned long rfbi_get_max_tx_rate(void);
+-void rfbi_init_display(struct omap_dss_device *display);
++int rfbi_init_display(struct omap_dss_device *display);
+
+ #endif
+diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
+index e3cf799..96602ae 100644
+--- a/drivers/video/omap2/dss/rfbi.c
++++ b/drivers/video/omap2/dss/rfbi.c
+@@ -1294,7 +1294,7 @@ static void rfbi_display_disable(struct omap_dss_device *dssdev)
+ omap_dss_stop_device(dssdev);
+ }
+
+-void rfbi_init_display(struct omap_dss_device *dssdev)
++int rfbi_init_display(struct omap_dss_device *dssdev)
+ {
+ dssdev->enable = rfbi_display_enable;
+ dssdev->disable = rfbi_display_disable;
+@@ -1305,4 +1305,6 @@ void rfbi_init_display(struct omap_dss_device *dssdev)
+ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
+
+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ return 0;
+ }
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+index 393fcd5..86b9a56 100644
+--- a/drivers/video/omap2/dss/sdi.c
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -228,7 +228,7 @@ static void sdi_get_timings(struct omap_dss_device *dssdev,
+ *timings = dssdev->panel.timings;
+ }
+
+-void sdi_init_display(struct omap_dss_device *dssdev)
++int sdi_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("SDI init\n");
+
+@@ -239,6 +239,8 @@ void sdi_init_display(struct omap_dss_device *dssdev)
+ dssdev->set_update_mode = sdi_display_set_update_mode;
+ dssdev->get_update_mode = sdi_display_get_update_mode;
+ dssdev->get_timings = sdi_get_timings;
++
++ return 0;
+ }
+
+ int sdi_init(bool skip_init)
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index 740c8c0..d8a83b2 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -711,7 +711,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+ return 0;
+ }
+
+-void venc_init_display(struct omap_dss_device *dssdev)
++int venc_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("init_display\n");
+
+@@ -724,6 +724,8 @@ void venc_init_display(struct omap_dss_device *dssdev)
+ dssdev->check_timings = venc_check_timings;
+ dssdev->get_wss = venc_get_wss;
+ dssdev->set_wss = venc_set_wss;
++
++ return 0;
+ }
+
+ void venc_dump_regs(struct seq_file *s)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch b/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch
new file mode 100644
index 0000000000..5a45e433a0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch
@@ -0,0 +1,209 @@
+From 964c2a99d0b9db59bc716022c7f9f6da580f44d6 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 11:17:15 +0300
+Subject: [PATCH 110/146] DSS2: isolate the SDI pads when SDI is disabled
+
+When SDI is disabled there is still ~1.6mA drain through the VSDI_CSI
+regulator. This seems to be internal to the SDI module, since even
+disconnecting the LCD panel doesn't get rid of the drain. Also
+disabling/resetting the SDI or the DSS module doesn't help. The only
+solution is to configure the SDI pads to safe mode with pull up
+resistors enabled on them when SDI gets disabled.
+
+Bootloader / platform code is still responsible for setting up the
+muxing, so in the driver check if all required pads are in SDI mode
+or all of them are in non-configured state.
+
+Signed-off-by: Imre Deak <imre.deak@nokia.com>
+
+Conflicts:
+
+ arch/arm/plat-omap/include/mach/display.h
+---
+ arch/arm/plat-omap/include/mach/display.h | 2 +
+ drivers/video/omap2/dss/sdi.c | 110 ++++++++++++++++++++++++++++-
+ 2 files changed, 111 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 3d8ed69..0695497 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -344,6 +344,8 @@ struct omap_dss_device {
+
+ struct {
+ u8 datapairs;
++ unsigned pad_off_pe : 1; /* pull pads if disabled */
++ unsigned pad_off_pu : 1; /* pull up */
+ } sdi;
+
+ struct {
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+index 86b9a56..c484e0c 100644
+--- a/drivers/video/omap2/dss/sdi.c
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -23,17 +23,120 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
++#include <linux/io.h>
+
+ #include <mach/board.h>
+ #include <mach/display.h>
+ #include "dss.h"
+
++#define CONTROL_PADCONF_BASE 0x48002000
++
++#define OMAP_SDI_PAD_DIS(pe,pu) ((7 << 0) | /* MODE 7 = safe */ \
++ (((pe) ? 1 : 0) << 3) | /* PULL_ENA */ \
++ (((pu) ? 1 : 0) << 4) | /* PULL_UP */ \
++ (1 << 8)) /* INPUT_EN */
++
++#define OMAP_SDI_PAD_EN (1 << 0) /* MODE 1 = SDI_xx */
++
++#define OMAP_SDI_PAD_MASK OMAP_SDI_PAD_DIS(1, 1)
+
+ static struct {
+ bool skip_init;
+ bool update_enabled;
+ } sdi;
+
++/* CONTROL_PADCONF_DSS_DATAXX */
++const u16 sdi_pads[] =
++{
++ 0x0f0, /* 10[ 7..0]:SDI_DAT1N */
++ 0x0f2, /* 10[15..0]:SDI_DAT1P */
++ 0x0f4, /* 12[ 7..0]:SDI_DAT2N */
++ 0x0f6, /* 12[15..0]:SDI_DAT2P */
++ 0x0f8, /* 14[ 7..0]:SDI_DAT3N */
++ 0x0fa, /* 14[15..0]:SDI_DAT3P */
++ 0x108, /* 22[ 7..0]:SDI_CLKN */
++ 0x10a, /* 22[15..0]:SDI_CLKP */
++};
++
++/*
++ * Check if bootloader / platform code has configured the SDI pads properly.
++ * This means it either configured all required pads for SDI mode, or that it
++ * left all the required pads unconfigured.
++ */
++static int sdi_pad_init(struct omap_dss_device *dssdev)
++{
++ unsigned req_map;
++ bool configured = false;
++ bool unconfigured = false;
++ int data_pairs;
++ int i;
++
++ data_pairs = dssdev->phy.sdi.datapairs;
++ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
++ req_map |= 3 << 6; /* clk lane */
++ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
++ u32 reg;
++ u32 val;
++
++ if (!((1 << i) & req_map))
++ /* Ignore unneded pads. */
++ continue;
++ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
++ val = omap_readw(reg);
++ switch (val & 0x07) { /* pad mode */
++ case 1:
++ if (unconfigured)
++ break;
++ /* Is the pull configuration ok for SDI mode? */
++ if ((val & OMAP_SDI_PAD_MASK) != OMAP_SDI_PAD_EN)
++ break;
++ configured = true;
++ break;
++ case 0:
++ case 7:
++ if (configured)
++ break;
++ unconfigured = true;
++ break;
++ default:
++ break;
++ }
++ }
++ if (i != ARRAY_SIZE(sdi_pads)) {
++ DSSERR("SDI: invalid pad configuration\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++static void sdi_pad_config(struct omap_dss_device *dssdev, bool enable)
++{
++ int data_pairs;
++ bool pad_off_pe, pad_off_pu;
++ unsigned req_map;
++ int i;
++
++ data_pairs = dssdev->phy.sdi.datapairs;
++ pad_off_pe = dssdev->phy.sdi.pad_off_pe;
++ pad_off_pu = dssdev->phy.sdi.pad_off_pu;
++ req_map = (1 << (data_pairs * 2)) - 1; /* data lanes */
++ req_map |= 3 << 6; /* clk lane */
++ for (i = 0; i < ARRAY_SIZE(sdi_pads); i++) {
++ u32 reg;
++ u16 val;
++
++ if (!((1 << i) & req_map))
++ continue;
++ if (enable)
++ val = OMAP_SDI_PAD_EN;
++ else
++ val = OMAP_SDI_PAD_DIS(pad_off_pe, pad_off_pu);
++ reg = CONTROL_PADCONF_BASE + sdi_pads[i];
++ omap_writew(val, reg);
++ }
++}
++
+ static void sdi_basic_init(void)
+ {
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+@@ -64,6 +167,8 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
+ goto err1;
+ }
+
++ sdi_pad_config(dssdev, 1);
++
+ /* In case of skip_init sdi_init has already enabled the clocks */
+ if (!sdi.skip_init)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+@@ -153,6 +258,7 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+@@ -172,6 +278,7 @@ static int sdi_display_suspend(struct omap_dss_device *dssdev)
+ dss_sdi_disable();
+
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ sdi_pad_config(dssdev, 0);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+@@ -183,6 +290,7 @@ static int sdi_display_resume(struct omap_dss_device *dssdev)
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ return -EINVAL;
+
++ sdi_pad_config(dssdev, 1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+ dss_sdi_enable();
+@@ -240,7 +348,7 @@ int sdi_init_display(struct omap_dss_device *dssdev)
+ dssdev->get_update_mode = sdi_display_get_update_mode;
+ dssdev->get_timings = sdi_get_timings;
+
+- return 0;
++ return sdi_pad_init(dssdev);
+ }
+
+ int sdi_init(bool skip_init)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0111-DSS2-Fix-bottom-field-initial-starting-line.patch b/recipes/linux/linux-omap-pm/dss2/0111-DSS2-Fix-bottom-field-initial-starting-line.patch
new file mode 100644
index 0000000000..a7970dca21
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0111-DSS2-Fix-bottom-field-initial-starting-line.patch
@@ -0,0 +1,210 @@
+From 740a3556ebdb8b046b91287a48a6c0fd84fdc1b2 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@nokia.com>
+Date: Mon, 1 Jun 2009 17:06:26 +0200
+Subject: [PATCH 111/146] DSS2: Fix bottom field initial starting line
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When downscaling the bottom field offset may be several source lines.
+Unfortunately the registers for the initial accumulator value will only
+hold the fractional part of of that offset so the integer part must be
+added to the bottom field base address. The TV-out quality is
+significantly improved as a result. Additionally this fixes the bottom
+field offset with DMA rotation and mirroring enabled as it was
+previously miscalculated.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 69 +++++++++++++++++++++++++-------------
+ 1 files changed, 45 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 762a0f1..2463bab 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1100,7 +1100,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
+ */
+ if (ilace && !fieldmode) {
+ accu1 = 0;
+- accu0 = fir_vinc / 2;
++ accu0 = (fir_vinc / 2) & 0x3ff;
+ if (accu0 >= 1024/2) {
+ accu1 = 1024/2;
+ accu0 -= accu1;
+@@ -1178,6 +1178,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+ {
+@@ -1227,8 +1228,8 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ case 1:
+ case 3:
+ *offset1 = 0;
+- if (fieldmode)
+- *offset0 = screen_width * ps;
++ if (field_offset)
++ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+
+@@ -1249,8 +1250,8 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ case 5:
+ case 7:
+ *offset1 = 0;
+- if (fieldmode)
+- *offset0 = screen_width * ps;
++ if (field_offset)
++ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+ *row_inc = pixinc(1 - (screen_width + width) -
+@@ -1268,6 +1269,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
++ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+ {
+@@ -1320,10 +1322,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ switch (rotation + mirror * 4) {
+ case 0:
+ *offset1 = 0;
+- if (fieldmode)
+- *offset0 = screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+- *offset0 = 0;
++ *offset0 = *offset1;
+ *row_inc = pixinc(1 + (screen_width - fbw) +
+ (fieldmode ? screen_width : 0),
+ ps);
+@@ -1331,8 +1333,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+ case 1:
+ *offset1 = screen_width * (fbh - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 + ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
+@@ -1341,8 +1343,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+ case 2:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 - screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-1 -
+@@ -1353,8 +1355,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ break;
+ case 3:
+ *offset1 = (fbw - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 - ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
+@@ -1365,8 +1367,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ /* mirroring */
+ case 0 + 4:
+ *offset1 = (fbw - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 + screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * 2 - 1 +
+@@ -1377,8 +1379,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+
+ case 1 + 4:
+ *offset1 = 0;
+- if (fieldmode)
+- *offset0 = *offset1 + screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
+@@ -1389,8 +1391,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+
+ case 2 + 4:
+ *offset1 = screen_width * (fbh - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 + screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(1 - screen_width * 2 -
+@@ -1401,8 +1403,8 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+
+ case 3 + 4:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+- if (fieldmode)
+- *offset0 = *offset1 + screen_width * ps;
++ if (field_offset)
++ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
+@@ -1498,6 +1500,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ s32 row_inc;
+ s32 pix_inc;
+ u16 frame_height = height;
++ unsigned int field_offset = 0;
+
+ if (paddr == 0)
+ return -EINVAL;
+@@ -1596,15 +1599,33 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ return -EINVAL;
+ }
+
++ if (ilace && !fieldmode) {
++ /*
++ * when downscaling the bottom field may have to start several
++ * source lines below the top field. Unfortunately ACCUI
++ * registers will only hold the fractional part of the offset
++ * so the integer part must be added to the base address of the
++ * bottom field.
++ */
++ if (!height || height == out_height)
++ field_offset = 0;
++ else
++ field_offset = height / out_height / 2;
++ }
++
++ /* Fields are independent but interleaved in memory. */
++ if (fieldmode)
++ field_offset = 1;
++
+ if (rotation_type == OMAP_DSS_ROT_DMA)
+ calc_dma_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+- fieldmode,
++ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+ else
+ calc_vrfb_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+- fieldmode,
++ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+
+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0112-DSS2-Correctly-determine-if-an-interlaced-display-i.patch b/recipes/linux/linux-omap-pm/dss2/0112-DSS2-Correctly-determine-if-an-interlaced-display-i.patch
new file mode 100644
index 0000000000..0a3a1be555
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0112-DSS2-Correctly-determine-if-an-interlaced-display-i.patch
@@ -0,0 +1,50 @@
+From a9a5c0bd138aaf83b4eeff0b2923abdb255be55c Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 11:22:24 +0300
+Subject: [PATCH 112/146] DSS2: Correctly determine if an interlaced display is used
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+When applying the settings to all the overlays ilace is initialzed to 0
+in the beginning and then changed to 1 when the first overlay directed
+to an interlaced display is found. If there are more overlays after that
+one which are not directed to an interlaced display the code would still
+pass ilace=1 to the the dispc code which would halve the output height of
+the overlay. Fix the problem by correctly setting ilace for each overlay.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+
+Conflicts:
+
+ drivers/video/omap2/dss/manager.c
+---
+ drivers/video/omap2/dss/manager.c | 5 ++---
+ 1 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index eeca3f9..f6df4d6 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -412,7 +412,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ enum omap_dss_update_mode mode;
+ struct omap_dss_device *dssdev;
+ struct omap_overlay *ovl;
+- bool ilace = 0;
++ bool ilace;
+ int outw, outh;
+ int r;
+ int num_planes_enabled = 0;
+@@ -452,8 +452,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+ mode != OMAP_DSS_UPDATE_AUTO)
+ continue;
+
+- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+- ilace = 1;
++ ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
+
+ if (ovl->info.out_width == 0)
+ outw = ovl->info.width;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0113-DSS2-Fix-omapfb-framebuffer-name.patch b/recipes/linux/linux-omap-pm/dss2/0113-DSS2-Fix-omapfb-framebuffer-name.patch
new file mode 100644
index 0000000000..020e065a76
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0113-DSS2-Fix-omapfb-framebuffer-name.patch
@@ -0,0 +1,115 @@
+From e9115293f6b4c7f737a5eeba34c2769dfd030e5d Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 11:25:19 +0300
+Subject: [PATCH 113/146] DSS2: Fix omapfb framebuffer name
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+After clearing the fix and var screeninfos fix.id should be reset to
+the proper value. Move the relevant memset() and strncpy() calls into
+a helper function which does the right thing.
+
+Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
+
+Conflicts:
+
+ drivers/video/omap2/omapfb/omapfb-main.c
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 30 +++++++++++++++---------------
+ 1 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index b4ac9ec..dc9c06c 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1171,6 +1171,13 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
+ rg->size = 0;
+ }
+
++static void clear_fb_info(struct fb_info *fbi)
++{
++ memset(&fbi->var, 0, sizeof(fbi->var));
++ memset(&fbi->fix, 0, sizeof(fbi->fix));
++ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
++}
++
+ static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
+ {
+ int i;
+@@ -1180,8 +1187,7 @@ static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
+ for (i = 0; i < fbdev->num_fbs; i++) {
+ struct fb_info *fbi = fbdev->fbs[i];
+ omapfb_free_fbmem(fbi);
+- memset(&fbi->fix, 0, sizeof(fbi->fix));
+- memset(&fbi->var, 0, sizeof(fbi->var));
++ clear_fb_info(fbi);
+ }
+
+ return 0;
+@@ -1509,8 +1515,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+ omapfb_free_fbmem(fbi);
+
+ if (size == 0) {
+- memset(&fbi->fix, 0, sizeof(fbi->fix));
+- memset(&fbi->var, 0, sizeof(fbi->var));
++ clear_fb_info(fbi);
+ return 0;
+ }
+
+@@ -1520,10 +1525,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+ if (old_size)
+ omapfb_alloc_fbmem(fbi, old_size, old_paddr);
+
+- if (rg->size == 0) {
+- memset(&fbi->fix, 0, sizeof(fbi->fix));
+- memset(&fbi->var, 0, sizeof(fbi->var));
+- }
++ if (rg->size == 0)
++ clear_fb_info(fbi);
+
+ return r;
+ }
+@@ -1556,8 +1559,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+ return 0;
+ err:
+ omapfb_free_fbmem(fbi);
+- memset(&fbi->fix, 0, sizeof(fbi->fix));
+- memset(&fbi->var, 0, sizeof(fbi->var));
++ clear_fb_info(fbi);
+ return r;
+ }
+
+@@ -1565,7 +1567,6 @@ err:
+ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ {
+ struct fb_var_screeninfo *var = &fbi->var;
+- struct fb_fix_screeninfo *fix = &fbi->fix;
+ struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ int r = 0;
+@@ -1574,11 +1575,8 @@ int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->pseudo_palette = fbdev->pseudo_palette;
+
+- strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+-
+ if (ofbi->region.size == 0) {
+- memset(&fbi->fix, 0, sizeof(fbi->fix));
+- memset(&fbi->var, 0, sizeof(fbi->var));
++ clear_fb_info(fbi);
+ return 0;
+ }
+
+@@ -1728,6 +1726,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+ return -ENOMEM;
+ }
+
++ clear_fb_info(fbi);
++
+ fbdev->fbs[i] = fbi;
+
+ ofbi = FB2OFB(fbi);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0114-DSS2-Overo-update-defconfig-to-lighter-one.patch b/recipes/linux/linux-omap-pm/dss2/0114-DSS2-Overo-update-defconfig-to-lighter-one.patch
new file mode 100644
index 0000000000..dcd293c407
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0114-DSS2-Overo-update-defconfig-to-lighter-one.patch
@@ -0,0 +1,1217 @@
+From acd5985012f2e205a2613d29487ba347a99c5393 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 21:57:15 +0300
+Subject: [PATCH 114/146] DSS2: Overo: update defconfig to lighter one
+
+---
+ arch/arm/configs/dss_overo_defconfig | 598 ++++++++++------------------------
+ 1 files changed, 174 insertions(+), 424 deletions(-)
+
+diff --git a/arch/arm/configs/dss_overo_defconfig b/arch/arm/configs/dss_overo_defconfig
+index 755a1b6..38a452c 100644
+--- a/arch/arm/configs/dss_overo_defconfig
++++ b/arch/arm/configs/dss_overo_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.29-omap1
+-# Thu Apr 2 11:30:57 2009
++# Linux kernel version: 2.6.31-rc1-omap1
++# Thu Jul 2 17:24:24 2009
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
+ CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_STACKTRACE_SUPPORT=y
+ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+@@ -18,23 +17,23 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+ CONFIG_OPROFILE_ARMV7=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
+
+ #
+ # General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+ CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_LOCALVERSION_AUTO is not set
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_SYSVIPC_SYSCTL=y
+@@ -67,6 +66,9 @@ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_NAMESPACES is not set
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+ CONFIG_ANON_INODES=y
+@@ -88,21 +90,32 @@ CONFIG_TIMERFD=y
+ CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+ CONFIG_AIO=y
++
++#
++# Performance Counters
++#
+ CONFIG_VM_EVENT_COUNTERS=y
+ CONFIG_SLUB_DEBUG=y
++# CONFIG_STRIP_ASM_SYMS is not set
+ # CONFIG_COMPAT_BRK is not set
+ # CONFIG_SLAB is not set
+ CONFIG_SLUB=y
+ # CONFIG_SLOB is not set
+ CONFIG_PROFILING=y
+ CONFIG_TRACEPOINTS=y
+-# CONFIG_MARKERS is not set
++CONFIG_MARKERS=y
+ CONFIG_OPROFILE=y
+ CONFIG_HAVE_OPROFILE=y
+ # CONFIG_KPROBES is not set
+ CONFIG_HAVE_KPROBES=y
+ CONFIG_HAVE_KRETPROBES=y
+ CONFIG_HAVE_CLK=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++# CONFIG_SLOW_WORK is not set
+ CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -114,8 +127,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_BLK_DEV_INTEGRITY is not set
+
+@@ -142,12 +154,14 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_VERSATILE is not set
+ # CONFIG_ARCH_AT91 is not set
+ # CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
+ # CONFIG_ARCH_EBSA110 is not set
+ # CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_STMP3XXX is not set
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+ # CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+@@ -156,24 +170,25 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
+ # CONFIG_ARCH_KIRKWOOD is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+ # CONFIG_ARCH_LOKI is not set
+ # CONFIG_ARCH_MV78XX0 is not set
+-# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_S3C64XX is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
+ # CONFIG_ARCH_DAVINCI is not set
+ CONFIG_ARCH_OMAP=y
+-# CONFIG_ARCH_MSM is not set
+-# CONFIG_ARCH_W90X900 is not set
+
+ #
+ # TI OMAP Implementations
+@@ -182,26 +197,20 @@ CONFIG_ARCH_OMAP_OTG=y
+ # CONFIG_ARCH_OMAP1 is not set
+ # CONFIG_ARCH_OMAP2 is not set
+ CONFIG_ARCH_OMAP3=y
++# CONFIG_ARCH_OMAP4 is not set
+
+ #
+ # OMAP Feature Selections
+ #
+ # CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+ # CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+-CONFIG_OMAP_SMARTREFLEX=y
+-# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+ # CONFIG_OMAP_RESET_CLOCKS is not set
+-CONFIG_OMAP_BOOT_TAG=y
+-CONFIG_OMAP_BOOT_REASON=y
+-# CONFIG_OMAP_COMPONENT_VERSION is not set
+-# CONFIG_OMAP_GPIO_SWITCH is not set
+ # CONFIG_OMAP_MUX is not set
+ CONFIG_OMAP_MCBSP=y
+ # CONFIG_OMAP_MBOX_FWK is not set
+ # CONFIG_OMAP_MPU_TIMER is not set
+ CONFIG_OMAP_32K_TIMER=y
+ CONFIG_OMAP_32K_TIMER_HZ=128
+-CONFIG_OMAP_TICK_GPTIMER=1
+ CONFIG_OMAP_DM_TIMER=y
+ # CONFIG_OMAP_LL_DEBUG_UART1 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+@@ -219,6 +228,7 @@ CONFIG_ARCH_OMAP3430=y
+ # CONFIG_MACH_OMAP3_BEAGLE is not set
+ CONFIG_MACH_OVERO=y
+ # CONFIG_MACH_OMAP3_PANDORA is not set
++# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+ #
+ # Processor Type
+@@ -246,7 +256,10 @@ CONFIG_ARM_THUMBEE=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_BPREDICT_DISABLE is not set
+ CONFIG_HAS_TLS_REG=y
+-# CONFIG_OUTER_CACHE is not set
++# CONFIG_ARM_ERRATA_430973 is not set
++# CONFIG_ARM_ERRATA_458693 is not set
++# CONFIG_ARM_ERRATA_460075 is not set
++CONFIG_COMMON_CLKDEV=y
+
+ #
+ # Bus support
+@@ -266,13 +279,13 @@ CONFIG_VMSPLIT_3G=y
+ # CONFIG_VMSPLIT_2G is not set
+ # CONFIG_VMSPLIT_1G is not set
+ CONFIG_PAGE_OFFSET=0xC0000000
+-# CONFIG_PREEMPT is not set
++CONFIG_PREEMPT=y
+ CONFIG_HZ=128
+ CONFIG_AEABI=y
+ # CONFIG_OABI_COMPAT is not set
+-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+ # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+ # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++# CONFIG_HIGHMEM is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+@@ -284,9 +297,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_PHYS_ADDR_T_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=0
+ CONFIG_VIRT_TO_BUS=y
+-CONFIG_UNEVICTABLE_LRU=y
++CONFIG_HAVE_MLOCK=y
++CONFIG_HAVE_MLOCKED_PAGE_BIT=y
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+ CONFIG_LEDS=y
+ CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+ #
+ # Boot options
+@@ -352,7 +368,6 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-CONFIG_COMPAT_NET_DEV_OPS=y
+ CONFIG_PACKET=y
+ CONFIG_PACKET_MMAP=y
+ CONFIG_UNIX=y
+@@ -379,10 +394,10 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=m
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
+ # CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+@@ -390,25 +405,7 @@ CONFIG_INET_TCP_DIAG=y
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_TCP_MD5SIG is not set
+-CONFIG_IPV6=m
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+-CONFIG_INET6_XFRM_MODE_TUNNEL=m
+-CONFIG_INET6_XFRM_MODE_BEET=m
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=m
+-CONFIG_IPV6_NDISC_NODETYPE=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_IPV6_MROUTE is not set
++# CONFIG_IPV6 is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ # CONFIG_IP_DCCP is not set
+@@ -426,6 +423,8 @@ CONFIG_IPV6_NDISC_NODETYPE=y
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
++# CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_DCB is not set
+
+@@ -433,58 +432,13 @@ CONFIG_IPV6_NDISC_NODETYPE=y
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
++# CONFIG_NET_DROP_MONITOR is not set
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+-CONFIG_BT=y
+-CONFIG_BT_L2CAP=y
+-CONFIG_BT_SCO=y
+-CONFIG_BT_RFCOMM=y
+-CONFIG_BT_RFCOMM_TTY=y
+-CONFIG_BT_BNEP=y
+-CONFIG_BT_BNEP_MC_FILTER=y
+-CONFIG_BT_BNEP_PROTO_FILTER=y
+-CONFIG_BT_HIDP=y
+-
+-#
+-# Bluetooth device drivers
+-#
+-# CONFIG_BT_HCIBTSDIO is not set
+-CONFIG_BT_HCIUART=y
+-CONFIG_BT_HCIUART_H4=y
+-CONFIG_BT_HCIUART_BCSP=y
+-# CONFIG_BT_HCIUART_LL is not set
+-# CONFIG_BT_HCIBRF6150 is not set
+-# CONFIG_BT_HCIH4P is not set
+-# CONFIG_BT_HCIVHCI is not set
++# CONFIG_BT is not set
+ # CONFIG_AF_RXRPC is not set
+-# CONFIG_PHONET is not set
+-CONFIG_WIRELESS=y
+-CONFIG_CFG80211=y
+-# CONFIG_CFG80211_REG_DEBUG is not set
+-CONFIG_NL80211=y
+-CONFIG_WIRELESS_OLD_REGULATORY=y
+-CONFIG_WIRELESS_EXT=y
+-CONFIG_WIRELESS_EXT_SYSFS=y
+-CONFIG_LIB80211=y
+-CONFIG_LIB80211_CRYPT_WEP=m
+-CONFIG_LIB80211_CRYPT_CCMP=m
+-CONFIG_LIB80211_CRYPT_TKIP=m
+-# CONFIG_LIB80211_DEBUG is not set
+-CONFIG_MAC80211=y
+-
+-#
+-# Rate control algorithm selection
+-#
+-CONFIG_MAC80211_RC_PID=y
+-CONFIG_MAC80211_RC_MINSTREL=y
+-CONFIG_MAC80211_RC_DEFAULT_PID=y
+-# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+-CONFIG_MAC80211_RC_DEFAULT="pid"
+-# CONFIG_MAC80211_MESH is not set
+-CONFIG_MAC80211_LEDS=y
+-# CONFIG_MAC80211_DEBUGFS is not set
+-# CONFIG_MAC80211_DEBUG_MENU is not set
++# CONFIG_WIRELESS is not set
+ # CONFIG_WIMAX is not set
+ # CONFIG_RFKILL is not set
+ # CONFIG_NET_9P is not set
+@@ -595,20 +549,20 @@ CONFIG_MTD_NAND_IDS=y
+ CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+-CONFIG_BLK_DEV_CRYPTOLOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=16384
+ # CONFIG_BLK_DEV_XIP is not set
+-CONFIG_CDROM_PKTCDVD=m
+-CONFIG_CDROM_PKTCDVD_BUFFERS=8
+-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
++# CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
+ CONFIG_MISC_DEVICES=y
+ # CONFIG_ICS932S401 is not set
+ # CONFIG_OMAP_STI is not set
+ # CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_ISL29003 is not set
+ # CONFIG_C2PORT is not set
+
+ #
+@@ -617,6 +571,7 @@ CONFIG_MISC_DEVICES=y
+ # CONFIG_EEPROM_AT24 is not set
+ # CONFIG_EEPROM_AT25 is not set
+ # CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_MAX6875 is not set
+ CONFIG_EEPROM_93CX6=m
+ CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+@@ -624,7 +579,7 @@ CONFIG_HAVE_IDE=y
+ #
+ # SCSI device support
+ #
+-CONFIG_RAID_ATTRS=m
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+@@ -638,12 +593,8 @@ CONFIG_BLK_DEV_SD=y
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SG is not set
+ # CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+@@ -661,34 +612,18 @@ CONFIG_SCSI_WAIT_SCAN=m
+ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
+ # CONFIG_SCSI_DEBUG is not set
+ # CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
+ # CONFIG_ATA is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=m
+-CONFIG_MD_LINEAR=m
+-CONFIG_MD_RAID0=m
+-CONFIG_MD_RAID1=m
+-CONFIG_MD_RAID10=m
+-CONFIG_MD_RAID456=m
+-CONFIG_MD_RAID5_RESHAPE=y
+-CONFIG_MD_MULTIPATH=m
+-CONFIG_MD_FAULTY=m
+-CONFIG_BLK_DEV_DM=m
+-# CONFIG_DM_DEBUG is not set
+-CONFIG_DM_CRYPT=m
+-CONFIG_DM_SNAPSHOT=m
+-CONFIG_DM_MIRROR=m
+-CONFIG_DM_ZERO=m
+-CONFIG_DM_MULTIPATH=m
+-CONFIG_DM_DELAY=m
+-# CONFIG_DM_UEVENT is not set
++# CONFIG_MD is not set
+ CONFIG_NETDEVICES=y
+-CONFIG_DUMMY=m
++# CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
+ # CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+-CONFIG_TUN=m
++# CONFIG_TUN is not set
+ # CONFIG_VETH is not set
+ # CONFIG_NET_ETHERNET is not set
+ # CONFIG_NETDEV_1000 is not set
+@@ -698,37 +633,14 @@ CONFIG_TUN=m
+ # Wireless LAN
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+-CONFIG_WLAN_80211=y
+-CONFIG_LIBERTAS=y
+-CONFIG_LIBERTAS_SDIO=y
+-CONFIG_LIBERTAS_DEBUG=y
+-# CONFIG_LIBERTAS_THINFIRM is not set
+-# CONFIG_MAC80211_HWSIM is not set
+-CONFIG_P54_COMMON=m
+-# CONFIG_IWLWIFI_LEDS is not set
+-CONFIG_HOSTAP=m
+-CONFIG_HOSTAP_FIRMWARE=y
+-CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+-# CONFIG_B43 is not set
+-# CONFIG_B43LEGACY is not set
+-# CONFIG_RT2X00 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+ # Enable WiMAX (Networking options) to see the WiMAX drivers
+ #
+ # CONFIG_WAN is not set
+-CONFIG_PPP=m
+-# CONFIG_PPP_MULTILINK is not set
+-# CONFIG_PPP_FILTER is not set
+-CONFIG_PPP_ASYNC=m
+-CONFIG_PPP_SYNC_TTY=m
+-CONFIG_PPP_DEFLATE=m
+-CONFIG_PPP_BSDCOMP=m
+-CONFIG_PPP_MPPE=m
+-CONFIG_PPPOE=m
+-# CONFIG_PPPOL2TP is not set
++# CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+-CONFIG_SLHC=m
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+@@ -762,7 +674,6 @@ CONFIG_INPUT_KEYBOARD=y
+ # CONFIG_KEYBOARD_XTKBD is not set
+ # CONFIG_KEYBOARD_NEWTON is not set
+ # CONFIG_KEYBOARD_STOWAWAY is not set
+-# CONFIG_KEYBOARD_TWL4030 is not set
+ # CONFIG_KEYBOARD_LM8323 is not set
+ # CONFIG_KEYBOARD_GPIO is not set
+ CONFIG_INPUT_MOUSE=y
+@@ -778,6 +689,7 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y
+ # CONFIG_MOUSE_BCM5974 is not set
+ # CONFIG_MOUSE_VSXXXAA is not set
+ # CONFIG_MOUSE_GPIO is not set
++# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+ # CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+@@ -819,6 +731,7 @@ CONFIG_SERIAL_8250_RSA=y
+ #
+ # Non-8250 serial port support
+ #
++# CONFIG_SERIAL_MAX3100 is not set
+ CONFIG_SERIAL_CORE=y
+ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+@@ -826,6 +739,7 @@ CONFIG_UNIX98_PTYS=y
+ # CONFIG_LEGACY_PTYS is not set
+ # CONFIG_IPMI_HANDLER is not set
+ CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
+ # CONFIG_TCG_TPM is not set
+@@ -841,6 +755,7 @@ CONFIG_I2C_HELPER_AUTO=y
+ #
+ # I2C system bus drivers (mostly embedded / system-on-chip)
+ #
++# CONFIG_I2C_DESIGNWARE is not set
+ # CONFIG_I2C_GPIO is not set
+ # CONFIG_I2C_OCORES is not set
+ CONFIG_I2C_OMAP=y
+@@ -865,12 +780,7 @@ CONFIG_I2C_OMAP=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-CONFIG_TWL4030_MADC=m
+-CONFIG_TWL4030_POWEROFF=y
+-# CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_SENSORS_TSL2563 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+@@ -889,8 +799,6 @@ CONFIG_SPI_OMAP24XX=y
+ #
+ # SPI Protocol Masters
+ #
+-# CONFIG_SPI_TSC210X is not set
+-# CONFIG_SPI_TSC2301 is not set
+ # CONFIG_SPI_SPIDEV is not set
+ # CONFIG_SPI_TLE62X0 is not set
+ CONFIG_ARCH_REQUIRE_GPIOLIB=y
+@@ -920,12 +828,7 @@ CONFIG_GPIO_TWL4030=y
+ # CONFIG_GPIO_MAX7301 is not set
+ # CONFIG_GPIO_MCP23S08 is not set
+ # CONFIG_W1 is not set
+-CONFIG_POWER_SUPPLY=m
+-# CONFIG_POWER_SUPPLY_DEBUG is not set
+-# CONFIG_PDA_POWER is not set
+-# CONFIG_BATTERY_DS2760 is not set
+-# CONFIG_TWL4030_BCI_BATTERY is not set
+-# CONFIG_BATTERY_BQ27x00 is not set
++# CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
+ # CONFIG_SENSORS_AD7414 is not set
+@@ -946,6 +849,7 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_F71805F is not set
+ # CONFIG_SENSORS_F71882FG is not set
+ # CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_G760A is not set
+ # CONFIG_SENSORS_GL518SM is not set
+ # CONFIG_SENSORS_GL520SM is not set
+ # CONFIG_SENSORS_IT87 is not set
+@@ -961,18 +865,23 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_LM90 is not set
+ # CONFIG_SENSORS_LM92 is not set
+ # CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_LTC4215 is not set
+ # CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_LM95241 is not set
+ # CONFIG_SENSORS_MAX1111 is not set
+ # CONFIG_SENSORS_MAX1619 is not set
+ # CONFIG_SENSORS_MAX6650 is not set
+ # CONFIG_SENSORS_PC87360 is not set
+ # CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_SHT15 is not set
+ # CONFIG_SENSORS_DME1737 is not set
+ # CONFIG_SENSORS_SMSC47M1 is not set
+ # CONFIG_SENSORS_SMSC47M192 is not set
+ # CONFIG_SENSORS_SMSC47B397 is not set
+ # CONFIG_SENSORS_ADS7828 is not set
+ # CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_TMP401 is not set
+ # CONFIG_SENSORS_VT1211 is not set
+ # CONFIG_SENSORS_W83781D is not set
+ # CONFIG_SENSORS_W83791D is not set
+@@ -982,6 +891,7 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_W83L786NG is not set
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_LIS3_SPI is not set
+ # CONFIG_SENSORS_TSC210X is not set
+ CONFIG_SENSORS_OMAP34XX=y
+ # CONFIG_HWMON_DEBUG_CHIP is not set
+@@ -995,6 +905,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
+ #
+ # CONFIG_SOFT_WATCHDOG is not set
+ CONFIG_OMAP_WATCHDOG=y
++# CONFIG_TWL4030_WATCHDOG is not set
+ CONFIG_SSB_POSSIBLE=y
+
+ #
+@@ -1012,7 +923,6 @@ CONFIG_SSB_POSSIBLE=y
+ # CONFIG_HTC_PASIC3 is not set
+ # CONFIG_TPS65010 is not set
+ CONFIG_TWL4030_CORE=y
+-# CONFIG_TWL4030_POWER is not set
+ # CONFIG_MFD_TMIO is not set
+ # CONFIG_MFD_T7L66XB is not set
+ # CONFIG_MFD_TC6387XB is not set
+@@ -1021,154 +931,9 @@ CONFIG_TWL4030_CORE=y
+ # CONFIG_MFD_WM8400 is not set
+ # CONFIG_MFD_WM8350_I2C is not set
+ # CONFIG_MFD_PCF50633 is not set
+-
+-#
+-# Multimedia devices
+-#
+-
+-#
+-# Multimedia core support
+-#
+-CONFIG_VIDEO_DEV=m
+-CONFIG_VIDEO_V4L2_COMMON=m
+-CONFIG_VIDEO_ALLOW_V4L1=y
+-CONFIG_VIDEO_V4L1_COMPAT=y
+-CONFIG_DVB_CORE=m
+-CONFIG_VIDEO_MEDIA=m
+-
+-#
+-# Multimedia drivers
+-#
+-CONFIG_MEDIA_ATTACH=y
+-CONFIG_MEDIA_TUNER=m
+-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+-CONFIG_MEDIA_TUNER_SIMPLE=m
+-CONFIG_MEDIA_TUNER_TDA8290=m
+-CONFIG_MEDIA_TUNER_TDA9887=m
+-CONFIG_MEDIA_TUNER_TEA5761=m
+-CONFIG_MEDIA_TUNER_TEA5767=m
+-CONFIG_MEDIA_TUNER_MT20XX=m
+-CONFIG_MEDIA_TUNER_XC2028=m
+-CONFIG_MEDIA_TUNER_XC5000=m
+-CONFIG_VIDEO_V4L2=m
+-CONFIG_VIDEO_V4L1=m
+-CONFIG_VIDEO_CAPTURE_DRIVERS=y
+-# CONFIG_VIDEO_ADV_DEBUG is not set
+-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+-# CONFIG_VIDEO_VIVI is not set
+-# CONFIG_VIDEO_CPIA is not set
+-# CONFIG_VIDEO_SAA5246A is not set
+-# CONFIG_VIDEO_SAA5249 is not set
+-# CONFIG_SOC_CAMERA is not set
+-CONFIG_RADIO_ADAPTERS=y
+-# CONFIG_RADIO_TEA5764 is not set
+-# CONFIG_DVB_DYNAMIC_MINORS is not set
+-CONFIG_DVB_CAPTURE_DRIVERS=y
+-# CONFIG_TTPCI_EEPROM is not set
+-# CONFIG_DVB_B2C2_FLEXCOP is not set
+-
+-#
+-# Supported DVB Frontends
+-#
+-
+-#
+-# Customise DVB Frontends
+-#
+-# CONFIG_DVB_FE_CUSTOMISE is not set
+-
+-#
+-# Multistandard (satellite) frontends
+-#
+-# CONFIG_DVB_STB0899 is not set
+-# CONFIG_DVB_STB6100 is not set
+-
+-#
+-# DVB-S (satellite) frontends
+-#
+-CONFIG_DVB_CX24110=m
+-CONFIG_DVB_CX24123=m
+-CONFIG_DVB_MT312=m
+-CONFIG_DVB_S5H1420=m
+-# CONFIG_DVB_STV0288 is not set
+-# CONFIG_DVB_STB6000 is not set
+-CONFIG_DVB_STV0299=m
+-CONFIG_DVB_TDA8083=m
+-CONFIG_DVB_TDA10086=m
+-# CONFIG_DVB_TDA8261 is not set
+-CONFIG_DVB_VES1X93=m
+-CONFIG_DVB_TUNER_ITD1000=m
+-# CONFIG_DVB_TUNER_CX24113 is not set
+-CONFIG_DVB_TDA826X=m
+-CONFIG_DVB_TUA6100=m
+-# CONFIG_DVB_CX24116 is not set
+-# CONFIG_DVB_SI21XX is not set
+-
+-#
+-# DVB-T (terrestrial) frontends
+-#
+-CONFIG_DVB_SP8870=m
+-CONFIG_DVB_SP887X=m
+-CONFIG_DVB_CX22700=m
+-CONFIG_DVB_CX22702=m
+-# CONFIG_DVB_DRX397XD is not set
+-CONFIG_DVB_L64781=m
+-CONFIG_DVB_TDA1004X=m
+-CONFIG_DVB_NXT6000=m
+-CONFIG_DVB_MT352=m
+-CONFIG_DVB_ZL10353=m
+-CONFIG_DVB_DIB3000MB=m
+-CONFIG_DVB_DIB3000MC=m
+-CONFIG_DVB_DIB7000M=m
+-CONFIG_DVB_DIB7000P=m
+-CONFIG_DVB_TDA10048=m
+-
+-#
+-# DVB-C (cable) frontends
+-#
+-CONFIG_DVB_VES1820=m
+-CONFIG_DVB_TDA10021=m
+-CONFIG_DVB_TDA10023=m
+-CONFIG_DVB_STV0297=m
+-
+-#
+-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+-#
+-CONFIG_DVB_NXT200X=m
+-# CONFIG_DVB_OR51211 is not set
+-# CONFIG_DVB_OR51132 is not set
+-CONFIG_DVB_BCM3510=m
+-CONFIG_DVB_LGDT330X=m
+-# CONFIG_DVB_LGDT3304 is not set
+-CONFIG_DVB_S5H1409=m
+-CONFIG_DVB_AU8522=m
+-CONFIG_DVB_S5H1411=m
+-
+-#
+-# ISDB-T (terrestrial) frontends
+-#
+-# CONFIG_DVB_S921 is not set
+-
+-#
+-# Digital terrestrial only tuners/PLL
+-#
+-CONFIG_DVB_PLL=m
+-CONFIG_DVB_TUNER_DIB0070=m
+-
+-#
+-# SEC control devices for DVB-S
+-#
+-CONFIG_DVB_LNBP21=m
+-# CONFIG_DVB_ISL6405 is not set
+-CONFIG_DVB_ISL6421=m
+-# CONFIG_DVB_LGS8GL5 is not set
+-
+-#
+-# Tools to develop new frontends
+-#
+-# CONFIG_DVB_DUMMY_FE is not set
+-# CONFIG_DVB_AF9013 is not set
+-# CONFIG_DAB is not set
++# CONFIG_AB3100_CORE is not set
++# CONFIG_EZX_PCAP is not set
++# CONFIG_MEDIA_SUPPORT is not set
+
+ #
+ # Graphics support
+@@ -1201,6 +966,7 @@ CONFIG_FB_CFB_IMAGEBLIT=m
+ # CONFIG_FB_VIRTUAL is not set
+ # CONFIG_FB_METRONOME is not set
+ # CONFIG_FB_MB862XX is not set
++# CONFIG_FB_BROADSHEET is not set
+ # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+ CONFIG_OMAP2_DSS=m
+ CONFIG_OMAP2_DSS_VRAM_SIZE=12
+@@ -1242,53 +1008,8 @@ CONFIG_DISPLAY_SUPPORT=y
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_FRAMEBUFFER_CONSOLE is not set
+ # CONFIG_LOGO is not set
+-CONFIG_SOUND=y
+-CONFIG_SOUND_OSS_CORE=y
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-CONFIG_SND_SEQUENCER=m
+-# CONFIG_SND_SEQ_DUMMY is not set
+-CONFIG_SND_OSSEMUL=y
+-CONFIG_SND_MIXER_OSS=y
+-CONFIG_SND_PCM_OSS=y
+-CONFIG_SND_PCM_OSS_PLUGINS=y
+-CONFIG_SND_SEQUENCER_OSS=y
+-# CONFIG_SND_HRTIMER is not set
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-CONFIG_SND_VERBOSE_PRINTK=y
+-CONFIG_SND_DEBUG=y
+-# CONFIG_SND_DEBUG_VERBOSE is not set
+-# CONFIG_SND_PCM_XRUN_DEBUG is not set
+-CONFIG_SND_DRIVERS=y
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_VIRMIDI is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
+-CONFIG_SND_ARM=y
+-CONFIG_SND_SPI=y
+-CONFIG_SND_SOC=y
+-CONFIG_SND_OMAP_SOC=y
+-CONFIG_SND_OMAP_SOC_MCBSP=y
+-CONFIG_SND_OMAP_SOC_OVERO=y
+-CONFIG_SND_SOC_I2C_AND_SPI=y
+-# CONFIG_SND_SOC_ALL_CODECS is not set
+-CONFIG_SND_SOC_TWL4030=y
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-CONFIG_HID_DEBUG=y
+-# CONFIG_HIDRAW is not set
+-# CONFIG_HID_PID is not set
+-
+-#
+-# Special HID drivers
+-#
+-CONFIG_HID_COMPAT=y
+-# CONFIG_HID_APPLE is not set
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+@@ -1312,7 +1033,7 @@ CONFIG_USB_INVENTRA_DMA=y
+ # CONFIG_USB_MUSB_DEBUG is not set
+
+ #
+-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+ #
+ CONFIG_USB_GADGET=y
+ # CONFIG_USB_GADGET_DEBUG is not set
+@@ -1327,6 +1048,7 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_OMAP is not set
+ # CONFIG_USB_GADGET_PXA25X is not set
+ # CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C_HSOTG is not set
+ # CONFIG_USB_GADGET_S3C2410 is not set
+ # CONFIG_USB_GADGET_IMX is not set
+ # CONFIG_USB_GADGET_M66592 is not set
+@@ -1335,9 +1057,11 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_CI13XXX is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+ CONFIG_USB_GADGET_DUALSPEED=y
+ # CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
+ CONFIG_USB_ETH=y
+ CONFIG_USB_ETH_RNDIS=y
+ # CONFIG_USB_GADGETFS is not set
+@@ -1354,6 +1078,7 @@ CONFIG_USB_OTG_UTILS=y
+ # CONFIG_USB_GPIO_VBUS is not set
+ # CONFIG_ISP1301_OMAP is not set
+ CONFIG_TWL4030_USB=y
++# CONFIG_NOP_USB_XCEIV is not set
+ CONFIG_MMC=y
+ # CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_UNSAFE_RESUME=y
+@@ -1385,8 +1110,11 @@ CONFIG_LEDS_CLASS=y
+ # CONFIG_LEDS_OMAP_PWM is not set
+ # CONFIG_LEDS_PCA9532 is not set
+ CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_GPIO_PLATFORM=y
+ # CONFIG_LEDS_LP5521 is not set
+ # CONFIG_LEDS_PCA955X is not set
++# CONFIG_LEDS_DAC124S085 is not set
++# CONFIG_LEDS_BD2802 is not set
+
+ #
+ # LED Triggers
+@@ -1395,7 +1123,12 @@ CONFIG_LEDS_TRIGGERS=y
+ CONFIG_LEDS_TRIGGER_TIMER=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+ # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
++# CONFIG_LEDS_TRIGGER_GPIO is not set
+ # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
++
++#
++# iptables trigger is under Netfilter config (LED target)
++#
+ CONFIG_RTC_LIB=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_HCTOSYS=y
+@@ -1428,6 +1161,7 @@ CONFIG_RTC_DRV_TWL4030=y
+ # CONFIG_RTC_DRV_S35390A is not set
+ # CONFIG_RTC_DRV_FM3130 is not set
+ # CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
+
+ #
+ # SPI RTC drivers
+@@ -1459,12 +1193,16 @@ CONFIG_RTC_DRV_TWL4030=y
+ # on-CPU RTC drivers
+ #
+ # CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
+ CONFIG_REGULATOR=y
+ # CONFIG_REGULATOR_DEBUG is not set
+ # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+ # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+ # CONFIG_REGULATOR_BQ24022 is not set
++# CONFIG_REGULATOR_MAX1586 is not set
+ CONFIG_REGULATOR_TWL4030=y
++# CONFIG_REGULATOR_LP3971 is not set
+ # CONFIG_UIO is not set
+ # CONFIG_STAGING is not set
+
+@@ -1480,6 +1218,7 @@ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ CONFIG_EXT3_FS=y
++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+ # CONFIG_EXT3_FS_XATTR is not set
+ # CONFIG_EXT4_FS is not set
+ CONFIG_JBD=y
+@@ -1487,15 +1226,12 @@ CONFIG_JBD=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ CONFIG_FS_POSIX_ACL=y
+-CONFIG_FILE_LOCKING=y
+-CONFIG_XFS_FS=m
+-# CONFIG_XFS_QUOTA is not set
+-# CONFIG_XFS_POSIX_ACL is not set
+-# CONFIG_XFS_RT is not set
+-# CONFIG_XFS_DEBUG is not set
++# CONFIG_XFS_FS is not set
+ # CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+ # CONFIG_BTRFS_FS is not set
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
+ CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+@@ -1508,16 +1244,18 @@ CONFIG_QFMT_V2=y
+ CONFIG_QUOTACTL=y
+ # CONFIG_AUTOFS_FS is not set
+ # CONFIG_AUTOFS4_FS is not set
+-CONFIG_FUSE_FS=m
++# CONFIG_FUSE_FS is not set
++
++#
++# Caches
++#
++# CONFIG_FSCACHE is not set
+
+ #
+ # CD-ROM/DVD Filesystems
+ #
+-CONFIG_ISO9660_FS=m
+-CONFIG_JOLIET=y
+-CONFIG_ZISOFS=y
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
+
+ #
+ # DOS/FAT/NT Filesystems
+@@ -1575,20 +1313,20 @@ CONFIG_JFFS2_CMODE_PRIORITY=y
+ # CONFIG_ROMFS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
++# CONFIG_NILFS2_FS is not set
+ CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+ CONFIG_NFS_V4=y
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+ # CONFIG_NFSD is not set
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=m
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_REGISTER_V4 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1676,12 +1414,17 @@ CONFIG_DEBUG_KERNEL=y
+ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_DETECT_HUNG_TASK=y
++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+ CONFIG_SCHED_DEBUG=y
+ CONFIG_SCHEDSTATS=y
+ CONFIG_TIMER_STATS=y
+ # CONFIG_DEBUG_OBJECTS is not set
+ # CONFIG_SLUB_DEBUG_ON is not set
+ # CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_KMEMLEAK is not set
++CONFIG_DEBUG_PREEMPT=y
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+@@ -1701,7 +1444,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_DEBUG_SG is not set
+ # CONFIG_DEBUG_NOTIFIERS is not set
+-CONFIG_FRAME_POINTER=y
+ # CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+@@ -1709,26 +1451,34 @@ CONFIG_FRAME_POINTER=y
+ # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+ # CONFIG_FAULT_INJECTION is not set
+ # CONFIG_LATENCYTOP is not set
++# CONFIG_PAGE_POISONING is not set
+ CONFIG_NOP_TRACER=y
+ CONFIG_HAVE_FUNCTION_TRACER=y
+ CONFIG_RING_BUFFER=y
++CONFIG_EVENT_TRACING=y
++CONFIG_CONTEXT_SWITCH_TRACER=y
+ CONFIG_TRACING=y
+-
+-#
+-# Tracers
+-#
++CONFIG_TRACING_SUPPORT=y
++CONFIG_FTRACE=y
+ # CONFIG_FUNCTION_TRACER is not set
+ # CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_PREEMPT_TRACER is not set
+ # CONFIG_SCHED_TRACER is not set
+-# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+ # CONFIG_BOOT_TRACER is not set
+-# CONFIG_TRACE_BRANCH_PROFILING is not set
++CONFIG_BRANCH_PROFILE_NONE=y
++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
++# CONFIG_PROFILE_ALL_BRANCHES is not set
+ # CONFIG_STACK_TRACER is not set
+-# CONFIG_FTRACE_STARTUP_TEST is not set
+-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_KMEMTRACE is not set
++# CONFIG_WORKQUEUE_TRACER is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_RING_BUFFER_BENCHMARK is not set
++# CONFIG_DYNAMIC_DEBUG is not set
+ # CONFIG_SAMPLES is not set
+ CONFIG_HAVE_ARCH_KGDB=y
+ # CONFIG_KGDB is not set
++CONFIG_ARM_UNWIND=y
+ CONFIG_DEBUG_USER=y
+ CONFIG_DEBUG_ERRORS=y
+ # CONFIG_DEBUG_STACK_USAGE is not set
+@@ -1741,10 +1491,6 @@ CONFIG_DEBUG_ERRORS=y
+ # CONFIG_SECURITY is not set
+ # CONFIG_SECURITYFS is not set
+ # CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_XOR_BLOCKS=m
+-CONFIG_ASYNC_CORE=m
+-CONFIG_ASYNC_MEMCPY=m
+-CONFIG_ASYNC_XOR=m
+ CONFIG_CRYPTO=y
+
+ #
+@@ -1759,13 +1505,15 @@ CONFIG_CRYPTO_BLKCIPHER2=y
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_HASH2=y
+ CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP=y
+ CONFIG_CRYPTO_MANAGER=y
+ CONFIG_CRYPTO_MANAGER2=y
+-CONFIG_CRYPTO_GF128MUL=m
+-CONFIG_CRYPTO_NULL=m
+-CONFIG_CRYPTO_CRYPTD=m
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++CONFIG_CRYPTO_WORKQUEUE=y
++# CONFIG_CRYPTO_CRYPTD is not set
+ # CONFIG_CRYPTO_AUTHENC is not set
+-CONFIG_CRYPTO_TEST=m
++# CONFIG_CRYPTO_TEST is not set
+
+ #
+ # Authenticated Encryption with Associated Data
+@@ -1780,65 +1528,66 @@ CONFIG_CRYPTO_TEST=m
+ CONFIG_CRYPTO_CBC=y
+ # CONFIG_CRYPTO_CTR is not set
+ # CONFIG_CRYPTO_CTS is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_LRW=m
+-CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
+ # CONFIG_CRYPTO_XTS is not set
+
+ #
+ # Hash modes
+ #
+-CONFIG_CRYPTO_HMAC=m
+-CONFIG_CRYPTO_XCBC=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
+
+ #
+ # Digest
+ #
+ CONFIG_CRYPTO_CRC32C=y
+-CONFIG_CRYPTO_MD4=m
++# CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_MICHAEL_MIC=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_RMD128 is not set
+ # CONFIG_CRYPTO_RMD160 is not set
+ # CONFIG_CRYPTO_RMD256 is not set
+ # CONFIG_CRYPTO_RMD320 is not set
+-CONFIG_CRYPTO_SHA1=m
+-CONFIG_CRYPTO_SHA256=m
+-CONFIG_CRYPTO_SHA512=m
+-CONFIG_CRYPTO_TGR192=m
+-CONFIG_CRYPTO_WP512=m
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
+
+ #
+ # Ciphers
+ #
+-CONFIG_CRYPTO_AES=y
+-CONFIG_CRYPTO_ANUBIS=m
+-CONFIG_CRYPTO_ARC4=y
+-CONFIG_CRYPTO_BLOWFISH=m
+-CONFIG_CRYPTO_CAMELLIA=m
+-CONFIG_CRYPTO_CAST5=m
+-CONFIG_CRYPTO_CAST6=m
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
+ CONFIG_CRYPTO_DES=y
+-CONFIG_CRYPTO_FCRYPT=m
+-CONFIG_CRYPTO_KHAZAD=m
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_SALSA20 is not set
+ # CONFIG_CRYPTO_SEED is not set
+-CONFIG_CRYPTO_SERPENT=m
+-CONFIG_CRYPTO_TEA=m
+-CONFIG_CRYPTO_TWOFISH=m
+-CONFIG_CRYPTO_TWOFISH_COMMON=m
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
+
+ #
+ # Compression
+ #
+-CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_ZLIB is not set
+ # CONFIG_CRYPTO_LZO is not set
+
+ #
+ # Random Number Generation
+ #
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+-CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_HW is not set
++CONFIG_BINARY_PRINTF=y
+
+ #
+ # Library routines
+@@ -1856,7 +1605,8 @@ CONFIG_ZLIB_INFLATE=y
+ CONFIG_ZLIB_DEFLATE=y
+ CONFIG_LZO_COMPRESS=y
+ CONFIG_LZO_DECOMPRESS=y
+-CONFIG_PLIST=y
++CONFIG_DECOMPRESS_GZIP=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_NLATTR=y
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0115-DSS2-SDI-make-sdi_pads-static.patch b/recipes/linux/linux-omap-pm/dss2/0115-DSS2-SDI-make-sdi_pads-static.patch
new file mode 100644
index 0000000000..59681c08ba
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0115-DSS2-SDI-make-sdi_pads-static.patch
@@ -0,0 +1,26 @@
+From 81a652bad3261a822821fd49d3bc21a165a8d26f Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 16:17:44 +0300
+Subject: [PATCH 115/146] DSS2: SDI: make sdi_pads static
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/sdi.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
+index c484e0c..ef07c7c 100644
+--- a/drivers/video/omap2/dss/sdi.c
++++ b/drivers/video/omap2/dss/sdi.c
+@@ -46,7 +46,7 @@ static struct {
+ } sdi;
+
+ /* CONTROL_PADCONF_DSS_DATAXX */
+-const u16 sdi_pads[] =
++static const u16 sdi_pads[] =
+ {
+ 0x0f0, /* 10[ 7..0]:SDI_DAT1N */
+ 0x0f2, /* 10[15..0]:SDI_DAT1P */
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0116-DSS2-Fix-default_color-sysfs-output.patch b/recipes/linux/linux-omap-pm/dss2/0116-DSS2-Fix-default_color-sysfs-output.patch
new file mode 100644
index 0000000000..97506adbf6
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0116-DSS2-Fix-default_color-sysfs-output.patch
@@ -0,0 +1,26 @@
+From 501537af71157a95e5947a5827514014909a6608 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 15 Jun 2009 15:13:25 +0300
+Subject: [PATCH 116/146] DSS2: Fix default_color sysfs output
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/manager.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index f6df4d6..0b0c51e 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -101,7 +101,7 @@ put_device:
+ static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+ char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d", mgr->info.default_color);
++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
+ }
+
+ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0117-DSS2-Locking-for-VRFB.patch b/recipes/linux/linux-omap-pm/dss2/0117-DSS2-Locking-for-VRFB.patch
new file mode 100644
index 0000000000..7902d2225c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0117-DSS2-Locking-for-VRFB.patch
@@ -0,0 +1,125 @@
+From 4044386e8f32ea442478809d945f50c5a3a66f88 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 16 Jun 2009 15:18:30 +0300
+Subject: [PATCH 117/146] DSS2: Locking for VRFB
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 25 ++++++++++++++++++++++---
+ 1 files changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 0c7d943..7cd7c61 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -3,6 +3,7 @@
+ #include <linux/ioport.h>
+ #include <linux/io.h>
+ #include <linux/bitops.h>
++#include <linux/mutex.h>
+
+ #include <mach/io.h>
+ #include <mach/vrfb.h>
+@@ -42,6 +43,8 @@ static unsigned long ctx_map;
+ /* bitmap of contexts for which we have to keep the HW context valid */
+ static unsigned long ctx_map_active;
+
++static DEFINE_MUTEX(ctx_lock);
++
+ /*
+ * Access to this happens from client drivers or the PM core after wake-up.
+ * For the first case we require locking at the driver level, for the second
+@@ -171,6 +174,8 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+
+ DBG("release ctx %d\n", ctx);
+
++ mutex_lock(&ctx_lock);
++
+ if (!(ctx_map & (1 << ctx))) {
+ BUG();
+ return;
+@@ -186,6 +191,8 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+ }
+
+ vrfb->context = 0xff;
++
++ mutex_unlock(&ctx_lock);
+ }
+ EXPORT_SYMBOL(omap_vrfb_release_ctx);
+
+@@ -194,16 +201,20 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ int rot;
+ u32 paddr;
+ u8 ctx;
++ int r;
+
+ DBG("request ctx\n");
+
++ mutex_lock(&ctx_lock);
++
+ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+ if ((ctx_map & (1 << ctx)) == 0)
+ break;
+
+ if (ctx == VRFB_NUM_CTXS) {
+ printk(KERN_ERR "vrfb: no free contexts\n");
+- return -EBUSY;
++ r = -EBUSY;
++ goto out;
+ }
+
+ DBG("found free ctx %d\n", ctx);
+@@ -223,7 +234,8 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ "area for ctx %d, rotation %d\n",
+ ctx, rot * 90);
+ omap_vrfb_release_ctx(vrfb);
+- return -ENOMEM;
++ r = -ENOMEM;
++ goto out;
+ }
+
+ vrfb->paddr[rot] = paddr;
+@@ -231,25 +243,31 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
+ }
+
+- return 0;
++ r = 0;
++out:
++ mutex_unlock(&ctx_lock);
++ return r;
+ }
+ EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+ void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
+ {
+ DBG("suspend ctx %d\n", vrfb->context);
++ mutex_lock(&ctx_lock);
+ if (vrfb->context >= VRFB_NUM_CTXS ||
+ (!(1 << vrfb->context) & ctx_map_active)) {
+ BUG();
+ return;
+ }
+ clear_bit(vrfb->context, &ctx_map_active);
++ mutex_unlock(&ctx_lock);
+ }
+ EXPORT_SYMBOL(omap_vrfb_suspend_ctx);
+
+ void omap_vrfb_resume_ctx(struct vrfb *vrfb)
+ {
+ DBG("resume ctx %d\n", vrfb->context);
++ mutex_lock(&ctx_lock);
+ if (vrfb->context >= VRFB_NUM_CTXS ||
+ ((1 << vrfb->context) & ctx_map_active)) {
+ BUG();
+@@ -263,6 +281,7 @@ void omap_vrfb_resume_ctx(struct vrfb *vrfb)
+ */
+ restore_hw_context(vrfb->context);
+ set_bit(vrfb->context, &ctx_map_active);
++ mutex_unlock(&ctx_lock);
+ }
+ EXPORT_SYMBOL(omap_vrfb_resume_ctx);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0118-DSS2-DISPC-fix-locking-issue-with-irq-handling.patch b/recipes/linux/linux-omap-pm/dss2/0118-DSS2-DISPC-fix-locking-issue-with-irq-handling.patch
new file mode 100644
index 0000000000..c01ece605b
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0118-DSS2-DISPC-fix-locking-issue-with-irq-handling.patch
@@ -0,0 +1,54 @@
+From 32720bafdbb70ab9f534d93b75a954c891bed8cc Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Sat, 13 Jun 2009 13:38:54 +0300
+Subject: [PATCH 118/146] DSS2: DISPC: fix locking issue with irq handling
+
+Fix the problem that an irq handler couldn't unregister
+itself
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dispc.c | 12 +++++++++++-
+ 1 files changed, 11 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 2463bab..4e1da6b 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -2732,6 +2732,7 @@ void dispc_irq_handler(void)
+ u32 handledirqs = 0;
+ u32 unhandled_errors;
+ struct omap_dispc_isr_data *isr_data;
++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+ spin_lock(&dispc.irq_lock);
+
+@@ -2745,8 +2746,15 @@ void dispc_irq_handler(void)
+ * off */
+ dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
+
++ /* make a copy and unlock, so that isrs can unregister
++ * themselves */
++ memcpy(registered_isr, dispc.registered_isr,
++ sizeof(registered_isr));
++
++ spin_unlock(&dispc.irq_lock);
++
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+- isr_data = &dispc.registered_isr[i];
++ isr_data = &registered_isr[i];
+
+ if (!isr_data->isr)
+ continue;
+@@ -2757,6 +2765,8 @@ void dispc_irq_handler(void)
+ }
+ }
+
++ spin_lock(&dispc.irq_lock);
++
+ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
+
+ if (unhandled_errors) {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0119-DSS2-OMAPFB-remove-unneeded-locks.patch b/recipes/linux/linux-omap-pm/dss2/0119-DSS2-OMAPFB-remove-unneeded-locks.patch
new file mode 100644
index 0000000000..2b0ba2da78
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0119-DSS2-OMAPFB-remove-unneeded-locks.patch
@@ -0,0 +1,391 @@
+From 995d5a236d8b1f7fe24da9dcacb1e89c214afdba Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 16 Jun 2009 14:33:07 +0300
+Subject: [PATCH 119/146] DSS2: OMAPFB: remove unneeded locks
+
+omapfb_lock() locks the whole omapfb device, meaning all framebuffers.
+Usually it is enough to lock only the framebuffer that is being
+manipulated, and for IOCTLs the fb framework does this already.
+
+Thus, we can remove many omapfb_lock()s totally, and change some
+to lock_fb_info().
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 47 ++--------------------------
+ drivers/video/omap2/omapfb/omapfb-main.c | 5 ---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c | 32 ++++++++++++-------
+ 3 files changed, 24 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index c513fe0..91308c2 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -44,8 +44,6 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+
+ DBG("omapfb_setup_plane\n");
+
+- omapfb_lock(fbdev);
+-
+ if (ofbi->num_overlays != 1) {
+ r = -EINVAL;
+ goto out;
+@@ -94,7 +92,6 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+ }
+
+ out:
+- omapfb_unlock(fbdev);
+ if (r)
+ dev_err(fbdev->dev, "setup_plane failed\n");
+ return r;
+@@ -103,9 +100,6 @@ out:
+ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+-
+- omapfb_lock(fbdev);
+
+ if (ofbi->num_overlays != 1) {
+ memset(pi, 0, sizeof(*pi));
+@@ -125,8 +119,6 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+ pi->out_height = ovli->out_height;
+ }
+
+- omapfb_unlock(fbdev);
+-
+ return 0;
+ }
+
+@@ -145,43 +137,32 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+
+ rg = &ofbi->region;
+
+- omapfb_lock(fbdev);
+-
+ for (i = 0; i < ofbi->num_overlays; i++) {
+- if (ofbi->overlays[i]->info.enabled) {
+- r = -EBUSY;
+- goto out;
+- }
++ if (ofbi->overlays[i]->info.enabled)
++ return -EBUSY;
+ }
+
+ if (rg->size != size || rg->type != mi->type) {
+ r = omapfb_realloc_fbmem(fbi, size, mi->type);
+ if (r) {
+ dev_err(fbdev->dev, "realloc fbmem failed\n");
+- goto out;
++ return r;
+ }
+ }
+
+- r = 0;
+-out:
+- omapfb_unlock(fbdev);
+-
+- return r;
++ return 0;
+ }
+
+ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb2_mem_region *rg;
+
+ rg = &ofbi->region;
+ memset(mi, 0, sizeof(*mi));
+
+- omapfb_lock(fbdev);
+ mi->size = rg->size;
+ mi->type = rg->type;
+- omapfb_unlock(fbdev);
+
+ return 0;
+ }
+@@ -189,8 +170,6 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+ static int omapfb_update_window(struct fb_info *fbi,
+ u32 x, u32 y, u32 w, u32 h)
+ {
+- struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ u16 dw, dh;
+
+@@ -205,9 +184,7 @@ static int omapfb_update_window(struct fb_info *fbi,
+ if (x + w > dw || y + h > dh)
+ return -EINVAL;
+
+- omapfb_lock(fbdev);
+ display->update(display, x, y, w, h);
+- omapfb_unlock(fbdev);
+
+ return 0;
+ }
+@@ -215,8 +192,6 @@ static int omapfb_update_window(struct fb_info *fbi,
+ static int omapfb_set_update_mode(struct fb_info *fbi,
+ enum omapfb_update_mode mode)
+ {
+- struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode um;
+ int r;
+@@ -241,9 +216,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
+ return -EINVAL;
+ }
+
+- omapfb_lock(fbdev);
+ r = display->set_update_mode(display, um);
+- omapfb_unlock(fbdev);
+
+ return r;
+ }
+@@ -251,17 +224,13 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
+ static int omapfb_get_update_mode(struct fb_info *fbi,
+ enum omapfb_update_mode *mode)
+ {
+- struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+ enum omap_dss_update_mode m;
+
+ if (!display || !display->get_update_mode)
+ return -EINVAL;
+
+- omapfb_lock(fbdev);
+ m = display->get_update_mode(display);
+- omapfb_unlock(fbdev);
+
+ switch (m) {
+ case OMAP_DSS_UPDATE_DISABLED:
+@@ -396,8 +365,6 @@ static int omapfb_memory_read(struct fb_info *fbi,
+ struct omapfb_memory_read *mr)
+ {
+ struct omap_dss_device *display = fb2display(fbi);
+- struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ void *buf;
+ int r;
+
+@@ -416,8 +383,6 @@ static int omapfb_memory_read(struct fb_info *fbi,
+ return -ENOMEM;
+ }
+
+- omapfb_lock(fbdev);
+-
+ r = display->memory_read(display, buf, mr->buffer_size,
+ mr->x, mr->y, mr->w, mr->h);
+
+@@ -428,8 +393,6 @@ static int omapfb_memory_read(struct fb_info *fbi,
+
+ vfree(buf);
+
+- omapfb_unlock(fbdev);
+-
+ return r;
+ }
+
+@@ -509,9 +472,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ break;
+ }
+
+- omapfb_lock(fbdev);
+ r = display->sync(display);
+- omapfb_unlock(fbdev);
+ break;
+
+ case OMAPFB_UPDATE_WINDOW_OLD:
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index dc9c06c..1473581 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -848,13 +848,10 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ int r = 0;
+
+ DBG("pan_display(%d)\n", ofbi->id);
+
+- omapfb_lock(fbdev);
+-
+ if (var->xoffset != fbi->var.xoffset ||
+ var->yoffset != fbi->var.yoffset) {
+ struct fb_var_screeninfo new_var;
+@@ -872,8 +869,6 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
+ }
+ }
+
+- omapfb_unlock(fbdev);
+-
+ return r;
+ }
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index a00f61a..ef30e0e 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -49,7 +49,6 @@ static ssize_t store_rotate_type(struct device *dev,
+ {
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ enum omap_dss_rotation_type rot_type;
+ int r;
+
+@@ -58,7 +57,7 @@ static ssize_t store_rotate_type(struct device *dev,
+ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
+ return -EINVAL;
+
+- omapfb_lock(fbdev);
++ lock_fb_info(fbi);
+
+ r = 0;
+ if (rot_type == ofbi->rotation_type)
+@@ -76,7 +75,7 @@ static ssize_t store_rotate_type(struct device *dev,
+ * need to do any further parameter checking at this point.
+ */
+ out:
+- omapfb_unlock(fbdev);
++ unlock_fb_info(fbi);
+
+ return r ? r : count;
+ }
+@@ -97,7 +96,6 @@ static ssize_t store_mirror(struct device *dev,
+ {
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ bool mirror;
+ int r;
+ struct fb_var_screeninfo new_var;
+@@ -107,7 +105,7 @@ static ssize_t store_mirror(struct device *dev,
+ if (mirror != 0 && mirror != 1)
+ return -EINVAL;
+
+- omapfb_lock(fbdev);
++ lock_fb_info(fbi);
+
+ ofbi->mirror = mirror;
+
+@@ -125,7 +123,7 @@ static ssize_t store_mirror(struct device *dev,
+
+ r = count;
+ out:
+- omapfb_unlock(fbdev);
++ unlock_fb_info(fbi);
+
+ return r;
+ }
+@@ -139,6 +137,9 @@ static ssize_t show_overlays(struct device *dev,
+ ssize_t l = 0;
+ int t;
+
++ omapfb_lock(fbdev);
++ lock_fb_info(fbi);
++
+ for (t = 0; t < ofbi->num_overlays; t++) {
+ struct omap_overlay *ovl = ofbi->overlays[t];
+ int ovlnum;
+@@ -153,6 +154,9 @@ static ssize_t show_overlays(struct device *dev,
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
++ unlock_fb_info(fbi);
++ omapfb_unlock(fbdev);
++
+ return l;
+ }
+
+@@ -192,6 +196,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+ len = len - 1;
+
+ omapfb_lock(fbdev);
++ lock_fb_info(fbi);
+
+ if (len > 0) {
+ char *p = (char *)buf;
+@@ -298,6 +303,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+
+ r = count;
+ out:
++ unlock_fb_info(fbi);
+ omapfb_unlock(fbdev);
+
+ return r;
+@@ -311,6 +317,8 @@ static ssize_t show_overlays_rotate(struct device *dev,
+ ssize_t l = 0;
+ int t;
+
++ lock_fb_info(fbi);
++
+ for (t = 0; t < ofbi->num_overlays; t++) {
+ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+ t == 0 ? "" : ",", ofbi->rotation[t]);
+@@ -318,6 +326,8 @@ static ssize_t show_overlays_rotate(struct device *dev,
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
++ unlock_fb_info(fbi);
++
+ return l;
+ }
+
+@@ -326,7 +336,6 @@ static ssize_t store_overlays_rotate(struct device *dev,
+ {
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ int num_ovls = 0, r, i;
+ int len;
+ bool changed = false;
+@@ -336,7 +345,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
+ if (buf[len - 1] == '\n')
+ len = len - 1;
+
+- omapfb_lock(fbdev);
++ lock_fb_info(fbi);
+
+ if (len > 0) {
+ char *p = (char *)buf;
+@@ -382,7 +391,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
+
+ r = count;
+ out:
+- omapfb_unlock(fbdev);
++ unlock_fb_info(fbi);
+
+ return r;
+ }
+@@ -401,14 +410,13 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
+ {
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+- struct omapfb2_device *fbdev = ofbi->fbdev;
+ unsigned long size;
+ int r;
+ int i;
+
+ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
+
+- omapfb_lock(fbdev);
++ lock_fb_info(fbi);
+
+ for (i = 0; i < ofbi->num_overlays; i++) {
+ if (ofbi->overlays[i]->info.enabled) {
+@@ -427,7 +435,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
+
+ r = count;
+ out:
+- omapfb_unlock(fbdev);
++ unlock_fb_info(fbi);
+
+ return r;
+ }
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0120-DSS2-DISPC-configuration-management.patch b/recipes/linux/linux-omap-pm/dss2/0120-DSS2-DISPC-configuration-management.patch
new file mode 100644
index 0000000000..ef94abfd0c
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0120-DSS2-DISPC-configuration-management.patch
@@ -0,0 +1,2006 @@
+From 43e7fcaa40dd3726bda3317b8419d4be4e73dbfb Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 12 Jun 2009 10:55:49 +0300
+Subject: [PATCH 120/146] DSS2: DISPC configuration management
+
+This commit implements caching and synchronization of DISPC shadow
+registers.
+
+I had to disable fifomerging, enabling it needs more thought and
+work.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 30 +-
+ drivers/video/omap2/dss/dispc.c | 307 ++--------
+ drivers/video/omap2/dss/display.c | 21 +-
+ drivers/video/omap2/dss/dsi.c | 41 +-
+ drivers/video/omap2/dss/dss.h | 19 +-
+ drivers/video/omap2/dss/manager.c | 933 ++++++++++++++++++++++++++---
+ drivers/video/omap2/dss/overlay.c | 64 ++-
+ drivers/video/omap2/dss/rfbi.c | 2 +-
+ drivers/video/omap2/dss/venc.c | 10 +
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 26 +
+ include/linux/omapfb.h | 1 +
+ 11 files changed, 1047 insertions(+), 407 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 0695497..be07c35 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -275,13 +275,19 @@ struct omap_overlay {
+ struct kobject kobj;
+ struct list_head list;
+
++ /* static fields */
+ const char *name;
+ int id;
+- struct omap_overlay_manager *manager;
+ enum omap_color_mode supported_modes;
+- struct omap_overlay_info info;
+ enum omap_overlay_caps caps;
+
++ /* dynamic fields */
++ struct omap_overlay_manager *manager;
++ struct omap_overlay_info info;
++
++ /* if true, info has been changed, but not applied() yet */
++ bool info_dirty;
++
+ int (*set_manager)(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr);
+ int (*unset_manager)(struct omap_overlay *ovl);
+@@ -290,6 +296,8 @@ struct omap_overlay {
+ struct omap_overlay_info *info);
+ void (*get_overlay_info)(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
++
++ int (*wait_for_go)(struct omap_overlay *ovl);
+ };
+
+ struct omap_overlay_manager_info {
+@@ -306,25 +314,33 @@ struct omap_overlay_manager {
+ struct kobject kobj;
+ struct list_head list;
+
++ /* static fields */
+ const char *name;
+ int id;
+ enum omap_overlay_manager_caps caps;
+- struct omap_overlay_manager_info info;
+- struct omap_dss_device *device;
+ int num_overlays;
+ struct omap_overlay **overlays;
+ enum omap_display_type supported_displays;
+
++ /* dynamic fields */
++ struct omap_dss_device *device;
++ struct omap_overlay_manager_info info;
++
++ bool device_changed;
++ /* if true, info has been changed but not applied() yet */
++ bool info_dirty;
++
+ int (*set_device)(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev);
+ int (*unset_device)(struct omap_overlay_manager *mgr);
+
+- int (*apply)(struct omap_overlay_manager *mgr);
+-
+ int (*set_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+ void (*get_manager_info)(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
++
++ int (*apply)(struct omap_overlay_manager *mgr);
++ int (*wait_for_go)(struct omap_overlay_manager *mgr);
+ };
+
+ struct omap_dss_device {
+@@ -450,8 +466,6 @@ struct omap_dss_device {
+ void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h);
+
+- void (*configure_overlay)(struct omap_overlay *overlay);
+-
+ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
+ u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 4e1da6b..d061d75 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -158,6 +158,8 @@ static struct {
+ unsigned long cache_prate;
+ struct dispc_clock_info cache_cinfo;
+
++ u32 fifo_size[3];
++
+ spinlock_t irq_lock;
+ u32 irq_error_mask;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+@@ -479,10 +481,21 @@ static inline void enable_clocks(bool enable)
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ }
+
++bool dispc_go_busy(enum omap_channel channel)
++{
++ int bit;
++
++ if (channel == OMAP_DSS_CHANNEL_LCD)
++ bit = 5; /* GOLCD */
++ else
++ bit = 6; /* GODIGIT */
++
++ return REG_GET(DISPC_CONTROL, bit, bit) == 1;
++}
++
+ void dispc_go(enum omap_channel channel)
+ {
+ int bit;
+- unsigned long tmo;
+
+ enable_clocks(1);
+
+@@ -500,13 +513,9 @@ void dispc_go(enum omap_channel channel)
+ else
+ bit = 6; /* GODIGIT */
+
+- tmo = jiffies + msecs_to_jiffies(200);
+- while (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+- if (time_after(jiffies, tmo)) {
+- DSSERR("timeout waiting GO flag\n");
+- goto end;
+- }
+- cpu_relax();
++ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
++ DSSERR("GO bit not down for channel %d\n", channel);
++ goto end;
+ }
+
+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
+@@ -942,31 +951,33 @@ void dispc_set_digit_size(u16 width, u16 height)
+ enable_clocks(0);
+ }
+
+-u32 dispc_get_plane_fifo_size(enum omap_plane plane)
++static void dispc_read_plane_fifo_sizes(void)
+ {
+ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+ DISPC_VID_FIFO_SIZE_STATUS(0),
+ DISPC_VID_FIFO_SIZE_STATUS(1) };
+ u32 size;
++ int plane;
+
+ enable_clocks(1);
+
+- if (cpu_is_omap24xx())
+- size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
+- else if (cpu_is_omap34xx())
+- size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
+- else
+- BUG();
++ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
++ if (cpu_is_omap24xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
++ else if (cpu_is_omap34xx())
++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
++ else
++ BUG();
+
+- if (cpu_is_omap34xx()) {
+- /* FIFOMERGE */
+- if (REG_GET(DISPC_CONFIG, 14, 14))
+- size *= 3;
++ dispc.fifo_size[plane] = size;
+ }
+
+ enable_clocks(0);
++}
+
+- return size;
++u32 dispc_get_plane_fifo_size(enum omap_plane plane)
++{
++ return dispc.fifo_size[plane];
+ }
+
+ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+@@ -974,16 +985,10 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+ DISPC_VID_FIFO_THRESHOLD(0),
+ DISPC_VID_FIFO_THRESHOLD(1) };
+- u32 size;
+-
+ enable_clocks(1);
+
+- size = dispc_get_plane_fifo_size(plane);
+-
+- BUG_ON(low > size || high > size);
+-
+- DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n",
+- plane, size,
++ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
++ plane,
+ REG_GET(ftrs_reg[plane], 11, 0),
+ REG_GET(ftrs_reg[plane], 27, 16),
+ low, high);
+@@ -1480,8 +1485,14 @@ static unsigned long calc_fclk(u16 width, u16 height,
+ return dispc_pclk_rate() * vf * hf;
+ }
+
++void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
++{
++ enable_clocks(1);
++ _dispc_set_channel_out(plane, channel_out);
++ enable_clocks(0);
++}
++
+ static int _dispc_setup_plane(enum omap_plane plane,
+- enum omap_channel channel_out,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+@@ -1631,7 +1642,6 @@ static int _dispc_setup_plane(enum omap_plane plane,
+ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+ offset0, offset1, row_inc, pix_inc);
+
+- _dispc_set_channel_out(plane, channel_out);
+ _dispc_set_color_mode(plane, color_mode);
+
+ _dispc_set_plane_ba0(plane, paddr + offset0);
+@@ -3068,6 +3078,8 @@ static void _omap_dispc_initial_config(void)
+ _dispc_setup_color_conv_coef();
+
+ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
++
++ dispc_read_plane_fifo_sizes();
+ }
+
+ int dispc_init(void)
+@@ -3127,7 +3139,7 @@ int dispc_enable_plane(enum omap_plane plane, bool enable)
+ return 0;
+ }
+
+-int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
++int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+@@ -3139,9 +3151,9 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ {
+ int r = 0;
+
+- DSSDBG("dispc_setup_plane %d, ch %d, pa %x, sw %d, %d,%d, %dx%d -> "
++ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
+- plane, channel_out, paddr, screen_width, pos_x, pos_y,
++ plane, paddr, screen_width, pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ ilace, color_mode,
+@@ -3149,7 +3161,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+
+ enable_clocks(1);
+
+- r = _dispc_setup_plane(plane, channel_out,
++ r = _dispc_setup_plane(plane,
+ paddr, screen_width,
+ pos_x, pos_y,
+ width, height,
+@@ -3163,230 +3175,3 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+
+ return r;
+ }
+-
+-static int dispc_is_intersecting(int x1, int y1, int w1, int h1,
+- int x2, int y2, int w2, int h2)
+-{
+- if (x1 >= (x2+w2))
+- return 0;
+-
+- if ((x1+w1) <= x2)
+- return 0;
+-
+- if (y1 >= (y2+h2))
+- return 0;
+-
+- if ((y1+h1) <= y2)
+- return 0;
+-
+- return 1;
+-}
+-
+-static int dispc_is_overlay_scaled(struct omap_overlay_info *pi)
+-{
+- if (pi->width != pi->out_width)
+- return 1;
+-
+- if (pi->height != pi->out_height)
+- return 1;
+-
+- return 0;
+-}
+-
+-/* returns the area that needs updating */
+-void dispc_setup_partial_planes(struct omap_dss_device *dssdev,
+- u16 *xi, u16 *yi, u16 *wi, u16 *hi)
+-{
+- struct omap_overlay_manager *mgr;
+- int i;
+-
+- int x, y, w, h;
+-
+- x = *xi;
+- y = *yi;
+- w = *wi;
+- h = *hi;
+-
+- DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
+- *xi, *yi, *wi, *hi);
+-
+-
+- mgr = dssdev->manager;
+-
+- if (!mgr) {
+- DSSDBG("no manager\n");
+- return;
+- }
+-
+- for (i = 0; i < mgr->num_overlays; i++) {
+- struct omap_overlay *ovl;
+- struct omap_overlay_info *pi;
+- ovl = mgr->overlays[i];
+-
+- if (ovl->manager != mgr)
+- continue;
+-
+- if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+- continue;
+-
+- pi = &ovl->info;
+-
+- if (!pi->enabled)
+- continue;
+- /*
+- * If the plane is intersecting and scaled, we
+- * enlarge the update region to accomodate the
+- * whole area
+- */
+-
+- if (dispc_is_intersecting(x, y, w, h,
+- pi->pos_x, pi->pos_y,
+- pi->out_width, pi->out_height)) {
+- if (dispc_is_overlay_scaled(pi)) {
+-
+- int x1, y1, x2, y2;
+-
+- if (x > pi->pos_x)
+- x1 = pi->pos_x;
+- else
+- x1 = x;
+-
+- if (y > pi->pos_y)
+- y1 = pi->pos_y;
+- else
+- y1 = y;
+-
+- if ((x + w) < (pi->pos_x + pi->out_width))
+- x2 = pi->pos_x + pi->out_width;
+- else
+- x2 = x + w;
+-
+- if ((y + h) < (pi->pos_y + pi->out_height))
+- y2 = pi->pos_y + pi->out_height;
+- else
+- y2 = y + h;
+-
+- x = x1;
+- y = y1;
+- w = x2 - x1;
+- h = y2 - y1;
+-
+- DSSDBG("Update area after enlarge due to "
+- "scaling %d, %d %dx%d\n",
+- x, y, w, h);
+- }
+- }
+- }
+-
+- for (i = 0; i < mgr->num_overlays; i++) {
+- struct omap_overlay *ovl = mgr->overlays[i];
+- struct omap_overlay_info *pi = &ovl->info;
+-
+- int px = pi->pos_x;
+- int py = pi->pos_y;
+- int pw = pi->width;
+- int ph = pi->height;
+- int pow = pi->out_width;
+- int poh = pi->out_height;
+- u32 pa = pi->paddr;
+- int psw = pi->screen_width;
+- int bpp;
+-
+- if (ovl->manager != mgr)
+- continue;
+-
+- /*
+- * If plane is not enabled or the update region
+- * does not intersect with the plane in question,
+- * we really disable the plane from hardware
+- */
+-
+- if (!pi->enabled ||
+- !dispc_is_intersecting(x, y, w, h,
+- px, py, pow, poh)) {
+- dispc_enable_plane(ovl->id, 0);
+- continue;
+- }
+-
+- switch (pi->color_mode) {
+- case OMAP_DSS_COLOR_RGB16:
+- case OMAP_DSS_COLOR_ARGB16:
+- case OMAP_DSS_COLOR_YUV2:
+- case OMAP_DSS_COLOR_UYVY:
+- bpp = 16;
+- break;
+-
+- case OMAP_DSS_COLOR_RGB24P:
+- bpp = 24;
+- break;
+-
+- case OMAP_DSS_COLOR_RGB24U:
+- case OMAP_DSS_COLOR_ARGB32:
+- case OMAP_DSS_COLOR_RGBA32:
+- case OMAP_DSS_COLOR_RGBX32:
+- bpp = 32;
+- break;
+-
+- default:
+- BUG();
+- return;
+- }
+-
+- if (x > pi->pos_x) {
+- px = 0;
+- pw -= (x - pi->pos_x);
+- pa += (x - pi->pos_x) * bpp / 8;
+- } else {
+- px = pi->pos_x - x;
+- }
+-
+- if (y > pi->pos_y) {
+- py = 0;
+- ph -= (y - pi->pos_y);
+- pa += (y - pi->pos_y) * psw * bpp / 8;
+- } else {
+- py = pi->pos_y - y;
+- }
+-
+- if (w < (px+pw))
+- pw -= (px+pw) - (w);
+-
+- if (h < (py+ph))
+- ph -= (py+ph) - (h);
+-
+- /* Can't scale the GFX plane */
+- if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 ||
+- dispc_is_overlay_scaled(pi) == 0) {
+- pow = pw;
+- poh = ph;
+- }
+-
+- DSSDBG("calc plane %d, %x, sw %d, %d,%d, %dx%d -> %dx%d\n",
+- ovl->id, pa, psw, px, py, pw, ph, pow, poh);
+-
+- dispc_setup_plane(ovl->id, mgr->id,
+- pa, psw,
+- px, py,
+- pw, ph,
+- pow, poh,
+- pi->color_mode, 0,
+- pi->rotation_type,
+- pi->rotation,
+- pi->mirror,
+- pi->global_alpha);
+-
+- if (dss_use_replication(dssdev, ovl->info.color_mode))
+- dispc_enable_replication(ovl->id, true);
+- else
+- dispc_enable_replication(ovl->id, false);
+-
+- dispc_enable_plane(ovl->id, 1);
+- }
+-
+- *xi = x;
+- *yi = y;
+- *wi = w;
+- *hi = h;
+-
+-}
+-
+diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
+index 1242c39..6b5d0cf 100644
+--- a/drivers/video/omap2/dss/display.c
++++ b/drivers/video/omap2/dss/display.c
+@@ -310,21 +310,17 @@ static void default_get_resolution(struct omap_dss_device *dssdev,
+ *yres = dssdev->panel.timings.y_res;
+ }
+
+-static void default_configure_overlay(struct omap_overlay *ovl)
++void default_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high)
+ {
+- unsigned low, high, size;
+- enum omap_burst_size burst;
+- enum omap_plane plane = ovl->id;
++ unsigned burst_size_bytes;
+
+- burst = OMAP_DSS_BURST_16x32;
+- size = 16 * 32 / 8;
++ *burst_size = OMAP_DSS_BURST_16x32;
++ burst_size_bytes = 16 * 32 / 8;
+
+- dispc_set_burst_size(plane, burst);
+-
+- high = dispc_get_plane_fifo_size(plane) - 1;
+- low = dispc_get_plane_fifo_size(plane) - size;
+-
+- dispc_setup_plane_fifo(plane, low, high);
++ *fifo_high = fifo_size - 1;
++ *fifo_low = fifo_size - burst_size_bytes;
+ }
+
+ static int default_wait_vsync(struct omap_dss_device *dssdev)
+@@ -431,7 +427,6 @@ void dss_init_device(struct platform_device *pdev,
+
+ dssdev->get_resolution = default_get_resolution;
+ dssdev->get_recommended_bpp = default_get_recommended_bpp;
+- dssdev->configure_overlay = default_configure_overlay;
+ dssdev->wait_vsync = default_wait_vsync;
+
+ switch (dssdev->type) {
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index ffac77b..875be0c 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2566,7 +2566,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+
+ dispc_disable_sidle();
+
+- dispc_enable_lcd_out(1);
++ dss_start_update(dssdev);
+
+ if (use_te_trigger)
+ dsi_vc_send_bta(1);
+@@ -2606,12 +2606,19 @@ static void dsi_set_update_region(struct omap_dss_device *dssdev,
+ static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+ {
+ u16 w, h;
++ int i;
+
+ DSSDBG("starting auto update\n");
+
+ /* In automatic mode the overlay settings are applied like on DPI/SDI.
+- * The overlay settings may not have been applied, if we were in manual
+- * mode earlier, so do it here */
++ * Mark the overlays dirty, so that we get the overlays configured, as
++ * manual mode has left them in bad shape after config partia planes */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_overlay *ovl;
++ ovl = omap_dss_get_overlay(i);
++ if (ovl->manager == dssdev->manager)
++ ovl->info_dirty = true;
++ }
+ dssdev->manager->apply(dssdev->manager);
+
+ dssdev->get_resolution(dssdev, &w, &h);
+@@ -2732,7 +2739,7 @@ static int dsi_update_thread(void *data)
+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) {
+- dispc_setup_partial_planes(device,
++ dss_setup_partial_planes(device,
+ &x, &y, &w, &h);
+ #if 1
+ /* XXX there seems to be a bug in this driver
+@@ -2741,12 +2748,13 @@ static int dsi_update_thread(void *data)
+ * are always odd, so "fix" it here for now */
+ if (w & 1) {
+ u16 dw, dh;
+- device->get_resolution(device, &dw, &dh);
++ device->get_resolution(device,
++ &dw, &dh);
+ if (x + w == dw)
+ x &= ~1;
+ ++w;
+
+- dispc_setup_partial_planes(device,
++ dss_setup_partial_planes(device,
+ &x, &y, &w, &h);
+ }
+ #endif
+@@ -3361,20 +3369,17 @@ static int dsi_display_memory_read(struct omap_dss_device *dssdev,
+ return r;
+ }
+
+-static void dsi_configure_overlay(struct omap_overlay *ovl)
++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high)
+ {
+- unsigned low, high, size;
+- enum omap_burst_size burst;
+- enum omap_plane plane = ovl->id;
++ unsigned burst_size_bytes;
+
+- burst = OMAP_DSS_BURST_16x32;
+- size = 16 * 32 / 8;
++ *burst_size = OMAP_DSS_BURST_16x32;
++ burst_size_bytes = 16 * 32 / 8;
+
+- dispc_set_burst_size(plane, burst);
+-
+- high = dispc_get_plane_fifo_size(plane) - size;
+- low = 0;
+- dispc_setup_plane_fifo(plane, low, high);
++ *fifo_high = fifo_size - burst_size_bytes;
++ *fifo_low = 0;
+ }
+
+ int dsi_init_display(struct omap_dss_device *dssdev)
+@@ -3401,8 +3406,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
+ dssdev->run_test = dsi_display_run_test;
+ dssdev->memory_read = dsi_display_memory_read;
+
+- dssdev->configure_overlay = dsi_configure_overlay;
+-
+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ dsi.vc[0].dssdev = dssdev;
+diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
+index 53f0f3d..50f7f5f 100644
+--- a/drivers/video/omap2/dss/dss.h
++++ b/drivers/video/omap2/dss/dss.h
+@@ -175,10 +175,17 @@ void dss_uninit_device(struct platform_device *pdev,
+ struct omap_dss_device *dssdev);
+ bool dss_use_replication(struct omap_dss_device *dssdev,
+ enum omap_color_mode mode);
++void default_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high);
+
+ /* manager */
+ int dss_init_overlay_managers(struct platform_device *pdev);
+ void dss_uninit_overlay_managers(struct platform_device *pdev);
++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
++void dss_setup_partial_planes(struct omap_dss_device *dssdev,
++ u16 *x, u16 *y, u16 *w, u16 *h);
++void dss_start_update(struct omap_dss_device *dssdev);
+
+ /* overlay */
+ void dss_init_overlays(struct platform_device *pdev);
+@@ -233,6 +240,9 @@ int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ int dsi_pll_program(struct dsi_clock_info *cinfo);
+ int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv);
+ void dsi_pll_uninit(void);
++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
++ u32 fifo_size, enum omap_burst_size *burst_size,
++ u32 *fifo_low, u32 *fifo_high);
+
+ /* DPI */
+ int dpi_init(void);
+@@ -270,8 +280,10 @@ void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
+ void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
+ void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
+ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
++void dispc_set_channel_out(enum omap_plane plane,
++ enum omap_channel channel_out);
+
+-int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
++int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+@@ -282,6 +294,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
+ u8 rotation, bool mirror,
+ u8 global_alpha);
+
++bool dispc_go_busy(enum omap_channel channel);
+ void dispc_go(enum omap_channel channel);
+ void dispc_enable_lcd_out(bool enable);
+ void dispc_enable_digit_out(bool enable);
+@@ -320,10 +333,6 @@ int dispc_set_clock_div(struct dispc_clock_info *cinfo);
+ int dispc_get_clock_div(struct dispc_clock_info *cinfo);
+ void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
+
+-void dispc_setup_partial_planes(struct omap_dss_device *dssdev,
+- u16 *x, u16 *y, u16 *w, u16 *h);
+-void dispc_draw_partial_planes(struct omap_dss_device *dssdev);
+-
+
+ /* VENC */
+ int venc_init(struct platform_device *pdev);
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 0b0c51e..7b8e556 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -25,8 +25,11 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/jiffies.h>
+
+ #include <mach/display.h>
++#include <mach/cpu.h>
+
+ #include "dss.h"
+
+@@ -348,6 +351,106 @@ static struct kobj_type manager_ktype = {
+ .default_attrs = manager_sysfs_attrs,
+ };
+
++/*
++ * We have 4 levels of cache for the dispc settings. First two are in SW and
++ * the latter two in HW.
++ *
++ * +--------------------+
++ * |overlay/manager_info|
++ * +--------------------+
++ * v
++ * apply()
++ * v
++ * +--------------------+
++ * | dss_cache |
++ * +--------------------+
++ * v
++ * configure()
++ * v
++ * +--------------------+
++ * | shadow registers |
++ * +--------------------+
++ * v
++ * VFP or lcd/digit_enable
++ * v
++ * +--------------------+
++ * | registers |
++ * +--------------------+
++ */
++
++struct overlay_cache_data {
++ /* If true, cache changed, but not written to shadow registers. Set
++ * in apply(), cleared when registers written. */
++ bool dirty;
++ /* If true, shadow registers contain changed values not yet in real
++ * registers. Set when writing to shadow registers, cleared at
++ * VSYNC/EVSYNC */
++ bool shadow_dirty;
++
++ bool enabled;
++
++ u32 paddr;
++ void __iomem *vaddr;
++ u16 screen_width;
++ u16 width;
++ u16 height;
++ enum omap_color_mode color_mode;
++ u8 rotation;
++ enum omap_dss_rotation_type rotation_type;
++ bool mirror;
++
++ u16 pos_x;
++ u16 pos_y;
++ u16 out_width; /* if 0, out_width == width */
++ u16 out_height; /* if 0, out_height == height */
++ u8 global_alpha;
++
++ enum omap_channel channel;
++ bool replication;
++ bool ilace;
++
++ enum omap_burst_size burst_size;
++ u32 fifo_low;
++ u32 fifo_high;
++
++ bool manual_update;
++};
++
++struct manager_cache_data {
++ /* If true, cache changed, but not written to shadow registers. Set
++ * in apply(), cleared when registers written. */
++ bool dirty;
++ /* If true, shadow registers contain changed values not yet in real
++ * registers. Set when writing to shadow registers, cleared at
++ * VSYNC/EVSYNC */
++ bool shadow_dirty;
++
++ u32 default_color;
++
++ enum omap_dss_trans_key_type trans_key_type;
++ u32 trans_key;
++ bool trans_enabled;
++
++ bool alpha_enabled;
++
++ bool manual_upd_display;
++ bool manual_update;
++ bool do_manual_update;
++
++ /* manual update region */
++ u16 x, y, w, h;
++};
++
++static struct {
++ spinlock_t lock;
++ struct overlay_cache_data overlay_cache[3];
++ struct manager_cache_data manager_cache[2];
++
++ bool irq_enabled;
++} dss_cache;
++
++
++
+ static int omap_dss_set_device(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+ {
+@@ -379,6 +482,7 @@ static int omap_dss_set_device(struct omap_overlay_manager *mgr,
+
+ dssdev->manager = mgr;
+ mgr->device = dssdev;
++ mgr->device_changed = true;
+
+ return 0;
+ }
+@@ -392,154 +496,814 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
+
+ mgr->device->manager = NULL;
+ mgr->device = NULL;
++ mgr->device_changed = true;
+
+ return 0;
+ }
+
++static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ struct manager_cache_data *mc;
++ enum omap_channel channel;
++ u32 irq;
++ int r;
++ int i;
++
++ if (!mgr->device)
++ return 0;
++
++ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
++ channel = OMAP_DSS_CHANNEL_DIGIT;
++ } else {
++ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++ enum omap_dss_update_mode mode;
++ mode = mgr->device->get_update_mode(mgr->device);
++ if (mode != OMAP_DSS_UPDATE_AUTO)
++ return 0;
++
++ irq = DISPC_IRQ_FRAMEDONE;
++ } else {
++ irq = DISPC_IRQ_VSYNC;
++ }
++ channel = OMAP_DSS_CHANNEL_LCD;
++ }
++
++ mc = &dss_cache.manager_cache[mgr->id];
++ i = 0;
++ while (1) {
++ unsigned long flags;
++ bool shadow_dirty, dirty;
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++ dirty = mc->dirty;
++ shadow_dirty = mc->shadow_dirty;
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ if (!dirty && !shadow_dirty) {
++ r = 0;
++ break;
++ }
++
++ /* 4 iterations is the worst case:
++ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
++ * 2 - first VSYNC, dirty = true
++ * 3 - dirty = false, shadow_dirty = true
++ * 4 - shadow_dirty = false */
++ if (i++ == 3) {
++ DSSERR("mgr(%d)->wait_for_go() not finishing\n",
++ mgr->id);
++ r = 0;
++ break;
++ }
++
++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++ if (r == -ERESTARTSYS)
++ break;
++
++ if (r) {
++ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
++ break;
++ }
++ }
++
++ return r;
++}
++
++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
++{
++ unsigned long timeout = msecs_to_jiffies(500);
++ enum omap_channel channel;
++ struct overlay_cache_data *oc;
++ struct omap_dss_device *dssdev;
++ u32 irq;
++ int r;
++ int i;
++
++ if (!ovl->manager || !ovl->manager->device)
++ return 0;
++
++ dssdev = ovl->manager->device;
++
++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
++ channel = OMAP_DSS_CHANNEL_DIGIT;
++ } else {
++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++ enum omap_dss_update_mode mode;
++ mode = dssdev->get_update_mode(dssdev);
++ if (mode != OMAP_DSS_UPDATE_AUTO)
++ return 0;
++
++ irq = DISPC_IRQ_FRAMEDONE;
++ } else {
++ irq = DISPC_IRQ_VSYNC;
++ }
++ channel = OMAP_DSS_CHANNEL_LCD;
++ }
++
++ oc = &dss_cache.overlay_cache[ovl->id];
++ i = 0;
++ while (1) {
++ unsigned long flags;
++ bool shadow_dirty, dirty;
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++ dirty = oc->dirty;
++ shadow_dirty = oc->shadow_dirty;
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ if (!dirty && !shadow_dirty) {
++ r = 0;
++ break;
++ }
++
++ /* 4 iterations is the worst case:
++ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
++ * 2 - first VSYNC, dirty = true
++ * 3 - dirty = false, shadow_dirty = true
++ * 4 - shadow_dirty = false */
++ if (i++ == 3) {
++ DSSERR("ovl(%d)->wait_for_go() not finishing\n",
++ ovl->id);
++ r = 0;
++ break;
++ }
++
++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
++ if (r == -ERESTARTSYS)
++ break;
++
++ if (r) {
++ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
++ break;
++ }
++ }
++
++ return r;
++}
+
+ static int overlay_enabled(struct omap_overlay *ovl)
+ {
+ return ovl->info.enabled && ovl->manager && ovl->manager->device;
+ }
+
+-/* We apply settings to both managers here so that we can use optimizations
+- * like fifomerge. Shadow registers can be changed first and the non-shadowed
+- * should be changed last, at the same time with GO */
+-static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
++/* Is rect1 a subset of rect2? */
++static bool rectangle_subset(int x1, int y1, int w1, int h1,
++ int x2, int y2, int w2, int h2)
+ {
++ if (x1 < x2 || y1 < y2)
++ return false;
++
++ if (x1 + w1 > x2 + w2)
++ return false;
++
++ if (y1 + h1 > y2 + h2)
++ return false;
++
++ return true;
++}
++
++/* Do rect1 and rect2 overlap? */
++static bool rectangle_intersects(int x1, int y1, int w1, int h1,
++ int x2, int y2, int w2, int h2)
++{
++ if (x1 >= x2 + w2)
++ return false;
++
++ if (x2 >= x1 + w1)
++ return false;
++
++ if (y1 >= y2 + h2)
++ return false;
++
++ if (y2 >= y1 + h1)
++ return false;
++
++ return true;
++}
++
++static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
++{
++ if (oc->out_width != 0 && oc->width != oc->out_width)
++ return true;
++
++ if (oc->out_height != 0 && oc->height != oc->out_height)
++ return true;
++
++ return false;
++}
++
++static int configure_overlay(enum omap_plane plane)
++{
++ struct overlay_cache_data *c;
++ struct manager_cache_data *mc;
++ u16 outw, outh;
++ u16 x, y, w, h;
++ u32 paddr;
++ int r;
++
++ DSSDBGF("%d", plane);
++
++ c = &dss_cache.overlay_cache[plane];
++
++ if (!c->enabled) {
++ dispc_enable_plane(plane, 0);
++ return 0;
++ }
++
++ mc = &dss_cache.manager_cache[c->channel];
++
++ x = c->pos_x;
++ y = c->pos_y;
++ w = c->width;
++ h = c->height;
++ outw = c->out_width == 0 ? c->width : c->out_width;
++ outh = c->out_height == 0 ? c->height : c->out_height;
++ paddr = c->paddr;
++
++ if (c->manual_update && mc->do_manual_update) {
++ unsigned bpp;
++ /* If the overlay is outside the update region, disable it */
++ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
++ x, y, outw, outh)) {
++ dispc_enable_plane(plane, 0);
++ return 0;
++ }
++
++ switch (c->color_mode) {
++ case OMAP_DSS_COLOR_RGB16:
++ case OMAP_DSS_COLOR_ARGB16:
++ case OMAP_DSS_COLOR_YUV2:
++ case OMAP_DSS_COLOR_UYVY:
++ bpp = 16;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24P:
++ bpp = 24;
++ break;
++
++ case OMAP_DSS_COLOR_RGB24U:
++ case OMAP_DSS_COLOR_ARGB32:
++ case OMAP_DSS_COLOR_RGBA32:
++ case OMAP_DSS_COLOR_RGBX32:
++ bpp = 32;
++ break;
++
++ default:
++ BUG();
++ }
++
++ if (mc->x > c->pos_x) {
++ x = 0;
++ w -= (mc->x - c->pos_x);
++ paddr += (mc->x - c->pos_x) * bpp / 8;
++ } else {
++ x = c->pos_x - mc->x;
++ }
++
++ if (mc->y > c->pos_y) {
++ y = 0;
++ h -= (mc->y - c->pos_y);
++ paddr += (mc->y - c->pos_y) * c->screen_width * bpp / 8;
++ } else {
++ y = c->pos_y - mc->y;
++ }
++
++ if (mc->w < (x+w))
++ w -= (x+w) - (mc->w);
++
++ if (mc->h < (y+h))
++ h -= (y+h) - (mc->h);
++
++ if (!dispc_is_overlay_scaled(c)) {
++ outw = w;
++ outh = h;
++ }
++ }
++
++ r = dispc_setup_plane(plane,
++ paddr,
++ c->screen_width,
++ x, y,
++ w, h,
++ outw, outh,
++ c->color_mode,
++ c->ilace,
++ c->rotation_type,
++ c->rotation,
++ c->mirror,
++ c->global_alpha);
++
++ if (r) {
++ /* this shouldn't happen */
++ DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
++ dispc_enable_plane(plane, 0);
++ return r;
++ }
++
++ dispc_enable_replication(plane, c->replication);
++
++ dispc_set_burst_size(plane, c->burst_size);
++ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
++
++ dispc_enable_plane(plane, 1);
++
++ return 0;
++}
++
++static void configure_manager(enum omap_channel channel)
++{
++ struct manager_cache_data *c;
++
++ DSSDBGF("%d", channel);
++
++ c = &dss_cache.manager_cache[channel];
++
++ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
++ dispc_enable_trans_key(channel, c->trans_enabled);
++ dispc_enable_alpha_blending(channel, c->alpha_enabled);
++}
++
++/* configure_dispc() tries to write values from cache to shadow registers.
++ * It writes only to those managers/overlays that are not busy.
++ * returns 0 if everything could be written to shadow registers.
++ * returns 1 if not everything could be written to shadow registers. */
++static int configure_dispc(void)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+ int i;
+- int ret = 0;
+- enum omap_dss_update_mode mode;
+- struct omap_dss_device *dssdev;
+- struct omap_overlay *ovl;
+- bool ilace;
+- int outw, outh;
+ int r;
+- int num_planes_enabled = 0;
++ bool mgr_busy[2];
++ bool mgr_go[2];
++ bool busy;
+
+- DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
++ r = 0;
++ busy = false;
+
+- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
++ mgr_go[0] = false;
++ mgr_go[1] = false;
+
+- /* Configure normal overlay parameters and disable unused overlays */
+- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+- ovl = omap_dss_get_overlay(i);
++ /* Commit overlay settings */
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ mc = &dss_cache.manager_cache[oc->channel];
+
+- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
++ if (!oc->dirty)
+ continue;
+
+- if (!overlay_enabled(ovl)) {
+- dispc_enable_plane(ovl->id, 0);
++ if (oc->manual_update && !mc->do_manual_update)
++ continue;
++
++ if (mgr_busy[oc->channel]) {
++ busy = true;
+ continue;
+ }
+
+- dssdev = ovl->manager->device;
++ r = configure_overlay(i);
++ if (r)
++ DSSERR("configure_overlay %d failed\n", i);
+
+- if (dss_check_overlay(ovl, dssdev)) {
+- dispc_enable_plane(ovl->id, 0);
++ oc->dirty = false;
++ oc->shadow_dirty = true;
++ mgr_go[oc->channel] = true;
++ }
++
++ /* Commit manager settings */
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++
++ if (!mc->dirty)
++ continue;
++
++ if (mc->manual_update && !mc->do_manual_update)
++ continue;
++
++ if (mgr_busy[i]) {
++ busy = true;
+ continue;
+ }
+
+- ++num_planes_enabled;
++ configure_manager(i);
++ mc->dirty = false;
++ mc->shadow_dirty = true;
++ mgr_go[i] = true;
++ }
+
+- /* On a manual update display, in manual update mode, update()
+- * handles configuring planes */
+- mode = OMAP_DSS_UPDATE_AUTO;
+- if (dssdev->get_update_mode)
+- mode = dssdev->get_update_mode(dssdev);
++ /* set GO */
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
+
+- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+- mode != OMAP_DSS_UPDATE_AUTO)
++ if (!mgr_go[i])
+ continue;
+
+- ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
++ /* We don't need GO with manual update display. LCD iface will
++ * always be turned off after frame, and new settings will be
++ * taken in to use at next update */
++ if (!mc->manual_upd_display)
++ dispc_go(i);
++ }
++
++ if (busy)
++ r = 1;
++ else
++ r = 0;
++
++ return r;
++}
+
+- if (ovl->info.out_width == 0)
+- outw = ovl->info.width;
++/* Configure dispc for partial update. Return possibly modified update
++ * area */
++void dss_setup_partial_planes(struct omap_dss_device *dssdev,
++ u16 *xi, u16 *yi, u16 *wi, u16 *hi)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ struct omap_overlay_manager *mgr;
++ int i;
++ u16 x, y, w, h;
++ unsigned long flags;
++
++ x = *xi;
++ y = *yi;
++ w = *wi;
++ h = *hi;
++
++ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
++ *xi, *yi, *wi, *hi);
++
++ mgr = dssdev->manager;
++
++ if (!mgr) {
++ DSSDBG("no manager\n");
++ return;
++ }
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++
++ /* We need to show the whole overlay if it is scaled. So look for
++ * those, and make the update area larger if found.
++ * Also mark the overlay cache dirty */
++ for (i = 0; i < num_ovls; ++i) {
++ unsigned x1, y1, x2, y2;
++ unsigned outw, outh;
++
++ oc = &dss_cache.overlay_cache[i];
++
++ if (oc->channel != mgr->id)
++ continue;
++
++ oc->dirty = true;
++
++ if (!oc->enabled)
++ continue;
++
++ if (!dispc_is_overlay_scaled(oc))
++ continue;
++
++ outw = oc->out_width == 0 ? oc->width : oc->out_width;
++ outh = oc->out_height == 0 ? oc->height : oc->out_height;
++
++ /* is the overlay outside the update region? */
++ if (!rectangle_intersects(x, y, w, h,
++ oc->pos_x, oc->pos_y,
++ outw, outh))
++ continue;
++
++ /* if the overlay totally inside the update region? */
++ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
++ x, y, w, h))
++ continue;
++
++ if (x > oc->pos_x)
++ x1 = oc->pos_x;
+ else
+- outw = ovl->info.out_width;
++ x1 = x;
+
+- if (ovl->info.out_height == 0)
+- outh = ovl->info.height;
++ if (y > oc->pos_y)
++ y1 = oc->pos_y;
+ else
+- outh = ovl->info.out_height;
+-
+- r = dispc_setup_plane(ovl->id, ovl->manager->id,
+- ovl->info.paddr,
+- ovl->info.screen_width,
+- ovl->info.pos_x,
+- ovl->info.pos_y,
+- ovl->info.width,
+- ovl->info.height,
+- outw,
+- outh,
+- ovl->info.color_mode,
+- ilace,
+- ovl->info.rotation_type,
+- ovl->info.rotation,
+- ovl->info.mirror,
+- ovl->info.global_alpha);
++ y1 = y;
+
+- if (r) {
+- DSSERR("dispc_setup_plane failed for ovl %d\n",
+- ovl->id);
+- dispc_enable_plane(ovl->id, 0);
+- continue;
+- }
++ if ((x + w) < (oc->pos_x + outw))
++ x2 = oc->pos_x + outw;
++ else
++ x2 = x + w;
+
+- if (dss_use_replication(dssdev, ovl->info.color_mode))
+- dispc_enable_replication(ovl->id, true);
++ if ((y + h) < (oc->pos_y + outh))
++ y2 = oc->pos_y + outh;
+ else
+- dispc_enable_replication(ovl->id, false);
++ y2 = y + h;
++
++ x = x1;
++ y = y1;
++ w = x2 - x1;
++ h = y2 - y1;
++
++ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
++ i, x, y, w, h);
++ }
++
++ mc = &dss_cache.manager_cache[mgr->id];
++ mc->do_manual_update = true;
++ mc->x = x;
++ mc->y = y;
++ mc->w = w;
++ mc->h = h;
++
++ configure_dispc();
++
++ mc->do_manual_update = false;
++
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ *xi = x;
++ *yi = y;
++ *wi = w;
++ *hi = h;
++}
++
++void dss_start_update(struct omap_dss_device *dssdev)
++{
++ struct manager_cache_data *mc;
++ struct overlay_cache_data *oc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
++ struct omap_overlay_manager *mgr;
++ int i;
++
++ mgr = dssdev->manager;
++
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ if (oc->channel != mgr->id)
++ continue;
++
++ oc->shadow_dirty = false;
++ }
++
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++ if (mgr->id != i)
++ continue;
++
++ mc->shadow_dirty = false;
++ }
++
++ dispc_enable_lcd_out(1);
++}
++
++static void dss_apply_irq_handler(void *data, u32 mask)
++{
++ struct manager_cache_data *mc;
++ struct overlay_cache_data *oc;
++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
++ int i, r;
++ bool mgr_busy[2];
++
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
++
++ spin_lock(&dss_cache.lock);
++
++ for (i = 0; i < num_ovls; ++i) {
++ oc = &dss_cache.overlay_cache[i];
++ if (!mgr_busy[oc->channel])
++ oc->shadow_dirty = false;
++ }
++
++ for (i = 0; i < num_mgrs; ++i) {
++ mc = &dss_cache.manager_cache[i];
++ if (!mgr_busy[i])
++ mc->shadow_dirty = false;
++ }
++
++ r = configure_dispc();
++ if (r == 1)
++ goto end;
++
++ /* re-read busy flags */
++ mgr_busy[0] = dispc_go_busy(0);
++ mgr_busy[1] = dispc_go_busy(1);
+
+- dispc_enable_plane(ovl->id, 1);
++ /* keep running as long as there are busy managers, so that
++ * we can collect overlay-applied information */
++ for (i = 0; i < num_mgrs; ++i) {
++ if (mgr_busy[i])
++ goto end;
+ }
+
+- /* Enable fifo merge if possible */
+- dispc_enable_fifomerge(num_planes_enabled == 1);
++ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
++ DISPC_IRQ_EVSYNC_EVEN);
++ dss_cache.irq_enabled = false;
++
++end:
++ spin_unlock(&dss_cache.lock);
++}
++
++static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
++{
++ struct overlay_cache_data *oc;
++ struct manager_cache_data *mc;
++ int i;
++ struct omap_overlay *ovl;
++ int num_planes_enabled = 0;
++ bool use_fifomerge;
++ unsigned long flags;
++ int r;
+
+- /* Go through overlays again. This time we configure fifos. We have to
+- * do this after enabling/disabling fifomerge so that we have correct
+- * knowledge of fifo sizes */
++ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
++
++ spin_lock_irqsave(&dss_cache.lock, flags);
++
++ /* Configure overlays */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_dss_device *dssdev;
++
+ ovl = omap_dss_get_overlay(i);
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+- if (!overlay_enabled(ovl))
++ oc = &dss_cache.overlay_cache[ovl->id];
++
++ if (!overlay_enabled(ovl)) {
++ if (oc->enabled) {
++ oc->enabled = false;
++ oc->dirty = true;
++ }
++ continue;
++ }
++
++ if (!ovl->info_dirty) {
++ if (oc->enabled)
++ ++num_planes_enabled;
++ continue;
++ }
++
++ dssdev = ovl->manager->device;
++
++ if (dss_check_overlay(ovl, dssdev)) {
++ if (oc->enabled) {
++ oc->enabled = false;
++ oc->dirty = true;
++ }
+ continue;
++ }
++
++ ovl->info_dirty = false;
++ oc->dirty = true;
++
++ oc->paddr = ovl->info.paddr;
++ oc->vaddr = ovl->info.vaddr;
++ oc->screen_width = ovl->info.screen_width;
++ oc->width = ovl->info.width;
++ oc->height = ovl->info.height;
++ oc->color_mode = ovl->info.color_mode;
++ oc->rotation = ovl->info.rotation;
++ oc->rotation_type = ovl->info.rotation_type;
++ oc->mirror = ovl->info.mirror;
++ oc->pos_x = ovl->info.pos_x;
++ oc->pos_y = ovl->info.pos_y;
++ oc->out_width = ovl->info.out_width;
++ oc->out_height = ovl->info.out_height;
++ oc->global_alpha = ovl->info.global_alpha;
+
+- ovl->manager->device->configure_overlay(ovl);
++ oc->replication =
++ dss_use_replication(dssdev, ovl->info.color_mode);
++
++ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
++
++ oc->channel = ovl->manager->id;
++
++ oc->enabled = true;
++
++ oc->manual_update =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
++
++ ++num_planes_enabled;
+ }
+
+- /* Configure managers, and issue GO */
++ /* Configure managers */
+ list_for_each_entry(mgr, &manager_list, list) {
++ struct omap_dss_device *dssdev;
++
+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
+ continue;
+
++ mc = &dss_cache.manager_cache[mgr->id];
++
++ if (mgr->device_changed) {
++ mgr->device_changed = false;
++ mgr->info_dirty = true;
++ }
++
++ if (!mgr->info_dirty)
++ continue;
++
++ if (!mgr->device)
++ continue;
++
+ dssdev = mgr->device;
+
+- if (!dssdev)
++ mgr->info_dirty = false;
++ mc->dirty = true;
++
++ mc->default_color = mgr->info.default_color;
++ mc->trans_key_type = mgr->info.trans_key_type;
++ mc->trans_key = mgr->info.trans_key;
++ mc->trans_enabled = mgr->info.trans_enabled;
++ mc->alpha_enabled = mgr->info.alpha_enabled;
++
++ mc->manual_upd_display =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
++
++ mc->manual_update =
++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
++ }
++
++ /* XXX TODO: Try to get fifomerge working. The problem is that it
++ * affects both managers, not individually but at the same time. This
++ * means the change has to be well synchronized. I guess the proper way
++ * is to have a two step process for fifo merge:
++ * fifomerge enable:
++ * 1. disable other planes, leaving one plane enabled
++ * 2. wait until the planes are disabled on HW
++ * 3. config merged fifo thresholds, enable fifomerge
++ * fifomerge disable:
++ * 1. config unmerged fifo thresholds, disable fifomerge
++ * 2. wait until fifo changes are in HW
++ * 3. enable planes
++ */
++ use_fifomerge = false;
++
++ /* Configure overlay fifos */
++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
++ struct omap_dss_device *dssdev;
++ u32 size;
++
++ ovl = omap_dss_get_overlay(i);
++
++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ continue;
+
+- dispc_set_trans_key(mgr->id, mgr->info.trans_key_type,
+- mgr->info.trans_key);
+- dispc_enable_trans_key(mgr->id, mgr->info.trans_enabled);
+- dispc_enable_alpha_blending(mgr->id, mgr->info.alpha_enabled);
++ oc = &dss_cache.overlay_cache[ovl->id];
+
+- /* We don't need GO with manual update display. LCD iface will
+- * always be turned off after frame, and new settings will
+- * be taken in to use at next update */
+- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
++ if (!oc->enabled)
+ continue;
+
+- dispc_go(mgr->id);
++ dssdev = ovl->manager->device;
++
++ size = dispc_get_plane_fifo_size(ovl->id);
++ if (use_fifomerge)
++ size *= 3;
++
++ switch (dssdev->type) {
++ case OMAP_DISPLAY_TYPE_DPI:
++ case OMAP_DISPLAY_TYPE_DBI:
++ case OMAP_DISPLAY_TYPE_SDI:
++ case OMAP_DISPLAY_TYPE_VENC:
++ default_get_overlay_fifo_thresholds(ovl->id, size,
++ &oc->burst_size, &oc->fifo_low,
++ &oc->fifo_high);
++ break;
++#ifdef CONFIG_OMAP2_DSS_DSI
++ case OMAP_DISPLAY_TYPE_DSI:
++ dsi_get_overlay_fifo_thresholds(ovl->id, size,
++ &oc->burst_size, &oc->fifo_low,
++ &oc->fifo_high);
++ break;
++#endif
++ default:
++ BUG();
++ }
+ }
+
++ r = 0;
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ if (!dss_cache.irq_enabled) {
++ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
++ DISPC_IRQ_EVSYNC_EVEN);
++ dss_cache.irq_enabled = true;
++ }
++ configure_dispc();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+
+- return ret;
++ spin_unlock_irqrestore(&dss_cache.lock, flags);
++
++ return r;
+ }
+
+ static int dss_check_manager(struct omap_overlay_manager *mgr)
+@@ -569,6 +1333,8 @@ static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
+ return r;
+ }
+
++ mgr->info_dirty = true;
++
+ return 0;
+ }
+
+@@ -588,6 +1354,8 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ {
+ int i, r;
+
++ spin_lock_init(&dss_cache.lock);
++
+ INIT_LIST_HEAD(&manager_list);
+
+ num_managers = 0;
+@@ -618,6 +1386,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
+ mgr->apply = &omap_dss_mgr_apply;
+ mgr->set_manager_info = &omap_dss_mgr_set_info;
+ mgr->get_manager_info = &omap_dss_mgr_get_info;
++ mgr->wait_for_go = &dss_mgr_wait_for_go;
+
+ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index 9f883aa..3652106 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -52,6 +52,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+ {
+ int i, r;
+ struct omap_overlay_manager *mgr = NULL;
++ struct omap_overlay_manager *old_mgr;
+ int len = size;
+
+ if (buf[size-1] == '\n')
+@@ -74,27 +75,32 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+ if (mgr)
+ DSSDBG("manager %s found\n", mgr->name);
+
+- if (mgr != ovl->manager) {
+- /* detach old manager */
+- if (ovl->manager) {
+- r = ovl->unset_manager(ovl);
+- if (r) {
+- DSSERR("detach failed\n");
+- return r;
+- }
+- }
++ if (mgr == ovl->manager)
++ return size;
+
+- if (mgr) {
+- r = ovl->set_manager(ovl, mgr);
+- if (r) {
+- DSSERR("Failed to attach overlay\n");
+- return r;
+- }
++ old_mgr = ovl->manager;
++
++ /* detach old manager */
++ if (old_mgr) {
++ r = ovl->unset_manager(ovl);
++ if (r) {
++ DSSERR("detach failed\n");
++ return r;
+ }
++
++ r = old_mgr->apply(old_mgr);
++ if (r)
++ return r;
+ }
+
+- if (ovl->manager) {
+- r = ovl->manager->apply(ovl->manager);
++ if (mgr) {
++ r = ovl->set_manager(ovl, mgr);
++ if (r) {
++ DSSERR("Failed to attach overlay\n");
++ return r;
++ }
++
++ r = mgr->apply(mgr);
+ if (r)
+ return r;
+ }
+@@ -403,6 +409,8 @@ static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
+ }
+ }
+
++ ovl->info_dirty = true;
++
+ return 0;
+ }
+
+@@ -412,22 +420,40 @@ static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
+ *info = ovl->info;
+ }
+
++static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
++{
++ return dss_mgr_wait_for_go_ovl(ovl);
++}
++
+ static int omap_dss_set_manager(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr)
+ {
+ int r;
+
++ if (!mgr)
++ return -EINVAL;
++
+ if (ovl->manager) {
+ DSSERR("overlay '%s' already has a manager '%s'\n",
+ ovl->name, ovl->manager->name);
++ return -EINVAL;
+ }
+
+- r = dss_check_overlay(ovl, mgr->device);
++ r = ovl->wait_for_go(ovl);
+ if (r)
+ return r;
+
++ if (ovl->info.enabled) {
++ DSSERR("overlay has to be disabled to change the manager\n");
++ return -EINVAL;
++ }
++
+ ovl->manager = mgr;
+
++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
++ dispc_set_channel_out(ovl->id, mgr->id);
++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
++
+ return 0;
+ }
+
+@@ -439,6 +465,7 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
+ }
+
+ ovl->manager = NULL;
++ /* XXX disable overlay? */
+
+ return 0;
+ }
+@@ -530,6 +557,7 @@ void dss_init_overlays(struct platform_device *pdev)
+ ovl->unset_manager = &omap_dss_unset_manager;
+ ovl->set_overlay_info = &dss_ovl_set_overlay_info;
+ ovl->get_overlay_info = &dss_ovl_get_overlay_info;
++ ovl->wait_for_go = &dss_ovl_wait_for_go;
+
+ omap_dss_add_overlay(ovl);
+
+diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
+index 96602ae..9dd2349 100644
+--- a/drivers/video/omap2/dss/rfbi.c
++++ b/drivers/video/omap2/dss/rfbi.c
+@@ -972,7 +972,7 @@ static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
+
+ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+ /*dssdev->driver->enable_te(dssdev, 1); */
+- dispc_setup_partial_planes(dssdev, &x, &y, &w, &h);
++ dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
+ }
+
+ #ifdef MEASURE_PERF
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index d8a83b2..a9a5a8c 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -711,6 +711,15 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+ return 0;
+ }
+
++static enum omap_dss_update_mode venc_display_get_update_mode(
++ struct omap_dss_device *dssdev)
++{
++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
++ return OMAP_DSS_UPDATE_AUTO;
++ else
++ return OMAP_DSS_UPDATE_DISABLED;
++}
++
+ int venc_init_display(struct omap_dss_device *dssdev)
+ {
+ DSSDBG("init_display\n");
+@@ -724,6 +733,7 @@ int venc_init_display(struct omap_dss_device *dssdev)
+ dssdev->check_timings = venc_check_timings;
+ dssdev->get_wss = venc_get_wss;
+ dssdev->set_wss = venc_set_wss;
++ dssdev->get_update_mode = venc_display_get_update_mode;
+
+ return 0;
+ }
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 91308c2..257f7cb 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -442,6 +442,22 @@ static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
+ return 0;
+ }
+
++static int omapfb_wait_for_go(struct fb_info *fbi)
++{
++ struct omapfb_info *ofbi = FB2OFB(fbi);
++ int r = 0;
++ int i;
++
++ for (i = 0; i < ofbi->num_overlays; ++i) {
++ struct omap_overlay *ovl = ofbi->overlays[i];
++ r = ovl->wait_for_go(ovl);
++ if (r)
++ break;
++ }
++
++ return r;
++}
++
+ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ {
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+@@ -624,6 +640,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ r = display->wait_vsync(display);
+ break;
+
++ case OMAPFB_WAITFORGO:
++ DBG("ioctl WAITFORGO\n");
++ if (!display) {
++ r = -EINVAL;
++ break;
++ }
++
++ r = omapfb_wait_for_go(fbi);
++ break;
++
+ /* LCD and CTRL tests do the same thing for backward
+ * compatibility */
+ case OMAPFB_LCD_TEST:
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index fd522d3..5014d2e 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -55,6 +55,7 @@
+ #define OMAPFB_WAITFORVSYNC OMAP_IO(57)
+ #define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
+ #define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
++#define OMAPFB_WAITFORGO OMAP_IO(60)
+
+ #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+ #define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0121-DSS2-VRFB-clean-up-BUG-calls.patch b/recipes/linux/linux-omap-pm/dss2/0121-DSS2-VRFB-clean-up-BUG-calls.patch
new file mode 100644
index 0000000000..fe988632be
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0121-DSS2-VRFB-clean-up-BUG-calls.patch
@@ -0,0 +1,70 @@
+From 1011922e3dd0c5f0f375fef28caa7222f68d4601 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 16 Jun 2009 17:14:03 +0300
+Subject: [PATCH 121/146] DSS2: VRFB: clean up BUG() calls
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/vrfb.c | 25 ++++++++++---------------
+ 1 files changed, 10 insertions(+), 15 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 7cd7c61..201640a 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -121,7 +121,6 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+
+ default:
+ BUG();
+- return;
+ }
+
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+@@ -176,10 +175,8 @@ void omap_vrfb_release_ctx(struct vrfb *vrfb)
+
+ mutex_lock(&ctx_lock);
+
+- if (!(ctx_map & (1 << ctx))) {
+- BUG();
+- return;
+- }
++ BUG_ON(!(ctx_map & (1 << ctx)));
++
+ clear_bit(ctx, &ctx_map_active);
+ clear_bit(ctx, &ctx_map);
+
+@@ -254,11 +251,10 @@ void omap_vrfb_suspend_ctx(struct vrfb *vrfb)
+ {
+ DBG("suspend ctx %d\n", vrfb->context);
+ mutex_lock(&ctx_lock);
+- if (vrfb->context >= VRFB_NUM_CTXS ||
+- (!(1 << vrfb->context) & ctx_map_active)) {
+- BUG();
+- return;
+- }
++
++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
++ BUG_ON(!((1 << vrfb->context) & ctx_map_active));
++
+ clear_bit(vrfb->context, &ctx_map_active);
+ mutex_unlock(&ctx_lock);
+ }
+@@ -268,11 +264,10 @@ void omap_vrfb_resume_ctx(struct vrfb *vrfb)
+ {
+ DBG("resume ctx %d\n", vrfb->context);
+ mutex_lock(&ctx_lock);
+- if (vrfb->context >= VRFB_NUM_CTXS ||
+- ((1 << vrfb->context) & ctx_map_active)) {
+- BUG();
+- return;
+- }
++
++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS);
++ BUG_ON((1 << vrfb->context) & ctx_map_active);
++
+ /*
+ * omap_vrfb_restore_context is normally called by the core domain
+ * save / restore logic, but since this VRFB context was suspended
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0122-DSS2-OMAPFB-don-t-fail-even-if-default-display-doe.patch b/recipes/linux/linux-omap-pm/dss2/0122-DSS2-OMAPFB-don-t-fail-even-if-default-display-doe.patch
new file mode 100644
index 0000000000..1438deac19
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0122-DSS2-OMAPFB-don-t-fail-even-if-default-display-doe.patch
@@ -0,0 +1,139 @@
+From 9abe23c8bc711a0883dfe8fd73371e35f48dddf0 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 23 Jun 2009 11:55:52 +0300
+Subject: [PATCH 122/146] DSS2: OMAPFB: don't fail even if default display doesn't start
+
+This will allow secondary displays to be used even if the
+main display is out of order.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-main.c | 91 ++++++++++++------------------
+ 1 files changed, 37 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 1473581..b806dc9 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1994,21 +1994,9 @@ static int omapfb_probe(struct platform_device *pdev)
+ for (i = 0; i < fbdev->num_managers; i++)
+ fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+
+-
+- /* gfx overlay should be the default one. find a display
+- * connected to that, and use it as default display */
+- ovl = omap_dss_get_overlay(0);
+- if (ovl->manager && ovl->manager->device) {
+- def_display = ovl->manager->device;
+- } else {
+- dev_err(&pdev->dev, "cannot find default display\n");
+- r = -EINVAL;
+- goto cleanup;
+- }
+-
+ if (def_mode && strlen(def_mode) > 0) {
+ if (omapfb_parse_def_modes(fbdev))
+- dev_err(&pdev->dev, "cannot parse default modes\n");
++ dev_warn(&pdev->dev, "cannot parse default modes\n");
+ }
+
+ r = omapfb_create_framebuffers(fbdev);
+@@ -2019,59 +2007,54 @@ static int omapfb_probe(struct platform_device *pdev)
+ struct omap_overlay_manager *mgr;
+ mgr = fbdev->managers[i];
+ r = mgr->apply(mgr);
+- if (r) {
+- dev_err(fbdev->dev, "failed to apply dispc config\n");
+- goto cleanup;
+- }
++ if (r)
++ dev_warn(fbdev->dev, "failed to apply dispc config\n");
+ }
+
+ DBG("mgr->apply'ed\n");
+
+- r = def_display->enable(def_display);
+- if (r) {
+- dev_err(fbdev->dev, "Failed to enable display '%s'\n",
+- def_display->name);
+- goto cleanup;
+- }
+-
+- /* set the update mode */
+- if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+-#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
+- if (def_display->enable_te)
+- def_display->enable_te(def_display, 1);
+- if (def_display->set_update_mode)
+- def_display->set_update_mode(def_display,
+- OMAP_DSS_UPDATE_AUTO);
+-#else
+- if (def_display->enable_te)
+- def_display->enable_te(def_display, 0);
+- if (def_display->set_update_mode)
+- def_display->set_update_mode(def_display,
+- OMAP_DSS_UPDATE_MANUAL);
+-#endif
++ /* gfx overlay should be the default one. find a display
++ * connected to that, and use it as default display */
++ ovl = omap_dss_get_overlay(0);
++ if (ovl->manager && ovl->manager->device) {
++ def_display = ovl->manager->device;
+ } else {
+- if (def_display->set_update_mode)
+- def_display->set_update_mode(def_display,
+- OMAP_DSS_UPDATE_AUTO);
++ dev_warn(&pdev->dev, "cannot find default display\n");
++ def_display = NULL;
+ }
+
+- for (i = 0; i < fbdev->num_displays; i++) {
+- struct omap_dss_device *display = fbdev->displays[i];
++ if (def_display) {
+ u16 w, h;
++ r = def_display->enable(def_display);
++ if (r)
++ dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
++ def_display->name);
+
+- if (!display->get_update_mode || !display->update)
+- continue;
+-
+- if (display->get_update_mode(display) ==
+- OMAP_DSS_UPDATE_MANUAL) {
+-
+- display->get_resolution(display, &w, &h);
+- display->update(display, 0, 0, w, h);
++ /* set the update mode */
++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 1);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
++#else /* MANUAL_UPDATE */
++ if (def_display->enable_te)
++ def_display->enable_te(def_display, 0);
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_MANUAL);
++
++ def_display->get_resolution(def_display, &w, &h);
++ def_display->update(def_display, 0, 0, w, h);
++#endif
++ } else {
++ if (def_display->set_update_mode)
++ def_display->set_update_mode(def_display,
++ OMAP_DSS_UPDATE_AUTO);
+ }
+ }
+
+- DBG("display->updated\n");
+-
+ return 0;
+
+ cleanup:
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0123-DSS2-DSI-Fix-external-TE-wait.patch b/recipes/linux/linux-omap-pm/dss2/0123-DSS2-DSI-Fix-external-TE-wait.patch
new file mode 100644
index 0000000000..1860c63160
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0123-DSS2-DSI-Fix-external-TE-wait.patch
@@ -0,0 +1,41 @@
+From 063a0c3e0e45a9de3d12811885463565655cbfde Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 26 Jun 2009 11:53:21 +0300
+Subject: [PATCH 123/146] DSS2: DSI: Fix external TE wait
+
+---
+ arch/arm/plat-omap/include/mach/display.h | 1 -
+ drivers/video/omap2/dss/dsi.c | 5 +++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index be07c35..92603eb 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -453,7 +453,6 @@ struct omap_dss_device {
+
+ int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
+ int (*get_te)(struct omap_dss_device *dssdev);
+- int (*wait_for_te)(struct omap_dss_device *dssdev);
+
+ u8 (*get_rotate)(struct omap_dss_device *dssdev);
+ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 875be0c..f3553f8 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2775,8 +2775,9 @@ static int dsi_update_thread(void *data)
+ device->driver->setup_update(device, x, y, w, h);
+ #endif
+
+- if (dsi.te_enabled && dsi.use_ext_te && device->wait_for_te)
+- device->wait_for_te(device);
++ if (dsi.te_enabled && dsi.use_ext_te &&
++ device->driver->wait_for_te)
++ device->driver->wait_for_te(device);
+
+ dsi_perf_mark_start();
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0124-DSS2-DSI-Increase-framedone-timeout-to-1s.patch b/recipes/linux/linux-omap-pm/dss2/0124-DSS2-DSI-Increase-framedone-timeout-to-1s.patch
new file mode 100644
index 0000000000..99e76dfc9e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0124-DSS2-DSI-Increase-framedone-timeout-to-1s.patch
@@ -0,0 +1,28 @@
+From 57da7b3252f9cbcf8ba536a6bde7a92937b5d7c8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 26 Jun 2009 14:50:47 +0300
+Subject: [PATCH 124/146] DSS2: DSI: Increase framedone timeout to 1s
+
+It seems that with heavy CPU load it may take more time
+until the work thread wakes up. I was unable to increase
+the priority so that the thread would wake up earlier.
+---
+ drivers/video/omap2/dss/dsi.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index f3553f8..97a67e5 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -2785,7 +2785,7 @@ static int dsi_update_thread(void *data)
+ dsi_update_screen_dispc(device, x, y, w, h);
+
+ /* wait for framedone */
+- timeout = msecs_to_jiffies(500);
++ timeout = msecs_to_jiffies(1000);
+ timeout = wait_event_timeout(dsi.waitqueue,
+ dsi.framedone_received == true,
+ timeout);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0125-DSS2-VRAM-Add-function-to-get-free-vram-info.patch b/recipes/linux/linux-omap-pm/dss2/0125-DSS2-VRAM-Add-function-to-get-free-vram-info.patch
new file mode 100644
index 0000000000..d3d62ce7a2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0125-DSS2-VRAM-Add-function-to-get-free-vram-info.patch
@@ -0,0 +1,76 @@
+From 0d16c11a3df3e09cb8ba20883174f600ac3611b5 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 24 Jun 2009 14:55:54 +0300
+Subject: [PATCH 125/146] DSS2: VRAM: Add function to get free vram info
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vram.h | 2 +
+ arch/arm/plat-omap/vram.c | 38 ++++++++++++++++++++++++++++++++
+ 2 files changed, 40 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index 8639e08..494ddde 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -28,6 +28,8 @@ extern int omap_vram_add_region(unsigned long paddr, size_t size);
+ extern int omap_vram_free(unsigned long paddr, size_t size);
+ extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+ extern int omap_vram_reserve(unsigned long paddr, size_t size);
++extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
++ unsigned long *largest_free_block);
+ extern void omap2_set_sdram_vram(u32 size, u32 start);
+ extern void omap2_set_sram_vram(u32 size, u32 start);
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index f3ce849..d4a8110 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -398,6 +398,44 @@ int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
+ }
+ EXPORT_SYMBOL(omap_vram_alloc);
+
++void omap_vram_get_info(unsigned long *vram,
++ unsigned long *free_vram,
++ unsigned long *largest_free_block)
++{
++ struct vram_region *vr;
++ struct vram_alloc *va;
++
++ *vram = 0;
++ *free_vram = 0;
++ *largest_free_block = 0;
++
++ mutex_lock(&region_mutex);
++
++ list_for_each_entry(vr, &region_list, list) {
++ unsigned free;
++ unsigned long pa;
++
++ pa = vr->paddr;
++ *vram += vr->pages << PAGE_SHIFT;
++
++ list_for_each_entry(va, &vr->alloc_list, list) {
++ free = va->paddr - pa;
++ *free_vram += free;
++ if (free > *largest_free_block)
++ *largest_free_block = free;
++ pa = va->paddr + (va->pages << PAGE_SHIFT);
++ }
++
++ free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
++ *free_vram += free;
++ if (free > *largest_free_block)
++ *largest_free_block = free;
++ }
++
++ mutex_unlock(&region_mutex);
++}
++EXPORT_SYMBOL(omap_vram_get_info);
++
+ #if defined(CONFIG_DEBUG_FS)
+ static int vram_debug_show(struct seq_file *s, void *unused)
+ {
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0126-DSS2-OMAPFB-implement-OMAPFB_GET_VRAM_INFO-ioctl.patch b/recipes/linux/linux-omap-pm/dss2/0126-DSS2-OMAPFB-implement-OMAPFB_GET_VRAM_INFO-ioctl.patch
new file mode 100644
index 0000000000..287a82cb81
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0126-DSS2-OMAPFB-implement-OMAPFB_GET_VRAM_INFO-ioctl.patch
@@ -0,0 +1,86 @@
+From fbc4a50eafe5d5023ef1c0a32d362c2166946164 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 24 Jun 2009 14:56:29 +0300
+Subject: [PATCH 126/146] DSS2: OMAPFB: implement OMAPFB_GET_VRAM_INFO ioctl
+
+This ioctl can be used to guess how big buffers it is possible to
+reserve.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/omapfb/omapfb-ioctl.c | 18 ++++++++++++++++++
+ include/linux/omapfb.h | 8 ++++++++
+ 2 files changed, 26 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+index 257f7cb..70fb64e 100644
+--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
+@@ -30,6 +30,7 @@
+
+ #include <mach/display.h>
+ #include <mach/vrfb.h>
++#include <mach/vram.h>
+
+ #include "omapfb.h"
+
+@@ -475,6 +476,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+ enum omapfb_update_mode update_mode;
+ int test_num;
+ struct omapfb_memory_read memory_read;
++ struct omapfb_vram_info vram_info;
+ } p;
+
+ int r = 0;
+@@ -695,6 +697,22 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+
+ break;
+
++ case OMAPFB_GET_VRAM_INFO: {
++ unsigned long vram, free, largest;
++
++ DBG("ioctl GET_VRAM_INFO\n");
++
++ omap_vram_get_info(&vram, &free, &largest);
++ p.vram_info.total = vram;
++ p.vram_info.free = free;
++ p.vram_info.largest_free_block = largest;
++
++ if (copy_to_user((void __user *)arg, &p.vram_info,
++ sizeof(p.vram_info)))
++ r = -EFAULT;
++ break;
++ }
++
+ default:
+ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
+ r = -EINVAL;
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index 5014d2e..0df0df9 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -56,6 +56,7 @@
+ #define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read)
+ #define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode)
+ #define OMAPFB_WAITFORGO OMAP_IO(60)
++#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info)
+
+ #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
+ #define OMAPFB_CAPS_LCDC_MASK 0x00fff000
+@@ -194,6 +195,13 @@ struct omapfb_ovl_colormode {
+ struct fb_bitfield transp;
+ };
+
++struct omapfb_vram_info {
++ __u32 total;
++ __u32 free;
++ __u32 largest_free_block;
++ __u32 reserved[5];
++};
++
+ #ifdef __KERNEL__
+
+ #include <linux/completion.h>
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0127-DSS2-DSI-increase-dsi-thread-priority.patch b/recipes/linux/linux-omap-pm/dss2/0127-DSS2-DSI-increase-dsi-thread-priority.patch
new file mode 100644
index 0000000000..213b846c85
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0127-DSS2-DSI-increase-dsi-thread-priority.patch
@@ -0,0 +1,37 @@
+From e847a1241c2707453701d5b680fafbb2ce2ae1d8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 26 Jun 2009 15:22:37 +0300
+Subject: [PATCH 127/146] DSS2: DSI: increase dsi thread priority
+
+This should help keep the framerates up even if there's
+lots of CPU load.
+---
+ drivers/video/omap2/dss/dsi.c | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 97a67e5..d2c5b94 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -3418,6 +3418,9 @@ int dsi_init_display(struct omap_dss_device *dssdev)
+ int dsi_init(struct platform_device *pdev)
+ {
+ u32 rev;
++ struct sched_param param = {
++ .sched_priority = MAX_USER_RT_PRIO-1
++ };
+
+ spin_lock_init(&dsi.errors_lock);
+ dsi.errors = 0;
+@@ -3432,6 +3435,8 @@ int dsi_init(struct platform_device *pdev)
+ DSSERR("cannot create kthread\n");
+ return PTR_ERR(dsi.thread);
+ }
++ sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
++
+ init_waitqueue_head(&dsi.waitqueue);
+ spin_lock_init(&dsi.update_lock);
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0128-DSS2-DSI-check-bus_lock-in-send_bta.patch b/recipes/linux/linux-omap-pm/dss2/0128-DSS2-DSI-check-bus_lock-in-send_bta.patch
new file mode 100644
index 0000000000..c12c712dbf
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0128-DSS2-DSI-check-bus_lock-in-send_bta.patch
@@ -0,0 +1,28 @@
+From 57cf924ba722d0ef7f48b4a0f8a44a0ddeefc470 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 26 Jun 2009 17:14:25 +0300
+Subject: [PATCH 128/146] DSS2: DSI: check bus_lock in send_bta()
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index d2c5b94..3b15684 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1786,7 +1786,9 @@ static int dsi_vc_send_bta(int channel)
+ {
+ unsigned long tmo;
+
+- /*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */
++ DSSDBG("dsi_vc_send_bta %d\n", channel);
++
++ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
+ DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0129-DSS2-DSI-export-dsi_vc_send_bta_sync.patch b/recipes/linux/linux-omap-pm/dss2/0129-DSS2-DSI-export-dsi_vc_send_bta_sync.patch
new file mode 100644
index 0000000000..8e72043652
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0129-DSS2-DSI-export-dsi_vc_send_bta_sync.patch
@@ -0,0 +1,47 @@
+From b3624e06210fe8f8306f4794a0e1059f25a7e74d Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Mon, 29 Jun 2009 14:38:58 +0300
+Subject: [PATCH 129/146] DSS2: DSI: export dsi_vc_send_bta_sync()
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/dsi.c | 3 ++-
+ 2 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 92603eb..6df28dc 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -212,6 +212,7 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
+ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
+ int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
+ int dsi_vc_send_null(int channel);
++int dsi_vc_send_bta_sync(int channel);
+
+ /* Board specific data */
+ struct omap_dss_board_info {
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 3b15684..1e18fdf 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -1808,7 +1808,7 @@ static int dsi_vc_send_bta(int channel)
+ return 0;
+ }
+
+-static int dsi_vc_send_bta_sync(int channel)
++int dsi_vc_send_bta_sync(int channel)
+ {
+ int r = 0;
+ u32 err;
+@@ -1839,6 +1839,7 @@ err:
+
+ return r;
+ }
++EXPORT_SYMBOL(dsi_vc_send_bta_sync);
+
+ static inline void dsi_vc_write_long_header(int channel, u8 data_type,
+ u16 len, u8 ecc)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0130-DSS2-DSI-clear-BTA-irq-before-enabling-it.patch b/recipes/linux/linux-omap-pm/dss2/0130-DSS2-DSI-clear-BTA-irq-before-enabling-it.patch
new file mode 100644
index 0000000000..5d0c557150
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0130-DSS2-DSI-clear-BTA-irq-before-enabling-it.patch
@@ -0,0 +1,26 @@
+From 852518e23aafed505a8432a3105d8045bf51a3f2 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 30 Jun 2009 11:39:30 +0300
+Subject: [PATCH 130/146] DSS2: DSI: clear BTA irq before enabling it
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 1e18fdf..45df3f7 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -616,6 +616,8 @@ static void dsi_vc_enable_bta_irq(int channel)
+ {
+ u32 l;
+
++ dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
++
+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+ l |= DSI_VC_IRQ_BTA;
+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0131-DSS2-DSI-check-dsi_set_te-return-value.patch b/recipes/linux/linux-omap-pm/dss2/0131-DSS2-DSI-check-dsi_set_te-return-value.patch
new file mode 100644
index 0000000000..b462d59310
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0131-DSS2-DSI-check-dsi_set_te-return-value.patch
@@ -0,0 +1,62 @@
+From b46425082619fb329b56f7628ee5c196d7301bd3 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 30 Jun 2009 11:43:56 +0300
+Subject: [PATCH 131/146] DSS2: DSI: check dsi_set_te() return value
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 14 ++++++++++----
+ 1 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 45df3f7..03cf2d6 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -3003,7 +3003,9 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ dsi.use_ext_te = dssdev->phy.dsi.ext_te;
+- dsi_set_te(dssdev, dsi.te_enabled);
++ r = dsi_set_te(dssdev, dsi.te_enabled);
++ if (r)
++ goto err3;
+
+ dsi.update_mode = dsi.user_update_mode;
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+@@ -3116,7 +3118,9 @@ static int dsi_display_resume(struct omap_dss_device *dssdev)
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+- dsi_set_te(dssdev, dsi.te_enabled);
++ r = dsi_set_te(dssdev, dsi.te_enabled);
++ if (r)
++ goto err2;
+
+ dsi.update_mode = dsi.user_update_mode;
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+@@ -3238,6 +3242,8 @@ static enum omap_dss_update_mode dsi_display_get_update_mode(
+
+ static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ {
++ int r = 0;
++
+ DSSDBGF("%d", enable);
+
+ if (!dssdev->driver->enable_te)
+@@ -3250,11 +3256,11 @@ static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ goto end;
+
+- dsi_set_te(dssdev, enable);
++ r = dsi_set_te(dssdev, enable);
+ end:
+ dsi_bus_unlock();
+
+- return 0;
++ return r;
+ }
+
+ static int dsi_display_get_te(struct omap_dss_device *dssdev)
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch b/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch
new file mode 100644
index 0000000000..c01c2520ec
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch
@@ -0,0 +1,406 @@
+From 29cb3408c094bacd42d8bb17cbafb6f1c57f6cc8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Tue, 30 Jun 2009 11:47:38 +0300
+Subject: [PATCH 132/146] DSS2: DSI: use only 1 VC. Fixes to TE.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ drivers/video/omap2/dss/dsi.c | 197 +++++++++++++++++++++++++---------------
+ 1 files changed, 123 insertions(+), 74 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
+index 03cf2d6..becaf64 100644
+--- a/drivers/video/omap2/dss/dsi.c
++++ b/drivers/video/omap2/dss/dsi.c
+@@ -192,6 +192,11 @@ enum fifo_size {
+ DSI_FIFO_SIZE_128 = 4,
+ };
+
++enum dsi_vc_mode {
++ DSI_VC_MODE_L4 = 0,
++ DSI_VC_MODE_VP,
++};
++
+ struct dsi_update_region {
+ bool dirty;
+ u16 x, y, w, h;
+@@ -210,6 +215,7 @@ static struct
+ struct regulator *vdds_dsi_reg;
+
+ struct {
++ enum dsi_vc_mode mode;
+ struct omap_dss_device *dssdev;
+ enum fifo_size fifo_size;
+ int dest_per; /* destination peripheral 0-3 */
+@@ -1629,14 +1635,36 @@ static void dsi_vc_print_status(int channel)
+ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
+ }
+
+-static void dsi_vc_config(int channel)
++static int dsi_vc_enable(int channel, bool enable)
++{
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBG("dsi_vc_enable channel %d, enable %d\n",
++ channel, enable);
++
++ enable = enable ? 1 : 0;
++
++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
++
++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void dsi_vc_initial_config(int channel)
+ {
+ u32 r;
+
+- DSSDBG("dsi_vc_config %d\n", channel);
++ DSSDBGF("%d", channel);
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+
++ if (FLD_GET(r, 15, 15)) /* VC_BUSY */
++ DSSERR("VC(%d) busy when trying to configure it!\n",
++ channel);
++
+ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+@@ -1649,47 +1677,51 @@ static void dsi_vc_config(int channel)
+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+ dsi_write_reg(DSI_VC_CTRL(channel), r);
++
++ dsi.vc[channel].mode = DSI_VC_MODE_L4;
+ }
+
+-static void dsi_vc_config_vp(int channel)
++static void dsi_vc_config_l4(int channel)
+ {
+- u32 r;
++ if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
++ return;
+
+- DSSDBG("dsi_vc_config_vp\n");
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBGF("%d", channel);
+
+- r = dsi_read_reg(DSI_VC_CTRL(channel));
++ dsi_vc_enable(channel, 0);
+
+- r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */
+- r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+- r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+- r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+- r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+- r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+- r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */
++ if(REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
++ DSSERR("vc(%d) busy when trying to config for L4\n", channel);
+
+- r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+- r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
+
+- dsi_write_reg(DSI_VC_CTRL(channel), r);
+-}
++ dsi_vc_enable(channel, 1);
+
++ dsi.vc[channel].mode = DSI_VC_MODE_L4;
++}
+
+-static int dsi_vc_enable(int channel, bool enable)
++static void dsi_vc_config_vp(int channel)
+ {
+- DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable);
++ if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
++ return;
+
+- enable = enable ? 1 : 0;
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
++ DSSDBGF("%d", channel);
+
+- REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
++ dsi_vc_enable(channel, 0);
+
+- if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
+- DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
+- return -EIO;
+- }
++ if(REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
++ DSSERR("vc(%d) busy when trying to config for VP\n", channel);
+
+- return 0;
++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
++
++ dsi_vc_enable(channel, 1);
++
++ dsi.vc[channel].mode = DSI_VC_MODE_VP;
+ }
+
++
+ static void dsi_vc_enable_hs(int channel, bool enable)
+ {
+ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
+@@ -1788,7 +1820,9 @@ static int dsi_vc_send_bta(int channel)
+ {
+ unsigned long tmo;
+
+- DSSDBG("dsi_vc_send_bta %d\n", channel);
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
++ (dsi.debug_write || dsi.debug_read))
++ DSSDBG("dsi_vc_send_bta %d\n", channel);
+
+ WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+@@ -1976,6 +2010,12 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
+
+ BUG_ON(len == 0);
+
++ if (REG_GET(DSI_VC_CTRL(channel), 1, 1) != 0) {
++ DSSERR("vc(%d) not in L4 mode when trying to write\n",
++ channel);
++ return -EIO;
++ }
++
+ if (len == 1) {
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
+ data[0], 0);
+@@ -2000,9 +2040,6 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len)
+ if (r)
+ return r;
+
+- /* Some devices need time to process the msg in low power mode.
+- This also makes the write synchronous, and checks that
+- the peripheral is still alive */
+ r = dsi_vc_send_bta_sync(channel);
+
+ return r;
+@@ -2016,7 +2053,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
+ int r;
+
+ if (dsi.debug_read)
+- DSSDBG("dsi_vc_dcs_read\n");
++ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd);
+
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
+ if (r)
+@@ -2291,10 +2328,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
+
+ dsi_write_reg(DSI_CTRL, r);
+
+- /* we configure vc0 for L4 communication, and
+- * vc1 for dispc */
+- dsi_vc_config(0);
+- dsi_vc_config_vp(1);
++ dsi_vc_initial_config(0);
+
+ /* set all vc targets to peripheral 0 */
+ dsi.vc[0].dest_per = 0;
+@@ -2535,10 +2569,11 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ int packet_len;
+ u32 l;
+ bool use_te_trigger;
++ const int channel = 0;
+
+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+
+- if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+ x, y, w, h);
+
+@@ -2559,22 +2594,27 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
+ dsi_vc_print_status(1);
+
+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+- dsi_write_reg(DSI_VC_TE(1), l);
++ dsi_write_reg(DSI_VC_TE(channel), l);
+
+- dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
++ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
+
+ if (use_te_trigger)
+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+ else
+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+- dsi_write_reg(DSI_VC_TE(1), l);
++ dsi_write_reg(DSI_VC_TE(channel), l);
+
+ dispc_disable_sidle();
+
+ dss_start_update(dssdev);
+
+- if (use_te_trigger)
+- dsi_vc_send_bta(1);
++ if (use_te_trigger) {
++ /* disable LP_RX_TO, so that we can receive TE. Time to wait
++ * for TE is longer than the timer allows */
++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
++
++ dsi_vc_send_bta(channel);
++ }
+ }
+
+ static void dsi_framedone_irq_callback(void *data, u32 mask)
+@@ -2637,19 +2677,12 @@ static void dsi_start_auto_update(struct omap_dss_device *dssdev)
+
+ static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
+ {
+- dssdev->driver->enable_te(dssdev, enable);
+-
+- if (!dsi.use_ext_te) {
+- if (enable) {
+- /* disable LP_RX_TO, so that we can receive TE. Time
+- * to wait for TE is longer than the timer allows */
+- REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+- } else {
+- REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+- }
+- }
+-
+- return 0;
++ int r;
++ r = dssdev->driver->enable_te(dssdev, enable);
++ /* XXX for some reason, DSI TE breaks if we don't wait here.
++ * Panel bug? Needs more studying */
++ msleep(100);
++ return r;
+ }
+
+ static void dsi_handle_framedone(void)
+@@ -2657,8 +2690,14 @@ static void dsi_handle_framedone(void)
+ u32 l;
+ unsigned long tmo;
+ int i = 0;
++ int r;
++ const int channel = 0;
++ u32 te_size;
++ bool use_te_trigger;
++
++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+
+- l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
++ l = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */
+
+ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
+ * itself off. However, DSI still has the pixels in its buffers, and is
+@@ -2667,24 +2706,26 @@ static void dsi_handle_framedone(void)
+ * DSI buffers, if any, so we'll just busyloop */
+ if (l > 0) {
+ tmo = jiffies + msecs_to_jiffies(50);
+- while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */
++ te_size = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */
++ while (te_size > 0) {
+ i++;
+ if (time_after(jiffies, tmo)) {
+ DSSERR("timeout waiting TE_SIZE to zero: %u\n",
+- REG_GET(DSI_VC_TE(1), 23, 0));
++ te_size);
+ break;
+ }
+ schedule();
++ te_size = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */
+ }
+ }
+
+- if (REG_GET(DSI_VC_TE(1), 30, 30))
++ if (REG_GET(DSI_VC_TE(channel), 30, 30))
+ DSSERR("TE_EN not zero\n");
+
+- if (REG_GET(DSI_VC_TE(1), 31, 31))
++ if (REG_GET(DSI_VC_TE(channel), 31, 31))
+ DSSERR("TE_START not zero\n");
+
+- if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("FRAMEDONE\n");
+
+ #if 0
+@@ -2698,6 +2739,16 @@ static void dsi_handle_framedone(void)
+ #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+ dispc_fake_vsync_irq();
+ #endif
++ if (use_te_trigger) {
++ /* enable LP_RX_TO again after the TE */
++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
++
++ /* send BTA after the frame, because we need to BTA after
++ * every trasmission for the TE to work */
++ r = dsi_vc_send_bta_sync(channel);
++ if (r)
++ DSSERR("BTA after framedone failed\n");
++ }
+ }
+
+ static int dsi_update_thread(void *data)
+@@ -2768,25 +2819,24 @@ static int dsi_update_thread(void *data)
+ dispc_set_lcd_size(w, h);
+ }
+
+- /* XXX We don't need to send the update area coords to the
+- * panel every time. But for some reason TE doesn't work if we
+- * don't send at least a BTA here... */
+-#if 0
+ if (dsi.active_update_region.dirty) {
+ dsi.active_update_region.dirty = false;
++ /* XXX TODO we don't need to send the coords, if they
++ * are the same that are already programmed to the
++ * panel. That should speed up manual update a bit */
+ device->driver->setup_update(device, x, y, w, h);
+ }
+-#else
+- device->driver->setup_update(device, x, y, w, h);
+-#endif
+-
+- if (dsi.te_enabled && dsi.use_ext_te &&
+- device->driver->wait_for_te)
+- device->driver->wait_for_te(device);
+
+ dsi_perf_mark_start();
+
+ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
++ dsi_vc_config_vp(0);
++
++ if (dsi.te_enabled && dsi.use_ext_te)
++ device->driver->wait_for_te(device);
++
++ dsi.framedone_received = false;
++
+ dsi_update_screen_dispc(device, x, y, w, h);
+
+ /* wait for framedone */
+@@ -2795,8 +2845,6 @@ static int dsi_update_thread(void *data)
+ dsi.framedone_received == true,
+ timeout);
+
+- dsi.framedone_received = false;
+-
+ if (timeout == 0) {
+ DSSERR("framedone timeout\n");
+ DSSERR("failed update %d,%d %dx%d\n",
+@@ -2808,6 +2856,8 @@ static int dsi_update_thread(void *data)
+ dsi_handle_framedone();
+ dsi_perf_show("DISPC");
+ }
++
++ dsi_vc_config_l4(0);
+ } else {
+ dsi_update_screen_l4(device, x, y, w, h);
+ dsi_perf_show("L4");
+@@ -2913,7 +2963,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
+
+ /* enable interface */
+ dsi_vc_enable(0, 1);
+- dsi_vc_enable(1, 1);
+ dsi_if_enable(1);
+ dsi_force_tx_stop_mode_io();
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0133-DSS2-VRAM-Remove-unused-defines.patch b/recipes/linux/linux-omap-pm/dss2/0133-DSS2-VRAM-Remove-unused-defines.patch
new file mode 100644
index 0000000000..8815149684
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0133-DSS2-VRAM-Remove-unused-defines.patch
@@ -0,0 +1,41 @@
+From bc4dd8997279f25e115e27781a8b9f90315cb3ef Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 1 Jul 2009 12:34:05 +0300
+Subject: [PATCH 133/146] DSS2: VRAM: Remove unused defines
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/vram.c | 11 ++---------
+ 1 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index d4a8110..940c25d 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -1,7 +1,7 @@
+ /*
+- * linux/arch/arm/plat-omap/vram.c
++ * arch/arm/plat-omap/vram.c
+ *
+- * Copyright (C) 2008 Nokia Corporation
++ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+@@ -49,13 +49,6 @@
+ /* Maximum size, in reality this is smaller if SRAM is partially locked. */
+ #define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
+
+-#define REG_MAP_SIZE(_page_cnt) \
+- ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+-#define REG_MAP_PTR(_rg, _page_nr) \
+- (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+-#define REG_MAP_MASK(_page_nr) \
+- (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+-
+ #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+
+ /* postponed regions are used to temporarily store region information at boot
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0134-DSS2-VENC-Add-invert_polarity-flag.patch b/recipes/linux/linux-omap-pm/dss2/0134-DSS2-VENC-Add-invert_polarity-flag.patch
new file mode 100644
index 0000000000..57d5c65f94
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0134-DSS2-VENC-Add-invert_polarity-flag.patch
@@ -0,0 +1,65 @@
+From 324ac5a3f4ea601d1854eadff1388a4310ce660e Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 1 Jul 2009 13:43:55 +0300
+Subject: [PATCH 134/146] DSS2: VENC: Add invert_polarity flag
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/display.h | 1 +
+ drivers/video/omap2/dss/venc.c | 21 +++++++++++++--------
+ 2 files changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
+index 6df28dc..9477ccb 100644
+--- a/arch/arm/plat-omap/include/mach/display.h
++++ b/arch/arm/plat-omap/include/mach/display.h
+@@ -381,6 +381,7 @@ struct omap_dss_device {
+
+ struct {
+ enum omap_dss_venc_type type;
++ bool invert_polarity;
+ } venc;
+ } phy;
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index a9a5a8c..091ecc4 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -510,6 +510,8 @@ void venc_exit(void)
+
+ static void venc_power_on(struct omap_dss_device *dssdev)
+ {
++ u32 l;
++
+ venc_enable_clocks(1);
+
+ venc_reset();
+@@ -518,14 +520,17 @@ static void venc_power_on(struct omap_dss_device *dssdev)
+ dss_set_venc_output(dssdev->phy.venc.type);
+ dss_set_dac_pwrdn_bgz(1);
+
+- if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) {
+- if (cpu_is_omap24xx())
+- venc_write_reg(VENC_OUTPUT_CONTROL, 0x2);
+- else
+- venc_write_reg(VENC_OUTPUT_CONTROL, 0xa);
+- } else { /* S-Video */
+- venc_write_reg(VENC_OUTPUT_CONTROL, 0xd);
+- }
++ l = 0;
++
++ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
++ l |= 1 << 1;
++ else /* S-Video */
++ l |= (1 << 0) | (1 << 2);
++
++ if (dssdev->phy.venc.invert_polarity == false)
++ l |= 1 << 3;
++
++ venc_write_reg(VENC_OUTPUT_CONTROL, l);
+
+ dispc_set_digit_size(dssdev->panel.timings.x_res,
+ dssdev->panel.timings.y_res/2);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0135-DSS2-VRAM-Add-defines-for-VRAM-types.patch b/recipes/linux/linux-omap-pm/dss2/0135-DSS2-VRAM-Add-defines-for-VRAM-types.patch
new file mode 100644
index 0000000000..a139847f4f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0135-DSS2-VRAM-Add-defines-for-VRAM-types.patch
@@ -0,0 +1,89 @@
+From 9a472e2308e253e64652ff35954c05525abfb10a Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Wed, 1 Jul 2009 14:42:52 +0300
+Subject: [PATCH 135/146] DSS2: VRAM: Add defines for VRAM types
+
+Also clean up includes a bit.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vram.h | 4 ++++
+ arch/arm/plat-omap/vram.c | 11 +++++------
+ drivers/video/omap2/omapfb/omapfb-main.c | 2 +-
+ 3 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index 494ddde..66b788e 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -24,6 +24,10 @@
+
+ #include <asm/types.h>
+
++#define OMAP_VRAM_MEMTYPE_SDRAM 0
++#define OMAP_VRAM_MEMTYPE_SRAM 1
++#define OMAP_VRAM_MEMTYPE_MAX 1
++
+ extern int omap_vram_add_region(unsigned long paddr, size_t size);
+ extern int omap_vram_free(unsigned long paddr, size_t size);
+ extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 940c25d..2954764 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -22,16 +22,15 @@
+
+ /*#define DEBUG*/
+
+-#include <linux/vmalloc.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/list.h>
+-#include <linux/dma-mapping.h>
+ #include <linux/seq_file.h>
+ #include <linux/bootmem.h>
+-#include <linux/omapfb.h>
+ #include <linux/completion.h>
+ #include <linux/debugfs.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
+
+ #include <asm/setup.h>
+
+@@ -82,9 +81,9 @@ static inline int region_mem_type(unsigned long paddr)
+ {
+ if (paddr >= OMAP2_SRAM_START &&
+ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+- return OMAPFB_MEMTYPE_SRAM;
++ return OMAP_VRAM_MEMTYPE_SRAM;
+ else
+- return OMAPFB_MEMTYPE_SDRAM;
++ return OMAP_VRAM_MEMTYPE_SDRAM;
+ }
+
+ static struct vram_region *omap_vram_create_region(unsigned long paddr,
+@@ -374,7 +373,7 @@ int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
+ unsigned pages;
+ int r;
+
+- BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
++ BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size);
+
+ DBG("alloc mem type %d size %d\n", mtype, size);
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index b806dc9..45f087f 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -1204,7 +1204,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+
+ if (!paddr) {
+ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+- r = omap_vram_alloc(OMAPFB_MEMTYPE_SDRAM, size, &paddr);
++ r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
+ } else {
+ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
+ ofbi->id);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0136-DSS2-VRAM-separate-VRAM-setup-from-the-old-fb-vram.patch b/recipes/linux/linux-omap-pm/dss2/0136-DSS2-VRAM-separate-VRAM-setup-from-the-old-fb-vram.patch
new file mode 100644
index 0000000000..d9a87d12bf
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0136-DSS2-VRAM-separate-VRAM-setup-from-the-old-fb-vram.patch
@@ -0,0 +1,311 @@
+From 623b67b81b32b758915a58816bc75e092aa33bb8 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:05:08 +0300
+Subject: [PATCH 136/146] DSS2: VRAM: separate VRAM setup from the old fb vram setup
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/mach-omap2/io.c | 2 +
+ arch/arm/plat-omap/fb.c | 11 +++++-
+ arch/arm/plat-omap/include/mach/vram.h | 6 +++
+ arch/arm/plat-omap/sram.c | 15 +++++---
+ arch/arm/plat-omap/vram.c | 60 ++++++++++++++++----------------
+ include/linux/omapfb.h | 5 +++
+ 6 files changed, 62 insertions(+), 37 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index 5c91f36..221c60f 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -32,6 +32,7 @@
+ #include <mach/sram.h>
+ #include <mach/sdrc.h>
+ #include <mach/gpmc.h>
++#include <mach/vram.h>
+
+ #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */
+ #include "clock.h"
+@@ -240,6 +241,7 @@ void __init omap2_map_common_io(void)
+ omap2_check_revision();
+ omap_sram_init();
+ omapfb_reserve_sdram();
++ omap_vram_reserve_sdram();
+ }
+
+ /*
+diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
+index 1dc3415..70fbeae 100644
+--- a/arch/arm/plat-omap/fb.c
++++ b/arch/arm/plat-omap/fb.c
+@@ -355,6 +355,16 @@ static inline int omap_init_fb(void)
+
+ arch_initcall(omap_init_fb);
+
++void omapfb_reserve_sdram(void) {}
++unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long start_avail,
++ unsigned long size_avail)
++{
++ return 0;
++}
++
+ #else
+
+ void omapfb_reserve_sdram(void) {}
+@@ -367,5 +377,4 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+ return 0;
+ }
+
+-
+ #endif
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index 66b788e..8d26b05 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -37,4 +37,10 @@ extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
+ extern void omap2_set_sdram_vram(u32 size, u32 start);
+ extern void omap2_set_sram_vram(u32 size, u32 start);
+
++extern void omap_vram_reserve_sdram(void);
++extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail);
+ #endif
+diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
+index 4ea7380..26797e7 100644
+--- a/arch/arm/plat-omap/sram.c
++++ b/arch/arm/plat-omap/sram.c
+@@ -19,6 +19,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/io.h>
++#include <linux/omapfb.h>
+
+ #include <asm/tlb.h>
+ #include <asm/cacheflush.h>
+@@ -28,6 +29,7 @@
+ #include <mach/sram.h>
+ #include <mach/board.h>
+ #include <mach/cpu.h>
++#include <mach/vram.h>
+
+ #include <mach/control.h>
+
+@@ -76,12 +78,6 @@ static unsigned long omap_sram_base;
+ static unsigned long omap_sram_size;
+ static unsigned long omap_sram_ceil;
+
+-extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+- unsigned long sram_vstart,
+- unsigned long sram_size,
+- unsigned long pstart_avail,
+- unsigned long size_avail);
+-
+ /*
+ * Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies. The default accessible size for all device types is 2k. A GP
+@@ -185,6 +181,13 @@ void __init omap_detect_sram(void)
+ omap_sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ);
+ omap_sram_size -= reserved;
++
++ reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
++ omap_sram_size,
++ omap_sram_start + SRAM_BOOTLOADER_SZ,
++ omap_sram_size - SRAM_BOOTLOADER_SZ);
++ omap_sram_size -= reserved;
++
+ omap_sram_ceil = omap_sram_base + omap_sram_size;
+ }
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 2954764..6c4bc18 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -39,7 +39,7 @@
+ #include <mach/dma.h>
+
+ #ifdef DEBUG
+-#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
++#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
+ #else
+ #define DBG(format, ...)
+ #endif
+@@ -239,7 +239,7 @@ static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
+ if (!(start <= paddr && end >= paddr + size - 1))
+ continue;
+ found:
+- DBG("FOUND area start %lx, end %lx\n", start, end);
++ DBG("found area start %lx, end %lx\n", start, end);
+
+ if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
+ return -ENOMEM;
+@@ -352,7 +352,7 @@ found:
+ if (end - start < pages << PAGE_SHIFT)
+ continue;
+
+- DBG("FOUND %lx, end %lx\n", start, end);
++ DBG("found %lx, end %lx\n", start, end);
+
+ alloc = omap_vram_create_allocation(rm, start, pages);
+ if (alloc == NULL)
+@@ -504,30 +504,30 @@ arch_initcall(omap_vram_init);
+ /* boottime vram alloc stuff */
+
+ /* set from board file */
+-static u32 omapfb_sram_vram_start __initdata;
+-static u32 omapfb_sram_vram_size __initdata;
++static u32 omap_vram_sram_start __initdata;
++static u32 omap_vram_sram_size __initdata;
+
+ /* set from board file */
+-static u32 omapfb_sdram_vram_start __initdata;
+-static u32 omapfb_sdram_vram_size __initdata;
++static u32 omap_vram_sdram_start __initdata;
++static u32 omap_vram_sdram_size __initdata;
+
+ /* set from kernel cmdline */
+-static u32 omapfb_def_sdram_vram_size __initdata;
+-static u32 omapfb_def_sdram_vram_start __initdata;
++static u32 omap_vram_def_sdram_size __initdata;
++static u32 omap_vram_def_sdram_start __initdata;
+
+-static void __init omapfb_early_vram(char **p)
++static void __init omap_vram_early_vram(char **p)
+ {
+- omapfb_def_sdram_vram_size = memparse(*p, p);
++ omap_vram_def_sdram_size = memparse(*p, p);
+ if (**p == ',')
+- omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
++ omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16);
+ }
+-__early_param("vram=", omapfb_early_vram);
++__early_param("vram=", omap_vram_early_vram);
+
+ /*
+ * Called from map_io. We need to call to this early enough so that we
+ * can reserve the fixed SDRAM regions before VM could get hold of them.
+ */
+-void __init omapfb_reserve_sdram(void)
++void __init omap_vram_reserve_sdram(void)
+ {
+ struct bootmem_data *bdata;
+ unsigned long sdram_start, sdram_size;
+@@ -535,14 +535,14 @@ void __init omapfb_reserve_sdram(void)
+ u32 size = 0;
+
+ /* cmdline arg overrides the board file definition */
+- if (omapfb_def_sdram_vram_size) {
+- size = omapfb_def_sdram_vram_size;
+- paddr = omapfb_def_sdram_vram_start;
++ if (omap_vram_def_sdram_size) {
++ size = omap_vram_def_sdram_size;
++ paddr = omap_vram_def_sdram_start;
+ }
+
+ if (!size) {
+- size = omapfb_sdram_vram_size;
+- paddr = omapfb_sdram_vram_start;
++ size = omap_vram_sdram_size;
++ paddr = omap_vram_sdram_start;
+ }
+
+ #ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
+@@ -564,7 +564,7 @@ void __init omapfb_reserve_sdram(void)
+ if (paddr) {
+ if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
+ paddr + size > sdram_start + sdram_size) {
+- printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
++ pr_err("Illegal SDRAM region for VRAM\n");
+ return;
+ }
+
+@@ -574,7 +574,7 @@ void __init omapfb_reserve_sdram(void)
+ }
+ } else {
+ if (size > sdram_size) {
+- printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
++ pr_err("Illegal SDRAM size for VRAM\n");
+ return;
+ }
+
+@@ -597,7 +597,7 @@ void __init omapfb_reserve_sdram(void)
+ * this point, since the driver built as a module would have problem with
+ * freeing / reallocating the regions.
+ */
+-unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
++unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_vstart,
+ unsigned long sram_size,
+ unsigned long pstart_avail,
+@@ -608,8 +608,8 @@ unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+ u32 paddr;
+ u32 size;
+
+- paddr = omapfb_sram_vram_start;
+- size = omapfb_sram_vram_size;
++ paddr = omap_vram_sram_start;
++ size = omap_vram_sram_size;
+
+ if (!size)
+ return 0;
+@@ -620,7 +620,7 @@ unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+ if (!paddr) {
+ /* Dynamic allocation */
+ if ((size_avail & PAGE_MASK) < size) {
+- printk(KERN_ERR "Not enough SRAM for VRAM\n");
++ pr_err("Not enough SRAM for VRAM\n");
+ return 0;
+ }
+ size_avail = (size_avail - size) & PAGE_MASK;
+@@ -629,7 +629,7 @@ unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+
+ if (paddr < sram_pstart ||
+ paddr + size > sram_pstart + sram_size) {
+- printk(KERN_ERR "Illegal SRAM region for VRAM\n");
++ pr_err("Illegal SRAM region for VRAM\n");
+ return 0;
+ }
+
+@@ -648,14 +648,14 @@ unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
+
+ void __init omap2_set_sdram_vram(u32 size, u32 start)
+ {
+- omapfb_sdram_vram_start = start;
+- omapfb_sdram_vram_size = size;
++ omap_vram_sdram_start = start;
++ omap_vram_sdram_size = size;
+ }
+
+ void __init omap2_set_sram_vram(u32 size, u32 start)
+ {
+- omapfb_sram_vram_start = start;
+- omapfb_sram_vram_size = size;
++ omap_vram_sram_start = start;
++ omap_vram_sram_size = size;
+ }
+
+ #endif
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index 0df0df9..67dc375 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -424,6 +424,11 @@ extern struct lcd_ctrl omap2_disp_ctrl;
+ extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
+
+ extern void omapfb_reserve_sdram(void);
++extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail);
+ extern void omapfb_register_panel(struct lcd_panel *panel);
+ extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+ extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0137-DSS2-VRFB-Update-license-information.patch b/recipes/linux/linux-omap-pm/dss2/0137-DSS2-VRFB-Update-license-information.patch
new file mode 100644
index 0000000000..e447b07bb0
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0137-DSS2-VRFB-Update-license-information.patch
@@ -0,0 +1,77 @@
+From 87bf295895fd2ee8a9019ddfcbef37cd98d28e20 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:18:43 +0300
+Subject: [PATCH 137/146] DSS2: VRFB: Update license information
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vrfb.h | 15 ++++++---------
+ arch/arm/plat-omap/vrfb.c | 20 ++++++++++++++++++++
+ 2 files changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index 9647d82..1a53c0e 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -1,15 +1,12 @@
+ /*
+- * File: arch/arm/plat-omap/include/mach/vrfb.h
+- *
+- * VRFB
++ * VRFB Rotation Engine
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+@@ -21,8 +18,8 @@
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+-#ifndef __VRFB_H
+-#define __VRFB_H
++#ifndef __OMAP_VRFB_H__
++#define __OMAP_VRFB_H__
+
+ #include <mach/display.h>
+ #define OMAP_VRFB_LINE_LEN 2048
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 201640a..24ea412 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -1,3 +1,23 @@
++/*
++ * VRFB Rotation Engine
++ *
++ * Copyright (C) 2009 Nokia Corporation
++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/ioport.h>
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0138-DSS2-VRAM-Update-license-information.patch b/recipes/linux/linux-omap-pm/dss2/0138-DSS2-VRAM-Update-license-information.patch
new file mode 100644
index 0000000000..cc83693ac3
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0138-DSS2-VRAM-Update-license-information.patch
@@ -0,0 +1,86 @@
+From 35ef20ad839dafe564b19561fd779af256460152 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:19:20 +0300
+Subject: [PATCH 138/146] DSS2: VRAM: Update license information
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vram.h | 13 ++++++-------
+ arch/arm/plat-omap/vram.c | 24 +++++++++++-------------
+ 2 files changed, 17 insertions(+), 20 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index 8d26b05..f6bb9fb 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -1,13 +1,12 @@
+ /*
+- * File: arch/arm/plat-omap/include/mach/vram.h
++ * VRAM manager for OMAP
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+@@ -19,8 +18,8 @@
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+-#ifndef __OMAPVRAM_H
+-#define __OMAPVRAM_H
++#ifndef __OMAP_VRAM_H__
++#define __OMAP_VRAM_H__
+
+ #include <asm/types.h>
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 6c4bc18..0fd5b13 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -1,23 +1,21 @@
+ /*
+- * arch/arm/plat-omap/vram.c
++ * VRAM manager for OMAP
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+- * Some code and ideas taken from drivers/video/omap/ driver
+- * by Imre Deak.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
+ *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
+ *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program. If not, see <http://www.gnu.org/licenses/>.
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+ /*#define DEBUG*/
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0139-DSS2-VRFB-use-pr_-instead-of-printk.patch b/recipes/linux/linux-omap-pm/dss2/0139-DSS2-VRFB-use-pr_-instead-of-printk.patch
new file mode 100644
index 0000000000..abaf1f73f2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0139-DSS2-VRFB-use-pr_-instead-of-printk.patch
@@ -0,0 +1,43 @@
+From c9a738cd1c5afda7f7c5a92cce23caa90d901c41 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:21:27 +0300
+Subject: [PATCH 139/146] DSS2: VRFB: use pr_* instead of printk
+
+---
+ arch/arm/plat-omap/vrfb.c | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
+index 24ea412..f526ee1 100644
+--- a/arch/arm/plat-omap/vrfb.c
++++ b/arch/arm/plat-omap/vrfb.c
+@@ -30,7 +30,7 @@
+ /*#define DEBUG*/
+
+ #ifdef DEBUG
+-#define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
++#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
+ #else
+ #define DBG(format, ...)
+ #endif
+@@ -229,7 +229,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ break;
+
+ if (ctx == VRFB_NUM_CTXS) {
+- printk(KERN_ERR "vrfb: no free contexts\n");
++ pr_err("vrfb: no free contexts\n");
+ r = -EBUSY;
+ goto out;
+ }
+@@ -247,7 +247,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
+ for (rot = 0; rot < 4; ++rot) {
+ paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
+- printk(KERN_ERR "vrfb: failed to reserve VRFB "
++ pr_err("vrfb: failed to reserve VRFB "
+ "area for ctx %d, rotation %d\n",
+ ctx, rot * 90);
+ omap_vrfb_release_ctx(vrfb);
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0140-DSS2-VRAM-Change-CONFIG_OMAP2_DSS_VRAM_SIZE-name.patch b/recipes/linux/linux-omap-pm/dss2/0140-DSS2-VRAM-Change-CONFIG_OMAP2_DSS_VRAM_SIZE-name.patch
new file mode 100644
index 0000000000..ea57a9514f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0140-DSS2-VRAM-Change-CONFIG_OMAP2_DSS_VRAM_SIZE-name.patch
@@ -0,0 +1,49 @@
+From 7f7e699c5481a69428c4c01b291f14a8eec5c52c Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:27:13 +0300
+Subject: [PATCH 140/146] DSS2: VRAM: Change CONFIG_OMAP2_DSS_VRAM_SIZE name
+
+Changed to CONFIG_OMAP2_VRAM_SIZE
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/vram.c | 4 ++--
+ drivers/video/omap2/dss/Kconfig | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 0fd5b13..89ae1cf 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -543,9 +543,9 @@ void __init omap_vram_reserve_sdram(void)
+ paddr = omap_vram_sdram_start;
+ }
+
+-#ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
++#ifdef CONFIG_OMAP2_VRAM_SIZE
+ if (!size) {
+- size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024;
++ size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
+ paddr = 0;
+ }
+ #endif
+diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
+index f2ce068..71d8dec 100644
+--- a/drivers/video/omap2/dss/Kconfig
++++ b/drivers/video/omap2/dss/Kconfig
+@@ -6,10 +6,10 @@ menuconfig OMAP2_DSS
+
+ if OMAP2_DSS
+
+-config OMAP2_DSS_VRAM_SIZE
++config OMAP2_VRAM_SIZE
+ int "VRAM size (MB)"
+ range 0 32
+- default 4
++ default 0
+ help
+ The amount of SDRAM to reserve at boot time for video RAM use.
+ This VRAM will be used by omapfb and other drivers that need
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0141-DSS2-VRAM-add-CONFIG_OMAP2_VRAM-flag.patch b/recipes/linux/linux-omap-pm/dss2/0141-DSS2-VRAM-add-CONFIG_OMAP2_VRAM-flag.patch
new file mode 100644
index 0000000000..562ad7a1e2
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0141-DSS2-VRAM-add-CONFIG_OMAP2_VRAM-flag.patch
@@ -0,0 +1,141 @@
+From 6f66d2245dc6359f7de98796f5d999a308f74179 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:49:07 +0300
+Subject: [PATCH 141/146] DSS2: VRAM: add CONFIG_OMAP2_VRAM flag
+
+CONFIG_OMAP2_VRAM controls wheter VRAM manager is compiled in or not.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/Kconfig | 3 +++
+ arch/arm/plat-omap/Makefile | 3 ++-
+ arch/arm/plat-omap/include/mach/vram.h | 22 ++++++++++++++++++++--
+ arch/arm/plat-omap/vram.c | 9 ++-------
+ drivers/video/omap2/omapfb/Kconfig | 1 +
+ 5 files changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index efe85d0..ca06037 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -183,6 +183,9 @@ config OMAP_SERIAL_WAKE
+ to data on the serial RX line. This allows you to wake the
+ system from serial console.
+
++config OMAP2_VRAM
++ bool
++
+ endmenu
+
+ endif
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index cfc0967..3232edc 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -4,7 +4,7 @@
+
+ # Common support
+ obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
+- usb.o fb.o vram.o vrfb.o io.o
++ usb.o fb.o vrfb.o io.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+@@ -25,3 +25,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
+ # OMAP mailbox framework
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
++obj-$(CONFIG_OMAP2_VRAM) += vram.o
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index f6bb9fb..4f2c2e6 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -21,6 +21,7 @@
+ #ifndef __OMAP_VRAM_H__
+ #define __OMAP_VRAM_H__
+
++#include <linux/autoconf.h>
+ #include <asm/types.h>
+
+ #define OMAP_VRAM_MEMTYPE_SDRAM 0
+@@ -33,8 +34,10 @@ extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr);
+ extern int omap_vram_reserve(unsigned long paddr, size_t size);
+ extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
+ unsigned long *largest_free_block);
+-extern void omap2_set_sdram_vram(u32 size, u32 start);
+-extern void omap2_set_sram_vram(u32 size, u32 start);
++
++#ifdef CONFIG_OMAP2_VRAM
++extern void omap_vram_set_sdram_vram(u32 size, u32 start);
++extern void omap_vram_set_sram_vram(u32 size, u32 start);
+
+ extern void omap_vram_reserve_sdram(void);
+ extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
+@@ -42,4 +45,19 @@ extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_size,
+ unsigned long pstart_avail,
+ unsigned long size_avail);
++#else
++static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
++static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
++
++static inline void omap_vram_reserve_sdram(void) { }
++static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
++ unsigned long sram_vstart,
++ unsigned long sram_size,
++ unsigned long pstart_avail,
++ unsigned long size_avail)
++{
++ return 0;
++}
++#endif
++
+ #endif
+diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c
+index 89ae1cf..634ce23 100644
+--- a/arch/arm/plat-omap/vram.c
++++ b/arch/arm/plat-omap/vram.c
+@@ -46,8 +46,6 @@
+ /* Maximum size, in reality this is smaller if SRAM is partially locked. */
+ #define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
+
+-#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
+-
+ /* postponed regions are used to temporarily store region information at boot
+ * time when we cannot yet allocate the region list */
+ #define MAX_POSTPONED_REGIONS 10
+@@ -644,17 +642,14 @@ unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
+ return reserved;
+ }
+
+-void __init omap2_set_sdram_vram(u32 size, u32 start)
++void __init omap_vram_set_sdram_vram(u32 size, u32 start)
+ {
+ omap_vram_sdram_start = start;
+ omap_vram_sdram_size = size;
+ }
+
+-void __init omap2_set_sram_vram(u32 size, u32 start)
++void __init omap_vram_set_sram_vram(u32 size, u32 start)
+ {
+ omap_vram_sram_start = start;
+ omap_vram_sram_size = size;
+ }
+-
+-#endif
+-
+diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
+index 4f66033..220c58b 100644
+--- a/drivers/video/omap2/omapfb/Kconfig
++++ b/drivers/video/omap2/omapfb/Kconfig
+@@ -2,6 +2,7 @@ menuconfig FB_OMAP2
+ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
+ depends on FB && OMAP2_DSS
+
++ select OMAP2_VRAM
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0142-DSS2-VRFB-Add-CONFIG_OMAP2_VRFB-flag.patch b/recipes/linux/linux-omap-pm/dss2/0142-DSS2-VRFB-Add-CONFIG_OMAP2_VRFB-flag.patch
new file mode 100644
index 0000000000..fdf96915b5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0142-DSS2-VRFB-Add-CONFIG_OMAP2_VRFB-flag.patch
@@ -0,0 +1,61 @@
+From 861c91bae473d89d11bf38036dd68ee7cd33f9c4 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 11:53:26 +0300
+Subject: [PATCH 142/146] DSS2: VRFB: Add CONFIG_OMAP2_VRFB flag
+
+CONFIG_OMAP2_VRFB controls if VRFB is compiled in or not.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/Kconfig | 3 +++
+ arch/arm/plat-omap/Makefile | 3 ++-
+ drivers/video/omap2/omapfb/Kconfig | 1 +
+ 3 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index ca06037..2d6ae55 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -186,6 +186,9 @@ config OMAP_SERIAL_WAKE
+ config OMAP2_VRAM
+ bool
+
++config OMAP2_VRFB
++ bool
++
+ endmenu
+
+ endif
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 3232edc..462edf3 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -4,7 +4,7 @@
+
+ # Common support
+ obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
+- usb.o fb.o vrfb.o io.o
++ usb.o fb.o io.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+@@ -26,3 +26,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
+ obj-$(CONFIG_OMAP2_VRAM) += vram.o
++obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
+diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
+index 220c58b..bb694cc 100644
+--- a/drivers/video/omap2/omapfb/Kconfig
++++ b/drivers/video/omap2/omapfb/Kconfig
+@@ -3,6 +3,7 @@ menuconfig FB_OMAP2
+ depends on FB && OMAP2_DSS
+
+ select OMAP2_VRAM
++ select OMAP2_VRFB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0143-DSS2-VRFB-VRAM-fix-checkpatch-warnings.patch b/recipes/linux/linux-omap-pm/dss2/0143-DSS2-VRFB-VRAM-fix-checkpatch-warnings.patch
new file mode 100644
index 0000000000..f9951f3403
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0143-DSS2-VRFB-VRAM-fix-checkpatch-warnings.patch
@@ -0,0 +1,41 @@
+From 3ef64847bf3139f00aa254f1c5dda46b5c13470d Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 15:14:57 +0300
+Subject: [PATCH 143/146] DSS2: VRFB/VRAM: fix checkpatch warnings
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ arch/arm/plat-omap/include/mach/vram.h | 2 +-
+ arch/arm/plat-omap/include/mach/vrfb.h | 3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h
+index 4f2c2e6..fe72f81 100644
+--- a/arch/arm/plat-omap/include/mach/vram.h
++++ b/arch/arm/plat-omap/include/mach/vram.h
+@@ -22,7 +22,7 @@
+ #define __OMAP_VRAM_H__
+
+ #include <linux/autoconf.h>
+-#include <asm/types.h>
++#include <linux/types.h>
+
+ #define OMAP_VRAM_MEMTYPE_SDRAM 0
+ #define OMAP_VRAM_MEMTYPE_SRAM 1
+diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h
+index 1a53c0e..dee929c 100644
+--- a/arch/arm/plat-omap/include/mach/vrfb.h
++++ b/arch/arm/plat-omap/include/mach/vrfb.h
+@@ -24,8 +24,7 @@
+ #include <mach/display.h>
+ #define OMAP_VRFB_LINE_LEN 2048
+
+-struct vrfb
+-{
++struct vrfb {
+ u8 context;
+ void __iomem *vaddr[4];
+ unsigned long paddr[4];
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0144-DSS2-fixes-to-dss_omap_3430sdp_defconfig-to-make-it.patch b/recipes/linux/linux-omap-pm/dss2/0144-DSS2-fixes-to-dss_omap_3430sdp_defconfig-to-make-it.patch
new file mode 100644
index 0000000000..908133d04e
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0144-DSS2-fixes-to-dss_omap_3430sdp_defconfig-to-make-it.patch
@@ -0,0 +1,1675 @@
+From 7d29cea64fc73b3f7f4524d4ce27ef721ed8b717 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 16:12:26 +0300
+Subject: [PATCH 144/146] DSS2: fixes to dss_omap_3430sdp_defconfig to make it boot
+
+---
+ arch/arm/configs/dss_omap_3430sdp_defconfig | 866 ++++++++++++++++++---------
+ 1 files changed, 598 insertions(+), 268 deletions(-)
+
+diff --git a/arch/arm/configs/dss_omap_3430sdp_defconfig b/arch/arm/configs/dss_omap_3430sdp_defconfig
+index dc30dce..cf44088 100644
+--- a/arch/arm/configs/dss_omap_3430sdp_defconfig
++++ b/arch/arm/configs/dss_omap_3430sdp_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.29-omap1
+-# Thu Apr 2 11:11:24 2009
++# Linux kernel version: 2.6.31-rc1-omap1
++# Thu Jul 2 17:25:15 2009
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
+ CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_STACKTRACE_SUPPORT=y
+ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+@@ -18,13 +17,13 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_OPROFILE_ARMV7=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
+
+ #
+ # General setup
+@@ -33,7 +32,7 @@ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+ CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_LOCALVERSION_AUTO is not set
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_SYSVIPC_SYSCTL=y
+@@ -51,7 +50,8 @@ CONFIG_CLASSIC_RCU=y
+ # CONFIG_PREEMPT_RCU is not set
+ # CONFIG_TREE_RCU_TRACE is not set
+ # CONFIG_PREEMPT_RCU_TRACE is not set
+-# CONFIG_IKCONFIG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_GROUP_SCHED=y
+ CONFIG_FAIR_GROUP_SCHED=y
+@@ -65,6 +65,9 @@ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_NAMESPACES is not set
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+ CONFIG_ANON_INODES=y
+@@ -73,11 +76,11 @@ CONFIG_UID16=y
+ # CONFIG_SYSCTL_SYSCALL is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+-CONFIG_KALLSYMS_EXTRA_PASS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
+ CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
++# CONFIG_ELF_CORE is not set
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
+ CONFIG_EPOLL=y
+@@ -86,17 +89,32 @@ CONFIG_TIMERFD=y
+ CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+ CONFIG_AIO=y
++
++#
++# Performance Counters
++#
+ CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
++CONFIG_SLUB_DEBUG=y
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_COMPAT_BRK is not set
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
+ # CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++CONFIG_MARKERS=y
++CONFIG_OPROFILE=y
+ CONFIG_HAVE_OPROFILE=y
+ # CONFIG_KPROBES is not set
+ CONFIG_HAVE_KPROBES=y
+ CONFIG_HAVE_KRETPROBES=y
+ CONFIG_HAVE_CLK=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++# CONFIG_SLOW_WORK is not set
+ CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -104,12 +122,11 @@ CONFIG_BASE_SMALL=0
+ CONFIG_MODULES=y
+ # CONFIG_MODULE_FORCE_LOAD is not set
+ CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_BLK_DEV_INTEGRITY is not set
+
+@@ -120,11 +137,11 @@ CONFIG_IOSCHED_NOOP=y
+ CONFIG_IOSCHED_AS=y
+ CONFIG_IOSCHED_DEADLINE=y
+ CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_AS is not set
+ # CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_CFQ=y
+ # CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_DEFAULT_IOSCHED="cfq"
+ CONFIG_FREEZER=y
+
+ #
+@@ -136,12 +153,14 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_VERSATILE is not set
+ # CONFIG_ARCH_AT91 is not set
+ # CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
+ # CONFIG_ARCH_EBSA110 is not set
+ # CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_STMP3XXX is not set
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+ # CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+@@ -150,24 +169,25 @@ CONFIG_FREEZER=y
+ # CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
+ # CONFIG_ARCH_KIRKWOOD is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+ # CONFIG_ARCH_LOKI is not set
+ # CONFIG_ARCH_MV78XX0 is not set
+-# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_S3C64XX is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
+ # CONFIG_ARCH_DAVINCI is not set
+ CONFIG_ARCH_OMAP=y
+-# CONFIG_ARCH_MSM is not set
+-# CONFIG_ARCH_W90X900 is not set
+
+ #
+ # TI OMAP Implementations
+@@ -176,33 +196,28 @@ CONFIG_ARCH_OMAP_OTG=y
+ # CONFIG_ARCH_OMAP1 is not set
+ # CONFIG_ARCH_OMAP2 is not set
+ CONFIG_ARCH_OMAP3=y
++# CONFIG_ARCH_OMAP4 is not set
+
+ #
+ # OMAP Feature Selections
+ #
+ # CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+ # CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+-CONFIG_OMAP_SMARTREFLEX=y
+-# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+-CONFIG_OMAP_RESET_CLOCKS=y
+-CONFIG_OMAP_BOOT_TAG=y
+-CONFIG_OMAP_BOOT_REASON=y
+-# CONFIG_OMAP_COMPONENT_VERSION is not set
+-# CONFIG_OMAP_GPIO_SWITCH is not set
++# CONFIG_OMAP_RESET_CLOCKS is not set
+ CONFIG_OMAP_MUX=y
+ CONFIG_OMAP_MUX_DEBUG=y
+ CONFIG_OMAP_MUX_WARNINGS=y
+-# CONFIG_OMAP_MCBSP is not set
++CONFIG_OMAP_MCBSP=y
+ # CONFIG_OMAP_MBOX_FWK is not set
+ # CONFIG_OMAP_MPU_TIMER is not set
+ CONFIG_OMAP_32K_TIMER=y
+ CONFIG_OMAP_32K_TIMER_HZ=128
+-CONFIG_OMAP_TICK_GPTIMER=1
+ CONFIG_OMAP_DM_TIMER=y
+ CONFIG_OMAP_LL_DEBUG_UART1=y
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART3 is not set
+-CONFIG_OMAP_SERIAL_WAKE=y
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
+ CONFIG_ARCH_OMAP34XX=y
+ CONFIG_ARCH_OMAP3430=y
+
+@@ -210,12 +225,13 @@ CONFIG_ARCH_OMAP3430=y
+ # OMAP Board Type
+ #
+ # CONFIG_MACH_NOKIA_RX51 is not set
+-# CONFIG_MACH_OMAP_LDP is not set
++CONFIG_MACH_OMAP_LDP=y
+ CONFIG_MACH_OMAP_3430SDP=y
+ # CONFIG_MACH_OMAP3EVM is not set
+-# CONFIG_MACH_OMAP3_BEAGLE is not set
+-# CONFIG_MACH_OVERO is not set
+-# CONFIG_MACH_OMAP3_PANDORA is not set
++CONFIG_MACH_OMAP3_BEAGLE=y
++CONFIG_MACH_OVERO=y
++CONFIG_MACH_OMAP3_PANDORA=y
++# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+ #
+ # Processor Type
+@@ -238,12 +254,15 @@ CONFIG_CPU_CP15_MMU=y
+ # Processor Features
+ #
+ CONFIG_ARM_THUMB=y
+-# CONFIG_ARM_THUMBEE is not set
++CONFIG_ARM_THUMBEE=y
+ # CONFIG_CPU_ICACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_BPREDICT_DISABLE is not set
+ CONFIG_HAS_TLS_REG=y
+-# CONFIG_OUTER_CACHE is not set
++# CONFIG_ARM_ERRATA_430973 is not set
++# CONFIG_ARM_ERRATA_458693 is not set
++# CONFIG_ARM_ERRATA_460075 is not set
++CONFIG_COMMON_CLKDEV=y
+
+ #
+ # Bus support
+@@ -266,10 +285,10 @@ CONFIG_PAGE_OFFSET=0xC0000000
+ # CONFIG_PREEMPT is not set
+ CONFIG_HZ=128
+ CONFIG_AEABI=y
+-CONFIG_OABI_COMPAT=y
+-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_OABI_COMPAT is not set
+ # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+ # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++# CONFIG_HIGHMEM is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+@@ -281,23 +300,41 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_PHYS_ADDR_T_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=0
+ CONFIG_VIRT_TO_BUS=y
+-CONFIG_UNEVICTABLE_LRU=y
+-# CONFIG_LEDS is not set
++CONFIG_HAVE_MLOCK=y
++CONFIG_HAVE_MLOCKED_PAGE_BIT=y
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_LEDS=y
+ CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+ #
+ # Boot options
+ #
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
++CONFIG_CMDLINE="console=ttyS2,115200 root=/dev/mmcblk0p3 rootwait debug"
+ # CONFIG_XIP_KERNEL is not set
+-# CONFIG_KEXEC is not set
++CONFIG_KEXEC=y
++CONFIG_ATAGS_PROC=y
+
+ #
+ # CPU Power Management
+ #
+-# CONFIG_CPU_FREQ is not set
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_STAT_DETAILS=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+ # CONFIG_CPU_IDLE is not set
+
+ #
+@@ -307,20 +344,16 @@ CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.16
+ #
+ # At least one emulation must be selected
+ #
+-CONFIG_FPE_NWFPE=y
+-# CONFIG_FPE_NWFPE_XP is not set
+-# CONFIG_FPE_FASTFPE is not set
+ CONFIG_VFP=y
+ CONFIG_VFPv3=y
+-# CONFIG_NEON is not set
++CONFIG_NEON=y
+
+ #
+ # Userspace binary formats
+ #
+ CONFIG_BINFMT_ELF=y
+-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+ CONFIG_HAVE_AOUT=y
+-# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_AOUT=m
+ CONFIG_BINFMT_MISC=y
+
+ #
+@@ -338,9 +371,8 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-CONFIG_COMPAT_NET_DEV_OPS=y
+ CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
++CONFIG_PACKET_MMAP=y
+ CONFIG_UNIX=y
+ CONFIG_XFRM=y
+ # CONFIG_XFRM_USER is not set
+@@ -365,7 +397,7 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
+ CONFIG_INET_XFRM_MODE_TRANSPORT=y
+ CONFIG_INET_XFRM_MODE_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_BEET=y
+@@ -376,7 +408,25 @@ CONFIG_INET_TCP_DIAG=y
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ # CONFIG_IP_DCCP is not set
+@@ -394,6 +444,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
++# CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_DCB is not set
+
+@@ -401,18 +453,62 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
++# CONFIG_NET_DROP_MONITOR is not set
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+-# CONFIG_BT is not set
++CONFIG_BT=y
++CONFIG_BT_L2CAP=y
++CONFIG_BT_SCO=y
++CONFIG_BT_RFCOMM=y
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=y
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=y
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIBTUSB is not set
++# CONFIG_BT_HCIBTSDIO is not set
++CONFIG_BT_HCIUART=y
++CONFIG_BT_HCIUART_H4=y
++CONFIG_BT_HCIUART_BCSP=y
++# CONFIG_BT_HCIUART_LL is not set
++CONFIG_BT_HCIBCM203X=y
++CONFIG_BT_HCIBPA10X=y
++# CONFIG_BT_HCIBFUSB is not set
++# CONFIG_BT_HCIVHCI is not set
+ # CONFIG_AF_RXRPC is not set
+-# CONFIG_PHONET is not set
+ CONFIG_WIRELESS=y
+-# CONFIG_CFG80211 is not set
++CONFIG_CFG80211=y
++# CONFIG_CFG80211_REG_DEBUG is not set
++# CONFIG_CFG80211_DEBUGFS is not set
+ CONFIG_WIRELESS_OLD_REGULATORY=y
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_LIB80211 is not set
+-# CONFIG_MAC80211 is not set
++CONFIG_WIRELESS_EXT=y
++CONFIG_WIRELESS_EXT_SYSFS=y
++CONFIG_LIB80211=y
++CONFIG_LIB80211_CRYPT_WEP=m
++CONFIG_LIB80211_CRYPT_CCMP=m
++CONFIG_LIB80211_CRYPT_TKIP=m
++# CONFIG_LIB80211_DEBUG is not set
++CONFIG_MAC80211=y
++CONFIG_MAC80211_DEFAULT_PS=y
++CONFIG_MAC80211_DEFAULT_PS_VALUE=1
++
++#
++# Rate control algorithm selection
++#
++CONFIG_MAC80211_RC_PID=y
++# CONFIG_MAC80211_RC_MINSTREL is not set
++CONFIG_MAC80211_RC_DEFAULT_PID=y
++# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
++CONFIG_MAC80211_RC_DEFAULT="pid"
++# CONFIG_MAC80211_MESH is not set
++CONFIG_MAC80211_LEDS=y
++# CONFIG_MAC80211_DEBUGFS is not set
++# CONFIG_MAC80211_DEBUG_MENU is not set
+ # CONFIG_WIMAX is not set
+ # CONFIG_RFKILL is not set
+ # CONFIG_NET_9P is not set
+@@ -427,7 +523,9 @@ CONFIG_WIRELESS_OLD_REGULATORY=y
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
+ # CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+@@ -438,7 +536,7 @@ CONFIG_MTD_CONCAT=y
+ CONFIG_MTD_PARTITIONS=y
+ # CONFIG_MTD_TESTS is not set
+ # CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_CMDLINE_PARTS is not set
+ # CONFIG_MTD_AFS_PARTS is not set
+ # CONFIG_MTD_AR7_PARTS is not set
+
+@@ -458,10 +556,8 @@ CONFIG_MTD_BLOCK=y
+ #
+ # RAM/ROM/Flash chip drivers
+ #
+-CONFIG_MTD_CFI=y
++# CONFIG_MTD_CFI is not set
+ # CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+ CONFIG_MTD_MAP_BANK_WIDTH_1=y
+ CONFIG_MTD_MAP_BANK_WIDTH_2=y
+ CONFIG_MTD_MAP_BANK_WIDTH_4=y
+@@ -472,10 +568,6 @@ CONFIG_MTD_CFI_I1=y
+ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_CFI_I4 is not set
+ # CONFIG_MTD_CFI_I8 is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-# CONFIG_MTD_CFI_AMDSTD is not set
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+@@ -484,9 +576,6 @@ CONFIG_MTD_CFI_UTIL=y
+ # Mapping drivers for chip access
+ #
+ # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_ARM_INTEGRATOR is not set
+-CONFIG_MTD_OMAP_NOR=y
+ # CONFIG_MTD_PLATRAM is not set
+
+ #
+@@ -507,22 +596,16 @@ CONFIG_MTD_OMAP_NOR=y
+ # CONFIG_MTD_DOC2001PLUS is not set
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+-CONFIG_MTD_NAND_ECC_SMC=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
+ # CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ # CONFIG_MTD_NAND_GPIO is not set
+-CONFIG_MTD_NAND_OMAP2=y
++# CONFIG_MTD_NAND_OMAP2 is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ # CONFIG_MTD_NAND_NANDSIM is not set
+ # CONFIG_MTD_NAND_PLATFORM is not set
+ # CONFIG_MTD_ALAUDA is not set
+-CONFIG_MTD_ONENAND=y
+-CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+-# CONFIG_MTD_ONENAND_GENERIC is not set
+-CONFIG_MTD_ONENAND_OMAP2=y
+-# CONFIG_MTD_ONENAND_OTP is not set
+-# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+-# CONFIG_MTD_ONENAND_SIM is not set
++# CONFIG_MTD_ONENAND is not set
+
+ #
+ # LPDDR flash memory drivers
+@@ -537,19 +620,23 @@ CONFIG_MTD_ONENAND_OMAP2=y
+ CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_CRYPTOLOOP=m
+ # CONFIG_BLK_DEV_NBD is not set
+ # CONFIG_BLK_DEV_UB is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=16384
+ # CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_CDROM_PKTCDVD_BUFFERS=8
++# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+ # CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
+ CONFIG_MISC_DEVICES=y
+ # CONFIG_ICS932S401 is not set
+ # CONFIG_OMAP_STI is not set
+ # CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_ISL29003 is not set
+ # CONFIG_C2PORT is not set
+
+ #
+@@ -558,14 +645,15 @@ CONFIG_MISC_DEVICES=y
+ # CONFIG_EEPROM_AT24 is not set
+ # CONFIG_EEPROM_AT25 is not set
+ # CONFIG_EEPROM_LEGACY is not set
+-# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_EEPROM_MAX6875 is not set
++CONFIG_EEPROM_93CX6=m
+ CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+
+ #
+ # SCSI device support
+ #
+-# CONFIG_RAID_ATTRS is not set
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=y
+ CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+@@ -579,13 +667,9 @@ CONFIG_BLK_DEV_SD=y
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
++CONFIG_CHR_DEV_SG=m
+ # CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ # CONFIG_SCSI_SCAN_ASYNC is not set
+@@ -602,26 +686,69 @@ CONFIG_SCSI_WAIT_SCAN=m
+ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
+ # CONFIG_SCSI_DEBUG is not set
+ # CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
+ # CONFIG_ATA is not set
+-# CONFIG_MD is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=m
++CONFIG_MD_LINEAR=m
++CONFIG_MD_RAID0=m
++CONFIG_MD_RAID1=m
++CONFIG_MD_RAID10=m
++CONFIG_MD_RAID456=m
++CONFIG_MD_RAID6_PQ=m
++CONFIG_MD_MULTIPATH=m
++CONFIG_MD_FAULTY=m
++CONFIG_BLK_DEV_DM=m
++# CONFIG_DM_DEBUG is not set
++CONFIG_DM_CRYPT=m
++CONFIG_DM_SNAPSHOT=m
++CONFIG_DM_MIRROR=m
++# CONFIG_DM_LOG_USERSPACE is not set
++CONFIG_DM_ZERO=m
++CONFIG_DM_MULTIPATH=m
++# CONFIG_DM_MULTIPATH_QL is not set
++# CONFIG_DM_MULTIPATH_ST is not set
++CONFIG_DM_DELAY=m
++# CONFIG_DM_UEVENT is not set
+ CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
++CONFIG_DUMMY=m
+ # CONFIG_BONDING is not set
+ # CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
++CONFIG_TUN=m
+ # CONFIG_VETH is not set
+-# CONFIG_PHYLIB is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++CONFIG_SMSC_PHY=y
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_NATIONAL_PHY is not set
++# CONFIG_STE10XP is not set
++# CONFIG_LSI_ET1011C_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ # CONFIG_AX88796 is not set
+ CONFIG_SMC91X=y
+ # CONFIG_DM9000 is not set
+ # CONFIG_ENC28J60 is not set
+-# CONFIG_SMC911X is not set
+-# CONFIG_SMSC911X is not set
++# CONFIG_ETHOC is not set
++CONFIG_SMC911X=m
++CONFIG_SMSC911X=m
+ # CONFIG_DNET is not set
+ # CONFIG_IBM_NEW_EMAC_ZMII is not set
+ # CONFIG_IBM_NEW_EMAC_RGMII is not set
+@@ -631,15 +758,41 @@ CONFIG_SMC91X=y
+ # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+ # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+ # CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-CONFIG_NETDEV_10000=y
++# CONFIG_KS8842 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
+
+ #
+ # Wireless LAN
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_IWLWIFI_LEDS is not set
++CONFIG_WLAN_80211=y
++CONFIG_LIBERTAS=y
++CONFIG_LIBERTAS_USB=y
++CONFIG_LIBERTAS_SDIO=y
++# CONFIG_LIBERTAS_SPI is not set
++CONFIG_LIBERTAS_DEBUG=y
++# CONFIG_LIBERTAS_THINFIRM is not set
++# CONFIG_AT76C50X_USB is not set
++CONFIG_USB_ZD1201=m
++# CONFIG_USB_NET_RNDIS_WLAN is not set
++CONFIG_RTL8187=m
++CONFIG_RTL8187_LEDS=y
++# CONFIG_MAC80211_HWSIM is not set
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++# CONFIG_P54_SPI is not set
++CONFIG_P54_LEDS=y
++# CONFIG_AR9170_USB is not set
++CONFIG_HOSTAP=m
++CONFIG_HOSTAP_FIRMWARE=y
++CONFIG_HOSTAP_FIRMWARE_NVRAM=y
++# CONFIG_B43 is not set
++# CONFIG_B43LEGACY is not set
++# CONFIG_ZD1211RW is not set
++# CONFIG_RT2X00 is not set
++# CONFIG_WL12XX is not set
++# CONFIG_IWM is not set
+
+ #
+ # Enable WiMAX (Networking options) to see the WiMAX drivers
+@@ -648,14 +801,43 @@ CONFIG_NETDEV_10000=y
+ #
+ # USB Network Adapters
+ #
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=y
++CONFIG_USB_NET_CDCETHER=y
++# CONFIG_USB_NET_CDC_EEM is not set
++CONFIG_USB_NET_DM9601=m
++# CONFIG_USB_NET_SMSC95XX is not set
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_RNDIS_HOST=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_BELKIN=y
++CONFIG_USB_ARMLINUX=y
++CONFIG_USB_EPSON2888=y
++CONFIG_USB_KC2190=y
++CONFIG_USB_NET_ZAURUS=m
++# CONFIG_USB_NET_INT51X1 is not set
+ # CONFIG_WAN is not set
+-# CONFIG_PPP is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_MPPE=m
++CONFIG_PPPOE=m
++# CONFIG_PPPOL2TP is not set
+ # CONFIG_SLIP is not set
++CONFIG_SLHC=m
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+@@ -671,7 +853,10 @@ CONFIG_INPUT=y
+ #
+ # Userland interfaces
+ #
+-# CONFIG_INPUT_MOUSEDEV is not set
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_EVBUG is not set
+@@ -686,34 +871,34 @@ CONFIG_INPUT_KEYBOARD=y
+ # CONFIG_KEYBOARD_XTKBD is not set
+ # CONFIG_KEYBOARD_NEWTON is not set
+ # CONFIG_KEYBOARD_STOWAWAY is not set
+-CONFIG_KEYBOARD_TWL4030=y
++# CONFIG_KEYBOARD_LM8323 is not set
+ # CONFIG_KEYBOARD_GPIO is not set
+-# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+ # CONFIG_INPUT_TABLET is not set
+-CONFIG_INPUT_TOUCHSCREEN=y
+-CONFIG_TOUCHSCREEN_ADS7846=y
+-# CONFIG_TOUCHSCREEN_FUJITSU is not set
+-# CONFIG_TOUCHSCREEN_GUNZE is not set
+-# CONFIG_TOUCHSCREEN_ELO is not set
+-# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+-# CONFIG_TOUCHSCREEN_MTOUCH is not set
+-# CONFIG_TOUCHSCREEN_INEXIO is not set
+-# CONFIG_TOUCHSCREEN_MK712 is not set
+-# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+-# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+-# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+-# CONFIG_TOUCHSCREEN_TSC2005 is not set
+-# CONFIG_TOUCHSCREEN_TSC210X is not set
+-# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+-# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+-# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+
+ #
+ # Hardware I/O ports
+ #
+-# CONFIG_SERIO is not set
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
+ # CONFIG_GAMEPORT is not set
+
+ #
+@@ -723,7 +908,7 @@ CONFIG_VT=y
+ CONFIG_CONSOLE_TRANSLATIONS=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_VT_HW_CONSOLE_BINDING=y
+ CONFIG_DEVKMEM=y
+ # CONFIG_SERIAL_NONSTANDARD is not set
+
+@@ -743,6 +928,7 @@ CONFIG_SERIAL_8250_RSA=y
+ #
+ # Non-8250 serial port support
+ #
++# CONFIG_SERIAL_MAX3100 is not set
+ CONFIG_SERIAL_CORE=y
+ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+@@ -750,6 +936,7 @@ CONFIG_UNIX98_PTYS=y
+ # CONFIG_LEGACY_PTYS is not set
+ # CONFIG_IPMI_HANDLER is not set
+ CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
+ # CONFIG_TCG_TPM is not set
+@@ -765,6 +952,7 @@ CONFIG_I2C_HELPER_AUTO=y
+ #
+ # I2C system bus drivers (mostly embedded / system-on-chip)
+ #
++# CONFIG_I2C_DESIGNWARE is not set
+ # CONFIG_I2C_GPIO is not set
+ # CONFIG_I2C_OCORES is not set
+ CONFIG_I2C_OMAP=y
+@@ -790,10 +978,6 @@ CONFIG_I2C_OMAP=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TWL4030_MADC is not set
+-# CONFIG_TWL4030_POWEROFF is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+@@ -813,14 +997,12 @@ CONFIG_SPI_OMAP24XX=y
+ #
+ # SPI Protocol Masters
+ #
+-# CONFIG_SPI_TSC210X is not set
+-# CONFIG_SPI_TSC2301 is not set
+ # CONFIG_SPI_SPIDEV is not set
+ # CONFIG_SPI_TLE62X0 is not set
+ CONFIG_ARCH_REQUIRE_GPIOLIB=y
+ CONFIG_GPIOLIB=y
+-# CONFIG_DEBUG_GPIO is not set
+-# CONFIG_GPIO_SYSFS is not set
++CONFIG_DEBUG_GPIO=y
++CONFIG_GPIO_SYSFS=y
+
+ #
+ # Memory mapped GPIO expanders:
+@@ -844,8 +1026,78 @@ CONFIG_GPIO_TWL4030=y
+ # CONFIG_GPIO_MAX7301 is not set
+ # CONFIG_GPIO_MCP23S08 is not set
+ # CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
++CONFIG_POWER_SUPPLY=m
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++# CONFIG_PDA_POWER is not set
++# CONFIG_BATTERY_DS2760 is not set
++# CONFIG_BATTERY_BQ27x00 is not set
++# CONFIG_BATTERY_MAX17040 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ADT7475 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_G760A is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_LTC4215 is not set
++# CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_LM95241 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_SHT15 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_TMP401 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_TSC210X is not set
++# CONFIG_SENSORS_OMAP34XX is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
+ # CONFIG_THERMAL is not set
+ # CONFIG_THERMAL_HWMON is not set
+ CONFIG_WATCHDOG=y
+@@ -855,7 +1107,8 @@ CONFIG_WATCHDOG_NOWAYOUT=y
+ # Watchdog Device Drivers
+ #
+ # CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_OMAP_WATCHDOG=y
++# CONFIG_OMAP_WATCHDOG is not set
++# CONFIG_TWL4030_WATCHDOG is not set
+
+ #
+ # USB-based Watchdog Cards
+@@ -878,7 +1131,6 @@ CONFIG_SSB_POSSIBLE=y
+ # CONFIG_HTC_PASIC3 is not set
+ # CONFIG_TPS65010 is not set
+ CONFIG_TWL4030_CORE=y
+-# CONFIG_TWL4030_POWER is not set
+ # CONFIG_MFD_TMIO is not set
+ # CONFIG_MFD_T7L66XB is not set
+ # CONFIG_MFD_TC6387XB is not set
+@@ -887,29 +1139,15 @@ CONFIG_TWL4030_CORE=y
+ # CONFIG_MFD_WM8400 is not set
+ # CONFIG_MFD_WM8350_I2C is not set
+ # CONFIG_MFD_PCF50633 is not set
+-
+-#
+-# Multimedia devices
+-#
+-
+-#
+-# Multimedia core support
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_VIDEO_MEDIA is not set
+-
+-#
+-# Multimedia drivers
+-#
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_AB3100_CORE is not set
++# CONFIG_EZX_PCAP is not set
++# CONFIG_MEDIA_SUPPORT is not set
+
+ #
+ # Graphics support
+ #
+ # CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+ # CONFIG_FIRMWARE_EDID is not set
+ # CONFIG_FB_DDC is not set
+@@ -936,10 +1174,11 @@ CONFIG_FB_CFB_IMAGEBLIT=m
+ # CONFIG_FB_VIRTUAL is not set
+ # CONFIG_FB_METRONOME is not set
+ # CONFIG_FB_MB862XX is not set
++# CONFIG_FB_BROADSHEET is not set
+ # CONFIG_FB_OMAP_LCD_VGA is not set
+ # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+ CONFIG_OMAP2_DSS=m
+-CONFIG_OMAP2_DSS_VRAM_SIZE=8
++CONFIG_OMAP2_VRAM_SIZE=8
+ CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+ # CONFIG_OMAP2_DSS_RFBI is not set
+ CONFIG_OMAP2_DSS_VENC=y
+@@ -965,7 +1204,11 @@ CONFIG_FB_OMAP2_NUM_FBS=3
+ #
+ # Display device support
+ #
+-# CONFIG_DISPLAY_SUPPORT is not set
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
+
+ #
+ # Console display driver support
+@@ -977,7 +1220,7 @@ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_SOUND is not set
+ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
++CONFIG_HID_DEBUG=y
+ # CONFIG_HIDRAW is not set
+
+ #
+@@ -990,28 +1233,35 @@ CONFIG_USB_HID=y
+ #
+ # Special HID drivers
+ #
+-CONFIG_HID_COMPAT=y
+-# CONFIG_HID_A4TECH is not set
+-# CONFIG_HID_APPLE is not set
+-# CONFIG_HID_BELKIN is not set
+-# CONFIG_HID_CHERRY is not set
+-# CONFIG_HID_CHICONY is not set
+-# CONFIG_HID_CYPRESS is not set
+-# CONFIG_HID_EZKEY is not set
+-# CONFIG_HID_GYRATION is not set
+-# CONFIG_HID_LOGITECH is not set
+-# CONFIG_HID_MICROSOFT is not set
+-# CONFIG_HID_MONTEREY is not set
++CONFIG_HID_A4TECH=y
++CONFIG_HID_APPLE=y
++CONFIG_HID_BELKIN=y
++CONFIG_HID_CHERRY=y
++CONFIG_HID_CHICONY=y
++CONFIG_HID_CYPRESS=y
++# CONFIG_HID_DRAGONRISE is not set
++CONFIG_HID_EZKEY=y
++# CONFIG_HID_KYE is not set
++CONFIG_HID_GYRATION=y
++# CONFIG_HID_KENSINGTON is not set
++CONFIG_HID_LOGITECH=y
++# CONFIG_LOGITECH_FF is not set
++# CONFIG_LOGIRUMBLEPAD2_FF is not set
++CONFIG_HID_MICROSOFT=y
++CONFIG_HID_MONTEREY=y
+ # CONFIG_HID_NTRIG is not set
+-# CONFIG_HID_PANTHERLORD is not set
+-# CONFIG_HID_PETALYNX is not set
+-# CONFIG_HID_SAMSUNG is not set
+-# CONFIG_HID_SONY is not set
+-# CONFIG_HID_SUNPLUS is not set
+-# CONFIG_GREENASIA_FF is not set
++CONFIG_HID_PANTHERLORD=y
++# CONFIG_PANTHERLORD_FF is not set
++CONFIG_HID_PETALYNX=y
++CONFIG_HID_SAMSUNG=y
++CONFIG_HID_SONY=y
++CONFIG_HID_SUNPLUS=y
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
+ # CONFIG_HID_TOPSEED is not set
+-# CONFIG_THRUSTMASTER_FF is not set
+-# CONFIG_ZEROPLUS_FF is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_WACOM is not set
++# CONFIG_HID_ZEROPLUS is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+@@ -1024,8 +1274,8 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_DEVICE_CLASS is not set
+-# CONFIG_USB_DYNAMIC_MINORS is not set
++CONFIG_USB_DEVICE_CLASS=y
++CONFIG_USB_DYNAMIC_MINORS=y
+ CONFIG_USB_SUSPEND=y
+ CONFIG_USB_OTG=y
+ # CONFIG_USB_OTG_WHITELIST is not set
+@@ -1038,13 +1288,10 @@ CONFIG_USB_MON=y
+ # USB Host Controller Drivers
+ #
+ # CONFIG_USB_C67X00_HCD is not set
+-CONFIG_USB_EHCI_HCD=m
+-CONFIG_OMAP_EHCI_PHY_MODE=y
+-# CONFIG_OMAP_EHCI_TLL_MODE is not set
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_HCD is not set
+ # CONFIG_USB_OXU210HP_HCD is not set
+ # CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
+ # CONFIG_USB_OHCI_HCD is not set
+ # CONFIG_USB_SL811_HCD is not set
+ # CONFIG_USB_R8A66597_HCD is not set
+@@ -1060,28 +1307,26 @@ CONFIG_USB_MUSB_SOC=y
+ CONFIG_USB_MUSB_OTG=y
+ CONFIG_USB_GADGET_MUSB_HDRC=y
+ CONFIG_USB_MUSB_HDRC_HCD=y
+-# CONFIG_MUSB_PIO_ONLY is not set
+-CONFIG_USB_INVENTRA_DMA=y
+-# CONFIG_USB_TI_CPPI_DMA is not set
++CONFIG_MUSB_PIO_ONLY=y
+ # CONFIG_USB_MUSB_DEBUG is not set
+
+ #
+ # USB Device Class drivers
+ #
+ # CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-# CONFIG_USB_WDM is not set
++CONFIG_USB_PRINTER=y
++CONFIG_USB_WDM=y
+ # CONFIG_USB_TMC is not set
+
+ #
+-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+ #
+
+ #
+-# see USB_STORAGE Help for more information
++# also be needed; see USB_STORAGE Help for more info
+ #
+ CONFIG_USB_STORAGE=y
+-CONFIG_USB_STORAGE_DEBUG=y
++# CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
+ # CONFIG_USB_STORAGE_ISD200 is not set
+@@ -1120,7 +1365,6 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+ # CONFIG_USB_IDMOUSE is not set
+ # CONFIG_USB_FTDI_ELAN is not set
+ # CONFIG_USB_APPLEDISPLAY is not set
+@@ -1128,12 +1372,12 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
+ # CONFIG_USB_IOWARRIOR is not set
+-CONFIG_USB_TEST=y
++# CONFIG_USB_TEST is not set
+ # CONFIG_USB_ISIGHTFW is not set
+ # CONFIG_USB_VST is not set
+ CONFIG_USB_GADGET=y
+-CONFIG_USB_GADGET_DEBUG=y
+-CONFIG_USB_GADGET_DEBUG_FILES=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
+ # CONFIG_USB_GADGET_DEBUG_FS is not set
+ CONFIG_USB_GADGET_VBUS_DRAW=2
+ CONFIG_USB_GADGET_SELECTED=y
+@@ -1144,6 +1388,7 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_OMAP is not set
+ # CONFIG_USB_GADGET_PXA25X is not set
+ # CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C_HSOTG is not set
+ # CONFIG_USB_GADGET_S3C2410 is not set
+ # CONFIG_USB_GADGET_IMX is not set
+ # CONFIG_USB_GADGET_M66592 is not set
+@@ -1152,11 +1397,13 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_CI13XXX is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+ CONFIG_USB_GADGET_DUALSPEED=y
+-CONFIG_USB_ZERO=m
+-# CONFIG_USB_ZERO_HNPTEST is not set
+-# CONFIG_USB_ETH is not set
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
++CONFIG_USB_ETH=m
++CONFIG_USB_ETH_RNDIS=y
+ # CONFIG_USB_GADGETFS is not set
+ # CONFIG_USB_FILE_STORAGE is not set
+ # CONFIG_USB_G_SERIAL is not set
+@@ -1171,27 +1418,57 @@ CONFIG_USB_OTG_UTILS=y
+ # CONFIG_USB_GPIO_VBUS is not set
+ # CONFIG_ISP1301_OMAP is not set
+ CONFIG_TWL4030_USB=y
++# CONFIG_NOP_USB_XCEIV is not set
+ CONFIG_MMC=y
+ # CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
++CONFIG_MMC_UNSAFE_RESUME=y
+
+ #
+ # MMC/SD/SDIO Card Drivers
+ #
+ CONFIG_MMC_BLOCK=y
+ CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
++CONFIG_SDIO_UART=y
+ # CONFIG_MMC_TEST is not set
+
+ #
+ # MMC/SD/SDIO Host Controller Drivers
+ #
+ # CONFIG_MMC_SDHCI is not set
+-CONFIG_MMC_OMAP_HS=m
++CONFIG_MMC_OMAP_HS=y
+ # CONFIG_MMC_SPI is not set
+ # CONFIG_MEMSTICK is not set
+ # CONFIG_ACCESSIBILITY is not set
+-# CONFIG_NEW_LEDS is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_OMAP_DEBUG is not set
++# CONFIG_LEDS_OMAP is not set
++# CONFIG_LEDS_OMAP_PWM is not set
++# CONFIG_LEDS_PCA9532 is not set
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_GPIO_PLATFORM=y
++# CONFIG_LEDS_LP5521 is not set
++# CONFIG_LEDS_PCA955X is not set
++# CONFIG_LEDS_DAC124S085 is not set
++# CONFIG_LEDS_BD2802 is not set
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
++# CONFIG_LEDS_TRIGGER_GPIO is not set
++# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
++
++#
++# iptables trigger is under Netfilter config (LED target)
++#
+ CONFIG_RTC_LIB=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_HCTOSYS=y
+@@ -1224,6 +1501,7 @@ CONFIG_RTC_DRV_TWL4030=y
+ # CONFIG_RTC_DRV_S35390A is not set
+ # CONFIG_RTC_DRV_FM3130 is not set
+ # CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
+
+ #
+ # SPI RTC drivers
+@@ -1255,12 +1533,16 @@ CONFIG_RTC_DRV_TWL4030=y
+ # on-CPU RTC drivers
+ #
+ # CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
+ CONFIG_REGULATOR=y
+ # CONFIG_REGULATOR_DEBUG is not set
+ # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+ # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+ # CONFIG_REGULATOR_BQ24022 is not set
++# CONFIG_REGULATOR_MAX1586 is not set
+ CONFIG_REGULATOR_TWL4030=y
++# CONFIG_REGULATOR_LP3971 is not set
+ # CONFIG_UIO is not set
+ # CONFIG_STAGING is not set
+
+@@ -1276,17 +1558,24 @@ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ CONFIG_EXT3_FS=y
++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+ # CONFIG_EXT3_FS_XATTR is not set
+ # CONFIG_EXT4_FS is not set
+ CONFIG_JBD=y
+ # CONFIG_JBD_DEBUG is not set
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-CONFIG_FILE_LOCKING=y
+-# CONFIG_XFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_XFS_FS=m
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_POSIX_ACL is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_DEBUG is not set
++# CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+ # CONFIG_BTRFS_FS is not set
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
+ CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+@@ -1299,13 +1588,22 @@ CONFIG_QFMT_V2=y
+ CONFIG_QUOTACTL=y
+ # CONFIG_AUTOFS_FS is not set
+ # CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
++CONFIG_FUSE_FS=m
++# CONFIG_CUSE is not set
++
++#
++# Caches
++#
++# CONFIG_FSCACHE is not set
+
+ #
+ # CD-ROM/DVD Filesystems
+ #
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
+
+ #
+ # DOS/FAT/NT Filesystems
+@@ -1340,13 +1638,15 @@ CONFIG_JFFS2_FS=y
+ CONFIG_JFFS2_FS_DEBUG=0
+ CONFIG_JFFS2_FS_WRITEBUFFER=y
+ # CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_FS_POSIX_ACL=y
++CONFIG_JFFS2_FS_SECURITY=y
+ CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+ CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_LZO=y
+ CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
++CONFIG_JFFS2_RUBIN=y
+ # CONFIG_JFFS2_CMODE_NONE is not set
+ CONFIG_JFFS2_CMODE_PRIORITY=y
+ # CONFIG_JFFS2_CMODE_SIZE is not set
+@@ -1361,19 +1661,21 @@ CONFIG_JFFS2_CMODE_PRIORITY=y
+ # CONFIG_ROMFS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
++# CONFIG_NILFS2_FS is not set
+ CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+ CONFIG_NFS_V4=y
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+ # CONFIG_NFSD is not set
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=m
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_REGISTER_V4 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1461,11 +1763,16 @@ CONFIG_DEBUG_KERNEL=y
+ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_DETECT_HUNG_TASK=y
++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+ CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
+ # CONFIG_DEBUG_OBJECTS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_KMEMLEAK is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+@@ -1475,16 +1782,16 @@ CONFIG_DEBUG_MUTEXES=y
+ # CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_STACKTRACE=y
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+-CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_WRITECOUNT is not set
+ # CONFIG_DEBUG_MEMORY_INIT is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_DEBUG_SG is not set
+ # CONFIG_DEBUG_NOTIFIERS is not set
+-CONFIG_FRAME_POINTER=y
+ # CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+@@ -1492,22 +1799,33 @@ CONFIG_FRAME_POINTER=y
+ # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+ # CONFIG_FAULT_INJECTION is not set
+ # CONFIG_LATENCYTOP is not set
++# CONFIG_PAGE_POISONING is not set
++CONFIG_NOP_TRACER=y
+ CONFIG_HAVE_FUNCTION_TRACER=y
+-
+-#
+-# Tracers
+-#
++CONFIG_RING_BUFFER=y
++CONFIG_EVENT_TRACING=y
++CONFIG_CONTEXT_SWITCH_TRACER=y
++CONFIG_TRACING=y
++CONFIG_TRACING_SUPPORT=y
++CONFIG_FTRACE=y
+ # CONFIG_FUNCTION_TRACER is not set
+ # CONFIG_IRQSOFF_TRACER is not set
+ # CONFIG_SCHED_TRACER is not set
+-# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+ # CONFIG_BOOT_TRACER is not set
+-# CONFIG_TRACE_BRANCH_PROFILING is not set
++CONFIG_BRANCH_PROFILE_NONE=y
++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
++# CONFIG_PROFILE_ALL_BRANCHES is not set
+ # CONFIG_STACK_TRACER is not set
+-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_KMEMTRACE is not set
++# CONFIG_WORKQUEUE_TRACER is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_RING_BUFFER_BENCHMARK is not set
++# CONFIG_DYNAMIC_DEBUG is not set
+ # CONFIG_SAMPLES is not set
+ CONFIG_HAVE_ARCH_KGDB=y
+ # CONFIG_KGDB is not set
++CONFIG_ARM_UNWIND=y
+ CONFIG_DEBUG_USER=y
+ CONFIG_DEBUG_ERRORS=y
+ # CONFIG_DEBUG_STACK_USAGE is not set
+@@ -1520,6 +1838,10 @@ CONFIG_DEBUG_ERRORS=y
+ # CONFIG_SECURITY is not set
+ # CONFIG_SECURITYFS is not set
+ # CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_XOR_BLOCKS=m
++CONFIG_ASYNC_CORE=m
++CONFIG_ASYNC_MEMCPY=m
++CONFIG_ASYNC_XOR=m
+ CONFIG_CRYPTO=y
+
+ #
+@@ -1534,13 +1856,15 @@ CONFIG_CRYPTO_BLKCIPHER2=y
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_HASH2=y
+ CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP=y
+ CONFIG_CRYPTO_MANAGER=y
+ CONFIG_CRYPTO_MANAGER2=y
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_NULL=m
++CONFIG_CRYPTO_WORKQUEUE=y
++CONFIG_CRYPTO_CRYPTD=m
+ # CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_TEST is not set
++CONFIG_CRYPTO_TEST=m
+
+ #
+ # Authenticated Encryption with Associated Data
+@@ -1555,57 +1879,59 @@ CONFIG_CRYPTO_MANAGER2=y
+ CONFIG_CRYPTO_CBC=y
+ # CONFIG_CRYPTO_CTR is not set
+ # CONFIG_CRYPTO_CTS is not set
+-CONFIG_CRYPTO_ECB=m
+-# CONFIG_CRYPTO_LRW is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_LRW=m
+ CONFIG_CRYPTO_PCBC=m
+ # CONFIG_CRYPTO_XTS is not set
+
+ #
+ # Hash modes
+ #
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
++CONFIG_CRYPTO_HMAC=m
++CONFIG_CRYPTO_XCBC=m
+
+ #
+ # Digest
+ #
+ CONFIG_CRYPTO_CRC32C=y
+-# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD4=m
+ CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
++CONFIG_CRYPTO_MICHAEL_MIC=y
+ # CONFIG_CRYPTO_RMD128 is not set
+ # CONFIG_CRYPTO_RMD160 is not set
+ # CONFIG_CRYPTO_RMD256 is not set
+ # CONFIG_CRYPTO_RMD320 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_WP512 is not set
++CONFIG_CRYPTO_SHA1=m
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_WP512=m
+
+ #
+ # Ciphers
+ #
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_AES=y
++CONFIG_CRYPTO_ANUBIS=m
++CONFIG_CRYPTO_ARC4=y
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_CAMELLIA=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
+ CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
++CONFIG_CRYPTO_FCRYPT=m
++CONFIG_CRYPTO_KHAZAD=m
+ # CONFIG_CRYPTO_SALSA20 is not set
+ # CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+ #
+ # Compression
+ #
+-# CONFIG_CRYPTO_DEFLATE is not set
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_ZLIB is not set
+ # CONFIG_CRYPTO_LZO is not set
+
+ #
+@@ -1613,6 +1939,7 @@ CONFIG_CRYPTO_DES=y
+ #
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+ CONFIG_CRYPTO_HW=y
++CONFIG_BINARY_PRINTF=y
+
+ #
+ # Library routines
+@@ -1620,15 +1947,18 @@ CONFIG_CRYPTO_HW=y
+ CONFIG_BITREVERSE=y
+ CONFIG_GENERIC_FIND_LAST_BIT=y
+ CONFIG_CRC_CCITT=y
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_T10DIF is not set
+-# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC16=m
++CONFIG_CRC_T10DIF=y
++CONFIG_CRC_ITU_T=y
+ CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
++CONFIG_CRC7=y
+ CONFIG_LIBCRC32C=y
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++CONFIG_DECOMPRESS_GZIP=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_NLATTR=y
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0145-DSS2-BEAGLE-get-DSS2-working-again-on-beagle.patch b/recipes/linux/linux-omap-pm/dss2/0145-DSS2-BEAGLE-get-DSS2-working-again-on-beagle.patch
new file mode 100644
index 0000000000..dee24393c5
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0145-DSS2-BEAGLE-get-DSS2-working-again-on-beagle.patch
@@ -0,0 +1,724 @@
+From 9389c500be4538327d33d656b73f0830cbb24d8d Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Thu, 2 Jul 2009 17:03:35 +0300
+Subject: [PATCH 145/146] DSS2: BEAGLE: get DSS2 working again on beagle
+
+---
+ arch/arm/configs/dss_omap3_beagle_defconfig | 185 +++++++++++++++------------
+ arch/arm/mach-omap2/board-omap3beagle.c | 30 +---
+ 2 files changed, 111 insertions(+), 104 deletions(-)
+
+diff --git a/arch/arm/configs/dss_omap3_beagle_defconfig b/arch/arm/configs/dss_omap3_beagle_defconfig
+index 7143168..2d6a70f 100644
+--- a/arch/arm/configs/dss_omap3_beagle_defconfig
++++ b/arch/arm/configs/dss_omap3_beagle_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.29-omap1
+-# Thu Apr 2 11:24:09 2009
++# Linux kernel version: 2.6.31-rc1-omap1
++# Thu Jul 2 17:25:47 2009
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
+ CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_STACKTRACE_SUPPORT=y
+ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+@@ -18,13 +17,12 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
+
+ #
+ # General setup
+@@ -33,7 +31,7 @@ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+ CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_LOCALVERSION_AUTO is not set
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_SYSVIPC_SYSCTL=y
+@@ -65,6 +63,9 @@ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_NAMESPACES is not set
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+ CONFIG_ANON_INODES=y
+@@ -86,17 +87,29 @@ CONFIG_TIMERFD=y
+ CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+ CONFIG_AIO=y
++
++#
++# Performance Counters
++#
+ CONFIG_VM_EVENT_COUNTERS=y
++# CONFIG_STRIP_ASM_SYMS is not set
+ CONFIG_COMPAT_BRK=y
+ CONFIG_SLAB=y
+ # CONFIG_SLUB is not set
+ # CONFIG_SLOB is not set
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ CONFIG_HAVE_OPROFILE=y
+ # CONFIG_KPROBES is not set
+ CONFIG_HAVE_KPROBES=y
+ CONFIG_HAVE_KRETPROBES=y
+ CONFIG_HAVE_CLK=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++# CONFIG_SLOW_WORK is not set
+ CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -108,8 +121,7 @@ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_BLK_DEV_INTEGRITY is not set
+
+@@ -136,12 +148,14 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ # CONFIG_ARCH_VERSATILE is not set
+ # CONFIG_ARCH_AT91 is not set
+ # CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
+ # CONFIG_ARCH_EBSA110 is not set
+ # CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_STMP3XXX is not set
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+ # CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+@@ -150,24 +164,25 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ # CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
+ # CONFIG_ARCH_KIRKWOOD is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+ # CONFIG_ARCH_LOKI is not set
+ # CONFIG_ARCH_MV78XX0 is not set
+-# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_S3C64XX is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
+ # CONFIG_ARCH_DAVINCI is not set
+ CONFIG_ARCH_OMAP=y
+-# CONFIG_ARCH_MSM is not set
+-# CONFIG_ARCH_W90X900 is not set
+
+ #
+ # TI OMAP Implementations
+@@ -176,29 +191,26 @@ CONFIG_ARCH_OMAP_OTG=y
+ # CONFIG_ARCH_OMAP1 is not set
+ # CONFIG_ARCH_OMAP2 is not set
+ CONFIG_ARCH_OMAP3=y
++# CONFIG_ARCH_OMAP4 is not set
+
+ #
+ # OMAP Feature Selections
+ #
+ # CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+ # CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+-# CONFIG_OMAP_SMARTREFLEX is not set
+ # CONFIG_OMAP_RESET_CLOCKS is not set
+-CONFIG_OMAP_BOOT_TAG=y
+-CONFIG_OMAP_BOOT_REASON=y
+-# CONFIG_OMAP_COMPONENT_VERSION is not set
+-# CONFIG_OMAP_GPIO_SWITCH is not set
+ # CONFIG_OMAP_MUX is not set
+ # CONFIG_OMAP_MCBSP is not set
+ # CONFIG_OMAP_MBOX_FWK is not set
+ # CONFIG_OMAP_MPU_TIMER is not set
+ CONFIG_OMAP_32K_TIMER=y
+ CONFIG_OMAP_32K_TIMER_HZ=128
+-CONFIG_OMAP_TICK_GPTIMER=12
+ CONFIG_OMAP_DM_TIMER=y
+ # CONFIG_OMAP_LL_DEBUG_UART1 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+ CONFIG_OMAP_LL_DEBUG_UART3=y
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
+ CONFIG_ARCH_OMAP34XX=y
+ CONFIG_ARCH_OMAP3430=y
+
+@@ -212,6 +224,7 @@ CONFIG_ARCH_OMAP3430=y
+ CONFIG_MACH_OMAP3_BEAGLE=y
+ # CONFIG_MACH_OVERO is not set
+ # CONFIG_MACH_OMAP3_PANDORA is not set
++# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+ #
+ # Processor Type
+@@ -239,7 +252,10 @@ CONFIG_ARM_THUMB=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_BPREDICT_DISABLE is not set
+ CONFIG_HAS_TLS_REG=y
+-# CONFIG_OUTER_CACHE is not set
++# CONFIG_ARM_ERRATA_430973 is not set
++# CONFIG_ARM_ERRATA_458693 is not set
++# CONFIG_ARM_ERRATA_460075 is not set
++CONFIG_COMMON_CLKDEV=y
+
+ #
+ # Bus support
+@@ -263,9 +279,9 @@ CONFIG_PAGE_OFFSET=0xC0000000
+ CONFIG_HZ=128
+ CONFIG_AEABI=y
+ CONFIG_OABI_COMPAT=y
+-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+ # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+ # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++# CONFIG_HIGHMEM is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+@@ -277,16 +293,19 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_PHYS_ADDR_T_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=0
+ CONFIG_VIRT_TO_BUS=y
+-CONFIG_UNEVICTABLE_LRU=y
++CONFIG_HAVE_MLOCK=y
++CONFIG_HAVE_MLOCKED_PAGE_BIT=y
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+ #
+ # Boot options
+ #
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.2.14:/tftpboot/rootfs ip=192.168.2.15 nolock,rsize=1024,wsize=1024 rw"
++CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.2.14:/tftpboot/rootfs ip=192.168.2.15 nolock,rsize=1024,wsize=1024 rw console=ttyS2,115200n8"
+ # CONFIG_XIP_KERNEL is not set
+ # CONFIG_KEXEC is not set
+
+@@ -322,17 +341,13 @@ CONFIG_BINFMT_MISC=y
+ #
+ # Power management options
+ #
+-CONFIG_PM=y
+-# CONFIG_PM_DEBUG is not set
+-# CONFIG_SUSPEND is not set
+-# CONFIG_APM_EMULATION is not set
++# CONFIG_PM is not set
+ CONFIG_ARCH_SUSPEND_POSSIBLE=y
+ CONFIG_NET=y
+
+ #
+ # Networking options
+ #
+-CONFIG_COMPAT_NET_DEV_OPS=y
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+@@ -388,6 +403,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
++# CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
+ # CONFIG_NET_SCHED is not set
+ # CONFIG_DCB is not set
+
+@@ -400,13 +417,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
+ # CONFIG_AF_RXRPC is not set
+-# CONFIG_PHONET is not set
+ CONFIG_WIRELESS=y
+ # CONFIG_CFG80211 is not set
+-CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_OLD_REGULATORY is not set
+ # CONFIG_WIRELESS_EXT is not set
+ # CONFIG_LIB80211 is not set
+-# CONFIG_MAC80211 is not set
++
++#
++# CFG80211 needs to be enabled for MAC80211
++#
++CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+ # CONFIG_WIMAX is not set
+ # CONFIG_RFKILL is not set
+ # CONFIG_NET_9P is not set
+@@ -493,7 +513,7 @@ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_ECC_SMC is not set
+ # CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ # CONFIG_MTD_NAND_GPIO is not set
+-CONFIG_MTD_NAND_OMAP2=y
++# CONFIG_MTD_NAND_OMAP2 is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ # CONFIG_MTD_NAND_NANDSIM is not set
+@@ -521,6 +541,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384
+ # CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
+ # CONFIG_MISC_DEVICES is not set
+ CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+@@ -544,10 +565,6 @@ CONFIG_BLK_DEV_SD=y
+ # CONFIG_BLK_DEV_SR is not set
+ # CONFIG_CHR_DEV_SG is not set
+ # CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+@@ -565,8 +582,10 @@ CONFIG_SCSI_WAIT_SCAN=m
+ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
+ # CONFIG_SCSI_DEBUG is not set
+ # CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
+ # CONFIG_ATA is not set
+ # CONFIG_MD is not set
+ CONFIG_NETDEVICES=y
+@@ -585,7 +604,6 @@ CONFIG_NETDEVICES=y
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
+-# CONFIG_IWLWIFI_LEDS is not set
+
+ #
+ # Enable WiMAX (Networking options) to see the WiMAX drivers
+@@ -663,6 +681,7 @@ CONFIG_UNIX98_PTYS=y
+ # CONFIG_LEGACY_PTYS is not set
+ # CONFIG_IPMI_HANDLER is not set
+ CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
+ # CONFIG_TCG_TPM is not set
+@@ -678,6 +697,7 @@ CONFIG_I2C_HELPER_AUTO=y
+ #
+ # I2C system bus drivers (mostly embedded / system-on-chip)
+ #
++# CONFIG_I2C_DESIGNWARE is not set
+ # CONFIG_I2C_GPIO is not set
+ # CONFIG_I2C_OCORES is not set
+ CONFIG_I2C_OMAP=y
+@@ -702,10 +722,6 @@ CONFIG_I2C_OMAP=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TWL4030_MADC is not set
+-# CONFIG_TWL4030_POWEROFF is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+@@ -727,7 +743,7 @@ CONFIG_GPIOLIB=y
+ # CONFIG_GPIO_MAX732X is not set
+ # CONFIG_GPIO_PCA953X is not set
+ # CONFIG_GPIO_PCF857X is not set
+-CONFIG_GPIO_TWL4030=y
++# CONFIG_GPIO_TWL4030 is not set
+
+ #
+ # PCI GPIO expanders:
+@@ -759,7 +775,6 @@ CONFIG_SSB_POSSIBLE=y
+ # CONFIG_HTC_PASIC3 is not set
+ # CONFIG_TPS65010 is not set
+ CONFIG_TWL4030_CORE=y
+-# CONFIG_TWL4030_POWER is not set
+ # CONFIG_MFD_TMIO is not set
+ # CONFIG_MFD_T7L66XB is not set
+ # CONFIG_MFD_TC6387XB is not set
+@@ -768,22 +783,8 @@ CONFIG_TWL4030_CORE=y
+ # CONFIG_MFD_WM8400 is not set
+ # CONFIG_MFD_WM8350_I2C is not set
+ # CONFIG_MFD_PCF50633 is not set
+-
+-#
+-# Multimedia devices
+-#
+-
+-#
+-# Multimedia core support
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_VIDEO_MEDIA is not set
+-
+-#
+-# Multimedia drivers
+-#
+-CONFIG_DAB=y
++# CONFIG_AB3100_CORE is not set
++# CONFIG_MEDIA_SUPPORT is not set
+
+ #
+ # Graphics support
+@@ -816,9 +817,10 @@ CONFIG_FB_CFB_IMAGEBLIT=m
+ # CONFIG_FB_VIRTUAL is not set
+ # CONFIG_FB_METRONOME is not set
+ # CONFIG_FB_MB862XX is not set
++# CONFIG_FB_BROADSHEET is not set
+ # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+ CONFIG_OMAP2_DSS=m
+-CONFIG_OMAP2_DSS_VRAM_SIZE=12
++CONFIG_OMAP2_VRAM_SIZE=8
+ CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+ # CONFIG_OMAP2_DSS_RFBI is not set
+ CONFIG_OMAP2_DSS_VENC=y
+@@ -860,8 +862,8 @@ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ CONFIG_USB_ARCH_HAS_EHCI=y
+ # CONFIG_USB is not set
+-# CONFIG_USB_OTG_WHITELIST is not set
+-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++CONFIG_USB_OTG_WHITELIST=y
++CONFIG_USB_OTG_BLACKLIST_HUB=y
+ CONFIG_USB_MUSB_HDRC=y
+ CONFIG_USB_MUSB_SOC=y
+
+@@ -878,7 +880,7 @@ CONFIG_USB_INVENTRA_DMA=y
+ # CONFIG_USB_MUSB_DEBUG is not set
+
+ #
+-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+ #
+ CONFIG_USB_GADGET=y
+ # CONFIG_USB_GADGET_DEBUG is not set
+@@ -893,6 +895,7 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_OMAP is not set
+ # CONFIG_USB_GADGET_PXA25X is not set
+ # CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C_HSOTG is not set
+ # CONFIG_USB_GADGET_S3C2410 is not set
+ # CONFIG_USB_GADGET_IMX is not set
+ # CONFIG_USB_GADGET_M66592 is not set
+@@ -901,9 +904,11 @@ CONFIG_USB_GADGET_SELECTED=y
+ # CONFIG_USB_GADGET_CI13XXX is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+ CONFIG_USB_GADGET_DUALSPEED=y
+ # CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
+ CONFIG_USB_ETH=y
+ CONFIG_USB_ETH_RNDIS=y
+ # CONFIG_USB_GADGETFS is not set
+@@ -920,6 +925,7 @@ CONFIG_USB_OTG_UTILS=y
+ # CONFIG_USB_GPIO_VBUS is not set
+ # CONFIG_ISP1301_OMAP is not set
+ CONFIG_TWL4030_USB=y
++# CONFIG_NOP_USB_XCEIV is not set
+ CONFIG_MMC=y
+ # CONFIG_MMC_DEBUG is not set
+ # CONFIG_MMC_UNSAFE_RESUME is not set
+@@ -936,7 +942,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
+ # MMC/SD/SDIO Host Controller Drivers
+ #
+ # CONFIG_MMC_SDHCI is not set
+-CONFIG_MMC_OMAP_HS=y
++# CONFIG_MMC_OMAP_HS is not set
+ # CONFIG_MEMSTICK is not set
+ # CONFIG_ACCESSIBILITY is not set
+ # CONFIG_NEW_LEDS is not set
+@@ -968,10 +974,11 @@ CONFIG_RTC_INTF_DEV=y
+ # CONFIG_RTC_DRV_PCF8563 is not set
+ # CONFIG_RTC_DRV_PCF8583 is not set
+ # CONFIG_RTC_DRV_M41T80 is not set
+-CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_TWL4030 is not set
+ # CONFIG_RTC_DRV_S35390A is not set
+ # CONFIG_RTC_DRV_FM3130 is not set
+ # CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
+
+ #
+ # SPI RTC drivers
+@@ -996,12 +1003,16 @@ CONFIG_RTC_DRV_TWL4030=y
+ # on-CPU RTC drivers
+ #
+ # CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
+ CONFIG_REGULATOR=y
+ # CONFIG_REGULATOR_DEBUG is not set
+ # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+ # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+ # CONFIG_REGULATOR_BQ24022 is not set
++# CONFIG_REGULATOR_MAX1586 is not set
+ CONFIG_REGULATOR_TWL4030=y
++# CONFIG_REGULATOR_LP3971 is not set
+ # CONFIG_UIO is not set
+ # CONFIG_STAGING is not set
+
+@@ -1017,6 +1028,7 @@ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ CONFIG_EXT3_FS=y
++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+ # CONFIG_EXT3_FS_XATTR is not set
+ # CONFIG_EXT4_FS is not set
+ CONFIG_JBD=y
+@@ -1024,10 +1036,12 @@ CONFIG_JBD=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+-CONFIG_FILE_LOCKING=y
+ # CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+ # CONFIG_BTRFS_FS is not set
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
+ CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+@@ -1043,6 +1057,11 @@ CONFIG_QUOTACTL=y
+ # CONFIG_FUSE_FS is not set
+
+ #
++# Caches
++#
++# CONFIG_FSCACHE is not set
++
++#
+ # CD-ROM/DVD Filesystems
+ #
+ # CONFIG_ISO9660_FS is not set
+@@ -1098,11 +1117,13 @@ CONFIG_JFFS2_RTIME=y
+ # CONFIG_ROMFS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
++# CONFIG_NILFS2_FS is not set
+ CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+ CONFIG_NFS_V4=y
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+ # CONFIG_NFSD is not set
+ CONFIG_LOCKD=y
+@@ -1110,7 +1131,6 @@ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_REGISTER_V4 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1198,11 +1218,15 @@ CONFIG_DEBUG_KERNEL=y
+ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_DETECT_HUNG_TASK=y
++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+ CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+ # CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_OBJECTS is not set
+ # CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_KMEMLEAK is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+@@ -1221,7 +1245,6 @@ CONFIG_DEBUG_INFO=y
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_DEBUG_SG is not set
+ # CONFIG_DEBUG_NOTIFIERS is not set
+-CONFIG_FRAME_POINTER=y
+ # CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+@@ -1229,22 +1252,15 @@ CONFIG_FRAME_POINTER=y
+ # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+ # CONFIG_FAULT_INJECTION is not set
+ # CONFIG_LATENCYTOP is not set
++# CONFIG_PAGE_POISONING is not set
+ CONFIG_HAVE_FUNCTION_TRACER=y
+-
+-#
+-# Tracers
+-#
+-# CONFIG_FUNCTION_TRACER is not set
+-# CONFIG_IRQSOFF_TRACER is not set
+-# CONFIG_SCHED_TRACER is not set
+-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+-# CONFIG_BOOT_TRACER is not set
+-# CONFIG_TRACE_BRANCH_PROFILING is not set
+-# CONFIG_STACK_TRACER is not set
+-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++CONFIG_TRACING_SUPPORT=y
++# CONFIG_FTRACE is not set
++# CONFIG_DYNAMIC_DEBUG is not set
+ # CONFIG_SAMPLES is not set
+ CONFIG_HAVE_ARCH_KGDB=y
+ # CONFIG_KGDB is not set
++CONFIG_ARM_UNWIND=y
+ CONFIG_DEBUG_USER=y
+ CONFIG_DEBUG_ERRORS=y
+ # CONFIG_DEBUG_STACK_USAGE is not set
+@@ -1271,10 +1287,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_HASH2=y
+ CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP=y
+ CONFIG_CRYPTO_MANAGER=y
+ CONFIG_CRYPTO_MANAGER2=y
+ # CONFIG_CRYPTO_GF128MUL is not set
+ # CONFIG_CRYPTO_NULL is not set
++CONFIG_CRYPTO_WORKQUEUE=y
+ # CONFIG_CRYPTO_CRYPTD is not set
+ # CONFIG_CRYPTO_AUTHENC is not set
+ # CONFIG_CRYPTO_TEST is not set
+@@ -1343,6 +1361,7 @@ CONFIG_CRYPTO_DES=y
+ # Compression
+ #
+ # CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_ZLIB is not set
+ # CONFIG_CRYPTO_LZO is not set
+
+ #
+@@ -1350,6 +1369,7 @@ CONFIG_CRYPTO_DES=y
+ #
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+ CONFIG_CRYPTO_HW=y
++# CONFIG_BINARY_PRINTF is not set
+
+ #
+ # Library routines
+@@ -1365,7 +1385,8 @@ CONFIG_CRC32=y
+ CONFIG_LIBCRC32C=y
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
++CONFIG_DECOMPRESS_GZIP=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_NLATTR=y
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 977bbbe..25aa7b6 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -136,24 +136,11 @@ static struct omap_dss_device beagle_dvi_device = {
+
+ static int beagle_panel_enable_tv(struct omap_dss_device *dssdev)
+ {
+-#define ENABLE_VDAC_DEDICATED 0x03
+-#define ENABLE_VDAC_DEV_GRP 0x20
+-
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEDICATED,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+- ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+-
+ return 0;
+ }
+
+ static void beagle_panel_disable_tv(struct omap_dss_device *dssdev)
+ {
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEDICATED);
+- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+- TWL4030_VDAC_DEV_GRP);
+ }
+
+ static struct omap_dss_device beagle_tv_device = {
+@@ -222,15 +209,6 @@ static struct twl4030_hsmmc_info mmc[] = {
+ {} /* Terminator */
+ };
+
+-static struct platform_device omap3_beagle_lcd_device = {
+- .name = "omap3beagle_lcd",
+- .id = -1,
+-};
+-
+-static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
+- .ctrl_name = "internal",
+-};
+-
+ static struct regulator_consumer_supply beagle_vmmc1_supply = {
+ .supply = "vmmc",
+ };
+@@ -316,6 +294,7 @@ static struct regulator_init_data beagle_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
++ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+@@ -340,11 +319,18 @@ static struct regulator_init_data beagle_vpll2 = {
+ .consumer_supplies = &beagle_vdds_dsi_supply,
+ };
+
++static struct twl4030_usb_data beagle_usb_data = {
++ .usb_mode = T2_USB_MODE_ULPI,
++};
++
+ static struct twl4030_platform_data beagle_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
++ .usb = &beagle_usb_data,
++
++ /* platform_data for children goes here */
+ .gpio = &beagle_gpio_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/dss2/0146-DSS2-change-include-asm-.-to-linux-.-in-oma.patch b/recipes/linux/linux-omap-pm/dss2/0146-DSS2-change-include-asm-.-to-linux-.-in-oma.patch
new file mode 100644
index 0000000000..7867385443
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/dss2/0146-DSS2-change-include-asm-.-to-linux-.-in-oma.patch
@@ -0,0 +1,29 @@
+From 7ae220f46384b34e72b8c3b0c2075a674a3f74fe Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+Date: Fri, 3 Jul 2009 08:53:11 +0300
+Subject: [PATCH 146/146] DSS2: change include <asm/...> to <linux/...> in omapfb.h
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+---
+ include/linux/omapfb.h | 5 ++---
+ 1 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
+index 67dc375..0290584 100644
+--- a/include/linux/omapfb.h
++++ b/include/linux/omapfb.h
+@@ -25,9 +25,8 @@
+ #define __OMAPFB_H
+
+ #include <linux/fb.h>
+-
+-#include <asm/ioctl.h>
+-#include <asm/types.h>
++#include <linux/ioctl.h>
++#include <linux/types.h>
+
+ /* IOCTL commands. */
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-omap-pm/fix-mtd.diff b/recipes/linux/linux-omap-pm/fix-mtd.diff
new file mode 100644
index 0000000000..76fe001fcd
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/fix-mtd.diff
@@ -0,0 +1,51 @@
+From patchwork Sat Jun 27 05:37:06 2009
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [MTD,NAND] : fix omap2.c compile failure and warning
+Date: Fri, 26 Jun 2009 19:37:06 -0000
+From: Singh, Vimal <vimalsingh@ti.com>
+X-Patchwork-Id: 29225
+
+> The 'status' you return in the case that you _have_ gone through the
+> loop is still wrong though, isn't it?
+Yes, I have corrected that in below patch. Its my bad, I did not fix it
+previously.
+
+Signed-off-by: Vimal Singh <vimalsingh at ti.com>
+Signed-off-by: Ming Lei <tom.leiming at gmail.com>
+
+---
+
+
+diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
+index 0cd76f8..3b6e6ad 100644
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -11,6 +11,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/sched.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/partitions.h>
+@@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+ unsigned long timeo = jiffies;
+- int status, state = this->state;
++ int status = NAND_STATUS_FAIL, state = this->state;
+
+ if (state == FL_ERASING)
+ timeo += (HZ * 400) / 1000;
+@@ -558,6 +560,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip
+ status = __raw_readb(this->IO_ADDR_R);
+- if (!(status & 0x40))
++ if (status & NAND_STATUS_READY)
+ break;
++ cond_resched();
+ }
+ return status;
+ }
diff --git a/recipes/linux/linux-omap-pm/fix-musb-oops.diff b/recipes/linux/linux-omap-pm/fix-musb-oops.diff
new file mode 100644
index 0000000000..788e7be5a8
--- /dev/null
+++ b/recipes/linux/linux-omap-pm/fix-musb-oops.diff
@@ -0,0 +1,60 @@
+From patchwork Mon Jun 29 09:06:48 2009
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2] usb: musb: Warn and check for OTG transceiver misconfiguration
+Date: Mon, 29 Jun 2009 09:06:48 -0000
+From: Roger Quadros <ext-roger.quadros@nokia.com>
+X-Patchwork-Id: 32914
+
+Warn if OTG is selected in Kconfig but not initialized by platform code.
+Add checks to prevent NULL pointer exception in case the
+OTG transceiver has not been initialized. i.e. musb->xceiv == NULL
+
+Signed-off-by: Roger Quadros <ext-roger.quadros@nokia.com>
+Tested-by: Paul Walmsley <paul@pwsan.com>
+
+---
+drivers/usb/musb/musb_core.c | 7 ++++++-
+ drivers/usb/musb/omap2430.c | 3 ++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 554a414..d0cfc22 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1861,7 +1861,8 @@ static void musb_free(struct musb *musb)
+ }
+
+ #ifdef CONFIG_USB_MUSB_OTG
+- put_device(musb->xceiv->dev);
++ if (musb->xceiv)
++ put_device(musb->xceiv->dev);
+ #endif
+
+ #ifdef CONFIG_USB_MUSB_HDRC_HCD
+@@ -1958,6 +1959,10 @@ bad_config:
+ musb->isr = generic_interrupt;
+ status = musb_platform_init(musb);
+
++#ifdef CONFIG_USB_MUSB_OTG
++ if (!musb->xceiv)
++ WARN(1, "MUSB: OTG transceiver not set up correctly\n");
++#endif
+ if (status < 0)
+ goto fail;
+ if (!musb->isr) {
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 3487520..8987d60 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -271,7 +271,8 @@ int musb_platform_suspend(struct musb *musb)
+ l |= ENABLEWAKEUP; /* enable wakeup */
+ omap_writel(l, OTG_SYSCONFIG);
+
+- otg_set_suspend(musb->xceiv, 1);
++ if (musb->xceiv)
++ otg_set_suspend(musb->xceiv, 1);
+
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 0);
diff --git a/recipes/linux/linux-omap-pm_2.6.29.bb b/recipes/linux/linux-omap-pm_2.6.29.bb
new file mode 100644
index 0000000000..b635f2154f
--- /dev/null
+++ b/recipes/linux/linux-omap-pm_2.6.29.bb
@@ -0,0 +1,210 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omap3-touchbook"
+
+SRCREV = "e63cf0710a4fb639d91d3e8b05aa485fbfa381b3"
+
+PV = "2.6.29"
+MACHINE_KERNEL_PR_append = "-pm2+gitr${SRCREV}"
+
+SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git;protocol=git;branch=pm-2.6.29 \
+ file://defconfig"
+
+SRC_URI_append = " \
+ file://no-empty-flash-warnings.patch;patch=1 \
+ file://no-cortex-deadlock.patch;patch=1 \
+ file://read_die_ids.patch;patch=1 \
+ file://fix-install.patch;patch=1 \
+ file://0124-leds-gpio-broken-with-current-git.patch;patch=1 \
+ file://ehci.patch;patch=1 \
+ file://dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch;patch=1 \
+ file://dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch;patch=1 \
+ file://dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch;patch=1 \
+ file://dss2/0004-DSS2-OMAP-framebuffer-driver.patch;patch=1 \
+ file://dss2/0005-DSS2-Add-panel-drivers.patch;patch=1 \
+ file://dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch;patch=1 \
+ file://dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch;patch=1 \
+ file://dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch;patch=1 \
+ file://dss2/0009-DSS2-Add-acx565akm-panel.patch;patch=1 \
+ file://dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch;patch=1 \
+ file://dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch;patch=1 \
+ file://dss2/0012-DSS2-Fix-DMA-rotation.patch;patch=1 \
+ file://dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch;patch=1 \
+ file://dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch;patch=1 \
+ file://dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch;patch=1 \
+ file://dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch;patch=1 \
+ file://dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch;patch=1 \
+ file://dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch;patch=1 \
+ file://dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch;patch=1 \
+ file://dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch;patch=1 \
+ file://dss2/0021-DSS2-Add-venc-register-dump.patch;patch=1 \
+ file://dss2/0022-DSS2-FB-remove-unused-var-warning.patch;patch=1 \
+ file://dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch;patch=1 \
+ file://dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch;patch=1 \
+ file://dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch;patch=1 \
+ file://dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch;patch=1 \
+ file://dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch;patch=1 \
+ file://dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch;patch=1 \
+ file://dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch;patch=1 \
+ file://dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch;patch=1 \
+ file://dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch;patch=1 \
+ file://dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch;patch=1 \
+ file://dss2/0033-DSS2-Prefer-3-tap-filter.patch;patch=1 \
+ file://dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch;patch=1 \
+ file://dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch;patch=1 \
+ file://dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch;patch=1 \
+ file://dss2/0037-DSS2-Added-support-for-querying-color-keying.patch;patch=1 \
+ file://dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch;patch=1 \
+ file://dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch;patch=1 \
+ file://dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch;patch=1 \
+ file://dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch;patch=1 \
+ file://dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch;patch=1 \
+ file://dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch;patch=1 \
+ file://dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch;patch=1 \
+ file://dss2/0045-DSS2-Fixed-line-endings-from-to.patch;patch=1 \
+ file://dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch;patch=1 \
+ file://dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch;patch=1 \
+ file://dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch;patch=1 \
+ file://dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch;patch=1 \
+ file://dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch;patch=1 \
+ file://dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch;patch=1 \
+ file://dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch;patch=1 \
+ file://dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch;patch=1 \
+ file://dss2/0054-DSS2-DSI-more-error-handling.patch;patch=1 \
+ file://dss2/0055-DSS2-Added-global-alpha-support.patch;patch=1 \
+ file://dss2/0056-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch;patch=1 \
+ file://dss2/0057-DSS2-Documentation-update-for-new-sysfs-entries-in.patch;patch=1 \
+ file://dss2/0058-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch;patch=1 \
+ file://dss2/0059-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch;patch=1 \
+ file://dss2/0060-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch;patch=1 \
+ file://dss2/0061-DSS2-VRFB-save-restore-context.patch;patch=1 \
+ file://dss2/0062-DSS2-VRAM-Fix-indentation.patch;patch=1 \
+ file://dss2/0063-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch;patch=1 \
+ file://dss2/0064-VRFB-fix-debug-messages.patch;patch=1 \
+ file://dss2/0065-VRFB-add-suspend-resume-functionality.patch;patch=1 \
+ file://dss2/0066-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch;patch=1 \
+ file://dss2/0067-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch;patch=1 \
+ file://dss2/0068-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch;patch=1 \
+ file://dss2/0069-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch;patch=1 \
+ file://dss2/0070-DSS2-fix-irq1.diff;patch=1 \
+ file://dss2/0071-DSS2-fix-irq2.diff;patch=1 \
+ file://dss2/merge-fixups.diff;patch=1 \
+ file://overo-cpufreq.diff;patch=1 \
+ file://register-all-OPPs.diff;patch=1 \
+ file://isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch;patch=1 \
+ file://isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch;patch=1 \
+ file://isp/v4l/0003-V4L-Int-if-Dummy-slave.patch;patch=1 \
+ file://isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch;patch=1 \
+ file://isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch;patch=1 \
+ file://isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch;patch=1 \
+ file://isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch;patch=1 \
+ file://isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch;patch=1 \
+ file://isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch;patch=1 \
+ file://isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch;patch=1 \
+ file://isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch;patch=1 \
+ file://isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch;patch=1 \
+ file://isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch;patch=1 \
+ file://isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch;patch=1 \
+ file://isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch;patch=1 \
+ file://isp/omap3camera/0003-omap3isp-Add-userspace-header.patch;patch=1 \
+ file://isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch;patch=1 \
+ file://isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch;patch=1 \
+ file://isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch;patch=1 \
+ file://isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch;patch=1 \
+ file://isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch;patch=1 \
+ file://isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch;patch=1 \
+ file://isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch;patch=1 \
+ file://isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch;patch=1 \
+ file://isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch;patch=1 \
+ file://modedb-hd720.patch;patch=1 \
+ file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://vfp/02-vfp-ptrace.patch;patch=1 \
+ file://vfp/03-vfp-corruption.patch;patch=1 \
+ file://vfp/04-vfp-threads.patch;patch=1 \
+ file://vfp/05-vfp-signal-handlers.patch;patch=1 \
+ file://arch-has-holes.diff;patch=1 \
+ file://musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch;patch=1 \
+ file://musb/0002-USB-composite-avoid-inconsistent-lock-state.patch;patch=1 \
+ file://musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch;patch=1 \
+ file://musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch;patch=1 \
+ file://musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch;patch=1 \
+ file://musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch;patch=1 \
+ file://musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch;patch=1 \
+ file://musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch;patch=1 \
+ file://musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch;patch=1 \
+ file://musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch;patch=1 \
+ file://musb/0011-musb-fix-isochronous-TXDMA-take-2.patch;patch=1 \
+ file://musb/0012-musb-fix-possible-panic-while-resuming.patch;patch=1 \
+ file://musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch;patch=1 \
+ file://musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch;patch=1 \
+ file://musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch;patch=1 \
+ file://musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch;patch=1 \
+ file://musb/0017-musb_host-refactor-URB-giveback.patch;patch=1 \
+ file://musb/0018-musb-split-out-CPPI-interrupt-handler.patch;patch=1 \
+ file://musb/0019-musb_host-simplify-check-for-active-URB.patch;patch=1 \
+ file://musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch;patch=1 \
+ file://musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch;patch=1 \
+ file://musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch;patch=1 \
+ file://musb/0023-musb-add-high-bandwidth-ISO-support.patch;patch=1 \
+ file://musb/0024-USB-otg-adding-nop-usb-transceiver.patch;patch=1 \
+ file://musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch;patch=1 \
+ file://musb/0026-musb-proper-hookup-to-transceiver-drivers.patch;patch=1 \
+ file://musb/0027-musb-otg-timer-cleanup.patch;patch=1 \
+ file://musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch;patch=1 \
+ file://musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch;patch=1 \
+ file://cache/l1cache-shift.patch;patch=1 \
+ file://cache/copy-page-tweak.patch;patch=1 \
+"
+
+
+SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
+ file://tincantools-puppy.diff;patch=1 \
+ file://tincantools-zippy.diff;patch=1 \
+"
+
+SRC_URI_append_omap3-touchbook = " \
+ file://beagle-asoc.patch;patch=1 \
+ file://accelerometer-mma7455l.patch;patch=1 \
+ file://accelerometer-touchscreen-mux-spi.patch;patch=1 \
+ file://touchscreen-ads7846-export-settings.patch;patch=1 \
+ file://touchscreen-ads7846-rotation-support.patch;patch=1 \
+ file://dspbridge.patch;patch=1 \
+ file://battery2-bq27200-no-error-message.patch;patch=1 \
+ file://sound-headphone-detection.patch;patch=1 \
+ file://dss2-fix-XY-coordinates-when-rotating.patch;patch=1 \
+ file://screen-backlight.patch;patch=1 \
+ file://battery1-tps65950-charging-management-1.patch;patch=1 \
+ file://dss2-fix-scaling-when-rotating.patch;patch=1 \
+ file://dss2-export-status.patch;patch=1 \
+ file://usb-otg-pc-connection.patch;patch=1 \
+ file://battery1-tps65950-charging-management-2.patch;patch=1 \
+ file://memory-move-malloc-end.patch;patch=1 \
+ file://aufs-1.patch;patch=1 \
+ file://aufs-2.patch;patch=1 \
+ file://aufs-3.patch;patch=1 \
+ file://aufs-squashfs-mount-to-avoid-initramfs.patch;patch=1 \
+ file://screen-backlight-accessible-by-user.patch;patch=1 \
+ file://dss2-blank-rotate-accessible-by-user.patch;patch=1 \
+ file://boot-no-power-message.patch;patch=1 \
+ file://usb-lower-current-consumption-upon-insertion.patch;patch=1 \
+ file://battery2-bq27200-gpio-charged.patch;patch=1 \
+ file://board-omap3beagle.c \
+"
+
+do_configure_prepend_omap3-touchbook() {
+ cp ${WORKDIR}/board-omap3beagle.c ${S}/arch/arm/mach-omap2
+}
+
+SRC_URI_append_omap3evm = " \
+ file://evm-mcspi-ts.diff;patch=1 \
+"
+
+S = "${WORKDIR}/git"
+
+
+module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
+
+
diff --git a/recipes/linux/linux-omap-pm_git.bb b/recipes/linux/linux-omap-pm_git.bb
index 11bfa4b087..574e0a3ca6 100644
--- a/recipes/linux/linux-omap-pm_git.bb
+++ b/recipes/linux/linux-omap-pm_git.bb
@@ -3,13 +3,15 @@ require linux.inc
DESCRIPTION = "Linux kernel for OMAP processors"
KERNEL_IMAGETYPE = "uImage"
-COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo"
+COMPATIBLE_MACHINE = "beagleboard"
DEFAULT_PREFERENCE = "-1"
-SRCREV = "9d76f46e79302058464b569dbad9af8c594dbe53"
+SRCREV = "7c5cb7862d32cb344be7831d466535d5255e35ac"
-PV = "2.6.29-pm0+gitr${SRCREV}"
+PV = "2.6.30+2.6.31rc1-pm1+gitr${SRCREV}"
+
+FILESPATHPKG_prepend = "linux-omap-pm-2.6.31:"
SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git;protocol=git;branch=pm \
file://defconfig"
@@ -19,68 +21,159 @@ SRC_URI_append = " \
file://no-cortex-deadlock.patch;patch=1 \
file://read_die_ids.patch;patch=1 \
file://fix-install.patch;patch=1 \
- file://0124-leds-gpio-broken-with-current-git.patch;patch=1 \
+ file://fix-musb-oops.diff;patch=1 \
+ file://fix-mtd.diff;patch=1 \
file://ehci.patch;patch=1 \
- file://dss2/0001-Revert-gro-Fix-legacy-path-napi_complete-crash.patch;patch=1 \
- file://dss2/0002-OMAPFB-move-omapfb.h-to-include-linux.patch;patch=1 \
- file://dss2/0003-DSS2-OMAP2-3-Display-Subsystem-driver.patch;patch=1 \
- file://dss2/0004-DSS2-OMAP-framebuffer-driver.patch;patch=1 \
- file://dss2/0005-DSS2-Add-panel-drivers.patch;patch=1 \
- file://dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch;patch=1 \
- file://dss2/0007-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch;patch=1 \
- file://dss2/0008-DSS2-Add-function-to-display-object-to-get-the-back.patch;patch=1 \
- file://dss2/0009-DSS2-Add-acx565akm-panel.patch;patch=1 \
- file://dss2/0010-DSS2-Small-VRFB-context-allocation-bug-fixed.patch;patch=1 \
- file://dss2/0011-DSS2-Allocated-memory-for-Color-Look-up-table.patch;patch=1 \
- file://dss2/0012-DSS2-Fix-DMA-rotation.patch;patch=1 \
- file://dss2/0013-DSS2-Verify-that-overlay-paddr-0.patch;patch=1 \
- file://dss2/0014-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch;patch=1 \
- file://dss2/0015-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch;patch=1 \
- file://dss2/0016-DSS2-DSI-improve-packet-len-calculation.patch;patch=1 \
- file://dss2/0017-DSS2-Disable-video-planes-on-sync-lost-error.patch;patch=1 \
- file://dss2/0018-DSS2-check-for-ovl-paddr-only-when-enabling.patch;patch=1 \
- file://dss2/0019-DSS2-Check-fclk-limits-when-configuring-video-plane.patch;patch=1 \
- file://dss2/0020-DSS2-Check-scaling-limits-against-proper-values.patch;patch=1 \
- file://dss2/0021-DSS2-Add-venc-register-dump.patch;patch=1 \
- file://dss2/0022-DSS2-FB-remove-unused-var-warning.patch;patch=1 \
- file://dss2/0023-DSS2-pass-the-default-FB-color-format-through-board.patch;patch=1 \
- file://dss2/0024-DSS2-Beagle-Use-gpio_set_value.patch;patch=1 \
- file://dss2/0025-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch;patch=1 \
- file://dss2/0026-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch;patch=1 \
- file://dss2/0027-DSS2-VRFB-rotation-and-mirroring-implemented.patch;patch=1 \
- file://dss2/0028-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch;patch=1 \
- file://dss2/0029-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch;patch=1 \
- file://dss2/0030-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch;patch=1 \
- file://dss2/0031-DSS2-do-bootmem-reserve-for-exclusive-access.patch;patch=1 \
- file://dss2/0032-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch;patch=1 \
- file://dss2/0033-DSS2-Prefer-3-tap-filter.patch;patch=1 \
- file://dss2/0034-DSS2-VRAM-improve-omap_vram_add_region.patch;patch=1 \
- file://dss2/0035-DSS2-Added-the-function-pointer-for-getting-default.patch;patch=1 \
- file://dss2/0036-DSS2-Added-support-for-setting-and-querying-alpha-b.patch;patch=1 \
- file://dss2/0037-DSS2-Added-support-for-querying-color-keying.patch;patch=1 \
- file://dss2/0038-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch;patch=1 \
- file://dss2/0039-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch;patch=1 \
- file://dss2/0040-DSS2-Provided-proper-exclusion-for-destination-colo.patch;patch=1 \
- file://dss2/0041-DSS2-Disable-vertical-offset-with-fieldmode.patch;patch=1 \
- file://dss2/0042-DSS2-Don-t-enable-fieldmode-automatically.patch;patch=1 \
- file://dss2/0043-DSS2-Swap-field-0-and-field-1-registers.patch;patch=1 \
- file://dss2/0044-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch;patch=1 \
- file://dss2/0045-DSS2-Fixed-line-endings-from-to.patch;patch=1 \
- file://dss2/0046-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch;patch=1 \
- file://dss2/0047-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch;patch=1 \
- file://dss2/0048-OMAP2-3-DMA-implement-trans-copy-and-const-fill.patch;patch=1 \
- file://dss2/0049-DSS2-VRAM-clear-allocated-area-with-DMA.patch;patch=1 \
- file://dss2/0050-DSS2-OMAPFB-remove-fb-clearing-code.patch;patch=1 \
- file://dss2/0051-DSS2-VRAM-use-debugfs-not-procfs.patch;patch=1 \
- file://dss2/0052-DSS2-VRAM-fix-section-mismatch-warning.patch;patch=1 \
- file://dss2/0053-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch;patch=1 \
- file://dss2/merge-fixups.diff;patch=1 \
- file://overo-cpufreq.diff;patch=1 \
- file://register-all-OPPs.diff;patch=1 \
+ file://dss2/0001-OMAPFB-move-omapfb.h-to-include-linux.patch;patch=1 \
+ file://dss2/0002-DSS2-OMAP2-3-Display-Subsystem-driver.patch;patch=1 \
+ file://dss2/0003-DSS2-OMAP-framebuffer-driver.patch;patch=1 \
+ file://dss2/0004-DSS2-Add-panel-drivers.patch;patch=1 \
+ file://dss2/0005-DSS2-HACK-Add-DSS2-support-for-N800.patch;patch=1 \
+ file://dss2/0006-DSS2-Add-DSS2-support-for-SDP-Beagle-Overo-EVM.patch;patch=1 \
+ file://dss2/0007-DSS2-Add-function-to-display-object-to-get-the-back.patch;patch=1 \
+ file://dss2/0008-DSS2-Add-acx565akm-panel.patch;patch=1 \
+ file://dss2/0009-DSS2-Small-VRFB-context-allocation-bug-fixed.patch;patch=1 \
+ file://dss2/0010-DSS2-Allocated-memory-for-Color-Look-up-table.patch;patch=1 \
+ file://dss2/0011-DSS2-Fix-DMA-rotation.patch;patch=1 \
+ file://dss2/0012-DSS2-Verify-that-overlay-paddr-0.patch;patch=1 \
+ file://dss2/0013-DSS2-Add-function-to-get-DSS-logic-clock-rate.patch;patch=1 \
+ file://dss2/0014-DSS2-DSI-calculate-VP_CLK_RATIO-properly.patch;patch=1 \
+ file://dss2/0015-DSS2-DSI-improve-packet-len-calculation.patch;patch=1 \
+ file://dss2/0016-DSS2-Disable-video-planes-on-sync-lost-error.patch;patch=1 \
+ file://dss2/0017-DSS2-check-for-ovl-paddr-only-when-enabling.patch;patch=1 \
+ file://dss2/0018-DSS2-Check-fclk-limits-when-configuring-video-plane.patch;patch=1 \
+ file://dss2/0019-DSS2-Check-scaling-limits-against-proper-values.patch;patch=1 \
+ file://dss2/0020-DSS2-Add-venc-register-dump.patch;patch=1 \
+ file://dss2/0021-DSS2-FB-remove-unused-var-warning.patch;patch=1 \
+ file://dss2/0022-DSS2-pass-the-default-FB-color-format-through-board.patch;patch=1 \
+ file://dss2/0023-DSS2-Beagle-Use-gpio_set_value.patch;patch=1 \
+ file://dss2/0024-DSS2-VRFB-Macro-for-calculating-base-address-of-th.patch;patch=1 \
+ file://dss2/0025-DSS2-DSI-sidlemode-to-noidle-while-sending-frame.patch;patch=1 \
+ file://dss2/0026-DSS2-VRFB-rotation-and-mirroring-implemented.patch;patch=1 \
+ file://dss2/0027-DSS2-OMAPFB-Added-support-for-the-YUV-VRFB-rotatio.patch;patch=1 \
+ file://dss2/0028-DSS2-OMAPFB-Set-line_length-correctly-for-YUV-with.patch;patch=1 \
+ file://dss2/0029-DSS2-dispc_get_trans_key-was-returning-wrong-key-ty.patch;patch=1 \
+ file://dss2/0030-DSS2-do-bootmem-reserve-for-exclusive-access.patch;patch=1 \
+ file://dss2/0031-DSS2-Fix-DISPC_VID_FIR-value-for-omap34xx.patch;patch=1 \
+ file://dss2/0032-DSS2-Prefer-3-tap-filter.patch;patch=1 \
+ file://dss2/0033-DSS2-VRAM-improve-omap_vram_add_region.patch;patch=1 \
+ file://dss2/0034-DSS2-Added-the-function-pointer-for-getting-default.patch;patch=1 \
+ file://dss2/0035-DSS2-Added-support-for-setting-and-querying-alpha-b.patch;patch=1 \
+ file://dss2/0036-DSS2-Added-support-for-querying-color-keying.patch;patch=1 \
+ file://dss2/0037-DSS2-OMAPFB-Some-color-keying-pointerd-renamed-in-D.patch;patch=1 \
+ file://dss2/0038-DSS2-Add-sysfs-entry-to-for-the-alpha-blending-supp.patch;patch=1 \
+ file://dss2/0039-DSS2-Provided-proper-exclusion-for-destination-colo.patch;patch=1 \
+ file://dss2/0040-DSS2-Disable-vertical-offset-with-fieldmode.patch;patch=1 \
+ file://dss2/0041-DSS2-Don-t-enable-fieldmode-automatically.patch;patch=1 \
+ file://dss2/0042-DSS2-Swap-field-0-and-field-1-registers.patch;patch=1 \
+ file://dss2/0043-DSS2-add-sysfs-entry-for-seting-the-rotate-type.patch;patch=1 \
+ file://dss2/0044-DSS2-Fixed-line-endings-from-to.patch;patch=1 \
+ file://dss2/0045-DSS2-DSI-decrease-sync-timeout-from-60s-to-2s.patch;patch=1 \
+ file://dss2/0046-DSS2-fix-return-value-for-rotate_type-sysfs-functio.patch;patch=1 \
+ file://dss2/0047-DSS2-VRAM-clear-allocated-area-with-DMA.patch;patch=1 \
+ file://dss2/0048-DSS2-OMAPFB-remove-fb-clearing-code.patch;patch=1 \
+ file://dss2/0049-DSS2-VRAM-use-debugfs-not-procfs.patch;patch=1 \
+ file://dss2/0050-DSS2-VRAM-fix-section-mismatch-warning.patch;patch=1 \
+ file://dss2/0051-DSS2-disable-LCD-DIGIT-before-resetting-DSS.patch;patch=1 \
+ file://dss2/0052-DSS2-DSI-more-error-handling.patch;patch=1 \
+ file://dss2/0053-DSS2-Added-global-alpha-support.patch;patch=1 \
+ file://dss2/0054-DSS2-Rotation-attrs-for-YUV-need-not-to-be-reversed.patch;patch=1 \
+ file://dss2/0055-DSS2-Documentation-update-for-new-sysfs-entries-in.patch;patch=1 \
+ file://dss2/0056-DSS2-Don-t-touch-plane-coordinates-when-changing-fb.patch;patch=1 \
+ file://dss2/0057-DSS2-DSI-configure-ENTER-EXIT_HS_MODE_LATENCY.patch;patch=1 \
+ file://dss2/0058-DSS2-Avoid-div-by-zero-when-calculating-required-fc.patch;patch=1 \
+ file://dss2/0059-DSS2-VRFB-save-restore-context.patch;patch=1 \
+ file://dss2/0060-DSS2-VRAM-Fix-indentation.patch;patch=1 \
+ file://dss2/0061-DSS2-fix-the-usage-of-get_last_off_on_transaction_i.patch;patch=1 \
+ file://dss2/0062-VRFB-fix-debug-messages.patch;patch=1 \
+ file://dss2/0063-VRFB-add-suspend-resume-functionality.patch;patch=1 \
+ file://dss2/0064-DSS2-DSI-tune-the-timings-to-be-more-relaxed.patch;patch=1 \
+ file://dss2/0065-DSS2-VRFB-don-t-WARN-when-releasing-inactive-ctx.patch;patch=1 \
+ file://dss2/0066-DSS2-Swap-field-offset-values-w-VRFB-rotation.patch;patch=1 \
+ file://dss2/0067-DSS2-OMAP3EVM-Added-DSI-powerup-and-powerdown-func.patch;patch=1 \
+ file://dss2/0068-DSS2-DSI-Improve-perf-measurement-output.patch;patch=1 \
+ file://dss2/0069-DSS2-DSI-Add-support-for-external-TE-signal.patch;patch=1 \
+ file://dss2/0070-DSS2-DSI-Fix-LP-clock.patch;patch=1 \
+ file://dss2/0071-DSS2-Do-not-swap-xres-yres-or-change-rotation-in-ch.patch;patch=1 \
+ file://dss2/0072-DSS2-Allow-independent-rotation-for-each-plane.patch;patch=1 \
+ file://dss2/0073-DSS2-DISPC-fix-irq-handling-locking.patch;patch=1 \
+ file://dss2/0074-DSS2-DISPC-clear-irqstatus-for-newly-enabled-irqs.patch;patch=1 \
+ file://dss2/0075-DSS2-Add-WSS-support.patch;patch=1 \
+ file://dss2/0076-DSS2-Fix-PAL-NTSC-timings.patch;patch=1 \
+ file://dss2/0077-DSS2-Add-venc-debugfs-file.patch;patch=1 \
+ file://dss2/0078-DSS2-Enable-replication-logic-feature.patch;patch=1 \
+ file://dss2/0079-DSS2-support-for-querying-the-supported-overlay-col.patch;patch=1 \
+ file://dss2/0080-DSS2-fix-uninitialized-var-in-OMAPFB_GET_CAPS-IOCTL.patch;patch=1 \
+ file://dss2/0081-DSS2-Reset-WSS-data-only-when-changing-TV-standard.patch;patch=1 \
+ file://dss2/0082-DSS2-DSI-implement-timeout-for-DSI-transfer.patch;patch=1 \
+ file://dss2/0083-DSS2-DSI-reset-perf-frame-counter-when-starting-au.patch;patch=1 \
+ file://dss2/0084-DSS2-DSI-Implement-DSI-bus-lock.patch;patch=1 \
+ file://dss2/0085-DSS2-OMAPFB-omapfb_get_ovl_colormode-to-static.patch;patch=1 \
+ file://dss2/0086-DSS2-VRFB-make-vrfb_hw_context-static.patch;patch=1 \
+ file://dss2/0087-DSS2-new-device-driver-model.patch;patch=1 \
+ file://dss2/0088-DSS2-Board-file-changes-for-new-device-model.patch;patch=1 \
+ file://dss2/0089-DSS2-Panel-driver-changes-for-new-device-model.patch;patch=1 \
+ file://dss2/0090-DSS2-VENC-venc-uses-regulator-framework.patch;patch=1 \
+ file://dss2/0091-DSS2-DSI-Use-regulator-framework.patch;patch=1 \
+ file://dss2/0092-DSS2-SDP-regulators-for-VDAC-DSI.patch;patch=1 \
+ file://dss2/0093-DSS2-Sharp-panel-use-regulator-fw.patch;patch=1 \
+ file://dss2/0094-DSS2-Beagle-regulators-for-VDAC-DSI.patch;patch=1 \
+ file://dss2/0095-DSS2-Fix-checkpatch-complaints.patch;patch=1 \
+ file://dss2/0096-DSS2-Overo-add-vdac-dsi-regulators-fix-panel-name.patch;patch=1 \
+ file://dss2/0097-DSS2-implement-overlay_manager_info.patch;patch=1 \
+ file://dss2/0098-DSS2-use-sysfs_streq-to-compare-display-names.patch;patch=1 \
+ file://dss2/0099-DSS2-Implement-function-to-verify-lcd-timings.patch;patch=1 \
+ file://dss2/0100-DSS2-Remove-non-existing-dsi-power-funcs-from-dss.h.patch;patch=1 \
+ file://dss2/0101-DSS2-move-to_dss_driver-and-to_dss_device-to-pu.patch;patch=1 \
+ file://dss2/0102-DSS2-CLK-change-omapfb-omapdss-in-clock-framewo.patch;patch=1 \
+ file://dss2/0103-DSS2-Use-clkdev.patch;patch=1 \
+ file://dss2/0104-DSS2-Fix-documentation.patch;patch=1 \
+ file://dss2/0105-DSS2-OMAPFB-first-set-TE-then-update-mode.patch;patch=1 \
+ file://dss2/0106-DSS2-OMAPFB-Disable-forced-display-update-on-fb-cl.patch;patch=1 \
+ file://dss2/0107-DSS2-DSI-use-INIT_COMPLETION-not-init_completion.patch;patch=1 \
+ file://dss2/0108-DSS2-DSI-Rewrite-of-the-DSI-update-and-cmd-queue.patch;patch=1 \
+ file://dss2/0109-DSS2-let-init_display-return-an-error-code.patch;patch=1 \
+ file://dss2/0110-DSS2-isolate-the-SDI-pads-when-SDI-is-disabled.patch;patch=1 \
+ file://dss2/0111-DSS2-Fix-bottom-field-initial-starting-line.patch;patch=1 \
+ file://dss2/0112-DSS2-Correctly-determine-if-an-interlaced-display-i.patch;patch=1 \
+ file://dss2/0113-DSS2-Fix-omapfb-framebuffer-name.patch;patch=1 \
+ file://dss2/0114-DSS2-Overo-update-defconfig-to-lighter-one.patch;patch=1 \
+ file://dss2/0115-DSS2-SDI-make-sdi_pads-static.patch;patch=1 \
+ file://dss2/0116-DSS2-Fix-default_color-sysfs-output.patch;patch=1 \
+ file://dss2/0117-DSS2-Locking-for-VRFB.patch;patch=1 \
+ file://dss2/0118-DSS2-DISPC-fix-locking-issue-with-irq-handling.patch;patch=1 \
+ file://dss2/0119-DSS2-OMAPFB-remove-unneeded-locks.patch;patch=1 \
+ file://dss2/0120-DSS2-DISPC-configuration-management.patch;patch=1 \
+ file://dss2/0121-DSS2-VRFB-clean-up-BUG-calls.patch;patch=1 \
+ file://dss2/0122-DSS2-OMAPFB-don-t-fail-even-if-default-display-doe.patch;patch=1 \
+ file://dss2/0123-DSS2-DSI-Fix-external-TE-wait.patch;patch=1 \
+ file://dss2/0124-DSS2-DSI-Increase-framedone-timeout-to-1s.patch;patch=1 \
+ file://dss2/0125-DSS2-VRAM-Add-function-to-get-free-vram-info.patch;patch=1 \
+ file://dss2/0126-DSS2-OMAPFB-implement-OMAPFB_GET_VRAM_INFO-ioctl.patch;patch=1 \
+ file://dss2/0127-DSS2-DSI-increase-dsi-thread-priority.patch;patch=1 \
+ file://dss2/0128-DSS2-DSI-check-bus_lock-in-send_bta.patch;patch=1 \
+ file://dss2/0129-DSS2-DSI-export-dsi_vc_send_bta_sync.patch;patch=1 \
+ file://dss2/0130-DSS2-DSI-clear-BTA-irq-before-enabling-it.patch;patch=1 \
+ file://dss2/0131-DSS2-DSI-check-dsi_set_te-return-value.patch;patch=1 \
+ file://dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch;patch=1 \
+ file://dss2/0133-DSS2-VRAM-Remove-unused-defines.patch;patch=1 \
+ file://dss2/0134-DSS2-VENC-Add-invert_polarity-flag.patch;patch=1 \
+ file://dss2/0135-DSS2-VRAM-Add-defines-for-VRAM-types.patch;patch=1 \
+ file://dss2/0136-DSS2-VRAM-separate-VRAM-setup-from-the-old-fb-vram.patch;patch=1 \
+ file://dss2/0137-DSS2-VRFB-Update-license-information.patch;patch=1 \
+ file://dss2/0138-DSS2-VRAM-Update-license-information.patch;patch=1 \
+ file://dss2/0139-DSS2-VRFB-use-pr_-instead-of-printk.patch;patch=1 \
+ file://dss2/0140-DSS2-VRAM-Change-CONFIG_OMAP2_DSS_VRAM_SIZE-name.patch;patch=1 \
+ file://dss2/0141-DSS2-VRAM-add-CONFIG_OMAP2_VRAM-flag.patch;patch=1 \
+ file://dss2/0142-DSS2-VRFB-Add-CONFIG_OMAP2_VRFB-flag.patch;patch=1 \
+ file://dss2/0143-DSS2-VRFB-VRAM-fix-checkpatch-warnings.patch;patch=1 \
+ file://dss2/0144-DSS2-fixes-to-dss_omap_3430sdp_defconfig-to-make-it.patch;patch=1 \
+ file://dss2/0145-DSS2-BEAGLE-get-DSS2-working-again-on-beagle.patch;patch=1 \
+ file://dss2/0146-DSS2-change-include-asm-.-to-linux-.-in-oma.patch;patch=1 \
"
-
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
+ file://beagle-writable-uboot.diff;patch=1 \
"
SRC_URI_append_omap3evm = " \
@@ -92,4 +185,3 @@ S = "${WORKDIR}/git"
module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
-
diff --git a/recipes/linux/linux-omap-psp-2.6.29/fix-section-mismatch.diff b/recipes/linux/linux-omap-psp-2.6.29/fix-section-mismatch.diff
new file mode 100644
index 0000000000..c7a74b7f2e
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/fix-section-mismatch.diff
@@ -0,0 +1,11 @@
+--- /tmp/board-omap3evm.c 2009-07-23 15:25:30.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3evm.c 2009-07-23 15:28:47.000000000 +0200
+@@ -186,7 +186,7 @@
+ .irq_line = 1,
+ };
+
+-static struct twl4030_platform_data omap3evm_twldata = {
++static struct twl4030_platform_data __initdata omap3evm_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+
diff --git a/recipes/linux/linux-omap-psp-2.6.29/fix-twl-merge-damage.diff b/recipes/linux/linux-omap-psp-2.6.29/fix-twl-merge-damage.diff
new file mode 100644
index 0000000000..7ca627d67d
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/fix-twl-merge-damage.diff
@@ -0,0 +1,19 @@
+--- /tmp/twl4030-regulator.c 2009-07-23 14:27:33.000000000 +0200
++++ git/drivers/regulator/twl4030-regulator.c 2009-07-23 14:27:51.000000000 +0200
+@@ -107,16 +107,6 @@
+ return (state & P1_GRP) != 0;
+ }
+
+-static int twl4030reg_is_enabled(struct regulator_dev *rdev)
+-{
+- int state = twl4030reg_grp(rdev);
+-
+- if (state < 0)
+- return state;
+-
+- return (state & P1_GRP) != 0;
+-}
+-
+ static int twl4030reg_enable(struct regulator_dev *rdev)
+ {
+ struct twlreg_info *info = rdev_get_drvdata(rdev);
diff --git a/recipes/linux/linux-omap-psp-2.6.29/no-3517-hack.diff b/recipes/linux/linux-omap-psp-2.6.29/no-3517-hack.diff
new file mode 100644
index 0000000000..06b62e581a
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/no-3517-hack.diff
@@ -0,0 +1,16 @@
+--- /tmp/usb-musb.c 2009-07-23 21:42:51.000000000 +0200
++++ git/arch/arm/mach-omap2/usb-musb.c 2009-07-23 21:46:46.000000000 +0200
+@@ -152,12 +152,10 @@
+ if (cpu_is_omap243x()) {
+ musb_resources[0].start = OMAP243X_HS_BASE;
+ musb_plat.clock = "usbhs_ick";
+- } else if (1 /*TODO: cpu_is_omap3517()*/) {
+- musb_resources[0].start = OMAP3517_HSUSB_OTG_BASE;
++ } else if (0 /*TODO: cpu_is_omap3517()*/) {
+ musb_plat.clock = "usbotg_vbusp_ck";
+ musb_resources[1].start = INT_OMAP3517_HSUSB_OTG;
+ /* set mux config for DRVVBUS */
+- omap_cfg_reg(E25_3517_USB0_DRVVBUS);
+ /* OMAP3517 can provide max of 500mA */
+ musb_plat.power = 250;
+ } else {
diff --git a/recipes/linux/linux-omap-psp-2.6.29/omap3517-evm/defconfig b/recipes/linux/linux-omap-psp-2.6.29/omap3517-evm/defconfig
new file mode 100644
index 0000000000..4fa37bd8ef
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/omap3517-evm/defconfig
@@ -0,0 +1,1498 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Tue Sep 8 15:41:48 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=1
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+CONFIG_ARCH_OMAP35XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3517EVM=y
+
+#
+# OMAP3 EVM Power Modules
+#
+# CONFIG_OMAP3EVM_TWL4030 is not set
+# CONFIG_OMAP3EVM_TPS65023 is not set
+# CONFIG_OMAP3EVM_TPS65073 is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_TI_DAVINCI_EMAC=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP_VIDEOOUT=y
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+# CONFIG_USB_STV680 is not set
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+CONFIG_PANEL_SHARP_LQ043T1DG01=y
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_TI_CPPI41_DMA=y
+CONFIG_USB_MUSB_DEBUG=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-psp-2.6.29/omap3evm/defconfig b/recipes/linux/linux-omap-psp-2.6.29/omap3evm/defconfig
new file mode 100644
index 0000000000..4b8a52f43d
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/omap3evm/defconfig
@@ -0,0 +1,2297 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Thu Jul 23 15:15:16 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+CONFIG_OMAP_MBOX_FWK=m
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+CONFIG_ARCH_OMAP35XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_MACH_OMAP3517EVM=y
+
+#
+# OMAP3 EVM Power Modules
+#
+CONFIG_OMAP3EVM_TWL4030=y
+# CONFIG_OMAP3EVM_TPS65023 is not set
+# CONFIG_OMAP3EVM_TPS65073 is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTSDIO=y
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=m
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+CONFIG_REALTEK_PHY=y
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_FIXED_PHY=y
+CONFIG_MDIO_BITBANG=y
+# CONFIG_MDIO_GPIO is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_TI_DAVINCI_EMAC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_SMC911X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_TWL4030=y
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_VIDEO_OMAP3=y
+# CONFIG_VIDEO_OMAP_VIDEOOUT is not set
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+# CONFIG_DVB_TDA8261 is not set
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+# CONFIG_DVB_TUNER_CX24113 is not set
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_SI21XX is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+# CONFIG_DVB_LGDT3304 is not set
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DVB_LGS8GL5 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_LTV350QV=y
+CONFIG_LCD_ILI9320=y
+# CONFIG_LCD_TDO24M is not set
+CONFIG_LCD_VGG2432A4=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3517EVM=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TLV320AIC3X=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_OPTICON is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+# CONFIG_LEDS_OMAP is not set
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_BQ24022=y
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_UIO is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_USB_ATMEL is not set
+# CONFIG_AGNX is not set
+# CONFIG_OTUS is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_ANDROID_BINDER_IPC is not set
+# CONFIG_ANDROID_LOGGER is not set
+# CONFIG_ANDROID_RAM_CONSOLE is not set
+# CONFIG_ANDROID_TIMED_GPIO is not set
+# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+CONFIG_PREEMPT_TRACER=y
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-psp-2.6.29/shiva-bits.diff b/recipes/linux/linux-omap-psp-2.6.29/shiva-bits.diff
new file mode 100644
index 0000000000..45d817a146
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/shiva-bits.diff
@@ -0,0 +1,11 @@
+--- /tmp/board-omap3517evm.c 2009-09-07 17:34:48.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3517evm.c 2009-09-07 17:35:00.000000000 +0200
+@@ -297,7 +297,7 @@
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "dvi",
+ .panel_name = "panel-generic",
+- .u.dpi.data_lines = 24,
++ .u.dpi.data_lines = 16,
+ .panel_enable = omap3517_evm_panel_enable_dvi,
+ .panel_disable = omap3517_evm_panel_disable_dvi,
+ };
diff --git a/recipes/linux/linux-omap-psp-2.6.29/shiva-ehci.diff b/recipes/linux/linux-omap-psp-2.6.29/shiva-ehci.diff
new file mode 100755
index 0000000000..418dca86b5
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.29/shiva-ehci.diff
@@ -0,0 +1,60 @@
+commit b73387d2642df981a4cfacddaa36aab8b1ea604b
+Author: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Fri Jul 10 18:01:29 2009 +0530
+
+ ehci: adding support for EHCI
+
+ Port1 is used and EHCI port on OMAP3517. GPIO57 is
+ used to reset the EHCI phy.
+
+ - Added usb_ehci_init()
+ - Added port1 phy reset padconfig
+
+diff --git a/arch/arm/mach-omap2/board-omap3517evm.c b/arch/arm/mach-omap2/board-omap3517evm.c
+index cb5af8f..af2d3a9 100644
+--- a/arch/arm/mach-omap2/board-omap3517evm.c
++++ b/arch/arm/mach-omap2/board-omap3517evm.c
+@@ -399,6 +399,9 @@ static void __init omap3517_evm_init(void)
+
+ omap3517evm_flash_init();
+ usb_musb_init();
++ /* GPIO57 as port1 phy reset */
++ omap_cfg_reg(N5_3517_GPIO57_OUT);
++ usb_ehci_init();
+ /*
+ * MMC init function
+ */
+
+diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h
+index aa9d5a1..4e5a247 100644
+--- a/arch/arm/plat-omap/include/mach/mux.h
++++ b/arch/arm/plat-omap/include/mach/mux.h
+@@ -805,6 +805,7 @@ enum omap34xx_index {
+ J25_34XX_GPIO170,
+ #ifdef CONFIG_MACH_OMAP3517EVM
+ E25_3517_USB0_DRVVBUS,
++ N5_3517_GPIO57_OUT,
+ #endif
+ };
+
+--- /tmp/mux.c 2009-09-08 15:06:05.000000000 +0200
++++ git/arch/arm/mach-omap2/mux.c 2009-09-08 15:08:28.000000000 +0200
+@@ -486,16 +486,10 @@
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+ MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+-#ifdef CONFIG_MACH_OMAP3517EVM
+ MUX_CFG_34XX("E25_3517_USB0_DRVVBUS", 0x212,
+ OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLDOWN)
+-#if 0
+-MUX_CFG_34XX("F24_3517_USB0_DM", 0x212,
+- OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLDOWN)
+-MUX_CFG_34XX("F25_3517_USB0_DP", 0x212,
+- OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLDOWN)
+-#endif
+-#endif
++MUX_CFG_34XX("N5_3517_GPIO57_OUT", 0x0ba,
++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+ };
+
+ #define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins)
diff --git a/recipes/linux/linux-omap-psp/omap3517-evm/defconfig b/recipes/linux/linux-omap-psp/omap3517-evm/defconfig
new file mode 100644
index 0000000000..9b22a1787f
--- /dev/null
+++ b/recipes/linux/linux-omap-psp/omap3517-evm/defconfig
@@ -0,0 +1,1646 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc7-omap1
+# Fri Sep 25 16:21:15 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=m
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+# CONFIG_OMAP_PM_SRF is not set
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+CONFIG_ARCH_OMAP35XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3517EVM=y
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_TI_DAVINCI_EMAC=y
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=m
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3_VOUT is not set
+# CONFIG_NTSC_M is not set
+# CONFIG_PAL_BDGHI is not set
+CONFIG_VIDEO_OMAP3_CAM=m
+CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER=m
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m
+# CONFIG_VIDEO_VPFE_CAPTURE is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SN9C20X_EVDEV=y
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+# CONFIG_VIDEO_PVRUSB2 is not set
+CONFIG_VIDEO_HDPVR=m
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+# CONFIG_VIDEO_OVCAMCHIP is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=0
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+CONFIG_PANEL_SHARP_LQ043T1DG01=y
+# CONFIG_PANEL_TAAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_TI_CPPI41_DMA=y
+CONFIG_USB_MUSB_DEBUG=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_TPS65023=m
+CONFIG_REGULATOR_TPS65073=m
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-psp/omap3evm/defconfig b/recipes/linux/linux-omap-psp/omap3evm/defconfig
new file mode 100644
index 0000000000..bbff6f6bf5
--- /dev/null
+++ b/recipes/linux/linux-omap-psp/omap3evm/defconfig
@@ -0,0 +1,2202 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc7-omap1
+# Fri Sep 25 09:36:54 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+# CONFIG_OMAP_PM_SRF is not set
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+CONFIG_ARCH_OMAP35XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP_LDP is not set
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_PMIC_TWL4030=y
+# CONFIG_PMIC_TPS65023 is not set
+# CONFIG_PMIC_TPS65073 is not set
+# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEBUGFS=y
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+CONFIG_CDROM_PKTCDVD_WCACHE=y
+CONFIG_ATA_OVER_ETH=m
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID6_PQ=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_TI_DAVINCI_EMAC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_INT51X1=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+# CONFIG_TWL4030_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+CONFIG_VIDEO_MSP3400=m
+# CONFIG_VIDEO_CS5345 is not set
+CONFIG_VIDEO_CS53L32A=m
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+CONFIG_VIDEO_WM8775=m
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_MT9P012 is not set
+# CONFIG_VIDEO_DW9710 is not set
+# CONFIG_VIDEO_OV3640 is not set
+# CONFIG_VIDEO_IMX046 is not set
+# CONFIG_VIDEO_LV8093 is not set
+# CONFIG_VIDEO_SAA7110 is not set
+CONFIG_VIDEO_SAA711X=m
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+CONFIG_VIDEO_TVP514X=y
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_VIDEO_OMAP3_VOUT=y
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+CONFIG_VIDEO_OMAP3_CAM=y
+CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER=m
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m
+# CONFIG_VIDEO_VPFE_CAPTURE is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SN9C20X_EVDEV=y
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+# CONFIG_USB_PWC_INPUT_EVDEV is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_USB_DSBR=m
+# CONFIG_USB_SI470X is not set
+CONFIG_USB_MR800=m
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+# CONFIG_DVB_B2C2_FLEXCOP_USB is not set
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=4
+# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_FB_OMAP2=y
+# CONFIG_FB_OMAP2_DEBUG_SUPPORT is not set
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_HRTIMER=m
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3EVM=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+CONFIG_MUSB_USE_SYSTEM_DMA_RX=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_TI_CPPI41_DMA is not set
+CONFIG_USB_MUSB_DEBUG=y
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+# CONFIG_USB_LD is not set
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TWL4030_USB is not set
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+CONFIG_LEDS_OMAP=m
+CONFIG_LEDS_OMAP_PWM=m
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS65073 is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+# CONFIG_GFS2_FS_LOCKING_DLM is not set
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+CONFIG_SLUB_STATS=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-psp_2.6.29.bb b/recipes/linux/linux-omap-psp_2.6.29.bb
new file mode 100644
index 0000000000..4c213b1dd1
--- /dev/null
+++ b/recipes/linux/linux-omap-psp_2.6.29.bb
@@ -0,0 +1,40 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omap3evm|omap3517-evm"
+
+SRCREV = "9abb6eb717acbca192ab251a056e3a66b2b47884"
+
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+PR_append = "+gitr${SRCREV}"
+
+SRC_URI = "git://arago-project.org/git/people/sriram/ti-psp-omap.git;protocol=git;branch=int_030000_build3 \
+ file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://defconfig"
+
+S = "${WORKDIR}/git"
+
+SRC_URI_append_omap3517-evm = " \
+ file://shiva-bits.diff;patch=1 \
+ file://shiva-ehci.diff;patch=1 \
+"
+
+SRC_URI_append_omap3evm = " \
+ file://fix-twl-merge-damage.diff;patch=1 \
+ file://fix-section-mismatch.diff;patch=1 \
+ file://no-3517-hack.diff;patch=1 \
+"
+
+do_install_append() {
+ install -d ${D}/boot
+ install -m 0644 Documentation/arm/OMAP/DSS ${D}/boot/
+}
+
+PACKAGES =+ "omap-dss-doc"
+FILES_omap-dss-doc = "/boot/DSS"
+
+module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
+
+
diff --git a/recipes/linux/linux-omap-psp_2.6.31.bb b/recipes/linux/linux-omap-psp_2.6.31.bb
new file mode 100644
index 0000000000..6828d52146
--- /dev/null
+++ b/recipes/linux/linux-omap-psp_2.6.31.bb
@@ -0,0 +1,28 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omap3evm|omap3517-evm"
+
+SRCREV = "9cf7a18fe227717dcc08163100dacd579de48e0c"
+
+PV = "2.6.30+2.6.31rc7"
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+PR_append = "+gitr${SRCREV}"
+
+SRC_URI = "git://arago-project.org/git/people/sriram/ti-psp-omap.git;protocol=git;branch=staging \
+ file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://defconfig"
+
+S = "${WORKDIR}/git"
+
+do_install_append() {
+ install -d ${D}/boot
+ install -m 0644 Documentation/arm/OMAP/DSS ${D}/boot/
+}
+
+PACKAGES =+ "omap-dss-doc"
+FILES_omap-dss-doc = "/boot/DSS"
+
+
diff --git a/recipes/linux/linux-omap-zoomsync/omapzoom2/defconfig b/recipes/linux/linux-omap-zoomsync/omapzoom2/defconfig
new file mode 100755
index 0000000000..5666bc9785
--- /dev/null
+++ b/recipes/linux/linux-omap-zoomsync/omapzoom2/defconfig
@@ -0,0 +1,1900 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc7-omap1
+# Fri Sep 18 11:52:16 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_DEBOBS is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_LL_DEBUG_UART_EXT=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+# CONFIG_OMAP_PM_SRF is not set
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+CONFIG_MACH_OMAP_ZOOM2=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_VERBOSE=y
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI=y
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_HDQ_MASTER_OMAP is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+# CONFIG_TWL4030_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_MT9P012 is not set
+# CONFIG_VIDEO_DW9710 is not set
+# CONFIG_VIDEO_OV3640 is not set
+CONFIG_VIDEO_IMX046=y
+CONFIG_VIDEO_LV8093=y
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP_VIDEOOUT=y
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER=y
+CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=y
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=4
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+# CONFIG_PANEL_GENERIC is not set
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+CONFIG_PANEL_NEC=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_ZOOM2=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_USB_MUSB_DEBUG=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+CONFIG_MPU_BRIDGE=y
+CONFIG_BRIDGE_MEMPOOL_SIZE=0x600000
+# CONFIG_BRIDGE_DEBUG is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/recipes/linux/linux-omap-zoomsync_2.6.31.bb b/recipes/linux/linux-omap-zoomsync_2.6.31.bb
new file mode 100644
index 0000000000..04490af6dd
--- /dev/null
+++ b/recipes/linux/linux-omap-zoomsync_2.6.31.bb
@@ -0,0 +1,28 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omapzoom2"
+
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_omapzoom2 = "1"
+
+LOBRANCH?= "master"
+
+SRCREV = "02b2ce47a93e32f3b4e26662d78a0f31a6ac37ab"
+OEV = "oe1"
+PE = "1"
+
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+PV = "2.6.30+2.6.31-rc7-${OEV}"
+PR_append = "+gitr${SRCREV}"
+
+SRC_URI = "git://dev.omapzoom.org/pub/scm/integration/kernel-omap3.git;branch=${LOBRANCH};protocol=git \
+ file://defconfig"
+
+SRC_URI_append = " \
+"
+
+S = "${WORKDIR}/git"
+
diff --git a/recipes/linux/linux-omap/ehci.patch b/recipes/linux/linux-omap/ehci.patch
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/recipes/linux/linux-omap/ehci.patch
diff --git a/recipes/linux/linux-omap/fix-omap4.diff b/recipes/linux/linux-omap/fix-omap4.diff
new file mode 100644
index 0000000000..5f8ffbce1d
--- /dev/null
+++ b/recipes/linux/linux-omap/fix-omap4.diff
@@ -0,0 +1,63 @@
+From: Tony Lindgren <tony@atomide.com>
+Date: Thu, 24 Sep 2009 23:23:07 +0000 (-0700)
+Subject: omap: Fix 44xx compile
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftmlind%2Flinux-omap-2.6.git;a=commitdiff_plain;h=61f04ee83c768c556168b09d71f0dc87b4a6090a
+
+omap: Fix 44xx compile
+
+Looks like these patches were not tested that well..
+
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+
+diff --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c
+index e4ebd6d..4af76bb 100644
+--- a/arch/arm/mach-omap2/cm4xxx.c
++++ b/arch/arm/mach-omap2/cm4xxx.c
+@@ -22,7 +22,6 @@
+ #include <asm/atomic.h>
+
+ #include "cm.h"
+-#include "cm-regbits-4xxx.h"
+
+ /* XXX move this to cm.h */
+ /* MAX_MODULE_READY_TIME: max milliseconds for module to leave idle */
+@@ -50,19 +49,7 @@
+ */
+ int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs)
+ {
+- int i = 0;
+- u8 cm_id;
+- u16 prcm_mod_offs;
+- u32 mask = OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK;
+-
+- cm_id = prcm_mod >> OMAP4_PRCM_MOD_CM_ID_SHIFT;
+- prcm_mod_offs = prcm_mod & OMAP4_PRCM_MOD_OFFS_MASK;
+-
+- while (((omap4_cm_read_mod_reg(cm_id, prcm_mod_offs, prcm_dev_offs,
+- OMAP4_CM_CLKCTRL_DREG) & mask) != 0) &&
+- (i++ < MAX_MODULE_READY_TIME))
+- udelay(1);
+-
+- return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
++ /* FIXME: Add clock manager related code */
++ return 0;
+ }
+
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index 7574b6f..e3a3bad 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -294,10 +294,10 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+ else if (cpu_is_omap34xx())
+ hwmods = omap34xx_hwmods;
+
+- omap_hwmod_init(hwmods);
+- omap2_mux_init();
+ #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
+ /* The OPP tables have to be registered before a clk init */
++ omap_hwmod_init(hwmods);
++ omap2_mux_init();
+ omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
+ pwrdm_init(powerdomains_omap);
+ clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
diff --git a/recipes/linux/linux-omap/fix-serial.eml b/recipes/linux/linux-omap/fix-serial.eml
new file mode 100644
index 0000000000..25c5923068
--- /dev/null
+++ b/recipes/linux/linux-omap/fix-serial.eml
@@ -0,0 +1,95 @@
+From: "Shilimkar, Santosh" <santosh.shilimkar@ti.com>
+
+Tony,
+OMAP4430 board build is breaking on the latest mainline head because of couple of issues.
+1. The serial.c merge conflict issue below wasn't fixed correctly :(
+Related link:
+http://article.gmane.org/gmane.linux.ports.arm.omap/23341
+
+2. Pauls below series breaks build as well.
+[PATCH 00/13] OMAP PM, clock, and SDRC updates for the 2.6.32 merge window
+
+
+Paul,
+Can you fix the same please? I don't have the correct " cm-regbits-4xxx.h" file to generate the patch.
+
+***************************************************
+CC arch/arm/mach-omap2/control.o
+ CC arch/arm/mach-omap2/mux.o
+ CC arch/arm/mach-omap2/devices.o
+ CC arch/arm/mach-omap2/serial.o
+ CC arch/arm/mach-omap2/gpmc.o
+ CC arch/arm/mach-omap2/timer-gp.o
+ CC arch/arm/mach-omap2/omap-smp.o
+ AS arch/arm/mach-omap2/omap-headsmp.o
+ CC arch/arm/mach-omap2/timer-mpu.o
+ CC arch/arm/mach-omap2/cm4xxx.o
+arch/arm/mach-omap2/cm4xxx.c:25:29: error: cm-regbits-4xxx.h: No such file or directory
+arch/arm/mach-omap2/cm4xxx.c: In function 'omap4_cm_wait_idlest_ready':
+arch/arm/mach-omap2/cm4xxx.c:61: error: implicit declaration of function 'omap4_cm_read_mod_reg'
+arch/arm/mach-omap2/cm4xxx.c:62: error: 'OMAP4_CM_CLKCTRL_DREG' undeclared (first use in this function)
+arch/arm/mach-omap2/cm4xxx.c:62: error: (Each undeclared identifier is reported only once
+arch/arm/mach-omap2/cm4xxx.c:62: error: for each function it appears in.)
+make[1]: *** [arch/arm/mach-omap2/cm4xxx.o] Error 1
+make: *** [arch/arm/mach-omap2] Error 2
+
+*****************************************************
+
+
+Tony,
+Patch regarding one 1. is below.
+
+From 3abd16f9b81dc55a2d894175d4a75f5a40c0fdd5 Mon Sep 17 00:00:00 2001
+From: Santosh Shilimkar <santosh.shilimkar@ti.com>
+Date: Sat, 26 Sep 2009 13:07:39 +0530
+Subject: [PATCH] ARM: OMAP4: Fix build break because of merge conflict
+
+On the latest mainline head 2.6.31 (commit:6d7f18f6), OMAP4430 board
+build is broken. This was mainly because of merge conflict which wasn't
+resolved correctly.
+
+The related patch and issue was discussed here.
+http://article.gmane.org/gmane.linux.ports.arm.omap/23341
+
+Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
+Cc: Kevin Hilman <khilman@deeprootsystems.com>
+Cc: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/serial.c | 14 ++------------
+ 1 files changed, 2 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
+index 3a529c7..54dfeb5 100644
+--- a/arch/arm/mach-omap2/serial.c
++++ b/arch/arm/mach-omap2/serial.c
+@@ -126,7 +116,7 @@ static struct plat_serial8250_port serial_platform_data2[] = {
+ #ifdef CONFIG_ARCH_OMAP4
+ static struct plat_serial8250_port serial_platform_data3[] = {
+ {
+- .membase = IO_ADDRESS(OMAP_UART4_BASE),
++ .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE),
+ .mapbase = OMAP_UART4_BASE,
+ .irq = 70,
+ .flags = UPF_BOOT_AUTOCONF,
+@@ -579,7 +569,7 @@ static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
+ {
+ .pdev = {
+ .name = "serial8250",
+- .id = 3
++ .id = 3,
+ .dev = {
+ .platform_data = serial_platform_data3,
+ },
+--
+1.5.4.7
+
+Thanks !!
+
+Regards,
+Santosh
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/recipes/linux/linux-omap/omap4430-sdp/defconfig b/recipes/linux/linux-omap/omap4430-sdp/defconfig
new file mode 100644
index 0000000000..23e43ea4ef
--- /dev/null
+++ b/recipes/linux/linux-omap/omap4430-sdp/defconfig
@@ -0,0 +1,866 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc7
+# Tue Jun 9 12:36:23 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+CONFIG_ARCH_OMAP4=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_MUX is not set
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_4430SDP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_DISABLE=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_GIC=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=2
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCAL_TIMERS=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
+CONFIG_HAVE_MLOCK=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS0,115200n8 initrd=0x81600000,20M ramdisk_size=20480"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap_2.6.29.bb b/recipes/linux/linux-omap_2.6.29.bb
index 67a4803893..48f94b06c3 100644
--- a/recipes/linux/linux-omap_2.6.29.bb
+++ b/recipes/linux/linux-omap_2.6.29.bb
@@ -3,11 +3,12 @@ require linux.inc
DESCRIPTION = "Linux kernel for OMAP processors"
KERNEL_IMAGETYPE = "uImage"
-COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omapzoom"
+COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omapzoom|omap3-touchbook"
DEFAULT_PREFERENCE = "-1"
DEFAULT_PREFERENCE_overo = "1"
DEFAULT_PREFERENCE_beagleboard = "1"
+DEFAULT_PREFERENCE_omap3evm = "1"
SRCREV = "58cf2f1425abfd3a449f9fe985e48be2d2555022"
@@ -151,17 +152,56 @@ SRC_URI_append = " \
file://isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch;patch=1 \
file://isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch;patch=1 \
file://isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch;patch=1 \
-# file://isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch;patch=1 \
-# file://isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch;patch=1 \
-# file://isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch;patch=1 \
+ file://isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch;patch=1 \
+ file://isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch;patch=1 \
+ file://isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch;patch=1 \
file://0124-leds-gpio-broken-with-current-git.patch;patch=1 \
file://modedb-hd720.patch;patch=1 \
file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://vfp/02-vfp-ptrace.patch;patch=1 \
+ file://vfp/03-vfp-corruption.patch;patch=1 \
+ file://vfp/04-vfp-threads.patch;patch=1 \
+ file://vfp/05-vfp-signal-handlers.patch;patch=1 \
+ file://arch-has-holes.diff;patch=1 \
+ file://cache/l1cache-shift.patch;patch=1 \
+ file://cache/copy-page-tweak.patch;patch=1 \
"
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
file://beagle-asoc.patch;patch=1 \
+ file://tincantools-puppy.diff;patch=1 \
+ file://tincantools-zippy.diff;patch=1 \
+ file://beaglebug/beaglebug-full.patch;patch=1 \
+"
+
+SRC_URI_append_omap3-touchbook = " \
+ file://beagle-asoc.patch;patch=1 \
+ file://accelerometer-mma7455l.patch;patch=1 \
+ file://accelerometer-touchscreen-mux-spi.patch;patch=1 \
+ file://touchscreen-ads7846-export-settings.patch;patch=1 \
+ file://touchscreen-ads7846-rotation-support.patch;patch=1 \
+ file://dspbridge.patch;patch=1 \
+ file://battery2-bq27200-no-error-message.patch;patch=1 \
+ file://sound-headphone-detection.patch;patch=1 \
+ file://dss2-fix-XY-coordinates-when-rotating.patch;patch=1 \
+ file://screen-backlight.patch;patch=1 \
+ file://battery1-tps65950-charging-management-1.patch;patch=1 \
+ file://dss2-fix-scaling-when-rotating.patch;patch=1 \
+ file://dss2-export-status.patch;patch=1 \
+ file://usb-otg-pc-connection.patch;patch=1 \
+ file://battery1-tps65950-charging-management-2.patch;patch=1 \
+ file://memory-move-malloc-end.patch;patch=1 \
+ file://aufs-1.patch;patch=1 \
+ file://aufs-2.patch;patch=1 \
+ file://aufs-3.patch;patch=1 \
+ file://aufs-squashfs-mount-to-avoid-initramfs.patch;patch=1 \
+ file://screen-backlight-accessible-by-user.patch;patch=1 \
+ file://dss2-blank-rotate-accessible-by-user.patch;patch=1 \
+ file://boot-no-power-message.patch;patch=1 \
+ file://usb-lower-current-consumption-upon-insertion.patch;patch=1 \
+ file://battery2-bq27200-gpio-charged.patch;patch=1 \
+ file://board-omap3beagle.c \
"
SRC_URI_append_omap3evm = " \
@@ -172,6 +212,18 @@ SRC_URI_append_omap3evm = " \
S = "${WORKDIR}/git"
+do_configure_prepend_omap3-touchbook() {
+ cp ${WORKDIR}/board-omap3beagle.c ${S}/arch/arm/mach-omap2
+}
+
+do_install_append() {
+ install -d ${D}/boot
+ install -m 0644 Documentation/arm/OMAP/DSS ${D}/boot || true
+}
+
+PACKAGES =+ "omap-dss-doc"
+FILES_omap-dss-doc = "/boot/DSS"
+
module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
diff --git a/recipes/linux/linux-omap_2.6.31.bb b/recipes/linux/linux-omap_2.6.31.bb
new file mode 100644
index 0000000000..38d1b315ac
--- /dev/null
+++ b/recipes/linux/linux-omap_2.6.31.bb
@@ -0,0 +1,69 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omapzoom"
+
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_omapzoom2 = "1"
+
+SRCREV = "945044d157dd63c6af0f2ed40a5346382af94eb4"
+
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+#PV = "2.6.30+2.6.31-rc8+gitr${SRCREV}"
+PV = "2.6.31"
+
+SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \
+ file://defconfig"
+
+SRC_URI_append = " \
+ file://ehci.patch;patch=1 \
+ file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://cache/l1cache-shift.patch;patch=1 \
+ file://cache/copy-page-tweak.patch;patch=1 \
+ file://dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch;patch=1 \
+ file://dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch;patch=1 \
+ file://dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch;patch=1 \
+ file://dss2/0004-OMAP-Add-VRAM-manager.patch;patch=1 \
+ file://dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch;patch=1 \
+ file://dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch;patch=1 \
+ file://dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch;patch=1 \
+ file://dss2/0008-OMAP-DSS2-Add-more-core-files.patch;patch=1 \
+ file://dss2/0009-OMAP-DSS2-DISPC.patch;patch=1 \
+ file://dss2/0010-OMAP-DSS2-DPI-driver.patch;patch=1 \
+ file://dss2/0011-OMAP-DSS2-Video-encoder-driver.patch;patch=1 \
+ file://dss2/0012-OMAP-DSS2-RFBI-driver.patch;patch=1 \
+ file://dss2/0013-OMAP-DSS2-SDI-driver.patch;patch=1 \
+ file://dss2/0014-OMAP-DSS2-DSI-driver.patch;patch=1 \
+ file://dss2/0015-OMAP-DSS2-omapfb-driver.patch;patch=1 \
+ file://dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch;patch=1 \
+ file://dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch;patch=1 \
+ file://dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch;patch=1 \
+ file://dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch;patch=1 \
+ file://dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch;patch=1 \
+ file://dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch;patch=1 \
+ file://expansion-boards/tincantools-zippy.patch;patch=1 \
+ file://madc/madc-driver.patch;patch=1 \
+ file://madc/madc.patch;patch=1 \
+ file://arch-has-holes.diff;patch=1 \
+ file://usb/0001-musb-fix-put_device-call-sequence.patch;patch=1 \
+ file://usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch;patch=1 \
+ file://usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch;patch=1 \
+ file://usb/0012-musb-Add-back-old-musb-procfs-file.patch;patch=1 \
+ file://usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch;patch=1 \
+ file://usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch;patch=1 \
+ file://usb/0015-musb-Add-context-save-and-restore-support.patch;patch=1 \
+ file://usb/0016-usb-update-defconfig.patch;patch=1 \
+ file://usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch;patch=1 \
+ file://modedb-hd720.patch;patch=1 \
+ file://dss2/beagle-dss2-support.patch;patch=1 \
+"
+
+SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
+"
+
+S = "${WORKDIR}/git"
+
+module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
+
diff --git a/recipes/linux/linux-omap_git.bb b/recipes/linux/linux-omap_git.bb
index ddc511e415..7690b4d381 100644
--- a/recipes/linux/linux-omap_git.bb
+++ b/recipes/linux/linux-omap_git.bb
@@ -3,40 +3,70 @@ require linux.inc
DESCRIPTION = "Linux kernel for OMAP processors"
KERNEL_IMAGETYPE = "uImage"
-COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo"
+COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omapzoom|omapzoom2|omap4430-sdp"
-# This is missing the EHCI patch for beagle
DEFAULT_PREFERENCE = "-1"
+SRCREV = "945044d157dd63c6af0f2ed40a5346382af94eb4"
-SRCREV = "90e758af52ba803cba233fabee81176d99589f09"
+FILESPATHPKG_prepend = "linux-omap-2.6.31:"
-#PV = "2.6.29+2.6.30-rc1+${PR}+gitr${SRCREV}"
-PV = "2.6.29-${PR}+gitr${SRCREV}"
-PR = "r0"
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+#PV = "2.6.30+2.6.31-rc8+gitr${SRCREV}"
+PV = "2.6.31"
SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \
file://defconfig"
SRC_URI_append = " \
- file://no-empty-flash-warnings.patch;patch=1 \
- file://no-cortex-deadlock.patch;patch=1 \
- file://read_die_ids.patch;patch=1 \
- file://fix-install.patch;patch=1 \
- file://DSS2.diff;patch=1 \
+ file://ehci.patch;patch=1 \
+ file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \
+ file://cache/l1cache-shift.patch;patch=1 \
+ file://cache/copy-page-tweak.patch;patch=1 \
+ file://dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch;patch=1 \
+ file://dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch;patch=1 \
+ file://dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch;patch=1 \
+ file://dss2/0004-OMAP-Add-VRAM-manager.patch;patch=1 \
+ file://dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch;patch=1 \
+ file://dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch;patch=1 \
+ file://dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch;patch=1 \
+ file://dss2/0008-OMAP-DSS2-Add-more-core-files.patch;patch=1 \
+ file://dss2/0009-OMAP-DSS2-DISPC.patch;patch=1 \
+ file://dss2/0010-OMAP-DSS2-DPI-driver.patch;patch=1 \
+ file://dss2/0011-OMAP-DSS2-Video-encoder-driver.patch;patch=1 \
+ file://dss2/0012-OMAP-DSS2-RFBI-driver.patch;patch=1 \
+ file://dss2/0013-OMAP-DSS2-SDI-driver.patch;patch=1 \
+ file://dss2/0014-OMAP-DSS2-DSI-driver.patch;patch=1 \
+ file://dss2/0015-OMAP-DSS2-omapfb-driver.patch;patch=1 \
+ file://dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch;patch=1 \
+ file://dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch;patch=1 \
+ file://dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch;patch=1 \
+ file://dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch;patch=1 \
+ file://dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch;patch=1 \
+ file://dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch;patch=1 \
+ file://expansion-boards/tincantools-zippy.patch;patch=1 \
+ file://madc/madc-driver.patch;patch=1 \
+ file://madc/madc.patch;patch=1 \
+ file://arch-has-holes.diff;patch=1 \
+ file://usb/0001-musb-fix-put_device-call-sequence.patch;patch=1 \
+ file://usb/0008-omap3-Add-CHIP_GE_OMAP3430ES3-for-HSUSB.patch;patch=1 \
+ file://usb/0011-musb-fix-musb-gadget_driver-NULL-bug.patch;patch=1 \
+ file://usb/0012-musb-Add-back-old-musb-procfs-file.patch;patch=1 \
+ file://usb/0013-musb-Remove-USB_SUSPEND-auto-select-with-OTG.patch;patch=1 \
+ file://usb/0014-musb-disable-PING-on-status-phase-of-control-transf.patch;patch=1 \
+ file://usb/0015-musb-Add-context-save-and-restore-support.patch;patch=1 \
+ file://usb/0016-usb-update-defconfig.patch;patch=1 \
+ file://usb/0001-ARM-OMAP-Fix-beagleboard-EHCI-setup.patch;patch=1 \
+ file://modedb-hd720.patch;patch=1 \
+ file://dss2/beagle-dss2-support.patch;patch=1 \
+ file://fix-serial.eml;patch=1 \
+ file://fix-omap4.diff;patch=1 \
"
-
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
- "
-
-SRC_URI_append_omap3evm = " \
- file://evm-mcspi-ts.diff;patch=1 \
"
S = "${WORKDIR}/git"
-
module_autoload_ohci-hcd_omap5912osk = "ohci-hcd"
-
diff --git a/recipes/linux/linux-omapandroid/omapzoom2/defconfig b/recipes/linux/linux-omapandroid/omapzoom2/defconfig
new file mode 100644
index 0000000000..a37a4d0035
--- /dev/null
+++ b/recipes/linux/linux-omapandroid/omapzoom2/defconfig
@@ -0,0 +1,1854 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Mon Jul 13 22:20:30 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ASHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_SMARTREFLEX is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=1
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_LL_DEBUG_UART_EXT=y
+CONFIG_OMAP_SERIAL_WAKE=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+# CONFIG_OMAP_PM_SRF is not set
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+CONFIG_MACH_OMAP_ZOOM2=y
+CONFIG_WIFI_CONTROL_FUNC=y
+# CONFIG_TIWLAN_SDIO is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_HAS_TLS_REG is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_HAS_WAKELOCK=y
+CONFIG_HAS_EARLYSUSPEND=y
+CONFIG_WAKELOCK=y
+CONFIG_WAKELOCK_STAT=y
+CONFIG_USER_WAKELOCK=y
+CONFIG_EARLYSUSPEND=y
+# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
+# CONFIG_CONSOLE_EARLYSUSPEND is not set
+CONFIG_FB_EARLYSUSPEND=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+CONFIG_ANDROID_PARANOID_NETWORK=y
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+# CONFIG_BT_BNEP_MC_FILTER is not set
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+CONFIG_BT_HCIUART_LL=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+CONFIG_RFKILL_PM=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_HWECC=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_ANDROID_PMEM=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_KERNEL_DEBUGGER_CORE is not set
+# CONFIG_UID_STAT is not set
+CONFIG_WL127X_RFKILL=y
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_SMC911X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_KEYRESET is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_OMAP is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI=y
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OMAP is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_DCC_TTY is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=y
+# CONFIG_TWL4030_POWEROFF is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_PCA963X is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+CONFIG_HDQ_MASTER_OMAP=y
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+CONFIG_W1_SLAVE_BQ27000=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_TWL4030_BCI_BATTERY=y
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_TCM825X is not set
+CONFIG_VIDEO_IMX046=y
+CONFIG_VIDEO_LV8093=y
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA7111 is not set
+# CONFIG_VIDEO_SAA7114 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP3_V4L2=y
+CONFIG_VIDEO_OMAP_VIDEOLIB=y
+CONFIG_VIDEO_OMAP_VIDEOOUT=y
+CONFIG_NTSC_M=y
+# CONFIG_PAL_BDGHI is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_OMAP_LCD_WVGA=y
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=4
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+
+#
+# OMAP2/3 Display Device Drivers
+#
+# CONFIG_PANEL_GENERIC is not set
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+CONFIG_PANEL_ZOOM2=y
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=1
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_ANDROID=y
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_MMC_BLOCK_PARANOID_RESUME=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_OMAP_HS_MMC2 is not set
+# CONFIG_OMAP_HS_MMC3 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_SWITCH=y
+# CONFIG_SWITCH_GPIO is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+CONFIG_RTC_INTF_ALARM=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_UIO is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_ECHO is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_ANDROID_BINDER_IPC is not set
+# CONFIG_ANDROID_LOGGER is not set
+# CONFIG_ANDROID_RAM_CONSOLE is not set
+# CONFIG_ANDROID_TIMED_OUTPUT is not set
+# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+# CONFIG_MPU_BRIDGE is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omapandroid_2.6.29.bb b/recipes/linux/linux-omapandroid_2.6.29.bb
new file mode 100644
index 0000000000..40444250dc
--- /dev/null
+++ b/recipes/linux/linux-omapandroid_2.6.29.bb
@@ -0,0 +1,24 @@
+require linux.inc
+
+DESCRIPTION = "Linux kernel for OMAP processors"
+KERNEL_IMAGETYPE = "uImage"
+
+COMPATIBLE_MACHINE = "omapzoom2"
+
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_omapzoom2 = "1"
+
+SRCREV = "1e5ddc5d409f25652fe99064f22c0aa75bc9b7b3"
+
+# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
+PV = "2.6.29"
+PR_append = "+gitr${SRCREV}"
+
+SRC_URI = "git://android.git.kernel.org/kernel/omap;branch=android-omap-2.6.29;protocol=git \
+ file://defconfig"
+
+SRC_URI_append = " \
+"
+
+S = "${WORKDIR}/git"
+
diff --git a/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb b/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb
index 786e4901c3..16fe38bf5c 100644
--- a/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb
+++ b/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb
@@ -25,7 +25,7 @@ do_configure() {
fi
- if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then
+ if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then
echo "CONFIG_AEABI=y" >> ${S}/.config
echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config
else
diff --git a/recipes/linux/linux-tornado-omap2_2.6.16.16.bb b/recipes/linux/linux-tornado-omap2_2.6.16.16.bb
index a9ebee14cd..9c6e133c28 100644
--- a/recipes/linux/linux-tornado-omap2_2.6.16.16.bb
+++ b/recipes/linux/linux-tornado-omap2_2.6.16.16.bb
@@ -24,7 +24,7 @@ do_configure() {
fi
- if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then
+ if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then
echo "CONFIG_AEABI=y" >> ${S}/.config
echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config
else